summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorHorst G. Burkhardt <horst@adelielinux.org>2022-06-11 20:53:24 -0500
committerZach van Rijn <me@zv.io>2022-10-21 18:34:01 -0500
commit04142312762064baaf4765e13b479d9e03cfad47 (patch)
tree9e79aede93d4872d94b16bd78da2022033909368 /system
parentb72d6e68ffe2d40ac154abebc28391c619d56bdf (diff)
downloadpackages-04142312762064baaf4765e13b479d9e03cfad47.tar.gz
packages-04142312762064baaf4765e13b479d9e03cfad47.tar.bz2
packages-04142312762064baaf4765e13b479d9e03cfad47.tar.xz
packages-04142312762064baaf4765e13b479d9e03cfad47.zip
system/easy-kernel: Update to 5.15.44-mc2
Diffstat (limited to 'system')
-rw-r--r--system/easy-kernel/0100-linux.5.15.44.patch (renamed from system/easy-kernel/0100-linux-5.15.28.patch)103535
-rw-r--r--system/easy-kernel/0130-lrng.patch28362
-rw-r--r--system/easy-kernel/0250-projectc-5.15-r1.patch9746
-rw-r--r--system/easy-kernel/0251-projectc-5.15-r1-zv-fix-5.15.28.patch125
-rw-r--r--system/easy-kernel/0500-print-fw-info.patch6
-rw-r--r--system/easy-kernel/1000-version.patch4
-rw-r--r--system/easy-kernel/APKBUILD20
7 files changed, 99618 insertions, 42180 deletions
diff --git a/system/easy-kernel/0100-linux-5.15.28.patch b/system/easy-kernel/0100-linux.5.15.44.patch
index 5e307cfc9..11060bfba 100644
--- a/system/easy-kernel/0100-linux-5.15.28.patch
+++ b/system/easy-kernel/0100-linux.5.15.44.patch
@@ -1,3 +1,15 @@
+diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
+index f627e705e663b..48d41b6696270 100644
+--- a/Documentation/ABI/testing/sysfs-fs-f2fs
++++ b/Documentation/ABI/testing/sysfs-fs-f2fs
+@@ -425,6 +425,7 @@ Description: Show status of f2fs superblock in real time.
+ 0x800 SBI_QUOTA_SKIP_FLUSH skip flushing quota in current CP
+ 0x1000 SBI_QUOTA_NEED_REPAIR quota file may be corrupted
+ 0x2000 SBI_IS_RESIZEFS resizefs is in process
++ 0x4000 SBI_IS_FREEZING freefs is in process
+ ====== ===================== =================================
+
+ What: /sys/fs/f2fs/<disk>/ckpt_thread_ioprio
diff --git a/Documentation/accounting/psi.rst b/Documentation/accounting/psi.rst
index f2b3439edcc2c..860fe651d6453 100644
--- a/Documentation/accounting/psi.rst
@@ -146,7 +158,7 @@ index e05e581af5cfe..6bd97cd50d625 100644
ARM white papers:
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
-index 43dc35fe5bc03..ed55ea20352bc 100644
+index 43dc35fe5bc03..fd3d14dabadcb 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1690,6 +1690,8 @@
@@ -173,7 +185,30 @@ index 43dc35fe5bc03..ed55ea20352bc 100644
kvm-intel.flexpriority=
[KVM,Intel] Disable FlexPriority feature (TPR shadow).
-@@ -5261,8 +5267,12 @@
+@@ -3446,8 +3452,7 @@
+ difficult since unequal pointers can no longer be
+ compared. However, if this command-line option is
+ specified, then all normal pointers will have their true
+- value printed. Pointers printed via %pK may still be
+- hashed. This option should only be specified when
++ value printed. This option should only be specified when
+ debugging the kernel. Please do not use on production
+ kernels.
+
+@@ -4302,6 +4307,12 @@
+ fully seed the kernel's CRNG. Default is controlled
+ by CONFIG_RANDOM_TRUST_CPU.
+
++ random.trust_bootloader={on,off}
++ [KNL] Enable or disable trusting the use of a
++ seed passed by the bootloader (if available) to
++ fully seed the kernel's CRNG. Default is controlled
++ by CONFIG_RANDOM_TRUST_BOOTLOADER.
++
+ randomize_kstack_offset=
+ [KNL] Enable or disable kernel stack offset
+ randomization, which provides roughly 5 bits of
+@@ -5261,8 +5272,12 @@
Specific mitigations can also be selected manually:
retpoline - replace indirect branches
@@ -188,7 +223,7 @@ index 43dc35fe5bc03..ed55ea20352bc 100644
Not specifying this option is equivalent to
spectre_v2=auto.
-@@ -6349,6 +6359,13 @@
+@@ -6349,6 +6364,13 @@
improve timer resolution at the expense of processing
more timer interrupts.
@@ -216,10 +251,55 @@ index fb578fbbb76ca..49857ce1cd03e 100644
* Bit 62 page swapped
* Bit 63 page present
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index 426162009ce99..0e486f41185ef 100644
+index 426162009ce99..609b891754081 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -1099,7 +1099,7 @@ task_delayacct
+@@ -795,6 +795,7 @@ bit 1 print system memory info
+ bit 2 print timer info
+ bit 3 print locks info if ``CONFIG_LOCKDEP`` is on
+ bit 4 print ftrace buffer
++bit 5 print all printk messages in buffer
+ ===== ============================================
+
+ So for example to print tasks and memory info on panic, user can::
+@@ -1013,28 +1014,22 @@ This is a directory, with the following entries:
+ * ``boot_id``: a UUID generated the first time this is retrieved, and
+ unvarying after that;
+
++* ``uuid``: a UUID generated every time this is retrieved (this can
++ thus be used to generate UUIDs at will);
++
+ * ``entropy_avail``: the pool's entropy count, in bits;
+
+ * ``poolsize``: the entropy pool size, in bits;
+
+ * ``urandom_min_reseed_secs``: obsolete (used to determine the minimum
+- number of seconds between urandom pool reseeding).
+-
+-* ``uuid``: a UUID generated every time this is retrieved (this can
+- thus be used to generate UUIDs at will);
++ number of seconds between urandom pool reseeding). This file is
++ writable for compatibility purposes, but writing to it has no effect
++ on any RNG behavior;
+
+ * ``write_wakeup_threshold``: when the entropy count drops below this
+ (as a number of bits), processes waiting to write to ``/dev/random``
+- are woken up.
+-
+-If ``drivers/char/random.c`` is built with ``ADD_INTERRUPT_BENCH``
+-defined, these additional entries are present:
+-
+-* ``add_interrupt_avg_cycles``: the average number of cycles between
+- interrupts used to feed the pool;
+-
+-* ``add_interrupt_avg_deviation``: the standard deviation seen on the
+- number of cycles between interrupts used to feed the pool.
++ are woken up. This file is writable for compatibility purposes, but
++ writing to it has no effect on any RNG behavior.
+
+
+ randomize_va_space
+@@ -1099,7 +1094,7 @@ task_delayacct
===============
Enables/disables task delay accounting (see
@@ -305,6 +385,20 @@ index ec1a5a63c1d09..b72ff17d600ae 100644
4. Unused AT_HWCAP bits
-----------------------
+diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
+index d410a47ffa57a..7c1750bcc5bd8 100644
+--- a/Documentation/arm64/silicon-errata.rst
++++ b/Documentation/arm64/silicon-errata.rst
+@@ -163,6 +163,9 @@ stable kernels.
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Qualcomm Tech. | Kryo4xx Silver | N/A | ARM64_ERRATUM_1024718 |
+ +----------------+-----------------+-----------------+-----------------------------+
++| Qualcomm Tech. | Kryo4xx Gold | N/A | ARM64_ERRATUM_1286807 |
+++----------------+-----------------+-----------------+-----------------------------+
++
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 |
+ +----------------+-----------------+-----------------+-----------------------------+
diff --git a/Documentation/dev-tools/kfence.rst b/Documentation/dev-tools/kfence.rst
index 0fbe3308bf37f..48244d32780f6 100644
--- a/Documentation/dev-tools/kfence.rst
@@ -454,6 +548,40 @@ index 877183cf42787..1ef849dc74d7e 100644
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
+diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
+index 2353f6cf3c805..750720e0123a0 100644
+--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
++++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
+@@ -106,7 +106,6 @@ allOf:
+ - mediatek,mt2701-smi-larb
+ - mediatek,mt2712-smi-larb
+ - mediatek,mt6779-smi-larb
+- - mediatek,mt8167-smi-larb
+ - mediatek,mt8192-smi-larb
+
+ then:
+diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+index bd217e6f5018a..5cd144a9ec992 100644
+--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
++++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+@@ -55,7 +55,7 @@ patternProperties:
+ properties:
+ reg:
+ description:
+- Contains the native Ready/Busy IDs.
++ Contains the chip-select IDs.
+
+ nand-ecc-engine:
+ allOf:
+@@ -184,7 +184,7 @@ examples:
+ nand-use-soft-ecc-engine;
+ nand-ecc-algo = "bch";
+
+- /* controller specific properties */
++ /* NAND chip specific properties */
+ };
+
+ nand@1 {
diff --git a/Documentation/devicetree/bindings/net/can/tcan4x5x.txt b/Documentation/devicetree/bindings/net/can/tcan4x5x.txt
index 0968b40aef1e8..e3501bfa22e90 100644
--- a/Documentation/devicetree/bindings/net/can/tcan4x5x.txt
@@ -486,6 +614,83 @@ index 2766fe45bb98b..ee42328a109dc 100644
eee-broken-100tx:
$ref: /schemas/types.yaml#/definitions/flag
description:
+diff --git a/Documentation/devicetree/bindings/net/qcom,ipa.yaml b/Documentation/devicetree/bindings/net/qcom,ipa.yaml
+index b8a0b392b24ea..c52ec1ee7df6e 100644
+--- a/Documentation/devicetree/bindings/net/qcom,ipa.yaml
++++ b/Documentation/devicetree/bindings/net/qcom,ipa.yaml
+@@ -106,6 +106,10 @@ properties:
+ - const: imem
+ - const: config
+
++ qcom,qmp:
++ $ref: /schemas/types.yaml#/definitions/phandle
++ description: phandle to the AOSS side-channel message RAM
++
+ qcom,smem-states:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: State bits used in by the AP to signal the modem.
+@@ -221,6 +225,8 @@ examples:
+ "imem",
+ "config";
+
++ qcom,qmp = <&aoss_qmp>;
++
+ qcom,smem-states = <&ipa_smp2p_out 0>,
+ <&ipa_smp2p_out 1>;
+ qcom,smem-state-names = "ipa-clock-enabled-valid",
+diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+index c115c95ee584e..5b8db76b6cdd7 100644
+--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+@@ -53,20 +53,18 @@ properties:
+ - allwinner,sun8i-r40-emac
+ - allwinner,sun8i-v3s-emac
+ - allwinner,sun50i-a64-emac
+- - loongson,ls2k-dwmac
+- - loongson,ls7a-dwmac
+ - amlogic,meson6-dwmac
+ - amlogic,meson8b-dwmac
+ - amlogic,meson8m2-dwmac
+ - amlogic,meson-gxbb-dwmac
+ - amlogic,meson-axg-dwmac
+- - loongson,ls2k-dwmac
+- - loongson,ls7a-dwmac
+ - ingenic,jz4775-mac
+ - ingenic,x1000-mac
+ - ingenic,x1600-mac
+ - ingenic,x1830-mac
+ - ingenic,x2000-mac
++ - loongson,ls2k-dwmac
++ - loongson,ls7a-dwmac
+ - rockchip,px30-gmac
+ - rockchip,rk3128-gmac
+ - rockchip,rk3228-gmac
+diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
+index ad2866c997383..fcd82df3aebbd 100644
+--- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
++++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
+@@ -58,7 +58,7 @@ patternProperties:
+ $ref: "/schemas/types.yaml#/definitions/string"
+ enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15, ADC2,
+ ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMCG1, EMMCG4,
+- EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWQSPID, FWSPIWP,
++ EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP,
+ GPIT0, GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
+ GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, HVI3C3, HVI3C4, I2C1, I2C10,
+ I2C11, I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5,
+diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml
+index 4fe35e650909c..8dcdd32c2e015 100644
+--- a/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml
++++ b/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml
+@@ -138,7 +138,7 @@ examples:
+ clocks = <&sys_clk>;
+ pinctrl-0 = <&sgpio2_pins>;
+ pinctrl-names = "default";
+- reg = <0x1101059c 0x100>;
++ reg = <0x1101059c 0x118>;
+ microchip,sgpio-port-ranges = <0 0>, <16 18>, <28 31>;
+ bus-frequency = <25000000>;
+ sgpio_in2: gpio@0 {
diff --git a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt b/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt
index 093edda0c8dfc..6cd83d920155f 100644
--- a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt
@@ -533,6 +738,38 @@ index 093edda0c8dfc..6cd83d920155f 100644
the possible 8 options selectable by the dvs gpios. The value of this
property should be between 0 and 7. If not specified or if out of range, the
default value of this property is set to 0.
+diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
+index 35a8045b2c70d..53627c6e2ae32 100644
+--- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
++++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
+@@ -106,7 +106,7 @@ examples:
+ dma-names = "rx", "tx";
+
+ flash@0 {
+- compatible = "spi-nor";
++ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <104000000>;
+ spi-tx-bus-width = <2>;
+diff --git a/Documentation/devicetree/bindings/spi/spi-mxic.txt b/Documentation/devicetree/bindings/spi/spi-mxic.txt
+index 529f2dab2648a..7bcbb229b78bb 100644
+--- a/Documentation/devicetree/bindings/spi/spi-mxic.txt
++++ b/Documentation/devicetree/bindings/spi/spi-mxic.txt
+@@ -8,11 +8,13 @@ Required properties:
+ - reg: should contain 2 entries, one for the registers and one for the direct
+ mapping area
+ - reg-names: should contain "regs" and "dirmap"
+-- interrupts: interrupt line connected to the SPI controller
+ - clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
+ - clocks: should contain 3 entries for the "ps_clk", "send_clk" and
+ "send_dly_clk" clocks
+
++Optional properties:
++- interrupts: interrupt line connected to the SPI controller
++
+ Example:
+
+ spi@43c30000 {
diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
index a07de5ed0ca6a..2d34f3ccb2572 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
@@ -554,6 +791,19 @@ index a07de5ed0ca6a..2d34f3ccb2572 100644
required:
- trip
+diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.yaml b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
+index 56853c17af667..1dc3d5d7b44fe 100644
+--- a/Documentation/devicetree/bindings/usb/usb-hcd.yaml
++++ b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
+@@ -33,7 +33,7 @@ patternProperties:
+ "^.*@[0-9a-f]{1,2}$":
+ description: The hard wired USB devices
+ type: object
+- $ref: /usb/usb-device.yaml
++ $ref: /schemas/usb/usb-device.yaml
+
+ additionalProperties: true
+
diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml b/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml
index 76cb9586ee00c..93cd77a6e92c0 100644
--- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml
@@ -621,6 +871,19 @@ index 94a2d7f01d999..d3cfa73cbb2b4 100644
:literal:
.. kernel-doc:: drivers/firewire/core-device.c
+diff --git a/Documentation/filesystems/ext4/attributes.rst b/Documentation/filesystems/ext4/attributes.rst
+index 54386a010a8d7..871d2da7a0a91 100644
+--- a/Documentation/filesystems/ext4/attributes.rst
++++ b/Documentation/filesystems/ext4/attributes.rst
+@@ -76,7 +76,7 @@ The beginning of an extended attribute block is in
+ - Checksum of the extended attribute block.
+ * - 0x14
+ - \_\_u32
+- - h\_reserved[2]
++ - h\_reserved[3]
+ - Zero.
+
+ The checksum is calculated against the FS UUID, the 64-bit block number
diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index 0eb799d9d05a2..7940a45d39522 100644
--- a/Documentation/filesystems/fscrypt.rst
@@ -865,11 +1128,44 @@ index 2afccc63856ee..1cfbf1add2fc9 100644
bit 1: enable rescheduling of new connections when it is safe.
That is, whenever expire_nodest_conn and for TCP sockets, when
+diff --git a/Documentation/process/stable-kernel-rules.rst b/Documentation/process/stable-kernel-rules.rst
+index 003c865e9c212..fbcb48bc2a903 100644
+--- a/Documentation/process/stable-kernel-rules.rst
++++ b/Documentation/process/stable-kernel-rules.rst
+@@ -168,7 +168,16 @@ Trees
+ - The finalized and tagged releases of all stable kernels can be found
+ in separate branches per version at:
+
+- https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
++ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
++
++ - The release candidate of all stable kernel versions can be found at:
++
++ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/
++
++ .. warning::
++ The -stable-rc tree is a snapshot in time of the stable-queue tree and
++ will change frequently, hence will be rebased often. It should only be
++ used for testing purposes (e.g. to be consumed by CI systems).
+
+
+ Review committee
diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst
-index 0ea967d345838..d25335993e553 100644
+index 0ea967d345838..9b52f50a68542 100644
--- a/Documentation/sound/hd-audio/models.rst
+++ b/Documentation/sound/hd-audio/models.rst
-@@ -326,6 +326,8 @@ usi-headset
+@@ -261,6 +261,10 @@ alc-sense-combo
+ huawei-mbx-stereo
+ Enable initialization verbs for Huawei MBX stereo speakers;
+ might be risky, try this at your own risk
++alc298-samsung-headphone
++ Samsung laptops with ALC298
++alc256-samsung-headphone
++ Samsung laptops with ALC256
+
+ ALC66x/67x/892
+ ==============
+@@ -326,6 +330,8 @@ usi-headset
Headset support on USI machines
dual-codecs
Lenovo laptops with dual codecs
@@ -878,6 +1174,15 @@ index 0ea967d345838..d25335993e553 100644
ALC680
======
+diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt
+index 9a35f50798a65..2c573541ab712 100644
+--- a/Documentation/sphinx/requirements.txt
++++ b/Documentation/sphinx/requirements.txt
+@@ -1,2 +1,4 @@
++# jinja2>=3.1 is not compatible with Sphinx<4.0
++jinja2<3.1
+ sphinx_rtd_theme
+ Sphinx==2.4.4
diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst
index a4e3ef2952401..6ed13398ca2ce 100644
--- a/Documentation/trace/coresight/coresight-config.rst
@@ -945,7 +1250,7 @@ index 8ddb9b09451c8..c47f381d0c002 100644
--------------------
diff --git a/MAINTAINERS b/MAINTAINERS
-index 3b79fd441dde8..c8103e57a70be 100644
+index 3b79fd441dde8..942e0b173f2cc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7024,7 +7024,6 @@ F: drivers/net/mdio/fwnode_mdio.c
@@ -964,8 +1269,17 @@ index 3b79fd441dde8..c8103e57a70be 100644
EXFAT FILE SYSTEM
M: Namjae Jeon <linkinjeon@kernel.org>
+@@ -15720,6 +15720,8 @@ F: arch/mips/generic/board-ranchu.c
+
+ RANDOM NUMBER DRIVER
+ M: "Theodore Ts'o" <tytso@mit.edu>
++M: Jason A. Donenfeld <Jason@zx2c4.com>
++T: git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git
+ S: Maintained
+ F: drivers/char/random.c
+
diff --git a/Makefile b/Makefile
-index ed6e7ec60eff6..ad64687080cff 100644
+index ed6e7ec60eff6..b8ce2ba174862 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
@@ -973,15 +1287,23 @@ index ed6e7ec60eff6..ad64687080cff 100644
VERSION = 5
PATCHLEVEL = 15
-SUBLEVEL = 0
-+SUBLEVEL = 28
++SUBLEVEL = 44
EXTRAVERSION =
NAME = Trick or Treat
diff --git a/arch/Kconfig b/arch/Kconfig
-index 8df1c71026435..d1e69d6e8498b 100644
+index 8df1c71026435..191589f26b1a8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
-@@ -1234,6 +1234,9 @@ config RELR
+@@ -1141,6 +1141,7 @@ config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+ config RANDOMIZE_KSTACK_OFFSET_DEFAULT
+ bool "Randomize kernel stack offset on syscall entry"
+ depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
++ depends on INIT_STACK_NONE || !CC_IS_CLANG || CLANG_VERSION >= 140000
+ help
+ The kernel stack offset can be randomized (after pt_regs) by
+ roughly 5 bits of entropy, frustrating memory corruption
+@@ -1234,6 +1235,9 @@ config RELR
config ARCH_HAS_MEM_ENCRYPT
bool
@@ -991,10 +1313,60 @@ index 8df1c71026435..d1e69d6e8498b 100644
config HAVE_SPARSE_SYSCALL_NR
bool
help
+diff --git a/arch/alpha/include/asm/timex.h b/arch/alpha/include/asm/timex.h
+index b565cc6f408e9..f89798da8a147 100644
+--- a/arch/alpha/include/asm/timex.h
++++ b/arch/alpha/include/asm/timex.h
+@@ -28,5 +28,6 @@ static inline cycles_t get_cycles (void)
+ __asm__ __volatile__ ("rpcc %0" : "=r"(ret));
+ return ret;
+ }
++#define get_cycles get_cycles
+
+ #endif
+diff --git a/arch/alpha/kernel/rtc.c b/arch/alpha/kernel/rtc.c
+index ce3077946e1d9..fb3025396ac96 100644
+--- a/arch/alpha/kernel/rtc.c
++++ b/arch/alpha/kernel/rtc.c
+@@ -80,7 +80,12 @@ init_rtc_epoch(void)
+ static int
+ alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
+ {
+- mc146818_get_time(tm);
++ int ret = mc146818_get_time(tm);
++
++ if (ret < 0) {
++ dev_err_ratelimited(dev, "unable to read current time\n");
++ return ret;
++ }
+
+ /* Adjust for non-default epochs. It's easier to depend on the
+ generic __get_rtc_time and adjust the epoch here than create
+diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
+index dd77a0c8f740b..66ba549b520fc 100644
+--- a/arch/arc/kernel/entry.S
++++ b/arch/arc/kernel/entry.S
+@@ -196,6 +196,7 @@ tracesys_exit:
+ st r0, [sp, PT_r0] ; sys call return value in pt_regs
+
+ ;POST Sys Call Ptrace Hook
++ mov r0, sp ; pt_regs needed
+ bl @syscall_trace_exit
+ b ret_from_exception ; NOT ret_from_system_call at is saves r0 which
+ ; we'd done before calling post hook above
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
-index 3793876f42d9b..8e90052f6f056 100644
+index 3793876f42d9b..5f7f5aab361f1 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
+@@ -43,7 +43,7 @@ SYSCALL_DEFINE0(arc_gettls)
+ return task_thread_info(current)->thr_ptr;
+ }
+
+-SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
++SYSCALL_DEFINE3(arc_usr_cmpxchg, int __user *, uaddr, int, expected, int, new)
+ {
+ struct pt_regs *regs = current_pt_regs();
+ u32 uval;
@@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hdr *x)
eflags = x->e_flags;
if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) {
@@ -1173,6 +1545,131 @@ index 7e0934180724d..27ca1ca6e827c 100644
omap3-beagle-xm.dtb \
omap3-beagle-xm-ab.dtb \
omap3-cm-t3517.dtb \
+diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts
+index 0d2fac98ce7d2..c8b80f156ec98 100644
+--- a/arch/arm/boot/dts/am3517-evm.dts
++++ b/arch/arm/boot/dts/am3517-evm.dts
+@@ -161,6 +161,8 @@
+
+ /* HS USB Host PHY on PORT 1 */
+ hsusb1_phy: hsusb1_phy {
++ pinctrl-names = "default";
++ pinctrl-0 = <&hsusb1_rst_pins>;
+ compatible = "usb-nop-xceiv";
+ reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */
+ #phy-cells = <0>;
+@@ -168,7 +170,9 @@
+ };
+
+ &davinci_emac {
+- status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&ethernet_pins>;
++ status = "okay";
+ };
+
+ &davinci_mdio {
+@@ -193,6 +197,8 @@
+ };
+
+ &i2c2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c2_pins>;
+ clock-frequency = <400000>;
+ /* User DIP swithes [1:8] / User LEDS [1:2] */
+ tca6416: gpio@21 {
+@@ -205,6 +211,8 @@
+ };
+
+ &i2c3 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c3_pins>;
+ clock-frequency = <400000>;
+ };
+
+@@ -223,6 +231,8 @@
+ };
+
+ &usbhshost {
++ pinctrl-names = "default";
++ pinctrl-0 = <&hsusb1_pins>;
+ port1-mode = "ehci-phy";
+ };
+
+@@ -231,8 +241,35 @@
+ };
+
+ &omap3_pmx_core {
+- pinctrl-names = "default";
+- pinctrl-0 = <&hsusb1_rst_pins>;
++
++ ethernet_pins: pinmux_ethernet_pins {
++ pinctrl-single,pins = <
++ OMAP3_CORE1_IOPAD(0x21fe, PIN_INPUT | MUX_MODE0) /* rmii_mdio_data */
++ OMAP3_CORE1_IOPAD(0x2200, MUX_MODE0) /* rmii_mdio_clk */
++ OMAP3_CORE1_IOPAD(0x2202, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd0 */
++ OMAP3_CORE1_IOPAD(0x2204, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd1 */
++ OMAP3_CORE1_IOPAD(0x2206, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_crs_dv */
++ OMAP3_CORE1_IOPAD(0x2208, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_rxer */
++ OMAP3_CORE1_IOPAD(0x220a, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd0 */
++ OMAP3_CORE1_IOPAD(0x220c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd1 */
++ OMAP3_CORE1_IOPAD(0x220e, PIN_OUTPUT_PULLDOWN |MUX_MODE0) /* rmii_txen */
++ OMAP3_CORE1_IOPAD(0x2210, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_50mhz_clk */
++ >;
++ };
++
++ i2c2_pins: pinmux_i2c2_pins {
++ pinctrl-single,pins = <
++ OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */
++ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */
++ >;
++ };
++
++ i2c3_pins: pinmux_i2c3_pins {
++ pinctrl-single,pins = <
++ OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */
++ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */
++ >;
++ };
+
+ leds_pins: pinmux_leds_pins {
+ pinctrl-single,pins = <
+@@ -300,8 +337,6 @@
+ };
+
+ &omap3_pmx_core2 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&hsusb1_pins>;
+
+ hsusb1_pins: pinmux_hsusb1_pins {
+ pinctrl-single,pins = <
+diff --git a/arch/arm/boot/dts/am3517-som.dtsi b/arch/arm/boot/dts/am3517-som.dtsi
+index 8b669e2eafec4..f7b680f6c48ad 100644
+--- a/arch/arm/boot/dts/am3517-som.dtsi
++++ b/arch/arm/boot/dts/am3517-som.dtsi
+@@ -69,6 +69,8 @@
+ };
+
+ &i2c1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+
+ s35390a: s35390a@30 {
+@@ -179,6 +181,13 @@
+
+ &omap3_pmx_core {
+
++ i2c1_pins: pinmux_i2c1_pins {
++ pinctrl-single,pins = <
++ OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */
++ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */
++ >;
++ };
++
+ wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* mmc1_dat7.gpio_129 */
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index 9b1a24cc5e91f..df3c8d1d8f641 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
@@ -1195,6 +1692,198 @@ index 9b1a24cc5e91f..df3c8d1d8f641 100644
reg = <0x12100 0x100>;
reg-shift = <2>;
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
+index 2efd70666738c..af7ea7cab8cfa 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
+@@ -231,6 +231,21 @@
+ gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_LOW>;
+ };
+ };
++
++ iio-hwmon {
++ compatible = "iio-hwmon";
++ io-channels = <&adc1 7>;
++ };
++};
++
++&adc1 {
++ status = "okay";
++ aspeed,int-vref-microvolt = <2500000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default
++ &pinctrl_adc10_default &pinctrl_adc11_default
++ &pinctrl_adc12_default &pinctrl_adc13_default
++ &pinctrl_adc14_default &pinctrl_adc15_default>;
+ };
+
+ &gpio0 {
+diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+index 6419c9762c0b6..6c9f34396a3ae 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+@@ -246,6 +246,21 @@
+ linux,code = <11>;
+ };
+ };
++
++ iio-hwmon {
++ compatible = "iio-hwmon";
++ io-channels = <&adc1 7>;
++ };
++};
++
++&adc1 {
++ status = "okay";
++ aspeed,int-vref-microvolt = <2500000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default
++ &pinctrl_adc10_default &pinctrl_adc11_default
++ &pinctrl_adc12_default &pinctrl_adc13_default
++ &pinctrl_adc14_default &pinctrl_adc15_default>;
+ };
+
+ &ehci1 {
+diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+index 6dde51c2aed3f..ac07c240419a2 100644
+--- a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+@@ -117,11 +117,6 @@
+ groups = "FWSPID";
+ };
+
+- pinctrl_fwqspid_default: fwqspid_default {
+- function = "FWQSPID";
+- groups = "FWQSPID";
+- };
+-
+ pinctrl_fwspiwp_default: fwspiwp_default {
+ function = "FWSPIWP";
+ groups = "FWSPIWP";
+@@ -653,12 +648,12 @@
+ };
+
+ pinctrl_qspi1_default: qspi1_default {
+- function = "QSPI1";
++ function = "SPI1";
+ groups = "QSPI1";
+ };
+
+ pinctrl_qspi2_default: qspi2_default {
+- function = "QSPI2";
++ function = "SPI2";
+ groups = "QSPI2";
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 1b47be1704f83..e5724b1a2e20d 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -364,6 +364,41 @@
+ status = "disabled";
+ };
+
++ adc0: adc@1e6e9000 {
++ compatible = "aspeed,ast2600-adc0";
++ reg = <0x1e6e9000 0x100>;
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_ADC>;
++ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
++ #io-channel-cells = <1>;
++ status = "disabled";
++ };
++
++ adc1: adc@1e6e9100 {
++ compatible = "aspeed,ast2600-adc1";
++ reg = <0x1e6e9100 0x100>;
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_ADC>;
++ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
++ #io-channel-cells = <1>;
++ status = "disabled";
++ };
++
++ sbc: secure-boot-controller@1e6f2000 {
++ compatible = "aspeed,ast2600-sbc";
++ reg = <0x1e6f2000 0x1000>;
++ };
++
++ video: video@1e700000 {
++ compatible = "aspeed,ast2600-video-engine";
++ reg = <0x1e700000 0x1000>;
++ clocks = <&syscon ASPEED_CLK_GATE_VCLK>,
++ <&syscon ASPEED_CLK_GATE_ECLK>;
++ clock-names = "vclk", "eclk";
++ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ };
++
+ gpio0: gpio@1e780000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+index d72c042f28507..a49c2966b41e2 100644
+--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
++++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+@@ -57,8 +57,8 @@
+ };
+
+ spi0: spi@f0004000 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_spi0_cs>;
++ pinctrl-names = "default", "cs";
++ pinctrl-1 = <&pinctrl_spi0_cs>;
+ cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>;
+ status = "okay";
+ };
+@@ -171,8 +171,8 @@
+ };
+
+ spi1: spi@f8008000 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_spi1_cs>;
++ pinctrl-names = "default", "cs";
++ pinctrl-1 = <&pinctrl_spi1_cs>;
+ cs-gpios = <&pioC 25 0>;
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+index d241c24f0d836..e519d27479362 100644
+--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
++++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+@@ -81,8 +81,8 @@
+ };
+
+ spi1: spi@fc018000 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_spi0_cs>;
++ pinctrl-names = "default", "cs";
++ pinctrl-1 = <&pinctrl_spi1_cs>;
+ cs-gpios = <&pioB 21 0>;
+ status = "okay";
+ };
+@@ -140,7 +140,7 @@
+ atmel,pins =
+ <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+ };
+- pinctrl_spi0_cs: spi0_cs_default {
++ pinctrl_spi1_cs: spi1_cs_default {
+ atmel,pins =
+ <AT91_PIOB 21 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+diff --git a/arch/arm/boot/dts/at91-sama7g5ek.dts b/arch/arm/boot/dts/at91-sama7g5ek.dts
+index f3d6aaa3a78dc..bac0e49cc5770 100644
+--- a/arch/arm/boot/dts/at91-sama7g5ek.dts
++++ b/arch/arm/boot/dts/at91-sama7g5ek.dts
+@@ -403,7 +403,7 @@
+ pinctrl_flx3_default: flx3_default {
+ pinmux = <PIN_PD16__FLEXCOM3_IO0>,
+ <PIN_PD17__FLEXCOM3_IO1>;
+- bias-disable;
++ bias-pull-up;
+ };
+
+ pinctrl_flx4_default: flx4_default {
diff --git a/arch/arm/boot/dts/at91-tse850-3.dts b/arch/arm/boot/dts/at91-tse850-3.dts
index 3ca97b47c69ce..7e5c598e7e68f 100644
--- a/arch/arm/boot/dts/at91-tse850-3.dts
@@ -1208,6 +1897,23 @@ index 3ca97b47c69ce..7e5c598e7e68f 100644
#address-cells = <1>;
#size-cells = <0>;
+diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+index 87bb39060e8be..ca03685f0f086 100644
+--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
++++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+@@ -219,6 +219,12 @@
+ wm8731: wm8731@1b {
+ compatible = "wm8731";
+ reg = <0x1b>;
++
++ /* PCK0 at 12MHz */
++ clocks = <&pmc PMC_TYPE_SYSTEM 8>;
++ clock-names = "mclk";
++ assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>;
++ assigned-clock-rates = <12000000>;
+ };
+ };
+
diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index 748df7955ae67..e96ddb2e26e2c 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -1231,10 +1937,102 @@ index 748df7955ae67..e96ddb2e26e2c 100644
reg = <0x21000 0x100>;
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
-index 3b60297af7f60..dff18fc9a9065 100644
+index 3b60297af7f60..89af57482bc8f 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -506,11 +506,17 @@
+@@ -290,6 +290,7 @@
+
+ hvs: hvs@7e400000 {
+ compatible = "brcm,bcm2711-hvs";
++ reg = <0x7e400000 0x8000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+@@ -458,12 +459,26 @@
+ #size-cells = <0>;
+ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
+
++ /* Source for d/i-cache-line-size and d/i-cache-sets
++ * https://developer.arm.com/documentation/100095/0003
++ * /Level-1-Memory-System/About-the-L1-memory-system?lang=en
++ * Source for d/i-cache-size
++ * https://www.raspberrypi.com/documentation/computers
++ * /processors.html#bcm2711
++ */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000d8>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ i-cache-size = <0xc000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+@@ -472,6 +487,13 @@
+ reg = <1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e0>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ i-cache-size = <0xc000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+@@ -480,6 +502,13 @@
+ reg = <2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e8>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ i-cache-size = <0xc000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+@@ -488,6 +517,28 @@
+ reg = <3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000f0>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ i-cache-size = <0xc000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
++ next-level-cache = <&l2>;
++ };
++
++ /* Source for d/i-cache-line-size and d/i-cache-sets
++ * https://developer.arm.com/documentation/100095/0003
++ * /Level-2-Memory-System/About-the-L2-memory-system?lang=en
++ * Source for d/i-cache-size
++ * https://www.raspberrypi.com/documentation/computers
++ * /processors.html#bcm2711
++ */
++ l2: l2-cache0 {
++ compatible = "cache";
++ cache-size = <0x100000>;
++ cache-line-size = <64>;
++ cache-sets = <1024>; // 1MiB(size)/64(line-size)=16384ways/16-way set
++ cache-level = <2>;
+ };
+ };
+
+@@ -506,11 +557,17 @@
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
@@ -1253,7 +2051,7 @@ index 3b60297af7f60..dff18fc9a9065 100644
IRQ_TYPE_LEVEL_HIGH>;
msi-controller;
msi-parent = <&pcie0>;
-@@ -576,6 +582,8 @@
+@@ -576,6 +633,8 @@
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
@@ -1262,6 +2060,93 @@ index 3b60297af7f60..dff18fc9a9065 100644
gpclk0_gpio49: gpclk0_gpio49 {
pin-gpclk {
pins = "gpio49";
+diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi
+index 0199ec98cd616..5dbdebc462594 100644
+--- a/arch/arm/boot/dts/bcm2837.dtsi
++++ b/arch/arm/boot/dts/bcm2837.dtsi
+@@ -40,12 +40,26 @@
+ #size-cells = <0>;
+ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
+
++ /* Source for d/i-cache-line-size and d/i-cache-sets
++ * https://developer.arm.com/documentation/ddi0500/e/level-1-memory-system
++ * /about-the-l1-memory-system?lang=en
++ *
++ * Source for d/i-cache-size
++ * https://magpi.raspberrypi.com/articles/raspberry-pi-3-specs-benchmarks
++ */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000d8>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
++ i-cache-size = <0x8000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+@@ -54,6 +68,13 @@
+ reg = <1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e0>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
++ i-cache-size = <0x8000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+@@ -62,6 +83,13 @@
+ reg = <2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e8>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
++ i-cache-size = <0x8000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+@@ -70,6 +98,27 @@
+ reg = <3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000f0>;
++ d-cache-size = <0x8000>;
++ d-cache-line-size = <64>;
++ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
++ i-cache-size = <0x8000>;
++ i-cache-line-size = <64>;
++ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
++ next-level-cache = <&l2>;
++ };
++
++ /* Source for cache-line-size + cache-sets
++ * https://developer.arm.com/documentation/ddi0500
++ * /e/level-2-memory-system/about-the-l2-memory-system?lang=en
++ * Source for cache-size
++ * https://datasheets.raspberrypi.com/cm/cm1-and-cm3-datasheet.pdf
++ */
++ l2: l2-cache0 {
++ compatible = "cache";
++ cache-size = <0x80000>;
++ cache-line-size = <64>;
++ cache-sets = <512>; // 512KiB(size)/64(line-size)=8192ways/16-way set
++ cache-level = <2>;
+ };
+ };
+ };
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index a3e06b6809476..c113661a6668f 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
@@ -1516,6 +2401,72 @@ index 5017b7b259cbe..618c812eef73e 100644
device_type = "memory";
reg = <0x00000000 0x08000000>;
};
+diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/dra7-l4.dtsi
+index 956a26d52a4c3..5733e3a4ea8e7 100644
+--- a/arch/arm/boot/dts/dra7-l4.dtsi
++++ b/arch/arm/boot/dts/dra7-l4.dtsi
+@@ -3482,8 +3482,7 @@
+ ti,timer-pwm;
+ };
+ };
+-
+- target-module@2c000 { /* 0x4882c000, ap 17 02.0 */
++ timer15_target: target-module@2c000 { /* 0x4882c000, ap 17 02.0 */
+ compatible = "ti,sysc-omap4-timer", "ti,sysc";
+ reg = <0x2c000 0x4>,
+ <0x2c010 0x4>;
+@@ -3511,7 +3510,7 @@
+ };
+ };
+
+- target-module@2e000 { /* 0x4882e000, ap 19 14.0 */
++ timer16_target: target-module@2e000 { /* 0x4882e000, ap 19 14.0 */
+ compatible = "ti,sysc-omap4-timer", "ti,sysc";
+ reg = <0x2e000 0x4>,
+ <0x2e010 0x4>;
+@@ -4189,11 +4188,11 @@
+ reg = <0x1d0010 0x4>;
+ reg-names = "sysc";
+ ti,sysc-midle = <SYSC_IDLE_FORCE>,
+- <SYSC_IDLE_NO>,
+- <SYSC_IDLE_SMART>;
++ <SYSC_IDLE_NO>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
++ power-domains = <&prm_vpe>;
+ clocks = <&vpe_clkctrl DRA7_VPE_VPE_CLKCTRL 0>;
+ clock-names = "fck";
+ #address-cells = <1>;
+diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
+index dfc1ef8ef6aea..61a3fb3e2a2f9 100644
+--- a/arch/arm/boot/dts/dra7.dtsi
++++ b/arch/arm/boot/dts/dra7.dtsi
+@@ -1320,20 +1320,20 @@
+ };
+
+ /* Local timers, see ARM architected timer wrap erratum i940 */
+-&timer3_target {
++&timer15_target {
+ ti,no-reset-on-init;
+ ti,no-idle;
+ timer@0 {
+- assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER3_CLKCTRL 24>;
++ assigned-clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>;
+ assigned-clock-parents = <&timer_sys_clk_div>;
+ };
+ };
+
+-&timer4_target {
++&timer16_target {
+ ti,no-reset-on-init;
+ ti,no-idle;
+ timer@0 {
+- assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 24>;
++ assigned-clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>;
+ assigned-clock-parents = <&timer_sys_clk_div>;
+ };
+ };
diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts
index 55922176807e6..5f5d9b1357365 100644
--- a/arch/arm/boot/dts/exynos4210-i9100.dts
@@ -1529,6 +2480,47 @@ index 55922176807e6..5f5d9b1357365 100644
device-wakeup-gpios = <&gpx3 1 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpx2 6 GPIO_ACTIVE_HIGH>;
};
+diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+index d31a68672bfac..d7d756614edd1 100644
+--- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
++++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+@@ -260,7 +260,7 @@
+ };
+
+ uart3_data: uart3-data {
+- samsung,pins = "gpa1-4", "gpa1-4";
++ samsung,pins = "gpa1-4", "gpa1-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
+index 39bbe18145cf2..f042954bdfa5d 100644
+--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
++++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
+@@ -118,6 +118,9 @@
+ status = "okay";
+ ddc = <&i2c_2>;
+ hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>;
++ vdd-supply = <&ldo8_reg>;
++ vdd_osc-supply = <&ldo10_reg>;
++ vdd_pll-supply = <&ldo8_reg>;
+ };
+
+ &i2c_0 {
+diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
+index a4f0e3ffedbd3..07f65213aae65 100644
+--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
++++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
+@@ -124,6 +124,9 @@
+ hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_hpd_irq>;
++ vdd-supply = <&ldo6_reg>;
++ vdd_osc-supply = <&ldo7_reg>;
++ vdd_pll-supply = <&ldo6_reg>;
+ };
+
+ &hsi2c_4 {
diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts
index 13112a8a5dd88..6544c730340fa 100644
--- a/arch/arm/boot/dts/gemini-nas4220b.dts
@@ -1554,6 +2546,95 @@ index 8cbaf1c811745..3b609d987d883 100644
>;
fsl,drive-strength = <MXS_DRIVE_4mA>;
fsl,voltage = <MXS_VOLTAGE_HIGH>;
+diff --git a/arch/arm/boot/dts/imx53-m53menlo.dts b/arch/arm/boot/dts/imx53-m53menlo.dts
+index 4f88e96d81ddb..d5c68d1ea707c 100644
+--- a/arch/arm/boot/dts/imx53-m53menlo.dts
++++ b/arch/arm/boot/dts/imx53-m53menlo.dts
+@@ -53,6 +53,31 @@
+ };
+ };
+
++ lvds-decoder {
++ compatible = "ti,ds90cf364a", "lvds-decoder";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ reg = <0>;
++
++ lvds_decoder_in: endpoint {
++ remote-endpoint = <&lvds0_out>;
++ };
++ };
++
++ port@1 {
++ reg = <1>;
++
++ lvds_decoder_out: endpoint {
++ remote-endpoint = <&panel_in>;
++ };
++ };
++ };
++ };
++
+ panel {
+ compatible = "edt,etm0700g0dh6";
+ pinctrl-0 = <&pinctrl_display_gpio>;
+@@ -61,7 +86,7 @@
+
+ port {
+ panel_in: endpoint {
+- remote-endpoint = <&lvds0_out>;
++ remote-endpoint = <&lvds_decoder_out>;
+ };
+ };
+ };
+@@ -450,7 +475,7 @@
+ reg = <2>;
+
+ lvds0_out: endpoint {
+- remote-endpoint = <&panel_in>;
++ remote-endpoint = <&lvds_decoder_in>;
+ };
+ };
+ };
+diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+index 30fa349f9d054..a696873dc1abe 100644
+--- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
++++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+@@ -286,6 +286,8 @@
+ codec: sgtl5000@a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_sgtl5000>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ VDDA-supply = <&reg_module_3v3_audio>;
+ VDDIO-supply = <&reg_module_3v3>;
+@@ -516,8 +518,6 @@
+ MX6QDL_PAD_DISP0_DAT21__AUD4_TXD 0x130b0
+ MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS 0x130b0
+ MX6QDL_PAD_DISP0_DAT23__AUD4_RXD 0x130b0
+- /* SGTL5000 sys_mclk */
+- MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+ >;
+ };
+
+@@ -810,6 +810,12 @@
+ >;
+ };
+
++ pinctrl_sgtl5000: sgtl5000grp {
++ fsl,pins = <
++ MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
++ >;
++ };
++
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0
diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
index d07d8f83456d2..ccfa8e320be62 100644
--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi
@@ -1596,6 +2677,19 @@ index b62a0dbb033ff..ec6fba5ee8fde 100644
};
};
};
+diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/imx6ull-colibri.dtsi
+index 0cdbf7b6e7285..b6fc879e9dbe6 100644
+--- a/arch/arm/boot/dts/imx6ull-colibri.dtsi
++++ b/arch/arm/boot/dts/imx6ull-colibri.dtsi
+@@ -37,7 +37,7 @@
+
+ reg_sd1_vmmc: regulator-sd1-vmmc {
+ compatible = "regulator-gpio";
+- gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>;
++ gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_reg_sd>;
+ regulator-always-on;
diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h
index eb025a9d47592..7328d4ef8559f 100644
--- a/arch/arm/boot/dts/imx6ull-pinfunc.h
@@ -1608,6 +2702,141 @@ index eb025a9d47592..7328d4ef8559f 100644
+#define MX6ULL_PAD_CSI_DATA07__ESAI_TX0 0x0200 0x048C 0x0000 0x9 0x0
#endif /* __DTS_IMX6ULL_PINFUNC_H */
+diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
+index 62b771c1d5a9a..f1c60b0cb143e 100644
+--- a/arch/arm/boot/dts/imx7-colibri.dtsi
++++ b/arch/arm/boot/dts/imx7-colibri.dtsi
+@@ -40,7 +40,7 @@
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&codec>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ };
+ };
+ };
+@@ -293,7 +293,7 @@
+ compatible = "fsl,sgtl5000";
+ #sound-dai-cells = <0>;
+ reg = <0x0a>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1_mclk>;
+ VDDA-supply = <&reg_module_3v3_avdd>;
+diff --git a/arch/arm/boot/dts/imx7-mba7.dtsi b/arch/arm/boot/dts/imx7-mba7.dtsi
+index 5e6bef230dc75..b55a7792a8391 100644
+--- a/arch/arm/boot/dts/imx7-mba7.dtsi
++++ b/arch/arm/boot/dts/imx7-mba7.dtsi
+@@ -264,7 +264,7 @@
+ tlv320aic32x4: audio-codec@18 {
+ compatible = "ti,tlv320aic32x4";
+ reg = <0x18>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ clock-names = "mclk";
+ ldoin-supply = <&reg_audio_3v3>;
+ iov-supply = <&reg_audio_3v3>;
+diff --git a/arch/arm/boot/dts/imx7d-nitrogen7.dts b/arch/arm/boot/dts/imx7d-nitrogen7.dts
+index e0751e6ba3c0f..a31de900139d6 100644
+--- a/arch/arm/boot/dts/imx7d-nitrogen7.dts
++++ b/arch/arm/boot/dts/imx7d-nitrogen7.dts
+@@ -288,7 +288,7 @@
+ codec: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ clock-names = "mclk";
+ wlf,shared-lrclk;
+ };
+diff --git a/arch/arm/boot/dts/imx7d-pico-hobbit.dts b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+index 7b2198a9372c6..d917dc4f2f227 100644
+--- a/arch/arm/boot/dts/imx7d-pico-hobbit.dts
++++ b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+@@ -31,7 +31,7 @@
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ };
+ };
+ };
+@@ -41,7 +41,7 @@
+ #sound-dai-cells = <0>;
+ reg = <0x0a>;
+ compatible = "fsl,sgtl5000";
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ VDDA-supply = <&reg_2p5v>;
+ VDDIO-supply = <&reg_vref_1v8>;
+ };
+diff --git a/arch/arm/boot/dts/imx7d-pico-pi.dts b/arch/arm/boot/dts/imx7d-pico-pi.dts
+index 70bea95c06d83..f263e391e24cb 100644
+--- a/arch/arm/boot/dts/imx7d-pico-pi.dts
++++ b/arch/arm/boot/dts/imx7d-pico-pi.dts
+@@ -31,7 +31,7 @@
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ };
+ };
+ };
+@@ -41,7 +41,7 @@
+ #sound-dai-cells = <0>;
+ reg = <0x0a>;
+ compatible = "fsl,sgtl5000";
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ VDDA-supply = <&reg_2p5v>;
+ VDDIO-supply = <&reg_vref_1v8>;
+ };
+diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
+index 4a0d83784d7d1..e5f1bdbe79921 100644
+--- a/arch/arm/boot/dts/imx7d-sdb.dts
++++ b/arch/arm/boot/dts/imx7d-sdb.dts
+@@ -385,14 +385,14 @@
+ codec: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ clock-names = "mclk";
+ wlf,shared-lrclk;
+ wlf,hp-cfg = <2 2 3>;
+ wlf,gpio-cfg = <1 3>;
+ assigned-clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_SRC>,
+ <&clks IMX7D_PLL_AUDIO_POST_DIV>,
+- <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <0>, <884736000>, <12288000>;
+ };
+diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts
+index 569bbd84e371a..558b064da743c 100644
+--- a/arch/arm/boot/dts/imx7s-warp.dts
++++ b/arch/arm/boot/dts/imx7s-warp.dts
+@@ -75,7 +75,7 @@
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&codec>;
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ };
+ };
+ };
+@@ -232,7 +232,7 @@
+ #sound-dai-cells = <0>;
+ reg = <0x0a>;
+ compatible = "fsl,sgtl5000";
+- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
++ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1_mclk>;
+ VDDA-supply = <&vgen4_reg>;
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index b7ea37ad4e55c..bcec98b964114 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
@@ -1621,6 +2850,78 @@ index b7ea37ad4e55c..bcec98b964114 100644
timeout-sec = <40>;
};
+diff --git a/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts b/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts
+index 2a0a98fe67f06..3240c67e0c392 100644
+--- a/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts
++++ b/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts
+@@ -11,3 +11,18 @@
+ model = "LogicPD Zoom OMAP35xx SOM-LV Development Kit";
+ compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3430", "ti,omap3";
+ };
++
++&omap3_pmx_core2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&hsusb2_2_pins>;
++ hsusb2_2_pins: pinmux_hsusb2_2_pins {
++ pinctrl-single,pins = <
++ OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */
++ OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */
++ OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */
++ OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */
++ OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */
++ OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */
++ >;
++ };
++};
+diff --git a/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts b/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
+index a604d92221a4f..c757f0d7781c1 100644
+--- a/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
++++ b/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
+@@ -11,3 +11,18 @@
+ model = "LogicPD Zoom DM3730 SOM-LV Development Kit";
+ compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3630", "ti,omap3";
+ };
++
++&omap3_pmx_core2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&hsusb2_2_pins>;
++ hsusb2_2_pins: pinmux_hsusb2_2_pins {
++ pinctrl-single,pins = <
++ OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */
++ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */
++ OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */
++ OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */
++ OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */
++ OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */
++ >;
++ };
++};
+diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/logicpd-som-lv.dtsi
+index b56524cc7fe27..55b619c99e24d 100644
+--- a/arch/arm/boot/dts/logicpd-som-lv.dtsi
++++ b/arch/arm/boot/dts/logicpd-som-lv.dtsi
+@@ -265,21 +265,6 @@
+ };
+ };
+
+-&omap3_pmx_core2 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&hsusb2_2_pins>;
+- hsusb2_2_pins: pinmux_hsusb2_2_pins {
+- pinctrl-single,pins = <
+- OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */
+- OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */
+- OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */
+- OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */
+- OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */
+- OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */
+- >;
+- };
+-};
+-
+ &uart2 {
+ interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
+ pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/ls1021a-tsn.dts b/arch/arm/boot/dts/ls1021a-tsn.dts
index 9d8f0c2a8aba3..aca78b5eddf20 100644
--- a/arch/arm/boot/dts/ls1021a-tsn.dts
@@ -2025,10 +3326,19 @@ index c2995a280729d..162d0726b0080 100644
- };
-};
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
-index 938cc691bb2fe..23ab27fe4ee5d 100644
+index 938cc691bb2fe..3923b38e798d0 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
-@@ -515,7 +515,7 @@
+@@ -31,6 +31,8 @@
+ aliases {
+ display0 = &lcd;
+ display1 = &tv0;
++ /delete-property/ mmc2;
++ /delete-property/ mmc3;
+ };
+
+ ldo_3v3: fixedregulator {
+@@ -515,7 +517,7 @@
compatible = "bosch,bma180";
reg = <0x41>;
pinctrl-names = "default";
@@ -2165,6 +3475,46 @@ index e5da3bc6f1050..218a10c0d8159 100644
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <42>;
gpmc,cs-wr-off-ns = <36>;
+diff --git a/arch/arm/boot/dts/openbmc-flash-layout-64.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-64.dtsi
+index 31f59de5190b8..7af41361c4800 100644
+--- a/arch/arm/boot/dts/openbmc-flash-layout-64.dtsi
++++ b/arch/arm/boot/dts/openbmc-flash-layout-64.dtsi
+@@ -28,7 +28,7 @@ partitions {
+ label = "rofs";
+ };
+
+- rwfs@6000000 {
++ rwfs@2a00000 {
+ reg = <0x2a00000 0x1600000>; // 22MB
+ label = "rwfs";
+ };
+diff --git a/arch/arm/boot/dts/openbmc-flash-layout.dtsi b/arch/arm/boot/dts/openbmc-flash-layout.dtsi
+index 6c26524e93e11..b47e14063c380 100644
+--- a/arch/arm/boot/dts/openbmc-flash-layout.dtsi
++++ b/arch/arm/boot/dts/openbmc-flash-layout.dtsi
+@@ -20,7 +20,7 @@ partitions {
+ label = "kernel";
+ };
+
+- rofs@c0000 {
++ rofs@4c0000 {
+ reg = <0x4c0000 0x1740000>;
+ label = "rofs";
+ };
+diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi
+index ff1bdb10ad198..08bc5f46649dd 100644
+--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
+@@ -142,7 +142,8 @@
+ clocks {
+ sleep_clk: sleep_clk {
+ compatible = "fixed-clock";
+- clock-frequency = <32768>;
++ clock-frequency = <32000>;
++ clock-output-names = "gcc_sleep_clk_src";
+ #clock-cells = <0>;
+ };
+
diff --git a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
index f7ea2e5dd1914..971d2e2292600 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
@@ -2193,6 +3543,39 @@ index f7ea2e5dd1914..971d2e2292600 100644
status = "okay";
compatible = "virtual,mdio-gpio";
gpios = <&qcom_pinmux 11 GPIO_ACTIVE_HIGH>,
+diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom-msm8960.dtsi
+index 172ea3c70eac2..c197927e7435f 100644
+--- a/arch/arm/boot/dts/qcom-msm8960.dtsi
++++ b/arch/arm/boot/dts/qcom-msm8960.dtsi
+@@ -146,7 +146,9 @@
+ reg = <0x108000 0x1000>;
+ qcom,ipc = <&l2cc 0x8 2>;
+
+- interrupts = <0 19 0>, <0 21 0>, <0 22 0>;
++ interrupts = <GIC_SPI 19 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ack", "err", "wakeup";
+
+ regulators {
+@@ -192,7 +194,7 @@
+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+ reg = <0x16440000 0x1000>,
+ <0x16400000 0x1000>;
+- interrupts = <0 154 0x0>;
++ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+@@ -318,7 +320,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x16080000 0x1000>;
+- interrupts = <0 147 0>;
++ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <24000000>;
+ cs-gpios = <&msmgpio 8 0>;
+
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 78ec496d5bc30..2b01bc29ddf23 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -2227,6 +3610,47 @@ index 1e6ce035f76a9..b5b784c5c65e4 100644
"imem",
"config";
+diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
+index 75af99c76d7ea..f31cf1df892b2 100644
+--- a/arch/arm/boot/dts/rk322x.dtsi
++++ b/arch/arm/boot/dts/rk322x.dtsi
+@@ -718,8 +718,8 @@
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ assigned-clocks = <&cru SCLK_HDMI_PHY>;
+ assigned-clock-parents = <&hdmi_phy>;
+- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>;
+- clock-names = "isfr", "iahb", "cec";
++ clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
++ clock-names = "iahb", "isfr", "cec";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>;
+ resets = <&cru SRST_HDMI_P>;
+diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
+index 4dcdcf17c9776..66ff5db53c5a9 100644
+--- a/arch/arm/boot/dts/rk3288.dtsi
++++ b/arch/arm/boot/dts/rk3288.dtsi
+@@ -971,7 +971,7 @@
+ status = "disabled";
+ };
+
+- crypto: cypto-controller@ff8a0000 {
++ crypto: crypto@ff8a0000 {
+ compatible = "rockchip,rk3288-crypto";
+ reg = <0x0 0xff8a0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
+index 801969c113d64..de88eb4847185 100644
+--- a/arch/arm/boot/dts/sama5d2.dtsi
++++ b/arch/arm/boot/dts/sama5d2.dtsi
+@@ -413,7 +413,7 @@
+ pmecc: ecc-engine@f8014070 {
+ compatible = "atmel,sama5d2-pmecc";
+ reg = <0xf8014070 0x490>,
+- <0xf8014500 0x100>;
++ <0xf8014500 0x200>;
+ };
+ };
+
diff --git a/arch/arm/boot/dts/sama7g5-pinfunc.h b/arch/arm/boot/dts/sama7g5-pinfunc.h
index 22fe9e522a97b..4eb30445d2057 100644
--- a/arch/arm/boot/dts/sama7g5-pinfunc.h
@@ -2240,6 +3664,63 @@ index 22fe9e522a97b..4eb30445d2057 100644
#define PIN_PD20__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD20, 6, 5)
#define PIN_PD21 117
#define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0)
+diff --git a/arch/arm/boot/dts/sama7g5.dtsi b/arch/arm/boot/dts/sama7g5.dtsi
+index 6c58c151c6d9e..ac84d2e37f9b2 100644
+--- a/arch/arm/boot/dts/sama7g5.dtsi
++++ b/arch/arm/boot/dts/sama7g5.dtsi
+@@ -319,8 +319,6 @@
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(7)>,
+ <&dma0 AT91_XDMAC_DT_PERID(8)>;
+ dma-names = "rx", "tx";
+- atmel,use-dma-rx;
+- atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+@@ -485,8 +483,6 @@
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(21)>,
+ <&dma0 AT91_XDMAC_DT_PERID(22)>;
+ dma-names = "rx", "tx";
+- atmel,use-dma-rx;
+- atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+@@ -511,8 +507,6 @@
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(23)>,
+ <&dma0 AT91_XDMAC_DT_PERID(24)>;
+ dma-names = "rx", "tx";
+- atmel,use-dma-rx;
+- atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
+index 0b021eef0b538..7c1d6423d7f8c 100644
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -782,7 +782,7 @@
+ };
+
+ qspi: spi@ff705000 {
+- compatible = "cdns,qspi-nor";
++ compatible = "intel,socfpga-qspi", "cdns,qspi-nor";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xff705000 0x1000>,
+diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
+index a574ea91d9d3f..3ba431dfa8c94 100644
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -756,7 +756,7 @@
+ };
+
+ qspi: spi@ff809000 {
+- compatible = "cdns,qspi-nor";
++ compatible = "intel,socfpga-qspi", "cdns,qspi-nor";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xff809000 0x100>,
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
index 2b645642b9352..2a745522404d6 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
@@ -2340,6 +3821,40 @@ index a060718758b67..25874e1b9c829 100644
reg = <1>; /* chip select */
spi-max-frequency = <100000000>;
m25p,fast-read;
+diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
+index 1a8f5e8b10e3a..66cd473ecb617 100644
+--- a/arch/arm/boot/dts/spear1340.dtsi
++++ b/arch/arm/boot/dts/spear1340.dtsi
+@@ -136,9 +136,9 @@
+ reg = <0xb4100000 0x1000>;
+ interrupts = <0 105 0x4>;
+ status = "disabled";
+- dmas = <&dwdma0 12 0 1>,
+- <&dwdma0 13 1 0>;
+- dma-names = "tx", "rx";
++ dmas = <&dwdma0 13 0 1>,
++ <&dwdma0 12 1 0>;
++ dma-names = "rx", "tx";
+ };
+
+ thermal@e07008c4 {
+diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
+index c87b881b2c8bb..9135533676879 100644
+--- a/arch/arm/boot/dts/spear13xx.dtsi
++++ b/arch/arm/boot/dts/spear13xx.dtsi
+@@ -284,9 +284,9 @@
+ #size-cells = <0>;
+ interrupts = <0 31 0x4>;
+ status = "disabled";
+- dmas = <&dwdma0 4 0 0>,
+- <&dwdma0 5 0 0>;
+- dma-names = "tx", "rx";
++ dmas = <&dwdma0 5 0 0>,
++ <&dwdma0 4 0 0>;
++ dma-names = "rx", "tx";
+ };
+
+ rtc@e0580000 {
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
index 264f3e9b5fce5..7fab746e0570e 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
@@ -2600,6 +4115,45 @@ index 4e89701df91f8..ae4f933abb895 100644
compatible = "operating-points-v2";
opp-120000000 {
+diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
+index b30bc1a25ebb9..084323d5c61cb 100644
+--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
++++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
+@@ -593,6 +593,17 @@
+ #size-cells = <0>;
+ };
+
++ gic: interrupt-controller@1c81000 {
++ compatible = "arm,gic-400";
++ reg = <0x01c81000 0x1000>,
++ <0x01c82000 0x2000>,
++ <0x01c84000 0x2000>,
++ <0x01c86000 0x2000>;
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
++ };
++
+ csi1: camera@1cb4000 {
+ compatible = "allwinner,sun8i-v3s-csi";
+ reg = <0x01cb4000 0x3000>;
+@@ -604,16 +615,5 @@
+ resets = <&ccu RST_BUS_CSI>;
+ status = "disabled";
+ };
+-
+- gic: interrupt-controller@1c81000 {
+- compatible = "arm,gic-400";
+- reg = <0x01c81000 0x1000>,
+- <0x01c82000 0x2000>,
+- <0x01c84000 0x2000>,
+- <0x01c86000 0x2000>;
+- interrupt-controller;
+- #interrupt-cells = <3>;
+- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+- };
+ };
+ };
diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts
index 1d2aac2cb6d03..fdc1d64dfff9d 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big.dts
@@ -2684,6 +4238,30 @@ index e6b54ac1ebd1a..84e2d24065e9a 100644
vdd_mux: regulator@0 {
compatible = "regulator-fixed";
regulator-name = "+VDD_MUX";
+diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
+index dd4d506683de7..7f14f0d005c3e 100644
+--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
++++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
+@@ -183,8 +183,8 @@
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+- "cdev1", "cdev2", "dap1", "dtb", "gma",
+- "gmb", "gmc", "gmd", "gme", "gpu7",
++ "cdev1", "cdev2", "dap1", "dtb", "dtf",
++ "gma", "gmb", "gmc", "gmd", "gme", "gpu7",
+ "gpv", "i2cp", "irrx", "irtx", "pta",
+ "rm", "slxa", "slxk", "spia", "spib",
+ "uac";
+@@ -203,7 +203,7 @@
+ };
+ conf_crtp {
+ nvidia,pins = "crtp", "dap2", "dap3", "dap4",
+- "dtc", "dte", "dtf", "gpu", "sdio1",
++ "dtc", "dte", "gpu", "sdio1",
+ "slxc", "slxd", "spdi", "spdo", "spig",
+ "uda";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 502a9d870ca44..45769d0ddd4ef 100644
--- a/arch/arm/configs/cm_x300_defconfig
@@ -2720,6 +4298,26 @@ index 118c4c927f264..6db871d4e0775 100644
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
+diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
+index 80a3ae02d7594..e883cb6dc6459 100644
+--- a/arch/arm/configs/multi_v5_defconfig
++++ b/arch/arm/configs/multi_v5_defconfig
+@@ -188,6 +188,7 @@ CONFIG_REGULATOR=y
+ CONFIG_REGULATOR_FIXED_VOLTAGE=y
+ CONFIG_MEDIA_SUPPORT=y
+ CONFIG_MEDIA_CAMERA_SUPPORT=y
++CONFIG_MEDIA_PLATFORM_SUPPORT=y
+ CONFIG_V4L_PLATFORM_DRIVERS=y
+ CONFIG_VIDEO_ASPEED=m
+ CONFIG_VIDEO_ATMEL_ISI=m
+@@ -195,6 +196,7 @@ CONFIG_DRM=y
+ CONFIG_DRM_ATMEL_HLCDC=m
+ CONFIG_DRM_PANEL_SIMPLE=y
+ CONFIG_DRM_ASPEED_GFX=m
++CONFIG_FB=y
+ CONFIG_FB_IMX=y
+ CONFIG_FB_ATMEL=y
+ CONFIG_BACKLIGHT_ATMEL_LCDC=y
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index 23595fc5a29a9..907d6512821ad 100644
--- a/arch/arm/configs/nhk8815_defconfig
@@ -2780,6 +4378,236 @@ index 52a56b8ce6a71..bc32c02cb86b1 100644
CONFIG_I2C=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
+diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
+index 2b575792363e5..e4dba5461cb3e 100644
+--- a/arch/arm/crypto/Kconfig
++++ b/arch/arm/crypto/Kconfig
+@@ -102,6 +102,8 @@ config CRYPTO_AES_ARM_BS
+ depends on KERNEL_MODE_NEON
+ select CRYPTO_SKCIPHER
+ select CRYPTO_LIB_AES
++ select CRYPTO_AES
++ select CRYPTO_CBC
+ select CRYPTO_SIMD
+ help
+ Use a faster and more secure NEON based implementation of AES in CBC,
+diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
+index eafa898ba6a73..0274f81cc8ea0 100644
+--- a/arch/arm/crypto/Makefile
++++ b/arch/arm/crypto/Makefile
+@@ -10,6 +10,7 @@ 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_BLAKE2B_NEON) += blake2b-neon.o
+ obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
+ obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o
+@@ -31,7 +32,8 @@ 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-core.o blake2s-glue.o
++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
+ sha2-arm-ce-y := sha2-ce-core.o sha2-ce-glue.o
+diff --git a/arch/arm/crypto/blake2s-core.S b/arch/arm/crypto/blake2s-core.S
+index 86345751bbf3a..df40e46601f10 100644
+--- a/arch/arm/crypto/blake2s-core.S
++++ b/arch/arm/crypto/blake2s-core.S
+@@ -167,8 +167,8 @@
+ .endm
+
+ //
+-// void blake2s_compress_arch(struct blake2s_state *state,
+-// const u8 *block, size_t nblocks, u32 inc);
++// void blake2s_compress(struct blake2s_state *state,
++// const u8 *block, size_t nblocks, u32 inc);
+ //
+ // Only the first three fields of struct blake2s_state are used:
+ // u32 h[8]; (inout)
+@@ -176,7 +176,7 @@
+ // u32 f[2]; (in)
+ //
+ .align 5
+-ENTRY(blake2s_compress_arch)
++ENTRY(blake2s_compress)
+ push {r0-r2,r4-r11,lr} // keep this an even number
+
+ .Lnext_block:
+@@ -303,4 +303,4 @@ ENTRY(blake2s_compress_arch)
+ str r3, [r12], #4
+ bne 1b
+ b .Lcopy_block_done
+-ENDPROC(blake2s_compress_arch)
++ENDPROC(blake2s_compress)
+diff --git a/arch/arm/crypto/blake2s-glue.c b/arch/arm/crypto/blake2s-glue.c
+index f2cc1e5fc9ec1..0238a70d9581e 100644
+--- a/arch/arm/crypto/blake2s-glue.c
++++ b/arch/arm/crypto/blake2s-glue.c
+@@ -1,78 +1,7 @@
+ // 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>
+
+ /* defined in blake2s-core.S */
+-EXPORT_SYMBOL(blake2s_compress_arch);
+-
+-static int crypto_blake2s_update_arm(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen)
+-{
+- return crypto_blake2s_update(desc, in, inlen, blake2s_compress_arch);
+-}
+-
+-static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out)
+-{
+- return crypto_blake2s_final(desc, out, blake2s_compress_arch);
+-}
+-
+-#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");
++EXPORT_SYMBOL(blake2s_compress);
+diff --git a/arch/arm/crypto/blake2s-shash.c b/arch/arm/crypto/blake2s-shash.c
+new file mode 100644
+index 0000000000000..763c73beea2d0
+--- /dev/null
++++ b/arch/arm/crypto/blake2s-shash.c
+@@ -0,0 +1,75 @@
++// 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/assembler.h b/arch/arm/include/asm/assembler.h
index e2b1fd558bf3c..09c241280ed9c 100644
--- a/arch/arm/include/asm/assembler.h
@@ -2829,6 +4657,20 @@ index a6f3b179e8a94..27218eabbf9a0 100644
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
+diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
+index f74944c6fe8d3..79d246ac93ab6 100644
+--- a/arch/arm/include/asm/io.h
++++ b/arch/arm/include/asm/io.h
+@@ -436,6 +436,9 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
+ #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+ extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
+ extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
++extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
++ unsigned long flags);
++#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
+ #endif
+
+ /*
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 9e6b972863077..8aeff55aebfaf 100644
--- a/arch/arm/include/asm/processor.h
@@ -2843,10 +4685,10 @@ index 9e6b972863077..8aeff55aebfaf 100644
" .popsection\n"
diff --git a/arch/arm/include/asm/spectre.h b/arch/arm/include/asm/spectre.h
new file mode 100644
-index 0000000000000..d1fa5607d3aa3
+index 0000000000000..85f9e538fb325
--- /dev/null
+++ b/arch/arm/include/asm/spectre.h
-@@ -0,0 +1,32 @@
+@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_SPECTRE_H
@@ -2874,11 +4716,28 @@ index 0000000000000..d1fa5607d3aa3
+ SPECTRE_V2_METHOD_LOOP8 = BIT(__SPECTRE_V2_METHOD_LOOP8),
+};
+
++#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
+void spectre_v2_update_state(unsigned int state, unsigned int methods);
++#else
++static inline void spectre_v2_update_state(unsigned int state,
++ unsigned int methods)
++{}
++#endif
+
+int spectre_bhb_update_vectors(unsigned int method);
+
+#endif
+diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h
+index 7c3b3671d6c25..6d1337c169cd3 100644
+--- a/arch/arm/include/asm/timex.h
++++ b/arch/arm/include/asm/timex.h
+@@ -11,5 +11,6 @@
+
+ typedef unsigned long cycles_t;
+ #define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })
++#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
+
+ #endif
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 36fbc33292526..32dbfd81f42a4 100644
--- a/arch/arm/include/asm/uaccess.h
@@ -3036,7 +4895,7 @@ index ae295a3bcfefd..6ef3b535b7bf7 100644
+
extra-y := $(head-y) vmlinux.lds
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
-index 241b73d64df73..a0654ab1074f9 100644
+index 241b73d64df73..68261a83b7ad8 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -597,11 +597,9 @@ call_fpe:
@@ -3096,9 +4955,9 @@ index 241b73d64df73..a0654ab1074f9 100644
+
+ @ bhb workaround
+ mov r0, #8
-+1: b . + 4
++3: W(b) . + 4
+ subs r0, r0, #1
-+ bne 1b
++ bne 3b
+ dsb
+ isb
+ b 2b
@@ -3220,6 +5079,111 @@ index d9c99db50243f..fde7ac271b147 100644
ARM( add r8, sp, #S_PC )
ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr
THUMB( mov r8, sp )
+diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S
+index a74289ebc8036..5f1b1ce10473a 100644
+--- a/arch/arm/kernel/entry-ftrace.S
++++ b/arch/arm/kernel/entry-ftrace.S
+@@ -22,10 +22,7 @@
+ * mcount can be thought of as a function called in the middle of a subroutine
+ * call. As such, it needs to be transparent for both the caller and the
+ * callee: the original lr needs to be restored when leaving mcount, and no
+- * registers should be clobbered. (In the __gnu_mcount_nc implementation, we
+- * clobber the ip register. This is OK because the ARM calling convention
+- * allows it to be clobbered in subroutines and doesn't use it to hold
+- * parameters.)
++ * registers should be clobbered.
+ *
+ * When using dynamic ftrace, we patch out the mcount call by a "pop {lr}"
+ * instead of the __gnu_mcount_nc call (see arch/arm/kernel/ftrace.c).
+@@ -70,26 +67,25 @@
+
+ .macro __ftrace_regs_caller
+
+- sub sp, sp, #8 @ space for PC and CPSR OLD_R0,
++ str lr, [sp, #-8]! @ store LR as PC and make space for CPSR/OLD_R0,
+ @ OLD_R0 will overwrite previous LR
+
+- add ip, sp, #12 @ move in IP the value of SP as it was
+- @ before the push {lr} of the mcount mechanism
++ ldr lr, [sp, #8] @ get previous LR
+
+- str lr, [sp, #0] @ store LR instead of PC
++ str r0, [sp, #8] @ write r0 as OLD_R0 over previous LR
+
+- ldr lr, [sp, #8] @ get previous LR
++ str lr, [sp, #-4]! @ store previous LR as LR
+
+- str r0, [sp, #8] @ write r0 as OLD_R0 over previous LR
++ add lr, sp, #16 @ move in LR the value of SP as it was
++ @ before the push {lr} of the mcount mechanism
+
+- stmdb sp!, {ip, lr}
+- stmdb sp!, {r0-r11, lr}
++ push {r0-r11, ip, lr}
+
+ @ stack content at this point:
+ @ 0 4 48 52 56 60 64 68 72
+- @ R0 | R1 | ... | LR | SP + 4 | previous LR | LR | PSR | OLD_R0 |
++ @ R0 | R1 | ... | IP | SP + 4 | previous LR | LR | PSR | OLD_R0 |
+
+- mov r3, sp @ struct pt_regs*
++ mov r3, sp @ struct pt_regs*
+
+ ldr r2, =function_trace_op
+ ldr r2, [r2] @ pointer to the current
+@@ -112,11 +108,9 @@ ftrace_graph_regs_call:
+ #endif
+
+ @ pop saved regs
+- ldmia sp!, {r0-r12} @ restore r0 through r12
+- ldr ip, [sp, #8] @ restore PC
+- ldr lr, [sp, #4] @ restore LR
+- ldr sp, [sp, #0] @ restore SP
+- mov pc, ip @ return
++ pop {r0-r11, ip, lr} @ restore r0 through r12
++ ldr lr, [sp], #4 @ restore LR
++ ldr pc, [sp], #12
+ .endm
+
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+@@ -132,11 +126,9 @@ ftrace_graph_regs_call:
+ bl prepare_ftrace_return
+
+ @ pop registers saved in ftrace_regs_caller
+- ldmia sp!, {r0-r12} @ restore r0 through r12
+- ldr ip, [sp, #8] @ restore PC
+- ldr lr, [sp, #4] @ restore LR
+- ldr sp, [sp, #0] @ restore SP
+- mov pc, ip @ return
++ pop {r0-r11, ip, lr} @ restore r0 through r12
++ ldr lr, [sp], #4 @ restore LR
++ ldr pc, [sp], #12
+
+ .endm
+ #endif
+@@ -202,16 +194,17 @@ ftrace_graph_call\suffix:
+ .endm
+
+ .macro mcount_exit
+- ldmia sp!, {r0-r3, ip, lr}
+- ret ip
++ ldmia sp!, {r0-r3}
++ ldr lr, [sp, #4]
++ ldr pc, [sp], #8
+ .endm
+
+ ENTRY(__gnu_mcount_nc)
+ UNWIND(.fnstart)
+ #ifdef CONFIG_DYNAMIC_FTRACE
+- mov ip, lr
+- ldmia sp!, {lr}
+- ret ip
++ push {lr}
++ ldr lr, [sp, #4]
++ ldr pc, [sp], #8
+ #else
+ __mcount
+ #endif
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0fc814bbc34b1..8796a69c78e00 100644
--- a/arch/arm/kernel/head-nommu.S
@@ -3437,21 +5401,48 @@ index 0000000000000..0dcefc36fb7a0
+ return sprintf(buf, "Mitigation: %s\n", method);
+}
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
-index 76ea4178a55cb..db798eac74315 100644
+index 76ea4178a55cb..8247749998259 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
-@@ -54,8 +54,7 @@ int notrace unwind_frame(struct stackframe *frame)
+@@ -53,18 +53,17 @@ int notrace unwind_frame(struct stackframe *frame)
+ return -EINVAL;
frame->sp = frame->fp;
- frame->fp = *(unsigned long *)(fp);
+- frame->fp = *(unsigned long *)(fp);
- frame->pc = frame->lr;
- frame->lr = *(unsigned long *)(fp + 4);
-+ frame->pc = *(unsigned long *)(fp + 4);
++ frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
++ frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4));
#else
/* check current frame pointer is within bounds */
if (fp < low + 12 || fp > high - 4)
+ return -EINVAL;
+
+ /* restore the registers from the stack frame */
+- frame->fp = *(unsigned long *)(fp - 12);
+- frame->sp = *(unsigned long *)(fp - 8);
+- frame->pc = *(unsigned long *)(fp - 4);
++ frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12));
++ frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8));
++ frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4));
+ #endif
+
+ return 0;
+diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
+index 6166ba38bf994..b74bfcf94fb1a 100644
+--- a/arch/arm/kernel/swp_emulate.c
++++ b/arch/arm/kernel/swp_emulate.c
+@@ -195,7 +195,7 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
+ destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
+
+ /* Check access in reasonable access range for both SWP and SWPB */
+- if (!access_ok((address & ~3), 4)) {
++ if (!access_ok((void __user *)(address & ~3), 4)) {
+ pr_debug("SWP{B} emulation: access to %p not allowed!\n",
+ (void *)address);
+ res = -EFAULT;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
-index 195dff58bafc7..655c4fe0b4d08 100644
+index 195dff58bafc7..54abd8720ddef 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
@@ -3462,6 +5453,15 @@ index 195dff58bafc7..655c4fe0b4d08 100644
#include <asm/unistd.h>
#include <asm/traps.h>
#include <asm/ptrace.h>
+@@ -574,7 +575,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
+ if (end < start || flags)
+ return -EINVAL;
+
+- if (!access_ok(start, end - start))
++ if (!access_ok((void __user *)start, end - start))
+ return -EFAULT;
+
+ return __do_cache_op(start, end);
@@ -787,10 +788,59 @@ static inline void __init kuser_init(void *vectors)
}
#endif
@@ -3549,6 +5549,227 @@ index 195dff58bafc7..655c4fe0b4d08 100644
-#endif
}
+#endif
+diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
+index 428012687a802..7f7f6bae21c2d 100644
+--- a/arch/arm/mach-davinci/board-da850-evm.c
++++ b/arch/arm/mach-davinci/board-da850-evm.c
+@@ -1101,11 +1101,13 @@ static int __init da850_evm_config_emac(void)
+ int ret;
+ u32 val;
+ struct davinci_soc_info *soc_info = &davinci_soc_info;
+- u8 rmii_en = soc_info->emac_pdata->rmii_en;
++ u8 rmii_en;
+
+ if (!machine_is_davinci_da850_evm())
+ return 0;
+
++ rmii_en = soc_info->emac_pdata->rmii_en;
++
+ cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+
+ val = __raw_readl(cfg_chip3_base);
+diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
+index 5a48abac6af49..4b554cc8fa58a 100644
+--- a/arch/arm/mach-exynos/Kconfig
++++ b/arch/arm/mach-exynos/Kconfig
+@@ -18,7 +18,6 @@ menuconfig ARCH_EXYNOS
+ select EXYNOS_PMU
+ select EXYNOS_SROM
+ select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
+- select GPIOLIB
+ select HAVE_ARM_ARCH_TIMER if ARCH_EXYNOS5
+ select HAVE_ARM_SCU if SMP
+ select HAVE_S3C2410_I2C if I2C
+diff --git a/arch/arm/mach-iop32x/include/mach/entry-macro.S b/arch/arm/mach-iop32x/include/mach/entry-macro.S
+index 8e6766d4621eb..341e5d9a6616d 100644
+--- a/arch/arm/mach-iop32x/include/mach/entry-macro.S
++++ b/arch/arm/mach-iop32x/include/mach/entry-macro.S
+@@ -20,7 +20,7 @@
+ mrc p6, 0, \irqstat, c8, c0, 0 @ Read IINTSRC
+ cmp \irqstat, #0
+ clzne \irqnr, \irqstat
+- rsbne \irqnr, \irqnr, #31
++ rsbne \irqnr, \irqnr, #32
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+diff --git a/arch/arm/mach-iop32x/include/mach/irqs.h b/arch/arm/mach-iop32x/include/mach/irqs.h
+index c4e78df428e86..e09ae5f48aec5 100644
+--- a/arch/arm/mach-iop32x/include/mach/irqs.h
++++ b/arch/arm/mach-iop32x/include/mach/irqs.h
+@@ -9,6 +9,6 @@
+ #ifndef __IRQS_H
+ #define __IRQS_H
+
+-#define NR_IRQS 32
++#define NR_IRQS 33
+
+ #endif
+diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
+index 2d48bf1398c10..d1e8824cbd824 100644
+--- a/arch/arm/mach-iop32x/irq.c
++++ b/arch/arm/mach-iop32x/irq.c
+@@ -32,14 +32,14 @@ static void intstr_write(u32 val)
+ static void
+ iop32x_irq_mask(struct irq_data *d)
+ {
+- iop32x_mask &= ~(1 << d->irq);
++ iop32x_mask &= ~(1 << (d->irq - 1));
+ intctl_write(iop32x_mask);
+ }
+
+ static void
+ iop32x_irq_unmask(struct irq_data *d)
+ {
+- iop32x_mask |= 1 << d->irq;
++ iop32x_mask |= 1 << (d->irq - 1);
+ intctl_write(iop32x_mask);
+ }
+
+@@ -65,7 +65,7 @@ void __init iop32x_init_irq(void)
+ machine_is_em7210())
+ *IOP3XX_PCIIRSR = 0x0f;
+
+- for (i = 0; i < NR_IRQS; i++) {
++ for (i = 1; i < NR_IRQS; i++) {
+ irq_set_chip_and_handler(i, &ext_chip, handle_level_irq);
+ irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
+ }
+diff --git a/arch/arm/mach-iop32x/irqs.h b/arch/arm/mach-iop32x/irqs.h
+index 69858e4e905d1..e1dfc8b4e7d7e 100644
+--- a/arch/arm/mach-iop32x/irqs.h
++++ b/arch/arm/mach-iop32x/irqs.h
+@@ -7,36 +7,40 @@
+ #ifndef __IOP32X_IRQS_H
+ #define __IOP32X_IRQS_H
+
++/* Interrupts in Linux start at 1, hardware starts at 0 */
++
++#define IOP_IRQ(x) ((x) + 1)
++
+ /*
+ * IOP80321 chipset interrupts
+ */
+-#define IRQ_IOP32X_DMA0_EOT 0
+-#define IRQ_IOP32X_DMA0_EOC 1
+-#define IRQ_IOP32X_DMA1_EOT 2
+-#define IRQ_IOP32X_DMA1_EOC 3
+-#define IRQ_IOP32X_AA_EOT 6
+-#define IRQ_IOP32X_AA_EOC 7
+-#define IRQ_IOP32X_CORE_PMON 8
+-#define IRQ_IOP32X_TIMER0 9
+-#define IRQ_IOP32X_TIMER1 10
+-#define IRQ_IOP32X_I2C_0 11
+-#define IRQ_IOP32X_I2C_1 12
+-#define IRQ_IOP32X_MESSAGING 13
+-#define IRQ_IOP32X_ATU_BIST 14
+-#define IRQ_IOP32X_PERFMON 15
+-#define IRQ_IOP32X_CORE_PMU 16
+-#define IRQ_IOP32X_BIU_ERR 17
+-#define IRQ_IOP32X_ATU_ERR 18
+-#define IRQ_IOP32X_MCU_ERR 19
+-#define IRQ_IOP32X_DMA0_ERR 20
+-#define IRQ_IOP32X_DMA1_ERR 21
+-#define IRQ_IOP32X_AA_ERR 23
+-#define IRQ_IOP32X_MSG_ERR 24
+-#define IRQ_IOP32X_SSP 25
+-#define IRQ_IOP32X_XINT0 27
+-#define IRQ_IOP32X_XINT1 28
+-#define IRQ_IOP32X_XINT2 29
+-#define IRQ_IOP32X_XINT3 30
+-#define IRQ_IOP32X_HPI 31
++#define IRQ_IOP32X_DMA0_EOT IOP_IRQ(0)
++#define IRQ_IOP32X_DMA0_EOC IOP_IRQ(1)
++#define IRQ_IOP32X_DMA1_EOT IOP_IRQ(2)
++#define IRQ_IOP32X_DMA1_EOC IOP_IRQ(3)
++#define IRQ_IOP32X_AA_EOT IOP_IRQ(6)
++#define IRQ_IOP32X_AA_EOC IOP_IRQ(7)
++#define IRQ_IOP32X_CORE_PMON IOP_IRQ(8)
++#define IRQ_IOP32X_TIMER0 IOP_IRQ(9)
++#define IRQ_IOP32X_TIMER1 IOP_IRQ(10)
++#define IRQ_IOP32X_I2C_0 IOP_IRQ(11)
++#define IRQ_IOP32X_I2C_1 IOP_IRQ(12)
++#define IRQ_IOP32X_MESSAGING IOP_IRQ(13)
++#define IRQ_IOP32X_ATU_BIST IOP_IRQ(14)
++#define IRQ_IOP32X_PERFMON IOP_IRQ(15)
++#define IRQ_IOP32X_CORE_PMU IOP_IRQ(16)
++#define IRQ_IOP32X_BIU_ERR IOP_IRQ(17)
++#define IRQ_IOP32X_ATU_ERR IOP_IRQ(18)
++#define IRQ_IOP32X_MCU_ERR IOP_IRQ(19)
++#define IRQ_IOP32X_DMA0_ERR IOP_IRQ(20)
++#define IRQ_IOP32X_DMA1_ERR IOP_IRQ(21)
++#define IRQ_IOP32X_AA_ERR IOP_IRQ(23)
++#define IRQ_IOP32X_MSG_ERR IOP_IRQ(24)
++#define IRQ_IOP32X_SSP IOP_IRQ(25)
++#define IRQ_IOP32X_XINT0 IOP_IRQ(27)
++#define IRQ_IOP32X_XINT1 IOP_IRQ(28)
++#define IRQ_IOP32X_XINT2 IOP_IRQ(29)
++#define IRQ_IOP32X_XINT3 IOP_IRQ(30)
++#define IRQ_IOP32X_HPI IOP_IRQ(31)
+
+ #endif
+diff --git a/arch/arm/mach-mmp/sram.c b/arch/arm/mach-mmp/sram.c
+index 6794e2db1ad5f..ecc46c31004f6 100644
+--- a/arch/arm/mach-mmp/sram.c
++++ b/arch/arm/mach-mmp/sram.c
+@@ -72,6 +72,8 @@ static int sram_probe(struct platform_device *pdev)
+ if (!info)
+ return -ENOMEM;
+
++ platform_set_drvdata(pdev, info);
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no memory resource defined\n");
+@@ -107,8 +109,6 @@ static int sram_probe(struct platform_device *pdev)
+ list_add(&info->node, &sram_bank_list);
+ mutex_unlock(&sram_lock);
+
+- platform_set_drvdata(pdev, info);
+-
+ dev_info(&pdev->dev, "initialized\n");
+ return 0;
+
+@@ -127,17 +127,19 @@ static int sram_remove(struct platform_device *pdev)
+ struct sram_bank_info *info;
+
+ info = platform_get_drvdata(pdev);
+- if (info == NULL)
+- return -ENODEV;
+
+- mutex_lock(&sram_lock);
+- list_del(&info->node);
+- mutex_unlock(&sram_lock);
++ if (info->sram_size) {
++ mutex_lock(&sram_lock);
++ list_del(&info->node);
++ mutex_unlock(&sram_lock);
++
++ gen_pool_destroy(info->gpool);
++ iounmap(info->sram_virt);
++ kfree(info->pool_name);
++ }
+
+- gen_pool_destroy(info->gpool);
+- iounmap(info->sram_virt);
+- kfree(info->pool_name);
+ kfree(info);
++
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-mstar/Kconfig b/arch/arm/mach-mstar/Kconfig
+index cd300eeedc206..0bf4d312bcfd9 100644
+--- a/arch/arm/mach-mstar/Kconfig
++++ b/arch/arm/mach-mstar/Kconfig
+@@ -3,6 +3,7 @@ menuconfig ARCH_MSTARV7
+ depends on ARCH_MULTI_V7
+ select ARM_GIC
+ select ARM_HEAVY_MB
++ select HAVE_ARM_ARCH_TIMER
+ select MST_IRQ
+ select MSTAR_MSC313_MPLL
+ help
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 6daaa645ae5d9..21413a9b7b6c6 100644
--- a/arch/arm/mach-omap2/display.c
@@ -3564,6 +5785,23 @@ index 6daaa645ae5d9..21413a9b7b6c6 100644
return r;
}
+diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
+index 5c3845730dbf5..0b80f8bcd3047 100644
+--- a/arch/arm/mach-omap2/omap4-common.c
++++ b/arch/arm/mach-omap2/omap4-common.c
+@@ -314,10 +314,12 @@ void __init omap_gic_of_init(void)
+
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
+ gic_dist_base_addr = of_iomap(np, 0);
++ of_node_put(np);
+ WARN_ON(!gic_dist_base_addr);
+
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer");
+ twd_base = of_iomap(np, 0);
++ of_node_put(np);
+ WARN_ON(!twd_base);
+
+ skip_errata_init:
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 0c2936c7a3799..a5e9cffcac10c 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
@@ -3614,6 +5852,33 @@ index 3edc5f614eefc..c1c2f041ad3b1 100644
if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
continue;
+diff --git a/arch/arm/mach-s3c/mach-jive.c b/arch/arm/mach-s3c/mach-jive.c
+index 0785638a9069b..7d15b84ae217e 100644
+--- a/arch/arm/mach-s3c/mach-jive.c
++++ b/arch/arm/mach-s3c/mach-jive.c
+@@ -236,11 +236,11 @@ static int __init jive_mtdset(char *options)
+ unsigned long set;
+
+ if (options == NULL || options[0] == '\0')
+- return 0;
++ return 1;
+
+ if (kstrtoul(options, 10, &set)) {
+ printk(KERN_ERR "failed to parse mtdset=%s\n", options);
+- return 0;
++ return 1;
+ }
+
+ switch (set) {
+@@ -255,7 +255,7 @@ static int __init jive_mtdset(char *options)
+ "using default.", set);
+ }
+
+- return 0;
++ return 1;
+ }
+
+ /* parse the mtdset= option given to the kernel command line */
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
index ee949255ced3f..09ef73b99dd86 100644
--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -3707,6 +5972,19 @@ index fbb80b883e5dd..201191cf68f32 100644
writel(__pa_symbol(secondary_startup),
sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff));
+diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
+index 1da11bdb1dfbd..1c6500c4e6a17 100644
+--- a/arch/arm/mach-vexpress/spc.c
++++ b/arch/arm/mach-vexpress/spc.c
+@@ -580,7 +580,7 @@ static int __init ve_spc_clk_init(void)
+ }
+
+ cluster = topology_physical_package_id(cpu_dev->id);
+- if (init_opp_table[cluster])
++ if (cluster < 0 || init_opp_table[cluster])
+ continue;
+
+ if (ve_init_opp_table(cpu_dev))
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 8355c38958942..f43cdc1cfbaed 100644
--- a/arch/arm/mm/Kconfig
@@ -3745,6 +6023,22 @@ index 8355c38958942..f43cdc1cfbaed 100644
config TLS_REG_EMUL
bool
select NEED_KUSER_HELPERS
+diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
+index 80fb5a4a5c050..2660bdfcad4d0 100644
+--- a/arch/arm/mm/ioremap.c
++++ b/arch/arm/mm/ioremap.c
+@@ -479,3 +479,11 @@ void __init early_ioremap_init(void)
+ {
+ early_ioremap_setup();
+ }
++
++bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
++ unsigned long flags)
++{
++ unsigned long pfn = PHYS_PFN(offset);
++
++ return memblock_is_map_memory(pfn);
++}
diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c
index 9c348042a7244..4b1619584b23c 100644
--- a/arch/arm/mm/kasan_init.c
@@ -3790,7 +6084,7 @@ index a4e0060051070..5e2be37a198e2 100644
if (pgprot_val(prot))
diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
-index 114c05ab4dd91..06dbfb968182d 100644
+index 114c05ab4dd91..fb9f3eb6bf483 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -6,8 +6,35 @@
@@ -4056,7 +6350,7 @@ index 114c05ab4dd91..06dbfb968182d 100644
static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned,
u32 mask, const char *msg)
{
-@@ -142,16 +281,17 @@ static bool check_spectre_auxcr(bool *warned, u32 bit)
+@@ -142,16 +281,18 @@ static bool check_spectre_auxcr(bool *warned, u32 bit)
void cpu_v7_ca8_ibe(void)
{
if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6)))
@@ -4069,6 +6363,7 @@ index 114c05ab4dd91..06dbfb968182d 100644
if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0)))
- cpu_v7_spectre_init();
+ cpu_v7_spectre_v2_init();
++ cpu_v7_spectre_bhb_init();
}
void cpu_v7_bugs_init(void)
@@ -4090,10 +6385,28 @@ index 14db56f49f0a3..6159010dac4a6 100644
obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
test-kprobes-objs := test-core.o
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index fee914c716aa2..b68d5cbbeca6a 100644
+index fee914c716aa2..8b6f090e0364c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
-@@ -1184,6 +1184,15 @@ config UNMAP_KERNEL_AT_EL0
+@@ -154,7 +154,6 @@ config ARM64
+ select HAVE_ARCH_KGDB
+ select HAVE_ARCH_MMAP_RND_BITS
+ select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
+- select HAVE_ARCH_PFN_VALID
+ select HAVE_ARCH_PREL32_RELOCATIONS
+ select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+ select HAVE_ARCH_SECCOMP_FILTER
+@@ -1053,9 +1052,6 @@ config HW_PERF_EVENTS
+ def_bool y
+ depends on ARM_PMU
+
+-config ARCH_HAS_FILTER_PGPROT
+- def_bool y
+-
+ # Supported by clang >= 7.0
+ config CC_HAVE_SHADOW_CALL_STACK
+ def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)
+@@ -1184,6 +1180,15 @@ config UNMAP_KERNEL_AT_EL0
If unsure, say Y.
@@ -4109,7 +6422,7 @@ index fee914c716aa2..b68d5cbbeca6a 100644
config RODATA_FULL_DEFAULT_ENABLED
bool "Apply r/o permissions of VM areas also to their linear aliases"
default y
-@@ -1264,7 +1273,8 @@ config KUSER_HELPERS
+@@ -1264,7 +1269,8 @@ config KUSER_HELPERS
config COMPAT_VDSO
bool "Enable vDSO for 32-bit applications"
@@ -4211,6 +6524,19 @@ index 8c6e8536b69fa..0baf0f8e4d272 100644
compatible = "allwinner,sun50i-h6-operating-points";
nvmem-cells = <&cpu_speed_grade>;
opp-shared;
+diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+index d301ac0d406bf..3ec301bd08a91 100644
+--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
++++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+@@ -594,7 +594,7 @@
+ };
+
+ qspi: spi@ff8d2000 {
+- compatible = "cdns,qspi-nor";
++ compatible = "intel,socfpga-qspi", "cdns,qspi-nor";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xff8d2000 0x100>,
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index 00c6f53290d43..a3a1ea0f21340 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -4291,6 +6617,64 @@ index 579f3d02d613e..b4e86196e3468 100644
pwms = <&pwm_AO_cd 1 1250 0>;
pwm-dutycycle-range = <100 0>;
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
+index d61f43052a344..8e9ad1e51d665 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
+@@ -11,26 +11,6 @@
+ compatible = "operating-points-v2";
+ opp-shared;
+
+- opp-100000000 {
+- opp-hz = /bits/ 64 <100000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-250000000 {
+- opp-hz = /bits/ 64 <250000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-500000000 {
+- opp-hz = /bits/ 64 <500000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-667000000 {
+- opp-hz = /bits/ 64 <667000000>;
+- opp-microvolt = <731000>;
+- };
+-
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <761000>;
+@@ -71,26 +51,6 @@
+ compatible = "operating-points-v2";
+ opp-shared;
+
+- opp-100000000 {
+- opp-hz = /bits/ 64 <100000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-250000000 {
+- opp-hz = /bits/ 64 <250000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-500000000 {
+- opp-hz = /bits/ 64 <500000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-667000000 {
+- opp-hz = /bits/ 64 <667000000>;
+- opp-microvolt = <731000>;
+- };
+-
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
index f42cf4b8af2d4..16dd409051b40 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
@@ -4362,6 +6746,64 @@ index 344573e157a7b..d33e54b5e1969 100644
#address-cells = <1>;
#size-cells = <1>;
compatible = "mxicy,mx25u6435f", "jedec,spi-nor";
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
+index 1e5d0ee5d541b..44c23c984034c 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
+@@ -11,26 +11,6 @@
+ compatible = "operating-points-v2";
+ opp-shared;
+
+- opp-100000000 {
+- opp-hz = /bits/ 64 <100000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-250000000 {
+- opp-hz = /bits/ 64 <250000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-500000000 {
+- opp-hz = /bits/ 64 <500000000>;
+- opp-microvolt = <731000>;
+- };
+-
+- opp-667000000 {
+- opp-hz = /bits/ 64 <667000000>;
+- opp-microvolt = <731000>;
+- };
+-
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+@@ -76,26 +56,6 @@
+ compatible = "operating-points-v2";
+ opp-shared;
+
+- opp-100000000 {
+- opp-hz = /bits/ 64 <100000000>;
+- opp-microvolt = <751000>;
+- };
+-
+- opp-250000000 {
+- opp-hz = /bits/ 64 <250000000>;
+- opp-microvolt = <751000>;
+- };
+-
+- opp-500000000 {
+- opp-hz = /bits/ 64 <500000000>;
+- opp-microvolt = <751000>;
+- };
+-
+- opp-667000000 {
+- opp-hz = /bits/ 64 <667000000>;
+- opp-microvolt = <751000>;
+- };
+-
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi
index feb0885047400..b40d2c1002c92 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi
@@ -4430,7 +6872,7 @@ index a350fee1264d7..a4d34398da358 100644
&hdmi_tx_tmds_port {
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts
-index effaa138b5f98..5751c48620edf 100644
+index effaa138b5f98..cadba194b149b 100644
--- a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts
@@ -123,7 +123,7 @@
@@ -4451,6 +6893,14 @@ index effaa138b5f98..5751c48620edf 100644
pwms = <&pwm_AO_cd 1 1250 0>;
pwm-dutycycle-range = <100 0>;
+@@ -437,6 +437,7 @@
+ "",
+ "eMMC_RST#", /* BOOT_12 */
+ "eMMC_DS", /* BOOT_13 */
++ "", "",
+ /* GPIOC */
+ "SD_D0_B", /* GPIOC_0 */
+ "SD_D1_B", /* GPIOC_1 */
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts
index f2c0981435944..9c0b544e22098 100644
--- a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts
@@ -4525,6 +6975,37 @@ index 2194a778973f1..a5d79f2f7c196 100644
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
+index 3d8b1f4f2001b..78bdbd2ccc9de 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
+@@ -95,26 +95,6 @@
+ compatible = "operating-points-v2";
+ opp-shared;
+
+- opp-100000000 {
+- opp-hz = /bits/ 64 <100000000>;
+- opp-microvolt = <730000>;
+- };
+-
+- opp-250000000 {
+- opp-hz = /bits/ 64 <250000000>;
+- opp-microvolt = <730000>;
+- };
+-
+- opp-500000000 {
+- opp-hz = /bits/ 64 <500000000>;
+- opp-microvolt = <730000>;
+- };
+-
+- opp-667000000 {
+- opp-hz = /bits/ 64 <666666666>;
+- opp-microvolt = <750000>;
+- };
+-
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <770000>;
diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
index 6288e104a0893..a2635b14da309 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -4540,9 +7021,22 @@ index 6288e104a0893..a2635b14da309 100644
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
diff --git a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
-index a5a64d17d9ea6..5118816b1ed76 100644
+index a5a64d17d9ea6..e8907d3fe2d11 100644
--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
+@@ -273,9 +273,9 @@
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0xff800000 0x3000>;
+
+- timer: timer@400 {
+- compatible = "brcm,bcm6328-timer", "syscon";
+- reg = <0x400 0x3c>;
++ twd: timer-mfd@400 {
++ compatible = "brcm,bcm4908-twd", "simple-mfd", "syscon";
++ reg = <0x400 0x4c>;
+ };
+
+ gpio0: gpio-controller@500 {
@@ -292,7 +292,7 @@
reg = <0x640 0x18>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
@@ -4566,11 +7060,50 @@ index a5a64d17d9ea6..5118816b1ed76 100644
- };
+ reboot {
+ compatible = "syscon-reboot";
-+ regmap = <&timer>;
++ regmap = <&twd>;
+ offset = <0x34>;
+ mask = <1>;
};
};
+diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
+index ec19fbf928a14..12a4b1c03390c 100644
+--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
++++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
+@@ -111,8 +111,8 @@
+ compatible = "silabs,si3226x";
+ reg = <0>;
+ spi-max-frequency = <5000000>;
+- spi-cpha = <1>;
+- spi-cpol = <1>;
++ spi-cpha;
++ spi-cpol;
+ pl022,hierarchy = <0>;
+ pl022,interface = <0>;
+ pl022,slave-tx-disable = <0>;
+@@ -135,8 +135,8 @@
+ at25,byte-len = <0x8000>;
+ at25,addr-mode = <2>;
+ at25,page-size = <64>;
+- spi-cpha = <1>;
+- spi-cpol = <1>;
++ spi-cpha;
++ spi-cpol;
+ pl022,hierarchy = <0>;
+ pl022,interface = <0>;
+ pl022,slave-tx-disable = <0>;
+diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
+index 2cfeaf3b0a876..8c218689fef70 100644
+--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
++++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
+@@ -687,7 +687,7 @@
+ };
+ };
+
+- sata: ahci@663f2000 {
++ sata: sata@663f2000 {
+ compatible = "brcm,iproc-ahci", "generic-ahci";
+ reg = <0x663f2000 0x1000>;
+ dma-coherent;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
index 79f155dedb2d0..e662677a6e28f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
@@ -4615,6 +7148,40 @@ index bfd14b64567e4..2f92e62ecafe9 100644
&enetc_port1 {
phy-handle = <&qds_phy1>;
phy-connection-type = "rgmii-id";
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+index 01b01e3204118..35d1939e690b0 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+@@ -536,9 +536,9 @@
+ clock-names = "i2c";
+ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+ QORIQ_CLK_PLL_DIV(1)>;
+- dmas = <&edma0 1 39>,
+- <&edma0 1 38>;
+- dma-names = "tx", "rx";
++ dmas = <&edma0 1 38>,
++ <&edma0 1 39>;
++ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+index 687fea6d8afa4..4e7bd04d97984 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+@@ -499,9 +499,9 @@
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+ QORIQ_CLK_PLL_DIV(2)>;
+- dmas = <&edma0 1 39>,
+- <&edma0 1 38>;
+- dma-names = "tx", "rx";
++ dmas = <&edma0 1 38>,
++ <&edma0 1 39>;
++ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
index 3063851c2fb91..d3f03dcbb8c38 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
@@ -4824,6 +7391,196 @@ index e99e7644ff392..49d7470812eef 100644
reset-gpios = <&gpio4 27 GPIO_ACTIVE_LOW>;
};
};
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
+index 1dc9d187601c5..a0bd540f27d3d 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
+@@ -89,12 +89,12 @@
+ pendown-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+
+ ti,x-min = /bits/ 16 <125>;
+- touchscreen-size-x = /bits/ 16 <4008>;
++ touchscreen-size-x = <4008>;
+ ti,y-min = /bits/ 16 <282>;
+- touchscreen-size-y = /bits/ 16 <3864>;
++ touchscreen-size-y = <3864>;
+ ti,x-plate-ohms = /bits/ 16 <180>;
+- touchscreen-max-pressure = /bits/ 16 <255>;
+- touchscreen-average-samples = /bits/ 16 <10>;
++ touchscreen-max-pressure = <255>;
++ touchscreen-average-samples = <10>;
+ ti,debounce-tol = /bits/ 16 <3>;
+ ti,debounce-rep = /bits/ 16 <1>;
+ ti,settle-delay-usec = /bits/ 16 <150>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+index 8e4a0ce99790b..7ea909a4c1d5e 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+@@ -103,12 +103,14 @@
+
+ &usbotg1 {
+ dr_mode = "otg";
++ over-current-active-low;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+ };
+
+ &usbotg2 {
+ dr_mode = "host";
++ disable-over-current;
+ status = "okay";
+ };
+
+@@ -166,7 +168,7 @@
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6
+- MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
++ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6
+ >;
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
+index b7c91bdc21dd9..806ee21651d1f 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
+@@ -139,12 +139,14 @@
+
+ &usbotg1 {
+ dr_mode = "otg";
++ over-current-active-low;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+ };
+
+ &usbotg2 {
+ dr_mode = "host";
++ disable-over-current;
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ status = "okay";
+ };
+@@ -231,7 +233,7 @@
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6
+- MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
++ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6
+ >;
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
+index d2ffd62a3bd46..942fed2eed643 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
+@@ -166,12 +166,14 @@
+
+ &usbotg1 {
+ dr_mode = "otg";
++ over-current-active-low;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+ };
+
+ &usbotg2 {
+ dr_mode = "host";
++ disable-over-current;
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ status = "okay";
+ };
+@@ -280,7 +282,7 @@
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6
+- MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
++ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6
+ >;
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
+index 7dfee715a2c4d..d8ce217c60166 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
+@@ -59,6 +59,10 @@
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ rohm,reset-snvs-powered;
+
++ #clock-cells = <0>;
++ clocks = <&osc_32k 0>;
++ clock-output-names = "clk-32k-out";
++
+ regulators {
+ buck1_reg: BUCK1 {
+ regulator-name = "buck1";
+diff --git a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
+index b16c7caf34c11..87b5e23c766f7 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
+@@ -70,12 +70,12 @@
+ pendown-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+
+ ti,x-min = /bits/ 16 <125>;
+- touchscreen-size-x = /bits/ 16 <4008>;
++ touchscreen-size-x = <4008>;
+ ti,y-min = /bits/ 16 <282>;
+- touchscreen-size-y = /bits/ 16 <3864>;
++ touchscreen-size-y = <3864>;
+ ti,x-plate-ohms = /bits/ 16 <180>;
+- touchscreen-max-pressure = /bits/ 16 <255>;
+- touchscreen-average-samples = /bits/ 16 <10>;
++ touchscreen-max-pressure = <255>;
++ touchscreen-average-samples = <10>;
+ ti,debounce-tol = /bits/ 16 <3>;
+ ti,debounce-rep = /bits/ 16 <1>;
+ ti,settle-delay-usec = /bits/ 16 <150>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+index da6c942fb7f9d..6d6cbd4c83b8f 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+@@ -263,7 +263,7 @@
+ ranges;
+
+ sai2: sai@30020000 {
+- compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
++ compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
+ reg = <0x30020000 0x10000>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SAI2_IPG>,
+@@ -277,7 +277,7 @@
+ };
+
+ sai3: sai@30030000 {
+- compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
++ compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
+ reg = <0x30030000 0x10000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SAI3_IPG>,
+@@ -291,7 +291,7 @@
+ };
+
+ sai5: sai@30050000 {
+- compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
++ compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
+ reg = <0x30050000 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SAI5_IPG>,
+@@ -307,7 +307,7 @@
+ };
+
+ sai6: sai@30060000 {
+- compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
++ compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
+ reg = <0x30060000 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SAI6_IPG>,
+@@ -364,7 +364,7 @@
+ };
+
+ sai7: sai@300b0000 {
+- compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
++ compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
+ reg = <0x300b0000 0x10000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MN_CLK_SAI7_IPG>,
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 4066b16126552..fd38092bb247e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -4863,6 +7620,19 @@ index 4066b16126552..fd38092bb247e 100644
csi2_mipi_ep: endpoint {
remote-endpoint = <&csi2_ep>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+index aebbe2b84aa13..a143f38bc78bd 100644
+--- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+@@ -155,7 +155,7 @@
+ };
+
+ clk: clock-controller {
+- compatible = "fsl,imx8qxp-clk", "fsl,scu-clk";
++ compatible = "fsl,imx8qm-clk", "fsl,scu-clk";
+ #clock-cells = <2>;
+ };
+
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index 2d5c1a348716a..6eabec2602e23 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -4898,6 +7668,83 @@ index dde9371dc5451..e4860b8a638ec 100644
reg = <0x0 0xf8005000 0x0 0x1000>;
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ao_ctrl HI6220_WDT0_PCLK>,
+diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+index 163f33b46e4f7..f4270cf189962 100644
+--- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
++++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+@@ -502,7 +502,7 @@
+ };
+
+ usb0: usb@ffb00000 {
+- compatible = "snps,dwc2";
++ compatible = "intel,socfpga-agilex-hsotg", "snps,dwc2";
+ reg = <0xffb00000 0x40000>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usbphy0>;
+@@ -515,7 +515,7 @@
+ };
+
+ usb1: usb@ffb40000 {
+- compatible = "snps,dwc2";
++ compatible = "intel,socfpga-agilex-hsotg", "snps,dwc2";
+ reg = <0xffb40000 0x40000>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usbphy0>;
+@@ -628,7 +628,7 @@
+ };
+
+ qspi: spi@ff8d2000 {
+- compatible = "cdns,qspi-nor";
++ compatible = "intel,socfpga-qspi", "cdns,qspi-nor";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xff8d2000 0x100>,
+diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+index 04da07ae44208..1cee26479bfec 100644
+--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+@@ -18,6 +18,7 @@
+
+ aliases {
+ spi0 = &spi0;
++ ethernet0 = &eth0;
+ ethernet1 = &eth1;
+ mmc0 = &sdhci0;
+ mmc1 = &sdhci1;
+@@ -138,7 +139,9 @@
+ /*
+ * U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
+ * contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
+- * 2 size cells and also expects that the second range starts at 16 MB offset. If these
++ * 2 size cells and also expects that the second range starts at 16 MB offset. Also it
++ * expects that first range uses same address for PCI (child) and CPU (parent) cells (so
++ * no remapping) and that this address is the lowest from all specified ranges. If these
+ * conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address
+ * space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window
+ * for IO and the rest 112 MB (64+32+16) for MEM, despite that maximal IO size is just 64 kB.
+@@ -147,6 +150,9 @@
+ * https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7
+ * https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf
+ * https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33
++ * Bug related to requirement of same child and parent addresses for first range is fixed
++ * in U-Boot version 2022.04 by following commit:
++ * https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17
+ */
+ #address-cells = <3>;
+ #size-cells = <2>;
+diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+index 9acc5d2b5a002..0adc194e46d15 100644
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -497,7 +497,7 @@
+ * (totaling 127 MiB) for MEM.
+ */
+ ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x07f00000 /* Port 0 MEM */
+- 0x81000000 0 0xefff0000 0 0xefff0000 0 0x00010000>; /* Port 0 IO */
++ 0x81000000 0 0x00000000 0 0xefff0000 0 0x00010000>; /* Port 0 IO */
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc 0>,
+ <0 0 0 2 &pcie_intc 1>,
diff --git a/arch/arm64/boot/dts/marvell/cn9130.dtsi b/arch/arm64/boot/dts/marvell/cn9130.dtsi
index a2b7e5ec979d3..327b04134134f 100644
--- a/arch/arm64/boot/dts/marvell/cn9130.dtsi
@@ -5227,7 +8074,7 @@ index a246dbd74cc11..b7b5264888b7c 100644
&gpio_keys {
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
-index c8921e2d6480f..495c15deacb7d 100644
+index c8921e2d6480f..de86ae3a7fd27 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -137,8 +137,8 @@
@@ -5318,7 +8165,16 @@ index c8921e2d6480f..495c15deacb7d 100644
next-level-cache = <&L2_700>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
-@@ -3616,7 +3616,7 @@
+@@ -1460,6 +1460,8 @@
+ "imem",
+ "config";
+
++ qcom,qmp = <&aoss_qmp>;
++
+ qcom,smem-states = <&ipa_smp2p_out 0>,
+ <&ipa_smp2p_out 1>;
+ qcom,smem-state-names = "ipa-clock-enabled-valid",
+@@ -3616,7 +3618,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
@@ -5327,7 +8183,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu0_alert0: trip-point0 {
-@@ -3665,7 +3665,7 @@
+@@ -3665,7 +3667,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
@@ -5336,7 +8192,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu1_alert0: trip-point0 {
-@@ -3714,7 +3714,7 @@
+@@ -3714,7 +3716,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
@@ -5345,7 +8201,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu2_alert0: trip-point0 {
-@@ -3763,7 +3763,7 @@
+@@ -3763,7 +3765,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
@@ -5354,7 +8210,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu3_alert0: trip-point0 {
-@@ -3812,7 +3812,7 @@
+@@ -3812,7 +3814,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
@@ -5363,7 +8219,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu4_alert0: trip-point0 {
-@@ -3861,7 +3861,7 @@
+@@ -3861,7 +3863,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
@@ -5372,7 +8228,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu5_alert0: trip-point0 {
-@@ -3910,7 +3910,7 @@
+@@ -3910,7 +3912,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
@@ -5381,7 +8237,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu6_alert0: trip-point0 {
-@@ -3951,7 +3951,7 @@
+@@ -3951,7 +3953,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
@@ -5390,7 +8246,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu7_alert0: trip-point0 {
-@@ -3992,7 +3992,7 @@
+@@ -3992,7 +3994,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
@@ -5399,7 +8255,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu8_alert0: trip-point0 {
-@@ -4033,7 +4033,7 @@
+@@ -4033,7 +4035,7 @@
polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
@@ -5409,7 +8265,7 @@ index c8921e2d6480f..495c15deacb7d 100644
trips {
cpu9_alert0: trip-point0 {
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
-index fd78f16181ddd..692973c4f4344 100644
+index fd78f16181ddd..b795a9993cc1b 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -429,7 +429,7 @@
@@ -5421,7 +8277,16 @@ index fd78f16181ddd..692973c4f4344 100644
"ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk",
"ufs_phy_tx_symbol_0_clk",
"usb3_phy_wrapper_gcc_usb30_pipe_clk";
-@@ -1258,15 +1258,11 @@
+@@ -615,6 +615,8 @@
+ interconnect-names = "memory",
+ "config";
+
++ qcom,qmp = <&aoss_qmp>;
++
+ qcom,smem-states = <&ipa_smp2p_out 0>,
+ <&ipa_smp2p_out 1>;
+ qcom,smem-state-names = "ipa-clock-enabled-valid",
+@@ -1258,15 +1260,11 @@
dp_phy: dp-phy@88ea200 {
reg = <0 0x088ea200 0 0x200>,
<0 0x088ea400 0 0x200>,
@@ -5453,7 +8318,7 @@ index 9c7f87e42fccd..a8724fd60645f 100644
reg = <0x00778000 0x7000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
-index b3b9119261844..519ca9a705b4f 100644
+index b3b9119261844..d20eacfc10176 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -2316,11 +2316,11 @@
@@ -5481,6 +8346,21 @@ index b3b9119261844..519ca9a705b4f 100644
clock-names = "iface", "bus", "core";
dmas = <&cryptobam 6>, <&cryptobam 7>;
dma-names = "rx", "tx";
+@@ -3608,10 +3608,10 @@
+ #clock-cells = <0>;
+ clock-frequency = <9600000>;
+ clock-output-names = "mclk";
+- qcom,micbias1-millivolt = <1800>;
+- qcom,micbias2-millivolt = <1800>;
+- qcom,micbias3-millivolt = <1800>;
+- qcom,micbias4-millivolt = <1800>;
++ qcom,micbias1-microvolt = <1800000>;
++ qcom,micbias2-microvolt = <1800000>;
++ qcom,micbias3-microvolt = <1800000>;
++ qcom,micbias4-microvolt = <1800000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
index 2ba23aa582a18..617a634ac9051 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -5553,11 +8433,170 @@ index 2b37ce6a9f9c5..9f476e3d0720b 100644
compatible = "qcom,rpm-msg-ram";
reg = <0x045f0000 0x7000>;
};
+diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
+index ef0232c2cf45b..f347f752d536d 100644
+--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
+@@ -3434,9 +3434,9 @@
+ qcom,tcs-offset = <0xd00>;
+ qcom,drv-id = <2>;
+ qcom,tcs-config = <ACTIVE_TCS 2>,
+- <SLEEP_TCS 1>,
+- <WAKE_TCS 1>,
+- <CONTROL_TCS 0>;
++ <SLEEP_TCS 3>,
++ <WAKE_TCS 3>,
++ <CONTROL_TCS 1>;
+
+ rpmhcc: clock-controller {
+ compatible = "qcom,sm8150-rpmh-clk";
+diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
+index d12e4cbfc8527..2786e2c8e5659 100644
+--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
+@@ -1434,8 +1434,8 @@
+ phys = <&pcie0_lane>;
+ phy-names = "pciephy";
+
+- perst-gpio = <&tlmm 79 GPIO_ACTIVE_LOW>;
+- enable-gpio = <&tlmm 81 GPIO_ACTIVE_HIGH>;
++ perst-gpios = <&tlmm 79 GPIO_ACTIVE_LOW>;
++ wake-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_default_state>;
+@@ -1495,7 +1495,7 @@
+ ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+- interrupts = <GIC_SPI 306 IRQ_TYPE_EDGE_RISING>;
++ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+@@ -1538,8 +1538,8 @@
+ phys = <&pcie1_lane>;
+ phy-names = "pciephy";
+
+- perst-gpio = <&tlmm 82 GPIO_ACTIVE_LOW>;
+- enable-gpio = <&tlmm 84 GPIO_ACTIVE_HIGH>;
++ perst-gpios = <&tlmm 82 GPIO_ACTIVE_LOW>;
++ wake-gpios = <&tlmm 84 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_default_state>;
+@@ -1601,7 +1601,7 @@
+ ranges = <0x01000000 0x0 0x64200000 0x0 0x64200000 0x0 0x100000>,
+ <0x02000000 0x0 0x64300000 0x0 0x64300000 0x0 0x3d00000>;
+
+- interrupts = <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
++ interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+@@ -1644,8 +1644,8 @@
+ phys = <&pcie2_lane>;
+ phy-names = "pciephy";
+
+- perst-gpio = <&tlmm 85 GPIO_ACTIVE_LOW>;
+- enable-gpio = <&tlmm 87 GPIO_ACTIVE_HIGH>;
++ perst-gpios = <&tlmm 85 GPIO_ACTIVE_LOW>;
++ wake-gpios = <&tlmm 87 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_default_state>;
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
-index e91cd8a5e5356..296ffb0e9888c 100644
+index e91cd8a5e5356..9ffb7355850c7 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
-@@ -2185,7 +2185,7 @@
+@@ -35,6 +35,24 @@
+ clock-frequency = <32000>;
+ #clock-cells = <0>;
+ };
++
++ ufs_phy_rx_symbol_0_clk: ufs-phy-rx-symbol-0 {
++ compatible = "fixed-clock";
++ clock-frequency = <1000>;
++ #clock-cells = <0>;
++ };
++
++ ufs_phy_rx_symbol_1_clk: ufs-phy-rx-symbol-1 {
++ compatible = "fixed-clock";
++ clock-frequency = <1000>;
++ #clock-cells = <0>;
++ };
++
++ ufs_phy_tx_symbol_0_clk: ufs-phy-tx-symbol-0 {
++ compatible = "fixed-clock";
++ clock-frequency = <1000>;
++ #clock-cells = <0>;
++ };
+ };
+
+ cpus {
+@@ -443,8 +461,30 @@
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+- clock-names = "bi_tcxo", "sleep_clk";
+- clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>;
++ clock-names = "bi_tcxo",
++ "sleep_clk",
++ "pcie_0_pipe_clk",
++ "pcie_1_pipe_clk",
++ "ufs_card_rx_symbol_0_clk",
++ "ufs_card_rx_symbol_1_clk",
++ "ufs_card_tx_symbol_0_clk",
++ "ufs_phy_rx_symbol_0_clk",
++ "ufs_phy_rx_symbol_1_clk",
++ "ufs_phy_tx_symbol_0_clk",
++ "usb3_phy_wrapper_gcc_usb30_pipe_clk",
++ "usb3_uni_phy_sec_gcc_usb30_pipe_clk";
++ clocks = <&rpmhcc RPMH_CXO_CLK>,
++ <&sleep_clk>,
++ <0>,
++ <0>,
++ <0>,
++ <0>,
++ <0>,
++ <&ufs_phy_rx_symbol_0_clk>,
++ <&ufs_phy_rx_symbol_1_clk>,
++ <&ufs_phy_tx_symbol_0_clk>,
++ <0>,
++ <0>;
+ };
+
+ ipcc: mailbox@408000 {
+@@ -696,6 +736,8 @@
+ interconnect-names = "memory",
+ "config";
+
++ qcom,qmp = <&aoss_qmp>;
++
+ qcom,smem-states = <&ipa_smp2p_out 0>,
+ <&ipa_smp2p_out 1>;
+ qcom,smem-state-names = "ipa-clock-enabled-valid",
+@@ -939,7 +981,7 @@
+ qcom,tcs-offset = <0xd00>;
+ qcom,drv-id = <2>;
+ qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
+- <WAKE_TCS 3>, <CONTROL_TCS 1>;
++ <WAKE_TCS 3>, <CONTROL_TCS 0>;
+
+ rpmhcc: clock-controller {
+ compatible = "qcom,sm8350-rpmh-clk";
+@@ -1060,8 +1102,8 @@
+ <75000000 300000000>,
+ <0 0>,
+ <0 0>,
+- <75000000 300000000>,
+- <75000000 300000000>;
++ <0 0>,
++ <0 0>;
+ status = "disabled";
+ };
+
+@@ -2185,7 +2227,7 @@
};
};
@@ -5878,6 +8917,19 @@ index 631d520cebee5..26899fb768a73 100644
polling-delay-passive = <250>;
polling-delay = <1000>;
thermal-sensors = <&tsc 4>;
+diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi
+index 248ebb61aa790..5200d0bbd9e9c 100644
+--- a/arch/arm64/boot/dts/rockchip/px30.dtsi
++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi
+@@ -711,7 +711,7 @@
+ clock-names = "pclk", "timer";
+ };
+
+- dmac: dmac@ff240000 {
++ dmac: dma-controller@ff240000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xff240000 0x0 0x4000>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
index 665b2e69455dd..ea6820902ede0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
@@ -5892,9 +8944,18 @@ index 665b2e69455dd..ea6820902ede0 100644
vdd_core: vdd-core {
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
-index 8c821acb21ffb..da84be6f4715e 100644
+index 8c821acb21ffb..3cbe83e6fb9a4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+@@ -489,7 +489,7 @@
+ status = "disabled";
+ };
+
+- dmac: dmac@ff1f0000 {
++ dmac: dma-controller@ff1f0000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xff1f0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
@@ -599,7 +599,7 @@
gpu: gpu@ff300000 {
@@ -5904,6 +8965,21 @@ index 8c821acb21ffb..da84be6f4715e 100644
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+index c4dd2a6b48368..f81ce3240342c 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+@@ -770,8 +770,8 @@
+ sd-uhs-sdr104;
+
+ /* Power supply */
+- vqmmc-supply = &vcc1v8_s3; /* IO line */
+- vmmc-supply = &vcc_sdio; /* card's power */
++ vqmmc-supply = <&vcc1v8_s3>; /* IO line */
++ vmmc-supply = <&vcc_sdio>; /* card's power */
+
+ #address-cells = <1>;
+ #size-cells = <0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index c1bcc8ca3769d..2f8e117109699 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -5998,6 +9074,59 @@ index 2b5f001ff4a61..9e5d07f5712e6 100644
&cpu_b0 {
cpu-supply = <&vdd_cpu_b>;
};
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
+index 292bb7e80cf35..3ae5d727e3674 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
+@@ -232,6 +232,7 @@
+
+ &usbdrd_dwc3_0 {
+ dr_mode = "otg";
++ extcon = <&extcon_usb3>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+index fb67db4619ea0..08fa00364b42f 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+@@ -25,6 +25,13 @@
+ };
+ };
+
++ extcon_usb3: extcon-usb3 {
++ compatible = "linux,extcon-usb-gpio";
++ id-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&usb3_id>;
++ };
++
+ clkin_gmac: external-gmac-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+@@ -422,9 +429,22 @@
+ <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
++
++ usb3 {
++ usb3_id: usb3-id {
++ rockchip,pins =
++ <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
+ };
+
+ &sdhci {
++ /*
++ * Signal integrity isn't great at 200MHz but 100MHz has proven stable
++ * enough.
++ */
++ max-frequency = <100000000>;
++
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
index b28888ea9262e..100a769165ef9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
@@ -6011,6 +9140,52 @@ index b28888ea9262e..100a769165ef9 100644
sdmmc-supply = <&vcc_sdio>;
gpio1830-supply = <&vcc_3v0>;
};
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+index 3871c7fd83b00..00f1d036dfe08 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+@@ -1802,10 +1802,10 @@
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_HDMI_CTRL>,
+ <&cru SCLK_HDMI_SFR>,
+- <&cru PLL_VPLL>,
++ <&cru SCLK_HDMI_CEC>,
+ <&cru PCLK_VIO_GRF>,
+- <&cru SCLK_HDMI_CEC>;
+- clock-names = "iahb", "isfr", "vpll", "grf", "cec";
++ <&cru PLL_VPLL>;
++ clock-names = "iahb", "isfr", "cec", "grf", "vpll";
+ power-domains = <&power RK3399_PD_HDCP>;
+ reg-io-width = <4>;
+ rockchip,grf = <&grf>;
+diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+index 42d1d219a3fd2..86291f3469f15 100644
+--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+@@ -59,7 +59,10 @@
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
+- <0x00 0x01840000 0x00 0xC0000>; /* GICR */
++ <0x00 0x01840000 0x00 0xC0000>, /* GICR */
++ <0x01 0x00000000 0x00 0x2000>, /* GICC */
++ <0x01 0x00010000 0x00 0x1000>, /* GICH */
++ <0x01 0x00020000 0x00 0x2000>; /* GICV */
+ /*
+ * vcpumntirq:
+ * virtual CPU interface maintenance interrupt
+diff --git a/arch/arm64/boot/dts/ti/k3-am64.dtsi b/arch/arm64/boot/dts/ti/k3-am64.dtsi
+index de6805b0c72c1..e589c58f60885 100644
+--- a/arch/arm64/boot/dts/ti/k3-am64.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am64.dtsi
+@@ -85,6 +85,7 @@
+ <0x00 0x68000000 0x00 0x68000000 0x00 0x08000000>, /* PCIe DAT0 */
+ <0x00 0x70000000 0x00 0x70000000 0x00 0x00200000>, /* OC SRAM */
+ <0x00 0x78000000 0x00 0x78000000 0x00 0x00800000>, /* Main R5FSS */
++ <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
+ <0x06 0x00000000 0x06 0x00000000 0x01 0x00000000>, /* PCIe DAT1 */
+ <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS0 DAT3 */
+
diff --git a/arch/arm64/boot/dts/ti/k3-am642.dtsi b/arch/arm64/boot/dts/ti/k3-am642.dtsi
index e2b397c884018..8a76f4821b11b 100644
--- a/arch/arm64/boot/dts/ti/k3-am642.dtsi
@@ -6023,8 +9198,36 @@ index e2b397c884018..8a76f4821b11b 100644
+ cache-sets = <256>;
};
};
+diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+index ba4e5d3e1ed7a..82be00069bcd5 100644
+--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+@@ -35,7 +35,10 @@
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
+- <0x00 0x01880000 0x00 0x90000>; /* GICR */
++ <0x00 0x01880000 0x00 0x90000>, /* GICR */
++ <0x00 0x6f000000 0x00 0x2000>, /* GICC */
++ <0x00 0x6f010000 0x00 0x1000>, /* GICH */
++ <0x00 0x6f020000 0x00 0x2000>; /* GICV */
+ /*
+ * vcpumntirq:
+ * virtual CPU interface maintenance interrupt
+diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi
+index a9fc1af03f27f..1607db9b32dd2 100644
+--- a/arch/arm64/boot/dts/ti/k3-am65.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi
+@@ -84,6 +84,7 @@
+ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
+ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
+ <0x00 0x50000000 0x00 0x50000000 0x00 0x8000000>,
++ <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A53 PERIPHBASE */
+ <0x00 0x70000000 0x00 0x70000000 0x00 0x200000>,
+ <0x05 0x00000000 0x05 0x00000000 0x01 0x0000000>,
+ <0x07 0x00000000 0x07 0x00000000 0x01 0x0000000>;
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
-index e8a41d09b45f2..7daa280220442 100644
+index e8a41d09b45f2..000b5732ea0c8 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
@@ -32,7 +32,7 @@
@@ -6036,7 +9239,19 @@ index e8a41d09b45f2..7daa280220442 100644
compatible = "mmio-mux";
#mux-control-cells = <1>;
mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */
-@@ -606,10 +606,10 @@
+@@ -54,7 +54,10 @@
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
+- <0x00 0x01900000 0x00 0x100000>; /* GICR */
++ <0x00 0x01900000 0x00 0x100000>, /* GICR */
++ <0x00 0x6f000000 0x00 0x2000>, /* GICC */
++ <0x00 0x6f010000 0x00 0x1000>, /* GICH */
++ <0x00 0x6f020000 0x00 0x2000>; /* GICV */
+
+ /* vcpumntirq: virtual CPU interface maintenance interrupt */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+@@ -606,10 +609,10 @@
clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
@@ -6051,7 +9266,7 @@ index e8a41d09b45f2..7daa280220442 100644
dma-coherent;
ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>,
diff --git a/arch/arm64/boot/dts/ti/k3-j7200.dtsi b/arch/arm64/boot/dts/ti/k3-j7200.dtsi
-index b7005b8031495..7586b5aea446f 100644
+index b7005b8031495..afe99f3920ccd 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200.dtsi
@@ -60,7 +60,7 @@
@@ -6081,8 +9296,16 @@ index b7005b8031495..7586b5aea446f 100644
next-level-cache = <&msmc_l3>;
};
+@@ -127,6 +127,7 @@
+ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* timesync router */
+ <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */
+ <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */
++ <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A72 PERIPHBASE */
+ <0x00 0x70000000 0x00 0x70000000 0x00 0x00800000>, /* MSMC RAM */
+ <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */
+ <0x41 0x00000000 0x41 0x00000000 0x01 0x00000000>, /* PCIe1 DAT1 */
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
-index cf3482376c1e6..e85c89eebfa31 100644
+index cf3482376c1e6..6c81997ee28ad 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
@@ -42,7 +42,7 @@
@@ -6094,7 +9317,19 @@ index cf3482376c1e6..e85c89eebfa31 100644
compatible = "mmio-mux";
reg = <0x00004080 0x50>;
#mux-control-cells = <1>;
-@@ -610,7 +610,7 @@
+@@ -76,7 +76,10 @@
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
+- <0x00 0x01900000 0x00 0x100000>; /* GICR */
++ <0x00 0x01900000 0x00 0x100000>, /* GICR */
++ <0x00 0x6f000000 0x00 0x2000>, /* GICC */
++ <0x00 0x6f010000 0x00 0x1000>, /* GICH */
++ <0x00 0x6f020000 0x00 0x2000>; /* GICV */
+
+ /* vcpumntirq: virtual CPU interface maintenance interrupt */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+@@ -610,7 +613,7 @@
clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
@@ -6103,7 +9338,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
vendor-id = <0x104c>;
device-id = <0xb00d>;
msi-map = <0x0 &gic_its 0x0 0x10000>;
-@@ -636,7 +636,7 @@
+@@ -636,7 +639,7 @@
clocks = <&k3_clks 239 1>;
clock-names = "fck";
max-functions = /bits/ 8 <6>;
@@ -6112,7 +9347,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
dma-coherent;
};
-@@ -658,7 +658,7 @@
+@@ -658,7 +661,7 @@
clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
@@ -6121,7 +9356,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
vendor-id = <0x104c>;
device-id = <0xb00d>;
msi-map = <0x0 &gic_its 0x10000 0x10000>;
-@@ -684,7 +684,7 @@
+@@ -684,7 +687,7 @@
clocks = <&k3_clks 240 1>;
clock-names = "fck";
max-functions = /bits/ 8 <6>;
@@ -6130,7 +9365,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
dma-coherent;
};
-@@ -706,7 +706,7 @@
+@@ -706,7 +709,7 @@
clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
@@ -6139,7 +9374,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
vendor-id = <0x104c>;
device-id = <0xb00d>;
msi-map = <0x0 &gic_its 0x20000 0x10000>;
-@@ -732,7 +732,7 @@
+@@ -732,7 +735,7 @@
clocks = <&k3_clks 241 1>;
clock-names = "fck";
max-functions = /bits/ 8 <6>;
@@ -6148,7 +9383,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
dma-coherent;
};
-@@ -754,7 +754,7 @@
+@@ -754,7 +757,7 @@
clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
@@ -6157,7 +9392,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
vendor-id = <0x104c>;
device-id = <0xb00d>;
msi-map = <0x0 &gic_its 0x30000 0x10000>;
-@@ -780,7 +780,7 @@
+@@ -780,7 +783,7 @@
clocks = <&k3_clks 242 1>;
clock-names = "fck";
max-functions = /bits/ 8 <6>;
@@ -6167,7 +9402,7 @@ index cf3482376c1e6..e85c89eebfa31 100644
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi
-index f0587fde147e6..69ce048a2136e 100644
+index f0587fde147e6..2cd8883de5b53 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi
@@ -61,7 +61,7 @@
@@ -6197,6 +9432,14 @@ index f0587fde147e6..69ce048a2136e 100644
next-level-cache = <&msmc_l3>;
};
+@@ -136,6 +136,7 @@
+ <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01800000>, /* PCIe Core*/
+ <0x00 0x10000000 0x00 0x10000000 0x00 0x10000000>, /* PCIe DAT */
+ <0x00 0x64800000 0x00 0x64800000 0x00 0x00800000>, /* C71 */
++ <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A72 PERIPHBASE */
+ <0x44 0x00000000 0x44 0x00000000 0x00 0x08000000>, /* PCIe2 DAT */
+ <0x44 0x10000000 0x44 0x10000000 0x00 0x08000000>, /* PCIe3 DAT */
+ <0x4d 0x80800000 0x4d 0x80800000 0x00 0x00800000>, /* C66_0 */
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts
index 4a86efa32d687..f7124e15f0ff6 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts
@@ -6241,6 +9484,19 @@ index 28dccb891a535..8278876ad33fa 100644
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 22 4>;
+diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
+index 545197bc05013..4972a81d40d60 100644
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -921,7 +921,7 @@ CONFIG_DMADEVICES=y
+ CONFIG_DMA_BCM2835=y
+ CONFIG_DMA_SUN6I=m
+ CONFIG_FSL_EDMA=y
+-CONFIG_IMX_SDMA=y
++CONFIG_IMX_SDMA=m
+ CONFIG_K3_DMA=y
+ CONFIG_MV_XOR=y
+ CONFIG_MV_XOR_V2=y
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index bfa58409a4d4d..448a575db8e8e 100644
--- a/arch/arm64/include/asm/assembler.h
@@ -6363,15 +9619,16 @@ index ef6be92b1921a..a77b5f49b3a6c 100644
DECLARE_STATIC_KEY_FALSE(arm64_mismatched_32bit_el0);
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
-index 6231e1f0abe7e..bfbf0c4c7c5e5 100644
+index 6231e1f0abe7e..39f5c1672f480 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
-@@ -73,6 +73,14 @@
+@@ -73,6 +73,15 @@
#define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_CORTEX_A77 0xD0D
+#define ARM_CPU_PART_NEOVERSE_V1 0xD40
+#define ARM_CPU_PART_CORTEX_A78 0xD41
++#define ARM_CPU_PART_CORTEX_A78AE 0xD42
+#define ARM_CPU_PART_CORTEX_X1 0xD44
+#define ARM_CPU_PART_CORTEX_A510 0xD46
+#define ARM_CPU_PART_CORTEX_A710 0xD47
@@ -6381,12 +9638,13 @@ index 6231e1f0abe7e..bfbf0c4c7c5e5 100644
#define APM_CPU_PART_POTENZA 0x000
-@@ -113,6 +121,14 @@
+@@ -113,6 +122,15 @@
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
+#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
+#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
++#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
+#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
+#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
+#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
@@ -6497,6 +9755,19 @@ index 6b776c8667b20..b02f0c328c8e4 100644
AARCH64_INSN_HINT_BTI = 0x20 << 5,
AARCH64_INSN_HINT_BTIC = 0x22 << 5,
+diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
+index 7fd836bea7eb4..3995652daf81a 100644
+--- a/arch/arm64/include/asm/io.h
++++ b/arch/arm64/include/asm/io.h
+@@ -192,4 +192,8 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
+ extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
+ extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
++extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
++ unsigned long flags);
++#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
++
+ #endif /* __ASM_IO_H */
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 327120c0089fe..f67a561e0935e 100644
--- a/arch/arm64/include/asm/kvm_arm.h
@@ -6552,11 +9823,35 @@ index f1745a8434144..05886322c300c 100644
#define MODULES_VSIZE (SZ_128M)
#define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT)))
#define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE)
+diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
+index a11ccadd47d29..094701ec5500b 100644
+--- a/arch/arm64/include/asm/module.lds.h
++++ b/arch/arm64/include/asm/module.lds.h
+@@ -1,8 +1,8 @@
+ SECTIONS {
+ #ifdef CONFIG_ARM64_MODULE_PLTS
+- .plt 0 (NOLOAD) : { BYTE(0) }
+- .init.plt 0 (NOLOAD) : { BYTE(0) }
+- .text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) }
++ .plt 0 : { BYTE(0) }
++ .init.plt 0 : { BYTE(0) }
++ .text.ftrace_trampoline 0 : { BYTE(0) }
+ #endif
+
+ #ifdef CONFIG_KASAN_SW_TAGS
diff --git a/arch/arm64/include/asm/mte-kasan.h b/arch/arm64/include/asm/mte-kasan.h
-index 22420e1f8c037..26e013e540ae2 100644
+index 22420e1f8c037..592aabb25b0e7 100644
--- a/arch/arm64/include/asm/mte-kasan.h
+++ b/arch/arm64/include/asm/mte-kasan.h
-@@ -84,10 +84,12 @@ static inline void __dc_gzva(u64 p)
+@@ -5,6 +5,7 @@
+ #ifndef __ASM_MTE_KASAN_H
+ #define __ASM_MTE_KASAN_H
+
++#include <asm/compiler.h>
+ #include <asm/mte-def.h>
+
+ #ifndef __ASSEMBLY__
+@@ -84,10 +85,12 @@ static inline void __dc_gzva(u64 p)
static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag,
bool init)
{
@@ -6571,7 +9866,7 @@ index 22420e1f8c037..26e013e540ae2 100644
curr = (u64)__tag_set(addr, tag);
mask = dczid_bs - 1;
-@@ -106,7 +108,7 @@ static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag,
+@@ -106,7 +109,7 @@ static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag,
*/
#define SET_MEMTAG_RANGE(stg_post, dc_gva) \
do { \
@@ -6580,6 +9875,18 @@ index 22420e1f8c037..26e013e540ae2 100644
do { \
curr = stg_post(curr); \
} while (curr < end1); \
+diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
+index f98c91bbd7c17..993a27ea6f543 100644
+--- a/arch/arm64/include/asm/page.h
++++ b/arch/arm64/include/asm/page.h
+@@ -41,7 +41,6 @@ void tag_clear_highpage(struct page *to);
+
+ typedef struct page *pgtable_t;
+
+-int pfn_valid(unsigned long pfn);
+ int pfn_is_map_memory(unsigned long pfn);
+
+ #include <asm/memory.h>
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index 8433a2058eb15..237224484d0f6 100644
--- a/arch/arm64/include/asm/pgalloc.h
@@ -6593,8 +9900,30 @@ index 8433a2058eb15..237224484d0f6 100644
__pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN);
}
+diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
+index 7032f04c8ac6e..b1e1b74d993c3 100644
+--- a/arch/arm64/include/asm/pgtable-prot.h
++++ b/arch/arm64/include/asm/pgtable-prot.h
+@@ -92,7 +92,7 @@ extern bool arm64_use_ng_mappings;
+ #define __P001 PAGE_READONLY
+ #define __P010 PAGE_READONLY
+ #define __P011 PAGE_READONLY
+-#define __P100 PAGE_EXECONLY
++#define __P100 PAGE_READONLY_EXEC /* PAGE_EXECONLY if Enhanced PAN */
+ #define __P101 PAGE_READONLY_EXEC
+ #define __P110 PAGE_READONLY_EXEC
+ #define __P111 PAGE_READONLY_EXEC
+@@ -101,7 +101,7 @@ extern bool arm64_use_ng_mappings;
+ #define __S001 PAGE_READONLY
+ #define __S010 PAGE_SHARED
+ #define __S011 PAGE_SHARED
+-#define __S100 PAGE_EXECONLY
++#define __S100 PAGE_READONLY_EXEC /* PAGE_EXECONLY if Enhanced PAN */
+ #define __S101 PAGE_READONLY_EXEC
+ #define __S110 PAGE_SHARED_EXEC
+ #define __S111 PAGE_SHARED_EXEC
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
-index dfa76afa0ccff..72f95c6a70519 100644
+index dfa76afa0ccff..ed57717cd0040 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -67,9 +67,15 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
@@ -6616,6 +9945,43 @@ index dfa76afa0ccff..72f95c6a70519 100644
#else
#define __pte_to_phys(pte) (pte_val(pte) & PTE_ADDR_MASK)
#define __phys_to_pte_val(phys) (phys)
+@@ -529,7 +535,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ PMD_TYPE_TABLE)
+ #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \
+ PMD_TYPE_SECT)
+-#define pmd_leaf(pmd) pmd_sect(pmd)
++#define pmd_leaf(pmd) (pmd_present(pmd) && !pmd_table(pmd))
+ #define pmd_bad(pmd) (!pmd_table(pmd))
+
+ #define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE)
+@@ -619,7 +625,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
+ #define pud_none(pud) (!pud_val(pud))
+ #define pud_bad(pud) (!pud_table(pud))
+ #define pud_present(pud) pte_present(pud_pte(pud))
+-#define pud_leaf(pud) pud_sect(pud)
++#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
+ #define pud_valid(pud) pte_valid(pud_pte(pud))
+
+ static inline void set_pud(pud_t *pudp, pud_t pud)
+@@ -1011,18 +1017,6 @@ static inline bool arch_wants_old_prefaulted_pte(void)
+ }
+ #define arch_wants_old_prefaulted_pte arch_wants_old_prefaulted_pte
+
+-static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
+-{
+- if (cpus_have_const_cap(ARM64_HAS_EPAN))
+- return prot;
+-
+- if (pgprot_val(prot) != pgprot_val(PAGE_EXECONLY))
+- return prot;
+-
+- return PAGE_READONLY_EXEC;
+-}
+-
+-
+ #endif /* !__ASSEMBLY__ */
+
+ #endif /* __ASM_PGTABLE_H */
diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
index 1bce62fa908a3..56f7b1d4d54b9 100644
--- a/arch/arm64/include/asm/rwonce.h
@@ -6653,10 +10019,20 @@ index e4ad9db53af1d..552891e626e53 100644
+
#endif /* __ASM_SECTIONS_H */
diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h
-index f62ca39da6c5a..86e0cc9b9c685 100644
+index f62ca39da6c5a..aa3d3607d5c8d 100644
--- a/arch/arm64/include/asm/spectre.h
+++ b/arch/arm64/include/asm/spectre.h
-@@ -93,5 +93,9 @@ void spectre_v4_enable_task_mitigation(struct task_struct *tsk);
+@@ -67,7 +67,8 @@ struct bp_hardening_data {
+
+ DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
+
+-static inline void arm64_apply_bp_hardening(void)
++/* Called during entry so must be __always_inline */
++static __always_inline void arm64_apply_bp_hardening(void)
+ {
+ struct bp_hardening_data *d;
+
+@@ -93,5 +94,9 @@ void spectre_v4_enable_task_mitigation(struct task_struct *tsk);
enum mitigation_state arm64_get_meltdown_state(void);
@@ -6811,7 +10187,7 @@ index 190b494e22ab9..0fd6056ba412b 100644
} while(0)
diff --git a/arch/arm64/include/asm/vectors.h b/arch/arm64/include/asm/vectors.h
new file mode 100644
-index 0000000000000..f64613a96d530
+index 0000000000000..bc9a2145f4194
--- /dev/null
+++ b/arch/arm64/include/asm/vectors.h
@@ -0,0 +1,73 @@
@@ -6873,14 +10249,14 @@ index 0000000000000..f64613a96d530
+DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector);
+
+#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
-+#define TRAMP_VALIAS 0
++#define TRAMP_VALIAS 0ul
+#endif
+
+static inline const char *
+arm64_get_bp_hardening_vector(enum arm64_bp_harden_el1_vectors slot)
+{
+ if (arm64_kernel_unmapped_at_el0())
-+ return (char *)TRAMP_VALIAS + SZ_2K * slot;
++ return (char *)(TRAMP_VALIAS + SZ_2K * slot);
+
+ WARN_ON_ONCE(slot == EL1_VECTOR_KPTI);
+
@@ -6917,11 +10293,66 @@ index b3edde68bc3e0..323e251ed37bc 100644
/* SVE registers */
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
+diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
+index 3f1490bfb938a..749e31475e413 100644
+--- a/arch/arm64/kernel/Makefile
++++ b/arch/arm64/kernel/Makefile
+@@ -74,6 +74,10 @@ obj-$(CONFIG_ARM64_MTE) += mte.o
+ obj-y += vdso-wrap.o
+ obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
+
++# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
++$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so
++$(obj)/vdso32-wrap.o: $(obj)/vdso32/vdso.so
++
+ obj-y += probes/
+ head-y := head.o
+ extra-y += $(head-y) vmlinux.lds
+diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
+index 3fb79b76e9d96..7bbf5104b7b7b 100644
+--- a/arch/arm64/kernel/alternative.c
++++ b/arch/arm64/kernel/alternative.c
+@@ -42,7 +42,7 @@ bool alternative_is_applied(u16 cpufeature)
+ /*
+ * Check if the target PC is within an alternative block.
+ */
+-static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
++static __always_inline bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
+ {
+ unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
+ return !(pc >= replptr && pc <= (replptr + alt->alt_len));
+@@ -50,7 +50,7 @@ static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
+
+ #define align_down(x, a) ((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
+
+-static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
++static __always_inline u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
+ {
+ u32 insn;
+
+@@ -95,7 +95,7 @@ static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnp
+ return insn;
+ }
+
+-static void patch_alternative(struct alt_instr *alt,
++static noinstr void patch_alternative(struct alt_instr *alt,
+ __le32 *origptr, __le32 *updptr, int nr_inst)
+ {
+ __le32 *replptr;
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
-index e2c20c036442f..a33d7b8f3b935 100644
+index e2c20c036442f..c67c19d701597 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
-@@ -464,6 +464,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
+@@ -208,6 +208,8 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
+ #ifdef CONFIG_ARM64_ERRATUM_1286807
+ {
+ ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
++ /* Kryo4xx Gold (rcpe to rfpe) => (r0p0 to r3p0) */
++ ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe),
+ },
+ #endif
+ {},
+@@ -464,6 +466,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
.matches = has_spectre_v4,
.cpu_enable = spectre_v4_enable_mitigation,
},
@@ -7074,6 +10505,30 @@ index 6ec7036ef7e18..e71c9cfb46e8c 100644
{},
};
+diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
+index 03991eeff6430..3006f43248084 100644
+--- a/arch/arm64/kernel/cpuidle.c
++++ b/arch/arm64/kernel/cpuidle.c
+@@ -54,6 +54,9 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
+ struct acpi_lpi_state *lpi;
+ struct acpi_processor *pr = per_cpu(processors, cpu);
+
++ if (unlikely(!pr || !pr->flags.has_lpi))
++ return -EINVAL;
++
+ /*
+ * If the PSCI cpu_suspend function hook has not been initialized
+ * idle states must not be enabled, so bail out
+@@ -61,9 +64,6 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
+ if (!psci_ops.cpu_suspend)
+ return -EOPNOTSUPP;
+
+- if (unlikely(!pr || !pr->flags.has_lpi))
+- return -EINVAL;
+-
+ count = pr->power.count - 1;
+ if (count <= 0)
+ return -ENODEV;
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 87731fea5e418..591c18a889a56 100644
--- a/arch/arm64/kernel/cpuinfo.c
@@ -7512,6 +10967,123 @@ index b5ec010c481f3..309a27553c875 100644
vfree(p);
return NULL;
}
+diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
+index e5e801bc53122..7c1c82c8115cc 100644
+--- a/arch/arm64/kernel/mte.c
++++ b/arch/arm64/kernel/mte.c
+@@ -73,6 +73,9 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)
+ mte_sync_page_tags(page, old_pte, check_swap,
+ pte_is_tagged);
+ }
++
++ /* ensure the tags are visible before the PTE is set */
++ smp_wmb();
+ }
+
+ int memcmp_pages(struct page *page1, struct page *page2)
+diff --git a/arch/arm64/kernel/paravirt.c b/arch/arm64/kernel/paravirt.c
+index 75fed4460407d..57c7c211f8c71 100644
+--- a/arch/arm64/kernel/paravirt.c
++++ b/arch/arm64/kernel/paravirt.c
+@@ -35,7 +35,7 @@ static u64 native_steal_clock(int cpu)
+ DEFINE_STATIC_CALL(pv_steal_clock, native_steal_clock);
+
+ struct pv_time_stolen_time_region {
+- struct pvclock_vcpu_stolen_time *kaddr;
++ struct pvclock_vcpu_stolen_time __rcu *kaddr;
+ };
+
+ static DEFINE_PER_CPU(struct pv_time_stolen_time_region, stolen_time_region);
+@@ -52,7 +52,9 @@ early_param("no-steal-acc", parse_no_stealacc);
+ /* return stolen time in ns by asking the hypervisor */
+ static u64 para_steal_clock(int cpu)
+ {
++ struct pvclock_vcpu_stolen_time *kaddr = NULL;
+ struct pv_time_stolen_time_region *reg;
++ u64 ret = 0;
+
+ reg = per_cpu_ptr(&stolen_time_region, cpu);
+
+@@ -61,28 +63,37 @@ static u64 para_steal_clock(int cpu)
+ * online notification callback runs. Until the callback
+ * has run we just return zero.
+ */
+- if (!reg->kaddr)
++ rcu_read_lock();
++ kaddr = rcu_dereference(reg->kaddr);
++ if (!kaddr) {
++ rcu_read_unlock();
+ return 0;
++ }
+
+- return le64_to_cpu(READ_ONCE(reg->kaddr->stolen_time));
++ ret = le64_to_cpu(READ_ONCE(kaddr->stolen_time));
++ rcu_read_unlock();
++ return ret;
+ }
+
+ static int stolen_time_cpu_down_prepare(unsigned int cpu)
+ {
++ struct pvclock_vcpu_stolen_time *kaddr = NULL;
+ struct pv_time_stolen_time_region *reg;
+
+ reg = this_cpu_ptr(&stolen_time_region);
+ if (!reg->kaddr)
+ return 0;
+
+- memunmap(reg->kaddr);
+- memset(reg, 0, sizeof(*reg));
++ kaddr = rcu_replace_pointer(reg->kaddr, NULL, true);
++ synchronize_rcu();
++ memunmap(kaddr);
+
+ return 0;
+ }
+
+ static int stolen_time_cpu_online(unsigned int cpu)
+ {
++ struct pvclock_vcpu_stolen_time *kaddr = NULL;
+ struct pv_time_stolen_time_region *reg;
+ struct arm_smccc_res res;
+
+@@ -93,17 +104,19 @@ static int stolen_time_cpu_online(unsigned int cpu)
+ if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+ return -EINVAL;
+
+- reg->kaddr = memremap(res.a0,
++ kaddr = memremap(res.a0,
+ sizeof(struct pvclock_vcpu_stolen_time),
+ MEMREMAP_WB);
+
++ rcu_assign_pointer(reg->kaddr, kaddr);
++
+ if (!reg->kaddr) {
+ pr_warn("Failed to map stolen time data structure\n");
+ return -ENOMEM;
+ }
+
+- if (le32_to_cpu(reg->kaddr->revision) != 0 ||
+- le32_to_cpu(reg->kaddr->attributes) != 0) {
++ if (le32_to_cpu(kaddr->revision) != 0 ||
++ le32_to_cpu(kaddr->attributes) != 0) {
+ pr_warn_once("Unexpected revision or attributes in stolen time data\n");
+ return -ENXIO;
+ }
+diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
+index 771f543464e06..33e0fabc0b79b 100644
+--- a/arch/arm64/kernel/patching.c
++++ b/arch/arm64/kernel/patching.c
+@@ -117,8 +117,8 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg)
+ int i, ret = 0;
+ struct aarch64_insn_patch *pp = arg;
+
+- /* The first CPU becomes master */
+- if (atomic_inc_return(&pp->cpu_count) == 1) {
++ /* The last CPU becomes master */
++ if (atomic_inc_return(&pp->cpu_count) == num_online_cpus()) {
+ for (i = 0; ret == 0 && i < pp->insn_cnt; i++)
+ ret = aarch64_insn_patch_text_nosync(pp->text_addrs[i],
+ pp->new_insns[i]);
diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index 4a72c27273097..86d9f20131723 100644
--- a/arch/arm64/kernel/perf_callchain.c
@@ -7636,7 +11208,7 @@ index 40adb8cdbf5af..23efabcb00b85 100644
if (task_spec_ssb_noexec(current)) {
arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS,
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
-index 902e4084c4775..6d45c63c64548 100644
+index 902e4084c4775..40be3a7c2c531 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -18,15 +18,18 @@
@@ -7712,7 +11284,31 @@ index 902e4084c4775..6d45c63c64548 100644
case SPECTRE_VULNERABLE:
fallthrough;
default:
-@@ -554,9 +594,9 @@ void __init spectre_v4_patch_fw_mitigation_enable(struct alt_instr *alt,
+@@ -193,17 +233,20 @@ static void install_bp_hardening_cb(bp_hardening_cb_t fn)
+ __this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
+ }
+
+-static void call_smc_arch_workaround_1(void)
++/* Called during entry so must be noinstr */
++static noinstr void call_smc_arch_workaround_1(void)
+ {
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+ }
+
+-static void call_hvc_arch_workaround_1(void)
++/* Called during entry so must be noinstr */
++static noinstr void call_hvc_arch_workaround_1(void)
+ {
+ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+ }
+
+-static void qcom_link_stack_sanitisation(void)
++/* Called during entry so must be noinstr */
++static noinstr void qcom_link_stack_sanitisation(void)
+ {
+ u64 tmp;
+
+@@ -554,9 +597,9 @@ void __init spectre_v4_patch_fw_mitigation_enable(struct alt_instr *alt,
* Patch a NOP in the Spectre-v4 mitigation code with an SMC/HVC instruction
* to call into firmware to adjust the mitigation state.
*/
@@ -7725,7 +11321,7 @@ index 902e4084c4775..6d45c63c64548 100644
{
u32 insn;
-@@ -770,3 +810,344 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
+@@ -770,3 +813,345 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
return -ENODEV;
}
}
@@ -7769,6 +11365,7 @@ index 902e4084c4775..6d45c63c64548 100644
+ if (scope == SCOPE_LOCAL_CPU) {
+ static const struct midr_range spectre_bhb_k32_list[] = {
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
@@ -8070,6 +11667,47 @@ index 902e4084c4775..6d45c63c64548 100644
+ pr_err("WARNING: %s", EBPF_WARN);
+}
+#endif
+diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
+index c287b9407f287..981f0c4157c2f 100644
+--- a/arch/arm64/kernel/signal.c
++++ b/arch/arm64/kernel/signal.c
+@@ -577,10 +577,12 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
+ {
+ int err;
+
+- err = sigframe_alloc(user, &user->fpsimd_offset,
+- sizeof(struct fpsimd_context));
+- if (err)
+- return err;
++ if (system_supports_fpsimd()) {
++ err = sigframe_alloc(user, &user->fpsimd_offset,
++ sizeof(struct fpsimd_context));
++ if (err)
++ return err;
++ }
+
+ /* fault information, if valid */
+ if (add_all || current->thread.fault_code) {
+diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
+index 6f6ff072acbde..3beaa6640ab35 100644
+--- a/arch/arm64/kernel/smp.c
++++ b/arch/arm64/kernel/smp.c
+@@ -234,6 +234,7 @@ asmlinkage notrace void secondary_start_kernel(void)
+ * Log the CPU info before it is marked online and might get read.
+ */
+ cpuinfo_store_cpu();
++ store_cpu_topology(cpu);
+
+ /*
+ * Enable GIC and timers.
+@@ -242,7 +243,6 @@ asmlinkage notrace void secondary_start_kernel(void)
+
+ ipi_setup(cpu);
+
+- store_cpu_topology(cpu);
+ numa_add_cpu(cpu);
+
+ /*
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 8982a2b78acfc..3b8dc538a4c42 100644
--- a/arch/arm64/kernel/stacktrace.c
@@ -8104,8 +11742,22 @@ index b03e383d944ab..fe0cd0568813e 100644
(void *)instruction_pointer(regs));
/* We cannot handle this */
+diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
+index 945e6bb326e3e..b5d8f72e8b32e 100644
+--- a/arch/arm64/kernel/vdso/Makefile
++++ b/arch/arm64/kernel/vdso/Makefile
+@@ -48,9 +48,6 @@ GCOV_PROFILE := n
+ targets += vdso.lds
+ CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+-# Force dependency (incbin is bad)
+-$(obj)/vdso.o : $(obj)/vdso.so
+-
+ # Link rule for the .so file, .lds has to be first
+ $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+ $(call if_changed,vdsold_and_vdso_check)
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
-index 3dba0c4f8f42b..3514269ac75fb 100644
+index 3dba0c4f8f42b..83e9399e38368 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -10,18 +10,15 @@ include $(srctree)/lib/vdso/Makefile
@@ -8151,6 +11803,16 @@ index 3dba0c4f8f42b..3514269ac75fb 100644
VDSO_CAFLAGS += $(call cc32-option,-fno-PIE)
ifdef CONFIG_DEBUG_INFO
VDSO_CAFLAGS += -g
+@@ -150,9 +144,6 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso)
+ targets += vdso.lds
+ CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+-# Force dependency (vdso.s includes vdso.so through incbin)
+-$(obj)/vdso.o: $(obj)/vdso.so
+-
+ include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index f6b1a88245db2..184abd7c4206e 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
@@ -8755,11 +12417,255 @@ index aa0060178343a..60a8b6a8a42b5 100644
regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
return 1;
}
+diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
+index 37a81754d9b61..3b269c7567984 100644
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -61,8 +61,34 @@ EXPORT_SYMBOL(memstart_addr);
+ * unless restricted on specific platforms (e.g. 30-bit on Raspberry Pi 4).
+ * In such case, ZONE_DMA32 covers the rest of the 32-bit addressable memory,
+ * otherwise it is empty.
++ *
++ * Memory reservation for crash kernel either done early or deferred
++ * depending on DMA memory zones configs (ZONE_DMA) --
++ *
++ * In absence of ZONE_DMA configs arm64_dma_phys_limit initialized
++ * here instead of max_zone_phys(). This lets early reservation of
++ * crash kernel memory which has a dependency on arm64_dma_phys_limit.
++ * Reserving memory early for crash kernel allows linear creation of block
++ * mappings (greater than page-granularity) for all the memory bank rangs.
++ * In this scheme a comparatively quicker boot is observed.
++ *
++ * If ZONE_DMA configs are defined, crash kernel memory reservation
++ * is delayed until DMA zone memory range size initilazation performed in
++ * zone_sizes_init(). The defer is necessary to steer clear of DMA zone
++ * memory range to avoid overlap allocation. So crash kernel memory boundaries
++ * are not known when mapping all bank memory ranges, which otherwise means
++ * not possible to exclude crash kernel range from creating block mappings
++ * so page-granularity mappings are created for the entire memory range.
++ * Hence a slightly slower boot is observed.
++ *
++ * Note: Page-granularity mapppings are necessary for crash kernel memory
++ * range for shrinking its size via /sys/kernel/kexec_crash_size interface.
+ */
+-phys_addr_t arm64_dma_phys_limit __ro_after_init;
++#if IS_ENABLED(CONFIG_ZONE_DMA) || IS_ENABLED(CONFIG_ZONE_DMA32)
++phys_addr_t __ro_after_init arm64_dma_phys_limit;
++#else
++phys_addr_t __ro_after_init arm64_dma_phys_limit = PHYS_MASK + 1;
++#endif
+
+ #ifdef CONFIG_KEXEC_CORE
+ /*
+@@ -153,50 +179,11 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
+ if (!arm64_dma_phys_limit)
+ arm64_dma_phys_limit = dma32_phys_limit;
+ #endif
+- if (!arm64_dma_phys_limit)
+- arm64_dma_phys_limit = PHYS_MASK + 1;
+ max_zone_pfns[ZONE_NORMAL] = max;
+
+ free_area_init(max_zone_pfns);
+ }
+
+-int pfn_valid(unsigned long pfn)
+-{
+- phys_addr_t addr = PFN_PHYS(pfn);
+- struct mem_section *ms;
+-
+- /*
+- * Ensure the upper PAGE_SHIFT bits are clear in the
+- * pfn. Else it might lead to false positives when
+- * some of the upper bits are set, but the lower bits
+- * match a valid pfn.
+- */
+- if (PHYS_PFN(addr) != pfn)
+- return 0;
+-
+- if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+- return 0;
+-
+- ms = __pfn_to_section(pfn);
+- if (!valid_section(ms))
+- return 0;
+-
+- /*
+- * ZONE_DEVICE memory does not have the memblock entries.
+- * memblock_is_map_memory() check for ZONE_DEVICE based
+- * addresses will always fail. Even the normal hotplugged
+- * memory will never have MEMBLOCK_NOMAP flag set in their
+- * memblock entries. Skip memblock search for all non early
+- * memory sections covering all of hotplug memory including
+- * both normal and ZONE_DEVICE based.
+- */
+- if (!early_section(ms))
+- return pfn_section_valid(ms, pfn);
+-
+- return memblock_is_memory(addr);
+-}
+-EXPORT_SYMBOL(pfn_valid);
+-
+ int pfn_is_map_memory(unsigned long pfn)
+ {
+ phys_addr_t addr = PFN_PHYS(pfn);
+@@ -352,6 +339,9 @@ void __init arm64_memblock_init(void)
+
+ early_init_fdt_scan_reserved_mem();
+
++ if (!IS_ENABLED(CONFIG_ZONE_DMA) && !IS_ENABLED(CONFIG_ZONE_DMA32))
++ reserve_crashkernel();
++
+ high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
+ }
+
+@@ -398,7 +388,8 @@ void __init bootmem_init(void)
+ * request_standard_resources() depends on crashkernel's memory being
+ * reserved, so do it here.
+ */
+- reserve_crashkernel();
++ if (IS_ENABLED(CONFIG_ZONE_DMA) || IS_ENABLED(CONFIG_ZONE_DMA32))
++ reserve_crashkernel();
+
+ memblock_dump_all();
+ }
+diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
+index b7c81dacabf07..b21f91cd830db 100644
+--- a/arch/arm64/mm/ioremap.c
++++ b/arch/arm64/mm/ioremap.c
+@@ -99,3 +99,11 @@ void __init early_ioremap_init(void)
+ {
+ early_ioremap_setup();
+ }
++
++bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
++ unsigned long flags)
++{
++ unsigned long pfn = PHYS_PFN(offset);
++
++ return pfn_is_map_memory(pfn);
++}
+diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
+index a38f54cd638c2..77ada00280d93 100644
+--- a/arch/arm64/mm/mmap.c
++++ b/arch/arm64/mm/mmap.c
+@@ -7,8 +7,10 @@
+
+ #include <linux/io.h>
+ #include <linux/memblock.h>
++#include <linux/mm.h>
+ #include <linux/types.h>
+
++#include <asm/cpufeature.h>
+ #include <asm/page.h>
+
+ /*
+@@ -38,3 +40,18 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+ {
+ return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK);
+ }
++
++static int __init adjust_protection_map(void)
++{
++ /*
++ * With Enhanced PAN we can honour the execute-only permissions as
++ * there is no PAN override with such mappings.
++ */
++ if (cpus_have_const_cap(ARM64_HAS_EPAN)) {
++ protection_map[VM_EXEC] = PAGE_EXECONLY;
++ protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
++ }
++
++ return 0;
++}
++arch_initcall(adjust_protection_map);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
-index cfd9deb347c38..9d03806316905 100644
+index cfd9deb347c38..6680689242df3 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
-@@ -616,6 +616,8 @@ early_param("rodata", parse_rodata);
+@@ -63,6 +63,7 @@ static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused;
+ static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;
+
+ static DEFINE_SPINLOCK(swapper_pgdir_lock);
++static DEFINE_MUTEX(fixmap_lock);
+
+ void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd)
+ {
+@@ -328,6 +329,12 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
+ }
+ BUG_ON(p4d_bad(p4d));
+
++ /*
++ * No need for locking during early boot. And it doesn't work as
++ * expected with KASLR enabled.
++ */
++ if (system_state != SYSTEM_BOOTING)
++ mutex_lock(&fixmap_lock);
+ pudp = pud_set_fixmap_offset(p4dp, addr);
+ do {
+ pud_t old_pud = READ_ONCE(*pudp);
+@@ -358,6 +365,8 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
+ } while (pudp++, addr = next, addr != end);
+
+ pud_clear_fixmap();
++ if (system_state != SYSTEM_BOOTING)
++ mutex_unlock(&fixmap_lock);
+ }
+
+ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
+@@ -516,7 +525,7 @@ static void __init map_mem(pgd_t *pgdp)
+ */
+ BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
+
+- if (can_set_direct_map() || crash_mem_map || IS_ENABLED(CONFIG_KFENCE))
++ if (can_set_direct_map() || IS_ENABLED(CONFIG_KFENCE))
+ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
+
+ /*
+@@ -527,6 +536,17 @@ static void __init map_mem(pgd_t *pgdp)
+ */
+ memblock_mark_nomap(kernel_start, kernel_end - kernel_start);
+
++#ifdef CONFIG_KEXEC_CORE
++ if (crash_mem_map) {
++ if (IS_ENABLED(CONFIG_ZONE_DMA) ||
++ IS_ENABLED(CONFIG_ZONE_DMA32))
++ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
++ else if (crashk_res.end)
++ memblock_mark_nomap(crashk_res.start,
++ resource_size(&crashk_res));
++ }
++#endif
++
+ /* map all the memory banks */
+ for_each_mem_range(i, &start, &end) {
+ if (start >= end)
+@@ -553,6 +573,25 @@ static void __init map_mem(pgd_t *pgdp)
+ __map_memblock(pgdp, kernel_start, kernel_end,
+ PAGE_KERNEL, NO_CONT_MAPPINGS);
+ memblock_clear_nomap(kernel_start, kernel_end - kernel_start);
++
++ /*
++ * Use page-level mappings here so that we can shrink the region
++ * in page granularity and put back unused memory to buddy system
++ * through /sys/kernel/kexec_crash_size interface.
++ */
++#ifdef CONFIG_KEXEC_CORE
++ if (crash_mem_map &&
++ !IS_ENABLED(CONFIG_ZONE_DMA) && !IS_ENABLED(CONFIG_ZONE_DMA32)) {
++ if (crashk_res.end) {
++ __map_memblock(pgdp, crashk_res.start,
++ crashk_res.end + 1,
++ PAGE_KERNEL,
++ NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
++ memblock_clear_nomap(crashk_res.start,
++ resource_size(&crashk_res));
++ }
++ }
++#endif
+ }
+
+ void mark_rodata_ro(void)
+@@ -616,6 +655,8 @@ early_param("rodata", parse_rodata);
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
static int __init map_entry_trampoline(void)
{
@@ -8768,7 +12674,7 @@ index cfd9deb347c38..9d03806316905 100644
pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;
phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start);
-@@ -624,11 +626,15 @@ static int __init map_entry_trampoline(void)
+@@ -624,11 +665,15 @@ static int __init map_entry_trampoline(void)
/* Map only the text into the trampoline page table */
memset(tramp_pg_dir, 0, PGD_SIZE);
@@ -8787,7 +12693,7 @@ index cfd9deb347c38..9d03806316905 100644
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
extern char __entry_tramp_data_start[];
-@@ -1499,6 +1505,11 @@ int arch_add_memory(int nid, u64 start, u64 size,
+@@ -1499,6 +1544,11 @@ int arch_add_memory(int nid, u64 start, u64 size,
if (ret)
__remove_pgd_mapping(swapper_pg_dir,
__phys_to_virt(start), size);
@@ -8813,10 +12719,46 @@ index 1c403536c9bb0..9bc4066c5bf33 100644
{ MODULES_END, "Modules end" },
{ VMALLOC_START, "vmalloc() area" },
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
-index 803e7773fa869..465c44d0c72fc 100644
+index 803e7773fa869..b56e7bd96594c 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
-@@ -1138,15 +1138,12 @@ out:
+@@ -1042,15 +1042,18 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+ goto out_off;
+ }
+
+- /* 1. Initial fake pass to compute ctx->idx. */
+-
+- /* Fake pass to fill in ctx->offset. */
+- if (build_body(&ctx, extra_pass)) {
++ /*
++ * 1. Initial fake pass to compute ctx->idx and ctx->offset.
++ *
++ * BPF line info needs ctx->offset[i] to be the offset of
++ * instruction[i] in jited image, so build prologue first.
++ */
++ if (build_prologue(&ctx, was_classic)) {
+ prog = orig_prog;
+ goto out_off;
+ }
+
+- if (build_prologue(&ctx, was_classic)) {
++ if (build_body(&ctx, extra_pass)) {
+ prog = orig_prog;
+ goto out_off;
+ }
+@@ -1123,6 +1126,11 @@ skip_init_ctx:
+ prog->jited_len = prog_size;
+
+ if (!prog->is_func || extra_pass) {
++ int i;
++
++ /* offset[prog->len] is the size of program */
++ for (i = 0; i <= prog->len; i++)
++ ctx.offset[i] *= AARCH64_INSN_SIZE;
+ bpf_prog_fill_jited_linfo(prog, ctx.offset + 1);
+ out_off:
+ kfree(ctx.offset);
+@@ -1138,15 +1146,12 @@ out:
u64 bpf_jit_alloc_exec_limit(void)
{
@@ -8846,10 +12788,41 @@ index 49305c2e6dfd3..b71c6cbb23095 100644
SSBS
SVE
UNMAP_KERNEL_AT_EL0
+diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h
+index c40f06ee8d3ef..ac5a54f57d407 100644
+--- a/arch/csky/include/asm/uaccess.h
++++ b/arch/csky/include/asm/uaccess.h
+@@ -3,14 +3,13 @@
+ #ifndef __ASM_CSKY_UACCESS_H
+ #define __ASM_CSKY_UACCESS_H
+
+-#define user_addr_max() \
+- (uaccess_kernel() ? KERNEL_DS.seg : get_fs().seg)
++#define user_addr_max() (current_thread_info()->addr_limit.seg)
+
+ static inline int __access_ok(unsigned long addr, unsigned long size)
+ {
+- unsigned long limit = current_thread_info()->addr_limit.seg;
++ unsigned long limit = user_addr_max();
+
+- return ((addr < limit) && ((addr + size) < limit));
++ return (size <= limit) && (addr <= (limit - size));
+ }
+ #define __access_ok __access_ok
+
diff --git a/arch/csky/kernel/perf_callchain.c b/arch/csky/kernel/perf_callchain.c
-index ab55e98ee8f62..35318a635a5fa 100644
+index ab55e98ee8f62..75e1f9df5f604 100644
--- a/arch/csky/kernel/perf_callchain.c
+++ b/arch/csky/kernel/perf_callchain.c
+@@ -49,7 +49,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
+ {
+ struct stackframe buftail;
+ unsigned long lr = 0;
+- unsigned long *user_frame_tail = (unsigned long *)fp;
++ unsigned long __user *user_frame_tail = (unsigned long __user *)fp;
+
+ /* Check accessibility of one struct frame_tail beyond */
+ if (!access_ok(user_frame_tail, sizeof(buftail)))
@@ -86,10 +86,11 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
@@ -8876,6 +12849,19 @@ index ab55e98ee8f62..35318a635a5fa 100644
pr_warn("C-SKY does not support perf in guest mode!");
return;
}
+diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c
+index c7b763d2f526e..8867ddf3e6c77 100644
+--- a/arch/csky/kernel/signal.c
++++ b/arch/csky/kernel/signal.c
+@@ -136,7 +136,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
+ static int
+ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
+ {
+- struct rt_sigframe *frame;
++ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c
index e5fbf8653a215..2020af88b6361 100644
--- a/arch/csky/kernel/traps.c
@@ -8947,6 +12933,37 @@ index 8d4ec76fceb45..dfe69e118b2be 100644
#define ARCH_HAS_READ_CURRENT_TIMER
+diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
+index ef5bfef8d490c..719ba3f3c45cd 100644
+--- a/arch/hexagon/include/asm/uaccess.h
++++ b/arch/hexagon/include/asm/uaccess.h
+@@ -25,17 +25,17 @@
+ * Returns true (nonzero) if the memory block *may* be valid, false (zero)
+ * if it is definitely invalid.
+ *
+- * User address space in Hexagon, like x86, goes to 0xbfffffff, so the
+- * simple MSB-based tests used by MIPS won't work. Some further
+- * optimization is probably possible here, but for now, keep it
+- * reasonably simple and not *too* slow. After all, we've got the
+- * MMU for backup.
+ */
++#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
++#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
+
+-#define __access_ok(addr, size) \
+- ((get_fs().seg == KERNEL_DS.seg) || \
+- (((unsigned long)addr < get_fs().seg) && \
+- (unsigned long)size < (get_fs().seg - (unsigned long)addr)))
++static inline int __access_ok(unsigned long addr, unsigned long size)
++{
++ unsigned long limit = TASK_SIZE;
++
++ return (size <= limit) && (addr <= (limit - size));
++}
++#define __access_ok __access_ok
+
+ /*
+ * When a kernel-mode page fault is taken, the faulting instruction
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
index feffe527ac929..febc95714d756 100644
--- a/arch/hexagon/kernel/time.c
@@ -9032,6 +13049,18 @@ index 40ca23bd228d6..2ce008e2d1644 100644
help
Selecting this option turns on bug checking for the IA-64
compare-and-exchange instructions. This is slow! Itaniums
+diff --git a/arch/ia64/include/asm/timex.h b/arch/ia64/include/asm/timex.h
+index 869a3ac6bf23a..7ccc077a60bed 100644
+--- a/arch/ia64/include/asm/timex.h
++++ b/arch/ia64/include/asm/timex.h
+@@ -39,6 +39,7 @@ get_cycles (void)
+ ret = ia64_getreg(_IA64_REG_AR_ITC);
+ return ret;
+ }
++#define get_cycles get_cycles
+
+ extern void ia64_cpu_local_tick (void);
+ extern unsigned long long ia64_native_sched_clock (void);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 441ed04b10378..d4048518a1d7d 100644
--- a/arch/ia64/kernel/kprobes.c
@@ -9096,6 +13125,78 @@ index 36fa0c3ef1296..eeab4f3e6c197 100644
help
Reserve certain memory regions on 68x328 based boards.
+diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
+index 0386252e9d043..4218750414bbf 100644
+--- a/arch/m68k/coldfire/device.c
++++ b/arch/m68k/coldfire/device.c
+@@ -480,7 +480,7 @@ static struct platform_device mcf_i2c5 = {
+ #endif /* MCFI2C_BASE5 */
+ #endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+
+-#if IS_ENABLED(CONFIG_MCF_EDMA)
++#ifdef MCFEDMA_BASE
+
+ static const struct dma_slave_map mcf_edma_map[] = {
+ { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) },
+@@ -552,7 +552,7 @@ static struct platform_device mcf_edma = {
+ .platform_data = &mcf_edma_data,
+ }
+ };
+-#endif /* IS_ENABLED(CONFIG_MCF_EDMA) */
++#endif /* MCFEDMA_BASE */
+
+ #ifdef MCFSDHC_BASE
+ static struct mcf_esdhc_platform_data mcf_esdhc_data = {
+@@ -651,7 +651,7 @@ static struct platform_device *mcf_devices[] __initdata = {
+ &mcf_i2c5,
+ #endif
+ #endif
+-#if IS_ENABLED(CONFIG_MCF_EDMA)
++#ifdef MCFEDMA_BASE
+ &mcf_edma,
+ #endif
+ #ifdef MCFSDHC_BASE
+diff --git a/arch/m68k/include/asm/timex.h b/arch/m68k/include/asm/timex.h
+index 6a21d93582805..f4a7a340f4cae 100644
+--- a/arch/m68k/include/asm/timex.h
++++ b/arch/m68k/include/asm/timex.h
+@@ -35,7 +35,7 @@ static inline unsigned long random_get_entropy(void)
+ {
+ if (mach_random_get_entropy)
+ return mach_random_get_entropy();
+- return 0;
++ return random_get_entropy_fallback();
+ }
+ #define random_get_entropy random_get_entropy
+
+diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h
+index ba670523885c8..60b786eb2254e 100644
+--- a/arch/m68k/include/asm/uaccess.h
++++ b/arch/m68k/include/asm/uaccess.h
+@@ -12,14 +12,17 @@
+ #include <asm/extable.h>
+
+ /* We let the MMU do all checking */
+-static inline int access_ok(const void __user *addr,
++static inline int access_ok(const void __user *ptr,
+ unsigned long size)
+ {
+- /*
+- * XXX: for !CONFIG_CPU_HAS_ADDRESS_SPACES this really needs to check
+- * for TASK_SIZE!
+- */
+- return 1;
++ unsigned long limit = TASK_SIZE;
++ unsigned long addr = (unsigned long)ptr;
++
++ if (IS_ENABLED(CONFIG_CPU_HAS_ADDRESS_SPACES) ||
++ !IS_ENABLED(CONFIG_MMU))
++ return 1;
++
++ return (size <= limit) && (addr <= (limit - size));
+ }
+
+ /*
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 9718ce94cc845..34d6458340b0f 100644
--- a/arch/m68k/kernel/traps.c
@@ -9109,6 +13210,76 @@ index 9718ce94cc845..34d6458340b0f 100644
}
#ifdef CONFIG_M68KFPU_EMU
+diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
+index d2a8ef9f89787..3fe96979d2c62 100644
+--- a/arch/microblaze/include/asm/uaccess.h
++++ b/arch/microblaze/include/asm/uaccess.h
+@@ -39,24 +39,13 @@
+
+ # define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
+
+-static inline int access_ok(const void __user *addr, unsigned long size)
++static inline int __access_ok(unsigned long addr, unsigned long size)
+ {
+- if (!size)
+- goto ok;
++ unsigned long limit = user_addr_max();
+
+- if ((get_fs().seg < ((unsigned long)addr)) ||
+- (get_fs().seg < ((unsigned long)addr + size - 1))) {
+- pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
+- (__force u32)addr, (u32)size,
+- (u32)get_fs().seg);
+- return 0;
+- }
+-ok:
+- pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
+- (__force u32)addr, (u32)size,
+- (u32)get_fs().seg);
+- return 1;
++ return (size <= limit) && (addr <= (limit - size));
+ }
++#define access_ok(addr, size) __access_ok((unsigned long)addr, size)
+
+ # define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
+ # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
+@@ -141,27 +130,27 @@ extern long __user_bad(void);
+
+ #define __get_user(x, ptr) \
+ ({ \
+- unsigned long __gu_val = 0; \
+ long __gu_err; \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+- __get_user_asm("lbu", (ptr), __gu_val, __gu_err); \
++ __get_user_asm("lbu", (ptr), x, __gu_err); \
+ break; \
+ case 2: \
+- __get_user_asm("lhu", (ptr), __gu_val, __gu_err); \
++ __get_user_asm("lhu", (ptr), x, __gu_err); \
+ break; \
+ case 4: \
+- __get_user_asm("lw", (ptr), __gu_val, __gu_err); \
++ __get_user_asm("lw", (ptr), x, __gu_err); \
+ break; \
+- case 8: \
+- __gu_err = __copy_from_user(&__gu_val, ptr, 8); \
+- if (__gu_err) \
+- __gu_err = -EFAULT; \
++ case 8: { \
++ __u64 __x = 0; \
++ __gu_err = raw_copy_from_user(&__x, ptr, 8) ? \
++ -EFAULT : 0; \
++ (x) = (typeof(x))(typeof((x) - (x)))__x; \
+ break; \
++ } \
+ default: \
+ /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
+ } \
+- x = (__force __typeof__(*(ptr))) __gu_val; \
+ __gu_err; \
+ })
+
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 584081df89c28..6e3f36c841e5d 100644
--- a/arch/mips/Kbuild.platforms
@@ -9239,6 +13410,19 @@ index 0000000000000..b4a1b6eb2f8ad
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "../../../../lib/clz_ctz.c"
+diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi
+index 9e34f433b9b58..efbbddaf0fde5 100644
+--- a/arch/mips/boot/dts/ingenic/jz4780.dtsi
++++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
+@@ -450,7 +450,7 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+- eth0_addr: eth-mac-addr@0x22 {
++ eth0_addr: eth-mac-addr@22 {
+ reg = <0x22 0x6>;
+ };
+ };
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
index 0a515cde1c183..25860fba6218d 100644
--- a/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -9356,6 +13540,61 @@ index 48e5bd4924522..7b4f247dc60cc 100644
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=m
+diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
+index ea5b5a83f1e11..011d1d678840a 100644
+--- a/arch/mips/dec/int-handler.S
++++ b/arch/mips/dec/int-handler.S
+@@ -131,7 +131,7 @@
+ */
+ mfc0 t0,CP0_CAUSE # get pending interrupts
+ mfc0 t1,CP0_STATUS
+-#ifdef CONFIG_32BIT
++#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
+ lw t2,cpu_fpu_mask
+ #endif
+ andi t0,ST0_IM # CAUSE.CE may be non-zero!
+@@ -139,7 +139,7 @@
+
+ beqz t0,spurious
+
+-#ifdef CONFIG_32BIT
++#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
+ and t2,t0
+ bnez t2,fpu # handle FPU immediately
+ #endif
+@@ -280,7 +280,7 @@ handle_it:
+ j dec_irq_dispatch
+ nop
+
+-#ifdef CONFIG_32BIT
++#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
+ fpu:
+ lw t0,fpu_kstat_irq
+ nop
+diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
+index d95016016b42b..2bad87551203b 100644
+--- a/arch/mips/dec/prom/Makefile
++++ b/arch/mips/dec/prom/Makefile
+@@ -6,4 +6,4 @@
+
+ lib-y += init.o memory.o cmdline.o identify.o console.o
+
+-lib-$(CONFIG_32BIT) += locore.o
++lib-$(CONFIG_CPU_R3000) += locore.o
+diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
+index eaad0ed4b523b..99b9b29750db3 100644
+--- a/arch/mips/dec/setup.c
++++ b/arch/mips/dec/setup.c
+@@ -746,7 +746,8 @@ void __init arch_init_irq(void)
+ dec_interrupt[DEC_IRQ_HALT] = -1;
+
+ /* Register board interrupts: FPU and cascade. */
+- if (dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
++ if (IS_ENABLED(CONFIG_MIPS_FP_SUPPORT) &&
++ dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
+ struct irq_desc *desc_fpu;
+ int irq_fpu;
+
diff --git a/arch/mips/generic/yamon-dt.c b/arch/mips/generic/yamon-dt.c
index a3aa22c77cadc..a07a5edbcda78 100644
--- a/arch/mips/generic/yamon-dt.c
@@ -9419,6 +13658,32 @@ index 0b983800f48b7..66a8b293fd80b 100644
: "=&r"(ret),
"=&r"(tmp),
"=" GCC_OFF_SMALL_ASM() (*(unsigned long long *)ptr)
+diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
+index 62c7dfb90e06c..1e1247add1cf8 100644
+--- a/arch/mips/include/asm/dec/prom.h
++++ b/arch/mips/include/asm/dec/prom.h
+@@ -43,16 +43,11 @@
+ */
+ #define REX_PROM_MAGIC 0x30464354
+
+-#ifdef CONFIG_64BIT
+-
+-#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
+-
+-#else /* !CONFIG_64BIT */
+-
+-#define prom_is_rex(magic) ((magic) == REX_PROM_MAGIC)
+-
+-#endif /* !CONFIG_64BIT */
+-
++/* KN04 and KN05 are REX PROMs, so only do the check for R3k systems. */
++static inline bool prom_is_rex(u32 magic)
++{
++ return !IS_ENABLED(CONFIG_CPU_R3000) || magic == REX_PROM_MAGIC;
++}
+
+ /*
+ * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's and
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index b463f2aa5a613..db497a8167da2 100644
--- a/arch/mips/include/asm/ftrace.h
@@ -9579,6 +13844,30 @@ index 0e6bf220db618..6c61e0a639249 100644
static inline const char *cvmx_chip_type_to_string(enum
cvmx_chip_types_enum type)
{
+diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
+index c7925d0e98746..867e9c3db76e9 100644
+--- a/arch/mips/include/asm/pgalloc.h
++++ b/arch/mips/include/asm/pgalloc.h
+@@ -15,6 +15,7 @@
+
+ #define __HAVE_ARCH_PMD_ALLOC_ONE
+ #define __HAVE_ARCH_PUD_ALLOC_ONE
++#define __HAVE_ARCH_PGD_FREE
+ #include <asm-generic/pgalloc.h>
+
+ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+@@ -48,6 +49,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+ extern void pgd_init(unsigned long page);
+ extern pgd_t *pgd_alloc(struct mm_struct *mm);
+
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
++{
++ free_pages((unsigned long)pgd, PGD_ORDER);
++}
++
+ #define __pte_free_tlb(tlb,pte,address) \
+ do { \
+ pgtable_pte_page_dtor(pte); \
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index af3788589ee6d..431a1c9d53fc7 100644
--- a/arch/mips/include/asm/r4kcache.h
@@ -9601,6 +13890,79 @@ index af3788589ee6d..431a1c9d53fc7 100644
" .previous" \
: "+r" (__err) \
: "i" (op), "r" (addr), "i" (-EFAULT)); \
+diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h
+index bb36a400203df..8c56b862fd9c2 100644
+--- a/arch/mips/include/asm/setup.h
++++ b/arch/mips/include/asm/setup.h
+@@ -16,7 +16,7 @@ static inline void setup_8250_early_printk_port(unsigned long base,
+ unsigned int reg_shift, unsigned int timeout) {}
+ #endif
+
+-extern void set_handler(unsigned long offset, void *addr, unsigned long len);
++void set_handler(unsigned long offset, const void *addr, unsigned long len);
+ extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
+
+ typedef void (*vi_handler_t)(void);
+diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h
+index b05bb70a2e46f..2e107886f97ac 100644
+--- a/arch/mips/include/asm/timex.h
++++ b/arch/mips/include/asm/timex.h
+@@ -40,9 +40,9 @@
+ typedef unsigned int cycles_t;
+
+ /*
+- * On R4000/R4400 before version 5.0 an erratum exists such that if the
+- * cycle counter is read in the exact moment that it is matching the
+- * compare register, no interrupt will be generated.
++ * On R4000/R4400 an erratum exists such that if the cycle counter is
++ * read in the exact moment that it is matching the compare register,
++ * no interrupt will be generated.
+ *
+ * There is a suggested workaround and also the erratum can't strike if
+ * the compare interrupt isn't being used as the clock source device.
+@@ -63,7 +63,7 @@ static inline int can_use_mips_counter(unsigned int prid)
+ if (!__builtin_constant_p(cpu_has_counter))
+ asm volatile("" : "=m" (cpu_data[0].options));
+ if (likely(cpu_has_counter &&
+- prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0))))
++ prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15))))
+ return 1;
+ else
+ return 0;
+@@ -76,25 +76,24 @@ static inline cycles_t get_cycles(void)
+ else
+ return 0; /* no usable counter */
+ }
++#define get_cycles get_cycles
+
+ /*
+ * Like get_cycles - but where c0_count is not available we desperately
+ * use c0_random in an attempt to get at least a little bit of entropy.
+- *
+- * R6000 and R6000A neither have a count register nor a random register.
+- * That leaves no entropy source in the CPU itself.
+ */
+ static inline unsigned long random_get_entropy(void)
+ {
+- unsigned int prid = read_c0_prid();
+- unsigned int imp = prid & PRID_IMP_MASK;
++ unsigned int c0_random;
+
+- if (can_use_mips_counter(prid))
++ if (can_use_mips_counter(read_c0_prid()))
+ return read_c0_count();
+- else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
+- return read_c0_random();
++
++ if (cpu_has_3kex)
++ c0_random = (read_c0_random() >> 8) & 0x3f;
+ else
+- return 0; /* no usable register */
++ c0_random = read_c0_random() & 0x3f;
++ return (random_get_entropy_fallback() << 6) | (0x3f - c0_random);
+ }
+ #define random_get_entropy random_get_entropy
+
diff --git a/arch/mips/include/asm/unaligned-emul.h b/arch/mips/include/asm/unaligned-emul.h
index 2022b18944b97..9af0f4d3d288c 100644
--- a/arch/mips/include/asm/unaligned-emul.h
@@ -10425,6 +14787,30 @@ index f979adfd4fc20..ef73ba1e0ec10 100644
pr_info("Software DMA cache coherency (command line)\n");
return 0;
}
+diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
+index d542fb7af3ba2..1986d13094100 100644
+--- a/arch/mips/kernel/smp.c
++++ b/arch/mips/kernel/smp.c
+@@ -351,6 +351,9 @@ asmlinkage void start_secondary(void)
+ cpu = smp_processor_id();
+ cpu_data[cpu].udelay_val = loops_per_jiffy;
+
++ set_cpu_sibling_map(cpu);
++ set_cpu_core_map(cpu);
++
+ cpumask_set_cpu(cpu, &cpu_coherent_mask);
+ notify_cpu_starting(cpu);
+
+@@ -362,9 +365,6 @@ asmlinkage void start_secondary(void)
+ /* The CPU is running and counters synchronised, now mark it online */
+ set_cpu_online(cpu, true);
+
+- set_cpu_sibling_map(cpu);
+- set_cpu_core_map(cpu);
+-
+ calculate_cpu_foreign_map();
+
+ /*
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 2afa3eef486a9..ae93a607ddf7e 100644
--- a/arch/mips/kernel/syscall.c
@@ -10464,6 +14850,72 @@ index 2afa3eef486a9..ae93a607ddf7e 100644
-{
- do_exit(SIGSEGV);
-}
+diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
+index caa01457dce60..ed339d7979f3f 100644
+--- a/arch/mips/kernel/time.c
++++ b/arch/mips/kernel/time.c
+@@ -141,15 +141,10 @@ static __init int cpu_has_mfc0_count_bug(void)
+ case CPU_R4400MC:
+ /*
+ * The published errata for the R4400 up to 3.0 say the CPU
+- * has the mfc0 from count bug.
++ * has the mfc0 from count bug. This seems the last version
++ * produced.
+ */
+- if ((current_cpu_data.processor_id & 0xff) <= 0x30)
+- return 1;
+-
+- /*
+- * we assume newer revisions are ok
+- */
+- return 0;
++ return 1;
+ }
+
+ return 0;
+diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
+index 6f07362de5cec..edd93430b954a 100644
+--- a/arch/mips/kernel/traps.c
++++ b/arch/mips/kernel/traps.c
+@@ -2085,19 +2085,19 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
+ * If no shadow set is selected then use the default handler
+ * that does normal register saving and standard interrupt exit
+ */
+- extern char except_vec_vi, except_vec_vi_lui;
+- extern char except_vec_vi_ori, except_vec_vi_end;
+- extern char rollback_except_vec_vi;
+- char *vec_start = using_rollback_handler() ?
+- &rollback_except_vec_vi : &except_vec_vi;
++ extern const u8 except_vec_vi[], except_vec_vi_lui[];
++ extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
++ extern const u8 rollback_except_vec_vi[];
++ const u8 *vec_start = using_rollback_handler() ?
++ rollback_except_vec_vi : except_vec_vi;
+ #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
+- const int lui_offset = &except_vec_vi_lui - vec_start + 2;
+- const int ori_offset = &except_vec_vi_ori - vec_start + 2;
++ const int lui_offset = except_vec_vi_lui - vec_start + 2;
++ const int ori_offset = except_vec_vi_ori - vec_start + 2;
+ #else
+- const int lui_offset = &except_vec_vi_lui - vec_start;
+- const int ori_offset = &except_vec_vi_ori - vec_start;
++ const int lui_offset = except_vec_vi_lui - vec_start;
++ const int ori_offset = except_vec_vi_ori - vec_start;
+ #endif
+- const int handler_len = &except_vec_vi_end - vec_start;
++ const int handler_len = except_vec_vi_end - vec_start;
+
+ if (handler_len > VECTORSPACING) {
+ /*
+@@ -2305,7 +2305,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
+ }
+
+ /* Install CPU exception handler */
+-void set_handler(unsigned long offset, void *addr, unsigned long size)
++void set_handler(unsigned long offset, const void *addr, unsigned long size)
+ {
+ #ifdef CONFIG_CPU_MICROMIPS
+ memcpy((void *)(ebase + offset), ((unsigned char *)addr - 1), size);
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index dd819e31fcbbf..7a623684d9b5e 100644
--- a/arch/mips/lantiq/clk.c
@@ -10487,6 +14939,19 @@ index dd819e31fcbbf..7a623684d9b5e 100644
static inline u32 get_counter_resolution(void)
{
u32 res;
+diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
+index 42222f849bd25..446a2536999bf 100644
+--- a/arch/mips/lantiq/falcon/sysctrl.c
++++ b/arch/mips/lantiq/falcon/sysctrl.c
+@@ -167,6 +167,8 @@ static inline void clkdev_add_sys(const char *dev, unsigned int module,
+ {
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
++ if (!clk)
++ return;
+ clk->cl.dev_id = dev;
+ clk->cl.con_id = NULL;
+ clk->cl.clk = clk;
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 63dccb2ed08b2..53fcc672a2944 100644
--- a/arch/mips/lantiq/xway/dma.c
@@ -10568,6 +15033,102 @@ index 63dccb2ed08b2..53fcc672a2944 100644
return 0;
}
+diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c
+index 3d5683e75cf1e..200fe9ff641d6 100644
+--- a/arch/mips/lantiq/xway/gptu.c
++++ b/arch/mips/lantiq/xway/gptu.c
+@@ -122,6 +122,8 @@ static inline void clkdev_add_gptu(struct device *dev, const char *con,
+ {
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
++ if (!clk)
++ return;
+ clk->cl.dev_id = dev_name(dev);
+ clk->cl.con_id = con;
+ clk->cl.clk = clk;
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 917fac1636b71..084f6caba5f23 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -315,6 +315,8 @@ static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate,
+ {
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
++ if (!clk)
++ return;
+ clk->cl.dev_id = dev;
+ clk->cl.con_id = con;
+ clk->cl.clk = clk;
+@@ -338,6 +340,8 @@ static void clkdev_add_cgu(const char *dev, const char *con,
+ {
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
++ if (!clk)
++ return;
+ clk->cl.dev_id = dev;
+ clk->cl.con_id = con;
+ clk->cl.clk = clk;
+@@ -356,24 +360,28 @@ static void clkdev_add_pci(void)
+ struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+ /* main pci clock */
+- clk->cl.dev_id = "17000000.pci";
+- clk->cl.con_id = NULL;
+- clk->cl.clk = clk;
+- clk->rate = CLOCK_33M;
+- clk->rates = valid_pci_rates;
+- clk->enable = pci_enable;
+- clk->disable = pmu_disable;
+- clk->module = 0;
+- clk->bits = PMU_PCI;
+- clkdev_add(&clk->cl);
++ if (clk) {
++ clk->cl.dev_id = "17000000.pci";
++ clk->cl.con_id = NULL;
++ clk->cl.clk = clk;
++ clk->rate = CLOCK_33M;
++ clk->rates = valid_pci_rates;
++ clk->enable = pci_enable;
++ clk->disable = pmu_disable;
++ clk->module = 0;
++ clk->bits = PMU_PCI;
++ clkdev_add(&clk->cl);
++ }
+
+ /* use internal/external bus clock */
+- clk_ext->cl.dev_id = "17000000.pci";
+- clk_ext->cl.con_id = "external";
+- clk_ext->cl.clk = clk_ext;
+- clk_ext->enable = pci_ext_enable;
+- clk_ext->disable = pci_ext_disable;
+- clkdev_add(&clk_ext->cl);
++ if (clk_ext) {
++ clk_ext->cl.dev_id = "17000000.pci";
++ clk_ext->cl.con_id = "external";
++ clk_ext->cl.clk = clk_ext;
++ clk_ext->enable = pci_ext_enable;
++ clk_ext->disable = pci_ext_disable;
++ clkdev_add(&clk_ext->cl);
++ }
+ }
+
+ /* xway socs can generate clocks on gpio pins */
+@@ -393,9 +401,15 @@ static void clkdev_add_clkout(void)
+ char *name;
+
+ name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
++ if (!name)
++ continue;
+ sprintf(name, "clkout%d", i);
+
+ clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++ if (!clk) {
++ kfree(name);
++ continue;
++ }
+ clk->cl.dev_id = "1f103000.cgu";
+ clk->cl.con_id = name;
+ clk->cl.clk = clk;
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index a46db08071953..7767137c3e49a 100644
--- a/arch/mips/lib/csum_partial.S
@@ -10685,6 +15246,65 @@ index 9a29e94d3db1d..3115d4de982c5 100644
- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon);
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, 0x9615,
+ PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
+diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
+index 9adad24c2e65e..046d51a454afc 100644
+--- a/arch/mips/mm/tlbex.c
++++ b/arch/mips/mm/tlbex.c
+@@ -2167,16 +2167,14 @@ static void build_r4000_tlb_load_handler(void)
+ uasm_i_tlbr(&p);
+
+ switch (current_cpu_type()) {
+- default:
+- if (cpu_has_mips_r2_exec_hazard) {
+- uasm_i_ehb(&p);
+- fallthrough;
+-
+ case CPU_CAVIUM_OCTEON:
+ case CPU_CAVIUM_OCTEON_PLUS:
+ case CPU_CAVIUM_OCTEON2:
+- break;
+- }
++ break;
++ default:
++ if (cpu_has_mips_r2_exec_hazard)
++ uasm_i_ehb(&p);
++ break;
+ }
+
+ /* Examine entrylo 0 or 1 based on ptr. */
+@@ -2243,15 +2241,14 @@ static void build_r4000_tlb_load_handler(void)
+ uasm_i_tlbr(&p);
+
+ switch (current_cpu_type()) {
+- default:
+- if (cpu_has_mips_r2_exec_hazard) {
+- uasm_i_ehb(&p);
+-
+ case CPU_CAVIUM_OCTEON:
+ case CPU_CAVIUM_OCTEON_PLUS:
+ case CPU_CAVIUM_OCTEON2:
+- break;
+- }
++ break;
++ default:
++ if (cpu_has_mips_r2_exec_hazard)
++ uasm_i_ehb(&p);
++ break;
+ }
+
+ /* Examine entrylo 0 or 1 based on ptr. */
+diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c
+index bdf53807d7c2b..bea857c9da8b7 100644
+--- a/arch/mips/ralink/ill_acc.c
++++ b/arch/mips/ralink/ill_acc.c
+@@ -61,6 +61,7 @@ static int __init ill_acc_of_setup(void)
+ pdev = of_find_device_by_node(np);
+ if (!pdev) {
+ pr_err("%pOFn: failed to lookup pdev\n", np);
++ of_node_put(np);
+ return -EINVAL;
+ }
+
diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
index bd71f5b142383..4c83786612193 100644
--- a/arch/mips/ralink/mt7621.c
@@ -10744,6 +15364,24 @@ index bd71f5b142383..4c83786612193 100644
}
void __init ralink_of_remap(void)
+diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
+index 04684990e28ef..b7f6f782d9a13 100644
+--- a/arch/mips/rb532/devices.c
++++ b/arch/mips/rb532/devices.c
+@@ -301,11 +301,9 @@ static int __init plat_setup_devices(void)
+ static int __init setup_kmac(char *s)
+ {
+ printk(KERN_INFO "korina mac = %s\n", s);
+- if (!mac_pton(s, korina_dev0_data.mac)) {
++ if (!mac_pton(s, korina_dev0_data.mac))
+ printk(KERN_ERR "Invalid mac\n");
+- return -EINVAL;
+- }
+- return 0;
++ return 1;
+ }
+
+ __setup("kmac=", setup_kmac);
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 240bb68ec2478..ff3ba7e778901 100644
--- a/arch/mips/sni/time.c
@@ -10765,6 +15403,57 @@ index 240bb68ec2478..ff3ba7e778901 100644
wmb();
*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
wmb();
+diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h
+index d4cbf069dc224..37a40981deb3b 100644
+--- a/arch/nds32/include/asm/uaccess.h
++++ b/arch/nds32/include/asm/uaccess.h
+@@ -70,9 +70,7 @@ static inline void set_fs(mm_segment_t fs)
+ * versions are void (ie, don't return a value as such).
+ */
+
+-#define get_user __get_user \
+-
+-#define __get_user(x, ptr) \
++#define get_user(x, ptr) \
+ ({ \
+ long __gu_err = 0; \
+ __get_user_check((x), (ptr), __gu_err); \
+@@ -85,6 +83,14 @@ static inline void set_fs(mm_segment_t fs)
+ (void)0; \
+ })
+
++#define __get_user(x, ptr) \
++({ \
++ long __gu_err = 0; \
++ const __typeof__(*(ptr)) __user *__p = (ptr); \
++ __get_user_err((x), __p, (__gu_err)); \
++ __gu_err; \
++})
++
+ #define __get_user_check(x, ptr, err) \
+ ({ \
+ const __typeof__(*(ptr)) __user *__p = (ptr); \
+@@ -165,12 +171,18 @@ do { \
+ : "r"(addr), "i"(-EFAULT) \
+ : "cc")
+
+-#define put_user __put_user \
++#define put_user(x, ptr) \
++({ \
++ long __pu_err = 0; \
++ __put_user_check((x), (ptr), __pu_err); \
++ __pu_err; \
++})
+
+ #define __put_user(x, ptr) \
+ ({ \
+ long __pu_err = 0; \
+- __put_user_err((x), (ptr), __pu_err); \
++ __typeof__(*(ptr)) __user *__p = (ptr); \
++ __put_user_err((x), __p, __pu_err); \
+ __pu_err; \
+ })
+
diff --git a/arch/nds32/kernel/perf_event_cpu.c b/arch/nds32/kernel/perf_event_cpu.c
index 0ce6f9f307e6a..f387919607813 100644
--- a/arch/nds32/kernel/perf_event_cpu.c
@@ -10826,6 +15515,163 @@ index 0ce6f9f307e6a..f387919607813 100644
misc |= PERF_RECORD_MISC_GUEST_USER;
else
misc |= PERF_RECORD_MISC_GUEST_KERNEL;
+diff --git a/arch/nios2/include/asm/timex.h b/arch/nios2/include/asm/timex.h
+index a769f871b28d9..40a1adc9bd03e 100644
+--- a/arch/nios2/include/asm/timex.h
++++ b/arch/nios2/include/asm/timex.h
+@@ -8,5 +8,8 @@
+ typedef unsigned long cycles_t;
+
+ extern cycles_t get_cycles(void);
++#define get_cycles get_cycles
++
++#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
+
+ #endif
+diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h
+index ba9340e96fd4c..ca9285a915efa 100644
+--- a/arch/nios2/include/asm/uaccess.h
++++ b/arch/nios2/include/asm/uaccess.h
+@@ -88,6 +88,7 @@ extern __must_check long strnlen_user(const char __user *s, long n);
+ /* Optimized macros */
+ #define __get_user_asm(val, insn, addr, err) \
+ { \
++ unsigned long __gu_val; \
+ __asm__ __volatile__( \
+ " movi %0, %3\n" \
+ "1: " insn " %1, 0(%2)\n" \
+@@ -96,14 +97,20 @@ extern __must_check long strnlen_user(const char __user *s, long n);
+ " .section __ex_table,\"a\"\n" \
+ " .word 1b, 2b\n" \
+ " .previous" \
+- : "=&r" (err), "=r" (val) \
++ : "=&r" (err), "=r" (__gu_val) \
+ : "r" (addr), "i" (-EFAULT)); \
++ val = (__force __typeof__(*(addr)))__gu_val; \
+ }
+
+-#define __get_user_unknown(val, size, ptr, err) do { \
++extern void __get_user_unknown(void);
++
++#define __get_user_8(val, ptr, err) do { \
++ u64 __val = 0; \
+ err = 0; \
+- if (__copy_from_user(&(val), ptr, size)) { \
++ if (raw_copy_from_user(&(__val), ptr, sizeof(val))) { \
+ err = -EFAULT; \
++ } else { \
++ val = (typeof(val))(typeof((val) - (val)))__val; \
+ } \
+ } while (0)
+
+@@ -119,8 +126,11 @@ do { \
+ case 4: \
+ __get_user_asm(val, "ldw", ptr, err); \
+ break; \
++ case 8: \
++ __get_user_8(val, ptr, err); \
++ break; \
+ default: \
+- __get_user_unknown(val, size, ptr, err); \
++ __get_user_unknown(); \
+ break; \
+ } \
+ } while (0)
+@@ -129,9 +139,7 @@ do { \
+ ({ \
+ long __gu_err = -EFAULT; \
+ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
+- unsigned long __gu_val = 0; \
+- __get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
+- (x) = (__force __typeof__(x))__gu_val; \
++ __get_user_common(x, sizeof(*(ptr)), __gu_ptr, __gu_err); \
+ __gu_err; \
+ })
+
+@@ -139,11 +147,9 @@ do { \
+ ({ \
+ long __gu_err = -EFAULT; \
+ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
+- unsigned long __gu_val = 0; \
+ if (access_ok( __gu_ptr, sizeof(*__gu_ptr))) \
+- __get_user_common(__gu_val, sizeof(*__gu_ptr), \
++ __get_user_common(x, sizeof(*__gu_ptr), \
+ __gu_ptr, __gu_err); \
+- (x) = (__force __typeof__(x))__gu_val; \
+ __gu_err; \
+ })
+
+diff --git a/arch/nios2/kernel/signal.c b/arch/nios2/kernel/signal.c
+index 2009ae2d3c3bb..386e46443b605 100644
+--- a/arch/nios2/kernel/signal.c
++++ b/arch/nios2/kernel/signal.c
+@@ -36,10 +36,10 @@ struct rt_sigframe {
+
+ static inline int rt_restore_ucontext(struct pt_regs *regs,
+ struct switch_stack *sw,
+- struct ucontext *uc, int *pr2)
++ struct ucontext __user *uc, int *pr2)
+ {
+ int temp;
+- unsigned long *gregs = uc->uc_mcontext.gregs;
++ unsigned long __user *gregs = uc->uc_mcontext.gregs;
+ int err;
+
+ /* Always make any pending restarted system calls return -EINTR */
+@@ -102,10 +102,11 @@ asmlinkage int do_rt_sigreturn(struct switch_stack *sw)
+ {
+ struct pt_regs *regs = (struct pt_regs *)(sw + 1);
+ /* Verify, can we follow the stack back */
+- struct rt_sigframe *frame = (struct rt_sigframe *) regs->sp;
++ struct rt_sigframe __user *frame;
+ sigset_t set;
+ int rval;
+
++ frame = (struct rt_sigframe __user *) regs->sp;
+ if (!access_ok(frame, sizeof(*frame)))
+ goto badframe;
+
+@@ -124,10 +125,10 @@ badframe:
+ return 0;
+ }
+
+-static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
++static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
+ {
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
+- unsigned long *gregs = uc->uc_mcontext.gregs;
++ unsigned long __user *gregs = uc->uc_mcontext.gregs;
+ int err = 0;
+
+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+@@ -162,8 +163,9 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+ return err;
+ }
+
+-static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+- size_t frame_size)
++static inline void __user *get_sigframe(struct ksignal *ksig,
++ struct pt_regs *regs,
++ size_t frame_size)
+ {
+ unsigned long usp;
+
+@@ -174,13 +176,13 @@ static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+ usp = sigsp(usp, ksig);
+
+ /* Verify, is it 32 or 64 bit aligned */
+- return (void *)((usp - frame_size) & -8UL);
++ return (void __user *)((usp - frame_size) & -8UL);
+ }
+
+ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
+ {
+- struct rt_sigframe *frame;
++ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
index 3a7eeae6f56a8..aa1c7e98722e3 100644
--- a/arch/openrisc/include/asm/syscalls.h
@@ -11078,6 +15924,34 @@ index a303ae9a77f41..16ee41e77174f 100644
})
#define mfctl(reg) ({ \
+diff --git a/arch/parisc/include/asm/timex.h b/arch/parisc/include/asm/timex.h
+index 06b510f8172e3..b4622cb06a75e 100644
+--- a/arch/parisc/include/asm/timex.h
++++ b/arch/parisc/include/asm/timex.h
+@@ -13,9 +13,10 @@
+
+ typedef unsigned long cycles_t;
+
+-static inline cycles_t get_cycles (void)
++static inline cycles_t get_cycles(void)
+ {
+ return mfctl(16);
+ }
++#define get_cycles get_cycles
+
+ #endif
+diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h
+index 8ecc1f0c0483d..d0e090a2c000d 100644
+--- a/arch/parisc/include/asm/traps.h
++++ b/arch/parisc/include/asm/traps.h
+@@ -17,6 +17,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err);
+ const char *trap_name(unsigned long code);
+ void do_page_fault(struct pt_regs *regs, unsigned long code,
+ unsigned long address);
++int handle_nadtlb_fault(struct pt_regs *regs);
+ #endif
+
+ #endif
diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh
index 056d588befdd6..70d3cffb02515 100644
--- a/arch/parisc/install.sh
@@ -11121,6 +15995,99 @@ index 9f939afe6b88c..437c8d31f3907 100644
and,COND(=) %r19,%r2,%r0
b,n syscall_restore_rfi
+diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
+index 80a0ab372802d..e59574f65e641 100644
+--- a/arch/parisc/kernel/patch.c
++++ b/arch/parisc/kernel/patch.c
+@@ -40,10 +40,7 @@ static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags,
+
+ *need_unmap = 1;
+ set_fixmap(fixmap, page_to_phys(page));
+- if (flags)
+- raw_spin_lock_irqsave(&patch_lock, *flags);
+- else
+- __acquire(&patch_lock);
++ raw_spin_lock_irqsave(&patch_lock, *flags);
+
+ return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
+ }
+@@ -52,10 +49,7 @@ static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
+ {
+ clear_fixmap(fixmap);
+
+- if (flags)
+- raw_spin_unlock_irqrestore(&patch_lock, *flags);
+- else
+- __release(&patch_lock);
++ raw_spin_unlock_irqrestore(&patch_lock, *flags);
+ }
+
+ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+@@ -67,8 +61,9 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+ int mapped;
+
+ /* Make sure we don't have any aliases in cache */
+- flush_kernel_vmap_range(addr, len);
+- flush_icache_range(start, end);
++ flush_kernel_dcache_range_asm(start, end);
++ flush_kernel_icache_range_asm(start, end);
++ flush_tlb_kernel_range(start, end);
+
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped);
+
+@@ -81,8 +76,10 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+ * We're crossing a page boundary, so
+ * need to remap
+ */
+- flush_kernel_vmap_range((void *)fixmap,
+- (p-fixmap) * sizeof(*p));
++ flush_kernel_dcache_range_asm((unsigned long)fixmap,
++ (unsigned long)p);
++ flush_tlb_kernel_range((unsigned long)fixmap,
++ (unsigned long)p);
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0, &flags);
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags,
+@@ -90,10 +87,10 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+ }
+ }
+
+- flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p));
++ flush_kernel_dcache_range_asm((unsigned long)fixmap, (unsigned long)p);
++ flush_tlb_kernel_range((unsigned long)fixmap, (unsigned long)p);
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0, &flags);
+- flush_icache_range(start, end);
+ }
+
+ void __kprobes __patch_text(void *addr, u32 insn)
+diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
+index 1b6129e7d776b..b861bbbc87178 100644
+--- a/arch/parisc/kernel/processor.c
++++ b/arch/parisc/kernel/processor.c
+@@ -418,8 +418,7 @@ show_cpuinfo (struct seq_file *m, void *v)
+ }
+ seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities);
+
+- seq_printf(m, "model\t\t: %s\n"
+- "model name\t: %s\n",
++ seq_printf(m, "model\t\t: %s - %s\n",
+ boot_cpu_data.pdc.sys_model_name,
+ cpuinfo->dev ?
+ cpuinfo->dev->name : "Unknown");
+diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
+index cceb09855e03f..3fb86ee507dd5 100644
+--- a/arch/parisc/kernel/setup.c
++++ b/arch/parisc/kernel/setup.c
+@@ -150,6 +150,8 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_PA11
+ dma_ops_init();
+ #endif
++
++ clear_sched_clock_stable();
+ }
+
+ /*
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index bbfe23c40c016..0fb06d87b3a5c 100644
--- a/arch/parisc/kernel/signal.c
@@ -11232,18 +16199,17 @@ index 3f24a0af1e047..9842dcb2041e5 100644
/* Clip LWS number to a 32-bit value for 32-bit processes */
depdi 0, 31, 32, %r20
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
-index 9fb1e794831b0..061119a56fbe8 100644
+index 9fb1e794831b0..d8e59a1000ab7 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
-@@ -249,30 +249,16 @@ void __init time_init(void)
+@@ -249,30 +249,12 @@ void __init time_init(void)
static int __init init_cr16_clocksource(void)
{
/*
- * The cr16 interval timers are not syncronized across CPUs on
- * different sockets, so mark them unstable and lower rating on
- * multi-socket SMP systems.
-+ * The cr16 interval timers are not syncronized across CPUs, even if
-+ * they share the same socket.
++ * The cr16 interval timers are not synchronized across CPUs.
*/
if (num_online_cpus() > 1 && !running_on_qemu) {
- int cpu;
@@ -11265,9 +16231,6 @@ index 9fb1e794831b0..061119a56fbe8 100644
- clocksource_cr16.rating = 0;
- break;
- }
-+ /* mark sched_clock unstable */
-+ clear_sched_clock_stable();
-+
+ clocksource_cr16.name = "cr16_unstable";
+ clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
+ clocksource_cr16.rating = 0;
@@ -11275,10 +16238,19 @@ index 9fb1e794831b0..061119a56fbe8 100644
/* register at clocksource framework */
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
-index 747c328fb8862..afe8b902a8fc4 100644
+index 747c328fb8862..6fe5a3e98edc2 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
-@@ -729,6 +729,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
+@@ -661,6 +661,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
+ by hand. Technically we need to emulate:
+ fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw
+ */
++ if (code == 17 && handle_nadtlb_fault(regs))
++ return;
+ fault_address = regs->ior;
+ fault_space = regs->isr;
+ break;
+@@ -729,6 +731,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
}
mmap_read_unlock(current->mm);
}
@@ -11287,7 +16259,7 @@ index 747c328fb8862..afe8b902a8fc4 100644
fallthrough;
case 27:
/* Data memory protection ID trap */
-@@ -782,7 +784,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
+@@ -782,7 +786,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
* unless pagefault_disable() was called before.
*/
@@ -11487,6 +16459,103 @@ index 367f6397bda7a..8603850580857 100644
EXPORT_SYMBOL(iowrite64_hi_lo);
EXPORT_SYMBOL(ioread8_rep);
EXPORT_SYMBOL(ioread16_rep);
+diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
+index 716960f5d92ea..5faa3cff47387 100644
+--- a/arch/parisc/mm/fault.c
++++ b/arch/parisc/mm/fault.c
+@@ -424,3 +424,92 @@ no_context:
+ goto no_context;
+ pagefault_out_of_memory();
+ }
++
++/* Handle non-access data TLB miss faults.
++ *
++ * For probe instructions, accesses to userspace are considered allowed
++ * if they lie in a valid VMA and the access type matches. We are not
++ * allowed to handle MM faults here so there may be situations where an
++ * actual access would fail even though a probe was successful.
++ */
++int
++handle_nadtlb_fault(struct pt_regs *regs)
++{
++ unsigned long insn = regs->iir;
++ int breg, treg, xreg, val = 0;
++ struct vm_area_struct *vma, *prev_vma;
++ struct task_struct *tsk;
++ struct mm_struct *mm;
++ unsigned long address;
++ unsigned long acc_type;
++
++ switch (insn & 0x380) {
++ case 0x280:
++ /* FDC instruction */
++ fallthrough;
++ case 0x380:
++ /* PDC and FIC instructions */
++ if (printk_ratelimit()) {
++ pr_warn("BUG: nullifying cache flush/purge instruction\n");
++ show_regs(regs);
++ }
++ if (insn & 0x20) {
++ /* Base modification */
++ breg = (insn >> 21) & 0x1f;
++ xreg = (insn >> 16) & 0x1f;
++ if (breg && xreg)
++ regs->gr[breg] += regs->gr[xreg];
++ }
++ regs->gr[0] |= PSW_N;
++ return 1;
++
++ case 0x180:
++ /* PROBE instruction */
++ treg = insn & 0x1f;
++ if (regs->isr) {
++ tsk = current;
++ mm = tsk->mm;
++ if (mm) {
++ /* Search for VMA */
++ address = regs->ior;
++ mmap_read_lock(mm);
++ vma = find_vma_prev(mm, address, &prev_vma);
++ mmap_read_unlock(mm);
++
++ /*
++ * Check if access to the VMA is okay.
++ * We don't allow for stack expansion.
++ */
++ acc_type = (insn & 0x40) ? VM_WRITE : VM_READ;
++ if (vma
++ && address >= vma->vm_start
++ && (vma->vm_flags & acc_type) == acc_type)
++ val = 1;
++ }
++ }
++ if (treg)
++ regs->gr[treg] = val;
++ regs->gr[0] |= PSW_N;
++ return 1;
++
++ case 0x300:
++ /* LPA instruction */
++ if (insn & 0x20) {
++ /* Base modification */
++ breg = (insn >> 21) & 0x1f;
++ xreg = (insn >> 16) & 0x1f;
++ if (breg && xreg)
++ regs->gr[breg] += regs->gr[xreg];
++ }
++ treg = insn & 0x1f;
++ if (treg)
++ regs->gr[treg] = 0;
++ regs->gr[0] |= PSW_N;
++ return 1;
++
++ default:
++ break;
++ }
++
++ return 0;
++}
diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c
index 24426a7e1a5e5..cc15d737fda64 100644
--- a/arch/parisc/mm/fixmap.c
@@ -11591,6 +16660,19 @@ index ba5b661893588..6b9f523882c58 100644
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index aa6808e706470..72610e2d61765 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -173,7 +173,7 @@ else
+ CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,$(call cc-option,-mtune=power5))
+ CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mcpu=power5,-mcpu=power4)
+ endif
+-else
++else ifdef CONFIG_PPC_BOOK3E_64
+ CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
+ endif
+
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 408b486b13dff..cd589539f313f 100644
--- a/arch/powerpc/boot/dts/charon.dts
@@ -11637,6 +16719,101 @@ index c90702b04a530..48e5cd61599c6 100644
};
};
+diff --git a/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts b/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts
+new file mode 100644
+index 0000000000000..73f8c998c64df
+--- /dev/null
++++ b/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts
+@@ -0,0 +1,30 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * T1040RDB-REV-A Device Tree Source
++ *
++ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
++ *
++ */
++
++#include "t1040rdb.dts"
++
++/ {
++ model = "fsl,T1040RDB-REV-A";
++ compatible = "fsl,T1040RDB-REV-A";
++};
++
++&seville_port0 {
++ label = "ETH5";
++};
++
++&seville_port2 {
++ label = "ETH7";
++};
++
++&seville_port4 {
++ label = "ETH9";
++};
++
++&seville_port6 {
++ label = "ETH11";
++};
+diff --git a/arch/powerpc/boot/dts/fsl/t1040rdb.dts b/arch/powerpc/boot/dts/fsl/t1040rdb.dts
+index af0c8a6f56138..b6733e7e65805 100644
+--- a/arch/powerpc/boot/dts/fsl/t1040rdb.dts
++++ b/arch/powerpc/boot/dts/fsl/t1040rdb.dts
+@@ -119,7 +119,7 @@
+ managed = "in-band-status";
+ phy-handle = <&phy_qsgmii_0>;
+ phy-mode = "qsgmii";
+- label = "ETH5";
++ label = "ETH3";
+ status = "okay";
+ };
+
+@@ -135,7 +135,7 @@
+ managed = "in-band-status";
+ phy-handle = <&phy_qsgmii_2>;
+ phy-mode = "qsgmii";
+- label = "ETH7";
++ label = "ETH5";
+ status = "okay";
+ };
+
+@@ -151,7 +151,7 @@
+ managed = "in-band-status";
+ phy-handle = <&phy_qsgmii_4>;
+ phy-mode = "qsgmii";
+- label = "ETH9";
++ label = "ETH7";
+ status = "okay";
+ };
+
+@@ -167,7 +167,7 @@
+ managed = "in-band-status";
+ phy-handle = <&phy_qsgmii_6>;
+ phy-mode = "qsgmii";
+- label = "ETH11";
++ label = "ETH9";
+ status = "okay";
+ };
+
+diff --git a/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi b/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
+index 099a598c74c00..bfe1ed5be3374 100644
+--- a/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
++++ b/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
+@@ -139,12 +139,12 @@
+ fman@400000 {
+ ethernet@e6000 {
+ phy-handle = <&phy_rgmii_0>;
+- phy-connection-type = "rgmii";
++ phy-connection-type = "rgmii-id";
+ };
+
+ ethernet@e8000 {
+ phy-handle = <&phy_rgmii_1>;
+- phy-connection-type = "rgmii";
++ phy-connection-type = "rgmii-id";
+ };
+
+ mdio0: mdio@fc000 {
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index cb2782dd6132c..e7b194775d783 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
@@ -11904,6 +17081,113 @@ index 21cc571ea9c2d..5c98a950eca0d 100644
static inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val)
{
}
+diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
+index a1d238255f077..a07960066b5fa 100644
+--- a/arch/powerpc/include/asm/interrupt.h
++++ b/arch/powerpc/include/asm/interrupt.h
+@@ -567,7 +567,7 @@ DECLARE_INTERRUPT_HANDLER_RAW(do_slb_fault);
+ DECLARE_INTERRUPT_HANDLER(do_bad_slb_fault);
+
+ /* hash_utils.c */
+-DECLARE_INTERRUPT_HANDLER_RAW(do_hash_fault);
++DECLARE_INTERRUPT_HANDLER(do_hash_fault);
+
+ /* fault.c */
+ DECLARE_INTERRUPT_HANDLER(do_page_fault);
+diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
+index f130783c8301d..a4fe1292909e6 100644
+--- a/arch/powerpc/include/asm/io.h
++++ b/arch/powerpc/include/asm/io.h
+@@ -359,25 +359,37 @@ static inline void __raw_writeq_be(unsigned long v, volatile void __iomem *addr)
+ */
+ static inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr)
+ {
+- __asm__ __volatile__("stbcix %0,0,%1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ stbcix %0,0,%1; \
++ .machine pop;"
+ : : "r" (val), "r" (paddr) : "memory");
+ }
+
+ static inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr)
+ {
+- __asm__ __volatile__("sthcix %0,0,%1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ sthcix %0,0,%1; \
++ .machine pop;"
+ : : "r" (val), "r" (paddr) : "memory");
+ }
+
+ static inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr)
+ {
+- __asm__ __volatile__("stwcix %0,0,%1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ stwcix %0,0,%1; \
++ .machine pop;"
+ : : "r" (val), "r" (paddr) : "memory");
+ }
+
+ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
+ {
+- __asm__ __volatile__("stdcix %0,0,%1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ stdcix %0,0,%1; \
++ .machine pop;"
+ : : "r" (val), "r" (paddr) : "memory");
+ }
+
+@@ -389,7 +401,10 @@ static inline void __raw_rm_writeq_be(u64 val, volatile void __iomem *paddr)
+ static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
+ {
+ u8 ret;
+- __asm__ __volatile__("lbzcix %0,0, %1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ lbzcix %0,0, %1; \
++ .machine pop;"
+ : "=r" (ret) : "r" (paddr) : "memory");
+ return ret;
+ }
+@@ -397,7 +412,10 @@ static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
+ static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
+ {
+ u16 ret;
+- __asm__ __volatile__("lhzcix %0,0, %1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ lhzcix %0,0, %1; \
++ .machine pop;"
+ : "=r" (ret) : "r" (paddr) : "memory");
+ return ret;
+ }
+@@ -405,7 +423,10 @@ static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
+ static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
+ {
+ u32 ret;
+- __asm__ __volatile__("lwzcix %0,0, %1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ lwzcix %0,0, %1; \
++ .machine pop;"
+ : "=r" (ret) : "r" (paddr) : "memory");
+ return ret;
+ }
+@@ -413,7 +434,10 @@ static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
+ static inline u64 __raw_rm_readq(volatile void __iomem *paddr)
+ {
+ u64 ret;
+- __asm__ __volatile__("ldcix %0,0, %1"
++ __asm__ __volatile__(".machine push; \
++ .machine power6; \
++ ldcix %0,0, %1; \
++ .machine pop;"
+ : "=r" (ret) : "r" (paddr) : "memory");
+ return ret;
+ }
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 19b6942c6969a..eaf3a562bf1ed 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -12094,6 +17378,23 @@ index 813918f407653..f798640422c2d 100644
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
+diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
+index 254687258f42b..f2c5c26869f1a 100644
+--- a/arch/powerpc/include/asm/page.h
++++ b/arch/powerpc/include/asm/page.h
+@@ -132,7 +132,11 @@ static inline bool pfn_valid(unsigned long pfn)
+ #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
+ #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+
+-#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
++#define virt_addr_valid(vaddr) ({ \
++ unsigned long _addr = (unsigned long)vaddr; \
++ _addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory && \
++ pfn_valid(virt_to_pfn(_addr)); \
++})
+
+ /*
+ * On Book-E parts we need __va to parse the device tree and we can't
diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h
index bcb7b5f917be6..b325022ffa2b0 100644
--- a/arch/powerpc/include/asm/paravirt.h
@@ -12135,6 +17436,35 @@ index baea657bc8687..bca31a61e57f8 100644
#define PPC_RAW_LDBRX(r, base, b) (0x7c000428 | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b))
#define PPC_RAW_STWCX(s, a, b) (0x7c00012d | ___PPC_RS(s) | ___PPC_RA(a) | ___PPC_RB(b))
#define PPC_RAW_CMPWI(a, i) (0x2c000000 | ___PPC_RA(a) | IMM_L(i))
+diff --git a/arch/powerpc/include/asm/set_memory.h b/arch/powerpc/include/asm/set_memory.h
+index b040094f79202..7ebc807aa8cc8 100644
+--- a/arch/powerpc/include/asm/set_memory.h
++++ b/arch/powerpc/include/asm/set_memory.h
+@@ -6,6 +6,8 @@
+ #define SET_MEMORY_RW 1
+ #define SET_MEMORY_NX 2
+ #define SET_MEMORY_X 3
++#define SET_MEMORY_NP 4 /* Set memory non present */
++#define SET_MEMORY_P 5 /* Set memory present */
+
+ int change_memory_attr(unsigned long addr, int numpages, long action);
+
+@@ -29,6 +31,14 @@ static inline int set_memory_x(unsigned long addr, int numpages)
+ return change_memory_attr(addr, numpages, SET_MEMORY_X);
+ }
+
+-int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot);
++static inline int set_memory_np(unsigned long addr, int numpages)
++{
++ return change_memory_attr(addr, numpages, SET_MEMORY_NP);
++}
++
++static inline int set_memory_p(unsigned long addr, int numpages)
++{
++ return change_memory_attr(addr, numpages, SET_MEMORY_P);
++}
+
+ #endif
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index c60ebd04b2ed9..61b968d9fba7c 100644
--- a/arch/powerpc/include/asm/syscall.h
@@ -12172,6 +17502,34 @@ index b4ec6c7dd72ee..2a4ea0e213a92 100644
#endif
#if defined(CONFIG_PPC64)
+diff --git a/arch/powerpc/include/asm/timex.h b/arch/powerpc/include/asm/timex.h
+index fa2e76e4093a3..14b4489de52c5 100644
+--- a/arch/powerpc/include/asm/timex.h
++++ b/arch/powerpc/include/asm/timex.h
+@@ -19,6 +19,7 @@ static inline cycles_t get_cycles(void)
+ {
+ return mftb();
+ }
++#define get_cycles get_cycles
+
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_TIMEX_H */
+diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
+index 22c79ab400060..b2680070d65d6 100644
+--- a/arch/powerpc/include/asm/uaccess.h
++++ b/arch/powerpc/include/asm/uaccess.h
+@@ -125,8 +125,11 @@ do { \
+ */
+ #define __get_user_atomic_128_aligned(kaddr, uaddr, err) \
+ __asm__ __volatile__( \
++ ".machine push\n" \
++ ".machine altivec\n" \
+ "1: lvx 0,0,%1 # get user\n" \
+ " stvx 0,0,%2 # put kernel\n" \
++ ".machine pop\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,%3\n" \
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 7be36c1e1db6d..b1b23b4d56ba2 100644
--- a/arch/powerpc/kernel/Makefile
@@ -12457,6 +17815,20 @@ index ec950b08a8dcc..4c6d1a8dcefed 100644
.endif
#endif
.endm
+diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
+index 617eba82531cb..6568823cf3063 100644
+--- a/arch/powerpc/kernel/kvm.c
++++ b/arch/powerpc/kernel/kvm.c
+@@ -669,7 +669,8 @@ static void __init kvm_use_magic_page(void)
+ on_each_cpu(kvm_map_magic_page, &features, 1);
+
+ /* Quick self-test to see if the mapping works */
+- if (!fault_in_pages_readable((const char *)KVM_MAGIC_PAGE, sizeof(u32))) {
++ if (fault_in_readable((const char __user *)KVM_MAGIC_PAGE,
++ sizeof(u32))) {
+ kvm_patching_worked = false;
+ return;
+ }
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index ed04a3ba66fe8..40a583e9d3c70 100644
--- a/arch/powerpc/kernel/module.c
@@ -12591,6 +17963,163 @@ index 18b04b08b9833..f845065c860e3 100644
return;
/*
+diff --git a/arch/powerpc/kernel/reloc_64.S b/arch/powerpc/kernel/reloc_64.S
+index 02d4719bf43a8..232e4549defe1 100644
+--- a/arch/powerpc/kernel/reloc_64.S
++++ b/arch/powerpc/kernel/reloc_64.S
+@@ -8,8 +8,10 @@
+ #include <asm/ppc_asm.h>
+
+ RELA = 7
+-RELACOUNT = 0x6ffffff9
++RELASZ = 8
++RELAENT = 9
+ R_PPC64_RELATIVE = 22
++R_PPC64_UADDR64 = 43
+
+ /*
+ * r3 = desired final address of kernel
+@@ -25,29 +27,38 @@ _GLOBAL(relocate)
+ add r9,r9,r12 /* r9 has runtime addr of .rela.dyn section */
+ ld r10,(p_st - 0b)(r12)
+ add r10,r10,r12 /* r10 has runtime addr of _stext */
++ ld r13,(p_sym - 0b)(r12)
++ add r13,r13,r12 /* r13 has runtime addr of .dynsym */
+
+ /*
+- * Scan the dynamic section for the RELA and RELACOUNT entries.
++ * Scan the dynamic section for the RELA, RELASZ and RELAENT entries.
+ */
+ li r7,0
+ li r8,0
+-1: ld r6,0(r11) /* get tag */
++.Ltags:
++ ld r6,0(r11) /* get tag */
+ cmpdi r6,0
+- beq 4f /* end of list */
++ beq .Lend_of_list /* end of list */
+ cmpdi r6,RELA
+ bne 2f
+ ld r7,8(r11) /* get RELA pointer in r7 */
+- b 3f
+-2: addis r6,r6,(-RELACOUNT)@ha
+- cmpdi r6,RELACOUNT@l
++ b 4f
++2: cmpdi r6,RELASZ
+ bne 3f
+- ld r8,8(r11) /* get RELACOUNT value in r8 */
+-3: addi r11,r11,16
+- b 1b
+-4: cmpdi r7,0 /* check we have both RELA and RELACOUNT */
++ ld r8,8(r11) /* get RELASZ value in r8 */
++ b 4f
++3: cmpdi r6,RELAENT
++ bne 4f
++ ld r12,8(r11) /* get RELAENT value in r12 */
++4: addi r11,r11,16
++ b .Ltags
++.Lend_of_list:
++ cmpdi r7,0 /* check we have RELA, RELASZ, RELAENT */
+ cmpdi cr1,r8,0
+- beq 6f
+- beq cr1,6f
++ beq .Lout
++ beq cr1,.Lout
++ cmpdi r12,0
++ beq .Lout
+
+ /*
+ * Work out linktime address of _stext and hence the
+@@ -62,23 +73,39 @@ _GLOBAL(relocate)
+
+ /*
+ * Run through the list of relocations and process the
+- * R_PPC64_RELATIVE ones.
++ * R_PPC64_RELATIVE and R_PPC64_UADDR64 ones.
+ */
++ divd r8,r8,r12 /* RELASZ / RELAENT */
+ mtctr r8
+-5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */
++.Lrels: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */
+ cmpdi r0,R_PPC64_RELATIVE
+- bne 6f
++ bne .Luaddr64
+ ld r6,0(r9) /* reloc->r_offset */
+ ld r0,16(r9) /* reloc->r_addend */
++ b .Lstore
++.Luaddr64:
++ srdi r14,r0,32 /* ELF64_R_SYM(reloc->r_info) */
++ clrldi r0,r0,32
++ cmpdi r0,R_PPC64_UADDR64
++ bne .Lnext
++ ld r6,0(r9)
++ ld r0,16(r9)
++ mulli r14,r14,24 /* 24 == sizeof(elf64_sym) */
++ add r14,r14,r13 /* elf64_sym[ELF64_R_SYM] */
++ ld r14,8(r14)
++ add r0,r0,r14
++.Lstore:
+ add r0,r0,r3
+ stdx r0,r7,r6
+- addi r9,r9,24
+- bdnz 5b
+-
+-6: blr
++.Lnext:
++ add r9,r9,r12
++ bdnz .Lrels
++.Lout:
++ blr
+
+ .balign 8
+ p_dyn: .8byte __dynamic_start - 0b
+ p_rela: .8byte __rela_dyn_start - 0b
++p_sym: .8byte __dynamic_symtab - 0b
+ p_st: .8byte _stext - 0b
+
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index ff80bbad22a58..e18a725a8e5d3 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -1235,6 +1235,12 @@ int __init early_init_dt_scan_rtas(unsigned long node,
+ entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+ sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
+
++#ifdef CONFIG_PPC64
++ /* need this feature to decide the crashkernel offset */
++ if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL))
++ powerpc_firmware_features |= FW_FEATURE_LPAR;
++#endif
++
+ if (basep && entryp && sizep) {
+ rtas.base = *basep;
+ rtas.entry = *entryp;
+diff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c
+index a0a78aba2083e..1ee4640a26413 100644
+--- a/arch/powerpc/kernel/secvar-sysfs.c
++++ b/arch/powerpc/kernel/secvar-sysfs.c
+@@ -26,15 +26,18 @@ static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *format;
+
+ node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
+- if (!of_device_is_available(node))
+- return -ENODEV;
++ if (!of_device_is_available(node)) {
++ rc = -ENODEV;
++ goto out;
++ }
+
+ rc = of_property_read_string(node, "format", &format);
+ if (rc)
+- return rc;
++ goto out;
+
+ rc = sprintf(buf, "%s\n", format);
+
++out:
+ of_node_put(node);
+
+ return rc;
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index 1f07317964e49..618aeccdf6918 100644
--- a/arch/powerpc/kernel/signal.h
@@ -12613,9 +18142,18 @@ index 1f07317964e49..618aeccdf6918 100644
#ifdef CONFIG_VSX
extern unsigned long copy_vsx_to_user(void __user *to,
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
-index 0608581967f09..f2da879264bcd 100644
+index 0608581967f09..3e053e2fd6b69 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
+@@ -1048,7 +1048,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
+ if (new_ctx == NULL)
+ return 0;
+ if (!access_ok(new_ctx, ctx_size) ||
+- fault_in_pages_readable((u8 __user *)new_ctx, ctx_size))
++ fault_in_readable((char __user *)new_ctx, ctx_size))
+ return -EFAULT;
+
+ /*
@@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
* or if another thread unmaps the region containing the context.
* We kill the task with a SIGSEGV in this situation.
@@ -12629,10 +18167,28 @@ index 0608581967f09..f2da879264bcd 100644
set_thread_flag(TIF_RESTOREALL);
return 0;
+@@ -1237,7 +1239,7 @@ SYSCALL_DEFINE3(debug_setcontext, struct ucontext __user *, ctx,
+ #endif
+
+ if (!access_ok(ctx, sizeof(*ctx)) ||
+- fault_in_pages_readable((u8 __user *)ctx, sizeof(*ctx)))
++ fault_in_readable((char __user *)ctx, sizeof(*ctx)))
+ return -EFAULT;
+
+ /*
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
-index 1831bba0582e1..bb9c077ac1322 100644
+index 1831bba0582e1..d1e1fc0acbea3 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
+@@ -688,7 +688,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
+ if (new_ctx == NULL)
+ return 0;
+ if (!access_ok(new_ctx, ctx_size) ||
+- fault_in_pages_readable((u8 __user *)new_ctx, ctx_size))
++ fault_in_readable((char __user *)new_ctx, ctx_size))
+ return -EFAULT;
+
+ /*
@@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
* We kill the task with a SIGSEGV in this situation.
*/
@@ -12726,6 +18282,20 @@ index 605bab448f847..fb95f92dcfac6 100644
static void fixup_topology(void)
{
+diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
+index 40bdefe9caa73..1a63e37f336ab 100644
+--- a/arch/powerpc/kernel/vmlinux.lds.S
++++ b/arch/powerpc/kernel/vmlinux.lds.S
+@@ -275,9 +275,7 @@ SECTIONS
+ . = ALIGN(8);
+ .dynsym : AT(ADDR(.dynsym) - LOAD_OFFSET)
+ {
+-#ifdef CONFIG_PPC32
+ __dynamic_symtab = .;
+-#endif
+ *(.dynsym)
+ }
+ .dynstr : AT(ADDR(.dynstr) - LOAD_OFFSET) { *(.dynstr) }
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index f9ea0e5357f92..ad94a2c6b7337 100644
--- a/arch/powerpc/kernel/watchdog.c
@@ -12813,8 +18383,330 @@ index f9ea0e5357f92..ad94a2c6b7337 100644
if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) {
per_cpu(wd_timer_tb, cpu) = tb;
wd_smp_clear_cpu_pending(cpu, tb);
+diff --git a/arch/powerpc/kexec/core.c b/arch/powerpc/kexec/core.c
+index 48525e8b57300..71b1bfdadd76a 100644
+--- a/arch/powerpc/kexec/core.c
++++ b/arch/powerpc/kexec/core.c
+@@ -147,11 +147,18 @@ void __init reserve_crashkernel(void)
+ if (!crashk_res.start) {
+ #ifdef CONFIG_PPC64
+ /*
+- * On 64bit we split the RMO in half but cap it at half of
+- * a small SLB (128MB) since the crash kernel needs to place
+- * itself and some stacks to be in the first segment.
++ * On the LPAR platform place the crash kernel to mid of
++ * RMA size (512MB or more) to ensure the crash kernel
++ * gets enough space to place itself and some stack to be
++ * in the first segment. At the same time normal kernel
++ * also get enough space to allocate memory for essential
++ * system resource in the first segment. Keep the crash
++ * kernel starts at 128MB offset on other platforms.
+ */
+- crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
++ if (firmware_has_feature(FW_FEATURE_LPAR))
++ crashk_res.start = ppc64_rma_size / 2;
++ else
++ crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
+ #else
+ crashk_res.start = KDUMP_KERNELBASE;
+ #endif
+diff --git a/arch/powerpc/kvm/book3s_32_sr.S b/arch/powerpc/kvm/book3s_32_sr.S
+index e3ab9df6cf199..6cfcd20d46686 100644
+--- a/arch/powerpc/kvm/book3s_32_sr.S
++++ b/arch/powerpc/kvm/book3s_32_sr.S
+@@ -122,11 +122,27 @@
+
+ /* 0x0 - 0xb */
+
+- /* 'current->mm' needs to be in r4 */
+- tophys(r4, r2)
+- lwz r4, MM(r4)
+- tophys(r4, r4)
+- /* This only clobbers r0, r3, r4 and r5 */
++ /* switch_mmu_context() needs paging, let's enable it */
++ mfmsr r9
++ ori r11, r9, MSR_DR
++ mtmsr r11
++ sync
++
++ /* switch_mmu_context() clobbers r12, rescue it */
++ SAVE_GPR(12, r1)
++
++ /* Calling switch_mmu_context(<inv>, current->mm, <inv>); */
++ lwz r4, MM(r2)
+ bl switch_mmu_context
+
++ /* restore r12 */
++ REST_GPR(12, r1)
++
++ /* Disable paging again */
++ mfmsr r9
++ li r6, MSR_DR
++ andc r9, r9, r6
++ mtmsr r9
++ sync
++
+ .endm
+diff --git a/arch/powerpc/kvm/book3s_64_entry.S b/arch/powerpc/kvm/book3s_64_entry.S
+index 983b8c18bc31e..a644003603da1 100644
+--- a/arch/powerpc/kvm/book3s_64_entry.S
++++ b/arch/powerpc/kvm/book3s_64_entry.S
+@@ -407,10 +407,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_DAWR1)
+ */
+ ld r10,HSTATE_SCRATCH0(r13)
+ cmpwi r10,BOOK3S_INTERRUPT_MACHINE_CHECK
+- beq machine_check_common
++ beq .Lcall_machine_check_common
+
+ cmpwi r10,BOOK3S_INTERRUPT_SYSTEM_RESET
+- beq system_reset_common
++ beq .Lcall_system_reset_common
+
+ b .
++
++.Lcall_machine_check_common:
++ b machine_check_common
++
++.Lcall_system_reset_common:
++ b system_reset_common
+ #endif
+diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
+index 6365087f31602..3cb2e05a7ee83 100644
+--- a/arch/powerpc/kvm/book3s_64_vio.c
++++ b/arch/powerpc/kvm/book3s_64_vio.c
+@@ -421,13 +421,19 @@ static void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt,
+ tbl[idx % TCES_PER_PAGE] = tce;
+ }
+
+-static void kvmppc_clear_tce(struct mm_struct *mm, struct iommu_table *tbl,
+- unsigned long entry)
++static void kvmppc_clear_tce(struct mm_struct *mm, struct kvmppc_spapr_tce_table *stt,
++ struct iommu_table *tbl, unsigned long entry)
+ {
+- unsigned long hpa = 0;
+- enum dma_data_direction dir = DMA_NONE;
++ unsigned long i;
++ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
++ unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
++
++ for (i = 0; i < subpages; ++i) {
++ unsigned long hpa = 0;
++ enum dma_data_direction dir = DMA_NONE;
+
+- iommu_tce_xchg_no_kill(mm, tbl, entry, &hpa, &dir);
++ iommu_tce_xchg_no_kill(mm, tbl, io_entry + i, &hpa, &dir);
++ }
+ }
+
+ static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm,
+@@ -486,6 +492,8 @@ static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
+ break;
+ }
+
++ iommu_tce_kill(tbl, io_entry, subpages);
++
+ return ret;
+ }
+
+@@ -545,6 +553,8 @@ static long kvmppc_tce_iommu_map(struct kvm *kvm,
+ break;
+ }
+
++ iommu_tce_kill(tbl, io_entry, subpages);
++
+ return ret;
+ }
+
+@@ -591,10 +601,9 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+ ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
+ entry, ua, dir);
+
+- iommu_tce_kill(stit->tbl, entry, 1);
+
+ if (ret != H_SUCCESS) {
+- kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry);
++ kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry);
+ goto unlock_exit;
+ }
+ }
+@@ -670,13 +679,13 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+ */
+ if (get_user(tce, tces + i)) {
+ ret = H_TOO_HARD;
+- goto invalidate_exit;
++ goto unlock_exit;
+ }
+ tce = be64_to_cpu(tce);
+
+ if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) {
+ ret = H_PARAMETER;
+- goto invalidate_exit;
++ goto unlock_exit;
+ }
+
+ list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
+@@ -685,19 +694,15 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+ iommu_tce_direction(tce));
+
+ if (ret != H_SUCCESS) {
+- kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl,
+- entry);
+- goto invalidate_exit;
++ kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl,
++ entry + i);
++ goto unlock_exit;
+ }
+ }
+
+ kvmppc_tce_put(stt, entry + i, tce);
+ }
+
+-invalidate_exit:
+- list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
+- iommu_tce_kill(stit->tbl, entry, npages);
+-
+ unlock_exit:
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+@@ -736,20 +741,16 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
+ continue;
+
+ if (ret == H_TOO_HARD)
+- goto invalidate_exit;
++ return ret;
+
+ WARN_ON_ONCE(1);
+- kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry);
++ kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry + i);
+ }
+ }
+
+ for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
+ kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value);
+
+-invalidate_exit:
+- list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
+- iommu_tce_kill(stit->tbl, ioba >> stt->page_shift, npages);
+-
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce);
+diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
+index 870b7f0c7ea56..fdeda6a9cff44 100644
+--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
++++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
+@@ -247,13 +247,19 @@ static void iommu_tce_kill_rm(struct iommu_table *tbl,
+ tbl->it_ops->tce_kill(tbl, entry, pages, true);
+ }
+
+-static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl,
+- unsigned long entry)
++static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt,
++ struct iommu_table *tbl, unsigned long entry)
+ {
+- unsigned long hpa = 0;
+- enum dma_data_direction dir = DMA_NONE;
++ unsigned long i;
++ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
++ unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
++
++ for (i = 0; i < subpages; ++i) {
++ unsigned long hpa = 0;
++ enum dma_data_direction dir = DMA_NONE;
+
+- iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir);
++ iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir);
++ }
+ }
+
+ static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
+@@ -316,6 +322,8 @@ static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
+ break;
+ }
+
++ iommu_tce_kill_rm(tbl, io_entry, subpages);
++
+ return ret;
+ }
+
+@@ -379,6 +387,8 @@ static long kvmppc_rm_tce_iommu_map(struct kvm *kvm,
+ break;
+ }
+
++ iommu_tce_kill_rm(tbl, io_entry, subpages);
++
+ return ret;
+ }
+
+@@ -420,10 +430,8 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+ ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
+ stit->tbl, entry, ua, dir);
+
+- iommu_tce_kill_rm(stit->tbl, entry, 1);
+-
+ if (ret != H_SUCCESS) {
+- kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
++ kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry);
+ return ret;
+ }
+ }
+@@ -561,7 +569,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+ ua = 0;
+ if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) {
+ ret = H_PARAMETER;
+- goto invalidate_exit;
++ goto unlock_exit;
+ }
+
+ list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
+@@ -570,19 +578,15 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+ iommu_tce_direction(tce));
+
+ if (ret != H_SUCCESS) {
+- kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl,
+- entry);
+- goto invalidate_exit;
++ kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl,
++ entry + i);
++ goto unlock_exit;
+ }
+ }
+
+ kvmppc_rm_tce_put(stt, entry + i, tce);
+ }
+
+-invalidate_exit:
+- list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
+- iommu_tce_kill_rm(stit->tbl, entry, npages);
+-
+ unlock_exit:
+ if (!prereg)
+ arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock);
+@@ -620,20 +624,16 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
+ continue;
+
+ if (ret == H_TOO_HARD)
+- goto invalidate_exit;
++ return ret;
+
+ WARN_ON_ONCE_RM(1);
+- kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
++ kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i);
+ }
+ }
+
+ for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
+ kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value);
+
+-invalidate_exit:
+- list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
+- iommu_tce_kill_rm(stit->tbl, ioba >> stt->page_shift, npages);
+-
+ return ret;
+ }
+
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
-index 2acb1c96cfafd..a2fd1db29f7e8 100644
+index 2acb1c96cfafd..7fa6857116690 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1731,7 +1731,6 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
@@ -12893,6 +18785,19 @@ index 2acb1c96cfafd..a2fd1db29f7e8 100644
if (!slot->arch.rmap)
return -ENOMEM;
}
+@@ -6072,8 +6101,11 @@ static int kvmppc_book3s_init_hv(void)
+ if (r)
+ return r;
+
+- if (kvmppc_radix_possible())
++ if (kvmppc_radix_possible()) {
+ r = kvmppc_radix_init();
++ if (r)
++ return r;
++ }
+
+ r = kvmppc_uvmem_init();
+ if (r < 0)
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index fcf4760a3a0ea..70b7a8f971538 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -12987,6 +18892,28 @@ index 977801c83aff8..8c15c90dd3a97 100644
local_irq_enable();
+diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
+index b4e6f70b97b94..ee305455bd8db 100644
+--- a/arch/powerpc/kvm/powerpc.c
++++ b/arch/powerpc/kvm/powerpc.c
+@@ -1507,7 +1507,7 @@ int kvmppc_handle_vmx_load(struct kvm_vcpu *vcpu,
+ {
+ enum emulation_result emulated = EMULATE_DONE;
+
+- if (vcpu->arch.mmio_vsx_copy_nums > 2)
++ if (vcpu->arch.mmio_vmx_copy_nums > 2)
+ return EMULATE_FAIL;
+
+ while (vcpu->arch.mmio_vmx_copy_nums) {
+@@ -1604,7 +1604,7 @@ int kvmppc_handle_vmx_store(struct kvm_vcpu *vcpu,
+ unsigned int index = rs & KVM_MMIO_REG_MASK;
+ enum emulation_result emulated = EMULATE_DONE;
+
+- if (vcpu->arch.mmio_vsx_copy_nums > 2)
++ if (vcpu->arch.mmio_vmx_copy_nums > 2)
+ return EMULATE_FAIL;
+
+ vcpu->arch.io_gpr = rs;
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 99a7c9132422c..54be64203b2ab 100644
--- a/arch/powerpc/lib/Makefile
@@ -13052,10 +18979,44 @@ index cda17bee5afea..c3e06922468b3 100644
void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
-index d8d5f901cee1c..d8cc49f39fe47 100644
+index d8d5f901cee1c..2d39b7c246e30 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
-@@ -3181,12 +3181,14 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
+@@ -112,9 +112,9 @@ static nokprobe_inline long address_ok(struct pt_regs *regs,
+ {
+ if (!user_mode(regs))
+ return 1;
+- if (__access_ok(ea, nb))
++ if (access_ok((void __user *)ea, nb))
+ return 1;
+- if (__access_ok(ea, 1))
++ if (access_ok((void __user *)ea, 1))
+ /* Access overlaps the end of the user region */
+ regs->dar = TASK_SIZE_MAX - 1;
+ else
+@@ -1014,7 +1014,10 @@ NOKPROBE_SYMBOL(emulate_dcbz);
+
+ #define __put_user_asmx(x, addr, err, op, cr) \
+ __asm__ __volatile__( \
++ ".machine push\n" \
++ ".machine power8\n" \
+ "1: " op " %2,0,%3\n" \
++ ".machine pop\n" \
+ " mfcr %1\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+@@ -1027,7 +1030,10 @@ NOKPROBE_SYMBOL(emulate_dcbz);
+
+ #define __get_user_asmx(x, addr, err, op) \
+ __asm__ __volatile__( \
++ ".machine push\n" \
++ ".machine power8\n" \
+ "1: "op" %1,0,%2\n" \
++ ".machine pop\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,%3\n" \
+@@ -3181,12 +3187,14 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
case BARRIER_EIEIO:
eieio();
break;
@@ -13070,6 +19031,15 @@ index d8d5f901cee1c..d8cc49f39fe47 100644
}
break;
+@@ -3304,7 +3312,7 @@ int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op)
+ __put_user_asmx(op->val, ea, err, "stbcx.", cr);
+ break;
+ case 2:
+- __put_user_asmx(op->val, ea, err, "stbcx.", cr);
++ __put_user_asmx(op->val, ea, err, "sthcx.", cr);
+ break;
+ #endif
+ case 4:
diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c
index 27061583a0107..203735caf6915 100644
--- a/arch/powerpc/mm/book3s32/mmu.c
@@ -13124,6 +19094,98 @@ index 27061583a0107..203735caf6915 100644
if ((top - base) > size) {
size <<= 1;
if (strict_kernel_rwx_enabled() && base + size > border)
+diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
+index c145776d3ae5e..7bfd88c4b5470 100644
+--- a/arch/powerpc/mm/book3s64/hash_utils.c
++++ b/arch/powerpc/mm/book3s64/hash_utils.c
+@@ -1522,8 +1522,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
+ }
+ EXPORT_SYMBOL_GPL(hash_page);
+
+-DECLARE_INTERRUPT_HANDLER(__do_hash_fault);
+-DEFINE_INTERRUPT_HANDLER(__do_hash_fault)
++DEFINE_INTERRUPT_HANDLER(do_hash_fault)
+ {
+ unsigned long ea = regs->dar;
+ unsigned long dsisr = regs->dsisr;
+@@ -1582,35 +1581,6 @@ DEFINE_INTERRUPT_HANDLER(__do_hash_fault)
+ }
+ }
+
+-/*
+- * The _RAW interrupt entry checks for the in_nmi() case before
+- * running the full handler.
+- */
+-DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault)
+-{
+- /*
+- * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then
+- * don't call hash_page, just fail the fault. This is required to
+- * prevent re-entrancy problems in the hash code, namely perf
+- * interrupts hitting while something holds H_PAGE_BUSY, and taking a
+- * hash fault. See the comment in hash_preload().
+- *
+- * We come here as a result of a DSI at a point where we don't want
+- * to call hash_page, such as when we are accessing memory (possibly
+- * user memory) inside a PMU interrupt that occurred while interrupts
+- * were soft-disabled. We want to invoke the exception handler for
+- * the access, or panic if there isn't a handler.
+- */
+- if (unlikely(in_nmi())) {
+- do_bad_page_fault_segv(regs);
+- return 0;
+- }
+-
+- __do_hash_fault(regs);
+-
+- return 0;
+-}
+-
+ #ifdef CONFIG_PPC_MM_SLICES
+ static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
+ {
+@@ -1677,26 +1647,18 @@ static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
+ #endif /* CONFIG_PPC_64K_PAGES */
+
+ /*
+- * __hash_page_* must run with interrupts off, as it sets the
+- * H_PAGE_BUSY bit. It's possible for perf interrupts to hit at any
+- * time and may take a hash fault reading the user stack, see
+- * read_user_stack_slow() in the powerpc/perf code.
+- *
+- * If that takes a hash fault on the same page as we lock here, it
+- * will bail out when seeing H_PAGE_BUSY set, and retry the access
+- * leading to an infinite loop.
++ * __hash_page_* must run with interrupts off, including PMI interrupts
++ * off, as it sets the H_PAGE_BUSY bit.
+ *
+- * Disabling interrupts here does not prevent perf interrupts, but it
+- * will prevent them taking hash faults (see the NMI test in
+- * do_hash_page), then read_user_stack's copy_from_user_nofault will
+- * fail and perf will fall back to read_user_stack_slow(), which
+- * walks the Linux page tables.
++ * It's otherwise possible for perf interrupts to hit at any time and
++ * may take a hash fault reading the user stack, which could take a
++ * hash miss and deadlock on the same H_PAGE_BUSY bit.
+ *
+ * Interrupts must also be off for the duration of the
+ * mm_is_thread_local test and update, to prevent preempt running the
+ * mm on another CPU (XXX: this may be racy vs kthread_use_mm).
+ */
+- local_irq_save(flags);
++ powerpc_local_irq_pmu_save(flags);
+
+ /* Is that local to this CPU ? */
+ if (mm_is_thread_local(mm))
+@@ -1721,7 +1683,7 @@ static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
+ mm_ctx_user_psize(&mm->context),
+ pte_val(*ptep));
+
+- local_irq_restore(flags);
++ powerpc_local_irq_pmu_restore(flags);
+ }
+
+ /*
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index ae20add7954a0..795d18a84f556 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -13146,6 +19208,39 @@ index ae20add7954a0..795d18a84f556 100644
pmd_clear(pmd);
return 1;
}
+diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
+index a8d0ce85d39ad..4a15172dfef29 100644
+--- a/arch/powerpc/mm/fault.c
++++ b/arch/powerpc/mm/fault.c
+@@ -568,18 +568,24 @@ NOKPROBE_SYMBOL(hash__do_page_fault);
+ static void __bad_page_fault(struct pt_regs *regs, int sig)
+ {
+ int is_write = page_fault_is_write(regs->dsisr);
++ const char *msg;
+
+ /* kernel has accessed a bad area */
+
++ if (regs->dar < PAGE_SIZE)
++ msg = "Kernel NULL pointer dereference";
++ else
++ msg = "Unable to handle kernel data access";
++
+ switch (TRAP(regs)) {
+ case INTERRUPT_DATA_STORAGE:
+- case INTERRUPT_DATA_SEGMENT:
+ case INTERRUPT_H_DATA_STORAGE:
+- pr_alert("BUG: %s on %s at 0x%08lx\n",
+- regs->dar < PAGE_SIZE ? "Kernel NULL pointer dereference" :
+- "Unable to handle kernel data access",
++ pr_alert("BUG: %s on %s at 0x%08lx\n", msg,
+ is_write ? "write" : "read", regs->dar);
+ break;
++ case INTERRUPT_DATA_SEGMENT:
++ pr_alert("BUG: %s at 0x%08lx\n", msg, regs->dar);
++ break;
+ case INTERRUPT_INST_STORAGE:
+ case INTERRUPT_INST_SEGMENT:
+ pr_alert("BUG: Unable to handle kernel instruction fetch%s",
diff --git a/arch/powerpc/mm/kasan/book3s_32.c b/arch/powerpc/mm/kasan/book3s_32.c
index 202bd260a0095..450a67ef0bbe1 100644
--- a/arch/powerpc/mm/kasan/book3s_32.c
@@ -13229,6 +19324,25 @@ index 202bd260a0095..450a67ef0bbe1 100644
+
return 0;
}
+diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/kasan_init_32.c
+index cf8770b1a692e..f3e4d069e0ba7 100644
+--- a/arch/powerpc/mm/kasan/kasan_init_32.c
++++ b/arch/powerpc/mm/kasan/kasan_init_32.c
+@@ -83,13 +83,12 @@ void __init
+ kasan_update_early_region(unsigned long k_start, unsigned long k_end, pte_t pte)
+ {
+ unsigned long k_cur;
+- phys_addr_t pa = __pa(kasan_early_shadow_page);
+
+ for (k_cur = k_start; k_cur != k_end; k_cur += PAGE_SIZE) {
+ pmd_t *pmd = pmd_off_k(k_cur);
+ pte_t *ptep = pte_offset_kernel(pmd, k_cur);
+
+- if ((pte_val(*ptep) & PTE_RPN_MASK) != pa)
++ if (pte_page(*ptep) != virt_to_page(lm_alias(kasan_early_shadow_page)))
+ continue;
+
+ __set_pte_at(&init_mm, k_cur, ptep, pte, 0);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index c3c4e31462eca..05b9c3f31456c 100644
--- a/arch/powerpc/mm/mem.c
@@ -13284,7 +19398,7 @@ index bf24451f3e71f..9235e720e3572 100644
ld r14,EX_TLB_DEAR(r12)
ld r15,EX_TLB_ESR(r12)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
-index 6f14c8fb6359d..59d3cfcd78879 100644
+index 6f14c8fb6359d..5fb829256b59d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -376,9 +376,9 @@ static void initialize_form2_numa_distance_lookup_table(void)
@@ -13363,6 +19477,132 @@ index 6f14c8fb6359d..59d3cfcd78879 100644
of_node_put(root);
}
+@@ -960,7 +956,9 @@ static int __init parse_numa_properties(void)
+ of_node_put(cpu);
+ }
+
+- node_set_online(nid);
++ /* node_set_online() is an UB if 'nid' is negative */
++ if (likely(nid >= 0))
++ node_set_online(nid);
+ }
+
+ get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
+diff --git a/arch/powerpc/mm/pageattr.c b/arch/powerpc/mm/pageattr.c
+index edea388e9d3fb..85753e32a4de9 100644
+--- a/arch/powerpc/mm/pageattr.c
++++ b/arch/powerpc/mm/pageattr.c
+@@ -15,12 +15,14 @@
+ #include <asm/pgtable.h>
+
+
++static pte_basic_t pte_update_delta(pte_t *ptep, unsigned long addr,
++ unsigned long old, unsigned long new)
++{
++ return pte_update(&init_mm, addr, ptep, old & ~new, new & ~old, 0);
++}
++
+ /*
+- * Updates the attributes of a page in three steps:
+- *
+- * 1. take the page_table_lock
+- * 2. install the new entry with the updated attributes
+- * 3. flush the TLB
++ * Updates the attributes of a page atomically.
+ *
+ * This sequence is safe against concurrent updates, and also allows updating the
+ * attributes of a page currently being executed or accessed.
+@@ -28,41 +30,39 @@
+ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
+ {
+ long action = (long)data;
+- pte_t pte;
+
+- spin_lock(&init_mm.page_table_lock);
+-
+- pte = ptep_get(ptep);
+-
+- /* modify the PTE bits as desired, then apply */
++ /* modify the PTE bits as desired */
+ switch (action) {
+ case SET_MEMORY_RO:
+- pte = pte_wrprotect(pte);
++ /* Don't clear DIRTY bit */
++ pte_update_delta(ptep, addr, _PAGE_KERNEL_RW & ~_PAGE_DIRTY, _PAGE_KERNEL_RO);
+ break;
+ case SET_MEMORY_RW:
+- pte = pte_mkwrite(pte_mkdirty(pte));
++ pte_update_delta(ptep, addr, _PAGE_KERNEL_RO, _PAGE_KERNEL_RW);
+ break;
+ case SET_MEMORY_NX:
+- pte = pte_exprotect(pte);
++ pte_update_delta(ptep, addr, _PAGE_KERNEL_ROX, _PAGE_KERNEL_RO);
+ break;
+ case SET_MEMORY_X:
+- pte = pte_mkexec(pte);
++ pte_update_delta(ptep, addr, _PAGE_KERNEL_RO, _PAGE_KERNEL_ROX);
++ break;
++ case SET_MEMORY_NP:
++ pte_update(&init_mm, addr, ptep, _PAGE_PRESENT, 0, 0);
++ break;
++ case SET_MEMORY_P:
++ pte_update(&init_mm, addr, ptep, 0, _PAGE_PRESENT, 0);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+- pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);
+-
+ /* See ptesync comment in radix__set_pte_at() */
+ if (radix_enabled())
+ asm volatile("ptesync": : :"memory");
+
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+
+- spin_unlock(&init_mm.page_table_lock);
+-
+ return 0;
+ }
+
+@@ -96,36 +96,3 @@ int change_memory_attr(unsigned long addr, int numpages, long action)
+ return apply_to_existing_page_range(&init_mm, start, size,
+ change_page_attr, (void *)action);
+ }
+-
+-/*
+- * Set the attributes of a page:
+- *
+- * This function is used by PPC32 at the end of init to set final kernel memory
+- * protection. It includes changing the maping of the page it is executing from
+- * and data pages it is using.
+- */
+-static int set_page_attr(pte_t *ptep, unsigned long addr, void *data)
+-{
+- pgprot_t prot = __pgprot((unsigned long)data);
+-
+- spin_lock(&init_mm.page_table_lock);
+-
+- set_pte_at(&init_mm, addr, ptep, pte_modify(*ptep, prot));
+- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+-
+- spin_unlock(&init_mm.page_table_lock);
+-
+- return 0;
+-}
+-
+-int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot)
+-{
+- unsigned long start = ALIGN_DOWN(addr, PAGE_SIZE);
+- unsigned long sz = numpages * PAGE_SIZE;
+-
+- if (numpages <= 0)
+- return 0;
+-
+- return apply_to_existing_page_range(&init_mm, start, sz, set_page_attr,
+- (void *)pgprot_val(prot));
+-}
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index cd16b407f47e1..9a93c1a5aa1d1 100644
--- a/arch/powerpc/mm/pgtable.c
@@ -13384,10 +19624,48 @@ index cd16b407f47e1..9a93c1a5aa1d1 100644
* This is called when relaxing access to a PTE. It's also called in the page
* fault path when we don't hit any of the major fault cases, ie, a minor
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
-index dcf5ecca19d99..fde1ed445ca46 100644
+index dcf5ecca19d99..f288597714407 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
-@@ -173,7 +173,7 @@ void mark_rodata_ro(void)
+@@ -138,10 +138,12 @@ 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))
++ if (v_block_mapped((unsigned long)_sinittext)) {
+ mmu_mark_initmem_nx();
+- else
+- set_memory_attr((unsigned long)_sinittext, numpages, PAGE_KERNEL);
++ } else {
++ set_memory_nx((unsigned long)_sinittext, numpages);
++ set_memory_rw((unsigned long)_sinittext, numpages);
++ }
+ }
+
+ #ifdef CONFIG_STRICT_KERNEL_RWX
+@@ -155,25 +157,21 @@ void mark_rodata_ro(void)
+ return;
+ }
+
+- numpages = PFN_UP((unsigned long)_etext) -
+- PFN_DOWN((unsigned long)_stext);
+-
+- set_memory_attr((unsigned long)_stext, numpages, PAGE_KERNEL_ROX);
+ /*
+- * mark .rodata as read only. Use __init_begin rather than __end_rodata
+- * to cover NOTES and EXCEPTION_TABLE.
++ * mark .text and .rodata as read only. Use __init_begin rather than
++ * __end_rodata to cover NOTES and EXCEPTION_TABLE.
+ */
+ numpages = PFN_UP((unsigned long)__init_begin) -
+- PFN_DOWN((unsigned long)__start_rodata);
++ PFN_DOWN((unsigned long)_stext);
+
+- set_memory_attr((unsigned long)__start_rodata, numpages, PAGE_KERNEL_RO);
++ set_memory_ro((unsigned long)_stext, numpages);
+
+ // mark_initmem_nx() should have already run by now
+ ptdump_check_wx();
}
#endif
@@ -13396,6 +19674,17 @@ index dcf5ecca19d99..fde1ed445ca46 100644
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
unsigned long addr = (unsigned long)page_address(page);
+@@ -182,8 +180,8 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
+ return;
+
+ if (enable)
+- set_memory_attr(addr, numpages, PAGE_KERNEL);
++ set_memory_p(addr, numpages);
+ else
+- set_memory_attr(addr, numpages, __pgprot(0));
++ set_memory_np(addr, numpages);
+ }
+ #endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 78c8cf01db5f9..175aabf101e87 100644
--- a/arch/powerpc/mm/pgtable_64.c
@@ -13616,6 +19905,93 @@ index 8b5157ccfebae..57e1b6680365c 100644
break;
/*
+diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
+index 2f46e31c76129..4f53d0b97539b 100644
+--- a/arch/powerpc/perf/Makefile
++++ b/arch/powerpc/perf/Makefile
+@@ -3,11 +3,11 @@
+ obj-y += callchain.o callchain_$(BITS).o perf_regs.o
+ obj-$(CONFIG_COMPAT) += callchain_32.o
+
+-obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o
++obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o
+ obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \
+ power5+-pmu.o power6-pmu.o power7-pmu.o \
+ isa207-common.o power8-pmu.o power9-pmu.o \
+- generic-compat-pmu.o power10-pmu.o
++ generic-compat-pmu.o power10-pmu.o bhrb.o
+ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
+
+ obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o
+diff --git a/arch/powerpc/perf/callchain.h b/arch/powerpc/perf/callchain.h
+index d6fa6e25234f4..19a8d051ddf10 100644
+--- a/arch/powerpc/perf/callchain.h
++++ b/arch/powerpc/perf/callchain.h
+@@ -2,7 +2,6 @@
+ #ifndef _POWERPC_PERF_CALLCHAIN_H
+ #define _POWERPC_PERF_CALLCHAIN_H
+
+-int read_user_stack_slow(const void __user *ptr, void *buf, int nb);
+ void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
+ struct pt_regs *regs);
+ void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
+@@ -26,17 +25,11 @@ static inline int __read_user_stack(const void __user *ptr, void *ret,
+ size_t size)
+ {
+ unsigned long addr = (unsigned long)ptr;
+- int rc;
+
+ if (addr > TASK_SIZE - size || (addr & (size - 1)))
+ return -EFAULT;
+
+- rc = copy_from_user_nofault(ret, ptr, size);
+-
+- if (IS_ENABLED(CONFIG_PPC64) && !radix_enabled() && rc)
+- return read_user_stack_slow(ptr, ret, size);
+-
+- return rc;
++ return copy_from_user_nofault(ret, ptr, size);
+ }
+
+ #endif /* _POWERPC_PERF_CALLCHAIN_H */
+diff --git a/arch/powerpc/perf/callchain_64.c b/arch/powerpc/perf/callchain_64.c
+index 8d0df4226328d..488e8a21a11ea 100644
+--- a/arch/powerpc/perf/callchain_64.c
++++ b/arch/powerpc/perf/callchain_64.c
+@@ -18,33 +18,6 @@
+
+ #include "callchain.h"
+
+-/*
+- * On 64-bit we don't want to invoke hash_page on user addresses from
+- * interrupt context, so if the access faults, we read the page tables
+- * to find which page (if any) is mapped and access it directly. Radix
+- * has no need for this so it doesn't use read_user_stack_slow.
+- */
+-int read_user_stack_slow(const void __user *ptr, void *buf, int nb)
+-{
+-
+- unsigned long addr = (unsigned long) ptr;
+- unsigned long offset;
+- struct page *page;
+- void *kaddr;
+-
+- if (get_user_page_fast_only(addr, FOLL_WRITE, &page)) {
+- kaddr = page_address(page);
+-
+- /* align address to page boundary */
+- offset = addr & ~PAGE_MASK;
+-
+- memcpy(buf, kaddr + offset, nb);
+- put_page(page);
+- return 0;
+- }
+- return -EFAULT;
+-}
+-
+ static int read_user_stack_64(const unsigned long __user *ptr, unsigned long *ret)
+ {
+ return __read_user_stack(ptr, ret, sizeof(*ret));
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 73e62e9b179bc..e78de70509472 100644
--- a/arch/powerpc/perf/core-book3s.c
@@ -13735,6 +20111,23 @@ index 73e62e9b179bc..e78de70509472 100644
if (unlikely(!found) && !arch_irq_disabled_regs(regs))
printk_ratelimited(KERN_WARNING "Can't find PMC that caused IRQ\n");
+diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
+index e106909ff9c37..e7583fbcc8fa1 100644
+--- a/arch/powerpc/perf/imc-pmu.c
++++ b/arch/powerpc/perf/imc-pmu.c
+@@ -1457,7 +1457,11 @@ static int trace_imc_event_init(struct perf_event *event)
+
+ event->hw.idx = -1;
+
+- event->pmu->task_ctx_nr = perf_hw_context;
++ /*
++ * There can only be a single PMU for perf_hw_context events which is assigned to
++ * core PMU. Hence use "perf_sw_context" for trace_imc.
++ */
++ event->pmu->task_ctx_nr = perf_sw_context;
+ event->destroy = reset_global_refc;
+ return 0;
+ }
diff --git a/arch/powerpc/perf/power10-events-list.h b/arch/powerpc/perf/power10-events-list.h
index 93be7197d2502..564f14097f07b 100644
--- a/arch/powerpc/perf/power10-events-list.h
@@ -13764,7 +20157,7 @@ index 93be7197d2502..564f14097f07b 100644
/*
* Memory Access Events
diff --git a/arch/powerpc/perf/power10-pmu.c b/arch/powerpc/perf/power10-pmu.c
-index f9d64c63bb4a7..9dd75f3858372 100644
+index f9d64c63bb4a7..07ca62d084d9d 100644
--- a/arch/powerpc/perf/power10-pmu.c
+++ b/arch/powerpc/perf/power10-pmu.c
@@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK;
@@ -13773,8 +20166,8 @@ index f9d64c63bb4a7..9dd75f3858372 100644
static const unsigned int power10_event_alternatives[][MAX_ALT] = {
- { PM_RUN_CYC_ALT, PM_RUN_CYC },
- { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
-+ { PM_CYC_ALT, PM_CYC },
+ { PM_INST_CMPL_ALT, PM_INST_CMPL },
++ { PM_CYC_ALT, PM_CYC },
};
static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[])
@@ -13867,6 +20260,26 @@ index f9d64c63bb4a7..9dd75f3858372 100644
.config_bhrb = power10_config_bhrb,
.bhrb_filter_map = power10_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
+diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
+index ff3382140d7e6..cbdd074ee2a70 100644
+--- a/arch/powerpc/perf/power9-pmu.c
++++ b/arch/powerpc/perf/power9-pmu.c
+@@ -133,11 +133,11 @@ int p9_dd22_bl_ev[] = {
+
+ /* Table of alternatives, sorted by column 0 */
+ static const unsigned int power9_event_alternatives[][MAX_ALT] = {
+- { PM_INST_DISP, PM_INST_DISP_ALT },
+- { PM_RUN_CYC_ALT, PM_RUN_CYC },
+- { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
+- { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
+ { PM_BR_2PATH, PM_BR_2PATH_ALT },
++ { PM_INST_DISP, PM_INST_DISP_ALT },
++ { PM_RUN_CYC_ALT, PM_RUN_CYC },
++ { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
++ { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
+ };
+
+ static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[])
diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c
index b299e43f5ef94..823397c802def 100644
--- a/arch/powerpc/platforms/44x/fsp2.c
@@ -14011,6 +20424,39 @@ index c6df294054fe9..d7081e9af65c7 100644
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC_CORE
+diff --git a/arch/powerpc/platforms/8xx/pic.c b/arch/powerpc/platforms/8xx/pic.c
+index f2ba837249d69..04a6abf14c295 100644
+--- a/arch/powerpc/platforms/8xx/pic.c
++++ b/arch/powerpc/platforms/8xx/pic.c
+@@ -153,6 +153,7 @@ int __init mpc8xx_pic_init(void)
+ if (mpc8xx_pic_host == NULL) {
+ printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
+ ret = -ENOMEM;
++ goto out;
+ }
+
+ ret = 0;
+diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
+index a208997ade88b..87a95cbff2f3f 100644
+--- a/arch/powerpc/platforms/Kconfig.cputype
++++ b/arch/powerpc/platforms/Kconfig.cputype
+@@ -111,6 +111,7 @@ config PPC_BOOK3S_64
+
+ config PPC_BOOK3E_64
+ bool "Embedded processors"
++ select PPC_FSL_BOOK3E
+ select PPC_FPU # Make it a choice ?
+ select PPC_SMP_MUXED_IPI
+ select PPC_DOORBELL
+@@ -287,7 +288,7 @@ config FSL_BOOKE
+ config PPC_FSL_BOOK3E
+ bool
+ select ARCH_SUPPORTS_HUGETLBFS if PHYS_64BIT || PPC64
+- select FSL_EMB_PERFMON
++ imply FSL_EMB_PERFMON
+ select PPC_SMP_MUXED_IPI
+ select PPC_DOORBELL
+ default y if FSL_BOOKE
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 30172e52e16b7..4d82c92ddd523 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
@@ -14155,6 +20601,23 @@ index a191f4c60ce71..113bdb151f687 100644
return 0;
}
+diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
+index 72c25295c1c2b..69c344c8884f3 100644
+--- a/arch/powerpc/platforms/powernv/rng.c
++++ b/arch/powerpc/platforms/powernv/rng.c
+@@ -43,7 +43,11 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+ unsigned long parity;
+
+ /* Calculate the parity of the value */
+- asm ("popcntd %0,%1" : "=r" (parity) : "r" (val));
++ asm (".machine push; \
++ .machine power7; \
++ popcntd %0,%1; \
++ .machine pop;"
++ : "=r" (parity) : "r" (val));
+
+ /* xor our value with the previous mask */
+ val ^= rng->mask;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index a52af8fbf5711..8322ca86d5acf 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
@@ -14240,6 +20703,28 @@ index e83e0891272d3..210a37a065fb7 100644
rc = dlpar_attach_node(dn, parent_dn);
if (rc)
dlpar_free_cc_nodes(dn);
+diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
+index 90c9d3531694b..4ba8245681192 100644
+--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
+@@ -78,6 +78,9 @@ int remove_phb_dynamic(struct pci_controller *phb)
+
+ pseries_msi_free_domains(phb);
+
++ /* Keep a reference so phb isn't freed yet */
++ get_device(&host_bridge->dev);
++
+ /* Remove the PCI bus and unregister the bridge device from sysfs */
+ phb->bus = NULL;
+ pci_remove_bus(b);
+@@ -101,6 +104,7 @@ int remove_phb_dynamic(struct pci_controller *phb)
+ * the pcibios_free_controller_deferred() callback;
+ * see pseries_root_bridge_prepare().
+ */
++ put_device(&host_bridge->dev);
+
+ return 0;
+ }
diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S
index efeeb1b885a17..329b9c4ae5429 100644
--- a/arch/powerpc/sysdev/dcr-low.S
@@ -14253,6 +20738,28 @@ index efeeb1b885a17..329b9c4ae5429 100644
rlwinm r3,r3,4,18,27; \
lis r5,table@h; \
ori r5,r5,table@l; \
+diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
+index 8963eaffb1b7b..39186ad6b3c3a 100644
+--- a/arch/powerpc/sysdev/fsl_gtm.c
++++ b/arch/powerpc/sysdev/fsl_gtm.c
+@@ -86,7 +86,7 @@ static LIST_HEAD(gtms);
+ */
+ struct gtm_timer *gtm_get_timer16(void)
+ {
+- struct gtm *gtm = NULL;
++ struct gtm *gtm;
+ int i;
+
+ list_for_each_entry(gtm, &gtms, list_node) {
+@@ -103,7 +103,7 @@ struct gtm_timer *gtm_get_timer16(void)
+ spin_unlock_irq(&gtm->lock);
+ }
+
+- if (gtm)
++ if (!list_empty(&gtms))
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+ }
diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig
index 97796c6b63f04..785c292d104b7 100644
--- a/arch/powerpc/sysdev/xive/Kconfig
@@ -14293,6 +20800,28 @@ index f143b6f111ac0..1179632560b8d 100644
list_for_each_entry(xibm, &xive_irq_bitmaps, list) {
memset(buf, 0, PAGE_SIZE);
bitmap_print_to_pagebuf(true, buf, xibm->bitmap, xibm->count);
+diff --git a/arch/powerpc/tools/relocs_check.sh b/arch/powerpc/tools/relocs_check.sh
+index 014e00e74d2b6..63792af004170 100755
+--- a/arch/powerpc/tools/relocs_check.sh
++++ b/arch/powerpc/tools/relocs_check.sh
+@@ -39,6 +39,7 @@ $objdump -R "$vmlinux" |
+ # R_PPC_NONE
+ grep -F -w -v 'R_PPC64_RELATIVE
+ R_PPC64_NONE
++R_PPC64_UADDR64
+ R_PPC_ADDR16_LO
+ R_PPC_ADDR16_HI
+ R_PPC_ADDR16_HA
+@@ -54,9 +55,3 @@ fi
+ num_bad=$(echo "$bad_relocs" | wc -l)
+ echo "WARNING: $num_bad bad relocations"
+ echo "$bad_relocs"
+-
+-# If we see this type of relocation it's an idication that
+-# we /may/ be using an old version of binutils.
+-if echo "$bad_relocs" | grep -q -F -w R_PPC64_UADDR64; then
+- echo "WARNING: You need at least binutils >= 2.19 to build a CONFIG_RELOCATABLE kernel"
+-fi
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index dd8241c009e53..8b28ff9d98d16 100644
--- a/arch/powerpc/xmon/xmon.c
@@ -14349,6 +20878,33 @@ index f076cee11af69..20bc4b8c13b92 100644
config SMP
bool "Symmetric Multi-Processing"
help
+diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
+index b44d6ecdb46e5..0aacd7052585b 100644
+--- a/arch/riscv/Kconfig.erratas
++++ b/arch/riscv/Kconfig.erratas
+@@ -2,6 +2,7 @@ menu "CPU errata selection"
+
+ config RISCV_ERRATA_ALTERNATIVE
+ bool "RISC-V alternative scheme"
++ depends on !XIP_KERNEL
+ default y
+ help
+ This Kconfig allows the kernel to automatically patch the
+diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
+index 30676ebb16ebd..46a534f047931 100644
+--- a/arch/riscv/Kconfig.socs
++++ b/arch/riscv/Kconfig.socs
+@@ -14,8 +14,8 @@ config SOC_SIFIVE
+ select CLK_SIFIVE
+ select CLK_SIFIVE_PRCI
+ select SIFIVE_PLIC
+- select RISCV_ERRATA_ALTERNATIVE
+- select ERRATA_SIFIVE
++ select RISCV_ERRATA_ALTERNATIVE if !XIP_KERNEL
++ select ERRATA_SIFIVE if !XIP_KERNEL
+ help
+ This enables support for SiFive SoC platform hardware.
+
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 0eb4568fbd290..e03f45f7711aa 100644
--- a/arch/riscv/Makefile
@@ -14380,6 +20936,72 @@ index 0eb4568fbd290..e03f45f7711aa 100644
ifneq ($(CONFIG_XIP_KERNEL),y)
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
+diff --git a/arch/riscv/boot/dts/canaan/k210.dtsi b/arch/riscv/boot/dts/canaan/k210.dtsi
+index 5e8ca81424821..780416d489aa7 100644
+--- a/arch/riscv/boot/dts/canaan/k210.dtsi
++++ b/arch/riscv/boot/dts/canaan/k210.dtsi
+@@ -113,7 +113,8 @@
+ compatible = "canaan,k210-plic", "sifive,plic-1.0.0";
+ reg = <0xC000000 0x4000000>;
+ interrupt-controller;
+- interrupts-extended = <&cpu0_intc 11 &cpu1_intc 11>;
++ interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>,
++ <&cpu1_intc 11>, <&cpu1_intc 9>;
+ riscv,ndev = <65>;
+ };
+
+diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
+index 0bcaf35045e79..82e7f8069ae77 100644
+--- a/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
++++ b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
+@@ -203,6 +203,8 @@
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ m25p,fast-read;
+ broken-flash-reset;
+ };
+diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
+index ac8a03f5867ad..8d335233853a7 100644
+--- a/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
++++ b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
+@@ -205,6 +205,8 @@
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ m25p,fast-read;
+ broken-flash-reset;
+ };
+diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
+index 623998194bc18..6703cfc055887 100644
+--- a/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
++++ b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
+@@ -213,6 +213,8 @@
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ m25p,fast-read;
+ broken-flash-reset;
+ };
+diff --git a/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
+index cf605ba0d67e4..ac0b56f7d2c9f 100644
+--- a/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
++++ b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
+@@ -178,6 +178,8 @@
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ m25p,fast-read;
+ broken-flash-reset;
+ };
diff --git a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts
index b254c60589a1c..cce5eca31f257 100644
--- a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts
@@ -14472,6 +21094,19 @@ index 9d2fbbc1f7778..4ef4bcb748729 100644
max-frequency = <200000000>;
status = "disabled";
};
+diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+index 7db8610534834..64c06c9b41dc8 100644
+--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
++++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+@@ -166,7 +166,7 @@
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+- dma: dma@3000000 {
++ dma: dma-controller@3000000 {
+ compatible = "sifive,fu540-c000-pdma";
+ reg = <0x0 0x3000000 0x0 0x8000>;
+ interrupt-parent = <&plic0>;
diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
index 60846e88ae4b1..22f971e971614 100644
--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
@@ -14558,6 +21193,22 @@ index 49b398fe99f1b..cc4f6787f9371 100644
#else
#define efi_init()
#endif
+diff --git a/arch/riscv/include/asm/module.lds.h b/arch/riscv/include/asm/module.lds.h
+index 4254ff2ff0494..1075beae1ac64 100644
+--- a/arch/riscv/include/asm/module.lds.h
++++ b/arch/riscv/include/asm/module.lds.h
+@@ -2,8 +2,8 @@
+ /* Copyright (C) 2017 Andes Technology Corporation */
+ #ifdef CONFIG_MODULE_SECTIONS
+ SECTIONS {
+- .plt (NOLOAD) : { BYTE(0) }
+- .got (NOLOAD) : { BYTE(0) }
+- .got.plt (NOLOAD) : { BYTE(0) }
++ .plt : { BYTE(0) }
++ .got : { BYTE(0) }
++ .got.plt : { BYTE(0) }
+ }
+ #endif
diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index a7d2811f35365..62d0e6e61da83 100644
--- a/arch/riscv/include/asm/smp.h
@@ -14593,6 +21244,43 @@ index a7d2811f35365..62d0e6e61da83 100644
#if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
bool cpu_has_hotplug(unsigned int cpu);
#else
+diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
+index 60da0dcacf145..74d888c8d631a 100644
+--- a/arch/riscv/include/asm/thread_info.h
++++ b/arch/riscv/include/asm/thread_info.h
+@@ -11,11 +11,17 @@
+ #include <asm/page.h>
+ #include <linux/const.h>
+
++#ifdef CONFIG_KASAN
++#define KASAN_STACK_ORDER 1
++#else
++#define KASAN_STACK_ORDER 0
++#endif
++
+ /* thread information allocation */
+ #ifdef CONFIG_64BIT
+-#define THREAD_SIZE_ORDER (2)
++#define THREAD_SIZE_ORDER (2 + KASAN_STACK_ORDER)
+ #else
+-#define THREAD_SIZE_ORDER (1)
++#define THREAD_SIZE_ORDER (1 + KASAN_STACK_ORDER)
+ #endif
+ #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
+
+diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h
+index 507cae273bc62..d6a7428f6248d 100644
+--- a/arch/riscv/include/asm/timex.h
++++ b/arch/riscv/include/asm/timex.h
+@@ -41,7 +41,7 @@ static inline u32 get_cycles_hi(void)
+ static inline unsigned long random_get_entropy(void)
+ {
+ if (unlikely(clint_time_val == NULL))
+- return 0;
++ return random_get_entropy_fallback();
+ return get_cycles();
+ }
+ #define random_get_entropy() random_get_entropy()
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 3397ddac1a30c..16308ef1e5787 100644
--- a/arch/riscv/kernel/Makefile
@@ -14731,10 +21419,91 @@ index e6eca271a4d60..cbef0fc73afa8 100644
unsigned long fdt_addr = internal->fdt_addr;
void *control_code_buffer = page_address(image->control_code_page);
riscv_kexec_method kexec_method = NULL;
+diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
+index 68a9e3d1fe16a..4a48287513c37 100644
+--- a/arch/riscv/kernel/module.c
++++ b/arch/riscv/kernel/module.c
+@@ -13,6 +13,19 @@
+ #include <linux/pgtable.h>
+ #include <asm/sections.h>
+
++/*
++ * The auipc+jalr instruction pair can reach any PC-relative offset
++ * in the range [-2^31 - 2^11, 2^31 - 2^11)
++ */
++static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
++{
++#ifdef CONFIG_32BIT
++ return true;
++#else
++ return (-(1L << 31) - (1L << 11)) <= val && val < ((1L << 31) - (1L << 11));
++#endif
++}
++
+ static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
+ {
+ if (v != (u32)v) {
+@@ -95,7 +108,7 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
+ ptrdiff_t offset = (void *)v - (void *)location;
+ s32 hi20;
+
+- if (offset != (s32)offset) {
++ if (!riscv_insn_valid_32bit_offset(offset)) {
+ pr_err(
+ "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
+ me->name, (long long)v, location);
+@@ -197,10 +210,9 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
+ Elf_Addr v)
+ {
+ ptrdiff_t offset = (void *)v - (void *)location;
+- s32 fill_v = offset;
+ u32 hi20, lo12;
+
+- if (offset != fill_v) {
++ if (!riscv_insn_valid_32bit_offset(offset)) {
+ /* Only emit the plt entry if offset over 32-bit range */
+ if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
+ offset = module_emit_plt_entry(me, v);
+@@ -224,10 +236,9 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
+ Elf_Addr v)
+ {
+ ptrdiff_t offset = (void *)v - (void *)location;
+- s32 fill_v = offset;
+ u32 hi20, lo12;
+
+- if (offset != fill_v) {
++ if (!riscv_insn_valid_32bit_offset(offset)) {
+ pr_err(
+ "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
+ me->name, (long long)v, location);
+diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
+index 0b552873a5778..765004b605132 100644
+--- a/arch/riscv/kernel/patch.c
++++ b/arch/riscv/kernel/patch.c
+@@ -104,7 +104,7 @@ static int patch_text_cb(void *data)
+ struct patch_insn *patch = data;
+ int ret = 0;
+
+- if (atomic_inc_return(&patch->cpu_count) == 1) {
++ if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
+ ret =
+ patch_text_nosync(patch->addr, &patch->insn,
+ GET_INSN_LENGTH(patch->insn));
diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
-index 0bb1854dce833..8ecfc4c128bc5 100644
+index 0bb1854dce833..357f985041cb9 100644
--- a/arch/riscv/kernel/perf_callchain.c
+++ b/arch/riscv/kernel/perf_callchain.c
+@@ -15,8 +15,8 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
+ {
+ struct stackframe buftail;
+ unsigned long ra = 0;
+- unsigned long *user_frame_tail =
+- (unsigned long *)(fp - sizeof(struct stackframe));
++ unsigned long __user *user_frame_tail =
++ (unsigned long __user *)(fp - sizeof(struct stackframe));
+
+ /* Check accessibility of one struct frame_tail beyond */
+ if (!access_ok(user_frame_tail, sizeof(buftail)))
@@ -56,10 +56,11 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
@@ -14748,7 +21517,14 @@ index 0bb1854dce833..8ecfc4c128bc5 100644
return;
fp = regs->s0;
-@@ -78,8 +79,10 @@ static bool fill_callchain(void *entry, unsigned long pc)
+@@ -72,14 +73,16 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+
+ static bool fill_callchain(void *entry, unsigned long pc)
+ {
+- return perf_callchain_store(entry, pc);
++ return perf_callchain_store(entry, pc) == 0;
+ }
+
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
@@ -14885,6 +21661,385 @@ index 0000000000000..99fe67377e5ed
+void __trace_hardirqs_off(void);
+
+#endif /* __TRACE_IRQ_H */
+diff --git a/arch/riscv/lib/memmove.S b/arch/riscv/lib/memmove.S
+index 07d1d2152ba5c..e0609e1f0864d 100644
+--- a/arch/riscv/lib/memmove.S
++++ b/arch/riscv/lib/memmove.S
+@@ -1,64 +1,316 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2022 Michael T. Kloos <michael@michaelkloos.com>
++ */
+
+ #include <linux/linkage.h>
+ #include <asm/asm.h>
+
+-ENTRY(__memmove)
+-WEAK(memmove)
+- move t0, a0
+- move t1, a1
+-
+- beq a0, a1, exit_memcpy
+- beqz a2, exit_memcpy
+- srli t2, a2, 0x2
+-
+- slt t3, a0, a1
+- beqz t3, do_reverse
+-
+- andi a2, a2, 0x3
+- li t4, 1
+- beqz t2, byte_copy
+-
+-word_copy:
+- lw t3, 0(a1)
+- addi t2, t2, -1
+- addi a1, a1, 4
+- sw t3, 0(a0)
+- addi a0, a0, 4
+- bnez t2, word_copy
+- beqz a2, exit_memcpy
+- j byte_copy
+-
+-do_reverse:
+- add a0, a0, a2
+- add a1, a1, a2
+- andi a2, a2, 0x3
+- li t4, -1
+- beqz t2, reverse_byte_copy
+-
+-reverse_word_copy:
+- addi a1, a1, -4
+- addi t2, t2, -1
+- lw t3, 0(a1)
+- addi a0, a0, -4
+- sw t3, 0(a0)
+- bnez t2, reverse_word_copy
+- beqz a2, exit_memcpy
+-
+-reverse_byte_copy:
+- addi a0, a0, -1
+- addi a1, a1, -1
++SYM_FUNC_START(__memmove)
++SYM_FUNC_START_WEAK(memmove)
++ /*
++ * Returns
++ * a0 - dest
++ *
++ * Parameters
++ * a0 - Inclusive first byte of dest
++ * a1 - Inclusive first byte of src
++ * a2 - Length of copy n
++ *
++ * Because the return matches the parameter register a0,
++ * we will not clobber or modify that register.
++ *
++ * Note: This currently only works on little-endian.
++ * To port to big-endian, reverse the direction of shifts
++ * in the 2 misaligned fixup copy loops.
++ */
+
++ /* Return if nothing to do */
++ beq a0, a1, return_from_memmove
++ beqz a2, return_from_memmove
++
++ /*
++ * Register Uses
++ * Forward Copy: a1 - Index counter of src
++ * Reverse Copy: a4 - Index counter of src
++ * Forward Copy: t3 - Index counter of dest
++ * Reverse Copy: t4 - Index counter of dest
++ * Both Copy Modes: t5 - Inclusive first multibyte/aligned of dest
++ * Both Copy Modes: t6 - Non-Inclusive last multibyte/aligned of dest
++ * Both Copy Modes: t0 - Link / Temporary for load-store
++ * Both Copy Modes: t1 - Temporary for load-store
++ * Both Copy Modes: t2 - Temporary for load-store
++ * Both Copy Modes: a5 - dest to src alignment offset
++ * Both Copy Modes: a6 - Shift ammount
++ * Both Copy Modes: a7 - Inverse Shift ammount
++ * Both Copy Modes: a2 - Alternate breakpoint for unrolled loops
++ */
++
++ /*
++ * Solve for some register values now.
++ * Byte copy does not need t5 or t6.
++ */
++ mv t3, a0
++ add t4, a0, a2
++ add a4, a1, a2
++
++ /*
++ * Byte copy if copying less than (2 * SZREG) bytes. This can
++ * cause problems with the bulk copy implementation and is
++ * small enough not to bother.
++ */
++ andi t0, a2, -(2 * SZREG)
++ beqz t0, byte_copy
++
++ /*
++ * Now solve for t5 and t6.
++ */
++ andi t5, t3, -SZREG
++ andi t6, t4, -SZREG
++ /*
++ * If dest(Register t3) rounded down to the nearest naturally
++ * aligned SZREG address, does not equal dest, then add SZREG
++ * to find the low-bound of SZREG alignment in the dest memory
++ * region. Note that this could overshoot the dest memory
++ * region if n is less than SZREG. This is one reason why
++ * we always byte copy if n is less than SZREG.
++ * Otherwise, dest is already naturally aligned to SZREG.
++ */
++ beq t5, t3, 1f
++ addi t5, t5, SZREG
++ 1:
++
++ /*
++ * If the dest and src are co-aligned to SZREG, then there is
++ * no need for the full rigmarole of a full misaligned fixup copy.
++ * Instead, do a simpler co-aligned copy.
++ */
++ xor t0, a0, a1
++ andi t1, t0, (SZREG - 1)
++ beqz t1, coaligned_copy
++ /* Fall through to misaligned fixup copy */
++
++misaligned_fixup_copy:
++ bltu a1, a0, misaligned_fixup_copy_reverse
++
++misaligned_fixup_copy_forward:
++ jal t0, byte_copy_until_aligned_forward
++
++ andi a5, a1, (SZREG - 1) /* Find the alignment offset of src (a1) */
++ slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */
++ sub a5, a1, t3 /* Find the difference between src and dest */
++ andi a1, a1, -SZREG /* Align the src pointer */
++ addi a2, t6, SZREG /* The other breakpoint for the unrolled loop*/
++
++ /*
++ * Compute The Inverse Shift
++ * a7 = XLEN - a6 = XLEN + -a6
++ * 2s complement negation to find the negative: -a6 = ~a6 + 1
++ * Add that to XLEN. XLEN = SZREG * 8.
++ */
++ not a7, a6
++ addi a7, a7, (SZREG * 8 + 1)
++
++ /*
++ * Fix Misalignment Copy Loop - Forward
++ * load_val0 = load_ptr[0];
++ * do {
++ * load_val1 = load_ptr[1];
++ * store_ptr += 2;
++ * store_ptr[0 - 2] = (load_val0 >> {a6}) | (load_val1 << {a7});
++ *
++ * if (store_ptr == {a2})
++ * break;
++ *
++ * load_val0 = load_ptr[2];
++ * load_ptr += 2;
++ * store_ptr[1 - 2] = (load_val1 >> {a6}) | (load_val0 << {a7});
++ *
++ * } while (store_ptr != store_ptr_end);
++ * store_ptr = store_ptr_end;
++ */
++
++ REG_L t0, (0 * SZREG)(a1)
++ 1:
++ REG_L t1, (1 * SZREG)(a1)
++ addi t3, t3, (2 * SZREG)
++ srl t0, t0, a6
++ sll t2, t1, a7
++ or t2, t0, t2
++ REG_S t2, ((0 * SZREG) - (2 * SZREG))(t3)
++
++ beq t3, a2, 2f
++
++ REG_L t0, (2 * SZREG)(a1)
++ addi a1, a1, (2 * SZREG)
++ srl t1, t1, a6
++ sll t2, t0, a7
++ or t2, t1, t2
++ REG_S t2, ((1 * SZREG) - (2 * SZREG))(t3)
++
++ bne t3, t6, 1b
++ 2:
++ mv t3, t6 /* Fix the dest pointer in case the loop was broken */
++
++ add a1, t3, a5 /* Restore the src pointer */
++ j byte_copy_forward /* Copy any remaining bytes */
++
++misaligned_fixup_copy_reverse:
++ jal t0, byte_copy_until_aligned_reverse
++
++ andi a5, a4, (SZREG - 1) /* Find the alignment offset of src (a4) */
++ slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */
++ sub a5, a4, t4 /* Find the difference between src and dest */
++ andi a4, a4, -SZREG /* Align the src pointer */
++ addi a2, t5, -SZREG /* The other breakpoint for the unrolled loop*/
++
++ /*
++ * Compute The Inverse Shift
++ * a7 = XLEN - a6 = XLEN + -a6
++ * 2s complement negation to find the negative: -a6 = ~a6 + 1
++ * Add that to XLEN. XLEN = SZREG * 8.
++ */
++ not a7, a6
++ addi a7, a7, (SZREG * 8 + 1)
++
++ /*
++ * Fix Misalignment Copy Loop - Reverse
++ * load_val1 = load_ptr[0];
++ * do {
++ * load_val0 = load_ptr[-1];
++ * store_ptr -= 2;
++ * store_ptr[1] = (load_val0 >> {a6}) | (load_val1 << {a7});
++ *
++ * if (store_ptr == {a2})
++ * break;
++ *
++ * load_val1 = load_ptr[-2];
++ * load_ptr -= 2;
++ * store_ptr[0] = (load_val1 >> {a6}) | (load_val0 << {a7});
++ *
++ * } while (store_ptr != store_ptr_end);
++ * store_ptr = store_ptr_end;
++ */
++
++ REG_L t1, ( 0 * SZREG)(a4)
++ 1:
++ REG_L t0, (-1 * SZREG)(a4)
++ addi t4, t4, (-2 * SZREG)
++ sll t1, t1, a7
++ srl t2, t0, a6
++ or t2, t1, t2
++ REG_S t2, ( 1 * SZREG)(t4)
++
++ beq t4, a2, 2f
++
++ REG_L t1, (-2 * SZREG)(a4)
++ addi a4, a4, (-2 * SZREG)
++ sll t0, t0, a7
++ srl t2, t1, a6
++ or t2, t0, t2
++ REG_S t2, ( 0 * SZREG)(t4)
++
++ bne t4, t5, 1b
++ 2:
++ mv t4, t5 /* Fix the dest pointer in case the loop was broken */
++
++ add a4, t4, a5 /* Restore the src pointer */
++ j byte_copy_reverse /* Copy any remaining bytes */
++
++/*
++ * Simple copy loops for SZREG co-aligned memory locations.
++ * These also make calls to do byte copies for any unaligned
++ * data at their terminations.
++ */
++coaligned_copy:
++ bltu a1, a0, coaligned_copy_reverse
++
++coaligned_copy_forward:
++ jal t0, byte_copy_until_aligned_forward
++
++ 1:
++ REG_L t1, ( 0 * SZREG)(a1)
++ addi a1, a1, SZREG
++ addi t3, t3, SZREG
++ REG_S t1, (-1 * SZREG)(t3)
++ bne t3, t6, 1b
++
++ j byte_copy_forward /* Copy any remaining bytes */
++
++coaligned_copy_reverse:
++ jal t0, byte_copy_until_aligned_reverse
++
++ 1:
++ REG_L t1, (-1 * SZREG)(a4)
++ addi a4, a4, -SZREG
++ addi t4, t4, -SZREG
++ REG_S t1, ( 0 * SZREG)(t4)
++ bne t4, t5, 1b
++
++ j byte_copy_reverse /* Copy any remaining bytes */
++
++/*
++ * These are basically sub-functions within the function. They
++ * are used to byte copy until the dest pointer is in alignment.
++ * At which point, a bulk copy method can be used by the
++ * calling code. These work on the same registers as the bulk
++ * copy loops. Therefore, the register values can be picked
++ * up from where they were left and we avoid code duplication
++ * without any overhead except the call in and return jumps.
++ */
++byte_copy_until_aligned_forward:
++ beq t3, t5, 2f
++ 1:
++ lb t1, 0(a1)
++ addi a1, a1, 1
++ addi t3, t3, 1
++ sb t1, -1(t3)
++ bne t3, t5, 1b
++ 2:
++ jalr zero, 0x0(t0) /* Return to multibyte copy loop */
++
++byte_copy_until_aligned_reverse:
++ beq t4, t6, 2f
++ 1:
++ lb t1, -1(a4)
++ addi a4, a4, -1
++ addi t4, t4, -1
++ sb t1, 0(t4)
++ bne t4, t6, 1b
++ 2:
++ jalr zero, 0x0(t0) /* Return to multibyte copy loop */
++
++/*
++ * Simple byte copy loops.
++ * These will byte copy until they reach the end of data to copy.
++ * At that point, they will call to return from memmove.
++ */
+ byte_copy:
+- lb t3, 0(a1)
+- addi a2, a2, -1
+- sb t3, 0(a0)
+- add a1, a1, t4
+- add a0, a0, t4
+- bnez a2, byte_copy
+-
+-exit_memcpy:
+- move a0, t0
+- move a1, t1
+- ret
+-END(__memmove)
++ bltu a1, a0, byte_copy_reverse
++
++byte_copy_forward:
++ beq t3, t4, 2f
++ 1:
++ lb t1, 0(a1)
++ addi a1, a1, 1
++ addi t3, t3, 1
++ sb t1, -1(t3)
++ bne t3, t4, 1b
++ 2:
++ ret
++
++byte_copy_reverse:
++ beq t4, t3, 2f
++ 1:
++ lb t1, -1(a4)
++ addi a4, a4, -1
++ addi t4, t4, -1
++ sb t1, 0(t4)
++ bne t4, t3, 1b
++ 2:
++
++return_from_memmove:
++ ret
++
++SYM_FUNC_END(memmove)
++SYM_FUNC_END(__memmove)
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index 7ebaef10ea1b6..ac7a25298a04a 100644
--- a/arch/riscv/mm/Makefile
@@ -14900,7 +22055,7 @@ index 7ebaef10ea1b6..ac7a25298a04a 100644
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
-index c0cddf0fc22db..3de593b26850e 100644
+index c0cddf0fc22db..7f130ac3b9f9a 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -187,10 +187,10 @@ static void __init setup_bootmem(void)
@@ -14915,7 +22070,35 @@ index c0cddf0fc22db..3de593b26850e 100644
/*
* memblock allocator is not aware of the fact that last 4K bytes of
* the addressable memory can not be mapped because of IS_ERR_VALUE
-@@ -451,6 +451,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
+@@ -218,8 +218,25 @@ static void __init setup_bootmem(void)
+ * early_init_fdt_reserve_self() since __pa() does
+ * not work for DTB pointers that are fixmap addresses
+ */
+- if (!IS_ENABLED(CONFIG_BUILTIN_DTB))
+- memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
++ if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) {
++ /*
++ * In case the DTB is not located in a memory region we won't
++ * be able to locate it later on via the linear mapping and
++ * get a segfault when accessing it via __va(dtb_early_pa).
++ * To avoid this situation copy DTB to a memory region.
++ * Note that memblock_phys_alloc will also reserve DTB region.
++ */
++ if (!memblock_is_memory(dtb_early_pa)) {
++ size_t fdt_size = fdt_totalsize(dtb_early_va);
++ phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE);
++ void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size);
++
++ memcpy(new_dtb_early_va, dtb_early_va, fdt_size);
++ early_memunmap(new_dtb_early_va, fdt_size);
++ _dtb_early_pa = new_dtb_early_pa;
++ } else
++ memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
++ }
+
+ early_init_fdt_scan_reserved_mem();
+ dma_contiguous_reserve(dma32_phys_limit);
+@@ -451,6 +468,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
}
#ifdef CONFIG_XIP_KERNEL
@@ -14923,7 +22106,7 @@ index c0cddf0fc22db..3de593b26850e 100644
/* called from head.S with MMU off */
asmlinkage void __init __copy_data(void)
{
-@@ -813,13 +814,22 @@ static void __init reserve_crashkernel(void)
+@@ -813,13 +831,22 @@ static void __init reserve_crashkernel(void)
/*
* Current riscv boot protocol requires 2MB alignment for
* RV64 and 4MB alignment for RV32 (hugepage size)
@@ -14978,10 +22161,27 @@ index b86de61b8caa2..797041b5109a2 100644
config S390
def_bool y
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
-index 450b351dfa8ef..d4fd1426a8226 100644
+index 450b351dfa8ef..c7b7a60f6405d 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
-@@ -79,10 +79,12 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y)
+@@ -32,6 +32,16 @@ KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector
+ KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member)
+ KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g)
+ KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,))
++
++ifdef CONFIG_CC_IS_GCC
++ ifeq ($(call cc-ifversion, -ge, 1200, y), y)
++ ifeq ($(call cc-ifversion, -lt, 1300, y), y)
++ KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
++ KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, array-bounds)
++ endif
++ endif
++endif
++
+ UTS_MACHINE := s390x
+ STACK_SIZE := $(if $(CONFIG_KASAN),65536,16384)
+ CHECKFLAGS += -D__s390__ -D__s390x__
+@@ -79,10 +89,12 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y)
KBUILD_CFLAGS_DECOMPRESSOR += $(cflags-y)
ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),)
@@ -15200,6 +22400,18 @@ index e4dc64cc9c555..287bb88f76986 100644
struct zpci_iomap_entry {
u32 fh;
+diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
+index 50d9b04ecbd14..bc50ee0e91ff1 100644
+--- a/arch/s390/include/asm/timex.h
++++ b/arch/s390/include/asm/timex.h
+@@ -201,6 +201,7 @@ static inline cycles_t get_cycles(void)
+ {
+ return (cycles_t) get_tod_clock() >> 2;
+ }
++#define get_cycles get_cycles
+
+ int get_phys_clock(unsigned long *clock);
+ void init_cpu_timer(void);
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index d72a6df058d79..785d54c9350c4 100644
--- a/arch/s390/kernel/crash_dump.c
@@ -15536,7 +22748,7 @@ index 67e5fff96ee06..ee67215a678a5 100644
/* Get information about *all* installed memory */
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
-index bcefc2173de45..12d28ff5281fa 100644
+index bcefc2173de45..4044826d72ae5 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs)
@@ -15548,6 +22760,28 @@ index bcefc2173de45..12d28ff5281fa 100644
} else
die(regs, "Unknown program exception");
}
+@@ -142,10 +142,10 @@ static inline void do_fp_trap(struct pt_regs *regs, __u32 fpc)
+ do_trap(regs, SIGFPE, si_code, "floating point exception");
+ }
+
+-static void translation_exception(struct pt_regs *regs)
++static void translation_specification_exception(struct pt_regs *regs)
+ {
+ /* May never happen. */
+- panic("Translation exception");
++ panic("Translation-Specification Exception");
+ }
+
+ static void illegal_op(struct pt_regs *regs)
+@@ -374,7 +374,7 @@ static void (*pgm_check_table[128])(struct pt_regs *regs) = {
+ [0x0f] = hfp_divide_exception,
+ [0x10] = do_dat_exception,
+ [0x11] = do_dat_exception,
+- [0x12] = translation_exception,
++ [0x12] = translation_specification_exception,
+ [0x13] = special_op_exception,
+ [0x14] = default_trap_handler,
+ [0x15] = operand_exception,
diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
index 5a656c7b7a67a..f95ccbd396925 100644
--- a/arch/s390/kernel/uv.c
@@ -15959,6 +23193,94 @@ index 034721a68d8fd..6ad634a27d5b9 100644
ptep = get_locked_pte(mm, hva, &ptl);
if (unlikely(!ptep))
return -EFAULT;
+diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
+index b833155ce8381..639924d983315 100644
+--- a/arch/s390/pci/pci.c
++++ b/arch/s390/pci/pci.c
+@@ -69,6 +69,7 @@ struct zpci_dev *get_zdev_by_fid(u32 fid)
+ list_for_each_entry(tmp, &zpci_list, entry) {
+ if (tmp->fid == fid) {
+ zdev = tmp;
++ zpci_zdev_get(zdev);
+ break;
+ }
+ }
+diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h
+index e359d2686178b..ecef3a9e16c00 100644
+--- a/arch/s390/pci/pci_bus.h
++++ b/arch/s390/pci/pci_bus.h
+@@ -19,7 +19,8 @@ void zpci_bus_remove_device(struct zpci_dev *zdev, bool set_error);
+ void zpci_release_device(struct kref *kref);
+ static inline void zpci_zdev_put(struct zpci_dev *zdev)
+ {
+- kref_put(&zdev->kref, zpci_release_device);
++ if (zdev)
++ kref_put(&zdev->kref, zpci_release_device);
+ }
+
+ static inline void zpci_zdev_get(struct zpci_dev *zdev)
+diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
+index be077b39da336..5011d27461fd3 100644
+--- a/arch/s390/pci/pci_clp.c
++++ b/arch/s390/pci/pci_clp.c
+@@ -22,6 +22,8 @@
+ #include <asm/clp.h>
+ #include <uapi/asm/clp.h>
+
++#include "pci_bus.h"
++
+ bool zpci_unique_uid;
+
+ void update_uid_checking(bool new)
+@@ -403,8 +405,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data)
+ return;
+
+ zdev = get_zdev_by_fid(entry->fid);
+- if (!zdev)
+- zpci_create_device(entry->fid, entry->fh, entry->config_state);
++ if (zdev) {
++ zpci_zdev_put(zdev);
++ return;
++ }
++ zpci_create_device(entry->fid, entry->fh, entry->config_state);
+ }
+
+ int clp_scan_pci_devices(void)
+diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
+index 5b8d647523f96..6d57625b8ed99 100644
+--- a/arch/s390/pci/pci_event.c
++++ b/arch/s390/pci/pci_event.c
+@@ -62,10 +62,12 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
+ pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
+
+ if (!pdev)
+- return;
++ goto no_pdev;
+
+ pdev->error_state = pci_channel_io_perm_failure;
+ pci_dev_put(pdev);
++no_pdev:
++ zpci_zdev_put(zdev);
+ }
+
+ void zpci_event_error(void *data)
+@@ -94,6 +96,7 @@ static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh)
+ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
+ {
+ struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
++ bool existing_zdev = !!zdev;
+ enum zpci_state state;
+
+ zpci_err("avail CCDF:\n");
+@@ -156,6 +159,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
+ default:
+ break;
+ }
++ if (existing_zdev)
++ zpci_zdev_put(zdev);
+ }
+
+ void zpci_event_availability(void *data)
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 958f790273ab9..10290e5c1f438 100644
--- a/arch/sh/Kconfig.debug
@@ -16201,10 +23523,33 @@ index 849236d4eca48..45e5c76d449ea 100644
$(call if_changed,uimage)
$(call if_changed,uimage.o)
@echo ' Image $@ is ready'
+diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h
+index 542915b462097..f86326a6f89e0 100644
+--- a/arch/sparc/include/asm/timex_32.h
++++ b/arch/sparc/include/asm/timex_32.h
+@@ -9,8 +9,6 @@
+
+ #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+
+-/* XXX Maybe do something better at some point... -DaveM */
+-typedef unsigned long cycles_t;
+-#define get_cycles() (0)
++#include <asm-generic/timex.h>
+
+ #endif
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
-index 02f3ad55dfe31..ffab16369beac 100644
+index 02f3ad55dfe31..74f80443b195f 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
+@@ -65,7 +65,7 @@ struct rt_signal_frame {
+ */
+ static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+ {
+- if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
++ if ((((unsigned long) fp) & 15) || !access_ok(fp, fplen))
+ return true;
+
+ return false;
@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs,
get_sigframe(ksig, regs, sigframe_size);
@@ -16249,6 +23594,39 @@ index 6323e5571887e..d69ea5b562cee 100644
kernel/config.tmp
kernel/vmlinux.lds
+kernel/capflags.c
+diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
+index 6ead1e2404576..8ca67a6926830 100644
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -224,7 +224,7 @@ void mconsole_go(struct mc_request *req)
+
+ void mconsole_stop(struct mc_request *req)
+ {
+- deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
++ block_signals();
+ os_set_fd_block(req->originating_fd, 1);
+ mconsole_reply(req, "stopped", 0, 0);
+ for (;;) {
+@@ -247,6 +247,7 @@ void mconsole_stop(struct mc_request *req)
+ }
+ os_set_fd_block(req->originating_fd, 0);
+ mconsole_reply(req, "", 0, 0);
++ unblock_signals();
+ }
+
+ static DEFINE_SPINLOCK(mc_devices_lock);
+diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
+index cd9dc0556e913..fefd343412c79 100644
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -27,6 +27,7 @@
+ #include <linux/blk-mq.h>
+ #include <linux/ata.h>
+ #include <linux/hdreg.h>
++#include <linux/major.h>
+ #include <linux/cdrom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c
index c080666330234..0ab58016db22f 100644
--- a/arch/um/drivers/virt-pci.c
@@ -16345,6 +23723,50 @@ index dab5744e9253d..1e69ef5bc35e0 100644
}
#define arch_local_irq_enable arch_local_irq_enable
+diff --git a/arch/um/include/asm/timex.h b/arch/um/include/asm/timex.h
+index e392a9a5bc9bd..9f27176adb26d 100644
+--- a/arch/um/include/asm/timex.h
++++ b/arch/um/include/asm/timex.h
+@@ -2,13 +2,8 @@
+ #ifndef __UM_TIMEX_H
+ #define __UM_TIMEX_H
+
+-typedef unsigned long cycles_t;
+-
+-static inline cycles_t get_cycles (void)
+-{
+- return 0;
+-}
+-
+ #define CLOCK_TICK_RATE (HZ)
+
++#include <asm-generic/timex.h>
++
+ #endif
+diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h
+index f512704a9ec7b..22b39de73c246 100644
+--- a/arch/um/include/asm/xor.h
++++ b/arch/um/include/asm/xor.h
+@@ -4,8 +4,10 @@
+
+ #ifdef CONFIG_64BIT
+ #undef CONFIG_X86_32
++#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_sse_pf64))
+ #else
+ #define CONFIG_X86_32 1
++#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_8regs))
+ #endif
+
+ #include <asm/cpufeature.h>
+@@ -16,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 ? &xor_block_8regs : NULL)
++ (time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x))
+ #endif
+
+ #endif
diff --git a/arch/um/include/shared/longjmp.h b/arch/um/include/shared/longjmp.h
index bdb2869b72b31..8863319039f3d 100644
--- a/arch/um/include/shared/longjmp.h
@@ -16521,10 +23943,29 @@ index 8a72c99994eb1..e3ee4db58b40d 100644
stop_ptraced_child(pid, 1, 1);
}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index d9830e7e1060f..1f96809606ac5 100644
+index d9830e7e1060f..d02b04d300966 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -1256,7 +1256,8 @@ config TOSHIBA
+@@ -468,6 +468,18 @@ config RETPOLINE
+ branches. Requires a compiler with -mindirect-branch=thunk-extern
+ support for full protection. The kernel may run slower.
+
++config CC_HAS_SLS
++ def_bool $(cc-option,-mharden-sls=all)
++
++config SLS
++ bool "Mitigate Straight-Line-Speculation"
++ depends on CC_HAS_SLS && X86_64
++ default n
++ help
++ Compile the kernel with straight-line-speculation options to guard
++ against straight line speculation. The kernel image might be slightly
++ larger.
++
+ config X86_CPU_RESCTRL
+ bool "x86 CPU resource control support"
+ depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
+@@ -1256,7 +1268,8 @@ config TOSHIBA
config I8K
tristate "Dell i8k legacy laptop support"
@@ -16534,7 +23975,7 @@ index d9830e7e1060f..1f96809606ac5 100644
select SENSORS_DELL_SMM
help
This option enables legacy /proc/i8k userspace interface in hwmon
-@@ -1518,6 +1519,7 @@ config AMD_MEM_ENCRYPT
+@@ -1518,6 +1531,7 @@ config AMD_MEM_ENCRYPT
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select INSTRUCTION_DECODER
select ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS
@@ -16542,7 +23983,7 @@ index d9830e7e1060f..1f96809606ac5 100644
help
Say yes to enable support for the encryption of system memory.
This requires an AMD processor that supports Secure Memory
-@@ -1917,6 +1919,7 @@ config EFI
+@@ -1917,6 +1931,7 @@ config EFI
depends on ACPI
select UCS2_STRING
select EFI_RUNTIME_WRAPPERS
@@ -16550,6 +23991,33 @@ index d9830e7e1060f..1f96809606ac5 100644
help
This enables the kernel to use EFI runtime services that are
available (such as the EFI variable services).
+@@ -2795,6 +2810,11 @@ config IA32_AOUT
+ config X86_X32
+ bool "x32 ABI for 64-bit mode"
+ depends on X86_64
++ # llvm-objcopy does not convert x86_64 .note.gnu.property or
++ # compressed debug sections to x86_x32 properly:
++ # https://github.com/ClangBuiltLinux/linux/issues/514
++ # https://github.com/ClangBuiltLinux/linux/issues/1141
++ depends on $(success,$(OBJCOPY) --version | head -n1 | grep -qv llvm)
+ help
+ Include code to run binaries for the x32 native 32-bit ABI
+ for 64-bit processors. An x32 process gets access to the
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index 7488cfbbd2f60..300227818206b 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -179,6 +179,10 @@ ifdef CONFIG_RETPOLINE
+ endif
+ endif
+
++ifdef CONFIG_SLS
++ KBUILD_CFLAGS += -mharden-sls=all
++endif
++
+ KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
+
+ ifdef CONFIG_LTO_CLANG
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 431bf7f846c3c..e118136460518 100644
--- a/arch/x86/boot/compressed/Makefile
@@ -16575,6 +24043,90 @@ index 431bf7f846c3c..e118136460518 100644
# sev.c indirectly inludes inat-table.h which is generated during
# compilation and stored in $(objtree). Add the directory to the includes so
+diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
+index 8bb92e9f4e973..70052779b235c 100644
+--- a/arch/x86/boot/compressed/efi_thunk_64.S
++++ b/arch/x86/boot/compressed/efi_thunk_64.S
+@@ -93,7 +93,7 @@ SYM_FUNC_START(__efi64_thunk)
+
+ pop %rbx
+ pop %rbp
+- ret
++ RET
+ SYM_FUNC_END(__efi64_thunk)
+
+ .code32
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 572c535cf45bc..fd9441f404570 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -813,7 +813,7 @@ SYM_FUNC_START(efi32_pe_entry)
+ 2: popl %edi // restore callee-save registers
+ popl %ebx
+ leave
+- ret
++ RET
+ SYM_FUNC_END(efi32_pe_entry)
+
+ .section ".rodata"
+@@ -868,7 +868,7 @@ SYM_FUNC_START(startup32_set_idt_entry)
+
+ pop %ecx
+ pop %ebx
+- ret
++ RET
+ SYM_FUNC_END(startup32_set_idt_entry)
+ #endif
+
+@@ -884,7 +884,7 @@ SYM_FUNC_START(startup32_load_idt)
+ movl %eax, rva(boot32_idt_desc+2)(%ebp)
+ lidt rva(boot32_idt_desc)(%ebp)
+ #endif
+- ret
++ RET
+ SYM_FUNC_END(startup32_load_idt)
+
+ /*
+@@ -954,7 +954,7 @@ SYM_FUNC_START(startup32_check_sev_cbit)
+ popl %ebx
+ popl %eax
+ #endif
+- ret
++ RET
+ SYM_FUNC_END(startup32_check_sev_cbit)
+
+ /*
+diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
+index c1e81a848b2a5..a63424d13627b 100644
+--- a/arch/x86/boot/compressed/mem_encrypt.S
++++ b/arch/x86/boot/compressed/mem_encrypt.S
+@@ -58,7 +58,7 @@ SYM_FUNC_START(get_sev_encryption_bit)
+
+ #endif /* CONFIG_AMD_MEM_ENCRYPT */
+
+- ret
++ RET
+ SYM_FUNC_END(get_sev_encryption_bit)
+
+ /**
+@@ -92,7 +92,7 @@ SYM_CODE_START_LOCAL(sev_es_req_cpuid)
+ /* All good - return success */
+ xorl %eax, %eax
+ 1:
+- ret
++ RET
+ 2:
+ movl $-1, %eax
+ jmp 1b
+@@ -221,7 +221,7 @@ SYM_FUNC_START(set_sev_encryption_mask)
+ #endif
+
+ xor %rax, %rax
+- ret
++ RET
+ SYM_FUNC_END(set_sev_encryption_mask)
+
+ .data
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index e81885384f604..99398cbdae434 100644
--- a/arch/x86/configs/i386_defconfig
@@ -16593,6 +24145,630 @@ index e8a7a0af2bdaa..d7298b104a456 100644
CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_DEBUG_BOOT_PARAMS=y
+CONFIG_KALLSYMS_ALL=y
+diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
+index f307c93fc90a7..c3af959648e62 100644
+--- a/arch/x86/crypto/Makefile
++++ b/arch/x86/crypto/Makefile
+@@ -62,7 +62,9 @@ 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-core.o blake2s-glue.o
++blake2s-x86_64-y := blake2s-shash.o
++obj-$(if $(CONFIG_CRYPTO_BLAKE2S_X86),y) += 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
+ ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S
+index 51d46d93efbcc..b48ddebb47489 100644
+--- a/arch/x86/crypto/aegis128-aesni-asm.S
++++ b/arch/x86/crypto/aegis128-aesni-asm.S
+@@ -122,7 +122,7 @@ SYM_FUNC_START_LOCAL(__load_partial)
+ pxor T0, MSG
+
+ .Lld_partial_8:
+- ret
++ RET
+ SYM_FUNC_END(__load_partial)
+
+ /*
+@@ -180,7 +180,7 @@ SYM_FUNC_START_LOCAL(__store_partial)
+ mov %r10b, (%r9)
+
+ .Lst_partial_1:
+- ret
++ RET
+ SYM_FUNC_END(__store_partial)
+
+ /*
+@@ -225,7 +225,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_init)
+ movdqu STATE4, 0x40(STATEP)
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_init)
+
+ /*
+@@ -337,7 +337,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
+ movdqu STATE3, 0x30(STATEP)
+ movdqu STATE4, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lad_out_1:
+ movdqu STATE4, 0x00(STATEP)
+@@ -346,7 +346,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
+ movdqu STATE2, 0x30(STATEP)
+ movdqu STATE3, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lad_out_2:
+ movdqu STATE3, 0x00(STATEP)
+@@ -355,7 +355,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
+ movdqu STATE1, 0x30(STATEP)
+ movdqu STATE2, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lad_out_3:
+ movdqu STATE2, 0x00(STATEP)
+@@ -364,7 +364,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
+ movdqu STATE0, 0x30(STATEP)
+ movdqu STATE1, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lad_out_4:
+ movdqu STATE1, 0x00(STATEP)
+@@ -373,11 +373,11 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
+ movdqu STATE4, 0x30(STATEP)
+ movdqu STATE0, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lad_out:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_ad)
+
+ .macro encrypt_block a s0 s1 s2 s3 s4 i
+@@ -452,7 +452,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc)
+ movdqu STATE2, 0x30(STATEP)
+ movdqu STATE3, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lenc_out_1:
+ movdqu STATE3, 0x00(STATEP)
+@@ -461,7 +461,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc)
+ movdqu STATE1, 0x30(STATEP)
+ movdqu STATE2, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lenc_out_2:
+ movdqu STATE2, 0x00(STATEP)
+@@ -470,7 +470,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc)
+ movdqu STATE0, 0x30(STATEP)
+ movdqu STATE1, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lenc_out_3:
+ movdqu STATE1, 0x00(STATEP)
+@@ -479,7 +479,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc)
+ movdqu STATE4, 0x30(STATEP)
+ movdqu STATE0, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lenc_out_4:
+ movdqu STATE0, 0x00(STATEP)
+@@ -488,11 +488,11 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc)
+ movdqu STATE3, 0x30(STATEP)
+ movdqu STATE4, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Lenc_out:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_enc)
+
+ /*
+@@ -532,7 +532,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_enc_tail)
+ movdqu STATE3, 0x40(STATEP)
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_enc_tail)
+
+ .macro decrypt_block a s0 s1 s2 s3 s4 i
+@@ -606,7 +606,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec)
+ movdqu STATE2, 0x30(STATEP)
+ movdqu STATE3, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Ldec_out_1:
+ movdqu STATE3, 0x00(STATEP)
+@@ -615,7 +615,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec)
+ movdqu STATE1, 0x30(STATEP)
+ movdqu STATE2, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Ldec_out_2:
+ movdqu STATE2, 0x00(STATEP)
+@@ -624,7 +624,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec)
+ movdqu STATE0, 0x30(STATEP)
+ movdqu STATE1, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Ldec_out_3:
+ movdqu STATE1, 0x00(STATEP)
+@@ -633,7 +633,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec)
+ movdqu STATE4, 0x30(STATEP)
+ movdqu STATE0, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Ldec_out_4:
+ movdqu STATE0, 0x00(STATEP)
+@@ -642,11 +642,11 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec)
+ movdqu STATE3, 0x30(STATEP)
+ movdqu STATE4, 0x40(STATEP)
+ FRAME_END
+- ret
++ RET
+
+ .Ldec_out:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_dec)
+
+ /*
+@@ -696,7 +696,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_dec_tail)
+ movdqu STATE3, 0x40(STATEP)
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_dec_tail)
+
+ /*
+@@ -743,5 +743,5 @@ SYM_FUNC_START(crypto_aegis128_aesni_final)
+ movdqu MSG, (%rsi)
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(crypto_aegis128_aesni_final)
+diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
+index 3f0fc7dd87d77..c799838242a69 100644
+--- a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
++++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
+@@ -525,7 +525,7 @@ ddq_add_8:
+ /* return updated IV */
+ vpshufb xbyteswap, xcounter, xcounter
+ vmovdqu xcounter, (p_iv)
+- ret
++ RET
+ .endm
+
+ /*
+diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
+index 4e3972570916e..363699dd72206 100644
+--- a/arch/x86/crypto/aesni-intel_asm.S
++++ b/arch/x86/crypto/aesni-intel_asm.S
+@@ -1594,7 +1594,7 @@ SYM_FUNC_START(aesni_gcm_dec)
+ GCM_ENC_DEC dec
+ GCM_COMPLETE arg10, arg11
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_dec)
+
+
+@@ -1683,7 +1683,7 @@ SYM_FUNC_START(aesni_gcm_enc)
+
+ GCM_COMPLETE arg10, arg11
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_enc)
+
+ /*****************************************************************************
+@@ -1701,7 +1701,7 @@ SYM_FUNC_START(aesni_gcm_init)
+ FUNC_SAVE
+ GCM_INIT %arg3, %arg4,%arg5, %arg6
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_init)
+
+ /*****************************************************************************
+@@ -1716,7 +1716,7 @@ SYM_FUNC_START(aesni_gcm_enc_update)
+ FUNC_SAVE
+ GCM_ENC_DEC enc
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_enc_update)
+
+ /*****************************************************************************
+@@ -1731,7 +1731,7 @@ SYM_FUNC_START(aesni_gcm_dec_update)
+ FUNC_SAVE
+ GCM_ENC_DEC dec
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_dec_update)
+
+ /*****************************************************************************
+@@ -1746,7 +1746,7 @@ SYM_FUNC_START(aesni_gcm_finalize)
+ FUNC_SAVE
+ GCM_COMPLETE %arg3 %arg4
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_finalize)
+
+ #endif
+@@ -1762,7 +1762,7 @@ SYM_FUNC_START_LOCAL(_key_expansion_256a)
+ pxor %xmm1, %xmm0
+ movaps %xmm0, (TKEYP)
+ add $0x10, TKEYP
+- ret
++ RET
+ SYM_FUNC_END(_key_expansion_256a)
+ SYM_FUNC_END_ALIAS(_key_expansion_128)
+
+@@ -1787,7 +1787,7 @@ SYM_FUNC_START_LOCAL(_key_expansion_192a)
+ shufps $0b01001110, %xmm2, %xmm1
+ movaps %xmm1, 0x10(TKEYP)
+ add $0x20, TKEYP
+- ret
++ RET
+ SYM_FUNC_END(_key_expansion_192a)
+
+ SYM_FUNC_START_LOCAL(_key_expansion_192b)
+@@ -1806,7 +1806,7 @@ SYM_FUNC_START_LOCAL(_key_expansion_192b)
+
+ movaps %xmm0, (TKEYP)
+ add $0x10, TKEYP
+- ret
++ RET
+ SYM_FUNC_END(_key_expansion_192b)
+
+ SYM_FUNC_START_LOCAL(_key_expansion_256b)
+@@ -1818,7 +1818,7 @@ SYM_FUNC_START_LOCAL(_key_expansion_256b)
+ pxor %xmm1, %xmm2
+ movaps %xmm2, (TKEYP)
+ add $0x10, TKEYP
+- ret
++ RET
+ SYM_FUNC_END(_key_expansion_256b)
+
+ /*
+@@ -1933,7 +1933,7 @@ SYM_FUNC_START(aesni_set_key)
+ popl KEYP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_set_key)
+
+ /*
+@@ -1957,7 +1957,7 @@ SYM_FUNC_START(aesni_enc)
+ popl KEYP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_enc)
+
+ /*
+@@ -2014,7 +2014,7 @@ SYM_FUNC_START_LOCAL(_aesni_enc1)
+ aesenc KEY, STATE
+ movaps 0x70(TKEYP), KEY
+ aesenclast KEY, STATE
+- ret
++ RET
+ SYM_FUNC_END(_aesni_enc1)
+
+ /*
+@@ -2122,7 +2122,7 @@ SYM_FUNC_START_LOCAL(_aesni_enc4)
+ aesenclast KEY, STATE2
+ aesenclast KEY, STATE3
+ aesenclast KEY, STATE4
+- ret
++ RET
+ SYM_FUNC_END(_aesni_enc4)
+
+ /*
+@@ -2147,7 +2147,7 @@ SYM_FUNC_START(aesni_dec)
+ popl KEYP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_dec)
+
+ /*
+@@ -2204,7 +2204,7 @@ SYM_FUNC_START_LOCAL(_aesni_dec1)
+ aesdec KEY, STATE
+ movaps 0x70(TKEYP), KEY
+ aesdeclast KEY, STATE
+- ret
++ RET
+ SYM_FUNC_END(_aesni_dec1)
+
+ /*
+@@ -2312,7 +2312,7 @@ SYM_FUNC_START_LOCAL(_aesni_dec4)
+ aesdeclast KEY, STATE2
+ aesdeclast KEY, STATE3
+ aesdeclast KEY, STATE4
+- ret
++ RET
+ SYM_FUNC_END(_aesni_dec4)
+
+ /*
+@@ -2372,7 +2372,7 @@ SYM_FUNC_START(aesni_ecb_enc)
+ popl LEN
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_ecb_enc)
+
+ /*
+@@ -2433,7 +2433,7 @@ SYM_FUNC_START(aesni_ecb_dec)
+ popl LEN
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_ecb_dec)
+
+ /*
+@@ -2477,7 +2477,7 @@ SYM_FUNC_START(aesni_cbc_enc)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_cbc_enc)
+
+ /*
+@@ -2570,7 +2570,7 @@ SYM_FUNC_START(aesni_cbc_dec)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_cbc_dec)
+
+ /*
+@@ -2627,7 +2627,7 @@ SYM_FUNC_START(aesni_cts_cbc_enc)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_cts_cbc_enc)
+
+ /*
+@@ -2688,7 +2688,7 @@ SYM_FUNC_START(aesni_cts_cbc_dec)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_cts_cbc_dec)
+
+ .pushsection .rodata
+@@ -2725,7 +2725,7 @@ SYM_FUNC_START_LOCAL(_aesni_inc_init)
+ mov $1, TCTR_LOW
+ movq TCTR_LOW, INC
+ movq CTR, TCTR_LOW
+- ret
++ RET
+ SYM_FUNC_END(_aesni_inc_init)
+
+ /*
+@@ -2753,7 +2753,7 @@ SYM_FUNC_START_LOCAL(_aesni_inc)
+ .Linc_low:
+ movaps CTR, IV
+ pshufb BSWAP_MASK, IV
+- ret
++ RET
+ SYM_FUNC_END(_aesni_inc)
+
+ /*
+@@ -2816,7 +2816,7 @@ SYM_FUNC_START(aesni_ctr_enc)
+ movups IV, (IVP)
+ .Lctr_enc_just_ret:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(aesni_ctr_enc)
+
+ #endif
+@@ -2932,7 +2932,7 @@ SYM_FUNC_START(aesni_xts_encrypt)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+
+ .Lxts_enc_1x:
+ add $64, LEN
+@@ -3092,7 +3092,7 @@ SYM_FUNC_START(aesni_xts_decrypt)
+ popl IVP
+ #endif
+ FRAME_END
+- ret
++ RET
+
+ .Lxts_dec_1x:
+ add $64, LEN
+diff --git a/arch/x86/crypto/aesni-intel_avx-x86_64.S b/arch/x86/crypto/aesni-intel_avx-x86_64.S
+index 98e3552b6e039..0852ab573fd30 100644
+--- a/arch/x86/crypto/aesni-intel_avx-x86_64.S
++++ b/arch/x86/crypto/aesni-intel_avx-x86_64.S
+@@ -1767,7 +1767,7 @@ SYM_FUNC_START(aesni_gcm_init_avx_gen2)
+ FUNC_SAVE
+ INIT GHASH_MUL_AVX, PRECOMPUTE_AVX
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_init_avx_gen2)
+
+ ###############################################################################
+@@ -1788,15 +1788,15 @@ SYM_FUNC_START(aesni_gcm_enc_update_avx_gen2)
+ # must be 192
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 11
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_enc_update:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 9
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_enc_update:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, ENC, 13
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_enc_update_avx_gen2)
+
+ ###############################################################################
+@@ -1817,15 +1817,15 @@ SYM_FUNC_START(aesni_gcm_dec_update_avx_gen2)
+ # must be 192
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 11
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_dec_update:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 9
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_dec_update:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX, GHASH_8_ENCRYPT_8_PARALLEL_AVX, GHASH_LAST_8_AVX, GHASH_MUL_AVX, DEC, 13
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_dec_update_avx_gen2)
+
+ ###############################################################################
+@@ -1846,15 +1846,15 @@ SYM_FUNC_START(aesni_gcm_finalize_avx_gen2)
+ # must be 192
+ GCM_COMPLETE GHASH_MUL_AVX, 11, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_finalize:
+ GCM_COMPLETE GHASH_MUL_AVX, 9, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_finalize:
+ GCM_COMPLETE GHASH_MUL_AVX, 13, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_finalize_avx_gen2)
+
+ ###############################################################################
+@@ -2735,7 +2735,7 @@ SYM_FUNC_START(aesni_gcm_init_avx_gen4)
+ FUNC_SAVE
+ INIT GHASH_MUL_AVX2, PRECOMPUTE_AVX2
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_init_avx_gen4)
+
+ ###############################################################################
+@@ -2756,15 +2756,15 @@ SYM_FUNC_START(aesni_gcm_enc_update_avx_gen4)
+ # must be 192
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 11
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_enc_update4:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 9
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_enc_update4:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, ENC, 13
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_enc_update_avx_gen4)
+
+ ###############################################################################
+@@ -2785,15 +2785,15 @@ SYM_FUNC_START(aesni_gcm_dec_update_avx_gen4)
+ # must be 192
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 11
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_dec_update4:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 9
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_dec_update4:
+ GCM_ENC_DEC INITIAL_BLOCKS_AVX2, GHASH_8_ENCRYPT_8_PARALLEL_AVX2, GHASH_LAST_8_AVX2, GHASH_MUL_AVX2, DEC, 13
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_dec_update_avx_gen4)
+
+ ###############################################################################
+@@ -2814,13 +2814,13 @@ SYM_FUNC_START(aesni_gcm_finalize_avx_gen4)
+ # must be 192
+ GCM_COMPLETE GHASH_MUL_AVX2, 11, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ key_128_finalize4:
+ GCM_COMPLETE GHASH_MUL_AVX2, 9, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ key_256_finalize4:
+ GCM_COMPLETE GHASH_MUL_AVX2, 13, arg3, arg4
+ FUNC_RESTORE
+- ret
++ RET
+ SYM_FUNC_END(aesni_gcm_finalize_avx_gen4)
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 0fc961bef299c..41901ba9d3a2c 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
@@ -16624,8 +24800,1454 @@ index 0fc961bef299c..41901ba9d3a2c 100644
.cra_module = THIS_MODULE,
},
} };
+diff --git a/arch/x86/crypto/blake2s-core.S b/arch/x86/crypto/blake2s-core.S
+index 2ca79974f8198..b50b35ff1fdba 100644
+--- a/arch/x86/crypto/blake2s-core.S
++++ b/arch/x86/crypto/blake2s-core.S
+@@ -171,7 +171,7 @@ SYM_FUNC_START(blake2s_compress_ssse3)
+ movdqu %xmm1,0x10(%rdi)
+ movdqu %xmm14,0x20(%rdi)
+ .Lendofloop:
+- ret
++ RET
+ SYM_FUNC_END(blake2s_compress_ssse3)
+
+ #ifdef CONFIG_AS_AVX512
+@@ -251,6 +251,6 @@ SYM_FUNC_START(blake2s_compress_avx512)
+ vmovdqu %xmm1,0x10(%rdi)
+ vmovdqu %xmm4,0x20(%rdi)
+ vzeroupper
+- retq
++ RET
+ SYM_FUNC_END(blake2s_compress_avx512)
+ #endif /* CONFIG_AS_AVX512 */
+diff --git a/arch/x86/crypto/blake2s-glue.c b/arch/x86/crypto/blake2s-glue.c
+index a40365ab301ee..69853c13e8fb0 100644
+--- a/arch/x86/crypto/blake2s-glue.c
++++ b/arch/x86/crypto/blake2s-glue.c
+@@ -5,7 +5,6 @@
+
+ #include <crypto/internal/blake2s.h>
+ #include <crypto/internal/simd.h>
+-#include <crypto/internal/hash.h>
+
+ #include <linux/types.h>
+ #include <linux/jump_label.h>
+@@ -28,9 +27,8 @@ asmlinkage void blake2s_compress_avx512(struct blake2s_state *state,
+ static __ro_after_init DEFINE_STATIC_KEY_FALSE(blake2s_use_ssse3);
+ static __ro_after_init DEFINE_STATIC_KEY_FALSE(blake2s_use_avx512);
+
+-void blake2s_compress_arch(struct blake2s_state *state,
+- const u8 *block, size_t nblocks,
+- const u32 inc)
++void blake2s_compress(struct blake2s_state *state, const u8 *block,
++ size_t nblocks, const u32 inc)
+ {
+ /* SIMD disables preemption, so relax after processing each page. */
+ BUILD_BUG_ON(SZ_4K / BLAKE2S_BLOCK_SIZE < 8);
+@@ -56,49 +54,12 @@ void blake2s_compress_arch(struct blake2s_state *state,
+ block += blocks * BLAKE2S_BLOCK_SIZE;
+ } while (nblocks);
+ }
+-EXPORT_SYMBOL(blake2s_compress_arch);
+-
+-static int crypto_blake2s_update_x86(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen)
+-{
+- return crypto_blake2s_update(desc, in, inlen, blake2s_compress_arch);
+-}
+-
+-static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out)
+-{
+- return crypto_blake2s_final(desc, out, blake2s_compress_arch);
+-}
+-
+-#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),
+-};
++EXPORT_SYMBOL(blake2s_compress);
+
+ static int __init blake2s_mod_init(void)
+ {
+- if (!boot_cpu_has(X86_FEATURE_SSSE3))
+- return 0;
+-
+- static_branch_enable(&blake2s_use_ssse3);
++ if (boot_cpu_has(X86_FEATURE_SSSE3))
++ static_branch_enable(&blake2s_use_ssse3);
+
+ if (IS_ENABLED(CONFIG_AS_AVX512) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
+@@ -109,26 +70,9 @@ static int __init blake2s_mod_init(void)
+ XFEATURE_MASK_AVX512, NULL))
+ static_branch_enable(&blake2s_use_avx512);
+
+- return IS_REACHABLE(CONFIG_CRYPTO_HASH) ?
+- crypto_register_shashes(blake2s_algs,
+- ARRAY_SIZE(blake2s_algs)) : 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));
++ return 0;
+ }
+
+ 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/crypto/blake2s-shash.c b/arch/x86/crypto/blake2s-shash.c
+new file mode 100644
+index 0000000000000..59ae28abe35cc
+--- /dev/null
++++ b/arch/x86/crypto/blake2s-shash.c
+@@ -0,0 +1,77 @@
++// 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/crypto/blowfish-x86_64-asm_64.S b/arch/x86/crypto/blowfish-x86_64-asm_64.S
+index 4222ac6d65848..802d715826891 100644
+--- a/arch/x86/crypto/blowfish-x86_64-asm_64.S
++++ b/arch/x86/crypto/blowfish-x86_64-asm_64.S
+@@ -135,10 +135,10 @@ SYM_FUNC_START(__blowfish_enc_blk)
+ jnz .L__enc_xor;
+
+ write_block();
+- ret;
++ RET;
+ .L__enc_xor:
+ xor_block();
+- ret;
++ RET;
+ SYM_FUNC_END(__blowfish_enc_blk)
+
+ SYM_FUNC_START(blowfish_dec_blk)
+@@ -170,7 +170,7 @@ SYM_FUNC_START(blowfish_dec_blk)
+
+ movq %r11, %r12;
+
+- ret;
++ RET;
+ SYM_FUNC_END(blowfish_dec_blk)
+
+ /**********************************************************************
+@@ -322,14 +322,14 @@ SYM_FUNC_START(__blowfish_enc_blk_4way)
+
+ popq %rbx;
+ popq %r12;
+- ret;
++ RET;
+
+ .L__enc_xor4:
+ xor_block4();
+
+ popq %rbx;
+ popq %r12;
+- ret;
++ RET;
+ SYM_FUNC_END(__blowfish_enc_blk_4way)
+
+ SYM_FUNC_START(blowfish_dec_blk_4way)
+@@ -364,5 +364,5 @@ SYM_FUNC_START(blowfish_dec_blk_4way)
+ popq %rbx;
+ popq %r12;
+
+- ret;
++ RET;
+ SYM_FUNC_END(blowfish_dec_blk_4way)
+diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
+index e2a0e0f4bf9d8..2e1658ddbe1a9 100644
+--- a/arch/x86/crypto/camellia-aesni-avx-asm_64.S
++++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
+@@ -192,7 +192,7 @@ SYM_FUNC_START_LOCAL(roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_c
+ roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+ %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15,
+ %rcx, (%r9));
+- ret;
++ RET;
+ SYM_FUNC_END(roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd)
+
+ .align 8
+@@ -200,7 +200,7 @@ SYM_FUNC_START_LOCAL(roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_a
+ roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3,
+ %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11,
+ %rax, (%r9));
+- ret;
++ RET;
+ SYM_FUNC_END(roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab)
+
+ /*
+@@ -778,7 +778,7 @@ SYM_FUNC_START_LOCAL(__camellia_enc_blk16)
+ %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
+
+ FRAME_END
+- ret;
++ RET;
+
+ .align 8
+ .Lenc_max32:
+@@ -865,7 +865,7 @@ SYM_FUNC_START_LOCAL(__camellia_dec_blk16)
+ %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
+
+ FRAME_END
+- ret;
++ RET;
+
+ .align 8
+ .Ldec_max32:
+@@ -906,7 +906,7 @@ SYM_FUNC_START(camellia_ecb_enc_16way)
+ %xmm8, %rsi);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_ecb_enc_16way)
+
+ SYM_FUNC_START(camellia_ecb_dec_16way)
+@@ -936,7 +936,7 @@ SYM_FUNC_START(camellia_ecb_dec_16way)
+ %xmm8, %rsi);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_ecb_dec_16way)
+
+ SYM_FUNC_START(camellia_cbc_dec_16way)
+@@ -987,5 +987,5 @@ SYM_FUNC_START(camellia_cbc_dec_16way)
+ %xmm8, %rsi);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_cbc_dec_16way)
+diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
+index 706f70829a07e..0e4e9abbf4de3 100644
+--- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
++++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S
+@@ -226,7 +226,7 @@ SYM_FUNC_START_LOCAL(roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_c
+ roundsm32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+ %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15,
+ %rcx, (%r9));
+- ret;
++ RET;
+ SYM_FUNC_END(roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd)
+
+ .align 8
+@@ -234,7 +234,7 @@ SYM_FUNC_START_LOCAL(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_a
+ roundsm32(%ymm4, %ymm5, %ymm6, %ymm7, %ymm0, %ymm1, %ymm2, %ymm3,
+ %ymm12, %ymm13, %ymm14, %ymm15, %ymm8, %ymm9, %ymm10, %ymm11,
+ %rax, (%r9));
+- ret;
++ RET;
+ SYM_FUNC_END(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab)
+
+ /*
+@@ -814,7 +814,7 @@ SYM_FUNC_START_LOCAL(__camellia_enc_blk32)
+ %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax));
+
+ FRAME_END
+- ret;
++ RET;
+
+ .align 8
+ .Lenc_max32:
+@@ -901,7 +901,7 @@ SYM_FUNC_START_LOCAL(__camellia_dec_blk32)
+ %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
+
+ FRAME_END
+- ret;
++ RET;
+
+ .align 8
+ .Ldec_max32:
+@@ -946,7 +946,7 @@ SYM_FUNC_START(camellia_ecb_enc_32way)
+ vzeroupper;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_ecb_enc_32way)
+
+ SYM_FUNC_START(camellia_ecb_dec_32way)
+@@ -980,7 +980,7 @@ SYM_FUNC_START(camellia_ecb_dec_32way)
+ vzeroupper;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_ecb_dec_32way)
+
+ SYM_FUNC_START(camellia_cbc_dec_32way)
+@@ -1047,5 +1047,5 @@ SYM_FUNC_START(camellia_cbc_dec_32way)
+
+ addq $(16 * 32), %rsp;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_cbc_dec_32way)
+diff --git a/arch/x86/crypto/camellia-x86_64-asm_64.S b/arch/x86/crypto/camellia-x86_64-asm_64.S
+index 1372e64088507..347c059f59403 100644
+--- a/arch/x86/crypto/camellia-x86_64-asm_64.S
++++ b/arch/x86/crypto/camellia-x86_64-asm_64.S
+@@ -213,13 +213,13 @@ SYM_FUNC_START(__camellia_enc_blk)
+ enc_outunpack(mov, RT1);
+
+ movq RR12, %r12;
+- ret;
++ RET;
+
+ .L__enc_xor:
+ enc_outunpack(xor, RT1);
+
+ movq RR12, %r12;
+- ret;
++ RET;
+ SYM_FUNC_END(__camellia_enc_blk)
+
+ SYM_FUNC_START(camellia_dec_blk)
+@@ -257,7 +257,7 @@ SYM_FUNC_START(camellia_dec_blk)
+ dec_outunpack();
+
+ movq RR12, %r12;
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_dec_blk)
+
+ /**********************************************************************
+@@ -448,14 +448,14 @@ SYM_FUNC_START(__camellia_enc_blk_2way)
+
+ movq RR12, %r12;
+ popq %rbx;
+- ret;
++ RET;
+
+ .L__enc2_xor:
+ enc_outunpack2(xor, RT2);
+
+ movq RR12, %r12;
+ popq %rbx;
+- ret;
++ RET;
+ SYM_FUNC_END(__camellia_enc_blk_2way)
+
+ SYM_FUNC_START(camellia_dec_blk_2way)
+@@ -495,5 +495,5 @@ SYM_FUNC_START(camellia_dec_blk_2way)
+
+ movq RR12, %r12;
+ movq RXOR, %rbx;
+- ret;
++ RET;
+ SYM_FUNC_END(camellia_dec_blk_2way)
+diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+index 8a6181b08b590..b258af420c92c 100644
+--- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
++++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+@@ -279,7 +279,7 @@ SYM_FUNC_START_LOCAL(__cast5_enc_blk16)
+ outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+ outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__cast5_enc_blk16)
+
+ .align 16
+@@ -352,7 +352,7 @@ SYM_FUNC_START_LOCAL(__cast5_dec_blk16)
+ outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+ outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
+
+- ret;
++ RET;
+
+ .L__skip_dec:
+ vpsrldq $4, RKR, RKR;
+@@ -393,7 +393,7 @@ SYM_FUNC_START(cast5_ecb_enc_16way)
+
+ popq %r15;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast5_ecb_enc_16way)
+
+ SYM_FUNC_START(cast5_ecb_dec_16way)
+@@ -431,7 +431,7 @@ SYM_FUNC_START(cast5_ecb_dec_16way)
+
+ popq %r15;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast5_ecb_dec_16way)
+
+ SYM_FUNC_START(cast5_cbc_dec_16way)
+@@ -483,7 +483,7 @@ SYM_FUNC_START(cast5_cbc_dec_16way)
+ popq %r15;
+ popq %r12;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast5_cbc_dec_16way)
+
+ SYM_FUNC_START(cast5_ctr_16way)
+@@ -559,5 +559,5 @@ SYM_FUNC_START(cast5_ctr_16way)
+ popq %r15;
+ popq %r12;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast5_ctr_16way)
+diff --git a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
+index fbddcecc3e3fc..82b716fd5dbac 100644
+--- a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
++++ b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
+@@ -289,7 +289,7 @@ SYM_FUNC_START_LOCAL(__cast6_enc_blk8)
+ outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+ outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__cast6_enc_blk8)
+
+ .align 8
+@@ -336,7 +336,7 @@ SYM_FUNC_START_LOCAL(__cast6_dec_blk8)
+ outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+ outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__cast6_dec_blk8)
+
+ SYM_FUNC_START(cast6_ecb_enc_8way)
+@@ -359,7 +359,7 @@ SYM_FUNC_START(cast6_ecb_enc_8way)
+
+ popq %r15;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast6_ecb_enc_8way)
+
+ SYM_FUNC_START(cast6_ecb_dec_8way)
+@@ -382,7 +382,7 @@ SYM_FUNC_START(cast6_ecb_dec_8way)
+
+ popq %r15;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast6_ecb_dec_8way)
+
+ SYM_FUNC_START(cast6_cbc_dec_8way)
+@@ -408,5 +408,5 @@ SYM_FUNC_START(cast6_cbc_dec_8way)
+ popq %r15;
+ popq %r12;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(cast6_cbc_dec_8way)
+diff --git a/arch/x86/crypto/chacha-avx2-x86_64.S b/arch/x86/crypto/chacha-avx2-x86_64.S
+index ee9a40ab41093..f3d8fc0182493 100644
+--- a/arch/x86/crypto/chacha-avx2-x86_64.S
++++ b/arch/x86/crypto/chacha-avx2-x86_64.S
+@@ -193,7 +193,7 @@ SYM_FUNC_START(chacha_2block_xor_avx2)
+
+ .Ldone2:
+ vzeroupper
+- ret
++ RET
+
+ .Lxorpart2:
+ # xor remaining bytes from partial register into output
+@@ -498,7 +498,7 @@ SYM_FUNC_START(chacha_4block_xor_avx2)
+
+ .Ldone4:
+ vzeroupper
+- ret
++ RET
+
+ .Lxorpart4:
+ # xor remaining bytes from partial register into output
+@@ -992,7 +992,7 @@ SYM_FUNC_START(chacha_8block_xor_avx2)
+ .Ldone8:
+ vzeroupper
+ lea -8(%r10),%rsp
+- ret
++ RET
+
+ .Lxorpart8:
+ # xor remaining bytes from partial register into output
+diff --git a/arch/x86/crypto/chacha-avx512vl-x86_64.S b/arch/x86/crypto/chacha-avx512vl-x86_64.S
+index bb193fde123a0..259383e1ad440 100644
+--- a/arch/x86/crypto/chacha-avx512vl-x86_64.S
++++ b/arch/x86/crypto/chacha-avx512vl-x86_64.S
+@@ -166,13 +166,13 @@ SYM_FUNC_START(chacha_2block_xor_avx512vl)
+
+ .Ldone2:
+ vzeroupper
+- ret
++ RET
+
+ .Lxorpart2:
+ # xor remaining bytes from partial register into output
+ mov %rcx,%rax
+ and $0xf,%rcx
+- jz .Ldone8
++ jz .Ldone2
+ mov %rax,%r9
+ and $~0xf,%r9
+
+@@ -432,13 +432,13 @@ SYM_FUNC_START(chacha_4block_xor_avx512vl)
+
+ .Ldone4:
+ vzeroupper
+- ret
++ RET
+
+ .Lxorpart4:
+ # xor remaining bytes from partial register into output
+ mov %rcx,%rax
+ and $0xf,%rcx
+- jz .Ldone8
++ jz .Ldone4
+ mov %rax,%r9
+ and $~0xf,%r9
+
+@@ -812,7 +812,7 @@ SYM_FUNC_START(chacha_8block_xor_avx512vl)
+
+ .Ldone8:
+ vzeroupper
+- ret
++ RET
+
+ .Lxorpart8:
+ # xor remaining bytes from partial register into output
+diff --git a/arch/x86/crypto/chacha-ssse3-x86_64.S b/arch/x86/crypto/chacha-ssse3-x86_64.S
+index ca1788bfee162..7111949cd5b99 100644
+--- a/arch/x86/crypto/chacha-ssse3-x86_64.S
++++ b/arch/x86/crypto/chacha-ssse3-x86_64.S
+@@ -108,7 +108,7 @@ SYM_FUNC_START_LOCAL(chacha_permute)
+ sub $2,%r8d
+ jnz .Ldoubleround
+
+- ret
++ RET
+ SYM_FUNC_END(chacha_permute)
+
+ SYM_FUNC_START(chacha_block_xor_ssse3)
+@@ -166,7 +166,7 @@ SYM_FUNC_START(chacha_block_xor_ssse3)
+
+ .Ldone:
+ FRAME_END
+- ret
++ RET
+
+ .Lxorpart:
+ # xor remaining bytes from partial register into output
+@@ -217,7 +217,7 @@ SYM_FUNC_START(hchacha_block_ssse3)
+ movdqu %xmm3,0x10(%rsi)
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(hchacha_block_ssse3)
+
+ SYM_FUNC_START(chacha_4block_xor_ssse3)
+@@ -762,7 +762,7 @@ SYM_FUNC_START(chacha_4block_xor_ssse3)
+
+ .Ldone4:
+ lea -8(%r10),%rsp
+- ret
++ RET
+
+ .Lxorpart4:
+ # xor remaining bytes from partial register into output
+diff --git a/arch/x86/crypto/crc32-pclmul_asm.S b/arch/x86/crypto/crc32-pclmul_asm.S
+index 6e7d4c4d32081..c392a6edbfff6 100644
+--- a/arch/x86/crypto/crc32-pclmul_asm.S
++++ b/arch/x86/crypto/crc32-pclmul_asm.S
+@@ -236,5 +236,5 @@ fold_64:
+ pxor %xmm2, %xmm1
+ pextrd $0x01, %xmm1, %eax
+
+- ret
++ RET
+ SYM_FUNC_END(crc32_pclmul_le_16)
+diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+index ac1f303eed0f4..80c0d22fc42c6 100644
+--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
++++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+@@ -306,7 +306,7 @@ do_return:
+ popq %rsi
+ popq %rdi
+ popq %rbx
+- ret
++ RET
+ SYM_FUNC_END(crc_pcl)
+
+ .section .rodata, "a", @progbits
+diff --git a/arch/x86/crypto/crct10dif-pcl-asm_64.S b/arch/x86/crypto/crct10dif-pcl-asm_64.S
+index b2533d63030e5..721474abfb719 100644
+--- a/arch/x86/crypto/crct10dif-pcl-asm_64.S
++++ b/arch/x86/crypto/crct10dif-pcl-asm_64.S
+@@ -257,7 +257,7 @@ SYM_FUNC_START(crc_t10dif_pcl)
+ # Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of xmm0.
+
+ pextrw $0, %xmm0, %eax
+- ret
++ RET
+
+ .align 16
+ .Lless_than_256_bytes:
+diff --git a/arch/x86/crypto/des3_ede-asm_64.S b/arch/x86/crypto/des3_ede-asm_64.S
+index fac0fdc3f25da..f4c760f4cade6 100644
+--- a/arch/x86/crypto/des3_ede-asm_64.S
++++ b/arch/x86/crypto/des3_ede-asm_64.S
+@@ -243,7 +243,7 @@ SYM_FUNC_START(des3_ede_x86_64_crypt_blk)
+ popq %r12;
+ popq %rbx;
+
+- ret;
++ RET;
+ SYM_FUNC_END(des3_ede_x86_64_crypt_blk)
+
+ /***********************************************************************
+@@ -528,7 +528,7 @@ SYM_FUNC_START(des3_ede_x86_64_crypt_blk_3way)
+ popq %r12;
+ popq %rbx;
+
+- ret;
++ RET;
+ SYM_FUNC_END(des3_ede_x86_64_crypt_blk_3way)
+
+ .section .rodata, "a", @progbits
+diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S
+index 99ac25e18e098..2bf8718999209 100644
+--- a/arch/x86/crypto/ghash-clmulni-intel_asm.S
++++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S
+@@ -85,7 +85,7 @@ SYM_FUNC_START_LOCAL(__clmul_gf128mul_ble)
+ psrlq $1, T2
+ pxor T2, T1
+ pxor T1, DATA
+- ret
++ RET
+ SYM_FUNC_END(__clmul_gf128mul_ble)
+
+ /* void clmul_ghash_mul(char *dst, const u128 *shash) */
+@@ -99,7 +99,7 @@ SYM_FUNC_START(clmul_ghash_mul)
+ pshufb BSWAP, DATA
+ movups DATA, (%rdi)
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(clmul_ghash_mul)
+
+ /*
+@@ -128,5 +128,5 @@ SYM_FUNC_START(clmul_ghash_update)
+ movups DATA, (%rdi)
+ .Lupdate_just_ret:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(clmul_ghash_update)
+diff --git a/arch/x86/crypto/nh-avx2-x86_64.S b/arch/x86/crypto/nh-avx2-x86_64.S
+index b22c7b9362726..6a0b15e7196a8 100644
+--- a/arch/x86/crypto/nh-avx2-x86_64.S
++++ b/arch/x86/crypto/nh-avx2-x86_64.S
+@@ -153,5 +153,5 @@ SYM_FUNC_START(nh_avx2)
+ vpaddq T1, T0, T0
+ vpaddq T4, T0, T0
+ vmovdqu T0, (HASH)
+- ret
++ RET
+ SYM_FUNC_END(nh_avx2)
+diff --git a/arch/x86/crypto/nh-sse2-x86_64.S b/arch/x86/crypto/nh-sse2-x86_64.S
+index d7ae22dd66839..34c567bbcb4fa 100644
+--- a/arch/x86/crypto/nh-sse2-x86_64.S
++++ b/arch/x86/crypto/nh-sse2-x86_64.S
+@@ -119,5 +119,5 @@ SYM_FUNC_START(nh_sse2)
+ paddq PASS2_SUMS, T1
+ movdqu T0, 0x00(HASH)
+ movdqu T1, 0x10(HASH)
+- ret
++ RET
+ SYM_FUNC_END(nh_sse2)
+diff --git a/arch/x86/crypto/poly1305-x86_64-cryptogams.pl b/arch/x86/crypto/poly1305-x86_64-cryptogams.pl
+index 71fae5a09e56d..2077ce7a56479 100644
+--- a/arch/x86/crypto/poly1305-x86_64-cryptogams.pl
++++ b/arch/x86/crypto/poly1305-x86_64-cryptogams.pl
+@@ -297,7 +297,7 @@ ___
+ $code.=<<___;
+ mov \$1,%eax
+ .Lno_key:
+- ret
++ RET
+ ___
+ &end_function("poly1305_init_x86_64");
+
+@@ -373,7 +373,7 @@ $code.=<<___;
+ .cfi_adjust_cfa_offset -48
+ .Lno_data:
+ .Lblocks_epilogue:
+- ret
++ RET
+ .cfi_endproc
+ ___
+ &end_function("poly1305_blocks_x86_64");
+@@ -399,7 +399,7 @@ $code.=<<___;
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+- ret
++ RET
+ ___
+ &end_function("poly1305_emit_x86_64");
+ if ($avx) {
+@@ -429,7 +429,7 @@ ___
+ &poly1305_iteration();
+ $code.=<<___;
+ pop $ctx
+- ret
++ RET
+ .size __poly1305_block,.-__poly1305_block
+
+ .type __poly1305_init_avx,\@abi-omnipotent
+@@ -594,7 +594,7 @@ __poly1305_init_avx:
+
+ lea -48-64($ctx),$ctx # size [de-]optimization
+ pop %rbp
+- ret
++ RET
+ .size __poly1305_init_avx,.-__poly1305_init_avx
+ ___
+
+@@ -747,7 +747,7 @@ $code.=<<___;
+ .cfi_restore %rbp
+ .Lno_data_avx:
+ .Lblocks_avx_epilogue:
+- ret
++ RET
+ .cfi_endproc
+
+ .align 32
+@@ -1452,7 +1452,7 @@ $code.=<<___ if (!$win64);
+ ___
+ $code.=<<___;
+ vzeroupper
+- ret
++ RET
+ .cfi_endproc
+ ___
+ &end_function("poly1305_blocks_avx");
+@@ -1508,7 +1508,7 @@ $code.=<<___;
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+- ret
++ RET
+ ___
+ &end_function("poly1305_emit_avx");
+
+@@ -1675,7 +1675,7 @@ $code.=<<___;
+ .cfi_restore %rbp
+ .Lno_data_avx2$suffix:
+ .Lblocks_avx2_epilogue$suffix:
+- ret
++ RET
+ .cfi_endproc
+
+ .align 32
+@@ -2201,7 +2201,7 @@ $code.=<<___ if (!$win64);
+ ___
+ $code.=<<___;
+ vzeroupper
+- ret
++ RET
+ .cfi_endproc
+ ___
+ if($avx > 2 && $avx512) {
+@@ -2792,7 +2792,7 @@ $code.=<<___ if (!$win64);
+ .cfi_def_cfa_register %rsp
+ ___
+ $code.=<<___;
+- ret
++ RET
+ .cfi_endproc
+ ___
+
+@@ -2893,7 +2893,7 @@ $code.=<<___ if ($flavour =~ /elf32/);
+ ___
+ $code.=<<___;
+ mov \$1,%eax
+- ret
++ RET
+ .size poly1305_init_base2_44,.-poly1305_init_base2_44
+ ___
+ {
+@@ -3010,7 +3010,7 @@ poly1305_blocks_vpmadd52:
+ jnz .Lblocks_vpmadd52_4x
+
+ .Lno_data_vpmadd52:
+- ret
++ RET
+ .size poly1305_blocks_vpmadd52,.-poly1305_blocks_vpmadd52
+ ___
+ }
+@@ -3451,7 +3451,7 @@ poly1305_blocks_vpmadd52_4x:
+ vzeroall
+
+ .Lno_data_vpmadd52_4x:
+- ret
++ RET
+ .size poly1305_blocks_vpmadd52_4x,.-poly1305_blocks_vpmadd52_4x
+ ___
+ }
+@@ -3824,7 +3824,7 @@ $code.=<<___;
+ vzeroall
+
+ .Lno_data_vpmadd52_8x:
+- ret
++ RET
+ .size poly1305_blocks_vpmadd52_8x,.-poly1305_blocks_vpmadd52_8x
+ ___
+ }
+@@ -3861,7 +3861,7 @@ poly1305_emit_base2_44:
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+- ret
++ RET
+ .size poly1305_emit_base2_44,.-poly1305_emit_base2_44
+ ___
+ } } }
+@@ -3916,7 +3916,7 @@ xor128_encrypt_n_pad:
+
+ .Ldone_enc:
+ mov $otp,%rax
+- ret
++ RET
+ .size xor128_encrypt_n_pad,.-xor128_encrypt_n_pad
+
+ .globl xor128_decrypt_n_pad
+@@ -3967,7 +3967,7 @@ xor128_decrypt_n_pad:
+
+ .Ldone_dec:
+ mov $otp,%rax
+- ret
++ RET
+ .size xor128_decrypt_n_pad,.-xor128_decrypt_n_pad
+ ___
+ }
+@@ -4109,7 +4109,7 @@ avx_handler:
+ pop %rbx
+ pop %rdi
+ pop %rsi
+- ret
++ RET
+ .size avx_handler,.-avx_handler
+
+ .section .pdata
+diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
+index b7ee24df7fbae..82f2313f512b8 100644
+--- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
++++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
+@@ -601,7 +601,7 @@ SYM_FUNC_START_LOCAL(__serpent_enc_blk8_avx)
+ write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+ write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_enc_blk8_avx)
+
+ .align 8
+@@ -655,7 +655,7 @@ SYM_FUNC_START_LOCAL(__serpent_dec_blk8_avx)
+ write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+ write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_dec_blk8_avx)
+
+ SYM_FUNC_START(serpent_ecb_enc_8way_avx)
+@@ -673,7 +673,7 @@ SYM_FUNC_START(serpent_ecb_enc_8way_avx)
+ store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_ecb_enc_8way_avx)
+
+ SYM_FUNC_START(serpent_ecb_dec_8way_avx)
+@@ -691,7 +691,7 @@ SYM_FUNC_START(serpent_ecb_dec_8way_avx)
+ store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_ecb_dec_8way_avx)
+
+ SYM_FUNC_START(serpent_cbc_dec_8way_avx)
+@@ -709,5 +709,5 @@ SYM_FUNC_START(serpent_cbc_dec_8way_avx)
+ store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_cbc_dec_8way_avx)
+diff --git a/arch/x86/crypto/serpent-avx2-asm_64.S b/arch/x86/crypto/serpent-avx2-asm_64.S
+index 9161b6e441f31..8ea34c9b93160 100644
+--- a/arch/x86/crypto/serpent-avx2-asm_64.S
++++ b/arch/x86/crypto/serpent-avx2-asm_64.S
+@@ -601,7 +601,7 @@ SYM_FUNC_START_LOCAL(__serpent_enc_blk16)
+ write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+ write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_enc_blk16)
+
+ .align 8
+@@ -655,7 +655,7 @@ SYM_FUNC_START_LOCAL(__serpent_dec_blk16)
+ write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+ write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_dec_blk16)
+
+ SYM_FUNC_START(serpent_ecb_enc_16way)
+@@ -677,7 +677,7 @@ SYM_FUNC_START(serpent_ecb_enc_16way)
+ vzeroupper;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_ecb_enc_16way)
+
+ SYM_FUNC_START(serpent_ecb_dec_16way)
+@@ -699,7 +699,7 @@ SYM_FUNC_START(serpent_ecb_dec_16way)
+ vzeroupper;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_ecb_dec_16way)
+
+ SYM_FUNC_START(serpent_cbc_dec_16way)
+@@ -722,5 +722,5 @@ SYM_FUNC_START(serpent_cbc_dec_16way)
+ vzeroupper;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_cbc_dec_16way)
+diff --git a/arch/x86/crypto/serpent-sse2-i586-asm_32.S b/arch/x86/crypto/serpent-sse2-i586-asm_32.S
+index 6379b99cb722e..8ccb03ad7cef5 100644
+--- a/arch/x86/crypto/serpent-sse2-i586-asm_32.S
++++ b/arch/x86/crypto/serpent-sse2-i586-asm_32.S
+@@ -553,12 +553,12 @@ SYM_FUNC_START(__serpent_enc_blk_4way)
+
+ write_blocks(%eax, RA, RB, RC, RD, RT0, RT1, RE);
+
+- ret;
++ RET;
+
+ .L__enc_xor4:
+ xor_blocks(%eax, RA, RB, RC, RD, RT0, RT1, RE);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_enc_blk_4way)
+
+ SYM_FUNC_START(serpent_dec_blk_4way)
+@@ -612,5 +612,5 @@ SYM_FUNC_START(serpent_dec_blk_4way)
+ movl arg_dst(%esp), %eax;
+ write_blocks(%eax, RC, RD, RB, RE, RT0, RT1, RA);
+
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_dec_blk_4way)
+diff --git a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
+index efb6dc17dc907..e0998a011d1dd 100644
+--- a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
++++ b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
+@@ -675,13 +675,13 @@ SYM_FUNC_START(__serpent_enc_blk_8way)
+ write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+ write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+
+ .L__enc_xor8:
+ xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+ xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__serpent_enc_blk_8way)
+
+ SYM_FUNC_START(serpent_dec_blk_8way)
+@@ -735,5 +735,5 @@ SYM_FUNC_START(serpent_dec_blk_8way)
+ write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+ write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(serpent_dec_blk_8way)
+diff --git a/arch/x86/crypto/sha1_avx2_x86_64_asm.S b/arch/x86/crypto/sha1_avx2_x86_64_asm.S
+index 5eed620f46765..a96b2fd26dab4 100644
+--- a/arch/x86/crypto/sha1_avx2_x86_64_asm.S
++++ b/arch/x86/crypto/sha1_avx2_x86_64_asm.S
+@@ -674,7 +674,7 @@ _loop3:
+ pop %r12
+ pop %rbx
+
+- ret
++ RET
+
+ SYM_FUNC_END(\name)
+ .endm
+diff --git a/arch/x86/crypto/sha1_ni_asm.S b/arch/x86/crypto/sha1_ni_asm.S
+index 5d8415f482bd7..2f94ec0e763bf 100644
+--- a/arch/x86/crypto/sha1_ni_asm.S
++++ b/arch/x86/crypto/sha1_ni_asm.S
+@@ -290,7 +290,7 @@ SYM_FUNC_START(sha1_ni_transform)
+ mov %rbp, %rsp
+ pop %rbp
+
+- ret
++ RET
+ SYM_FUNC_END(sha1_ni_transform)
+
+ .section .rodata.cst16.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 16
+diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S
+index d25668d2a1e92..263f916362e02 100644
+--- a/arch/x86/crypto/sha1_ssse3_asm.S
++++ b/arch/x86/crypto/sha1_ssse3_asm.S
+@@ -99,7 +99,7 @@
+ pop %rbp
+ pop %r12
+ pop %rbx
+- ret
++ RET
+
+ SYM_FUNC_END(\name)
+ .endm
+diff --git a/arch/x86/crypto/sha256-avx-asm.S b/arch/x86/crypto/sha256-avx-asm.S
+index 4739cd31b9db1..3baa1ec390974 100644
+--- a/arch/x86/crypto/sha256-avx-asm.S
++++ b/arch/x86/crypto/sha256-avx-asm.S
+@@ -458,7 +458,7 @@ done_hash:
+ popq %r13
+ popq %r12
+ popq %rbx
+- ret
++ RET
+ SYM_FUNC_END(sha256_transform_avx)
+
+ .section .rodata.cst256.K256, "aM", @progbits, 256
+diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S
+index 4087f7432a7e8..9bcdbc47b8b4b 100644
+--- a/arch/x86/crypto/sha256-avx2-asm.S
++++ b/arch/x86/crypto/sha256-avx2-asm.S
+@@ -710,7 +710,7 @@ done_hash:
+ popq %r13
+ popq %r12
+ popq %rbx
+- ret
++ RET
+ SYM_FUNC_END(sha256_transform_rorx)
+
+ .section .rodata.cst512.K256, "aM", @progbits, 512
+diff --git a/arch/x86/crypto/sha256-ssse3-asm.S b/arch/x86/crypto/sha256-ssse3-asm.S
+index ddfa863b4ee33..c4a5db612c327 100644
+--- a/arch/x86/crypto/sha256-ssse3-asm.S
++++ b/arch/x86/crypto/sha256-ssse3-asm.S
+@@ -472,7 +472,7 @@ done_hash:
+ popq %r12
+ popq %rbx
+
+- ret
++ RET
+ SYM_FUNC_END(sha256_transform_ssse3)
+
+ .section .rodata.cst256.K256, "aM", @progbits, 256
+diff --git a/arch/x86/crypto/sha256_ni_asm.S b/arch/x86/crypto/sha256_ni_asm.S
+index 7abade04a3a38..94d50dd27cb53 100644
+--- a/arch/x86/crypto/sha256_ni_asm.S
++++ b/arch/x86/crypto/sha256_ni_asm.S
+@@ -326,7 +326,7 @@ SYM_FUNC_START(sha256_ni_transform)
+
+ .Ldone_hash:
+
+- ret
++ RET
+ SYM_FUNC_END(sha256_ni_transform)
+
+ .section .rodata.cst256.K256, "aM", @progbits, 256
+diff --git a/arch/x86/crypto/sha512-avx-asm.S b/arch/x86/crypto/sha512-avx-asm.S
+index 3d8f0fd4eea87..1fefe6dd3a9e2 100644
+--- a/arch/x86/crypto/sha512-avx-asm.S
++++ b/arch/x86/crypto/sha512-avx-asm.S
+@@ -361,7 +361,7 @@ updateblock:
+ pop %rbx
+
+ nowork:
+- ret
++ RET
+ SYM_FUNC_END(sha512_transform_avx)
+
+ ########################################################################
+diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S
+index 072cb0f0deae3..5cdaab7d69015 100644
+--- a/arch/x86/crypto/sha512-avx2-asm.S
++++ b/arch/x86/crypto/sha512-avx2-asm.S
+@@ -679,7 +679,7 @@ done_hash:
+ pop %r12
+ pop %rbx
+
+- ret
++ RET
+ SYM_FUNC_END(sha512_transform_rorx)
+
+ ########################################################################
+diff --git a/arch/x86/crypto/sha512-ssse3-asm.S b/arch/x86/crypto/sha512-ssse3-asm.S
+index bd51c9070bedc..b84c22e06c5f7 100644
+--- a/arch/x86/crypto/sha512-ssse3-asm.S
++++ b/arch/x86/crypto/sha512-ssse3-asm.S
+@@ -363,7 +363,7 @@ updateblock:
+ pop %rbx
+
+ nowork:
+- ret
++ RET
+ SYM_FUNC_END(sha512_transform_ssse3)
+
+ ########################################################################
+diff --git a/arch/x86/crypto/sm4-aesni-avx-asm_64.S b/arch/x86/crypto/sm4-aesni-avx-asm_64.S
+index 1cc72b4804fab..4767ab61ff489 100644
+--- a/arch/x86/crypto/sm4-aesni-avx-asm_64.S
++++ b/arch/x86/crypto/sm4-aesni-avx-asm_64.S
+@@ -246,7 +246,7 @@ SYM_FUNC_START(sm4_aesni_avx_crypt4)
+ .Lblk4_store_output_done:
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx_crypt4)
+
+ .align 8
+@@ -356,7 +356,7 @@ SYM_FUNC_START_LOCAL(__sm4_crypt_blk8)
+ vpshufb RTMP2, RB3, RB3;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(__sm4_crypt_blk8)
+
+ /*
+@@ -412,7 +412,7 @@ SYM_FUNC_START(sm4_aesni_avx_crypt8)
+ .Lblk8_store_output_done:
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx_crypt8)
+
+ /*
+@@ -487,7 +487,7 @@ SYM_FUNC_START(sm4_aesni_avx_ctr_enc_blk8)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx_ctr_enc_blk8)
+
+ /*
+@@ -537,7 +537,7 @@ SYM_FUNC_START(sm4_aesni_avx_cbc_dec_blk8)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx_cbc_dec_blk8)
+
+ /*
+@@ -590,5 +590,5 @@ SYM_FUNC_START(sm4_aesni_avx_cfb_dec_blk8)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx_cfb_dec_blk8)
+diff --git a/arch/x86/crypto/sm4-aesni-avx2-asm_64.S b/arch/x86/crypto/sm4-aesni-avx2-asm_64.S
+index 9c5d3f3ad45a9..4732fe8bb65b6 100644
+--- a/arch/x86/crypto/sm4-aesni-avx2-asm_64.S
++++ b/arch/x86/crypto/sm4-aesni-avx2-asm_64.S
+@@ -268,7 +268,7 @@ SYM_FUNC_START_LOCAL(__sm4_crypt_blk16)
+ vpshufb RTMP2, RB3, RB3;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(__sm4_crypt_blk16)
+
+ #define inc_le128(x, minus_one, tmp) \
+@@ -387,7 +387,7 @@ SYM_FUNC_START(sm4_aesni_avx2_ctr_enc_blk16)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx2_ctr_enc_blk16)
+
+ /*
+@@ -441,7 +441,7 @@ SYM_FUNC_START(sm4_aesni_avx2_cbc_dec_blk16)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx2_cbc_dec_blk16)
+
+ /*
+@@ -497,5 +497,5 @@ SYM_FUNC_START(sm4_aesni_avx2_cfb_dec_blk16)
+
+ vzeroall;
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(sm4_aesni_avx2_cfb_dec_blk16)
+diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
+index 37e63b3c664eb..31f9b2ec3857d 100644
+--- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
++++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
+@@ -267,7 +267,7 @@ SYM_FUNC_START_LOCAL(__twofish_enc_blk8)
+ outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+ outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__twofish_enc_blk8)
+
+ .align 8
+@@ -307,7 +307,7 @@ SYM_FUNC_START_LOCAL(__twofish_dec_blk8)
+ outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+ outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+
+- ret;
++ RET;
+ SYM_FUNC_END(__twofish_dec_blk8)
+
+ SYM_FUNC_START(twofish_ecb_enc_8way)
+@@ -327,7 +327,7 @@ SYM_FUNC_START(twofish_ecb_enc_8way)
+ store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(twofish_ecb_enc_8way)
+
+ SYM_FUNC_START(twofish_ecb_dec_8way)
+@@ -347,7 +347,7 @@ SYM_FUNC_START(twofish_ecb_dec_8way)
+ store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(twofish_ecb_dec_8way)
+
+ SYM_FUNC_START(twofish_cbc_dec_8way)
+@@ -372,5 +372,5 @@ SYM_FUNC_START(twofish_cbc_dec_8way)
+ popq %r12;
+
+ FRAME_END
+- ret;
++ RET;
+ SYM_FUNC_END(twofish_cbc_dec_8way)
+diff --git a/arch/x86/crypto/twofish-i586-asm_32.S b/arch/x86/crypto/twofish-i586-asm_32.S
+index a6f09e4f2e463..3abcad6618840 100644
+--- a/arch/x86/crypto/twofish-i586-asm_32.S
++++ b/arch/x86/crypto/twofish-i586-asm_32.S
+@@ -260,7 +260,7 @@ SYM_FUNC_START(twofish_enc_blk)
+ pop %ebx
+ pop %ebp
+ mov $1, %eax
+- ret
++ RET
+ SYM_FUNC_END(twofish_enc_blk)
+
+ SYM_FUNC_START(twofish_dec_blk)
+@@ -317,5 +317,5 @@ SYM_FUNC_START(twofish_dec_blk)
+ pop %ebx
+ pop %ebp
+ mov $1, %eax
+- ret
++ RET
+ SYM_FUNC_END(twofish_dec_blk)
+diff --git a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
+index bca4cea757ce2..d2288bf38a8a5 100644
+--- a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
++++ b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
+@@ -258,7 +258,7 @@ SYM_FUNC_START(__twofish_enc_blk_3way)
+ popq %rbx;
+ popq %r12;
+ popq %r13;
+- ret;
++ RET;
+
+ .L__enc_xor3:
+ outunpack_enc3(xor);
+@@ -266,7 +266,7 @@ SYM_FUNC_START(__twofish_enc_blk_3way)
+ popq %rbx;
+ popq %r12;
+ popq %r13;
+- ret;
++ RET;
+ SYM_FUNC_END(__twofish_enc_blk_3way)
+
+ SYM_FUNC_START(twofish_dec_blk_3way)
+@@ -301,5 +301,5 @@ SYM_FUNC_START(twofish_dec_blk_3way)
+ popq %rbx;
+ popq %r12;
+ popq %r13;
+- ret;
++ RET;
+ SYM_FUNC_END(twofish_dec_blk_3way)
+diff --git a/arch/x86/crypto/twofish-x86_64-asm_64.S b/arch/x86/crypto/twofish-x86_64-asm_64.S
+index d2e56232494a8..775af290cd196 100644
+--- a/arch/x86/crypto/twofish-x86_64-asm_64.S
++++ b/arch/x86/crypto/twofish-x86_64-asm_64.S
+@@ -252,7 +252,7 @@ SYM_FUNC_START(twofish_enc_blk)
+
+ popq R1
+ movl $1,%eax
+- ret
++ RET
+ SYM_FUNC_END(twofish_enc_blk)
+
+ SYM_FUNC_START(twofish_dec_blk)
+@@ -304,5 +304,5 @@ SYM_FUNC_START(twofish_dec_blk)
+
+ popq R1
+ movl $1,%eax
+- ret
++ RET
+ SYM_FUNC_END(twofish_dec_blk)
+diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
+index ccb9d32768f31..00413e37feee1 100644
+--- a/arch/x86/entry/entry_32.S
++++ b/arch/x86/entry/entry_32.S
+@@ -740,7 +740,7 @@ SYM_FUNC_START(schedule_tail_wrapper)
+ popl %eax
+
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(schedule_tail_wrapper)
+ .popsection
+
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
-index e38a4cf795d96..97b1f84bb53f8 100644
+index e38a4cf795d96..e23319ad3f42a 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -574,6 +574,10 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
@@ -16639,7 +26261,22 @@ index e38a4cf795d96..97b1f84bb53f8 100644
POP_REGS pop_rdi=0
/*
-@@ -890,6 +894,7 @@ SYM_CODE_START_LOCAL(paranoid_entry)
+@@ -734,7 +738,7 @@ SYM_FUNC_START(asm_load_gs_index)
+ 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
+ swapgs
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(asm_load_gs_index)
+ EXPORT_SYMBOL(asm_load_gs_index)
+
+@@ -885,11 +889,12 @@ SYM_CODE_START_LOCAL(paranoid_entry)
+ * is needed here.
+ */
+ SAVE_AND_SET_GSBASE scratch_reg=%rax save_reg=%rbx
+- ret
++ RET
+
.Lparanoid_entry_checkgs:
/* EBX = 1 -> kernel GSBASE active, no restore required */
movl $1, %ebx
@@ -16647,7 +26284,7 @@ index e38a4cf795d96..97b1f84bb53f8 100644
/*
* The kernel-enforced convention is a negative GSBASE indicates
* a kernel value. No SWAPGS needed on entry and exit.
-@@ -897,21 +902,14 @@ SYM_CODE_START_LOCAL(paranoid_entry)
+@@ -897,22 +902,15 @@ SYM_CODE_START_LOCAL(paranoid_entry)
movl $MSR_GS_BASE, %ecx
rdmsr
testl %edx, %edx
@@ -16670,21 +26307,25 @@ index e38a4cf795d96..97b1f84bb53f8 100644
-
- /* EBX = 0 -> SWAPGS required on exit */
- xorl %ebx, %ebx
- ret
+- ret
++ RET
SYM_CODE_END(paranoid_entry)
-@@ -993,11 +991,6 @@ SYM_CODE_START_LOCAL(error_entry)
+ /*
+@@ -991,12 +989,7 @@ SYM_CODE_START_LOCAL(error_entry)
+ movq %rax, %rsp /* switch stack */
+ ENCODE_FRAME_POINTER
pushq %r12
- ret
-
+- ret
+-
-.Lerror_entry_done_lfence:
- FENCE_SWAPGS_KERNEL_ENTRY
-.Lerror_entry_done:
- ret
--
++ RET
+
/*
* There are two places in the kernel that can potentially fault with
- * usergs. Handle them here. B stepping K8s sometimes report a
@@ -1020,8 +1013,14 @@ SYM_CODE_START_LOCAL(error_entry)
* .Lgs_change's error handler with kernel gsbase.
*/
@@ -16698,10 +26339,62 @@ index e38a4cf795d96..97b1f84bb53f8 100644
+ */
+.Lerror_entry_done_lfence:
+ FENCE_SWAPGS_KERNEL_ENTRY
-+ ret
++ RET
.Lbstep_iret:
/* Fix truncated RIP */
+diff --git a/arch/x86/entry/thunk_32.S b/arch/x86/entry/thunk_32.S
+index f1f96d4d8cd60..7591bab060f70 100644
+--- a/arch/x86/entry/thunk_32.S
++++ b/arch/x86/entry/thunk_32.S
+@@ -24,7 +24,7 @@ SYM_CODE_START_NOALIGN(\name)
+ popl %edx
+ popl %ecx
+ popl %eax
+- ret
++ RET
+ _ASM_NOKPROBE(\name)
+ SYM_CODE_END(\name)
+ .endm
+diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S
+index 496b11ec469de..505b488fcc655 100644
+--- a/arch/x86/entry/thunk_64.S
++++ b/arch/x86/entry/thunk_64.S
+@@ -50,7 +50,7 @@ SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore)
+ popq %rsi
+ popq %rdi
+ popq %rbp
+- ret
++ RET
+ _ASM_NOKPROBE(__thunk_restore)
+ SYM_CODE_END(__thunk_restore)
+ #endif
+diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S
+index 6ddd7a937b3e3..d33c6513fd2cb 100644
+--- a/arch/x86/entry/vdso/vdso32/system_call.S
++++ b/arch/x86/entry/vdso/vdso32/system_call.S
+@@ -78,7 +78,7 @@ SYM_INNER_LABEL(int80_landing_pad, SYM_L_GLOBAL)
+ popl %ecx
+ CFI_RESTORE ecx
+ CFI_ADJUST_CFA_OFFSET -4
+- ret
++ RET
+ CFI_ENDPROC
+
+ .size __kernel_vsyscall,.-__kernel_vsyscall
+diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
+index 99dafac992e2c..d77d278ee9dd6 100644
+--- a/arch/x86/entry/vdso/vsgx.S
++++ b/arch/x86/entry/vdso/vsgx.S
+@@ -81,7 +81,7 @@ SYM_FUNC_START(__vdso_sgx_enter_enclave)
+ pop %rbx
+ leave
+ .cfi_def_cfa %rsp, 8
+- ret
++ RET
+
+ /* The out-of-line code runs with the pre-leave stack frame. */
+ .cfi_def_cfa %rbp, 16
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 1b40b92970831..fd2ee9408e914 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -16716,6 +26409,31 @@ index 1b40b92970831..fd2ee9408e914 100644
}
regs->orig_ax = -1;
if (tmp)
+diff --git a/arch/x86/entry/vsyscall/vsyscall_emu_64.S b/arch/x86/entry/vsyscall/vsyscall_emu_64.S
+index 2e203f3a25a7b..15e35159ebb68 100644
+--- a/arch/x86/entry/vsyscall/vsyscall_emu_64.S
++++ b/arch/x86/entry/vsyscall/vsyscall_emu_64.S
+@@ -19,17 +19,17 @@ __vsyscall_page:
+
+ mov $__NR_gettimeofday, %rax
+ syscall
+- ret
++ RET
+
+ .balign 1024, 0xcc
+ mov $__NR_time, %rax
+ syscall
+- ret
++ RET
+
+ .balign 1024, 0xcc
+ mov $__NR_getcpu, %rax
+ syscall
+- ret
++ RET
+
+ .balign 4096, 0xcc
+
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 6dfa8ddaa60f7..81d5e0a1f48cd 100644
--- a/arch/x86/events/core.c
@@ -16773,7 +26491,7 @@ index 6dfa8ddaa60f7..81d5e0a1f48cd 100644
else
misc |= PERF_RECORD_MISC_GUEST_KERNEL;
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
-index 9a044438072ba..97ede6fb15f26 100644
+index 9a044438072ba..265cb203d9d5c 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -243,7 +243,8 @@ static struct extra_reg intel_skl_extra_regs[] __read_mostly = {
@@ -16786,6 +26504,15 @@ index 9a044438072ba..97ede6fb15f26 100644
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */
+@@ -280,7 +281,7 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = {
+ INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
+ INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+ INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+- INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
++ INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff1f, FE),
+ INTEL_UEVENT_EXTRA_REG(0x40ad, MSR_PEBS_FRONTEND, 0x7, FE),
+ INTEL_UEVENT_EXTRA_REG(0x04c2, MSR_PEBS_FRONTEND, 0x8, FE),
+ EVENT_EXTRA_END
@@ -288,7 +289,7 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = {
static struct event_constraint intel_spr_event_constraints[] = {
@@ -16850,7 +26577,20 @@ index 9a044438072ba..97ede6fb15f26 100644
};
static __init void intel_clovertown_quirk(void)
-@@ -6181,6 +6200,19 @@ __init int intel_pmu_init(void)
+@@ -5447,7 +5466,11 @@ static void intel_pmu_check_event_constraints(struct event_constraint *event_con
+ /* Disabled fixed counters which are not in CPUID */
+ c->idxmsk64 &= intel_ctrl;
+
+- if (c->idxmsk64 != INTEL_PMC_MSK_FIXED_REF_CYCLES)
++ /*
++ * Don't extend the pseudo-encoding to the
++ * generic counters
++ */
++ if (!use_fixed_pseudo_encoding(c->code))
+ c->idxmsk64 |= (1ULL << num_counters) - 1;
+ }
+ c->idxmsk64 &=
+@@ -6181,6 +6204,19 @@ __init int intel_pmu_init(void)
pmu->num_counters = x86_pmu.num_counters;
pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
}
@@ -16908,9 +26648,18 @@ index 9e6d6eaeb4cb6..f455dd93f9219 100644
return false;
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
-index 7f406c14715fd..2d33bba9a1440 100644
+index 7f406c14715fd..215aed65e9782 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
+@@ -472,7 +472,7 @@ static u64 pt_config_filters(struct perf_event *event)
+ pt->filters.filter[range].msr_b = filter->msr_b;
+ }
+
+- rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
++ rtit_ctl |= (u64)filter->config << pt_address_ranges[range].reg_off;
+ }
+
+ return rtit_ctl;
@@ -897,8 +897,9 @@ static void pt_handle_status(struct pt *pt)
* means we are already losing data; need to let the decoder
* know.
@@ -17178,7 +26927,7 @@ index bd13736d0c054..0ad2378fe6ad7 100644
/*
diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
-index 84b87538a15de..bab883c0b6fee 100644
+index 84b87538a15de..66570e95af398 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -22,7 +22,7 @@
@@ -17242,14 +26991,36 @@ index 84b87538a15de..bab883c0b6fee 100644
*/
#define __WARN_FLAGS(flags) \
do { \
-+ __auto_type f = BUGFLAG_WARNING|(flags); \
++ __auto_type __flags = BUGFLAG_WARNING|(flags); \
instrumentation_begin(); \
- _BUG_FLAGS(ASM_UD2, BUGFLAG_WARNING|(flags)); \
- annotate_reachable(); \
-+ _BUG_FLAGS(ASM_UD2, f, ASM_REACHABLE); \
++ _BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \
instrumentation_end(); \
} while (0)
+diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
+index 7516e4199b3c6..20fd0acd7d800 100644
+--- a/arch/x86/include/asm/compat.h
++++ b/arch/x86/include/asm/compat.h
+@@ -28,15 +28,13 @@ typedef u16 compat_ipc_pid_t;
+ typedef __kernel_fsid_t compat_fsid_t;
+
+ struct compat_stat {
+- compat_dev_t st_dev;
+- u16 __pad1;
++ u32 st_dev;
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
+- compat_dev_t st_rdev;
+- u16 __pad2;
++ u32 st_rdev;
+ u32 st_size;
+ u32 st_blksize;
+ u32 st_blocks;
diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h
index 3d52b094850a9..dd5ea1bdf04c5 100644
--- a/arch/x86/include/asm/cpu_entry_area.h
@@ -17315,7 +27086,7 @@ index 91d7182ad2d6e..4ec3613551e3b 100644
unsigned char buf[MAX_INSN_SIZE]);
int insn_fetch_from_user_inatomic(struct pt_regs *regs,
diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h
-index 562854c608082..8d55bd11848cb 100644
+index 562854c608082..e087cd7837c31 100644
--- a/arch/x86/include/asm/irq_stack.h
+++ b/arch/x86/include/asm/irq_stack.h
@@ -77,11 +77,11 @@
@@ -17332,12 +27103,13 @@ index 562854c608082..8d55bd11848cb 100644
\
asm_inline volatile( \
"movq %%rsp, (%[tos]) \n" \
-@@ -98,6 +98,25 @@
+@@ -98,6 +98,26 @@
); \
}
+#define ASM_CALL_ARG0 \
-+ "call %P[__func] \n"
++ "call %P[__func] \n" \
++ ASM_REACHABLE
+
+#define ASM_CALL_ARG1 \
+ "movq %[arg1], %%rdi \n" \
@@ -17358,7 +27130,7 @@ index 562854c608082..8d55bd11848cb 100644
/* Macros to assert type correctness for run_*_on_irqstack macros */
#define assert_function_type(func, proto) \
static_assert(__builtin_types_compatible_p(typeof(&func), proto))
-@@ -147,8 +166,7 @@
+@@ -147,8 +167,7 @@
*/
#define ASM_CALL_SYSVEC \
"call irq_enter_rcu \n" \
@@ -17368,7 +27140,7 @@ index 562854c608082..8d55bd11848cb 100644
"call irq_exit_rcu \n"
#define SYSVEC_CONSTRAINTS , [arg1] "r" (regs)
-@@ -168,12 +186,10 @@
+@@ -168,12 +187,10 @@
*/
#define ASM_CALL_IRQ \
"call irq_enter_rcu \n" \
@@ -17383,7 +27155,7 @@ index 562854c608082..8d55bd11848cb 100644
#define run_irq_on_irqstack_cond(func, regs, vector) \
{ \
-@@ -185,9 +201,6 @@
+@@ -185,9 +202,6 @@
IRQ_CONSTRAINTS, regs, vector); \
}
@@ -17393,7 +27165,7 @@ index 562854c608082..8d55bd11848cb 100644
/*
* Macro to invoke __do_softirq on the irq stack. This is only called from
* task context when bottom halves are about to be reenabled and soft
-@@ -197,7 +210,7 @@
+@@ -197,7 +211,7 @@
#define do_softirq_own_stack() \
{ \
__this_cpu_write(hardirq_stack_inuse, true); \
@@ -17415,7 +27187,7 @@ index cefe1d81e2e8b..9e50da3ed01a3 100644
KVM_X86_OP(tlb_flush_current)
KVM_X86_OP_NULL(tlb_remote_flush)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
-index 13f64654dfff8..01759199d7238 100644
+index 13f64654dfff8..49d814b2a341a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -98,7 +98,7 @@
@@ -17435,7 +27207,15 @@ index 13f64654dfff8..01759199d7238 100644
};
};
-@@ -751,7 +752,7 @@ struct kvm_vcpu_arch {
+@@ -504,6 +505,7 @@ struct kvm_pmu {
+ u64 global_ctrl_mask;
+ u64 global_ovf_ctrl_mask;
+ u64 reserved_bits;
++ u64 raw_event_mask;
+ u8 version;
+ struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
+ struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
+@@ -751,7 +753,7 @@ struct kvm_vcpu_arch {
u8 preempted;
u64 msr_val;
u64 last_steal;
@@ -17444,7 +27224,7 @@ index 13f64654dfff8..01759199d7238 100644
} st;
u64 l1_tsc_offset;
-@@ -1340,6 +1341,7 @@ struct kvm_x86_ops {
+@@ -1340,6 +1342,7 @@ struct kvm_x86_ops {
void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
@@ -17452,7 +27232,7 @@ index 13f64654dfff8..01759199d7238 100644
void (*tlb_flush_all)(struct kvm_vcpu *vcpu);
void (*tlb_flush_current)(struct kvm_vcpu *vcpu);
-@@ -1485,6 +1487,7 @@ struct kvm_x86_ops {
+@@ -1485,6 +1488,7 @@ struct kvm_x86_ops {
};
struct kvm_x86_nested_ops {
@@ -17460,7 +27240,7 @@ index 13f64654dfff8..01759199d7238 100644
int (*check_events)(struct kvm_vcpu *vcpu);
bool (*hv_timer_pending)(struct kvm_vcpu *vcpu);
void (*triple_fault)(struct kvm_vcpu *vcpu);
-@@ -1507,6 +1510,7 @@ struct kvm_x86_init_ops {
+@@ -1507,6 +1511,7 @@ struct kvm_x86_init_ops {
int (*disabled_by_bios)(void);
int (*check_processor_compatibility)(void);
int (*hardware_setup)(void);
@@ -17468,6 +27248,43 @@ index 13f64654dfff8..01759199d7238 100644
struct kvm_x86_ops *runtime_ops;
};
+@@ -1554,8 +1559,9 @@ static inline int kvm_arch_flush_remote_tlb(struct kvm *kvm)
+ return -ENOTSUPP;
+ }
+
+-int kvm_mmu_module_init(void);
+-void kvm_mmu_module_exit(void);
++void kvm_mmu_x86_module_init(void);
++int kvm_mmu_vendor_module_init(void);
++void kvm_mmu_vendor_module_exit(void);
+
+ void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
+ int kvm_mmu_create(struct kvm_vcpu *vcpu);
+diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
+index 365111789cc68..030907922bd07 100644
+--- a/arch/x86/include/asm/linkage.h
++++ b/arch/x86/include/asm/linkage.h
+@@ -18,6 +18,20 @@
+ #define __ALIGN_STR __stringify(__ALIGN)
+ #endif
+
++#ifdef CONFIG_SLS
++#define RET ret; int3
++#else
++#define RET ret
++#endif
++
++#else /* __ASSEMBLY__ */
++
++#ifdef CONFIG_SLS
++#define ASM_RET "ret; int3\n\t"
++#else
++#define ASM_RET "ret\n\t"
++#endif
++
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* _ASM_X86_LINKAGE_H */
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 9c80c68d75b54..3fb9f5ebefa42 100644
--- a/arch/x86/include/asm/mem_encrypt.h
@@ -17480,6 +27297,69 @@ index 9c80c68d75b54..3fb9f5ebefa42 100644
#include <asm/bootparam.h>
+diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
+index ab45a220fac47..fcbfe94903bb8 100644
+--- a/arch/x86/include/asm/microcode.h
++++ b/arch/x86/include/asm/microcode.h
+@@ -132,10 +132,12 @@ extern void load_ucode_ap(void);
+ void reload_early_microcode(void);
+ extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+ extern bool initrd_gone;
++void microcode_bsp_resume(void);
+ #else
+ static inline void __init load_ucode_bsp(void) { }
+ static inline void load_ucode_ap(void) { }
+ static inline void reload_early_microcode(void) { }
++static inline void microcode_bsp_resume(void) { }
+ static inline bool
+ get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; }
+ #endif
+diff --git a/arch/x86/include/asm/msi.h b/arch/x86/include/asm/msi.h
+index b85147d75626e..d71c7e8b738d2 100644
+--- a/arch/x86/include/asm/msi.h
++++ b/arch/x86/include/asm/msi.h
+@@ -12,14 +12,17 @@ int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
+ /* Structs and defines for the X86 specific MSI message format */
+
+ typedef struct x86_msi_data {
+- u32 vector : 8,
+- delivery_mode : 3,
+- dest_mode_logical : 1,
+- reserved : 2,
+- active_low : 1,
+- is_level : 1;
+-
+- u32 dmar_subhandle;
++ union {
++ struct {
++ u32 vector : 8,
++ delivery_mode : 3,
++ dest_mode_logical : 1,
++ reserved : 2,
++ active_low : 1,
++ is_level : 1;
++ };
++ u32 dmar_subhandle;
++ };
+ } __attribute__ ((packed)) arch_msi_msg_data_t;
+ #define arch_msi_msg_data x86_msi_data
+
+diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
+index a7c413432b33d..66ae309840fef 100644
+--- a/arch/x86/include/asm/msr-index.h
++++ b/arch/x86/include/asm/msr-index.h
+@@ -128,9 +128,9 @@
+ #define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */
+ #define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */
+
+-/* SRBDS support */
+ #define MSR_IA32_MCU_OPT_CTRL 0x00000123
+-#define RNGDS_MITG_DIS BIT(0)
++#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
++#define RTM_ALLOW BIT(1) /* TSX development mode */
+
+ #define MSR_IA32_SYSENTER_CS 0x00000174
+ #define MSR_IA32_SYSENTER_ESP 0x00000175
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index ec2d5c8c66947..b3dd514f80a0b 100644
--- a/arch/x86/include/asm/nospec-branch.h
@@ -17548,6 +27428,35 @@ index a8d4ad8565681..e9e2c3ba59239 100644
#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
#define IRQ_STACK_ORDER (2 + KASAN_STACK_ORDER)
+diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
+index da3a1ac82be58..4d8b2731f4f85 100644
+--- a/arch/x86/include/asm/paravirt.h
++++ b/arch/x86/include/asm/paravirt.h
+@@ -665,7 +665,7 @@ bool __raw_callee_save___native_vcpu_is_preempted(long cpu);
+ "call " #func ";" \
+ PV_RESTORE_ALL_CALLER_REGS \
+ FRAME_END \
+- "ret;" \
++ ASM_RET \
+ ".size " PV_THUNK_NAME(func) ", .-" PV_THUNK_NAME(func) ";" \
+ ".popsection")
+
+diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
+index 8fc1b5003713f..a2b6626c681f5 100644
+--- a/arch/x86/include/asm/perf_event.h
++++ b/arch/x86/include/asm/perf_event.h
+@@ -241,6 +241,11 @@ struct x86_pmu_capability {
+ #define INTEL_PMC_IDX_FIXED_SLOTS (INTEL_PMC_IDX_FIXED + 3)
+ #define INTEL_PMC_MSK_FIXED_SLOTS (1ULL << INTEL_PMC_IDX_FIXED_SLOTS)
+
++static inline bool use_fixed_pseudo_encoding(u64 code)
++{
++ return !(code & 0xff);
++}
++
+ /*
+ * We model BTS tracing as another fixed-mode PMC.
+ *
diff --git a/arch/x86/include/asm/pkru.h b/arch/x86/include/asm/pkru.h
index ccc539faa5bbc..4d8b9448fe8d2 100644
--- a/arch/x86/include/asm/pkru.h
@@ -17575,6 +27484,28 @@ index 9ad2acaaae9b8..577f342dbfb27 100644
unsigned int sig_on_uaccess_err:1;
/*
+diff --git a/arch/x86/include/asm/qspinlock_paravirt.h b/arch/x86/include/asm/qspinlock_paravirt.h
+index 159622ee06748..1474cf96251dd 100644
+--- a/arch/x86/include/asm/qspinlock_paravirt.h
++++ b/arch/x86/include/asm/qspinlock_paravirt.h
+@@ -48,7 +48,7 @@ asm (".pushsection .text;"
+ "jne .slowpath;"
+ "pop %rdx;"
+ FRAME_END
+- "ret;"
++ ASM_RET
+ ".slowpath: "
+ "push %rsi;"
+ "movzbl %al,%esi;"
+@@ -56,7 +56,7 @@ asm (".pushsection .text;"
+ "pop %rsi;"
+ "pop %rdx;"
+ FRAME_END
+- "ret;"
++ ASM_RET
+ ".size " PV_UNLOCK ", .-" PV_UNLOCK ";"
+ ".popsection");
+
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 5db5d083c8732..331474b150f16 100644
--- a/arch/x86/include/asm/realmode.h
@@ -17608,6 +27539,39 @@ index f248eb2ac2d4a..3881b5333eb81 100644
const char *stack_type_name(enum stack_type type);
static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
+diff --git a/arch/x86/include/asm/static_call.h b/arch/x86/include/asm/static_call.h
+index cbb67b6030f97..3432345693927 100644
+--- a/arch/x86/include/asm/static_call.h
++++ b/arch/x86/include/asm/static_call.h
+@@ -35,7 +35,7 @@
+ __ARCH_DEFINE_STATIC_CALL_TRAMP(name, ".byte 0xe9; .long " #func " - (. + 4)")
+
+ #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \
+- __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; nop; nop; nop; nop")
++ __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; int3; nop; nop; nop")
+
+
+ #define ARCH_ADD_TRAMP_KEY(name) \
+diff --git a/arch/x86/include/asm/timex.h b/arch/x86/include/asm/timex.h
+index a4a8b1b16c0c1..956e4145311b1 100644
+--- a/arch/x86/include/asm/timex.h
++++ b/arch/x86/include/asm/timex.h
+@@ -5,6 +5,15 @@
+ #include <asm/processor.h>
+ #include <asm/tsc.h>
+
++static inline unsigned long random_get_entropy(void)
++{
++ if (!IS_ENABLED(CONFIG_X86_TSC) &&
++ !cpu_feature_enabled(X86_FEATURE_TSC))
++ return random_get_entropy_fallback();
++ return rdtsc();
++}
++#define random_get_entropy random_get_entropy
++
+ /* Assume we use the PIT time source for the clock tick */
+ #define CLOCK_TICK_RATE PIT_TICK_RATE
+
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 9239399e54914..55160445ea78b 100644
--- a/arch/x86/include/asm/topology.h
@@ -17638,6 +27602,27 @@ index 7f7200021bd13..6221be7cafc3b 100644
#endif
#endif /* _ASM_X86_TRAPS_H */
+diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
+index 01a300a9700b9..fbdc3d9514943 100644
+--- a/arch/x86/include/asm/tsc.h
++++ b/arch/x86/include/asm/tsc.h
+@@ -20,13 +20,12 @@ extern void disable_TSC(void);
+
+ static inline cycles_t get_cycles(void)
+ {
+-#ifndef CONFIG_X86_TSC
+- if (!boot_cpu_has(X86_FEATURE_TSC))
++ if (!IS_ENABLED(CONFIG_X86_TSC) &&
++ !cpu_feature_enabled(X86_FEATURE_TSC))
+ return 0;
+-#endif
+-
+ return rdtsc();
+ }
++#define get_cycles get_cycles
+
+ extern struct system_counterval_t convert_art_to_tsc(u64 art);
+ extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 5c95d242f38d7..bb1430283c726 100644
--- a/arch/x86/include/asm/uaccess.h
@@ -17709,6 +27694,226 @@ index 8f4e8fa6ed759..2ff3e600f4269 100644
###
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 14bcd59bcdee2..94ac7402c1ac2 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -1319,6 +1319,17 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d)
+ return 0;
+ }
+
++static int __init disable_acpi_xsdt(const struct dmi_system_id *d)
++{
++ if (!acpi_force) {
++ pr_notice("%s detected: force use of acpi=rsdt\n", d->ident);
++ acpi_gbl_do_not_use_xsdt = TRUE;
++ } else {
++ pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n");
++ }
++ return 0;
++}
++
+ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
+ {
+ if (!acpi_force) {
+@@ -1442,6 +1453,19 @@ static const struct dmi_system_id acpi_dmi_table[] __initconst = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+ },
+ },
++ /*
++ * Boxes that need ACPI XSDT use disabled due to corrupted tables
++ */
++ {
++ .callback = disable_acpi_xsdt,
++ .ident = "Advantech DAC-BJ01",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"),
++ DMI_MATCH(DMI_BIOS_VERSION, "V1.12"),
++ DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"),
++ },
++ },
+ {}
+ };
+
+diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
+index daf88f8143c5f..cf69081073b54 100644
+--- a/arch/x86/kernel/acpi/wakeup_32.S
++++ b/arch/x86/kernel/acpi/wakeup_32.S
+@@ -60,7 +60,7 @@ save_registers:
+ popl saved_context_eflags
+
+ movl $ret_point, saved_eip
+- ret
++ RET
+
+
+ restore_registers:
+@@ -70,7 +70,7 @@ restore_registers:
+ movl saved_context_edi, %edi
+ pushl saved_context_eflags
+ popfl
+- ret
++ RET
+
+ SYM_CODE_START(do_suspend_lowlevel)
+ call save_processor_state
+@@ -86,7 +86,7 @@ SYM_CODE_START(do_suspend_lowlevel)
+ ret_point:
+ call restore_registers
+ call restore_processor_state
+- ret
++ RET
+ SYM_CODE_END(do_suspend_lowlevel)
+
+ .data
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index e9da3dc712541..ae0f718b8ebb5 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -537,7 +537,7 @@ asm (
+ " .type int3_magic, @function\n"
+ "int3_magic:\n"
+ " movl $1, (%" _ASM_ARG1 ")\n"
+-" ret\n"
++ ASM_RET
+ " .size int3_magic, .-int3_magic\n"
+ " .popsection\n"
+ );
+@@ -930,10 +930,13 @@ void text_poke_sync(void)
+ }
+
+ struct text_poke_loc {
+- s32 rel_addr; /* addr := _stext + rel_addr */
+- s32 rel32;
++ /* addr := _stext + rel_addr */
++ s32 rel_addr;
++ s32 disp;
++ u8 len;
+ u8 opcode;
+ const u8 text[POKE_MAX_OPCODE_SIZE];
++ /* see text_poke_bp_batch() */
+ u8 old;
+ };
+
+@@ -948,7 +951,8 @@ static struct bp_patching_desc *bp_desc;
+ static __always_inline
+ struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp)
+ {
+- struct bp_patching_desc *desc = __READ_ONCE(*descp); /* rcu_dereference */
++ /* rcu_dereference */
++ struct bp_patching_desc *desc = __READ_ONCE(*descp);
+
+ if (!desc || !arch_atomic_inc_not_zero(&desc->refs))
+ return NULL;
+@@ -982,7 +986,7 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
+ {
+ struct bp_patching_desc *desc;
+ struct text_poke_loc *tp;
+- int len, ret = 0;
++ int ret = 0;
+ void *ip;
+
+ if (user_mode(regs))
+@@ -1022,8 +1026,7 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
+ goto out_put;
+ }
+
+- len = text_opcode_size(tp->opcode);
+- ip += len;
++ ip += tp->len;
+
+ switch (tp->opcode) {
+ case INT3_INSN_OPCODE:
+@@ -1038,12 +1041,12 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
+ break;
+
+ case CALL_INSN_OPCODE:
+- int3_emulate_call(regs, (long)ip + tp->rel32);
++ int3_emulate_call(regs, (long)ip + tp->disp);
+ break;
+
+ case JMP32_INSN_OPCODE:
+ case JMP8_INSN_OPCODE:
+- int3_emulate_jmp(regs, (long)ip + tp->rel32);
++ int3_emulate_jmp(regs, (long)ip + tp->disp);
+ break;
+
+ default:
+@@ -1118,7 +1121,7 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries
+ */
+ for (do_sync = 0, i = 0; i < nr_entries; i++) {
+ u8 old[POKE_MAX_OPCODE_SIZE] = { tp[i].old, };
+- int len = text_opcode_size(tp[i].opcode);
++ int len = tp[i].len;
+
+ if (len - INT3_INSN_SIZE > 0) {
+ memcpy(old + INT3_INSN_SIZE,
+@@ -1195,20 +1198,36 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
+ const void *opcode, size_t len, const void *emulate)
+ {
+ struct insn insn;
+- int ret;
++ int ret, i;
+
+ memcpy((void *)tp->text, opcode, len);
+ if (!emulate)
+ emulate = opcode;
+
+ ret = insn_decode_kernel(&insn, emulate);
+-
+ BUG_ON(ret < 0);
+- BUG_ON(len != insn.length);
+
+ tp->rel_addr = addr - (void *)_stext;
++ tp->len = len;
+ tp->opcode = insn.opcode.bytes[0];
+
++ switch (tp->opcode) {
++ case RET_INSN_OPCODE:
++ case JMP32_INSN_OPCODE:
++ case JMP8_INSN_OPCODE:
++ /*
++ * Control flow instructions without implied execution of the
++ * next instruction can be padded with INT3.
++ */
++ for (i = insn.length; i < len; i++)
++ BUG_ON(tp->text[i] != INT3_INSN_OPCODE);
++ break;
++
++ default:
++ BUG_ON(len != insn.length);
++ };
++
++
+ switch (tp->opcode) {
+ case INT3_INSN_OPCODE:
+ case RET_INSN_OPCODE:
+@@ -1217,7 +1236,7 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
+ case CALL_INSN_OPCODE:
+ case JMP32_INSN_OPCODE:
+ case JMP8_INSN_OPCODE:
+- tp->rel32 = insn.immediate.value;
++ tp->disp = insn.immediate.value;
+ break;
+
+ default: /* assume NOP */
+@@ -1225,13 +1244,13 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
+ case 2: /* NOP2 -- emulate as JMP8+0 */
+ BUG_ON(memcmp(emulate, x86_nops[len], len));
+ tp->opcode = JMP8_INSN_OPCODE;
+- tp->rel32 = 0;
++ tp->disp = 0;
+ break;
+
+ case 5: /* NOP5 -- emulate as JMP32+0 */
+ BUG_ON(memcmp(emulate, x86_nops[len], len));
+ tp->opcode = JMP32_INSN_OPCODE;
+- tp->rel32 = 0;
++ tp->disp = 0;
+ break;
+
+ default: /* unknown instruction */
diff --git a/arch/x86/kernel/cc_platform.c b/arch/x86/kernel/cc_platform.c
new file mode 100644
index 0000000000000..03bb2f343ddb7
@@ -18129,7 +28334,7 @@ index ecfca3bbcd968..13320a06e14bd 100644
case X86_BUG_SPEC_STORE_BYPASS:
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index b3410f1ac2175..58b1416c05da4 100644
+index b3410f1ac2175..ec7d3ff5c6629 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1396,9 +1396,8 @@ void __init early_cpu_init(void)
@@ -18199,11 +28404,34 @@ index b3410f1ac2175..58b1416c05da4 100644
/*
* ESPFIX is a strange bug. All real CPUs have it. Paravirt
* systems that run Linux at CPL > 0 may or may not have the
+@@ -1684,6 +1714,8 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
+ validate_apic_and_package_id(c);
+ x86_spec_ctrl_setup_ap();
+ update_srbds_msr();
++
++ tsx_ap_init();
+ }
+
+ static __init int setup_noclflush(char *arg)
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
-index 95521302630d4..ee6f23f7587d4 100644
+index 95521302630d4..2a8e584fc9913 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
-@@ -75,6 +75,7 @@ extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
+@@ -55,11 +55,10 @@ enum tsx_ctrl_states {
+ extern __ro_after_init enum tsx_ctrl_states tsx_ctrl_state;
+
+ extern void __init tsx_init(void);
+-extern void tsx_enable(void);
+-extern void tsx_disable(void);
+-extern void tsx_clear_cpuid(void);
++void tsx_ap_init(void);
+ #else
+ static inline void tsx_init(void) { }
++static inline void tsx_ap_init(void) { }
+ #endif /* CONFIG_CPU_SUP_INTEL */
+
+ extern void get_cpu_cap(struct cpuinfo_x86 *c);
+@@ -75,6 +74,7 @@ extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
extern int detect_extended_topology(struct cpuinfo_x86 *c);
extern int detect_ht_early(struct cpuinfo_x86 *c);
extern void detect_ht(struct cpuinfo_x86 *c);
@@ -18224,6 +28452,24 @@ index 6d50136f7ab98..3fcdda4c1e114 100644
}
static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
+diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
+index 8321c43554a1d..f7a5370a9b3b8 100644
+--- a/arch/x86/kernel/cpu/intel.c
++++ b/arch/x86/kernel/cpu/intel.c
+@@ -717,13 +717,6 @@ static void init_intel(struct cpuinfo_x86 *c)
+
+ init_intel_misc_features(c);
+
+- if (tsx_ctrl_state == TSX_CTRL_ENABLE)
+- tsx_enable();
+- else if (tsx_ctrl_state == TSX_CTRL_DISABLE)
+- tsx_disable();
+- else if (tsx_ctrl_state == TSX_CTRL_RTM_ALWAYS_ABORT)
+- tsx_clear_cpuid();
+-
+ split_lock_init();
+ bus_lock_init();
+
diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
index 08831acc1d036..c0c57bd05f02d 100644
--- a/arch/x86/kernel/cpu/mce/amd.c
@@ -18392,10 +28638,44 @@ index acfd5d9f93c68..baafbb37be678 100644
(m->bank == 0) &&
((m->status & 0xa0000000ffffffff) == 0x80000000000f0005))
return true;
+diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
+index efb69be41ab18..150ebfb8c12ed 100644
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -775,9 +775,9 @@ static struct subsys_interface mc_cpu_interface = {
+ };
+
+ /**
+- * mc_bp_resume - Update boot CPU microcode during resume.
++ * microcode_bsp_resume - Update boot CPU microcode during resume.
+ */
+-static void mc_bp_resume(void)
++void microcode_bsp_resume(void)
+ {
+ int cpu = smp_processor_id();
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+@@ -789,7 +789,7 @@ static void mc_bp_resume(void)
+ }
+
+ static struct syscore_ops mc_syscore_ops = {
+- .resume = mc_bp_resume,
++ .resume = microcode_bsp_resume,
+ };
+
+ static int mc_cpu_starting(unsigned int cpu)
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index e095c28d27ae8..ef6316fef99ff 100644
+index e095c28d27ae8..ba0efc30fac52 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
+@@ -79,7 +79,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_stimer0)
+ inc_irq_stat(hyperv_stimer0_count);
+ if (hv_stimer0_handler)
+ hv_stimer0_handler();
+- add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0);
++ add_interrupt_randomness(HYPERV_STIMER0_VECTOR);
+ ack_APIC_irq();
+
+ set_irq_regs(old_regs);
@@ -163,12 +163,22 @@ static uint32_t __init ms_hyperv_platform(void)
cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
&eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
@@ -18425,10 +28705,99 @@ index e095c28d27ae8..ef6316fef99ff 100644
static unsigned char hv_get_nmi_reason(void)
diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
-index 001808e3901cc..48afe96ae0f0f 100644
+index 001808e3901cc..7c63a1911fae9 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
-@@ -410,6 +410,8 @@ void sgx_encl_release(struct kref *ref)
+@@ -12,6 +12,30 @@
+ #include "encls.h"
+ #include "sgx.h"
+
++/*
++ * Calculate byte offset of a PCMD struct associated with an enclave page. PCMD's
++ * follow right after the EPC data in the backing storage. In addition to the
++ * visible enclave pages, there's one extra page slot for SECS, before PCMD
++ * structs.
++ */
++static inline pgoff_t sgx_encl_get_backing_page_pcmd_offset(struct sgx_encl *encl,
++ unsigned long page_index)
++{
++ pgoff_t epc_end_off = encl->size + sizeof(struct sgx_secs);
++
++ return epc_end_off + page_index * sizeof(struct sgx_pcmd);
++}
++
++/*
++ * Free a page from the backing storage in the given page index.
++ */
++static inline void sgx_encl_truncate_backing_page(struct sgx_encl *encl, unsigned long page_index)
++{
++ struct inode *inode = file_inode(encl->backing);
++
++ shmem_truncate_range(inode, PFN_PHYS(page_index), PFN_PHYS(page_index) + PAGE_SIZE - 1);
++}
++
+ /*
+ * ELDU: Load an EPC page as unblocked. For more info, see "OS Management of EPC
+ * Pages" in the SDM.
+@@ -22,9 +46,11 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
+ {
+ unsigned long va_offset = encl_page->desc & SGX_ENCL_PAGE_VA_OFFSET_MASK;
+ struct sgx_encl *encl = encl_page->encl;
++ pgoff_t page_index, page_pcmd_off;
+ struct sgx_pageinfo pginfo;
+ struct sgx_backing b;
+- pgoff_t page_index;
++ bool pcmd_page_empty;
++ u8 *pcmd_page;
+ int ret;
+
+ if (secs_page)
+@@ -32,14 +58,16 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
+ else
+ page_index = PFN_DOWN(encl->size);
+
++ page_pcmd_off = sgx_encl_get_backing_page_pcmd_offset(encl, page_index);
++
+ ret = sgx_encl_get_backing(encl, page_index, &b);
+ if (ret)
+ return ret;
+
+ pginfo.addr = encl_page->desc & PAGE_MASK;
+ pginfo.contents = (unsigned long)kmap_atomic(b.contents);
+- pginfo.metadata = (unsigned long)kmap_atomic(b.pcmd) +
+- b.pcmd_offset;
++ pcmd_page = kmap_atomic(b.pcmd);
++ pginfo.metadata = (unsigned long)pcmd_page + b.pcmd_offset;
+
+ if (secs_page)
+ pginfo.secs = (u64)sgx_get_epc_virt_addr(secs_page);
+@@ -55,11 +83,24 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
+ ret = -EFAULT;
+ }
+
+- kunmap_atomic((void *)(unsigned long)(pginfo.metadata - b.pcmd_offset));
++ memset(pcmd_page + b.pcmd_offset, 0, sizeof(struct sgx_pcmd));
++
++ /*
++ * The area for the PCMD in the page was zeroed above. Check if the
++ * whole page is now empty meaning that all PCMD's have been zeroed:
++ */
++ pcmd_page_empty = !memchr_inv(pcmd_page, 0, PAGE_SIZE);
++
++ kunmap_atomic(pcmd_page);
+ kunmap_atomic((void *)(unsigned long)pginfo.contents);
+
+ sgx_encl_put_backing(&b, false);
+
++ sgx_encl_truncate_backing_page(encl, page_index);
++
++ if (pcmd_page_empty)
++ sgx_encl_truncate_backing_page(encl, PFN_DOWN(page_pcmd_off));
++
+ return ret;
+ }
+
+@@ -410,6 +451,8 @@ void sgx_encl_release(struct kref *ref)
}
kfree(entry);
@@ -18437,6 +28806,35 @@ index 001808e3901cc..48afe96ae0f0f 100644
}
xa_destroy(&encl->page_array);
+@@ -577,7 +620,7 @@ static struct page *sgx_encl_get_backing_page(struct sgx_encl *encl,
+ int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index,
+ struct sgx_backing *backing)
+ {
+- pgoff_t pcmd_index = PFN_DOWN(encl->size) + 1 + (page_index >> 5);
++ pgoff_t page_pcmd_off = sgx_encl_get_backing_page_pcmd_offset(encl, page_index);
+ struct page *contents;
+ struct page *pcmd;
+
+@@ -585,7 +628,7 @@ int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index,
+ if (IS_ERR(contents))
+ return PTR_ERR(contents);
+
+- pcmd = sgx_encl_get_backing_page(encl, pcmd_index);
++ pcmd = sgx_encl_get_backing_page(encl, PFN_DOWN(page_pcmd_off));
+ if (IS_ERR(pcmd)) {
+ put_page(contents);
+ return PTR_ERR(pcmd);
+@@ -594,9 +637,7 @@ int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index,
+ backing->page_index = page_index;
+ backing->contents = contents;
+ backing->pcmd = pcmd;
+- backing->pcmd_offset =
+- (page_index & (PAGE_SIZE / sizeof(struct sgx_pcmd) - 1)) *
+- sizeof(struct sgx_pcmd);
++ backing->pcmd_offset = page_pcmd_off & (PAGE_SIZE - 1);
+
+ return 0;
+ }
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 63d3de02bbccb..8471a8b9b48e8 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
@@ -18491,6 +28889,162 @@ index 63d3de02bbccb..8471a8b9b48e8 100644
}
static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
+diff --git a/arch/x86/kernel/cpu/tsx.c b/arch/x86/kernel/cpu/tsx.c
+index 9c7a5f0492929..ec7bbac3a9f29 100644
+--- a/arch/x86/kernel/cpu/tsx.c
++++ b/arch/x86/kernel/cpu/tsx.c
+@@ -19,7 +19,7 @@
+
+ enum tsx_ctrl_states tsx_ctrl_state __ro_after_init = TSX_CTRL_NOT_SUPPORTED;
+
+-void tsx_disable(void)
++static void tsx_disable(void)
+ {
+ u64 tsx;
+
+@@ -39,7 +39,7 @@ void tsx_disable(void)
+ wrmsrl(MSR_IA32_TSX_CTRL, tsx);
+ }
+
+-void tsx_enable(void)
++static void tsx_enable(void)
+ {
+ u64 tsx;
+
+@@ -58,7 +58,7 @@ void tsx_enable(void)
+ wrmsrl(MSR_IA32_TSX_CTRL, tsx);
+ }
+
+-static bool __init tsx_ctrl_is_supported(void)
++static bool tsx_ctrl_is_supported(void)
+ {
+ u64 ia32_cap = x86_read_arch_cap_msr();
+
+@@ -84,7 +84,45 @@ static enum tsx_ctrl_states x86_get_tsx_auto_mode(void)
+ return TSX_CTRL_ENABLE;
+ }
+
+-void tsx_clear_cpuid(void)
++/*
++ * Disabling TSX is not a trivial business.
++ *
++ * First of all, there's a CPUID bit: X86_FEATURE_RTM_ALWAYS_ABORT
++ * which says that TSX is practically disabled (all transactions are
++ * aborted by default). When that bit is set, the kernel unconditionally
++ * disables TSX.
++ *
++ * In order to do that, however, it needs to dance a bit:
++ *
++ * 1. The first method to disable it is through MSR_TSX_FORCE_ABORT and
++ * the MSR is present only when *two* CPUID bits are set:
++ *
++ * - X86_FEATURE_RTM_ALWAYS_ABORT
++ * - X86_FEATURE_TSX_FORCE_ABORT
++ *
++ * 2. The second method is for CPUs which do not have the above-mentioned
++ * MSR: those use a different MSR - MSR_IA32_TSX_CTRL and disable TSX
++ * through that one. Those CPUs can also have the initially mentioned
++ * CPUID bit X86_FEATURE_RTM_ALWAYS_ABORT set and for those the same strategy
++ * applies: TSX gets disabled unconditionally.
++ *
++ * When either of the two methods are present, the kernel disables TSX and
++ * clears the respective RTM and HLE feature flags.
++ *
++ * An additional twist in the whole thing presents late microcode loading
++ * which, when done, may cause for the X86_FEATURE_RTM_ALWAYS_ABORT CPUID
++ * bit to be set after the update.
++ *
++ * A subsequent hotplug operation on any logical CPU except the BSP will
++ * cause for the supported CPUID feature bits to get re-detected and, if
++ * RTM and HLE get cleared all of a sudden, but, userspace did consult
++ * them before the update, then funny explosions will happen. Long story
++ * short: the kernel doesn't modify CPUID feature bits after booting.
++ *
++ * That's why, this function's call in init_intel() doesn't clear the
++ * feature flags.
++ */
++static void tsx_clear_cpuid(void)
+ {
+ u64 msr;
+
+@@ -97,6 +135,39 @@ void tsx_clear_cpuid(void)
+ rdmsrl(MSR_TSX_FORCE_ABORT, msr);
+ msr |= MSR_TFA_TSX_CPUID_CLEAR;
+ wrmsrl(MSR_TSX_FORCE_ABORT, msr);
++ } else if (tsx_ctrl_is_supported()) {
++ rdmsrl(MSR_IA32_TSX_CTRL, msr);
++ msr |= TSX_CTRL_CPUID_CLEAR;
++ wrmsrl(MSR_IA32_TSX_CTRL, msr);
++ }
++}
++
++/*
++ * Disable TSX development mode
++ *
++ * When the microcode released in Feb 2022 is applied, TSX will be disabled by
++ * default on some processors. MSR 0x122 (TSX_CTRL) and MSR 0x123
++ * (IA32_MCU_OPT_CTRL) can be used to re-enable TSX for development, doing so is
++ * not recommended for production deployments. In particular, applying MD_CLEAR
++ * flows for mitigation of the Intel TSX Asynchronous Abort (TAA) transient
++ * execution attack may not be effective on these processors when Intel TSX is
++ * enabled with updated microcode.
++ */
++static void tsx_dev_mode_disable(void)
++{
++ u64 mcu_opt_ctrl;
++
++ /* Check if RTM_ALLOW exists */
++ if (!boot_cpu_has_bug(X86_BUG_TAA) || !tsx_ctrl_is_supported() ||
++ !cpu_feature_enabled(X86_FEATURE_SRBDS_CTRL))
++ return;
++
++ rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
++
++ if (mcu_opt_ctrl & RTM_ALLOW) {
++ mcu_opt_ctrl &= ~RTM_ALLOW;
++ wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
++ setup_force_cpu_cap(X86_FEATURE_RTM_ALWAYS_ABORT);
+ }
+ }
+
+@@ -105,14 +176,14 @@ void __init tsx_init(void)
+ char arg[5] = {};
+ int ret;
+
++ tsx_dev_mode_disable();
++
+ /*
+- * Hardware will always abort a TSX transaction if both CPUID bits
+- * RTM_ALWAYS_ABORT and TSX_FORCE_ABORT are set. In this case, it is
+- * better not to enumerate CPUID.RTM and CPUID.HLE bits. Clear them
+- * here.
++ * Hardware will always abort a TSX transaction when the CPUID bit
++ * RTM_ALWAYS_ABORT is set. In this case, it is better not to enumerate
++ * CPUID.RTM and CPUID.HLE bits. Clear them here.
+ */
+- if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT) &&
+- boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)) {
++ if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT)) {
+ tsx_ctrl_state = TSX_CTRL_RTM_ALWAYS_ABORT;
+ tsx_clear_cpuid();
+ setup_clear_cpu_cap(X86_FEATURE_RTM);
+@@ -175,3 +246,16 @@ void __init tsx_init(void)
+ setup_force_cpu_cap(X86_FEATURE_HLE);
+ }
+ }
++
++void tsx_ap_init(void)
++{
++ tsx_dev_mode_disable();
++
++ if (tsx_ctrl_state == TSX_CTRL_ENABLE)
++ tsx_enable();
++ else if (tsx_ctrl_state == TSX_CTRL_DISABLE)
++ tsx_disable();
++ else if (tsx_ctrl_state == TSX_CTRL_RTM_ALWAYS_ABORT)
++ /* See comment over that function for more details. */
++ tsx_clear_cpuid();
++}
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 5601b95944fae..6c5defd6569a3 100644
--- a/arch/x86/kernel/dumpstack_64.c
@@ -18511,6 +29065,75 @@ index 5601b95944fae..6c5defd6569a3 100644
if (type == STACK_TYPE_ENTRY) {
/*
* On 64-bit, we have a generic entry stack that we
+diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
+index bc0657f0deedf..f267205f2d5a4 100644
+--- a/arch/x86/kernel/e820.c
++++ b/arch/x86/kernel/e820.c
+@@ -995,8 +995,10 @@ early_param("memmap", parse_memmap_opt);
+ */
+ void __init e820__reserve_setup_data(void)
+ {
++ struct setup_indirect *indirect;
+ struct setup_data *data;
+- u64 pa_data;
++ u64 pa_data, pa_next;
++ u32 len;
+
+ pa_data = boot_params.hdr.setup_data;
+ if (!pa_data)
+@@ -1004,6 +1006,14 @@ void __init e820__reserve_setup_data(void)
+
+ while (pa_data) {
+ data = early_memremap(pa_data, sizeof(*data));
++ if (!data) {
++ pr_warn("e820: failed to memremap setup_data entry\n");
++ return;
++ }
++
++ len = sizeof(*data);
++ pa_next = data->next;
++
+ e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
+
+ /*
+@@ -1015,18 +1025,27 @@ void __init e820__reserve_setup_data(void)
+ sizeof(*data) + data->len,
+ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
+
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
+- e820__range_update(((struct setup_indirect *)data->data)->addr,
+- ((struct setup_indirect *)data->data)->len,
+- E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
+- e820__range_update_kexec(((struct setup_indirect *)data->data)->addr,
+- ((struct setup_indirect *)data->data)->len,
+- E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
++ if (data->type == SETUP_INDIRECT) {
++ len += data->len;
++ early_memunmap(data, sizeof(*data));
++ data = early_memremap(pa_data, len);
++ if (!data) {
++ pr_warn("e820: failed to memremap indirect setup_data\n");
++ return;
++ }
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT) {
++ e820__range_update(indirect->addr, indirect->len,
++ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
++ e820__range_update_kexec(indirect->addr, indirect->len,
++ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
++ }
+ }
+
+- pa_data = data->next;
+- early_memunmap(data, sizeof(*data));
++ pa_data = pa_next;
++ early_memunmap(data, len);
+ }
+
+ e820__update_table(e820_table);
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 391a4e2b86049..8690fab95ae4b 100644
--- a/arch/x86/kernel/early-quirks.c
@@ -18546,6 +29169,97 @@ index 391a4e2b86049..8690fab95ae4b 100644
/*
* HPET on the current version of the Baytrail platform has accuracy
* problems: it will halt in deep idle state - so we disable it.
+diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
+index 7ada7bd03a327..759e1cef5e695 100644
+--- a/arch/x86/kernel/fpu/core.c
++++ b/arch/x86/kernel/fpu/core.c
+@@ -25,17 +25,7 @@
+ */
+ union fpregs_state init_fpstate __ro_after_init;
+
+-/*
+- * Track whether the kernel is using the FPU state
+- * currently.
+- *
+- * This flag is used:
+- *
+- * - by IRQ context code to potentially use the FPU
+- * if it's unused.
+- *
+- * - to debug kernel_fpu_begin()/end() correctness
+- */
++/* Track in-kernel FPU usage */
+ static DEFINE_PER_CPU(bool, in_kernel_fpu);
+
+ /*
+@@ -43,42 +33,37 @@ static DEFINE_PER_CPU(bool, in_kernel_fpu);
+ */
+ DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
+
+-static bool kernel_fpu_disabled(void)
+-{
+- return this_cpu_read(in_kernel_fpu);
+-}
+-
+-static bool interrupted_kernel_fpu_idle(void)
+-{
+- return !kernel_fpu_disabled();
+-}
+-
+-/*
+- * Were we in user mode (or vm86 mode) when we were
+- * interrupted?
+- *
+- * Doing kernel_fpu_begin/end() is ok if we are running
+- * in an interrupt context from user mode - we'll just
+- * save the FPU state as required.
+- */
+-static bool interrupted_user_mode(void)
+-{
+- struct pt_regs *regs = get_irq_regs();
+- return regs && user_mode(regs);
+-}
+-
+ /*
+ * Can we use the FPU in kernel mode with the
+ * whole "kernel_fpu_begin/end()" sequence?
+- *
+- * It's always ok in process context (ie "not interrupt")
+- * but it is sometimes ok even from an irq.
+ */
+ bool irq_fpu_usable(void)
+ {
+- return !in_interrupt() ||
+- interrupted_user_mode() ||
+- interrupted_kernel_fpu_idle();
++ if (WARN_ON_ONCE(in_nmi()))
++ return false;
++
++ /* In kernel FPU usage already active? */
++ if (this_cpu_read(in_kernel_fpu))
++ return false;
++
++ /*
++ * When not in NMI or hard interrupt context, FPU can be used in:
++ *
++ * - Task context except from within fpregs_lock()'ed critical
++ * regions.
++ *
++ * - Soft interrupt processing context which cannot happen
++ * while in a fpregs_lock()'ed critical region.
++ */
++ if (!in_hardirq())
++ return true;
++
++ /*
++ * In hard interrupt context it's safe when soft interrupts
++ * are enabled, which means the interrupt did not hit in
++ * a fpregs_lock()'ed critical region.
++ */
++ return !softirq_count();
+ }
+ EXPORT_SYMBOL(irq_fpu_usable);
+
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index 66ed317ebc0d3..125cbbe10fefa 100644
--- a/arch/x86/kernel/fpu/regset.c
@@ -18576,6 +29290,153 @@ index 66ed317ebc0d3..125cbbe10fefa 100644
/* Mark FP and SSE as in use when XSAVE is enabled */
if (use_xsave())
+diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
+index 831b25c5e7058..7f71bd4dcd0d6 100644
+--- a/arch/x86/kernel/fpu/signal.c
++++ b/arch/x86/kernel/fpu/signal.c
+@@ -205,7 +205,7 @@ retry:
+ fpregs_unlock();
+
+ if (ret) {
+- if (!fault_in_pages_writeable(buf_fx, fpu_user_xstate_size))
++ if (!fault_in_writeable(buf_fx, fpu_user_xstate_size))
+ goto retry;
+ return -EFAULT;
+ }
+@@ -278,10 +278,9 @@ retry:
+ if (ret != -EFAULT)
+ return -EINVAL;
+
+- ret = fault_in_pages_readable(buf, size);
+- if (!ret)
++ if (!fault_in_readable(buf, size))
+ goto retry;
+- return ret;
++ return -EFAULT;
+ }
+
+ /*
+diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
+index 1b3ce3b4a2a2f..847776cc1aa40 100644
+--- a/arch/x86/kernel/ftrace.c
++++ b/arch/x86/kernel/ftrace.c
+@@ -308,7 +308,7 @@ union ftrace_op_code_union {
+ } __attribute__((packed));
+ };
+
+-#define RET_SIZE 1
++#define RET_SIZE 1 + IS_ENABLED(CONFIG_SLS)
+
+ static unsigned long
+ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
+diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S
+index e405fe1a8bf41..a0ed0e4a2c0cd 100644
+--- a/arch/x86/kernel/ftrace_32.S
++++ b/arch/x86/kernel/ftrace_32.S
+@@ -19,7 +19,7 @@
+ #endif
+
+ SYM_FUNC_START(__fentry__)
+- ret
++ RET
+ SYM_FUNC_END(__fentry__)
+ EXPORT_SYMBOL(__fentry__)
+
+@@ -84,7 +84,7 @@ ftrace_graph_call:
+
+ /* This is weak to keep gas from relaxing the jumps */
+ SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK)
+- ret
++ RET
+ SYM_CODE_END(ftrace_caller)
+
+ SYM_CODE_START(ftrace_regs_caller)
+@@ -177,7 +177,7 @@ SYM_CODE_START(ftrace_graph_caller)
+ popl %edx
+ popl %ecx
+ popl %eax
+- ret
++ RET
+ SYM_CODE_END(ftrace_graph_caller)
+
+ .globl return_to_handler
+diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S
+index 7c273846c6877..d6af81d1b7883 100644
+--- a/arch/x86/kernel/ftrace_64.S
++++ b/arch/x86/kernel/ftrace_64.S
+@@ -132,7 +132,7 @@
+ #ifdef CONFIG_DYNAMIC_FTRACE
+
+ SYM_FUNC_START(__fentry__)
+- retq
++ RET
+ SYM_FUNC_END(__fentry__)
+ EXPORT_SYMBOL(__fentry__)
+
+@@ -181,11 +181,11 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
+
+ /*
+ * This is weak to keep gas from relaxing the jumps.
+- * It is also used to copy the retq for trampolines.
++ * It is also used to copy the RET for trampolines.
+ */
+ SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK)
+ UNWIND_HINT_FUNC
+- retq
++ RET
+ SYM_FUNC_END(ftrace_epilogue)
+
+ SYM_FUNC_START(ftrace_regs_caller)
+@@ -299,7 +299,7 @@ fgraph_trace:
+ #endif
+
+ SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL)
+- retq
++ RET
+
+ trace:
+ /* save_mcount_regs fills in first two parameters */
+@@ -331,7 +331,7 @@ SYM_FUNC_START(ftrace_graph_caller)
+
+ restore_mcount_regs
+
+- retq
++ RET
+ SYM_FUNC_END(ftrace_graph_caller)
+
+ SYM_FUNC_START(return_to_handler)
+diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
+index d8c64dab0efe0..eb8656bac99b6 100644
+--- a/arch/x86/kernel/head_32.S
++++ b/arch/x86/kernel/head_32.S
+@@ -340,7 +340,7 @@ SYM_FUNC_END(startup_32_smp)
+ __INIT
+ setup_once:
+ andl $0,setup_once_ref /* Once is enough, thanks */
+- ret
++ RET
+
+ SYM_FUNC_START(early_idt_handler_array)
+ # 36(%esp) %eflags
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index 882213df37130..71f336425e58a 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -1435,8 +1435,12 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+ hpet_rtc_timer_reinit();
+ memset(&curr_time, 0, sizeof(struct rtc_time));
+
+- if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
+- mc146818_get_time(&curr_time);
++ if (hpet_rtc_flags & (RTC_UIE | RTC_AIE)) {
++ if (unlikely(mc146818_get_time(&curr_time) < 0)) {
++ pr_err_ratelimited("unable to read current time from RTC\n");
++ return IRQ_HANDLED;
++ }
++ }
+
+ if (hpet_rtc_flags & RTC_UIE &&
+ curr_time.tm_sec != hpet_prev_update_sec) {
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index e28f6a5d14f1b..766ffe3ba3137 100644
--- a/arch/x86/kernel/irq.c
@@ -18592,8 +29453,306 @@ index e28f6a5d14f1b..766ffe3ba3137 100644
}
EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler);
+diff --git a/arch/x86/kernel/irqflags.S b/arch/x86/kernel/irqflags.S
+index 8ef35063964b1..b8db1022aa6ca 100644
+--- a/arch/x86/kernel/irqflags.S
++++ b/arch/x86/kernel/irqflags.S
+@@ -10,6 +10,6 @@
+ SYM_FUNC_START(native_save_fl)
+ pushf
+ pop %_ASM_AX
+- ret
++ RET
+ SYM_FUNC_END(native_save_fl)
+ EXPORT_SYMBOL(native_save_fl)
+diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
+index 64b6da95af984..e2e89bebcbc32 100644
+--- a/arch/x86/kernel/kdebugfs.c
++++ b/arch/x86/kernel/kdebugfs.c
+@@ -88,11 +88,13 @@ create_setup_data_node(struct dentry *parent, int no,
+
+ static int __init create_setup_data_nodes(struct dentry *parent)
+ {
++ struct setup_indirect *indirect;
+ struct setup_data_node *node;
+ struct setup_data *data;
+- int error;
++ u64 pa_data, pa_next;
+ struct dentry *d;
+- u64 pa_data;
++ int error;
++ u32 len;
+ int no = 0;
+
+ d = debugfs_create_dir("setup_data", parent);
+@@ -112,12 +114,29 @@ static int __init create_setup_data_nodes(struct dentry *parent)
+ error = -ENOMEM;
+ goto err_dir;
+ }
+-
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
+- node->paddr = ((struct setup_indirect *)data->data)->addr;
+- node->type = ((struct setup_indirect *)data->data)->type;
+- node->len = ((struct setup_indirect *)data->data)->len;
++ pa_next = data->next;
++
++ if (data->type == SETUP_INDIRECT) {
++ len = sizeof(*data) + data->len;
++ memunmap(data);
++ data = memremap(pa_data, len, MEMREMAP_WB);
++ if (!data) {
++ kfree(node);
++ error = -ENOMEM;
++ goto err_dir;
++ }
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT) {
++ node->paddr = indirect->addr;
++ node->type = indirect->type;
++ node->len = indirect->len;
++ } else {
++ node->paddr = pa_data;
++ node->type = data->type;
++ node->len = data->len;
++ }
+ } else {
+ node->paddr = pa_data;
+ node->type = data->type;
+@@ -125,7 +144,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)
+ }
+
+ create_setup_data_node(d, no, node);
+- pa_data = data->next;
++ pa_data = pa_next;
+
+ memunmap(data);
+ no++;
+diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
+index b6e046e4b2895..f6727c67ae028 100644
+--- a/arch/x86/kernel/kprobes/core.c
++++ b/arch/x86/kernel/kprobes/core.c
+@@ -1044,7 +1044,7 @@ asm(
+ RESTORE_REGS_STRING
+ " popfl\n"
+ #endif
+- " ret\n"
++ ASM_RET
+ ".size kretprobe_trampoline, .-kretprobe_trampoline\n"
+ );
+ NOKPROBE_SYMBOL(kretprobe_trampoline);
+diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c
+index d0a19121c6a4f..257892fcefa79 100644
+--- a/arch/x86/kernel/ksysfs.c
++++ b/arch/x86/kernel/ksysfs.c
+@@ -91,26 +91,41 @@ static int get_setup_data_paddr(int nr, u64 *paddr)
+
+ static int __init get_setup_data_size(int nr, size_t *size)
+ {
+- int i = 0;
++ u64 pa_data = boot_params.hdr.setup_data, pa_next;
++ struct setup_indirect *indirect;
+ struct setup_data *data;
+- u64 pa_data = boot_params.hdr.setup_data;
++ int i = 0;
++ u32 len;
+
+ while (pa_data) {
+ data = memremap(pa_data, sizeof(*data), MEMREMAP_WB);
+ if (!data)
+ return -ENOMEM;
++ pa_next = data->next;
++
+ if (nr == i) {
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT)
+- *size = ((struct setup_indirect *)data->data)->len;
+- else
++ if (data->type == SETUP_INDIRECT) {
++ len = sizeof(*data) + data->len;
++ memunmap(data);
++ data = memremap(pa_data, len, MEMREMAP_WB);
++ if (!data)
++ return -ENOMEM;
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT)
++ *size = indirect->len;
++ else
++ *size = data->len;
++ } else {
+ *size = data->len;
++ }
+
+ memunmap(data);
+ return 0;
+ }
+
+- pa_data = data->next;
++ pa_data = pa_next;
+ memunmap(data);
+ i++;
+ }
+@@ -120,9 +135,11 @@ static int __init get_setup_data_size(int nr, size_t *size)
+ static ssize_t type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+ {
++ struct setup_indirect *indirect;
++ struct setup_data *data;
+ int nr, ret;
+ u64 paddr;
+- struct setup_data *data;
++ u32 len;
+
+ ret = kobj_to_setup_data_nr(kobj, &nr);
+ if (ret)
+@@ -135,10 +152,20 @@ static ssize_t type_show(struct kobject *kobj,
+ if (!data)
+ return -ENOMEM;
+
+- if (data->type == SETUP_INDIRECT)
+- ret = sprintf(buf, "0x%x\n", ((struct setup_indirect *)data->data)->type);
+- else
++ if (data->type == SETUP_INDIRECT) {
++ len = sizeof(*data) + data->len;
++ memunmap(data);
++ data = memremap(paddr, len, MEMREMAP_WB);
++ if (!data)
++ return -ENOMEM;
++
++ indirect = (struct setup_indirect *)data->data;
++
++ ret = sprintf(buf, "0x%x\n", indirect->type);
++ } else {
+ ret = sprintf(buf, "0x%x\n", data->type);
++ }
++
+ memunmap(data);
+ return ret;
+ }
+@@ -149,9 +176,10 @@ static ssize_t setup_data_data_read(struct file *fp,
+ char *buf,
+ loff_t off, size_t count)
+ {
++ struct setup_indirect *indirect;
++ struct setup_data *data;
+ int nr, ret = 0;
+ u64 paddr, len;
+- struct setup_data *data;
+ void *p;
+
+ ret = kobj_to_setup_data_nr(kobj, &nr);
+@@ -165,10 +193,27 @@ static ssize_t setup_data_data_read(struct file *fp,
+ if (!data)
+ return -ENOMEM;
+
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
+- paddr = ((struct setup_indirect *)data->data)->addr;
+- len = ((struct setup_indirect *)data->data)->len;
++ if (data->type == SETUP_INDIRECT) {
++ len = sizeof(*data) + data->len;
++ memunmap(data);
++ data = memremap(paddr, len, MEMREMAP_WB);
++ if (!data)
++ return -ENOMEM;
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT) {
++ paddr = indirect->addr;
++ len = indirect->len;
++ } else {
++ /*
++ * Even though this is technically undefined, return
++ * the data as though it is a normal setup_data struct.
++ * This will at least allow it to be inspected.
++ */
++ paddr += sizeof(*data);
++ len = data->len;
++ }
+ } else {
+ paddr += sizeof(*data);
+ len = data->len;
+diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
+index b656456c3a944..d36b58e705b6c 100644
+--- a/arch/x86/kernel/kvm.c
++++ b/arch/x86/kernel/kvm.c
+@@ -66,6 +66,7 @@ static DEFINE_PER_CPU_DECRYPTED(struct kvm_vcpu_pv_apf_data, apf_reason) __align
+ DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible;
+ static int has_steal_clock = 0;
+
++static int has_guest_poll = 0;
+ /*
+ * No need for any "IO delay" on KVM
+ */
+@@ -457,19 +458,22 @@ static bool pv_tlb_flush_supported(void)
+ {
+ return (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+ !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+- kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
++ kvm_para_has_feature(KVM_FEATURE_STEAL_TIME) &&
++ (num_possible_cpus() != 1));
+ }
+
+ static bool pv_ipi_supported(void)
+ {
+- return kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI);
++ return (kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI) &&
++ (num_possible_cpus() != 1));
+ }
+
+ static bool pv_sched_yield_supported(void)
+ {
+ return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
+ !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+- kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
++ kvm_para_has_feature(KVM_FEATURE_STEAL_TIME) &&
++ (num_possible_cpus() != 1));
+ }
+
+ #define KVM_IPI_CLUSTER_SIZE (2 * BITS_PER_LONG)
+@@ -507,7 +511,7 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
+ } else if (apic_id < min && max - apic_id < KVM_IPI_CLUSTER_SIZE) {
+ ipi_bitmap <<= min - apic_id;
+ min = apic_id;
+- } else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
++ } else if (apic_id > min && apic_id < min + KVM_IPI_CLUSTER_SIZE) {
+ max = apic_id < max ? max : apic_id;
+ } else {
+ ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+@@ -647,14 +651,26 @@ static int kvm_cpu_down_prepare(unsigned int cpu)
+
+ static int kvm_suspend(void)
+ {
++ u64 val = 0;
++
+ kvm_guest_cpu_offline(false);
+
++#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
++ if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL))
++ rdmsrl(MSR_KVM_POLL_CONTROL, val);
++ has_guest_poll = !(val & 1);
++#endif
+ return 0;
+ }
+
+ static void kvm_resume(void)
+ {
+ kvm_cpu_online(raw_smp_processor_id());
++
++#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
++ if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL) && has_guest_poll)
++ wrmsrl(MSR_KVM_POLL_CONTROL, 0);
++#endif
+ }
+
+ static struct syscore_ops kvm_syscore_ops = {
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
-index 5e9a34b5bd741..867a341a0c7e8 100644
+index 5e9a34b5bd741..32e546e416296 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -67,6 +67,7 @@ static unsigned long int get_module_load_offset(void)
@@ -18618,6 +29777,46 @@ index 5e9a34b5bd741..867a341a0c7e8 100644
vfree(p);
return NULL;
}
+@@ -269,6 +270,14 @@ int module_finalize(const Elf_Ehdr *hdr,
+ orc_ip = s;
+ }
+
++ /*
++ * See alternative_instructions() for the ordering rules between the
++ * various patching types.
++ */
++ if (para) {
++ void *pseg = (void *)para->sh_addr;
++ apply_paravirt(pseg, pseg + para->sh_size);
++ }
+ if (alt) {
+ /* patch .altinstructions */
+ void *aseg = (void *)alt->sh_addr;
+@@ -282,11 +291,6 @@ int module_finalize(const Elf_Ehdr *hdr,
+ tseg, tseg + text->sh_size);
+ }
+
+- if (para) {
+- void *pseg = (void *)para->sh_addr;
+- apply_paravirt(pseg, pseg + para->sh_size);
+- }
+-
+ /* make jump label nops */
+ jump_label_apply_nops(me);
+
+diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
+index 04cafc057bed4..f1cdb8891ad41 100644
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -41,7 +41,7 @@ extern void _paravirt_nop(void);
+ asm (".pushsection .entry.text, \"ax\"\n"
+ ".global _paravirt_nop\n"
+ "_paravirt_nop:\n\t"
+- "ret\n\t"
++ ASM_RET
+ ".size _paravirt_nop, . - _paravirt_nop\n\t"
+ ".type _paravirt_nop, @function\n\t"
+ ".popsection");
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 1d9463e3096b6..f2f733bcb2b95 100644
--- a/arch/x86/kernel/process.c
@@ -18676,11 +29875,158 @@ index 0a40df66a40de..fa700b46588e0 100644
/* Jump to the identity-mapped low memory code */
#ifdef CONFIG_X86_32
+diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
+index f469153eca8ab..fcc8a7699103a 100644
+--- a/arch/x86/kernel/relocate_kernel_32.S
++++ b/arch/x86/kernel/relocate_kernel_32.S
+@@ -91,7 +91,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
+ movl %edi, %eax
+ addl $(identity_mapped - relocate_kernel), %eax
+ pushl %eax
+- ret
++ RET
+ SYM_CODE_END(relocate_kernel)
+
+ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+@@ -159,7 +159,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+ xorl %edx, %edx
+ xorl %esi, %esi
+ xorl %ebp, %ebp
+- ret
++ RET
+ 1:
+ popl %edx
+ movl CP_PA_SWAP_PAGE(%edi), %esp
+@@ -190,7 +190,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+ movl %edi, %eax
+ addl $(virtual_mapped - relocate_kernel), %eax
+ pushl %eax
+- ret
++ RET
+ SYM_CODE_END(identity_mapped)
+
+ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
+@@ -208,7 +208,7 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
+ popl %edi
+ popl %esi
+ popl %ebx
+- ret
++ RET
+ SYM_CODE_END(virtual_mapped)
+
+ /* Do the copies */
+@@ -271,7 +271,7 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
+ popl %edi
+ popl %ebx
+ popl %ebp
+- ret
++ RET
+ SYM_CODE_END(swap_pages)
+
+ .globl kexec_control_code_size
+diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
+index c53271aebb64d..5019091af059e 100644
+--- a/arch/x86/kernel/relocate_kernel_64.S
++++ b/arch/x86/kernel/relocate_kernel_64.S
+@@ -104,7 +104,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
+ /* jump to identity mapped page */
+ addq $(identity_mapped - relocate_kernel), %r8
+ pushq %r8
+- ret
++ RET
+ SYM_CODE_END(relocate_kernel)
+
+ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+@@ -191,7 +191,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+ xorl %r14d, %r14d
+ xorl %r15d, %r15d
+
+- ret
++ RET
+
+ 1:
+ popq %rdx
+@@ -210,7 +210,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
+ call swap_pages
+ movq $virtual_mapped, %rax
+ pushq %rax
+- ret
++ RET
+ SYM_CODE_END(identity_mapped)
+
+ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
+@@ -231,7 +231,7 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
+ popq %r12
+ popq %rbp
+ popq %rbx
+- ret
++ RET
+ SYM_CODE_END(virtual_mapped)
+
+ /* Do the copies */
+@@ -288,7 +288,7 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
+ lea PAGE_SIZE(%rax), %rsi
+ jmp 0b
+ 3:
+- ret
++ RET
+ SYM_CODE_END(swap_pages)
+
+ .globl kexec_control_code_size
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index 40ed44ead0631..48596f9fddf45 100644
+index 40ed44ead0631..8e56c4de00b9c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
-@@ -713,9 +713,6 @@ static void __init early_reserve_memory(void)
+@@ -368,21 +368,41 @@ static void __init parse_setup_data(void)
+
+ static void __init memblock_x86_reserve_range_setup_data(void)
+ {
++ struct setup_indirect *indirect;
+ struct setup_data *data;
+- u64 pa_data;
++ u64 pa_data, pa_next;
++ u32 len;
+
+ pa_data = boot_params.hdr.setup_data;
+ while (pa_data) {
+ data = early_memremap(pa_data, sizeof(*data));
++ if (!data) {
++ pr_warn("setup: failed to memremap setup_data entry\n");
++ return;
++ }
++
++ len = sizeof(*data);
++ pa_next = data->next;
++
+ memblock_reserve(pa_data, sizeof(*data) + data->len);
+
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT)
+- memblock_reserve(((struct setup_indirect *)data->data)->addr,
+- ((struct setup_indirect *)data->data)->len);
++ if (data->type == SETUP_INDIRECT) {
++ len += data->len;
++ early_memunmap(data, sizeof(*data));
++ data = early_memremap(pa_data, len);
++ if (!data) {
++ pr_warn("setup: failed to memremap indirect setup_data\n");
++ return;
++ }
+
+- pa_data = data->next;
+- early_memunmap(data, sizeof(*data));
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT)
++ memblock_reserve(indirect->addr, indirect->len);
++ }
++
++ pa_data = pa_next;
++ early_memunmap(data, len);
+ }
+ }
+
+@@ -713,9 +733,6 @@ static void __init early_reserve_memory(void)
early_reserve_initrd();
@@ -18690,7 +30036,7 @@ index 40ed44ead0631..48596f9fddf45 100644
memblock_x86_reserve_range_setup_data();
reserve_ibft_region();
-@@ -890,6 +887,9 @@ void __init setup_arch(char **cmdline_p)
+@@ -890,6 +907,9 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
@@ -18874,8 +30220,48 @@ index a6895e440bc35..a0064cf77e562 100644
}
sev_es_setup_play_dead();
+diff --git a/arch/x86/kernel/sev_verify_cbit.S b/arch/x86/kernel/sev_verify_cbit.S
+index ee04941a6546a..3355e27c69ebf 100644
+--- a/arch/x86/kernel/sev_verify_cbit.S
++++ b/arch/x86/kernel/sev_verify_cbit.S
+@@ -85,5 +85,5 @@ SYM_FUNC_START(sev_verify_cbit)
+ #endif
+ /* Return page-table pointer */
+ movq %rdi, %rax
+- ret
++ RET
+ SYM_FUNC_END(sev_verify_cbit)
+diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c
+index ea028e736831a..3ec2cb881eef0 100644
+--- a/arch/x86/kernel/static_call.c
++++ b/arch/x86/kernel/static_call.c
+@@ -12,10 +12,11 @@ enum insn_type {
+ };
+
+ /*
+- * data16 data16 xorq %rax, %rax - a single 5 byte instruction that clears %rax
+- * The REX.W cancels the effect of any data16.
++ * cs cs cs xorl %eax, %eax - a single 5 byte instruction that clears %[er]ax
+ */
+-static const u8 xor5rax[] = { 0x66, 0x66, 0x48, 0x31, 0xc0 };
++static const u8 xor5rax[] = { 0x2e, 0x2e, 0x2e, 0x31, 0xc0 };
++
++static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc };
+
+ static void __ref __static_call_transform(void *insn, enum insn_type type, void *func)
+ {
+@@ -42,8 +43,7 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, void
+ break;
+
+ case RET:
+- code = text_gen_insn(RET_INSN_OPCODE, insn, func);
+- size = RET_INSN_SIZE;
++ code = &retinsn;
+ break;
+ }
+
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
-index a58800973aed3..5b1984d468227 100644
+index a58800973aed3..928e1ac820e67 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -313,17 +313,19 @@ out:
@@ -18974,7 +30360,15 @@ index a58800973aed3..5b1984d468227 100644
tsk->thread.error_code = error_code;
tsk->thread.trap_nr = X86_TRAP_GP;
-@@ -709,7 +743,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r
+@@ -625,6 +659,7 @@ static bool do_int3(struct pt_regs *regs)
+
+ return res == NOTIFY_STOP;
+ }
++NOKPROBE_SYMBOL(do_int3);
+
+ static void do_int3_user(struct pt_regs *regs)
+ {
+@@ -709,7 +744,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r
stack = (unsigned long *)sp;
if (!get_stack_info_noinstr(stack, current, &info) || info.type == STACK_TYPE_ENTRY ||
@@ -19102,6 +30496,22 @@ index 50a4515fe0ad1..9452dc9664b51 100644
static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval,
unsigned int cpu, bool bootcpu)
{
+diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
+index 641f0fe1e5b4a..1258a5872d128 100644
+--- a/arch/x86/kernel/verify_cpu.S
++++ b/arch/x86/kernel/verify_cpu.S
+@@ -132,9 +132,9 @@ SYM_FUNC_START_LOCAL(verify_cpu)
+ .Lverify_cpu_no_longmode:
+ popf # Restore caller passed flags
+ movl $1,%eax
+- ret
++ RET
+ .Lverify_cpu_sse_ok:
+ popf # Restore caller passed flags
+ xorl %eax, %eax
+- ret
++ RET
+ SYM_FUNC_END(verify_cpu)
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index e5a7a10a0164d..17d58740891e2 100644
--- a/arch/x86/kernel/vm86_32.c
@@ -19125,7 +30535,7 @@ index e5a7a10a0164d..17d58740891e2 100644
static int do_vm86_irq_handling(int subfunction, int irqnumber);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
-index 751aa85a30012..5f1d4a5aa8716 100644
+index 751aa85a30012..b17c9b00669e5 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -232,6 +232,25 @@ u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu)
@@ -19219,6 +30629,18 @@ index 751aa85a30012..5f1d4a5aa8716 100644
kvm_cpu_cap_mask(CPUID_7_ECX,
F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) |
+@@ -723,6 +725,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ union cpuid10_eax eax;
+ union cpuid10_edx edx;
+
++ if (!static_cpu_has(X86_FEATURE_ARCH_PERFMON)) {
++ entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
++ break;
++ }
++
+ perf_get_x86_pmu_capability(&cap);
+
+ /*
diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c
index 54a83a7445384..f33c804a922ac 100644
--- a/arch/x86/kvm/debugfs.c
@@ -19233,11 +30655,234 @@ index 54a83a7445384..f33c804a922ac 100644
ret = -ENOMEM;
memset(log, 0, sizeof(log));
for (i = 0; i < KVM_NR_PAGE_SIZES; i++) {
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index 9a144ca8e1460..82eff14bd064d 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -315,7 +315,7 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
+ __FOP_FUNC(#name)
+
+ #define __FOP_RET(name) \
+- "ret \n\t" \
++ ASM_RET \
+ ".size " name ", .-" name "\n\t"
+
+ #define FOP_RET(name) \
+@@ -427,15 +427,30 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
+ FOP_END
+
+ /* Special case for SETcc - 1 instruction per cc */
++
++/*
++ * Depending on .config the SETcc functions look like:
++ *
++ * SETcc %al [3 bytes]
++ * RET [1 byte]
++ * INT3 [1 byte; CONFIG_SLS]
++ *
++ * Which gives possible sizes 4 or 5. When rounded up to the
++ * next power-of-two alignment they become 4 or 8.
++ */
++#define SETCC_LENGTH (4 + IS_ENABLED(CONFIG_SLS))
++#define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS))
++static_assert(SETCC_LENGTH <= SETCC_ALIGN);
++
+ #define FOP_SETCC(op) \
+- ".align 4 \n\t" \
++ ".align " __stringify(SETCC_ALIGN) " \n\t" \
+ ".type " #op ", @function \n\t" \
+ #op ": \n\t" \
+ #op " %al \n\t" \
+ __FOP_RET(#op)
+
+ asm(".pushsection .fixup, \"ax\"\n"
+- "kvm_fastop_exception: xor %esi, %esi; ret\n"
++ "kvm_fastop_exception: xor %esi, %esi; " ASM_RET
+ ".popsection");
+
+ FOP_START(setcc)
+@@ -1053,7 +1068,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
+ static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
+ {
+ u8 rc;
+- void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
++ void (*fop)(void) = (void *)em_setcc + SETCC_ALIGN * (condition & 0xf);
+
+ flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
+ asm("push %[flags]; popf; " CALL_NOSPEC
+@@ -1614,11 +1629,6 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ goto exception;
+ }
+
+- if (!seg_desc.p) {
+- err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
+- goto exception;
+- }
+-
+ dpl = seg_desc.dpl;
+
+ switch (seg) {
+@@ -1658,6 +1668,10 @@ 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,
+@@ -1682,6 +1696,11 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ break;
+ }
+
++ if (!seg_desc.p) {
++ err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
++ goto exception;
++ }
++
+ if (seg_desc.s) {
+ /* mark segment as accessed */
+ if (!(seg_desc.type & 1)) {
+@@ -3510,8 +3529,10 @@ static int em_rdpid(struct x86_emulate_ctxt *ctxt)
+ {
+ u64 tsc_aux = 0;
+
+- if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
++ if (!ctxt->ops->guest_has_rdpid(ctxt))
+ return emulate_ud(ctxt);
++
++ ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux);
+ ctxt->dst.val = tsc_aux;
+ return X86EMUL_CONTINUE;
+ }
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
-index d5124b520f761..2092834efba11 100644
+index d5124b520f761..762b43f0d9194 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
-@@ -1922,11 +1922,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+@@ -236,7 +236,7 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
+ struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
+ int ret;
+
+- if (!synic->active && !host)
++ if (!synic->active && (!host || data))
+ return 1;
+
+ trace_kvm_hv_synic_set_msr(vcpu->vcpu_id, msr, data, host);
+@@ -282,6 +282,9 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
+ case HV_X64_MSR_EOM: {
+ int i;
+
++ if (!synic->active)
++ break;
++
+ for (i = 0; i < ARRAY_SIZE(synic->sint); i++)
+ kvm_hv_notify_acked_sint(vcpu, i);
+ break;
+@@ -446,6 +449,9 @@ static int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
+ struct kvm_lapic_irq irq;
+ int ret, vector;
+
++ if (KVM_BUG_ON(!lapic_in_kernel(vcpu), vcpu->kvm))
++ return -EINVAL;
++
+ if (sint >= ARRAY_SIZE(synic->sint))
+ return -EINVAL;
+
+@@ -658,7 +664,7 @@ static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config,
+ struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
+ struct kvm_vcpu_hv_synic *synic = to_hv_synic(vcpu);
+
+- if (!synic->active && !host)
++ if (!synic->active && (!host || config))
+ return 1;
+
+ if (unlikely(!host && hv_vcpu->enforce_cpuid && new_config.direct_mode &&
+@@ -687,7 +693,7 @@ static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count,
+ struct kvm_vcpu *vcpu = hv_stimer_to_vcpu(stimer);
+ struct kvm_vcpu_hv_synic *synic = to_hv_synic(vcpu);
+
+- if (!synic->active && !host)
++ if (!synic->active && (!host || count))
+ return 1;
+
+ trace_kvm_hv_stimer_set_count(hv_stimer_to_vcpu(stimer)->vcpu_id,
+@@ -1749,7 +1755,7 @@ struct kvm_hv_hcall {
+ sse128_t xmm[HV_HYPERCALL_MAX_XMM_REGISTERS];
+ };
+
+-static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool ex)
++static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
+ {
+ int i;
+ gpa_t gpa;
+@@ -1765,7 +1771,8 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+ int sparse_banks_len;
+ bool all_cpus;
+
+- if (!ex) {
++ if (hc->code == HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST ||
++ hc->code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE) {
+ if (hc->fast) {
+ flush.address_space = hc->ingpa;
+ flush.flags = hc->outgpa;
+@@ -1819,7 +1826,8 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+
+ if (!all_cpus) {
+ if (hc->fast) {
+- if (sparse_banks_len > HV_HYPERCALL_MAX_XMM_REGISTERS - 1)
++ /* XMM0 is already consumed, each XMM holds two sparse banks. */
++ if (sparse_banks_len > 2 * (HV_HYPERCALL_MAX_XMM_REGISTERS - 1))
+ return HV_STATUS_INVALID_HYPERCALL_INPUT;
+ for (i = 0; i < sparse_banks_len; i += 2) {
+ sparse_banks[i] = sse128_lo(hc->xmm[i / 2 + 1]);
+@@ -1874,7 +1882,7 @@ static void kvm_send_ipi_to_many(struct kvm *kvm, u32 vector,
+ }
+ }
+
+-static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool ex)
++static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
+ {
+ struct kvm *kvm = vcpu->kvm;
+ struct hv_send_ipi_ex send_ipi_ex;
+@@ -1887,8 +1895,9 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+ int sparse_banks_len;
+ u32 vector;
+ bool all_cpus;
++ int i;
+
+- if (!ex) {
++ if (hc->code == HVCALL_SEND_IPI) {
+ if (!hc->fast) {
+ if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi,
+ sizeof(send_ipi))))
+@@ -1907,9 +1916,15 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+
+ trace_kvm_hv_send_ipi(vector, sparse_banks[0]);
+ } else {
+- if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi_ex,
+- sizeof(send_ipi_ex))))
+- return HV_STATUS_INVALID_HYPERCALL_INPUT;
++ if (!hc->fast) {
++ if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi_ex,
++ sizeof(send_ipi_ex))))
++ return HV_STATUS_INVALID_HYPERCALL_INPUT;
++ } else {
++ send_ipi_ex.vector = (u32)hc->ingpa;
++ send_ipi_ex.vp_set.format = hc->outgpa;
++ send_ipi_ex.vp_set.valid_bank_mask = sse128_lo(hc->xmm[0]);
++ }
+
+ trace_kvm_hv_send_ipi_ex(send_ipi_ex.vector,
+ send_ipi_ex.vp_set.format,
+@@ -1917,23 +1932,40 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
+
+ vector = send_ipi_ex.vector;
+ valid_bank_mask = send_ipi_ex.vp_set.valid_bank_mask;
+- sparse_banks_len = bitmap_weight(&valid_bank_mask, 64) *
+- sizeof(sparse_banks[0]);
++ sparse_banks_len = bitmap_weight(&valid_bank_mask, 64);
all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL;
@@ -19249,19 +30894,39 @@ index d5124b520f761..2092834efba11 100644
- if (!all_cpus &&
- kvm_read_guest(kvm,
-+ if (kvm_read_guest(kvm,
- hc->ingpa + offsetof(struct hv_send_ipi_ex,
- vp_set.bank_contents),
- sparse_banks,
-@@ -1934,6 +1936,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
- return HV_STATUS_INVALID_HYPERCALL_INPUT;
+- hc->ingpa + offsetof(struct hv_send_ipi_ex,
+- vp_set.bank_contents),
+- sparse_banks,
+- sparse_banks_len))
+- return HV_STATUS_INVALID_HYPERCALL_INPUT;
++ if (!hc->fast) {
++ if (kvm_read_guest(kvm,
++ hc->ingpa + offsetof(struct hv_send_ipi_ex,
++ vp_set.bank_contents),
++ sparse_banks,
++ sparse_banks_len * sizeof(sparse_banks[0])))
++ return HV_STATUS_INVALID_HYPERCALL_INPUT;
++ } else {
++ /*
++ * The lower half of XMM0 is already consumed, each XMM holds
++ * two sparse banks.
++ */
++ if (sparse_banks_len > (2 * HV_HYPERCALL_MAX_XMM_REGISTERS - 1))
++ return HV_STATUS_INVALID_HYPERCALL_INPUT;
++ for (i = 0; i < sparse_banks_len; i++) {
++ if (i % 2)
++ sparse_banks[i] = sse128_lo(hc->xmm[(i + 1) / 2]);
++ else
++ sparse_banks[i] = sse128_hi(hc->xmm[i / 2]);
++ }
++ }
}
+check_and_send_ipi:
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
return HV_STATUS_INVALID_HYPERCALL_INPUT;
-@@ -2022,7 +2025,7 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
+@@ -2022,7 +2054,7 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
{
bool longmode;
@@ -19270,7 +30935,15 @@ index d5124b520f761..2092834efba11 100644
if (longmode)
kvm_rax_write(vcpu, result);
else {
-@@ -2171,7 +2174,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
+@@ -2092,6 +2124,7 @@ static bool is_xmm_fast_hypercall(struct kvm_hv_hcall *hc)
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX:
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX:
++ case HVCALL_SEND_IPI_EX:
+ return true;
+ }
+
+@@ -2171,7 +2204,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
}
#ifdef CONFIG_X86_64
@@ -19279,6 +30952,58 @@ index d5124b520f761..2092834efba11 100644
hc.param = kvm_rcx_read(vcpu);
hc.ingpa = kvm_rdx_read(vcpu);
hc.outgpa = kvm_r8_read(vcpu);
+@@ -2243,46 +2276,28 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
+ kvm_hv_hypercall_complete_userspace;
+ return 0;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST:
+- if (unlikely(!hc.rep_cnt || hc.rep_idx)) {
+- ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+- break;
+- }
+- ret = kvm_hv_flush_tlb(vcpu, &hc, false);
+- break;
+- case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
+- if (unlikely(hc.rep)) {
+- ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+- break;
+- }
+- ret = kvm_hv_flush_tlb(vcpu, &hc, false);
+- break;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX:
+ if (unlikely(!hc.rep_cnt || hc.rep_idx)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+- ret = kvm_hv_flush_tlb(vcpu, &hc, true);
++ ret = kvm_hv_flush_tlb(vcpu, &hc);
+ break;
++ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX:
+ if (unlikely(hc.rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+- ret = kvm_hv_flush_tlb(vcpu, &hc, true);
++ ret = kvm_hv_flush_tlb(vcpu, &hc);
+ break;
+ case HVCALL_SEND_IPI:
+- if (unlikely(hc.rep)) {
+- ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+- break;
+- }
+- ret = kvm_hv_send_ipi(vcpu, &hc, false);
+- break;
+ case HVCALL_SEND_IPI_EX:
+- if (unlikely(hc.fast || hc.rep)) {
++ if (unlikely(hc.rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+- ret = kvm_hv_send_ipi(vcpu, &hc, true);
++ ret = kvm_hv_send_ipi(vcpu, &hc);
+ break;
+ case HVCALL_POST_DEBUG_DATA:
+ case HVCALL_RETRIEVE_DEBUG_DATA:
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
index 8c065da73f8e5..4e0f52660842b 100644
--- a/arch/x86/kvm/ioapic.c
@@ -19332,11 +31057,33 @@ index 650642b18d151..c2d7cfe82d004 100644
unsigned long irq_states[PIC_NUM_PINS];
};
+diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
+index 68b420289d7ed..fb09cd22cb7f5 100644
+--- a/arch/x86/kvm/kvm_emulate.h
++++ b/arch/x86/kvm/kvm_emulate.h
+@@ -226,6 +226,7 @@ struct x86_emulate_ops {
+ bool (*guest_has_long_mode)(struct x86_emulate_ctxt *ctxt);
+ bool (*guest_has_movbe)(struct x86_emulate_ctxt *ctxt);
+ bool (*guest_has_fxsr)(struct x86_emulate_ctxt *ctxt);
++ bool (*guest_has_rdpid)(struct x86_emulate_ctxt *ctxt);
+
+ void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
+
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
-index d6ac32f3f650c..91c2dc9f198df 100644
+index d6ac32f3f650c..493d636e62316 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
-@@ -676,38 +676,32 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
+@@ -113,7 +113,8 @@ static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
+
+ static bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu)
+ {
+- return pi_inject_timer && kvm_vcpu_apicv_active(vcpu);
++ return pi_inject_timer && kvm_vcpu_apicv_active(vcpu) &&
++ (kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm));
+ }
+
+ bool kvm_can_use_hv_timer(struct kvm_vcpu *vcpu)
+@@ -676,38 +677,32 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
{
u8 val;
@@ -19382,7 +31129,44 @@ index d6ac32f3f650c..91c2dc9f198df 100644
highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu);
else
highest_irr = apic_find_highest_irr(apic);
-@@ -2629,7 +2623,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
+@@ -993,6 +988,10 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
+ *r = -1;
+
+ if (irq->shorthand == APIC_DEST_SELF) {
++ if (KVM_BUG_ON(!src, kvm)) {
++ *r = 0;
++ return true;
++ }
+ *r = kvm_apic_set_irq(src->vcpu, irq, dest_map);
+ return true;
+ }
+@@ -2127,10 +2126,9 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
+ break;
+
+ case APIC_SELF_IPI:
+- if (apic_x2apic_mode(apic)) {
+- kvm_lapic_reg_write(apic, APIC_ICR,
+- APIC_DEST_SELF | (val & APIC_VECTOR_MASK));
+- } else
++ if (apic_x2apic_mode(apic))
++ kvm_apic_send_ipi(apic, APIC_DEST_SELF | (val & APIC_VECTOR_MASK), 0);
++ else
+ ret = 1;
+ break;
+ default:
+@@ -2248,10 +2246,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+
+ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
+ {
+- struct kvm_lapic *apic = vcpu->arch.apic;
+-
+- apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
+- | (kvm_lapic_get_reg(apic, APIC_TASKPRI) & 4));
++ apic_set_tpr(vcpu->arch.apic, (cr8 & 0x0f) << 4);
+ }
+
+ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
+@@ -2629,7 +2624,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
kvm_apic_set_version(vcpu);
apic_update_ppr(apic);
@@ -19391,8 +31175,20 @@ index d6ac32f3f650c..91c2dc9f198df 100644
apic->lapic_timer.expired_tscdeadline = 0;
apic_update_lvtt(apic);
apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
+diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
+index e9688a9f7b579..7bb165c232334 100644
+--- a/arch/x86/kvm/mmu.h
++++ b/arch/x86/kvm/mmu.h
+@@ -49,6 +49,7 @@
+ X86_CR4_LA57)
+
+ #define KVM_MMU_CR0_ROLE_BITS (X86_CR0_PG | X86_CR0_WP)
++#define KVM_MMU_EFER_ROLE_BITS (EFER_LME | EFER_NX)
+
+ static __always_inline u64 rsvd_bits(int s, int e)
+ {
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
-index 0cc58901bf7a7..2297dd90fe4a5 100644
+index 0cc58901bf7a7..3417405077adf 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -1592,7 +1592,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
@@ -19417,7 +31213,16 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
if (iterator->level == PT32E_ROOT_LEVEL) {
/*
-@@ -3579,7 +3579,7 @@ set_root_pgd:
+@@ -3314,6 +3314,8 @@ static void mmu_free_root_page(struct kvm *kvm, hpa_t *root_hpa,
+ return;
+
+ sp = to_shadow_page(*root_hpa & PT64_BASE_ADDR_MASK);
++ if (WARN_ON(!sp))
++ return;
+
+ if (is_tdp_mmu_page(sp))
+ kvm_tdp_mmu_put_root(kvm, sp, false);
+@@ -3579,7 +3581,7 @@ set_root_pgd:
out_unlock:
write_unlock(&vcpu->kvm->mmu_lock);
@@ -19426,7 +31231,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
}
static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu)
-@@ -3889,12 +3889,23 @@ static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr)
+@@ -3889,12 +3891,23 @@ static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr)
walk_shadow_page_lockless_end(vcpu);
}
@@ -19451,7 +31256,15 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
arch.gfn = gfn;
arch.direct_map = vcpu->arch.mmu->direct_map;
arch.cr3 = vcpu->arch.mmu->get_guest_pgd(vcpu);
-@@ -4679,6 +4690,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu,
+@@ -3956,6 +3969,7 @@ static bool kvm_faultin_pfn(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
+
+ *pfn = __gfn_to_pfn_memslot(slot, gfn, false, NULL,
+ write, writable, hva);
++ return false;
+
+ out_retry:
+ *r = RET_PF_RETRY;
+@@ -4679,6 +4693,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu,
/* PKEY and LA57 are active iff long mode is active. */
ext.cr4_pke = ____is_efer_lma(regs) && ____is_cr4_pke(regs);
ext.cr4_la57 = ____is_efer_lma(regs) && ____is_cr4_la57(regs);
@@ -19459,7 +31272,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
}
ext.valid = 1;
-@@ -4851,7 +4863,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
+@@ -4851,7 +4866,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
struct kvm_mmu *context = &vcpu->arch.guest_mmu;
struct kvm_mmu_role_regs regs = {
.cr0 = cr0,
@@ -19468,7 +31281,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
.efer = efer,
};
union kvm_mmu_role new_role;
-@@ -4915,7 +4927,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
+@@ -4915,7 +4930,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
context->direct_map = false;
update_permission_bitmask(context, true);
@@ -19477,7 +31290,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
reset_rsvds_bits_mask_ept(vcpu, context, execonly);
reset_ept_shadow_zero_bits_mask(vcpu, context, execonly);
}
-@@ -5368,7 +5380,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+@@ -5368,7 +5383,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
{
@@ -19486,7 +31299,26 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
++vcpu->stat.invlpg;
}
EXPORT_SYMBOL_GPL(kvm_mmu_invlpg);
-@@ -5473,8 +5485,8 @@ slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot,
+@@ -5381,14 +5396,16 @@ void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid)
+ uint i;
+
+ if (pcid == kvm_get_active_pcid(vcpu)) {
+- mmu->invlpg(vcpu, gva, mmu->root_hpa);
++ if (mmu->invlpg)
++ mmu->invlpg(vcpu, gva, mmu->root_hpa);
+ tlb_flush = true;
+ }
+
+ for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
+ if (VALID_PAGE(mmu->prev_roots[i].hpa) &&
+ pcid == kvm_get_pcid(vcpu, mmu->prev_roots[i].pgd)) {
+- mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa);
++ if (mmu->invlpg)
++ mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa);
+ tlb_flush = true;
+ }
+ }
+@@ -5473,8 +5490,8 @@ slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot,
}
static __always_inline bool
@@ -19497,7 +31329,32 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
{
return slot_handle_level(kvm, memslot, fn, PG_LEVEL_4K,
PG_LEVEL_4K, flush_on_yield);
-@@ -5758,13 +5770,11 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
+@@ -5575,6 +5592,7 @@ static void kvm_zap_obsolete_pages(struct kvm *kvm)
+ {
+ struct kvm_mmu_page *sp, *node;
+ int nr_zapped, batch = 0;
++ bool unstable;
+
+ restart:
+ list_for_each_entry_safe_reverse(sp, node,
+@@ -5606,11 +5624,12 @@ restart:
+ goto restart;
+ }
+
+- if (__kvm_mmu_prepare_zap_page(kvm, sp,
+- &kvm->arch.zapped_obsolete_pages, &nr_zapped)) {
+- batch += nr_zapped;
++ unstable = __kvm_mmu_prepare_zap_page(kvm, sp,
++ &kvm->arch.zapped_obsolete_pages, &nr_zapped);
++ batch += nr_zapped;
++
++ if (unstable)
+ goto restart;
+- }
+ }
+
+ /*
+@@ -5758,13 +5777,11 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, gfn_start,
gfn_end, flush);
@@ -19513,7 +31370,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
kvm_dec_notifier_count(kvm, gfn_start, gfn_end);
-@@ -5856,21 +5866,21 @@ restart:
+@@ -5856,21 +5873,21 @@ restart:
void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
const struct kvm_memory_slot *slot)
{
@@ -19542,7 +31399,7 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
read_unlock(&kvm->mmu_lock);
}
}
-@@ -5897,8 +5907,11 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
+@@ -5897,8 +5914,11 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
if (kvm_memslots_have_rmaps(kvm)) {
write_lock(&kvm->mmu_lock);
@@ -19556,6 +31413,154 @@ index 0cc58901bf7a7..2297dd90fe4a5 100644
write_unlock(&kvm->mmu_lock);
}
+@@ -6091,12 +6111,24 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp)
+ return 0;
+ }
+
+-int kvm_mmu_module_init(void)
++/*
++ * 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)
+ {
+- int ret = -ENOMEM;
+-
+ if (nx_huge_pages == -1)
+ __set_nx_huge_pages(get_nx_auto_mode());
++}
++
++/*
++ * The bulk of the MMU initialization is deferred until the vendor module is
++ * loaded as many of the masks/values may be modified by VMX or SVM, i.e. need
++ * to be reset when a potentially different vendor module is loaded.
++ */
++int kvm_mmu_vendor_module_init(void)
++{
++ int ret = -ENOMEM;
+
+ /*
+ * MMU roles use union aliasing which is, generally speaking, an
+@@ -6168,7 +6200,7 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
+ mmu_free_memory_caches(vcpu);
+ }
+
+-void kvm_mmu_module_exit(void)
++void kvm_mmu_vendor_module_exit(void)
+ {
+ mmu_destroy_caches();
+ percpu_counter_destroy(&kvm_total_used_mmu_pages);
+diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
+index 913d52a7923e6..a1811f51eda92 100644
+--- a/arch/x86/kvm/mmu/paging_tmpl.h
++++ b/arch/x86/kvm/mmu/paging_tmpl.h
+@@ -34,9 +34,8 @@
+ #define PT_HAVE_ACCESSED_DIRTY(mmu) true
+ #ifdef CONFIG_X86_64
+ #define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
+- #define CMPXCHG cmpxchg
++ #define CMPXCHG "cmpxchgq"
+ #else
+- #define CMPXCHG cmpxchg64
+ #define PT_MAX_FULL_LEVELS 2
+ #endif
+ #elif PTTYPE == 32
+@@ -52,7 +51,7 @@
+ #define PT_GUEST_DIRTY_SHIFT PT_DIRTY_SHIFT
+ #define PT_GUEST_ACCESSED_SHIFT PT_ACCESSED_SHIFT
+ #define PT_HAVE_ACCESSED_DIRTY(mmu) true
+- #define CMPXCHG cmpxchg
++ #define CMPXCHG "cmpxchgl"
+ #elif PTTYPE == PTTYPE_EPT
+ #define pt_element_t u64
+ #define guest_walker guest_walkerEPT
+@@ -65,7 +64,9 @@
+ #define PT_GUEST_DIRTY_SHIFT 9
+ #define PT_GUEST_ACCESSED_SHIFT 8
+ #define PT_HAVE_ACCESSED_DIRTY(mmu) ((mmu)->ept_ad)
+- #define CMPXCHG cmpxchg64
++ #ifdef CONFIG_X86_64
++ #define CMPXCHG "cmpxchgq"
++ #endif
+ #define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
+ #else
+ #error Invalid PTTYPE value
+@@ -147,43 +148,39 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+ pt_element_t __user *ptep_user, unsigned index,
+ pt_element_t orig_pte, pt_element_t new_pte)
+ {
+- int npages;
+- pt_element_t ret;
+- pt_element_t *table;
+- struct page *page;
+-
+- npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
+- if (likely(npages == 1)) {
+- table = kmap_atomic(page);
+- ret = CMPXCHG(&table[index], orig_pte, new_pte);
+- kunmap_atomic(table);
+-
+- kvm_release_page_dirty(page);
+- } else {
+- struct vm_area_struct *vma;
+- unsigned long vaddr = (unsigned long)ptep_user & PAGE_MASK;
+- unsigned long pfn;
+- unsigned long paddr;
+-
+- mmap_read_lock(current->mm);
+- vma = find_vma_intersection(current->mm, vaddr, vaddr + PAGE_SIZE);
+- if (!vma || !(vma->vm_flags & VM_PFNMAP)) {
+- mmap_read_unlock(current->mm);
+- return -EFAULT;
+- }
+- pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+- paddr = pfn << PAGE_SHIFT;
+- table = memremap(paddr, PAGE_SIZE, MEMREMAP_WB);
+- if (!table) {
+- mmap_read_unlock(current->mm);
+- return -EFAULT;
+- }
+- ret = CMPXCHG(&table[index], orig_pte, new_pte);
+- memunmap(table);
+- mmap_read_unlock(current->mm);
+- }
++ int r = -EFAULT;
++
++ if (!user_access_begin(ptep_user, sizeof(pt_element_t)))
++ return -EFAULT;
++
++#ifdef CMPXCHG
++ asm volatile("1:" LOCK_PREFIX CMPXCHG " %[new], %[ptr]\n"
++ "mov $0, %[r]\n"
++ "setnz %b[r]\n"
++ "2:"
++ _ASM_EXTABLE_UA(1b, 2b)
++ : [ptr] "+m" (*ptep_user),
++ [old] "+a" (orig_pte),
++ [r] "+q" (r)
++ : [new] "r" (new_pte)
++ : "memory");
++#else
++ asm volatile("1:" LOCK_PREFIX "cmpxchg8b %[ptr]\n"
++ "movl $0, %[r]\n"
++ "jz 2f\n"
++ "incl %[r]\n"
++ "2:"
++ _ASM_EXTABLE_UA(1b, 2b)
++ : [ptr] "+m" (*ptep_user),
++ [old] "+A" (orig_pte),
++ [r] "+rm" (r)
++ : [new_lo] "b" ((u32)new_pte),
++ [new_hi] "c" ((u32)(new_pte >> 32))
++ : "memory");
++#endif
+
+- return (ret != orig_pte);
++ user_access_end();
++ return r;
+ }
+
+ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
index eb7b227fc6cfe..31d6456d8ac33 100644
--- a/arch/x86/kvm/mmu/spte.h
@@ -19616,10 +31621,88 @@ index b1748b988d3ae..e19cabbcb65c8 100644
/*
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
-index 64ccfc1fa5535..d479b2b121259 100644
+index 64ccfc1fa5535..853780eb033b4 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
-@@ -316,9 +316,6 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
+@@ -99,15 +99,18 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
+ }
+
+ /*
+- * Finds the next valid root after root (or the first valid root if root
+- * is NULL), takes a reference on it, and returns that next root. If root
+- * is not NULL, this thread should have already taken a reference on it, and
+- * that reference will be dropped. If no valid root is found, this
+- * function will return NULL.
++ * Returns the next root after @prev_root (or the first root if @prev_root is
++ * NULL). A reference to the returned root is acquired, and the reference to
++ * @prev_root is released (the caller obviously must hold a reference to
++ * @prev_root if it's non-NULL).
++ *
++ * If @only_valid is true, invalid roots are skipped.
++ *
++ * Returns NULL if the end of tdp_mmu_roots was reached.
+ */
+ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm,
+ struct kvm_mmu_page *prev_root,
+- bool shared)
++ bool shared, bool only_valid)
+ {
+ struct kvm_mmu_page *next_root;
+
+@@ -121,9 +124,14 @@ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm,
+ next_root = list_first_or_null_rcu(&kvm->arch.tdp_mmu_roots,
+ typeof(*next_root), link);
+
+- while (next_root && !kvm_tdp_mmu_get_root(kvm, next_root))
++ while (next_root) {
++ if ((!only_valid || !next_root->role.invalid) &&
++ kvm_tdp_mmu_get_root(kvm, next_root))
++ break;
++
+ next_root = list_next_or_null_rcu(&kvm->arch.tdp_mmu_roots,
+ &next_root->link, typeof(*next_root), link);
++ }
+
+ rcu_read_unlock();
+
+@@ -143,13 +151,19 @@ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm,
+ * mode. In the unlikely event that this thread must free a root, the lock
+ * will be temporarily dropped and reacquired in write mode.
+ */
+-#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared) \
+- for (_root = tdp_mmu_next_root(_kvm, NULL, _shared); \
+- _root; \
+- _root = tdp_mmu_next_root(_kvm, _root, _shared)) \
+- if (kvm_mmu_page_as_id(_root) != _as_id) { \
++#define __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared, _only_valid)\
++ for (_root = tdp_mmu_next_root(_kvm, NULL, _shared, _only_valid); \
++ _root; \
++ _root = tdp_mmu_next_root(_kvm, _root, _shared, _only_valid)) \
++ if (kvm_mmu_page_as_id(_root) != _as_id) { \
+ } else
+
++#define for_each_valid_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared) \
++ __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared, true)
++
++#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared) \
++ __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared, false)
++
+ #define for_each_tdp_mmu_root(_kvm, _root, _as_id) \
+ list_for_each_entry_rcu(_root, &_kvm->arch.tdp_mmu_roots, link, \
+ lockdep_is_held_type(&kvm->mmu_lock, 0) || \
+@@ -199,7 +213,10 @@ hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu)
+
+ role = page_role_for_level(vcpu, vcpu->arch.mmu->shadow_root_level);
+
+- /* Check for an existing root before allocating a new one. */
++ /*
++ * Check for an existing root before allocating a new one. Note, the
++ * role check prevents consuming an invalid root.
++ */
+ for_each_tdp_mmu_root(kvm, root, kvm_mmu_role_as_id(role)) {
+ if (root->role.word == role.word &&
+ kvm_tdp_mmu_get_root(kvm, root))
+@@ -316,9 +333,6 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
struct kvm_mmu_page *sp = sptep_to_sp(rcu_dereference(pt));
int level = sp->role.level;
gfn_t base_gfn = sp->gfn;
@@ -19629,7 +31712,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
int i;
trace_kvm_mmu_prepare_zap_page(sp);
-@@ -326,8 +323,9 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
+@@ -326,8 +340,9 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
tdp_mmu_unlink_page(kvm, sp, shared);
for (i = 0; i < PT64_ENT_PER_PAGE; i++) {
@@ -19641,7 +31724,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
if (shared) {
/*
-@@ -373,7 +371,7 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
+@@ -373,7 +388,7 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt,
shared);
}
@@ -19650,7 +31733,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
KVM_PAGES_PER_HPAGE(level + 1));
call_rcu(&sp->rcu_head, tdp_mmu_free_sp_rcu_callback);
-@@ -503,6 +501,8 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm,
+@@ -503,6 +518,8 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm,
struct tdp_iter *iter,
u64 new_spte)
{
@@ -19659,7 +31742,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
lockdep_assert_held_read(&kvm->mmu_lock);
/*
-@@ -613,6 +613,8 @@ static inline void __tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter,
+@@ -613,6 +630,8 @@ static inline void __tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter,
u64 new_spte, bool record_acc_track,
bool record_dirty_log)
{
@@ -19668,7 +31751,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
lockdep_assert_held_write(&kvm->mmu_lock);
/*
-@@ -678,18 +680,19 @@ static inline void tdp_mmu_set_spte_no_dirty_log(struct kvm *kvm,
+@@ -678,18 +697,19 @@ static inline void tdp_mmu_set_spte_no_dirty_log(struct kvm *kvm,
* If this function should yield and flush is set, it will perform a remote
* TLB flush before yielding.
*
@@ -19697,7 +31780,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
/* Ensure forward progress has been made before yielding. */
if (iter->next_last_level_gfn == iter->yielded_gfn)
return false;
-@@ -709,12 +712,10 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,
+@@ -709,12 +729,10 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm,
WARN_ON(iter->gfn > iter->next_last_level_gfn);
@@ -19712,7 +31795,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
}
/*
-@@ -1083,8 +1084,8 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
+@@ -1083,8 +1101,8 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
struct kvm_mmu_page *root;
for_each_tdp_mmu_root(kvm, root, range->slot->as_id)
@@ -19723,7 +31806,35 @@ index 64ccfc1fa5535..d479b2b121259 100644
return flush;
}
-@@ -1415,10 +1416,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
+@@ -1270,7 +1288,7 @@ bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
+
+ lockdep_assert_held_read(&kvm->mmu_lock);
+
+- for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
++ for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
+ spte_set |= wrprot_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages, min_level);
+
+@@ -1298,6 +1316,9 @@ retry:
+ if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
+ continue;
+
++ if (!is_shadow_present_pte(iter.old_spte))
++ continue;
++
+ if (spte_ad_need_write_protect(iter.old_spte)) {
+ if (is_writable_pte(iter.old_spte))
+ new_spte = iter.old_spte & ~PT_WRITABLE_MASK;
+@@ -1341,7 +1362,7 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
+
+ lockdep_assert_held_read(&kvm->mmu_lock);
+
+- for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
++ for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
+ spte_set |= clear_dirty_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages);
+
+@@ -1415,10 +1436,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
* Clear leaf entries which could be replaced by large mappings, for
* GFNs within the slot.
*/
@@ -19736,7 +31847,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
{
gfn_t start = slot->base_gfn;
gfn_t end = start + slot->npages;
-@@ -1429,10 +1429,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm,
+@@ -1429,10 +1449,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm,
tdp_root_for_each_pte(iter, root, start, end) {
retry:
@@ -19748,7 +31859,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
if (!is_shadow_present_pte(iter.old_spte) ||
!is_last_spte(iter.old_spte, iter.level))
-@@ -1444,6 +1442,7 @@ retry:
+@@ -1444,6 +1462,7 @@ retry:
pfn, PG_LEVEL_NUM))
continue;
@@ -19756,7 +31867,7 @@ index 64ccfc1fa5535..d479b2b121259 100644
if (!tdp_mmu_zap_spte_atomic(kvm, &iter)) {
/*
* The iter must explicitly re-read the SPTE because
-@@ -1452,30 +1451,24 @@ retry:
+@@ -1452,30 +1471,24 @@ retry:
iter.old_spte = READ_ONCE(*rcu_dereference(iter.sptep));
goto retry;
}
@@ -19782,15 +31893,16 @@ index 64ccfc1fa5535..d479b2b121259 100644
lockdep_assert_held_read(&kvm->mmu_lock);
- for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
+- for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
- flush = zap_collapsible_spte_range(kvm, root, slot, flush);
-
- return flush;
++ for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
+ zap_collapsible_spte_range(kvm, root, slot);
}
/*
-@@ -1500,12 +1493,12 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root,
+@@ -1500,12 +1513,12 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root,
!is_last_spte(iter.old_spte, iter.level))
continue;
@@ -19807,10 +31919,20 @@ index 64ccfc1fa5535..d479b2b121259 100644
spte_set = true;
}
diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
-index 358f447d40120..ba3681cd38ab4 100644
+index 358f447d40120..39468b637d2e4 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.h
+++ b/arch/x86/kvm/mmu/tdp_mmu.h
-@@ -66,9 +66,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
+@@ -10,9 +10,6 @@ hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu);
+ __must_check static inline bool kvm_tdp_mmu_get_root(struct kvm *kvm,
+ struct kvm_mmu_page *root)
+ {
+- if (root->role.invalid)
+- return false;
+-
+ return refcount_inc_not_zero(&root->tdp_mmu_root_count);
+ }
+
+@@ -66,9 +63,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
struct kvm_memory_slot *slot,
gfn_t gfn, unsigned long mask,
bool wrprot);
@@ -19823,19 +31945,41 @@ index 358f447d40120..ba3681cd38ab4 100644
bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
struct kvm_memory_slot *slot, gfn_t gfn,
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
-index 0772bad9165c5..f256f01056bdb 100644
+index 0772bad9165c5..62333f9756a36 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
-@@ -95,7 +95,7 @@ static void kvm_perf_overflow_intr(struct perf_event *perf_event,
+@@ -95,9 +95,8 @@ static void kvm_perf_overflow_intr(struct perf_event *perf_event,
}
static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
- unsigned config, bool exclude_user,
+- bool exclude_kernel, bool intr,
+- bool in_tx, bool in_tx_cp)
+ u64 config, bool exclude_user,
- bool exclude_kernel, bool intr,
- bool in_tx, bool in_tx_cp)
++ bool exclude_kernel, bool intr)
{
-@@ -173,8 +173,8 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
+ struct perf_event *event;
+ struct perf_event_attr attr = {
+@@ -113,16 +112,14 @@ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
+
+ attr.sample_period = get_sample_period(pmc, pmc->counter);
+
+- if (in_tx)
+- attr.config |= HSW_IN_TX;
+- if (in_tx_cp) {
++ if ((attr.config & HSW_IN_TX_CHECKPOINTED) &&
++ guest_cpuid_is_intel(pmc->vcpu)) {
+ /*
+ * HSW_IN_TX_CHECKPOINTED is not supported with nonzero
+ * period. Just clear the sample period so at least
+ * allocating the counter doesn't fail.
+ */
+ attr.sample_period = 0;
+- attr.config |= HSW_IN_TX_CHECKPOINTED;
+ }
+
+ event = perf_event_create_kernel_counter(&attr, -1, current,
+@@ -173,11 +170,12 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
{
@@ -19846,7 +31990,11 @@ index 0772bad9165c5..f256f01056bdb 100644
struct kvm *kvm = pmc->vcpu->kvm;
struct kvm_pmu_event_filter *filter;
int i;
-@@ -206,23 +206,18 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
++ struct kvm_pmu *pmu = vcpu_to_pmu(pmc->vcpu);
+ bool allow_event = true;
+
+ if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+@@ -206,23 +204,18 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
if (!allow_event)
return;
@@ -19868,12 +32016,32 @@ index 0772bad9165c5..f256f01056bdb 100644
if (type == PERF_TYPE_RAW)
- config = eventsel & X86_RAW_EVENT_MASK;
-+ config = eventsel & AMD64_RAW_EVENT_MASK;
++ config = eventsel & pmu->raw_event_mask;
if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
return;
+@@ -233,9 +226,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ pmc_reprogram_counter(pmc, type, config,
+ !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
+ !(eventsel & ARCH_PERFMON_EVENTSEL_OS),
+- eventsel & ARCH_PERFMON_EVENTSEL_INT,
+- (eventsel & HSW_IN_TX),
+- (eventsel & HSW_IN_TX_CHECKPOINTED));
++ eventsel & ARCH_PERFMON_EVENTSEL_INT);
+ }
+ EXPORT_SYMBOL_GPL(reprogram_gp_counter);
+
+@@ -271,7 +262,7 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
+ kvm_x86_ops.pmu_ops->find_fixed_event(idx),
+ !(en_field & 0x2), /* exclude user */
+ !(en_field & 0x1), /* exclude kernel */
+- pmi, false, false);
++ pmi);
+ }
+ EXPORT_SYMBOL_GPL(reprogram_fixed_counter);
+
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
-index 0e4f2b1fa9fbd..a06d95165ac7c 100644
+index 0e4f2b1fa9fbd..c206decb39fab 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -24,8 +24,7 @@ struct kvm_event_hw_type_mapping {
@@ -19886,8 +32054,24 @@ index 0e4f2b1fa9fbd..a06d95165ac7c 100644
unsigned (*find_fixed_event)(int idx);
bool (*pmc_is_enabled)(struct kvm_pmc *pmc);
struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx);
+@@ -142,6 +141,15 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
+ return sample_period;
+ }
+
++static inline void pmc_update_sample_period(struct kvm_pmc *pmc)
++{
++ if (!pmc->perf_event || pmc->is_paused)
++ return;
++
++ perf_event_period(pmc->perf_event,
++ get_sample_period(pmc, pmc->counter));
++}
++
+ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel);
+ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int fixed_idx);
+ void reprogram_counter(struct kvm_pmu *pmu, int pmc_idx);
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
-index 8052d92069e01..cdbb48e12745c 100644
+index 8052d92069e01..3d3f8dfb80457 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -342,8 +342,6 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu)
@@ -19899,7 +32083,48 @@ index 8052d92069e01..cdbb48e12745c 100644
break;
case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
WARN_ONCE(1, "Invalid backing page\n");
-@@ -988,16 +986,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
+@@ -801,7 +799,7 @@ int svm_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
+ {
+ struct kvm_kernel_irq_routing_entry *e;
+ struct kvm_irq_routing_table *irq_rt;
+- int idx, ret = -EINVAL;
++ int idx, ret = 0;
+
+ if (!kvm_arch_has_assigned_device(kvm) ||
+ !irq_remapping_cap(IRQ_POSTING_CAP))
+@@ -812,7 +810,13 @@ int svm_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
+
+ idx = srcu_read_lock(&kvm->irq_srcu);
+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
+- WARN_ON(guest_irq >= irq_rt->nr_rt_entries);
++
++ if (guest_irq >= irq_rt->nr_rt_entries ||
++ hlist_empty(&irq_rt->map[guest_irq])) {
++ pr_warn_once("no route for guest_irq %u/%u (broken user space?)\n",
++ guest_irq, irq_rt->nr_rt_entries);
++ goto out;
++ }
+
+ hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) {
+ struct vcpu_data vcpu_info;
+@@ -943,15 +947,10 @@ out:
+ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ {
+ u64 entry;
+- /* ID = 0xff (broadcast), ID > 0xff (reserved) */
+ int h_physical_id = kvm_cpu_get_apicid(cpu);
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+- /*
+- * Since the host physical APIC id is 8 bits,
+- * we can support host APIC ID upto 255.
+- */
+- if (WARN_ON(h_physical_id > AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
++ if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
+ return;
+
+ entry = READ_ONCE(*(svm->avic_physical_id_cache));
+@@ -988,16 +987,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -20008,10 +32233,33 @@ index 510b833cbd399..556e7a3f35627 100644
.triple_fault = nested_svm_triple_fault,
.get_nested_state_pages = svm_get_nested_state_pages,
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
-index fdf587f19c5fb..06f8034f62e4f 100644
+index fdf587f19c5fb..d35c94e13afb0 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
-@@ -134,10 +134,10 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
+@@ -44,6 +44,22 @@ static struct kvm_event_hw_type_mapping amd_event_mapping[] = {
+ [7] = { 0xd1, 0x00, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+ };
+
++/* duplicated from amd_f17h_perfmon_event_map. */
++static struct kvm_event_hw_type_mapping amd_f17h_event_mapping[] = {
++ [0] = { 0x76, 0x00, PERF_COUNT_HW_CPU_CYCLES },
++ [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS },
++ [2] = { 0x60, 0xff, PERF_COUNT_HW_CACHE_REFERENCES },
++ [3] = { 0x64, 0x09, PERF_COUNT_HW_CACHE_MISSES },
++ [4] = { 0xc2, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
++ [5] = { 0xc3, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
++ [6] = { 0x87, 0x02, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
++ [7] = { 0x87, 0x01, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
++};
++
++/* amd_pmc_perf_hw_id depends on these being the same size */
++static_assert(ARRAY_SIZE(amd_event_mapping) ==
++ ARRAY_SIZE(amd_f17h_event_mapping));
++
+ static unsigned int get_msr_base(struct kvm_pmu *pmu, enum pmu_type type)
+ {
+ struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu);
+@@ -134,21 +150,27 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
return &pmu->gp_counters[msr_to_index(msr)];
}
@@ -20020,21 +32268,64 @@ index fdf587f19c5fb..06f8034f62e4f 100644
- u8 unit_mask)
+static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc)
{
++ struct kvm_event_hw_type_mapping *event_mapping;
+ u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
+ u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
int i;
++ if (guest_cpuid_family(pmc->vcpu) >= 0x17)
++ event_mapping = amd_f17h_event_mapping;
++ else
++ event_mapping = amd_event_mapping;
++
for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++)
-@@ -282,7 +282,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
+- if (amd_event_mapping[i].eventsel == event_select
+- && amd_event_mapping[i].unit_mask == unit_mask)
++ if (event_mapping[i].eventsel == event_select
++ && event_mapping[i].unit_mask == unit_mask)
+ break;
+
+ if (i == ARRAY_SIZE(amd_event_mapping))
+ return PERF_COUNT_HW_MAX;
+
+- return amd_event_mapping[i].event_type;
++ return event_mapping[i].event_type;
+ }
+
+ /* return PERF_COUNT_HW_MAX as AMD doesn't have fixed events */
+@@ -256,17 +278,16 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_COUNTER);
+ if (pmc) {
+ pmc->counter += data - pmc_read_counter(pmc);
++ pmc_update_sample_period(pmc);
+ return 0;
+ }
+ /* MSR_EVNTSELn */
+ pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_EVNTSEL);
+ if (pmc) {
+- if (data == pmc->eventsel)
+- return 0;
+- if (!(data & pmu->reserved_bits)) {
++ data &= ~pmu->reserved_bits;
++ if (data != pmc->eventsel)
+ reprogram_gp_counter(pmc, data);
+- return 0;
+- }
++ return 0;
+ }
+
+ return 1;
+@@ -282,7 +303,8 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS;
pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1;
- pmu->reserved_bits = 0xffffffff00200000ull;
+ pmu->reserved_bits = 0xfffffff000280000ull;
++ pmu->raw_event_mask = AMD64_RAW_EVENT_MASK;
pmu->version = 1;
/* not applicable to AMD; but clean them to prevent any fall out */
pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
-@@ -320,7 +320,7 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu)
+@@ -320,7 +342,7 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu)
}
struct kvm_pmu_ops amd_pmu_ops = {
@@ -20044,7 +32335,7 @@ index fdf587f19c5fb..06f8034f62e4f 100644
.pmc_is_enabled = amd_pmc_is_enabled,
.pmc_idx_to_pmc = amd_pmc_idx_to_pmc,
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
-index 7e34d7163adab..134c4ea5e6ad8 100644
+index 7e34d7163adab..c8c3212250618 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1787,7 +1787,12 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
@@ -20069,7 +32360,25 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
/*
* Do not copy ap_jump_table. Since the mirror does not share the same
* KVM contexts as the original, and they may have different
-@@ -2311,7 +2317,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu)
+@@ -1984,11 +1990,14 @@ static void sev_flush_guest_memory(struct vcpu_svm *svm, void *va,
+ unsigned long len)
+ {
+ /*
+- * If hardware enforced cache coherency for encrypted mappings of the
+- * same physical page is supported, nothing to do.
++ * If CPU enforced cache coherency for encrypted mappings of the
++ * same physical page is supported, use CLFLUSHOPT instead. NOTE: cache
++ * flush is still needed in order to work properly with DMA devices.
+ */
+- if (boot_cpu_has(X86_FEATURE_SME_COHERENT))
++ if (boot_cpu_has(X86_FEATURE_SME_COHERENT)) {
++ clflush_cache_range(va, PAGE_SIZE);
+ return;
++ }
+
+ /*
+ * If the VM Page Flush MSR is supported, use it to flush the page
+@@ -2311,7 +2320,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu)
}
#define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE)
@@ -20078,7 +32387,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
{
struct vmcb_control_area *control = &svm->vmcb->control;
struct ghcb *ghcb = svm->ghcb;
-@@ -2322,14 +2328,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+@@ -2322,14 +2331,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
scratch_gpa_beg = ghcb_get_sw_scratch(ghcb);
if (!scratch_gpa_beg) {
pr_err("vmgexit: scratch gpa not provided\n");
@@ -20095,7 +32404,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
}
if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) {
-@@ -2347,7 +2353,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+@@ -2347,7 +2356,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
scratch_gpa_end > ghcb_scratch_end) {
pr_err("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n",
scratch_gpa_beg, scratch_gpa_end);
@@ -20104,7 +32413,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
}
scratch_va = (void *)svm->ghcb;
-@@ -2360,18 +2366,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+@@ -2360,18 +2369,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
if (len > GHCB_SCRATCH_AREA_LIMIT) {
pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n",
len, GHCB_SCRATCH_AREA_LIMIT);
@@ -20126,7 +32435,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
}
/*
-@@ -2387,7 +2393,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+@@ -2387,7 +2396,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
svm->ghcb_sa = scratch_va;
svm->ghcb_sa_len = len;
@@ -20135,7 +32444,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
}
static void set_ghcb_msr_bits(struct vcpu_svm *svm, u64 value, u64 mask,
-@@ -2526,10 +2532,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+@@ -2526,10 +2535,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
ghcb_set_sw_exit_info_1(ghcb, 0);
ghcb_set_sw_exit_info_2(ghcb, 0);
@@ -20148,7 +32457,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
break;
ret = kvm_sev_es_mmio_read(vcpu,
-@@ -2538,7 +2544,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+@@ -2538,7 +2547,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
svm->ghcb_sa);
break;
case SVM_VMGEXIT_MMIO_WRITE:
@@ -20158,7 +32467,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
break;
ret = kvm_sev_es_mmio_write(vcpu,
-@@ -2581,6 +2588,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+@@ -2581,6 +2591,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
vcpu_unimpl(vcpu,
"vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",
control->exit_info_1, control->exit_info_2);
@@ -20166,7 +32475,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
break;
default:
ret = svm_invoke_exit_handler(vcpu, exit_code);
-@@ -2593,6 +2601,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
+@@ -2593,6 +2604,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
{
int count;
int bytes;
@@ -20174,7 +32483,7 @@ index 7e34d7163adab..134c4ea5e6ad8 100644
if (svm->vmcb->control.exit_info_2 > INT_MAX)
return -EINVAL;
-@@ -2601,8 +2610,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
+@@ -2601,8 +2613,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
if (unlikely(check_mul_overflow(count, size, &bytes)))
return -EINVAL;
@@ -20416,10 +32725,19 @@ index 989685098b3ea..26f2da1590eda 100644
.set_tss_addr = svm_set_tss_addr,
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
-index 5d30db599e10d..ff0855c03c917 100644
+index 5d30db599e10d..cf2d8365aeb4b 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
-@@ -461,7 +461,7 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm)
+@@ -22,6 +22,8 @@
+ #include <asm/svm.h>
+ #include <asm/sev-common.h>
+
++#include "kvm_cache_regs.h"
++
+ #define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT)
+
+ #define IOPM_SIZE PAGE_SIZE * 3
+@@ -461,7 +463,7 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm)
int enter_svm_guest_mode(struct kvm_vcpu *vcpu,
u64 vmcb_gpa, struct vmcb *vmcb12, bool from_vmrun);
@@ -20428,6 +32746,49 @@ index 5d30db599e10d..ff0855c03c917 100644
void svm_free_nested(struct vcpu_svm *svm);
int svm_allocate_nested(struct vcpu_svm *svm);
int nested_svm_vmrun(struct kvm_vcpu *vcpu);
+@@ -497,7 +499,7 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
+ #define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31
+ #define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
+
+-#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL)
++#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK GENMASK_ULL(11, 0)
+ #define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
+ #define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
+ #define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
+diff --git a/arch/x86/kvm/svm/svm_onhyperv.c b/arch/x86/kvm/svm/svm_onhyperv.c
+index 98aa981c04ec5..8cdc62c74a964 100644
+--- a/arch/x86/kvm/svm/svm_onhyperv.c
++++ b/arch/x86/kvm/svm/svm_onhyperv.c
+@@ -4,7 +4,6 @@
+ */
+
+ #include <linux/kvm_host.h>
+-#include "kvm_cache_regs.h"
+
+ #include <asm/mshyperv.h>
+
+diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
+index 4fa17df123cd6..dfaeb47fcf2a7 100644
+--- a/arch/x86/kvm/svm/vmenter.S
++++ b/arch/x86/kvm/svm/vmenter.S
+@@ -148,7 +148,7 @@ SYM_FUNC_START(__svm_vcpu_run)
+ pop %edi
+ #endif
+ pop %_ASM_BP
+- ret
++ RET
+
+ 3: cmpb $0, kvm_rebooting
+ jne 2b
+@@ -202,7 +202,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
+ pop %edi
+ #endif
+ pop %_ASM_BP
+- ret
++ RET
+
+ 3: cmpb $0, kvm_rebooting
+ jne 2b
diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
index ba6f99f584ac3..a7ed30d5647af 100644
--- a/arch/x86/kvm/vmx/evmcs.c
@@ -20456,7 +32817,7 @@ index 152ab0aa82cf6..b43976e4b9636 100644
#define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
-index eedcebf580041..a0193b11c381d 100644
+index eedcebf580041..1546a10ecb564 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -523,29 +523,6 @@ static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu,
@@ -20729,7 +33090,19 @@ index eedcebf580041..a0193b11c381d 100644
/*
* VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between
-@@ -6750,6 +6748,7 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *))
+@@ -4603,6 +4601,11 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
+ kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
+ }
+
++ if (vmx->nested.update_vmcs01_apicv_status) {
++ vmx->nested.update_vmcs01_apicv_status = false;
++ kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
++ }
++
+ if ((vm_exit_reason != -1) &&
+ (enable_shadow_vmcs || evmptr_is_valid(vmx->nested.hv_evmcs_vmptr)))
+ vmx->nested.need_vmcs12_to_shadow_sync = true;
+@@ -6750,6 +6753,7 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *))
}
struct kvm_x86_nested_ops vmx_nested_ops = {
@@ -20738,7 +33111,7 @@ index eedcebf580041..a0193b11c381d 100644
.hv_timer_pending = nested_vmx_preemption_timer_pending,
.triple_fault = nested_vmx_triple_fault,
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
-index 10cc4f65c4efd..6427d95de01cf 100644
+index 10cc4f65c4efd..e7275ce15a8b0 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -68,10 +68,11 @@ static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
@@ -20756,7 +33129,64 @@ index 10cc4f65c4efd..6427d95de01cf 100644
int i;
for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++)
-@@ -706,7 +707,7 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
+@@ -395,6 +396,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ struct kvm_pmc *pmc;
+ u32 msr = msr_info->index;
+ u64 data = msr_info->data;
++ u64 reserved_bits;
+
+ switch (msr) {
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+@@ -437,20 +439,20 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ !(msr & MSR_PMC_FULL_WIDTH_BIT))
+ data = (s64)(s32)data;
+ pmc->counter += data - pmc_read_counter(pmc);
+- if (pmc->perf_event && !pmc->is_paused)
+- perf_event_period(pmc->perf_event,
+- get_sample_period(pmc, data));
++ pmc_update_sample_period(pmc);
+ return 0;
+ } else if ((pmc = get_fixed_pmc(pmu, msr))) {
+ pmc->counter += data - pmc_read_counter(pmc);
+- if (pmc->perf_event && !pmc->is_paused)
+- perf_event_period(pmc->perf_event,
+- get_sample_period(pmc, data));
++ pmc_update_sample_period(pmc);
+ return 0;
+ } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
+ if (data == pmc->eventsel)
+ return 0;
+- if (!(data & pmu->reserved_bits)) {
++ reserved_bits = pmu->reserved_bits;
++ if ((pmc->idx == 2) &&
++ (pmu->raw_event_mask & HSW_IN_TX_CHECKPOINTED))
++ reserved_bits ^= HSW_IN_TX_CHECKPOINTED;
++ if (!(data & reserved_bits)) {
+ reprogram_gp_counter(pmc, data);
+ return 0;
+ }
+@@ -477,6 +479,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
++ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+@@ -523,8 +526,10 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ entry = kvm_find_cpuid_entry(vcpu, 7, 0);
+ if (entry &&
+ (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
+- (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM)))
+- pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED;
++ (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) {
++ pmu->reserved_bits ^= HSW_IN_TX;
++ pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
++ }
+
+ bitmap_set(pmu->all_valid_pmc_idx,
+ 0, pmu->nr_arch_gp_counters);
+@@ -706,7 +711,7 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
}
struct kvm_pmu_ops intel_pmu_ops = {
@@ -20904,8 +33334,64 @@ index 5f81ef092bd43..46fb83d6a286e 100644
return 0;
idx = srcu_read_lock(&kvm->irq_srcu);
+diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
+index 3a6461694fc25..435c187927c48 100644
+--- a/arch/x86/kvm/vmx/vmenter.S
++++ b/arch/x86/kvm/vmx/vmenter.S
+@@ -49,14 +49,14 @@ SYM_FUNC_START_LOCAL(vmx_vmenter)
+ je 2f
+
+ 1: vmresume
+- ret
++ RET
+
+ 2: vmlaunch
+- ret
++ RET
+
+ 3: cmpb $0, kvm_rebooting
+ je 4f
+- ret
++ RET
+ 4: ud2
+
+ _ASM_EXTABLE(1b, 3b)
+@@ -89,7 +89,7 @@ SYM_FUNC_START(vmx_vmexit)
+ pop %_ASM_AX
+ .Lvmexit_skip_rsb:
+ #endif
+- ret
++ RET
+ SYM_FUNC_END(vmx_vmexit)
+
+ /**
+@@ -228,7 +228,7 @@ SYM_FUNC_START(__vmx_vcpu_run)
+ pop %edi
+ #endif
+ pop %_ASM_BP
+- ret
++ RET
+
+ /* VM-Fail. Out-of-line to avoid a taken Jcc after VM-Exit. */
+ 2: mov $1, %eax
+@@ -293,7 +293,7 @@ SYM_FUNC_START(vmread_error_trampoline)
+ pop %_ASM_AX
+ pop %_ASM_BP
+
+- ret
++ RET
+ SYM_FUNC_END(vmread_error_trampoline)
+
+ SYM_FUNC_START(vmx_do_interrupt_nmi_irqoff)
+@@ -326,5 +326,5 @@ SYM_FUNC_START(vmx_do_interrupt_nmi_irqoff)
+ */
+ mov %_ASM_BP, %_ASM_SP
+ pop %_ASM_BP
+- ret
++ RET
+ SYM_FUNC_END(vmx_do_interrupt_nmi_irqoff)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
-index 7d595effb66f0..322485ab9271c 100644
+index 7d595effb66f0..16a660a0ed5f7 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -769,24 +769,13 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu)
@@ -21059,7 +33545,19 @@ index 7d595effb66f0..322485ab9271c 100644
kvm_vcpu_kick(vcpu);
return 0;
-@@ -4833,8 +4791,33 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
+@@ -4140,6 +4098,11 @@ static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
++ if (is_guest_mode(vcpu)) {
++ vmx->nested.update_vmcs01_apicv_status = true;
++ return;
++ }
++
+ pin_controls_set(vmx, vmx_pin_based_exec_ctrl(vmx));
+ if (cpu_has_secondary_exec_ctrls()) {
+ if (kvm_vcpu_apicv_active(vcpu))
+@@ -4833,8 +4796,33 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
dr6 = vmx_get_exit_qual(vcpu);
if (!(vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
@@ -21093,7 +33591,7 @@ index 7d595effb66f0..322485ab9271c 100644
kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
return 1;
-@@ -5907,18 +5890,14 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
+@@ -5907,18 +5895,14 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
vmx_flush_pml_buffer(vcpu);
/*
@@ -21116,7 +33614,7 @@ index 7d595effb66f0..322485ab9271c 100644
if (is_guest_mode(vcpu)) {
/*
* PML is never enabled when running L2, bail immediately if a
-@@ -5940,10 +5919,30 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
+@@ -5940,10 +5924,30 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
*/
nested_mark_vmcs12_pages_dirty(vcpu);
@@ -21147,7 +33645,7 @@ index 7d595effb66f0..322485ab9271c 100644
if (exit_reason.failed_vmentry) {
dump_vmcs(vcpu);
vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-@@ -6288,9 +6287,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
+@@ -6288,9 +6292,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
int max_irr;
@@ -21159,7 +33657,7 @@ index 7d595effb66f0..322485ab9271c 100644
return -EIO;
if (pi_test_on(&vmx->pi_desc)) {
-@@ -6300,22 +6299,33 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
+@@ -6300,22 +6304,33 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
* But on x86 this is just a compiler barrier anyway.
*/
smp_mb__after_atomic();
@@ -21205,7 +33703,7 @@ index 7d595effb66f0..322485ab9271c 100644
return max_irr;
}
-@@ -6626,9 +6636,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
+@@ -6626,9 +6641,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
* consistency check VM-Exit due to invalid guest state and bail.
*/
if (unlikely(vmx->emulation_required)) {
@@ -21216,7 +33714,7 @@ index 7d595effb66f0..322485ab9271c 100644
vmx->exit_reason.full = EXIT_REASON_INVALID_STATE;
vmx->exit_reason.failed_vmentry = 1;
-@@ -6720,7 +6728,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
+@@ -6720,7 +6733,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
* If the L02 MSR bitmap does not intercept the MSR, then we need to
* save it.
*/
@@ -21225,7 +33723,7 @@ index 7d595effb66f0..322485ab9271c 100644
vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
-@@ -7524,6 +7532,7 @@ static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
+@@ -7524,6 +7537,7 @@ static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
if (ret)
return ret;
@@ -21233,7 +33731,7 @@ index 7d595effb66f0..322485ab9271c 100644
vmx->nested.smm.guest_mode = false;
}
return 0;
-@@ -7551,6 +7560,8 @@ static void vmx_migrate_timers(struct kvm_vcpu *vcpu)
+@@ -7551,6 +7565,8 @@ static void vmx_migrate_timers(struct kvm_vcpu *vcpu)
static void hardware_unsetup(void)
{
@@ -21242,7 +33740,7 @@ index 7d595effb66f0..322485ab9271c 100644
if (nested)
nested_vmx_hardware_unsetup();
-@@ -7606,6 +7617,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
+@@ -7606,6 +7622,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
.cache_reg = vmx_cache_reg,
.get_rflags = vmx_get_rflags,
.set_rflags = vmx_set_rflags,
@@ -21250,7 +33748,7 @@ index 7d595effb66f0..322485ab9271c 100644
.tlb_flush_all = vmx_flush_tlb_all,
.tlb_flush_current = vmx_flush_tlb_current,
-@@ -7809,10 +7821,10 @@ static __init int hardware_setup(void)
+@@ -7809,10 +7826,10 @@ static __init int hardware_setup(void)
ple_window_shrink = 0;
}
@@ -21263,7 +33761,7 @@ index 7d595effb66f0..322485ab9271c 100644
if (cpu_has_vmx_tsc_scaling()) {
kvm_has_tsc_control = true;
-@@ -7879,8 +7891,6 @@ static __init int hardware_setup(void)
+@@ -7879,8 +7896,6 @@ static __init int hardware_setup(void)
vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit;
}
@@ -21272,7 +33770,7 @@ index 7d595effb66f0..322485ab9271c 100644
kvm_mce_cap_supported |= MCG_LMCE_P;
if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST)
-@@ -7904,6 +7914,9 @@ static __init int hardware_setup(void)
+@@ -7904,6 +7919,9 @@ static __init int hardware_setup(void)
r = alloc_kvm_area();
if (r)
nested_vmx_hardware_unsetup();
@@ -21282,7 +33780,7 @@ index 7d595effb66f0..322485ab9271c 100644
return r;
}
-@@ -7912,6 +7925,7 @@ static struct kvm_x86_init_ops vmx_init_ops __initdata = {
+@@ -7912,6 +7930,7 @@ static struct kvm_x86_init_ops vmx_init_ops __initdata = {
.disabled_by_bios = vmx_disabled_by_bios,
.check_processor_compatibility = vmx_check_processor_compat,
.hardware_setup = hardware_setup,
@@ -21291,10 +33789,18 @@ index 7d595effb66f0..322485ab9271c 100644
.runtime_ops = &vmx_x86_ops,
};
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
-index 592217fd7d920..3f9c8548625d6 100644
+index 592217fd7d920..460c7bd8158cc 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
-@@ -400,6 +400,69 @@ static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr,
+@@ -164,6 +164,7 @@ struct nested_vmx {
+ bool change_vmcs01_virtual_apic_mode;
+ bool reload_vmcs01_apic_access_page;
+ bool update_vmcs01_cpu_dirty_logging;
++ bool update_vmcs01_apicv_status;
+
+ /*
+ * Enlightened VMCS has been enabled. It does not mean that L1 has to
+@@ -400,6 +401,69 @@ static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr,
void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu);
@@ -21365,7 +33871,7 @@ index 592217fd7d920..3f9c8548625d6 100644
{
return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index bfe0de3008a60..8213f7fb71a7b 100644
+index bfe0de3008a60..75da9c0d5ae37 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -848,6 +848,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3)
@@ -21404,7 +33910,17 @@ index bfe0de3008a60..8213f7fb71a7b 100644
MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS,
MSR_CORE_PERF_GLOBAL_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL,
MSR_ARCH_PERFMON_PERFCTR0, MSR_ARCH_PERFMON_PERFCTR1,
-@@ -3193,10 +3206,36 @@ static void kvm_vcpu_flush_tlb_guest(struct kvm_vcpu *vcpu)
+@@ -1592,8 +1605,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ return r;
+ }
+
+- /* Update reserved bits */
+- if ((efer ^ old_efer) & EFER_NX)
++ if ((efer ^ old_efer) & KVM_MMU_EFER_ROLE_BITS)
+ kvm_mmu_reset_context(vcpu);
+
+ return 0;
+@@ -3193,10 +3205,36 @@ static void kvm_vcpu_flush_tlb_guest(struct kvm_vcpu *vcpu)
static_call(kvm_x86_tlb_flush_guest)(vcpu);
}
@@ -21443,7 +33959,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (kvm_xen_msr_enabled(vcpu->kvm)) {
kvm_xen_runstate_set_running(vcpu);
-@@ -3206,47 +3245,86 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
+@@ -3206,47 +3244,86 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
return;
@@ -21460,7 +33976,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
+ if (unlikely(slots->generation != ghc->generation ||
+ kvm_is_error_hva(ghc->hva) || !ghc->memslot)) {
+ gfn_t gfn = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS;
-
++
+ /* We rely on the fact that it fits in a single page. */
+ BUILD_BUG_ON((sizeof(*st) - 1) & KVM_STEAL_VALID_BITS);
+
@@ -21468,7 +33984,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
+ kvm_is_error_hva(ghc->hva) || !ghc->memslot)
+ return;
+ }
-+
+
+ st = (struct kvm_steal_time __user *)ghc->hva;
/*
* Doing a TLB flush here, on the guest's behalf, can avoid
@@ -21547,7 +34063,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
}
int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-@@ -3282,7 +3360,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+@@ -3282,7 +3359,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!msr_info->host_initiated)
return 1;
@@ -21556,7 +34072,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
return 1;
if (data & ~msr_ent.data)
return 1;
-@@ -3376,6 +3454,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+@@ -3376,6 +3453,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (data & ~supported_xss)
return 1;
vcpu->arch.ia32_xss = data;
@@ -21564,7 +34080,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
break;
case MSR_SMI_COUNT:
if (!msr_info->host_initiated)
-@@ -4285,8 +4364,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+@@ -4285,8 +4363,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
{
@@ -21577,7 +34093,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
return;
-@@ -4294,16 +4375,23 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
+@@ -4294,16 +4374,23 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
if (vcpu->arch.st.preempted)
return;
@@ -21585,29 +34101,29 @@ index bfe0de3008a60..8213f7fb71a7b 100644
- &vcpu->arch.st.cache, true))
+ /* This happens on process exit */
+ if (unlikely(current->mm != vcpu->kvm->mm))
-+ return;
-+
+ return;
+
+- st = map.hva +
+- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
+ slots = kvm_memslots(vcpu->kvm);
+
+ if (unlikely(slots->generation != ghc->generation ||
+ kvm_is_error_hva(ghc->hva) || !ghc->memslot))
- return;
++ return;
-- st = map.hva +
-- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
+- st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED;
+ st = (struct kvm_steal_time __user *)ghc->hva;
+ BUILD_BUG_ON(sizeof(st->preempted) != sizeof(preempted));
-- st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED;
+- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true);
+ if (!copy_to_user_nofault(&st->preempted, &preempted, sizeof(preempted)))
+ vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED;
-
-- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true);
++
+ mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa));
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
-@@ -4331,8 +4419,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+@@ -4331,8 +4418,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
struct kvm_lapic_state *s)
{
@@ -21617,7 +34133,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
return kvm_apic_get_state(vcpu, s);
}
-@@ -4642,8 +4729,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
+@@ -4642,8 +4728,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
vcpu->arch.apic->sipi_vector = events->sipi_vector;
if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
@@ -21629,7 +34145,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
vcpu->arch.smi_pending = events->smi.pending;
-@@ -6948,7 +7037,13 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
+@@ -6948,7 +7036,13 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
unsigned short port, void *val, unsigned int count)
{
if (vcpu->arch.pio.count) {
@@ -21644,7 +34160,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
} else {
int r = __emulator_pio_in(vcpu, size, port, count);
if (!r)
-@@ -6957,7 +7052,6 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
+@@ -6957,7 +7051,6 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
/* Results already available, fall through. */
}
@@ -21652,7 +34168,27 @@ index bfe0de3008a60..8213f7fb71a7b 100644
complete_emulator_pio_in(vcpu, val);
return 1;
}
-@@ -7905,7 +7999,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+@@ -7300,6 +7393,11 @@ static bool emulator_guest_has_fxsr(struct x86_emulate_ctxt *ctxt)
+ return guest_cpuid_has(emul_to_vcpu(ctxt), X86_FEATURE_FXSR);
+ }
+
++static bool emulator_guest_has_rdpid(struct x86_emulate_ctxt *ctxt)
++{
++ return guest_cpuid_has(emul_to_vcpu(ctxt), X86_FEATURE_RDPID);
++}
++
+ static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg)
+ {
+ return kvm_register_read_raw(emul_to_vcpu(ctxt), reg);
+@@ -7382,6 +7480,7 @@ static const struct x86_emulate_ops emulate_ops = {
+ .guest_has_long_mode = emulator_guest_has_long_mode,
+ .guest_has_movbe = emulator_guest_has_movbe,
+ .guest_has_fxsr = emulator_guest_has_fxsr,
++ .guest_has_rdpid = emulator_guest_has_rdpid,
+ .set_nmi_mask = emulator_set_nmi_mask,
+ .get_hflags = emulator_get_hflags,
+ .exiting_smm = emulator_exiting_smm,
+@@ -7905,7 +8004,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
* updating interruptibility state and injecting single-step #DBs.
*/
if (emulation_type & EMULTYPE_SKIP) {
@@ -21666,7 +34202,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (ctxt->eflags & X86_EFLAGS_RF)
kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
return 1;
-@@ -7969,6 +8068,9 @@ restart:
+@@ -7969,6 +8073,9 @@ restart:
writeback = false;
r = 0;
vcpu->arch.complete_userspace_io = complete_emulated_mmio;
@@ -21676,7 +34212,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
} else if (r == EMULATION_RESTART)
goto restart;
else
-@@ -8340,7 +8442,7 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {
+@@ -8340,7 +8447,7 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {
.is_in_guest = kvm_is_in_guest,
.is_user_mode = kvm_is_user_mode,
.get_guest_ip = kvm_get_guest_ip,
@@ -21685,7 +34221,14 @@ index bfe0de3008a60..8213f7fb71a7b 100644
};
#ifdef CONFIG_X86_64
-@@ -8461,8 +8563,6 @@ int kvm_arch_init(void *opaque)
+@@ -8455,14 +8562,12 @@ int kvm_arch_init(void *opaque)
+ }
+ kvm_nr_uret_msrs = 0;
+
+- r = kvm_mmu_module_init();
++ r = kvm_mmu_vendor_module_init();
+ if (r)
+ goto out_free_percpu;
kvm_timer_init();
@@ -21694,7 +34237,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (boot_cpu_has(X86_FEATURE_XSAVE)) {
host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
-@@ -8496,7 +8596,6 @@ void kvm_arch_exit(void)
+@@ -8496,7 +8601,6 @@ void kvm_arch_exit(void)
clear_hv_tscchange_cb();
#endif
kvm_lapic_exit();
@@ -21702,7 +34245,30 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block,
-@@ -8686,7 +8785,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
+@@ -8508,7 +8612,7 @@ void kvm_arch_exit(void)
+ cancel_work_sync(&pvclock_gtod_work);
+ #endif
+ kvm_x86_ops.hardware_enable = NULL;
+- kvm_mmu_module_exit();
++ kvm_mmu_vendor_module_exit();
+ free_percpu(user_return_msrs);
+ kmem_cache_destroy(x86_emulator_cache);
+ kmem_cache_destroy(x86_fpu_cache);
+@@ -8567,6 +8671,13 @@ static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
+ if (clock_type != KVM_CLOCK_PAIRING_WALLCLOCK)
+ return -KVM_EOPNOTSUPP;
+
++ /*
++ * When tsc is in permanent catchup mode guests won't be able to use
++ * pvclock_read_retry loop to get consistent view of pvclock
++ */
++ if (vcpu->arch.tsc_always_catchup)
++ return -KVM_EOPNOTSUPP;
++
+ if (!kvm_get_walltime_and_clockread(&ts, &cycle))
+ return -KVM_EOPNOTSUPP;
+
+@@ -8686,7 +8797,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
trace_kvm_hypercall(nr, a0, a1, a2, a3);
@@ -21711,7 +34277,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (!op_64_bit) {
nr &= 0xFFFFFFFF;
a0 &= 0xFFFFFFFF;
-@@ -8790,14 +8889,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
+@@ -8790,14 +8901,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
{
struct kvm_run *kvm_run = vcpu->run;
@@ -21727,7 +34293,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
kvm_run->cr8 = kvm_get_cr8(vcpu);
kvm_run->apic_base = kvm_get_apic_base(vcpu);
-@@ -9359,8 +9451,7 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
+@@ -9359,8 +9463,7 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
if (irqchip_split(vcpu->kvm))
kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors);
else {
@@ -21737,7 +34303,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (ioapic_in_kernel(vcpu->kvm))
kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors);
}
-@@ -9378,12 +9469,16 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu)
+@@ -9378,12 +9481,16 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu)
if (!kvm_apic_hw_enabled(vcpu->arch.apic))
return;
@@ -21756,7 +34322,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
}
void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-@@ -9475,10 +9570,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
+@@ -9475,10 +9582,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
/* Flushing all ASIDs flushes the current ASID... */
kvm_clear_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
}
@@ -21768,7 +34334,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) {
vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS;
-@@ -9629,10 +9721,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
+@@ -9629,10 +9733,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
/*
* This handles the case where a posted interrupt was
@@ -21784,7 +34350,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (kvm_vcpu_exit_request(vcpu)) {
vcpu->mode = OUTSIDE_GUEST_MODE;
-@@ -9668,8 +9762,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
+@@ -9668,8 +9774,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST))
break;
@@ -21795,7 +34361,30 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (unlikely(kvm_vcpu_exit_request(vcpu))) {
exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED;
-@@ -10817,11 +10911,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+@@ -10707,8 +10813,21 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+ r = kvm_create_lapic(vcpu, lapic_timer_advance_ns);
+ if (r < 0)
+ goto fail_mmu_destroy;
+- if (kvm_apicv_activated(vcpu->kvm))
++
++ /*
++ * Defer evaluating inhibits until the vCPU is first run, as
++ * this vCPU will not get notified of any changes until this
++ * vCPU is visible to other vCPUs (marked online and added to
++ * the set of vCPUs). Opportunistically mark APICv active as
++ * VMX in particularly is highly unlikely to have inhibits.
++ * Ignore the current per-VM APICv state so that vCPU creation
++ * is guaranteed to run with a deterministic value, the request
++ * will ensure the vCPU gets the correct state before VM-Entry.
++ */
++ if (enable_apicv) {
+ vcpu->arch.apicv_active = true;
++ kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
++ }
+ } else
+ static_branch_inc(&kvm_has_noapic_vcpu);
+
+@@ -10817,11 +10936,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
@@ -21807,7 +34396,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
kvmclock_reset(vcpu);
static_call(kvm_x86_vcpu_free)(vcpu);
-@@ -10908,7 +10999,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
+@@ -10908,7 +11024,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vcpu->arch.msr_misc_features_enables = 0;
@@ -21817,7 +34406,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
}
memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs));
-@@ -10927,8 +11019,6 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
+@@ -10927,8 +11044,6 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
eax = 0x600;
kvm_rdx_write(vcpu, eax);
@@ -21826,7 +34415,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
static_call(kvm_x86_vcpu_reset)(vcpu, init_event);
kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
-@@ -11104,6 +11194,10 @@ int kvm_arch_hardware_setup(void *opaque)
+@@ -11104,6 +11219,10 @@ int kvm_arch_hardware_setup(void *opaque)
memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
kvm_ops_static_call_update();
@@ -21837,7 +34426,7 @@ index bfe0de3008a60..8213f7fb71a7b 100644
if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
supported_xss = 0;
-@@ -11131,6 +11225,9 @@ int kvm_arch_hardware_setup(void *opaque)
+@@ -11131,6 +11250,9 @@ int kvm_arch_hardware_setup(void *opaque)
void kvm_arch_hardware_unsetup(void)
{
@@ -21847,6 +34436,26 @@ index bfe0de3008a60..8213f7fb71a7b 100644
static_call(kvm_x86_hardware_unsetup)();
}
+@@ -12509,3 +12631,19 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_enter);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_exit);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_enter);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_exit);
++
++static int __init kvm_x86_init(void)
++{
++ kvm_mmu_x86_module_init();
++ return 0;
++}
++module_init(kvm_x86_init);
++
++static void __exit kvm_x86_exit(void)
++{
++ /*
++ * If module_init() is implemented, module_exit() must also be
++ * implemented to allow module unload.
++ */
++}
++module_exit(kvm_x86_exit);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 7d66d63dc55a6..bc7ef6820ac8f 100644
--- a/arch/x86/kvm/x86.h
@@ -22088,6 +34697,685 @@ index 8f62baebd0286..ab9f88de6deb9 100644
if (!longmode) {
params[0] = (u32)kvm_rbx_read(vcpu);
params[1] = (u32)kvm_rcx_read(vcpu);
+diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S
+index 16bc9130e7a5e..e768815e58ae4 100644
+--- a/arch/x86/lib/atomic64_386_32.S
++++ b/arch/x86/lib/atomic64_386_32.S
+@@ -9,81 +9,83 @@
+ #include <asm/alternative.h>
+
+ /* if you want SMP support, implement these with real spinlocks */
+-.macro LOCK reg
++.macro IRQ_SAVE reg
+ pushfl
+ cli
+ .endm
+
+-.macro UNLOCK reg
++.macro IRQ_RESTORE reg
+ popfl
+ .endm
+
+-#define BEGIN(op) \
++#define BEGIN_IRQ_SAVE(op) \
+ .macro endp; \
+ SYM_FUNC_END(atomic64_##op##_386); \
+ .purgem endp; \
+ .endm; \
+ SYM_FUNC_START(atomic64_##op##_386); \
+- LOCK v;
++ IRQ_SAVE v;
+
+ #define ENDP endp
+
+-#define RET \
+- UNLOCK v; \
+- ret
+-
+-#define RET_ENDP \
+- RET; \
+- ENDP
++#define RET_IRQ_RESTORE \
++ IRQ_RESTORE v; \
++ RET
+
+ #define v %ecx
+-BEGIN(read)
++BEGIN_IRQ_SAVE(read)
+ movl (v), %eax
+ movl 4(v), %edx
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(set)
++BEGIN_IRQ_SAVE(set)
+ movl %ebx, (v)
+ movl %ecx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(xchg)
++BEGIN_IRQ_SAVE(xchg)
+ movl (v), %eax
+ movl 4(v), %edx
+ movl %ebx, (v)
+ movl %ecx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %ecx
+-BEGIN(add)
++BEGIN_IRQ_SAVE(add)
+ addl %eax, (v)
+ adcl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %ecx
+-BEGIN(add_return)
++BEGIN_IRQ_SAVE(add_return)
+ addl (v), %eax
+ adcl 4(v), %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %ecx
+-BEGIN(sub)
++BEGIN_IRQ_SAVE(sub)
+ subl %eax, (v)
+ sbbl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %ecx
+-BEGIN(sub_return)
++BEGIN_IRQ_SAVE(sub_return)
+ negl %edx
+ negl %eax
+ sbbl $0, %edx
+@@ -91,47 +93,52 @@ BEGIN(sub_return)
+ adcl 4(v), %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(inc)
++BEGIN_IRQ_SAVE(inc)
+ addl $1, (v)
+ adcl $0, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(inc_return)
++BEGIN_IRQ_SAVE(inc_return)
+ movl (v), %eax
+ movl 4(v), %edx
+ addl $1, %eax
+ adcl $0, %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(dec)
++BEGIN_IRQ_SAVE(dec)
+ subl $1, (v)
+ sbbl $0, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(dec_return)
++BEGIN_IRQ_SAVE(dec_return)
+ movl (v), %eax
+ movl 4(v), %edx
+ subl $1, %eax
+ sbbl $0, %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(add_unless)
++BEGIN_IRQ_SAVE(add_unless)
+ addl %eax, %ecx
+ adcl %edx, %edi
+ addl (v), %eax
+@@ -143,7 +150,7 @@ BEGIN(add_unless)
+ movl %edx, 4(v)
+ movl $1, %eax
+ 2:
+- RET
++ RET_IRQ_RESTORE
+ 3:
+ cmpl %edx, %edi
+ jne 1b
+@@ -153,7 +160,7 @@ ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(inc_not_zero)
++BEGIN_IRQ_SAVE(inc_not_zero)
+ movl (v), %eax
+ movl 4(v), %edx
+ testl %eax, %eax
+@@ -165,7 +172,7 @@ BEGIN(inc_not_zero)
+ movl %edx, 4(v)
+ movl $1, %eax
+ 2:
+- RET
++ RET_IRQ_RESTORE
+ 3:
+ testl %edx, %edx
+ jne 1b
+@@ -174,7 +181,7 @@ ENDP
+ #undef v
+
+ #define v %esi
+-BEGIN(dec_if_positive)
++BEGIN_IRQ_SAVE(dec_if_positive)
+ movl (v), %eax
+ movl 4(v), %edx
+ subl $1, %eax
+@@ -183,5 +190,6 @@ BEGIN(dec_if_positive)
+ movl %eax, (v)
+ movl %edx, 4(v)
+ 1:
+-RET_ENDP
++ RET_IRQ_RESTORE
++ENDP
+ #undef v
+diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S
+index ce6935690766f..90afb488b396a 100644
+--- a/arch/x86/lib/atomic64_cx8_32.S
++++ b/arch/x86/lib/atomic64_cx8_32.S
+@@ -18,7 +18,7 @@
+
+ SYM_FUNC_START(atomic64_read_cx8)
+ read64 %ecx
+- ret
++ RET
+ SYM_FUNC_END(atomic64_read_cx8)
+
+ SYM_FUNC_START(atomic64_set_cx8)
+@@ -28,7 +28,7 @@ SYM_FUNC_START(atomic64_set_cx8)
+ cmpxchg8b (%esi)
+ jne 1b
+
+- ret
++ RET
+ SYM_FUNC_END(atomic64_set_cx8)
+
+ SYM_FUNC_START(atomic64_xchg_cx8)
+@@ -37,7 +37,7 @@ SYM_FUNC_START(atomic64_xchg_cx8)
+ cmpxchg8b (%esi)
+ jne 1b
+
+- ret
++ RET
+ SYM_FUNC_END(atomic64_xchg_cx8)
+
+ .macro addsub_return func ins insc
+@@ -68,7 +68,7 @@ SYM_FUNC_START(atomic64_\func\()_return_cx8)
+ popl %esi
+ popl %ebx
+ popl %ebp
+- ret
++ RET
+ SYM_FUNC_END(atomic64_\func\()_return_cx8)
+ .endm
+
+@@ -93,7 +93,7 @@ SYM_FUNC_START(atomic64_\func\()_return_cx8)
+ movl %ebx, %eax
+ movl %ecx, %edx
+ popl %ebx
+- ret
++ RET
+ SYM_FUNC_END(atomic64_\func\()_return_cx8)
+ .endm
+
+@@ -118,7 +118,7 @@ SYM_FUNC_START(atomic64_dec_if_positive_cx8)
+ movl %ebx, %eax
+ movl %ecx, %edx
+ popl %ebx
+- ret
++ RET
+ SYM_FUNC_END(atomic64_dec_if_positive_cx8)
+
+ SYM_FUNC_START(atomic64_add_unless_cx8)
+@@ -149,7 +149,7 @@ SYM_FUNC_START(atomic64_add_unless_cx8)
+ addl $8, %esp
+ popl %ebx
+ popl %ebp
+- ret
++ RET
+ 4:
+ cmpl %edx, 4(%esp)
+ jne 2b
+@@ -176,5 +176,5 @@ SYM_FUNC_START(atomic64_inc_not_zero_cx8)
+ movl $1, %eax
+ 3:
+ popl %ebx
+- ret
++ RET
+ SYM_FUNC_END(atomic64_inc_not_zero_cx8)
+diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S
+index 4304320e51f4d..929ad1747dea0 100644
+--- a/arch/x86/lib/checksum_32.S
++++ b/arch/x86/lib/checksum_32.S
+@@ -127,7 +127,7 @@ SYM_FUNC_START(csum_partial)
+ 8:
+ popl %ebx
+ popl %esi
+- ret
++ RET
+ SYM_FUNC_END(csum_partial)
+
+ #else
+@@ -245,7 +245,7 @@ SYM_FUNC_START(csum_partial)
+ 90:
+ popl %ebx
+ popl %esi
+- ret
++ RET
+ SYM_FUNC_END(csum_partial)
+
+ #endif
+@@ -371,7 +371,7 @@ EXC( movb %cl, (%edi) )
+ popl %esi
+ popl %edi
+ popl %ecx # equivalent to addl $4,%esp
+- ret
++ RET
+ SYM_FUNC_END(csum_partial_copy_generic)
+
+ #else
+@@ -447,7 +447,7 @@ EXC( movb %dl, (%edi) )
+ popl %esi
+ popl %edi
+ popl %ebx
+- ret
++ RET
+ SYM_FUNC_END(csum_partial_copy_generic)
+
+ #undef ROUND
+diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S
+index c4c7dd115953c..fe59b8ac4fccd 100644
+--- a/arch/x86/lib/clear_page_64.S
++++ b/arch/x86/lib/clear_page_64.S
+@@ -17,7 +17,7 @@ SYM_FUNC_START(clear_page_rep)
+ movl $4096/8,%ecx
+ xorl %eax,%eax
+ rep stosq
+- ret
++ RET
+ SYM_FUNC_END(clear_page_rep)
+ EXPORT_SYMBOL_GPL(clear_page_rep)
+
+@@ -39,7 +39,7 @@ SYM_FUNC_START(clear_page_orig)
+ leaq 64(%rdi),%rdi
+ jnz .Lloop
+ nop
+- ret
++ RET
+ SYM_FUNC_END(clear_page_orig)
+ EXPORT_SYMBOL_GPL(clear_page_orig)
+
+@@ -47,6 +47,6 @@ SYM_FUNC_START(clear_page_erms)
+ movl $4096,%ecx
+ xorl %eax,%eax
+ rep stosb
+- ret
++ RET
+ SYM_FUNC_END(clear_page_erms)
+ EXPORT_SYMBOL_GPL(clear_page_erms)
+diff --git a/arch/x86/lib/cmpxchg16b_emu.S b/arch/x86/lib/cmpxchg16b_emu.S
+index 3542502faa3b7..33c70c0160ea0 100644
+--- a/arch/x86/lib/cmpxchg16b_emu.S
++++ b/arch/x86/lib/cmpxchg16b_emu.S
+@@ -37,11 +37,11 @@ SYM_FUNC_START(this_cpu_cmpxchg16b_emu)
+
+ popfq
+ mov $1, %al
+- ret
++ RET
+
+ .Lnot_same:
+ popfq
+ xor %al,%al
+- ret
++ RET
+
+ SYM_FUNC_END(this_cpu_cmpxchg16b_emu)
+diff --git a/arch/x86/lib/cmpxchg8b_emu.S b/arch/x86/lib/cmpxchg8b_emu.S
+index ca01ed6029f4f..6a912d58fecc3 100644
+--- a/arch/x86/lib/cmpxchg8b_emu.S
++++ b/arch/x86/lib/cmpxchg8b_emu.S
+@@ -32,7 +32,7 @@ SYM_FUNC_START(cmpxchg8b_emu)
+ movl %ecx, 4(%esi)
+
+ popfl
+- ret
++ RET
+
+ .Lnot_same:
+ movl (%esi), %eax
+@@ -40,7 +40,7 @@ SYM_FUNC_START(cmpxchg8b_emu)
+ movl 4(%esi), %edx
+
+ popfl
+- ret
++ RET
+
+ SYM_FUNC_END(cmpxchg8b_emu)
+ EXPORT_SYMBOL(cmpxchg8b_emu)
+diff --git a/arch/x86/lib/copy_mc_64.S b/arch/x86/lib/copy_mc_64.S
+index e5f77e2930349..2c623a2bbd26e 100644
+--- a/arch/x86/lib/copy_mc_64.S
++++ b/arch/x86/lib/copy_mc_64.S
+@@ -77,7 +77,7 @@ SYM_FUNC_START(copy_mc_fragile)
+ .L_done_memcpy_trap:
+ xorl %eax, %eax
+ .L_done:
+- ret
++ RET
+ SYM_FUNC_END(copy_mc_fragile)
+
+ .section .fixup, "ax"
+@@ -132,7 +132,7 @@ SYM_FUNC_START(copy_mc_enhanced_fast_string)
+ rep movsb
+ /* Copy successful. Return zero */
+ xorl %eax, %eax
+- ret
++ RET
+ SYM_FUNC_END(copy_mc_enhanced_fast_string)
+
+ .section .fixup, "ax"
+@@ -145,7 +145,7 @@ SYM_FUNC_END(copy_mc_enhanced_fast_string)
+ * user-copy routines.
+ */
+ movq %rcx, %rax
+- ret
++ RET
+
+ .previous
+
+diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
+index db4b4f9197c7d..30ea644bf446d 100644
+--- a/arch/x86/lib/copy_page_64.S
++++ b/arch/x86/lib/copy_page_64.S
+@@ -17,7 +17,7 @@ SYM_FUNC_START(copy_page)
+ ALTERNATIVE "jmp copy_page_regs", "", X86_FEATURE_REP_GOOD
+ movl $4096/8, %ecx
+ rep movsq
+- ret
++ RET
+ SYM_FUNC_END(copy_page)
+ EXPORT_SYMBOL(copy_page)
+
+@@ -85,5 +85,5 @@ SYM_FUNC_START_LOCAL(copy_page_regs)
+ movq (%rsp), %rbx
+ movq 1*8(%rsp), %r12
+ addq $2*8, %rsp
+- ret
++ RET
+ SYM_FUNC_END(copy_page_regs)
+diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
+index 57b79c577496d..84cee84fc658a 100644
+--- a/arch/x86/lib/copy_user_64.S
++++ b/arch/x86/lib/copy_user_64.S
+@@ -105,7 +105,7 @@ SYM_FUNC_START(copy_user_generic_unrolled)
+ jnz 21b
+ 23: xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+
+ .section .fixup,"ax"
+ 30: shll $6,%ecx
+@@ -173,7 +173,7 @@ SYM_FUNC_START(copy_user_generic_string)
+ movsb
+ xorl %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+
+ .section .fixup,"ax"
+ 11: leal (%rdx,%rcx,8),%ecx
+@@ -207,7 +207,7 @@ SYM_FUNC_START(copy_user_enhanced_fast_string)
+ movsb
+ xorl %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+
+ .section .fixup,"ax"
+ 12: movl %ecx,%edx /* ecx is zerorest also */
+@@ -239,7 +239,7 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_tail)
+ 1: rep movsb
+ 2: mov %ecx,%eax
+ ASM_CLAC
+- ret
++ RET
+
+ /*
+ * Return zero to pretend that this copy succeeded. This
+@@ -250,7 +250,7 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_tail)
+ */
+ 3: xorl %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+
+ _ASM_EXTABLE_CPY(1b, 2b)
+ SYM_CODE_END(.Lcopy_user_handle_tail)
+@@ -361,7 +361,7 @@ SYM_FUNC_START(__copy_user_nocache)
+ xorl %eax,%eax
+ ASM_CLAC
+ sfence
+- ret
++ RET
+
+ .section .fixup,"ax"
+ .L_fixup_4x8b_copy:
+diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S
+index 1fbd8ee9642d1..d9e16a2cf2856 100644
+--- a/arch/x86/lib/csum-copy_64.S
++++ b/arch/x86/lib/csum-copy_64.S
+@@ -201,7 +201,7 @@ SYM_FUNC_START(csum_partial_copy_generic)
+ movq 3*8(%rsp), %r13
+ movq 4*8(%rsp), %r15
+ addq $5*8, %rsp
+- ret
++ RET
+ .Lshort:
+ movl %ecx, %r10d
+ jmp .L1
+diff --git a/arch/x86/lib/error-inject.c b/arch/x86/lib/error-inject.c
+index be5b5fb1598bd..520897061ee09 100644
+--- a/arch/x86/lib/error-inject.c
++++ b/arch/x86/lib/error-inject.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+
++#include <linux/linkage.h>
+ #include <linux/error-injection.h>
+ #include <linux/kprobes.h>
+
+@@ -10,7 +11,7 @@ asm(
+ ".type just_return_func, @function\n"
+ ".globl just_return_func\n"
+ "just_return_func:\n"
+- " ret\n"
++ ASM_RET
+ ".size just_return_func, .-just_return_func\n"
+ );
+
+diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
+index fa1bc2104b326..b70d98d79a9da 100644
+--- a/arch/x86/lib/getuser.S
++++ b/arch/x86/lib/getuser.S
+@@ -57,7 +57,7 @@ SYM_FUNC_START(__get_user_1)
+ 1: movzbl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_1)
+ EXPORT_SYMBOL(__get_user_1)
+
+@@ -71,7 +71,7 @@ SYM_FUNC_START(__get_user_2)
+ 2: movzwl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_2)
+ EXPORT_SYMBOL(__get_user_2)
+
+@@ -85,7 +85,7 @@ SYM_FUNC_START(__get_user_4)
+ 3: movl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_4)
+ EXPORT_SYMBOL(__get_user_4)
+
+@@ -100,7 +100,7 @@ SYM_FUNC_START(__get_user_8)
+ 4: movq (%_ASM_AX),%rdx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ #else
+ LOAD_TASK_SIZE_MINUS_N(7)
+ cmp %_ASM_DX,%_ASM_AX
+@@ -112,7 +112,7 @@ SYM_FUNC_START(__get_user_8)
+ 5: movl 4(%_ASM_AX),%ecx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ #endif
+ SYM_FUNC_END(__get_user_8)
+ EXPORT_SYMBOL(__get_user_8)
+@@ -124,7 +124,7 @@ SYM_FUNC_START(__get_user_nocheck_1)
+ 6: movzbl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_nocheck_1)
+ EXPORT_SYMBOL(__get_user_nocheck_1)
+
+@@ -134,7 +134,7 @@ SYM_FUNC_START(__get_user_nocheck_2)
+ 7: movzwl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_nocheck_2)
+ EXPORT_SYMBOL(__get_user_nocheck_2)
+
+@@ -144,7 +144,7 @@ SYM_FUNC_START(__get_user_nocheck_4)
+ 8: movl (%_ASM_AX),%edx
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_nocheck_4)
+ EXPORT_SYMBOL(__get_user_nocheck_4)
+
+@@ -159,7 +159,7 @@ SYM_FUNC_START(__get_user_nocheck_8)
+ #endif
+ xor %eax,%eax
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__get_user_nocheck_8)
+ EXPORT_SYMBOL(__get_user_nocheck_8)
+
+@@ -169,7 +169,7 @@ SYM_CODE_START_LOCAL(.Lbad_get_user_clac)
+ bad_get_user:
+ xor %edx,%edx
+ mov $(-EFAULT),%_ASM_AX
+- ret
++ RET
+ SYM_CODE_END(.Lbad_get_user_clac)
+
+ #ifdef CONFIG_X86_32
+@@ -179,7 +179,7 @@ bad_get_user_8:
+ xor %edx,%edx
+ xor %ecx,%ecx
+ mov $(-EFAULT),%_ASM_AX
+- ret
++ RET
+ SYM_CODE_END(.Lbad_get_user_8_clac)
+ #endif
+
+diff --git a/arch/x86/lib/hweight.S b/arch/x86/lib/hweight.S
+index dbf8cc97b7f53..12c16c6aa44a3 100644
+--- a/arch/x86/lib/hweight.S
++++ b/arch/x86/lib/hweight.S
+@@ -32,7 +32,7 @@ SYM_FUNC_START(__sw_hweight32)
+ imull $0x01010101, %eax, %eax # w_tmp *= 0x01010101
+ shrl $24, %eax # w = w_tmp >> 24
+ __ASM_SIZE(pop,) %__ASM_REG(dx)
+- ret
++ RET
+ SYM_FUNC_END(__sw_hweight32)
+ EXPORT_SYMBOL(__sw_hweight32)
+
+@@ -65,7 +65,7 @@ SYM_FUNC_START(__sw_hweight64)
+
+ popq %rdx
+ popq %rdi
+- ret
++ RET
+ #else /* CONFIG_X86_32 */
+ /* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */
+ pushl %ecx
+@@ -77,7 +77,7 @@ SYM_FUNC_START(__sw_hweight64)
+ addl %ecx, %eax # result
+
+ popl %ecx
+- ret
++ RET
+ #endif
+ SYM_FUNC_END(__sw_hweight64)
+ EXPORT_SYMBOL(__sw_hweight64)
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index a1d24fdc07cf0..eb3ccffb9b9dc 100644
--- a/arch/x86/lib/insn-eval.c
@@ -22126,19 +35414,503 @@ index c565def611e24..55e371cc69fd5 100644
#define get_next(t, insn) \
({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
+diff --git a/arch/x86/lib/iomap_copy_64.S b/arch/x86/lib/iomap_copy_64.S
+index cb5a1964506b1..a1f9416bf67a5 100644
+--- a/arch/x86/lib/iomap_copy_64.S
++++ b/arch/x86/lib/iomap_copy_64.S
+@@ -11,5 +11,5 @@
+ SYM_FUNC_START(__iowrite32_copy)
+ movl %edx,%ecx
+ rep movsd
+- ret
++ RET
+ SYM_FUNC_END(__iowrite32_copy)
+diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
+index 1cc9da6e29c79..59cf2343f3d90 100644
+--- a/arch/x86/lib/memcpy_64.S
++++ b/arch/x86/lib/memcpy_64.S
+@@ -39,7 +39,7 @@ SYM_FUNC_START_WEAK(memcpy)
+ rep movsq
+ movl %edx, %ecx
+ rep movsb
+- ret
++ RET
+ SYM_FUNC_END(memcpy)
+ SYM_FUNC_END_ALIAS(__memcpy)
+ EXPORT_SYMBOL(memcpy)
+@@ -53,7 +53,7 @@ SYM_FUNC_START_LOCAL(memcpy_erms)
+ movq %rdi, %rax
+ movq %rdx, %rcx
+ rep movsb
+- ret
++ RET
+ SYM_FUNC_END(memcpy_erms)
+
+ SYM_FUNC_START_LOCAL(memcpy_orig)
+@@ -137,7 +137,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movq %r9, 1*8(%rdi)
+ movq %r10, -2*8(%rdi, %rdx)
+ movq %r11, -1*8(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_16bytes:
+ cmpl $8, %edx
+@@ -149,7 +149,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movq -1*8(%rsi, %rdx), %r9
+ movq %r8, 0*8(%rdi)
+ movq %r9, -1*8(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_8bytes:
+ cmpl $4, %edx
+@@ -162,7 +162,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movl -4(%rsi, %rdx), %r8d
+ movl %ecx, (%rdi)
+ movl %r8d, -4(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_3bytes:
+ subl $1, %edx
+@@ -180,7 +180,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movb %cl, (%rdi)
+
+ .Lend:
+- retq
++ RET
+ SYM_FUNC_END(memcpy_orig)
+
+ .popsection
+diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
+index 64801010d312d..50ea390df7128 100644
+--- a/arch/x86/lib/memmove_64.S
++++ b/arch/x86/lib/memmove_64.S
+@@ -40,7 +40,7 @@ SYM_FUNC_START(__memmove)
+ /* FSRM implies ERMS => no length checks, do the copy directly */
+ .Lmemmove_begin_forward:
+ ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM
+- ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; retq", X86_FEATURE_ERMS
++ ALTERNATIVE "", __stringify(movq %rdx, %rcx; rep movsb; RET), X86_FEATURE_ERMS
+
+ /*
+ * movsq instruction have many startup latency
+@@ -205,7 +205,7 @@ SYM_FUNC_START(__memmove)
+ movb (%rsi), %r11b
+ movb %r11b, (%rdi)
+ 13:
+- retq
++ RET
+ SYM_FUNC_END(__memmove)
+ SYM_FUNC_END_ALIAS(memmove)
+ EXPORT_SYMBOL(__memmove)
+diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S
+index 9827ae267f96e..d624f2bc42f16 100644
+--- a/arch/x86/lib/memset_64.S
++++ b/arch/x86/lib/memset_64.S
+@@ -40,7 +40,7 @@ SYM_FUNC_START(__memset)
+ movl %edx,%ecx
+ rep stosb
+ movq %r9,%rax
+- ret
++ RET
+ SYM_FUNC_END(__memset)
+ SYM_FUNC_END_ALIAS(memset)
+ EXPORT_SYMBOL(memset)
+@@ -63,7 +63,7 @@ SYM_FUNC_START_LOCAL(memset_erms)
+ movq %rdx,%rcx
+ rep stosb
+ movq %r9,%rax
+- ret
++ RET
+ SYM_FUNC_END(memset_erms)
+
+ SYM_FUNC_START_LOCAL(memset_orig)
+@@ -125,7 +125,7 @@ SYM_FUNC_START_LOCAL(memset_orig)
+
+ .Lende:
+ movq %r10,%rax
+- ret
++ RET
+
+ .Lbad_alignment:
+ cmpq $7,%rdx
+diff --git a/arch/x86/lib/msr-reg.S b/arch/x86/lib/msr-reg.S
+index a2b9caa5274c8..ebd259f314963 100644
+--- a/arch/x86/lib/msr-reg.S
++++ b/arch/x86/lib/msr-reg.S
+@@ -35,7 +35,7 @@ SYM_FUNC_START(\op\()_safe_regs)
+ movl %edi, 28(%r10)
+ popq %r12
+ popq %rbx
+- ret
++ RET
+ 3:
+ movl $-EIO, %r11d
+ jmp 2b
+@@ -77,7 +77,7 @@ SYM_FUNC_START(\op\()_safe_regs)
+ popl %esi
+ popl %ebp
+ popl %ebx
+- ret
++ RET
+ 3:
+ movl $-EIO, 4(%esp)
+ jmp 2b
+diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
+index 0ea344c5ea439..ecb2049c1273f 100644
+--- a/arch/x86/lib/putuser.S
++++ b/arch/x86/lib/putuser.S
+@@ -52,7 +52,7 @@ SYM_INNER_LABEL(__put_user_nocheck_1, SYM_L_GLOBAL)
+ 1: movb %al,(%_ASM_CX)
+ xor %ecx,%ecx
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__put_user_1)
+ EXPORT_SYMBOL(__put_user_1)
+ EXPORT_SYMBOL(__put_user_nocheck_1)
+@@ -66,7 +66,7 @@ SYM_INNER_LABEL(__put_user_nocheck_2, SYM_L_GLOBAL)
+ 2: movw %ax,(%_ASM_CX)
+ xor %ecx,%ecx
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__put_user_2)
+ EXPORT_SYMBOL(__put_user_2)
+ EXPORT_SYMBOL(__put_user_nocheck_2)
+@@ -80,7 +80,7 @@ SYM_INNER_LABEL(__put_user_nocheck_4, SYM_L_GLOBAL)
+ 3: movl %eax,(%_ASM_CX)
+ xor %ecx,%ecx
+ ASM_CLAC
+- ret
++ RET
+ SYM_FUNC_END(__put_user_4)
+ EXPORT_SYMBOL(__put_user_4)
+ EXPORT_SYMBOL(__put_user_nocheck_4)
diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S
-index ec9922cba30a4..5385d26af6e45 100644
+index ec9922cba30a4..9556ff5f4773f 100644
--- a/arch/x86/lib/retpoline.S
+++ b/arch/x86/lib/retpoline.S
+@@ -23,7 +23,7 @@
+ .Ldo_rop_\@:
+ mov %\reg, (%_ASM_SP)
+ UNWIND_HINT_FUNC
+- ret
++ RET
+ .endm
+
+ .macro THUNK reg
@@ -34,7 +34,7 @@ SYM_FUNC_START(__x86_indirect_thunk_\reg)
ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \
__stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \
- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_AMD
-+ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE
++ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg; int3), X86_FEATURE_RETPOLINE_LFENCE
SYM_FUNC_END(__x86_indirect_thunk_\reg)
+diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
+index 508c81e97ab10..f1c0befb62df5 100644
+--- a/arch/x86/lib/usercopy_64.c
++++ b/arch/x86/lib/usercopy_64.c
+@@ -121,7 +121,7 @@ void __memcpy_flushcache(void *_dst, const void *_src, size_t size)
+
+ /* cache copy and flush to align dest */
+ if (!IS_ALIGNED(dest, 8)) {
+- unsigned len = min_t(unsigned, size, ALIGN(dest, 8) - dest);
++ size_t len = min_t(size_t, size, ALIGN(dest, 8) - dest);
+
+ memcpy((void *) dest, (void *) source, len);
+ clean_cache_range((void *) dest, len);
+diff --git a/arch/x86/math-emu/div_Xsig.S b/arch/x86/math-emu/div_Xsig.S
+index 951da2ad54bbf..8c270ab415bee 100644
+--- a/arch/x86/math-emu/div_Xsig.S
++++ b/arch/x86/math-emu/div_Xsig.S
+@@ -341,7 +341,7 @@ L_exit:
+ popl %esi
+
+ leave
+- ret
++ RET
+
+
+ #ifdef PARANOID
+diff --git a/arch/x86/math-emu/div_small.S b/arch/x86/math-emu/div_small.S
+index d047d1816abe9..637439bfefa47 100644
+--- a/arch/x86/math-emu/div_small.S
++++ b/arch/x86/math-emu/div_small.S
+@@ -44,5 +44,5 @@ SYM_FUNC_START(FPU_div_small)
+ popl %esi
+
+ leave
+- ret
++ RET
+ SYM_FUNC_END(FPU_div_small)
+diff --git a/arch/x86/math-emu/mul_Xsig.S b/arch/x86/math-emu/mul_Xsig.S
+index 4afc7b1fa6e95..54a031b661421 100644
+--- a/arch/x86/math-emu/mul_Xsig.S
++++ b/arch/x86/math-emu/mul_Xsig.S
+@@ -62,7 +62,7 @@ SYM_FUNC_START(mul32_Xsig)
+
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(mul32_Xsig)
+
+
+@@ -115,7 +115,7 @@ SYM_FUNC_START(mul64_Xsig)
+
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(mul64_Xsig)
+
+
+@@ -175,5 +175,5 @@ SYM_FUNC_START(mul_Xsig_Xsig)
+
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(mul_Xsig_Xsig)
+diff --git a/arch/x86/math-emu/polynom_Xsig.S b/arch/x86/math-emu/polynom_Xsig.S
+index 702315eecb860..35fd723fc0df8 100644
+--- a/arch/x86/math-emu/polynom_Xsig.S
++++ b/arch/x86/math-emu/polynom_Xsig.S
+@@ -133,5 +133,5 @@ L_accum_done:
+ popl %edi
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(polynomial_Xsig)
+diff --git a/arch/x86/math-emu/reg_norm.S b/arch/x86/math-emu/reg_norm.S
+index cad1d60b1e844..594936eeed67a 100644
+--- a/arch/x86/math-emu/reg_norm.S
++++ b/arch/x86/math-emu/reg_norm.S
+@@ -72,7 +72,7 @@ L_exit_valid:
+ L_exit:
+ popl %ebx
+ leave
+- ret
++ RET
+
+
+ L_zero:
+@@ -138,7 +138,7 @@ L_exit_nuo_valid:
+
+ popl %ebx
+ leave
+- ret
++ RET
+
+ L_exit_nuo_zero:
+ movl TAG_Zero,%eax
+@@ -146,5 +146,5 @@ L_exit_nuo_zero:
+
+ popl %ebx
+ leave
+- ret
++ RET
+ SYM_FUNC_END(FPU_normalize_nuo)
+diff --git a/arch/x86/math-emu/reg_round.S b/arch/x86/math-emu/reg_round.S
+index 4a9fc3cc5a4d4..0bb2a092161af 100644
+--- a/arch/x86/math-emu/reg_round.S
++++ b/arch/x86/math-emu/reg_round.S
+@@ -437,7 +437,7 @@ fpu_Arith_exit:
+ popl %edi
+ popl %esi
+ leave
+- ret
++ RET
+
+
+ /*
+diff --git a/arch/x86/math-emu/reg_u_add.S b/arch/x86/math-emu/reg_u_add.S
+index 9c9e2c810afe8..07247287a3af7 100644
+--- a/arch/x86/math-emu/reg_u_add.S
++++ b/arch/x86/math-emu/reg_u_add.S
+@@ -164,6 +164,6 @@ L_exit:
+ popl %edi
+ popl %esi
+ leave
+- ret
++ RET
+ #endif /* PARANOID */
+ SYM_FUNC_END(FPU_u_add)
+diff --git a/arch/x86/math-emu/reg_u_div.S b/arch/x86/math-emu/reg_u_div.S
+index e2fb5c2644c55..b5a41e2fc484c 100644
+--- a/arch/x86/math-emu/reg_u_div.S
++++ b/arch/x86/math-emu/reg_u_div.S
+@@ -468,7 +468,7 @@ L_exit:
+ popl %esi
+
+ leave
+- ret
++ RET
+ #endif /* PARANOID */
+
+ SYM_FUNC_END(FPU_u_div)
+diff --git a/arch/x86/math-emu/reg_u_mul.S b/arch/x86/math-emu/reg_u_mul.S
+index 0c779c87ac5b3..e2588b24b8c2c 100644
+--- a/arch/x86/math-emu/reg_u_mul.S
++++ b/arch/x86/math-emu/reg_u_mul.S
+@@ -144,7 +144,7 @@ L_exit:
+ popl %edi
+ popl %esi
+ leave
+- ret
++ RET
+ #endif /* PARANOID */
+
+ SYM_FUNC_END(FPU_u_mul)
+diff --git a/arch/x86/math-emu/reg_u_sub.S b/arch/x86/math-emu/reg_u_sub.S
+index e9bb7c248649f..4c900c29e4ff2 100644
+--- a/arch/x86/math-emu/reg_u_sub.S
++++ b/arch/x86/math-emu/reg_u_sub.S
+@@ -270,5 +270,5 @@ L_exit:
+ popl %edi
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(FPU_u_sub)
+diff --git a/arch/x86/math-emu/round_Xsig.S b/arch/x86/math-emu/round_Xsig.S
+index d9d7de8dbd7b6..126c40473badb 100644
+--- a/arch/x86/math-emu/round_Xsig.S
++++ b/arch/x86/math-emu/round_Xsig.S
+@@ -78,7 +78,7 @@ L_exit:
+ popl %esi
+ popl %ebx
+ leave
+- ret
++ RET
+ SYM_FUNC_END(round_Xsig)
+
+
+@@ -138,5 +138,5 @@ L_n_exit:
+ popl %esi
+ popl %ebx
+ leave
+- ret
++ RET
+ SYM_FUNC_END(norm_Xsig)
+diff --git a/arch/x86/math-emu/shr_Xsig.S b/arch/x86/math-emu/shr_Xsig.S
+index 726af985f7582..f726bf6f6396e 100644
+--- a/arch/x86/math-emu/shr_Xsig.S
++++ b/arch/x86/math-emu/shr_Xsig.S
+@@ -45,7 +45,7 @@ SYM_FUNC_START(shr_Xsig)
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_31:
+ cmpl $64,%ecx
+@@ -61,7 +61,7 @@ L_more_than_31:
+ movl $0,8(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_63:
+ cmpl $96,%ecx
+@@ -76,7 +76,7 @@ L_more_than_63:
+ movl %edx,8(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_95:
+ xorl %eax,%eax
+@@ -85,5 +85,5 @@ L_more_than_95:
+ movl %eax,8(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(shr_Xsig)
+diff --git a/arch/x86/math-emu/wm_shrx.S b/arch/x86/math-emu/wm_shrx.S
+index 4fc89174caf0c..f608a28a4c43a 100644
+--- a/arch/x86/math-emu/wm_shrx.S
++++ b/arch/x86/math-emu/wm_shrx.S
+@@ -55,7 +55,7 @@ SYM_FUNC_START(FPU_shrx)
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_31:
+ cmpl $64,%ecx
+@@ -70,7 +70,7 @@ L_more_than_31:
+ movl $0,4(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_63:
+ cmpl $96,%ecx
+@@ -84,7 +84,7 @@ L_more_than_63:
+ movl %edx,4(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+
+ L_more_than_95:
+ xorl %eax,%eax
+@@ -92,7 +92,7 @@ L_more_than_95:
+ movl %eax,4(%esi)
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(FPU_shrx)
+
+
+@@ -146,7 +146,7 @@ SYM_FUNC_START(FPU_shrxs)
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+
+ /* Shift by [0..31] bits */
+ Ls_less_than_32:
+@@ -163,7 +163,7 @@ Ls_less_than_32:
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+
+ /* Shift by [64..95] bits */
+ Ls_more_than_63:
+@@ -189,7 +189,7 @@ Ls_more_than_63:
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+
+ Ls_more_than_95:
+ /* Shift by [96..inf) bits */
+@@ -203,5 +203,5 @@ Ls_more_than_95:
+ popl %ebx
+ popl %esi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(FPU_shrxs)
diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c
index f5e1e60c9095f..6c2f1b76a0b61 100644
--- a/arch/x86/mm/cpu_entry_area.c
@@ -22209,6 +35981,132 @@ index 84a2c8c4af735..4bfed53e210ec 100644
unreachable();
}
#endif
+diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
+index 36098226a9573..b01f5d2caad04 100644
+--- a/arch/x86/mm/init_64.c
++++ b/arch/x86/mm/init_64.c
+@@ -902,6 +902,8 @@ static void __meminit vmemmap_use_sub_pmd(unsigned long start, unsigned long end
+
+ static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end)
+ {
++ const unsigned long page = ALIGN_DOWN(start, PMD_SIZE);
++
+ vmemmap_flush_unused_pmd();
+
+ /*
+@@ -914,8 +916,7 @@ static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long
+ * Mark with PAGE_UNUSED the unused parts of the new memmap range
+ */
+ if (!IS_ALIGNED(start, PMD_SIZE))
+- memset((void *)start, PAGE_UNUSED,
+- start - ALIGN_DOWN(start, PMD_SIZE));
++ memset((void *)page, PAGE_UNUSED, start - page);
+
+ /*
+ * We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of
+diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
+index 60ade7dd71bd9..7ce9b8dd87577 100644
+--- a/arch/x86/mm/ioremap.c
++++ b/arch/x86/mm/ioremap.c
+@@ -614,6 +614,7 @@ static bool memremap_is_efi_data(resource_size_t phys_addr,
+ static bool memremap_is_setup_data(resource_size_t phys_addr,
+ unsigned long size)
+ {
++ struct setup_indirect *indirect;
+ struct setup_data *data;
+ u64 paddr, paddr_next;
+
+@@ -626,6 +627,10 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
+
+ data = memremap(paddr, sizeof(*data),
+ MEMREMAP_WB | MEMREMAP_DEC);
++ if (!data) {
++ pr_warn("failed to memremap setup_data entry\n");
++ return false;
++ }
+
+ paddr_next = data->next;
+ len = data->len;
+@@ -635,10 +640,21 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
+ return true;
+ }
+
+- if (data->type == SETUP_INDIRECT &&
+- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
+- paddr = ((struct setup_indirect *)data->data)->addr;
+- len = ((struct setup_indirect *)data->data)->len;
++ if (data->type == SETUP_INDIRECT) {
++ memunmap(data);
++ data = memremap(paddr, sizeof(*data) + len,
++ MEMREMAP_WB | MEMREMAP_DEC);
++ if (!data) {
++ pr_warn("failed to memremap indirect setup_data\n");
++ return false;
++ }
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT) {
++ paddr = indirect->addr;
++ len = indirect->len;
++ }
+ }
+
+ memunmap(data);
+@@ -659,22 +675,51 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
+ static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
+ unsigned long size)
+ {
++ struct setup_indirect *indirect;
+ struct setup_data *data;
+ u64 paddr, paddr_next;
+
+ paddr = boot_params.hdr.setup_data;
+ while (paddr) {
+- unsigned int len;
++ unsigned int len, size;
+
+ if (phys_addr == paddr)
+ return true;
+
+ data = early_memremap_decrypted(paddr, sizeof(*data));
++ if (!data) {
++ pr_warn("failed to early memremap setup_data entry\n");
++ return false;
++ }
++
++ size = sizeof(*data);
+
+ paddr_next = data->next;
+ len = data->len;
+
+- early_memunmap(data, sizeof(*data));
++ if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
++ early_memunmap(data, sizeof(*data));
++ return true;
++ }
++
++ if (data->type == SETUP_INDIRECT) {
++ size += len;
++ early_memunmap(data, sizeof(*data));
++ data = early_memremap_decrypted(paddr, size);
++ if (!data) {
++ pr_warn("failed to early memremap indirect setup_data\n");
++ return false;
++ }
++
++ indirect = (struct setup_indirect *)data->data;
++
++ if (indirect->type != SETUP_INDIRECT) {
++ paddr = indirect->addr;
++ len = indirect->len;
++ }
++ }
++
++ early_memunmap(data, size);
+
+ if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
+ return true;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index ff08dc4636347..e29b1418d00c7 100644
--- a/arch/x86/mm/mem_encrypt.c
@@ -22221,6 +36119,27 @@ index ff08dc4636347..e29b1418d00c7 100644
#include <asm/tlbflush.h>
#include <asm/fixmap.h>
+diff --git a/arch/x86/mm/mem_encrypt_boot.S b/arch/x86/mm/mem_encrypt_boot.S
+index 17d292b7072f1..3d1dba05fce4a 100644
+--- a/arch/x86/mm/mem_encrypt_boot.S
++++ b/arch/x86/mm/mem_encrypt_boot.S
+@@ -65,7 +65,7 @@ SYM_FUNC_START(sme_encrypt_execute)
+ movq %rbp, %rsp /* Restore original stack pointer */
+ pop %rbp
+
+- ret
++ RET
+ SYM_FUNC_END(sme_encrypt_execute)
+
+ SYM_FUNC_START(__enc_copy)
+@@ -151,6 +151,6 @@ SYM_FUNC_START(__enc_copy)
+ pop %r12
+ pop %r15
+
+- ret
++ RET
+ .L__enc_copy_end:
+ SYM_FUNC_END(__enc_copy)
diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
index 470b202084306..700ce8fdea87c 100644
--- a/arch/x86/mm/mem_encrypt_identity.c
@@ -22241,6 +36160,66 @@ index 470b202084306..700ce8fdea87c 100644
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mem_encrypt.h>
+diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
+index 59ba2968af1b3..511172d70825c 100644
+--- a/arch/x86/mm/tlb.c
++++ b/arch/x86/mm/tlb.c
+@@ -854,13 +854,11 @@ done:
+ nr_invalidate);
+ }
+
+-static bool tlb_is_not_lazy(int cpu)
++static bool tlb_is_not_lazy(int cpu, void *data)
+ {
+ return !per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
+ }
+
+-static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask);
+-
+ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
+ EXPORT_PER_CPU_SYMBOL(cpu_tlbstate_shared);
+
+@@ -889,36 +887,11 @@ STATIC_NOPV void native_flush_tlb_multi(const struct cpumask *cpumask,
+ * up on the new contents of what used to be page tables, while
+ * doing a speculative memory access.
+ */
+- if (info->freed_tables) {
++ if (info->freed_tables)
+ on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
+- } else {
+- /*
+- * Although we could have used on_each_cpu_cond_mask(),
+- * open-coding it has performance advantages, as it eliminates
+- * the need for indirect calls or retpolines. In addition, it
+- * allows to use a designated cpumask for evaluating the
+- * condition, instead of allocating one.
+- *
+- * This code works under the assumption that there are no nested
+- * TLB flushes, an assumption that is already made in
+- * flush_tlb_mm_range().
+- *
+- * cond_cpumask is logically a stack-local variable, but it is
+- * more efficient to have it off the stack and not to allocate
+- * it on demand. Preemption is disabled and this code is
+- * non-reentrant.
+- */
+- struct cpumask *cond_cpumask = this_cpu_ptr(&flush_tlb_mask);
+- int cpu;
+-
+- cpumask_clear(cond_cpumask);
+-
+- for_each_cpu(cpu, cpumask) {
+- if (tlb_is_not_lazy(cpu))
+- __cpumask_set_cpu(cpu, cond_cpumask);
+- }
+- on_each_cpu_mask(cond_cpumask, flush_tlb_func, (void *)info, true);
+- }
++ else
++ on_each_cpu_cond_mask(tlb_is_not_lazy, flush_tlb_func,
++ (void *)info, 1, cpumask);
+ }
+
+ void flush_tlb_multi(const struct cpumask *cpumask,
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 9ea57389c554b..d99434dc215c2 100644
--- a/arch/x86/net/bpf_jit_comp.c
@@ -22430,6 +36409,65 @@ index 2edd86649468f..615a76d700194 100644
static const struct dmi_system_id msi_k8t_dmi_table[] = {
+diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
+index 5debe4ac6f819..f153e9ab8c966 100644
+--- a/arch/x86/pci/xen.c
++++ b/arch/x86/pci/xen.c
+@@ -472,7 +472,6 @@ static __init void xen_setup_pci_msi(void)
+ xen_msi_ops.setup_msi_irqs = xen_setup_msi_irqs;
+ }
+ xen_msi_ops.teardown_msi_irqs = xen_pv_teardown_msi_irqs;
+- pci_msi_ignore_mask = 1;
+ } else if (xen_hvm_domain()) {
+ xen_msi_ops.setup_msi_irqs = xen_hvm_setup_msi_irqs;
+ xen_msi_ops.teardown_msi_irqs = xen_teardown_msi_irqs;
+@@ -486,6 +485,11 @@ static __init void xen_setup_pci_msi(void)
+ * in allocating the native domain and never use it.
+ */
+ x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain;
++ /*
++ * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely
++ * controlled by the hypervisor.
++ */
++ pci_msi_ignore_mask = 1;
+ }
+
+ #else /* CONFIG_PCI_MSI */
+diff --git a/arch/x86/platform/efi/efi_stub_32.S b/arch/x86/platform/efi/efi_stub_32.S
+index 09ec84f6ef517..f3cfdb1c9a359 100644
+--- a/arch/x86/platform/efi/efi_stub_32.S
++++ b/arch/x86/platform/efi/efi_stub_32.S
+@@ -56,5 +56,5 @@ SYM_FUNC_START(efi_call_svam)
+
+ movl 16(%esp), %ebx
+ leave
+- ret
++ RET
+ SYM_FUNC_END(efi_call_svam)
+diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
+index 90380a17ab238..2206b8bc47b8a 100644
+--- a/arch/x86/platform/efi/efi_stub_64.S
++++ b/arch/x86/platform/efi/efi_stub_64.S
+@@ -23,5 +23,5 @@ SYM_FUNC_START(__efi_call)
+ mov %rsi, %rcx
+ CALL_NOSPEC rdi
+ leave
+- ret
++ RET
+ SYM_FUNC_END(__efi_call)
+diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
+index fd3dd1708eba5..f2a8eec69f8f6 100644
+--- a/arch/x86/platform/efi/efi_thunk_64.S
++++ b/arch/x86/platform/efi/efi_thunk_64.S
+@@ -63,7 +63,7 @@ SYM_CODE_START(__efi64_thunk)
+ 1: movq 24(%rsp), %rsp
+ pop %rbx
+ pop %rbp
+- retq
++ RET
+
+ .code32
+ 2: pushl $__KERNEL_CS
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index b15ebfe40a73e..b0b848d6933af 100644
--- a/arch/x86/platform/efi/quirks.c
@@ -22444,6 +36482,158 @@ index b15ebfe40a73e..b0b848d6933af 100644
if (!new) {
pr_err("Failed to map new boot services memmap\n");
return;
+diff --git a/arch/x86/platform/olpc/xo1-wakeup.S b/arch/x86/platform/olpc/xo1-wakeup.S
+index 75f4faff84682..3a5abffe5660d 100644
+--- a/arch/x86/platform/olpc/xo1-wakeup.S
++++ b/arch/x86/platform/olpc/xo1-wakeup.S
+@@ -77,7 +77,7 @@ save_registers:
+ pushfl
+ popl saved_context_eflags
+
+- ret
++ RET
+
+ restore_registers:
+ movl saved_context_ebp, %ebp
+@@ -88,7 +88,7 @@ restore_registers:
+ pushl saved_context_eflags
+ popfl
+
+- ret
++ RET
+
+ SYM_CODE_START(do_olpc_suspend_lowlevel)
+ call save_processor_state
+@@ -109,7 +109,7 @@ ret_point:
+
+ call restore_registers
+ call restore_processor_state
+- ret
++ RET
+ SYM_CODE_END(do_olpc_suspend_lowlevel)
+
+ .data
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index 6665f88020983..732cb075d7072 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -25,6 +25,7 @@
+ #include <asm/cpu.h>
+ #include <asm/mmu_context.h>
+ #include <asm/cpu_device_id.h>
++#include <asm/microcode.h>
+
+ #ifdef CONFIG_X86_32
+ __visible unsigned long saved_context_ebx;
+@@ -40,7 +41,8 @@ static void msr_save_context(struct saved_context *ctxt)
+ struct saved_msr *end = msr + ctxt->saved_msrs.num;
+
+ while (msr < end) {
+- msr->valid = !rdmsrl_safe(msr->info.msr_no, &msr->info.reg.q);
++ if (msr->valid)
++ rdmsrl(msr->info.msr_no, msr->info.reg.q);
+ msr++;
+ }
+ }
+@@ -261,11 +263,18 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
+ x86_platform.restore_sched_clock_state();
+ mtrr_bp_restore();
+ perf_restore_debug_store();
+- msr_restore_context(ctxt);
+
+ c = &cpu_data(smp_processor_id());
+ if (cpu_has(c, X86_FEATURE_MSR_IA32_FEAT_CTL))
+ init_ia32_feat_ctl(c);
++
++ microcode_bsp_resume();
++
++ /*
++ * This needs to happen after the microcode has been updated upon resume
++ * because some of the MSRs are "emulated" in microcode.
++ */
++ msr_restore_context(ctxt);
+ }
+
+ /* Needed by apm.c */
+@@ -424,8 +433,10 @@ static int msr_build_context(const u32 *msr_id, const int num)
+ }
+
+ for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
++ u64 dummy;
++
+ msr_array[i].info.msr_no = msr_id[j];
+- msr_array[i].valid = false;
++ msr_array[i].valid = !rdmsrl_safe(msr_id[j], &dummy);
+ msr_array[i].info.reg.q = 0;
+ }
+ saved_msrs->num = total_num;
+@@ -500,10 +511,24 @@ static int pm_cpu_check(const struct x86_cpu_id *c)
+ return ret;
+ }
+
++static void pm_save_spec_msr(void)
++{
++ u32 spec_msr_id[] = {
++ MSR_IA32_SPEC_CTRL,
++ MSR_IA32_TSX_CTRL,
++ MSR_TSX_FORCE_ABORT,
++ MSR_IA32_MCU_OPT_CTRL,
++ MSR_AMD64_LS_CFG,
++ };
++
++ msr_build_context(spec_msr_id, ARRAY_SIZE(spec_msr_id));
++}
++
+ static int pm_check_save_msr(void)
+ {
+ dmi_check_system(msr_save_dmi_table);
+ pm_cpu_check(msr_save_cpu_table);
++ pm_save_spec_msr();
+
+ return 0;
+ }
+diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S
+index 8786653ad3c06..5606a15cf9a17 100644
+--- a/arch/x86/power/hibernate_asm_32.S
++++ b/arch/x86/power/hibernate_asm_32.S
+@@ -32,7 +32,7 @@ SYM_FUNC_START(swsusp_arch_suspend)
+ FRAME_BEGIN
+ call swsusp_save
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(swsusp_arch_suspend)
+
+ SYM_CODE_START(restore_image)
+@@ -108,5 +108,5 @@ SYM_FUNC_START(restore_registers)
+ /* tell the hibernation core that we've just restored the memory */
+ movl %eax, in_suspend
+
+- ret
++ RET
+ SYM_FUNC_END(restore_registers)
+diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S
+index d9bed596d849c..0a0539e1cc814 100644
+--- a/arch/x86/power/hibernate_asm_64.S
++++ b/arch/x86/power/hibernate_asm_64.S
+@@ -66,7 +66,7 @@ SYM_FUNC_START(restore_registers)
+ /* tell the hibernation core that we've just restored the memory */
+ movq %rax, in_suspend(%rip)
+
+- ret
++ RET
+ SYM_FUNC_END(restore_registers)
+
+ SYM_FUNC_START(swsusp_arch_suspend)
+@@ -96,7 +96,7 @@ SYM_FUNC_START(swsusp_arch_suspend)
+ FRAME_BEGIN
+ call swsusp_save
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(swsusp_arch_suspend)
+
+ SYM_FUNC_START(restore_image)
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 31b5856010cba..1d20ed4b28729 100644
--- a/arch/x86/realmode/init.c
@@ -22508,6 +36698,74 @@ index 31b5856010cba..1d20ed4b28729 100644
#endif
sme_sev_setup_real_mode(trampoline_header);
+diff --git a/arch/x86/um/checksum_32.S b/arch/x86/um/checksum_32.S
+index 13f118dec74f8..aed782ab77213 100644
+--- a/arch/x86/um/checksum_32.S
++++ b/arch/x86/um/checksum_32.S
+@@ -110,7 +110,7 @@ csum_partial:
+ 7:
+ popl %ebx
+ popl %esi
+- ret
++ RET
+
+ #else
+
+@@ -208,7 +208,7 @@ csum_partial:
+ 80:
+ popl %ebx
+ popl %esi
+- ret
++ RET
+
+ #endif
+ EXPORT_SYMBOL(csum_partial)
+diff --git a/arch/x86/um/setjmp_32.S b/arch/x86/um/setjmp_32.S
+index 62eaf8c80e041..2d991ddbcca57 100644
+--- a/arch/x86/um/setjmp_32.S
++++ b/arch/x86/um/setjmp_32.S
+@@ -34,7 +34,7 @@ kernel_setjmp:
+ movl %esi,12(%edx)
+ movl %edi,16(%edx)
+ movl %ecx,20(%edx) # Return address
+- ret
++ RET
+
+ .size kernel_setjmp,.-kernel_setjmp
+
+diff --git a/arch/x86/um/setjmp_64.S b/arch/x86/um/setjmp_64.S
+index 1b5d40d4ff46d..b46acb6a8ebd8 100644
+--- a/arch/x86/um/setjmp_64.S
++++ b/arch/x86/um/setjmp_64.S
+@@ -33,7 +33,7 @@ kernel_setjmp:
+ movq %r14,40(%rdi)
+ movq %r15,48(%rdi)
+ movq %rsi,56(%rdi) # Return address
+- ret
++ RET
+
+ .size kernel_setjmp,.-kernel_setjmp
+
+diff --git a/arch/x86/um/shared/sysdep/syscalls_64.h b/arch/x86/um/shared/sysdep/syscalls_64.h
+index 8a7d5e1da98e5..1e6875b4ffd83 100644
+--- a/arch/x86/um/shared/sysdep/syscalls_64.h
++++ b/arch/x86/um/shared/sysdep/syscalls_64.h
+@@ -10,13 +10,12 @@
+ #include <linux/msg.h>
+ #include <linux/shm.h>
+
+-typedef long syscall_handler_t(void);
++typedef long syscall_handler_t(long, long, long, long, long, long);
+
+ extern syscall_handler_t *sys_call_table[];
+
+ #define EXECUTE_SYSCALL(syscall, regs) \
+- (((long (*)(long, long, long, long, long, long)) \
+- (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
++ (((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+ UPT_SYSCALL_ARG2(&regs->regs), \
+ UPT_SYSCALL_ARG3(&regs->regs), \
+ UPT_SYSCALL_ARG4(&regs->regs), \
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
index 58f51667e2e4b..8249685b40960 100644
--- a/arch/x86/um/syscalls_64.c
@@ -22544,10 +36802,92 @@ index a7b7d674f5005..133ef31639df1 100644
xen_boot_params_init_edd();
#ifdef CONFIG_ACPI
+diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
+index e13b0b49fcdfc..d7249f4c90f1b 100644
+--- a/arch/x86/xen/pmu.c
++++ b/arch/x86/xen/pmu.c
+@@ -512,10 +512,7 @@ irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id)
+ return ret;
+ }
+
+-bool is_xen_pmu(int cpu)
+-{
+- return (get_xenpmu_data() != NULL);
+-}
++bool is_xen_pmu;
+
+ void xen_pmu_init(int cpu)
+ {
+@@ -526,7 +523,7 @@ void xen_pmu_init(int cpu)
+
+ BUILD_BUG_ON(sizeof(struct xen_pmu_data) > PAGE_SIZE);
+
+- if (xen_hvm_domain())
++ if (xen_hvm_domain() || (cpu != 0 && !is_xen_pmu))
+ return;
+
+ xenpmu_data = (struct xen_pmu_data *)get_zeroed_page(GFP_KERNEL);
+@@ -547,7 +544,8 @@ void xen_pmu_init(int cpu)
+ per_cpu(xenpmu_shared, cpu).xenpmu_data = xenpmu_data;
+ per_cpu(xenpmu_shared, cpu).flags = 0;
+
+- if (cpu == 0) {
++ if (!is_xen_pmu) {
++ is_xen_pmu = true;
+ perf_register_guest_info_callbacks(&xen_guest_cbs);
+ xen_pmu_arch_init();
+ }
+diff --git a/arch/x86/xen/pmu.h b/arch/x86/xen/pmu.h
+index 0e83a160589bc..65c58894fc79f 100644
+--- a/arch/x86/xen/pmu.h
++++ b/arch/x86/xen/pmu.h
+@@ -4,6 +4,8 @@
+
+ #include <xen/interface/xenpmu.h>
+
++extern bool is_xen_pmu;
++
+ irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id);
+ #ifdef CONFIG_XEN_HAVE_VPMU
+ void xen_pmu_init(int cpu);
+@@ -12,7 +14,6 @@ void xen_pmu_finish(int cpu);
+ static inline void xen_pmu_init(int cpu) {}
+ static inline void xen_pmu_finish(int cpu) {}
+ #endif
+-bool is_xen_pmu(int cpu);
+ bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err);
+ bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err);
+ int pmu_apic_update(uint32_t reg);
+diff --git a/arch/x86/xen/smp_hvm.c b/arch/x86/xen/smp_hvm.c
+index 6ff3c887e0b99..b70afdff419ca 100644
+--- a/arch/x86/xen/smp_hvm.c
++++ b/arch/x86/xen/smp_hvm.c
+@@ -19,6 +19,12 @@ static void __init xen_hvm_smp_prepare_boot_cpu(void)
+ */
+ xen_vcpu_setup(0);
+
++ /*
++ * Called again in case the kernel boots on vcpu >= MAX_VIRT_CPUS.
++ * Refer to comments in xen_hvm_init_time_ops().
++ */
++ xen_hvm_init_time_ops();
++
+ /*
+ * The alternative logic (which patches the unlock/lock) runs before
+ * the smp bootup up code is activated. Hence we need to set this up
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
-index 7ed56c6075b0c..477c484eb202c 100644
+index 7ed56c6075b0c..cd5539fc5eb45 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
+@@ -129,7 +129,7 @@ int xen_smp_intr_init_pv(unsigned int cpu)
+ per_cpu(xen_irq_work, cpu).irq = rc;
+ per_cpu(xen_irq_work, cpu).name = callfunc_name;
+
+- if (is_xen_pmu(cpu)) {
++ if (is_xen_pmu) {
+ pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
+ rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
+ xen_pmu_irq_handler,
@@ -148,28 +148,12 @@ int xen_smp_intr_init_pv(unsigned int cpu)
return rc;
}
@@ -22597,8 +36937,57 @@ index 7ed56c6075b0c..477c484eb202c 100644
+ x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.get_smp_config = _get_smp_config;
}
+diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
+index d9c945ee11008..9ef0a5cca96ee 100644
+--- a/arch/x86/xen/time.c
++++ b/arch/x86/xen/time.c
+@@ -558,6 +558,11 @@ static void xen_hvm_setup_cpu_clockevents(void)
+
+ void __init xen_hvm_init_time_ops(void)
+ {
++ static bool hvm_time_initialized;
++
++ if (hvm_time_initialized)
++ return;
++
+ /*
+ * vector callback is needed otherwise we cannot receive interrupts
+ * on cpu > 0 and at this point we don't know how many cpus are
+@@ -567,7 +572,22 @@ void __init xen_hvm_init_time_ops(void)
+ return;
+
+ if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
+- pr_info("Xen doesn't support pvclock on HVM, disable pv timer");
++ pr_info_once("Xen doesn't support pvclock on HVM, disable pv timer");
++ return;
++ }
++
++ /*
++ * Only MAX_VIRT_CPUS 'vcpu_info' are embedded inside 'shared_info'.
++ * The __this_cpu_read(xen_vcpu) is still NULL when Xen HVM guest
++ * boots on vcpu >= MAX_VIRT_CPUS (e.g., kexec), To access
++ * __this_cpu_read(xen_vcpu) via xen_clocksource_read() will panic.
++ *
++ * The xen_hvm_init_time_ops() should be called again later after
++ * __this_cpu_read(xen_vcpu) is available.
++ */
++ if (!__this_cpu_read(xen_vcpu)) {
++ pr_info("Delay xen_init_time_common() as kernel is running on vcpu=%d\n",
++ xen_vcpu_nr(0));
+ return;
+ }
+
+@@ -577,6 +597,8 @@ void __init xen_hvm_init_time_ops(void)
+ x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
+
+ x86_platform.set_wallclock = xen_set_wallclock;
++
++ hvm_time_initialized = true;
+ }
+ #endif
+
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
-index 1e626444712be..3bebf66569b48 100644
+index 1e626444712be..962d30ea01a22 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -20,6 +20,7 @@
@@ -22609,6 +36998,59 @@ index 1e626444712be..3bebf66569b48 100644
/*
* Enable events. This clears the event mask and tests the pending
+@@ -44,7 +45,7 @@ SYM_FUNC_START(xen_irq_enable_direct)
+ call check_events
+ 1:
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(xen_irq_enable_direct)
+
+
+@@ -54,7 +55,7 @@ SYM_FUNC_END(xen_irq_enable_direct)
+ */
+ SYM_FUNC_START(xen_irq_disable_direct)
+ movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
+- ret
++ RET
+ SYM_FUNC_END(xen_irq_disable_direct)
+
+ /*
+@@ -70,7 +71,7 @@ SYM_FUNC_START(xen_save_fl_direct)
+ testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
+ setz %ah
+ addb %ah, %ah
+- ret
++ RET
+ SYM_FUNC_END(xen_save_fl_direct)
+
+ /*
+@@ -99,7 +100,7 @@ SYM_FUNC_START(check_events)
+ pop %rcx
+ pop %rax
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(check_events)
+
+ SYM_FUNC_START(xen_read_cr2)
+@@ -107,14 +108,14 @@ SYM_FUNC_START(xen_read_cr2)
+ _ASM_MOV PER_CPU_VAR(xen_vcpu), %_ASM_AX
+ _ASM_MOV XEN_vcpu_info_arch_cr2(%_ASM_AX), %_ASM_AX
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(xen_read_cr2);
+
+ SYM_FUNC_START(xen_read_cr2_direct)
+ FRAME_BEGIN
+ _ASM_MOV PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_arch_cr2, %_ASM_AX
+ FRAME_END
+- ret
++ RET
+ SYM_FUNC_END(xen_read_cr2_direct);
+
+ .macro xen_pv_trap name
@@ -191,6 +192,25 @@ SYM_CODE_START(xen_iret)
jmp hypercall_iret
SYM_CODE_END(xen_iret)
@@ -22635,11 +37077,406 @@ index 1e626444712be..3bebf66569b48 100644
/*
* Xen handles syscall callbacks much like ordinary exceptions, which
* means we have:
+diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
+index cb6538ae2fe07..565062932ef11 100644
+--- a/arch/x86/xen/xen-head.S
++++ b/arch/x86/xen/xen-head.S
+@@ -70,7 +70,7 @@ SYM_CODE_START(hypercall_page)
+ .rept (PAGE_SIZE / 32)
+ UNWIND_HINT_FUNC
+ .skip 31, 0x90
+- ret
++ RET
+ .endr
+
+ #define HYPERCALL(n) \
+diff --git a/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
+index 9bf8bad1dd18a..c33932568aa73 100644
+--- a/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
++++ b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
+@@ -8,19 +8,19 @@
+ reg = <0x00000000 0x08000000>;
+ bank-width = <2>;
+ device-width = <2>;
+- partition@0x0 {
++ partition@0 {
+ label = "data";
+ reg = <0x00000000 0x06000000>;
+ };
+- partition@0x6000000 {
++ partition@6000000 {
+ label = "boot loader area";
+ reg = <0x06000000 0x00800000>;
+ };
+- partition@0x6800000 {
++ partition@6800000 {
+ label = "kernel image";
+ reg = <0x06800000 0x017e0000>;
+ };
+- partition@0x7fe0000 {
++ partition@7fe0000 {
+ label = "boot environment";
+ reg = <0x07fe0000 0x00020000>;
+ };
+diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+index 40c2f81f7cb66..7bde2ab2d6fb5 100644
+--- a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
++++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+@@ -8,19 +8,19 @@
+ reg = <0x08000000 0x01000000>;
+ bank-width = <2>;
+ device-width = <2>;
+- partition@0x0 {
++ partition@0 {
+ label = "boot loader area";
+ reg = <0x00000000 0x00400000>;
+ };
+- partition@0x400000 {
++ partition@400000 {
+ label = "kernel image";
+ reg = <0x00400000 0x00600000>;
+ };
+- partition@0xa00000 {
++ partition@a00000 {
+ label = "data";
+ reg = <0x00a00000 0x005e0000>;
+ };
+- partition@0xfe0000 {
++ partition@fe0000 {
+ label = "boot environment";
+ reg = <0x00fe0000 0x00020000>;
+ };
+diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+index fb8d3a9f33c23..0655b868749a4 100644
+--- a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
++++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+@@ -8,11 +8,11 @@
+ reg = <0x08000000 0x00400000>;
+ bank-width = <2>;
+ device-width = <2>;
+- partition@0x0 {
++ partition@0 {
+ label = "boot loader area";
+ reg = <0x00000000 0x003f0000>;
+ };
+- partition@0x3f0000 {
++ partition@3f0000 {
+ label = "boot environment";
+ reg = <0x003f0000 0x00010000>;
+ };
+diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
+index bd5aeb7955675..a63eca1266577 100644
+--- a/arch/xtensa/include/asm/pgtable.h
++++ b/arch/xtensa/include/asm/pgtable.h
+@@ -411,6 +411,10 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
+
+ typedef pte_t *pte_addr_t;
+
++void update_mmu_tlb(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep);
++#define __HAVE_ARCH_UPDATE_MMU_TLB
++
+ #endif /* !defined (__ASSEMBLY__) */
+
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
+index 7f63aca6a0d34..9dd4efe1bf0bd 100644
+--- a/arch/xtensa/include/asm/processor.h
++++ b/arch/xtensa/include/asm/processor.h
+@@ -226,8 +226,8 @@ extern unsigned long get_wchan(struct task_struct *p);
+
+ #define xtensa_set_sr(x, sr) \
+ ({ \
+- unsigned int v = (unsigned int)(x); \
+- __asm__ __volatile__ ("wsr %0, "__stringify(sr) :: "a"(v)); \
++ __asm__ __volatile__ ("wsr %0, "__stringify(sr) :: \
++ "a"((unsigned int)(x))); \
+ })
+
+ #define xtensa_get_sr(sr) \
+diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h
+index 233ec75e60c69..3f2462f2d0270 100644
+--- a/arch/xtensa/include/asm/timex.h
++++ b/arch/xtensa/include/asm/timex.h
+@@ -29,10 +29,6 @@
+
+ extern unsigned long ccount_freq;
+
+-typedef unsigned long long cycles_t;
+-
+-#define get_cycles() (0)
+-
+ void local_timer_setup(unsigned cpu);
+
+ /*
+@@ -59,4 +55,6 @@ static inline void set_linux_timer (unsigned long ccompare)
+ xtensa_set_sr(ccompare, SREG_CCOMPARE + LINUX_TIMER);
+ }
+
++#include <asm-generic/timex.h>
++
+ #endif /* _XTENSA_TIMEX_H */
+diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
+index 45cc0ae0af6f9..c7b9f12896f20 100644
+--- a/arch/xtensa/kernel/coprocessor.S
++++ b/arch/xtensa/kernel/coprocessor.S
+@@ -29,7 +29,7 @@
+ .if XTENSA_HAVE_COPROCESSOR(x); \
+ .align 4; \
+ .Lsave_cp_regs_cp##x: \
+- xchal_cp##x##_store a2 a4 a5 a6 a7; \
++ xchal_cp##x##_store a2 a3 a4 a5 a6; \
+ jx a0; \
+ .endif
+
+@@ -46,7 +46,7 @@
+ .if XTENSA_HAVE_COPROCESSOR(x); \
+ .align 4; \
+ .Lload_cp_regs_cp##x: \
+- xchal_cp##x##_load a2 a4 a5 a6 a7; \
++ xchal_cp##x##_load a2 a3 a4 a5 a6; \
+ jx a0; \
+ .endif
+
+diff --git a/arch/xtensa/kernel/jump_label.c b/arch/xtensa/kernel/jump_label.c
+index 61cf6497a646b..ad1841cecdfb7 100644
+--- a/arch/xtensa/kernel/jump_label.c
++++ b/arch/xtensa/kernel/jump_label.c
+@@ -40,7 +40,7 @@ static int patch_text_stop_machine(void *data)
+ {
+ struct patch *patch = data;
+
+- if (atomic_inc_return(&patch->cpu_count) == 1) {
++ if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
+ local_patch_text(patch->addr, patch->data, patch->sz);
+ atomic_inc(&patch->cpu_count);
+ } else {
+@@ -61,7 +61,7 @@ static void patch_text(unsigned long addr, const void *data, size_t sz)
+ .data = data,
+ };
+ stop_machine_cpuslocked(patch_text_stop_machine,
+- &patch, NULL);
++ &patch, cpu_online_mask);
+ } else {
+ unsigned long flags;
+
+diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
+index f436cf2efd8b7..27a477dae2322 100644
+--- a/arch/xtensa/mm/tlb.c
++++ b/arch/xtensa/mm/tlb.c
+@@ -162,6 +162,12 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+ }
+ }
+
++void update_mmu_tlb(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep)
++{
++ local_flush_tlb_page(vma, address);
++}
++
+ #ifdef CONFIG_DEBUG_TLB_SANITY
+
+ static unsigned get_pte_for_vaddr(unsigned vaddr)
+diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
+index 81d7c7e8f7e96..10b79d3c74e07 100644
+--- a/arch/xtensa/platforms/iss/console.c
++++ b/arch/xtensa/platforms/iss/console.c
+@@ -36,24 +36,19 @@ static void rs_poll(struct timer_list *);
+ static struct tty_driver *serial_driver;
+ static struct tty_port serial_port;
+ static DEFINE_TIMER(serial_timer, rs_poll);
+-static DEFINE_SPINLOCK(timer_lock);
+
+ static int rs_open(struct tty_struct *tty, struct file * filp)
+ {
+- spin_lock_bh(&timer_lock);
+ if (tty->count == 1)
+ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+- spin_unlock_bh(&timer_lock);
+
+ return 0;
+ }
+
+ static void rs_close(struct tty_struct *tty, struct file * filp)
+ {
+- spin_lock_bh(&timer_lock);
+ if (tty->count == 1)
+ del_timer_sync(&serial_timer);
+- spin_unlock_bh(&timer_lock);
+ }
+
+
+@@ -73,8 +68,6 @@ static void rs_poll(struct timer_list *unused)
+ int rd = 1;
+ unsigned char c;
+
+- spin_lock(&timer_lock);
+-
+ while (simc_poll(0)) {
+ rd = simc_read(0, &c, 1);
+ if (rd <= 0)
+@@ -87,7 +80,6 @@ static void rs_poll(struct timer_list *unused)
+ tty_flip_buffer_push(port);
+ if (rd)
+ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+- spin_unlock(&timer_lock);
+ }
+
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 485a258b0ab37..18abafb135e0b 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -184,14 +184,13 @@ int sb_min_blocksize(struct super_block *sb, int size)
+
+ EXPORT_SYMBOL(sb_min_blocksize);
+
+-int __sync_blockdev(struct block_device *bdev, int wait)
++int sync_blockdev_nowait(struct block_device *bdev)
+ {
+ if (!bdev)
+ return 0;
+- if (!wait)
+- return filemap_flush(bdev->bd_inode->i_mapping);
+- return filemap_write_and_wait(bdev->bd_inode->i_mapping);
++ return filemap_flush(bdev->bd_inode->i_mapping);
+ }
++EXPORT_SYMBOL_GPL(sync_blockdev_nowait);
+
+ /*
+ * Write out and wait upon all the dirty data associated with a block
+@@ -199,7 +198,9 @@ int __sync_blockdev(struct block_device *bdev, int wait)
+ */
+ int sync_blockdev(struct block_device *bdev)
+ {
+- return __sync_blockdev(bdev, 1);
++ if (!bdev)
++ return 0;
++ return filemap_write_and_wait(bdev->bd_inode->i_mapping);
+ }
+ EXPORT_SYMBOL(sync_blockdev);
+
+@@ -1016,7 +1017,7 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty)
+ }
+ EXPORT_SYMBOL(__invalidate_device);
+
+-void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
++void sync_bdevs(bool wait)
+ {
+ struct inode *inode, *old_inode = NULL;
+
+@@ -1047,8 +1048,19 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
+ bdev = I_BDEV(inode);
+
+ mutex_lock(&bdev->bd_disk->open_mutex);
+- if (bdev->bd_openers)
+- func(bdev, arg);
++ if (!bdev->bd_openers) {
++ ; /* skip */
++ } else if (wait) {
++ /*
++ * We keep the error status of individual mapping so
++ * that applications can catch the writeback error using
++ * fsync(2). See filemap_fdatawait_keep_errors() for
++ * details.
++ */
++ filemap_fdatawait_keep_errors(inode->i_mapping);
++ } else {
++ filemap_fdatawrite(inode->i_mapping);
++ }
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+
+ spin_lock(&blockdev_superblock->s_inode_list_lock);
+diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
+index 85b8e1c3a762d..e37af3f8a733d 100644
+--- a/block/bfq-cgroup.c
++++ b/block/bfq-cgroup.c
+@@ -644,6 +644,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ {
+ struct bfq_entity *entity = &bfqq->entity;
+
++ /*
++ * oom_bfqq is not allowed to move, oom_bfqq will hold ref to root_group
++ * until elevator exit.
++ */
++ if (bfqq == &bfqd->oom_bfqq)
++ return;
+ /*
+ * Get extra reference to prevent bfqq from being freed in
+ * next possible expire or deactivate.
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
-index 480e1a1348596..e66970bf27dbe 100644
+index 480e1a1348596..63d2d66dece56 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
-@@ -5991,48 +5991,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
+@@ -2662,6 +2662,15 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
+ * are likely to increase the throughput.
+ */
+ bfqq->new_bfqq = new_bfqq;
++ /*
++ * The above assignment schedules the following redirections:
++ * each time some I/O for bfqq arrives, the process that
++ * generated that I/O is disassociated from bfqq and
++ * associated with new_bfqq. Here we increases new_bfqq->ref
++ * in advance, adding the number of processes that are
++ * expected to be associated with new_bfqq as they happen to
++ * issue I/O.
++ */
+ new_bfqq->ref += process_refs;
+ return new_bfqq;
+ }
+@@ -2724,6 +2733,10 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ {
+ struct bfq_queue *in_service_bfqq, *new_bfqq;
+
++ /* if a merge has already been setup, then proceed with that first */
++ if (bfqq->new_bfqq)
++ return bfqq->new_bfqq;
++
+ /*
+ * Check delayed stable merge for rotational or non-queueing
+ * devs. For this branch to be executed, bfqq must not be
+@@ -2825,9 +2838,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ if (bfq_too_late_for_merging(bfqq))
+ return NULL;
+
+- if (bfqq->new_bfqq)
+- return bfqq->new_bfqq;
+-
+ if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
+ return NULL;
+
+@@ -5061,7 +5071,7 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
+ struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
+ struct request *rq;
+ struct bfq_queue *in_serv_queue;
+- bool waiting_rq, idle_timer_disabled;
++ bool waiting_rq, idle_timer_disabled = false;
+
+ spin_lock_irq(&bfqd->lock);
+
+@@ -5069,14 +5079,15 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
+ waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
+
+ rq = __bfq_dispatch_request(hctx);
+-
+- idle_timer_disabled =
+- waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
++ if (in_serv_queue == bfqd->in_service_queue) {
++ idle_timer_disabled =
++ waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
++ }
+
+ spin_unlock_irq(&bfqd->lock);
+-
+- bfq_update_dispatch_stats(hctx->queue, rq, in_serv_queue,
+- idle_timer_disabled);
++ bfq_update_dispatch_stats(hctx->queue, rq,
++ idle_timer_disabled ? in_serv_queue : NULL,
++ idle_timer_disabled);
+
+ return rq;
+ }
+@@ -5991,48 +6002,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
spin_lock_irq(&bfqd->lock);
bfqq = bfq_init_rq(rq);
@@ -22689,7 +37526,7 @@ index 480e1a1348596..e66970bf27dbe 100644
if (at_head)
list_add(&rq->queuelist, &bfqd->dispatch);
else
-@@ -6059,7 +6018,6 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
+@@ -6059,7 +6029,6 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
* merge).
*/
cmd_flags = rq->cmd_flags;
@@ -22697,7 +37534,7 @@ index 480e1a1348596..e66970bf27dbe 100644
spin_unlock_irq(&bfqd->lock);
bfq_update_insert_stats(q, bfqq, idle_timer_disabled,
-@@ -6920,6 +6878,8 @@ static void bfq_exit_queue(struct elevator_queue *e)
+@@ -6920,6 +6889,8 @@ static void bfq_exit_queue(struct elevator_queue *e)
spin_unlock_irq(&bfqd->lock);
#endif
@@ -22706,6 +37543,19 @@ index 480e1a1348596..e66970bf27dbe 100644
kfree(bfqd);
}
+diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
+index b74cc0da118ec..709b901de3ca9 100644
+--- a/block/bfq-wf2q.c
++++ b/block/bfq-wf2q.c
+@@ -519,7 +519,7 @@ unsigned short bfq_ioprio_to_weight(int ioprio)
+ static unsigned short bfq_weight_to_ioprio(int weight)
+ {
+ return max_t(int, 0,
+- IOPRIO_NR_LEVELS * BFQ_WEIGHT_CONVERSION_COEFF - weight);
++ IOPRIO_NR_LEVELS - weight / BFQ_WEIGHT_CONVERSION_COEFF);
+ }
+
+ static void bfq_get_entity(struct bfq_entity *entity)
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 6b47cddbbca17..4a7c33ed9a661 100644
--- a/block/bio-integrity.c
@@ -22720,7 +37570,7 @@ index 6b47cddbbca17..4a7c33ed9a661 100644
}
diff --git a/block/bio.c b/block/bio.c
-index a6fb6a0b42955..25f1ed261100b 100644
+index a6fb6a0b42955..8906c9856a7de 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -567,7 +567,8 @@ void bio_truncate(struct bio *bio, unsigned new_size)
@@ -22733,8 +37583,17 @@ index a6fb6a0b42955..25f1ed261100b 100644
truncated = true;
}
done += bv.bv_len;
+@@ -1551,7 +1552,7 @@ EXPORT_SYMBOL(bio_split);
+ void bio_trim(struct bio *bio, sector_t offset, sector_t size)
+ {
+ if (WARN_ON_ONCE(offset > BIO_MAX_SECTORS || size > BIO_MAX_SECTORS ||
+- offset + size > bio->bi_iter.bi_size))
++ offset + size > bio_sectors(bio)))
+ return;
+
+ size <<= 9;
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
-index 9a1c5839dd469..0eec59e4df65c 100644
+index 9a1c5839dd469..07a2524e6efdc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -633,6 +633,14 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
@@ -22785,11 +37644,48 @@ index 9a1c5839dd469..0eec59e4df65c 100644
fail:
blkdev_put_no_open(bdev);
/*
+@@ -844,11 +855,11 @@ static void blkcg_fill_root_iostats(void)
+ blk_queue_root_blkg(bdev->bd_disk->queue);
+ struct blkg_iostat tmp;
+ int cpu;
++ unsigned long flags;
+
+ memset(&tmp, 0, sizeof(tmp));
+ for_each_possible_cpu(cpu) {
+ struct disk_stats *cpu_dkstats;
+- unsigned long flags;
+
+ cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);
+ tmp.ios[BLKG_IOSTAT_READ] +=
+@@ -864,11 +875,11 @@ static void blkcg_fill_root_iostats(void)
+ cpu_dkstats->sectors[STAT_WRITE] << 9;
+ tmp.bytes[BLKG_IOSTAT_DISCARD] +=
+ cpu_dkstats->sectors[STAT_DISCARD] << 9;
+-
+- flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
+- blkg_iostat_set(&blkg->iostat.cur, &tmp);
+- u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
+ }
++
++ flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
++ blkg_iostat_set(&blkg->iostat.cur, &tmp);
++ u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
+ }
+ }
+
diff --git a/block/blk-core.c b/block/blk-core.c
-index 4d8f5fe915887..42ac3a985c2d7 100644
+index 4d8f5fe915887..5009b9f1c3c9d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
-@@ -350,13 +350,6 @@ void blk_queue_start_drain(struct request_queue *q)
+@@ -49,6 +49,7 @@
+ #include "blk-mq.h"
+ #include "blk-mq-sched.h"
+ #include "blk-pm.h"
++#include "blk-rq-qos.h"
+
+ struct dentry *blk_debugfs_root;
+
+@@ -350,13 +351,6 @@ void blk_queue_start_drain(struct request_queue *q)
wake_up_all(&q->mq_freeze_wq);
}
@@ -22803,7 +37699,7 @@ index 4d8f5fe915887..42ac3a985c2d7 100644
/**
* blk_cleanup_queue - shutdown a request queue
* @q: request queue to shutdown
-@@ -374,7 +367,8 @@ void blk_cleanup_queue(struct request_queue *q)
+@@ -374,7 +368,8 @@ void blk_cleanup_queue(struct request_queue *q)
WARN_ON_ONCE(blk_queue_registered(q));
/* mark @q DYING, no new request or merges will be allowed afterwards */
@@ -22813,7 +37709,13 @@ index 4d8f5fe915887..42ac3a985c2d7 100644
blk_queue_flag_set(QUEUE_FLAG_NOMERGES, q);
blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
-@@ -389,8 +383,10 @@ void blk_cleanup_queue(struct request_queue *q)
+@@ -386,11 +381,16 @@ void blk_cleanup_queue(struct request_queue *q)
+ */
+ blk_freeze_queue(q);
+
++ /* cleanup rq qos structures for queue without disk */
++ rq_qos_exit(q);
++
blk_queue_flag_set(QUEUE_FLAG_DEAD, q);
blk_sync_queue(q);
@@ -22825,7 +37727,7 @@ index 4d8f5fe915887..42ac3a985c2d7 100644
/*
* In theory, request pool of sched_tags belongs to request queue.
-@@ -887,10 +883,8 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
+@@ -887,10 +887,8 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
if (unlikely(!current->io_context))
create_task_io_context(current, GFP_ATOMIC, q->node);
@@ -22837,7 +37739,7 @@ index 4d8f5fe915887..42ac3a985c2d7 100644
blk_cgroup_bio_start(bio);
blkcg_bio_issue_init(bio);
-@@ -1293,20 +1287,32 @@ void blk_account_io_start(struct request *rq)
+@@ -1293,20 +1291,32 @@ void blk_account_io_start(struct request *rq)
}
static unsigned long __part_start_io_acct(struct block_device *part,
@@ -22874,7 +37776,7 @@ index 4d8f5fe915887..42ac3a985c2d7 100644
/**
* bio_start_io_acct - start I/O accounting for bio based drivers
-@@ -1316,14 +1322,15 @@ static unsigned long __part_start_io_acct(struct block_device *part,
+@@ -1316,14 +1326,15 @@ static unsigned long __part_start_io_acct(struct block_device *part,
*/
unsigned long bio_start_io_acct(struct bio *bio)
{
@@ -22909,10 +37811,10 @@ index 4201728bf3a5a..94a86acbb7f67 100644
if (!q->elevator) {
flush_rq->tag = BLK_MQ_NO_TAG;
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
-index b3880e4ba22a1..eb7b0d6bd11f6 100644
+index b3880e4ba22a1..10851493940c3 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
-@@ -2311,7 +2311,14 @@ static void ioc_timer_fn(struct timer_list *timer)
+@@ -2311,11 +2311,28 @@ static void ioc_timer_fn(struct timer_list *timer)
hwm = current_hweight_max(iocg);
new_hwi = hweight_after_donation(iocg, old_hwi, hwm,
usage, &now);
@@ -22928,6 +37830,21 @@ index b3880e4ba22a1..eb7b0d6bd11f6 100644
iocg->hweight_donating = hwa;
iocg->hweight_after_donation = new_hwi;
list_add(&iocg->surplus_list, &surpluses);
+- } else {
++ } else if (!iocg->abs_vdebt) {
++ /*
++ * @iocg doesn't have enough to donate. Reset
++ * its inuse to active.
++ *
++ * Don't reset debtors as their inuse's are
++ * owned by debt handling. This shouldn't affect
++ * donation calculuation in any meaningful way
++ * as @iocg doesn't have a meaningful amount of
++ * share anyway.
++ */
+ TRACE_IOCG_PATH(inuse_shortage, iocg, &now,
+ iocg->inuse, iocg->active,
+ iocg->hweight_inuse, new_hwi);
diff --git a/block/blk-map.c b/block/blk-map.c
index 4526adde01564..c7f71d83eff18 100644
--- a/block/blk-map.c
@@ -22941,6 +37858,73 @@ index 4526adde01564..c7f71d83eff18 100644
if (!page)
goto cleanup;
+diff --git a/block/blk-merge.c b/block/blk-merge.c
+index 7a5c81c02c800..bbe66a9010bf1 100644
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -7,6 +7,7 @@
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
+ #include <linux/scatterlist.h>
++#include <linux/blk-cgroup.h>
+
+ #include <trace/events/block.h>
+
+@@ -561,6 +562,9 @@ static inline unsigned int blk_rq_get_max_segments(struct request *rq)
+ static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
+ unsigned int nr_phys_segs)
+ {
++ if (!blk_cgroup_mergeable(req, bio))
++ goto no_merge;
++
+ if (blk_integrity_merge_bio(req->q, req, bio) == false)
+ goto no_merge;
+
+@@ -657,6 +661,9 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
+ if (total_phys_segments > blk_rq_get_max_segments(req))
+ return 0;
+
++ if (!blk_cgroup_mergeable(req, next->bio))
++ return 0;
++
+ if (blk_integrity_merge_rq(q, req, next) == false)
+ return 0;
+
+@@ -863,6 +870,10 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
+ if (rq->rq_disk != bio->bi_bdev->bd_disk)
+ return false;
+
++ /* don't merge across cgroup boundaries */
++ if (!blk_cgroup_mergeable(rq, bio))
++ return false;
++
+ /* only merge integrity protected bio into ditto rq */
+ if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
+ return false;
+diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
+index 0f006cabfd914..35770e33c817a 100644
+--- a/block/blk-mq-sched.c
++++ b/block/blk-mq-sched.c
+@@ -208,11 +208,18 @@ static int __blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
+
+ static int blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
+ {
++ unsigned long end = jiffies + HZ;
+ int ret;
+
+ do {
+ ret = __blk_mq_do_dispatch_sched(hctx);
+- } while (ret == 1);
++ if (ret != 1)
++ break;
++ if (need_resched() || time_is_before_jiffies(end)) {
++ blk_mq_delay_run_hw_queue(hctx, 0);
++ break;
++ }
++ } while (1);
+
+ return ret;
+ }
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 652a31fc3bb38..82de39926a9f6 100644
--- a/block/blk-mq.c
@@ -23051,7 +38035,7 @@ index 17bd020268d42..2dad62cc15727 100644
*/
void blk_set_runtime_active(struct request_queue *q)
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
-index 614d9d47de36b..4737ec024ee9b 100644
+index 614d9d47de36b..00021f0123701 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -805,16 +805,6 @@ static void blk_release_queue(struct kobject *kobj)
@@ -23071,6 +38055,27 @@ index 614d9d47de36b..4737ec024ee9b 100644
blk_exit_queue(q);
blk_queue_free_zone_bitmaps(q);
+@@ -964,15 +954,17 @@ void blk_unregister_queue(struct gendisk *disk)
+ */
+ if (queue_is_mq(q))
+ blk_mq_unregister_dev(disk_to_dev(disk), q);
+-
+- kobject_uevent(&q->kobj, KOBJ_REMOVE);
+- kobject_del(&q->kobj);
+ blk_trace_remove_sysfs(disk_to_dev(disk));
+
+ mutex_lock(&q->sysfs_lock);
+ if (q->elevator)
+ elv_unregister_queue(q);
+ mutex_unlock(&q->sysfs_lock);
++
++ /* Now that we've deleted all child objects, we can delete the queue. */
++ kobject_uevent(&q->kobj, KOBJ_REMOVE);
++ kobject_del(&q->kobj);
++
+ mutex_unlock(&q->sysfs_dir_lock);
+
+ kobject_put(&disk_to_dev(disk)->kobj);
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index 874c1c37bf0c6..0c119be0e8133 100644
--- a/block/blk-wbt.c
@@ -23172,10 +38177,27 @@ index ff45d8388f487..1b5e57f6115f3 100644
if (err) {
diff --git a/block/genhd.c b/block/genhd.c
-index ab12ae6e636e8..2dcedbe4ef046 100644
+index ab12ae6e636e8..74e19d67ceab5 100644
--- a/block/genhd.c
+++ b/block/genhd.c
-@@ -420,6 +420,8 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
+@@ -19,6 +19,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/kmod.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/idr.h>
+ #include <linux/log2.h>
+@@ -323,7 +324,7 @@ int blk_alloc_ext_minor(void)
+ {
+ int idx;
+
+- idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT, GFP_KERNEL);
++ idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT - 1, GFP_KERNEL);
+ if (idx == -ENOSPC)
+ return -EBUSY;
+ return idx;
+@@ -420,6 +421,8 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
DISK_MAX_PARTS);
disk->minors = DISK_MAX_PARTS;
}
@@ -23184,7 +38206,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
} else {
if (WARN_ON(disk->minors))
return -EINVAL;
-@@ -432,10 +434,6 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
+@@ -432,10 +435,6 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
disk->flags |= GENHD_FL_EXT_DEVT;
}
@@ -23195,7 +38217,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
/* delay uevents, until we scanned partition table */
dev_set_uevent_suppress(ddev, 1);
-@@ -446,7 +444,12 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
+@@ -446,7 +445,12 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
ddev->devt = MKDEV(disk->major, disk->first_minor);
ret = device_add(ddev);
if (ret)
@@ -23209,7 +38231,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
if (!sysfs_deprecated) {
ret = sysfs_create_link(block_depr, &ddev->kobj,
kobject_name(&ddev->kobj));
-@@ -467,11 +470,15 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
+@@ -467,11 +471,15 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
disk->part0->bd_holder_dir =
kobject_create_and_add("holders", &ddev->kobj);
@@ -23227,7 +38249,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
ret = bd_register_pending_holders(disk);
if (ret < 0)
-@@ -530,8 +537,6 @@ out_del_block_link:
+@@ -530,8 +538,6 @@ out_del_block_link:
sysfs_remove_link(block_depr, dev_name(ddev));
out_device_del:
device_del(ddev);
@@ -23236,7 +38258,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
out_free_ext_minor:
if (disk->major == BLOCK_EXT_MAJOR)
blk_free_ext_minor(disk->first_minor);
-@@ -539,6 +544,20 @@ out_free_ext_minor:
+@@ -539,6 +545,20 @@ out_free_ext_minor:
}
EXPORT_SYMBOL(device_add_disk);
@@ -23257,7 +38279,7 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
/**
* del_gendisk - remove the gendisk
* @disk: the struct gendisk to remove
-@@ -1082,6 +1101,8 @@ static void disk_release(struct device *dev)
+@@ -1082,6 +1102,8 @@ static void disk_release(struct device *dev)
might_sleep();
WARN_ON_ONCE(disk_live(disk));
@@ -23266,8 +38288,19 @@ index ab12ae6e636e8..2dcedbe4ef046 100644
disk_release_events(disk);
kfree(disk->random);
xa_destroy(&disk->part_tbl);
+diff --git a/block/holder.c b/block/holder.c
+index 9dc084182337f..27cddce1b4461 100644
+--- a/block/holder.c
++++ b/block/holder.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ #include <linux/genhd.h>
++#include <linux/slab.h>
+
+ struct bd_holder_disk {
+ struct list_head list;
diff --git a/block/ioctl.c b/block/ioctl.c
-index eb0491e90b9a0..a31be7fa31a51 100644
+index eb0491e90b9a0..cd506a9029630 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -113,6 +113,7 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
@@ -23328,6 +38361,15 @@ index eb0491e90b9a0..a31be7fa31a51 100644
}
static int put_ushort(unsigned short __user *argp, unsigned short val)
+@@ -633,7 +645,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
+ case BLKGETSIZE:
+ size = i_size_read(bdev->bd_inode);
+- if ((size >> 9) > ~0UL)
++ if ((size >> 9) > ~(compat_ulong_t)0)
+ return -EFBIG;
+ return compat_put_ulong(argp, size >> 9);
+
diff --git a/block/ioprio.c b/block/ioprio.c
index 0e4ff245f2bf2..6f01d35a5145a 100644
--- a/block/ioprio.c
@@ -23387,8 +38429,20 @@ index 7f3c3932b723e..cd2342d297048 100644
STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
#undef STORE_FUNCTION
#undef STORE_INT
+diff --git a/block/partitions/core.c b/block/partitions/core.c
+index 7bea19dd9458f..b9e9af84f5188 100644
+--- a/block/partitions/core.c
++++ b/block/partitions/core.c
+@@ -5,6 +5,7 @@
+ * Copyright (C) 2020 Christoph Hellwig
+ */
+ #include <linux/fs.h>
++#include <linux/major.h>
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
+ #include <linux/genhd.h>
diff --git a/crypto/Kconfig b/crypto/Kconfig
-index 536df4b6b825c..285f82647d2b7 100644
+index 536df4b6b825c..55718de561375 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -233,12 +233,12 @@ config CRYPTO_DH
@@ -23405,6 +38459,18 @@ index 536df4b6b825c..285f82647d2b7 100644
help
Generic implementation of the ECDH algorithm
+@@ -1919,9 +1919,10 @@ config CRYPTO_STATS
+ config CRYPTO_HASH_INFO
+ bool
+
+-source "lib/crypto/Kconfig"
+ source "drivers/crypto/Kconfig"
+ source "crypto/asymmetric_keys/Kconfig"
+ source "certs/Kconfig"
+
+ endif # if CRYPTO
++
++source "lib/crypto/Kconfig"
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 43f999dba4dc0..f3d95af3e4284 100644
--- a/crypto/algapi.c
@@ -23423,6 +38489,290 @@ index c4eda56cff891..5ffcd3ab4a753 100644
MODULE_DESCRIPTION("Cryptographic core API");
MODULE_LICENSE("GPL");
-MODULE_SOFTDEP("pre: cryptomgr");
+diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
+index 0b4d07aa88111..f94a1d1ad3a6c 100644
+--- a/crypto/asymmetric_keys/pkcs7_verify.c
++++ b/crypto/asymmetric_keys/pkcs7_verify.c
+@@ -174,12 +174,6 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
+ pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
+ sinfo->index, certix);
+
+- if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) {
+- pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
+- sinfo->index);
+- continue;
+- }
+-
+ sinfo->signer = x509;
+ return 0;
+ }
+diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
+index 4fefb219bfdc8..7c9e6be35c30c 100644
+--- a/crypto/asymmetric_keys/public_key.c
++++ b/crypto/asymmetric_keys/public_key.c
+@@ -60,39 +60,83 @@ static void public_key_destroy(void *payload0, void *payload3)
+ }
+
+ /*
+- * Determine the crypto algorithm name.
++ * Given a public_key, and an encoding and hash_algo to be used for signing
++ * and/or verification with that key, determine the name of the corresponding
++ * akcipher algorithm. Also check that encoding and hash_algo are allowed.
+ */
+-static
+-int software_key_determine_akcipher(const char *encoding,
+- const char *hash_algo,
+- const struct public_key *pkey,
+- char alg_name[CRYPTO_MAX_ALG_NAME])
++static int
++software_key_determine_akcipher(const struct public_key *pkey,
++ const char *encoding, const char *hash_algo,
++ char alg_name[CRYPTO_MAX_ALG_NAME])
+ {
+ int n;
+
+- if (strcmp(encoding, "pkcs1") == 0) {
+- /* The data wangled by the RSA algorithm is typically padded
+- * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
+- * sec 8.2].
++ if (!encoding)
++ return -EINVAL;
++
++ if (strcmp(pkey->pkey_algo, "rsa") == 0) {
++ /*
++ * RSA signatures usually use EMSA-PKCS1-1_5 [RFC3447 sec 8.2].
++ */
++ if (strcmp(encoding, "pkcs1") == 0) {
++ if (!hash_algo)
++ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
++ "pkcs1pad(%s)",
++ pkey->pkey_algo);
++ else
++ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
++ "pkcs1pad(%s,%s)",
++ pkey->pkey_algo, hash_algo);
++ return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
++ }
++ if (strcmp(encoding, "raw") != 0)
++ return -EINVAL;
++ /*
++ * Raw RSA cannot differentiate between different hash
++ * algorithms.
++ */
++ if (hash_algo)
++ return -EINVAL;
++ } else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
++ if (strcmp(encoding, "x962") != 0)
++ return -EINVAL;
++ /*
++ * ECDSA signatures are taken over a raw hash, so they don't
++ * differentiate between different hash algorithms. That means
++ * that the verifier should hard-code a specific hash algorithm.
++ * Unfortunately, in practice ECDSA is used with multiple SHAs,
++ * so we have to allow all of them and not just one.
+ */
+ if (!hash_algo)
+- n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
+- "pkcs1pad(%s)",
+- pkey->pkey_algo);
+- else
+- n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
+- "pkcs1pad(%s,%s)",
+- pkey->pkey_algo, hash_algo);
+- return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
+- }
+-
+- if (strcmp(encoding, "raw") == 0 ||
+- strcmp(encoding, "x962") == 0) {
+- strcpy(alg_name, pkey->pkey_algo);
+- return 0;
++ return -EINVAL;
++ if (strcmp(hash_algo, "sha1") != 0 &&
++ strcmp(hash_algo, "sha224") != 0 &&
++ strcmp(hash_algo, "sha256") != 0 &&
++ strcmp(hash_algo, "sha384") != 0 &&
++ strcmp(hash_algo, "sha512") != 0)
++ return -EINVAL;
++ } else if (strcmp(pkey->pkey_algo, "sm2") == 0) {
++ if (strcmp(encoding, "raw") != 0)
++ return -EINVAL;
++ if (!hash_algo)
++ return -EINVAL;
++ if (strcmp(hash_algo, "sm3") != 0)
++ return -EINVAL;
++ } else if (strcmp(pkey->pkey_algo, "ecrdsa") == 0) {
++ if (strcmp(encoding, "raw") != 0)
++ return -EINVAL;
++ if (!hash_algo)
++ return -EINVAL;
++ if (strcmp(hash_algo, "streebog256") != 0 &&
++ strcmp(hash_algo, "streebog512") != 0)
++ return -EINVAL;
++ } else {
++ /* Unknown public key algorithm */
++ return -ENOPKG;
+ }
+-
+- return -ENOPKG;
++ if (strscpy(alg_name, pkey->pkey_algo, CRYPTO_MAX_ALG_NAME) < 0)
++ return -EINVAL;
++ return 0;
+ }
+
+ static u8 *pkey_pack_u32(u8 *dst, u32 val)
+@@ -113,9 +157,8 @@ static int software_key_query(const struct kernel_pkey_params *params,
+ u8 *key, *ptr;
+ int ret, len;
+
+- ret = software_key_determine_akcipher(params->encoding,
+- params->hash_algo,
+- pkey, alg_name);
++ ret = software_key_determine_akcipher(pkey, params->encoding,
++ params->hash_algo, alg_name);
+ if (ret < 0)
+ return ret;
+
+@@ -179,9 +222,8 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
+
+ pr_devel("==>%s()\n", __func__);
+
+- ret = software_key_determine_akcipher(params->encoding,
+- params->hash_algo,
+- pkey, alg_name);
++ ret = software_key_determine_akcipher(pkey, params->encoding,
++ params->hash_algo, alg_name);
+ if (ret < 0)
+ return ret;
+
+@@ -325,9 +367,23 @@ int public_key_verify_signature(const struct public_key *pkey,
+ BUG_ON(!sig);
+ BUG_ON(!sig->s);
+
+- ret = software_key_determine_akcipher(sig->encoding,
+- sig->hash_algo,
+- pkey, alg_name);
++ /*
++ * If the signature specifies a public key algorithm, it *must* match
++ * the key's actual public key algorithm.
++ *
++ * Small exception: ECDSA signatures don't specify the curve, but ECDSA
++ * keys do. So the strings can mismatch slightly in that case:
++ * "ecdsa-nist-*" for the key, but "ecdsa" for the signature.
++ */
++ if (sig->pkey_algo) {
++ if (strcmp(pkey->pkey_algo, sig->pkey_algo) != 0 &&
++ (strncmp(pkey->pkey_algo, "ecdsa-", 6) != 0 ||
++ strcmp(sig->pkey_algo, "ecdsa") != 0))
++ return -EKEYREJECTED;
++ }
++
++ ret = software_key_determine_akcipher(pkey, sig->encoding,
++ sig->hash_algo, alg_name);
+ if (ret < 0)
+ return ret;
+
+diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
+index 3d45161b271a4..7fd56df8b9194 100644
+--- a/crypto/asymmetric_keys/x509_public_key.c
++++ b/crypto/asymmetric_keys/x509_public_key.c
+@@ -128,12 +128,6 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
+ goto out;
+ }
+
+- ret = -EKEYREJECTED;
+- if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0 &&
+- (strncmp(cert->pub->pkey_algo, "ecdsa-", 6) != 0 ||
+- strcmp(cert->sig->pkey_algo, "ecdsa") != 0))
+- goto out;
+-
+ ret = public_key_verify_signature(cert->pub, cert->sig);
+ if (ret < 0) {
+ if (ret == -ENOPKG) {
+diff --git a/crypto/authenc.c b/crypto/authenc.c
+index 670bf1a01d00e..17f674a7cdff5 100644
+--- a/crypto/authenc.c
++++ b/crypto/authenc.c
+@@ -253,7 +253,7 @@ static int crypto_authenc_decrypt_tail(struct aead_request *req,
+ dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
+
+ skcipher_request_set_tfm(skreq, ctx->enc);
+- skcipher_request_set_callback(skreq, aead_request_flags(req),
++ skcipher_request_set_callback(skreq, flags,
+ req->base.complete, req->base.data);
+ skcipher_request_set_crypt(skreq, src, dst,
+ req->cryptlen - authsize, req->iv);
+diff --git a/crypto/blake2s_generic.c b/crypto/blake2s_generic.c
+index 72fe480f9bd67..5f96a21f87883 100644
+--- a/crypto/blake2s_generic.c
++++ b/crypto/blake2s_generic.c
+@@ -15,12 +15,12 @@
+ static int crypto_blake2s_update_generic(struct shash_desc *desc,
+ const u8 *in, unsigned int inlen)
+ {
+- return crypto_blake2s_update(desc, in, inlen, blake2s_compress_generic);
++ 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, blake2s_compress_generic);
++ return crypto_blake2s_final(desc, out, true);
+ }
+
+ #define BLAKE2S_ALG(name, driver_name, digest_size) \
+diff --git a/crypto/drbg.c b/crypto/drbg.c
+index ea85d4a0fe9e9..03c9ef768c227 100644
+--- a/crypto/drbg.c
++++ b/crypto/drbg.c
+@@ -1491,12 +1491,13 @@ static int drbg_generate_long(struct drbg_state *drbg,
+ return 0;
+ }
+
+-static void drbg_schedule_async_seed(struct random_ready_callback *rdy)
++static int drbg_schedule_async_seed(struct notifier_block *nb, unsigned long action, void *data)
+ {
+- struct drbg_state *drbg = container_of(rdy, struct drbg_state,
++ struct drbg_state *drbg = container_of(nb, struct drbg_state,
+ random_ready);
+
+ schedule_work(&drbg->seed_work);
++ return 0;
+ }
+
+ static int drbg_prepare_hrng(struct drbg_state *drbg)
+@@ -1511,10 +1512,8 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
+
+ INIT_WORK(&drbg->seed_work, drbg_async_seed);
+
+- drbg->random_ready.owner = THIS_MODULE;
+- drbg->random_ready.func = drbg_schedule_async_seed;
+-
+- err = add_random_ready_callback(&drbg->random_ready);
++ drbg->random_ready.notifier_call = drbg_schedule_async_seed;
++ err = register_random_ready_notifier(&drbg->random_ready);
+
+ switch (err) {
+ case 0:
+@@ -1525,7 +1524,7 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
+ fallthrough;
+
+ default:
+- drbg->random_ready.func = NULL;
++ drbg->random_ready.notifier_call = NULL;
+ return err;
+ }
+
+@@ -1629,8 +1628,8 @@ free_everything:
+ */
+ static int drbg_uninstantiate(struct drbg_state *drbg)
+ {
+- if (drbg->random_ready.func) {
+- del_random_ready_callback(&drbg->random_ready);
++ if (drbg->random_ready.notifier_call) {
++ unregister_random_ready_notifier(&drbg->random_ready);
+ cancel_work_sync(&drbg->seed_work);
+ }
+
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index a11b3208760f3..f6d3a84e3c214 100644
--- a/crypto/jitterentropy.c
@@ -23482,6 +38832,49 @@ index d569c7ed6c800..9d10b846ccf73 100644
padata_do_serial(padata);
}
+diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
+index 8ac3e73e8ea65..9d804831c8b3f 100644
+--- a/crypto/rsa-pkcs1pad.c
++++ b/crypto/rsa-pkcs1pad.c
+@@ -476,6 +476,8 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
+ pos++;
+
+ if (digest_info) {
++ if (digest_info->size > dst_len - pos)
++ goto done;
+ if (crypto_memneq(out_buf + pos, digest_info->data,
+ digest_info->size))
+ goto done;
+@@ -495,7 +497,7 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
+ sg_nents_for_len(req->src,
+ req->src_len + req->dst_len),
+ req_ctx->out_buf + ctx->key_size,
+- req->dst_len, ctx->key_size);
++ req->dst_len, req->src_len);
+ /* Do the actual verification step. */
+ if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
+ req->dst_len) != 0)
+@@ -538,7 +540,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
+
+ if (WARN_ON(req->dst) ||
+ WARN_ON(!req->dst_len) ||
+- !ctx->key_size || req->src_len < ctx->key_size)
++ !ctx->key_size || req->src_len != ctx->key_size)
+ return -EINVAL;
+
+ req_ctx->out_buf = kmalloc(ctx->key_size + req->dst_len, GFP_KERNEL);
+@@ -621,6 +623,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
+
+ rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn);
+
++ if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) {
++ err = -EINVAL;
++ goto err_free_inst;
++ }
++
+ err = -ENAMETOOLONG;
+ hash_name = crypto_attr_alg_name(tb[2]);
+ if (IS_ERR(hash_name)) {
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 82b0400985a51..00149657a4bc1 100644
--- a/crypto/tcrypt.c
@@ -23505,6 +38898,15 @@ index 82b0400985a51..00149657a4bc1 100644
}
if (secs) {
+diff --git a/crypto/xts.c b/crypto/xts.c
+index 6c12f30dbdd6d..63c85b9e64e08 100644
+--- a/crypto/xts.c
++++ b/crypto/xts.c
+@@ -466,3 +466,4 @@ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("XTS block cipher mode");
+ MODULE_ALIAS_CRYPTO("xts");
+ MODULE_IMPORT_NS(CRYPTO_INTERNAL);
++MODULE_SOFTDEP("pre: ecb");
diff --git a/drivers/Makefile b/drivers/Makefile
index be5d40ae14882..a110338c860c7 100644
--- a/drivers/Makefile
@@ -23737,6 +39139,20 @@ index 89b12afed564e..ba77598ee43e8 100644
/* Execute the _PTS method (Prepare To Sleep) */
arg_list.count = 1;
+diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
+index 915c2433463d7..e7c30ce06e189 100644
+--- a/drivers/acpi/acpica/nswalk.c
++++ b/drivers/acpi/acpica/nswalk.c
+@@ -169,6 +169,9 @@ acpi_ns_walk_namespace(acpi_object_type type,
+
+ if (start_node == ACPI_ROOT_OBJECT) {
+ start_node = acpi_gbl_root_node;
++ if (!start_node) {
++ return_ACPI_STATUS(AE_NO_NAMESPACE);
++ }
+ }
+
+ /* Null child means "get first node" */
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index e5ba9795ec696..8d7736d2d2699 100644
--- a/drivers/acpi/acpica/utdelete.c
@@ -23749,6 +39165,67 @@ index e5ba9795ec696..8d7736d2d2699 100644
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS,
+diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
+index 19e50fcbf4d6f..598fd19b65fa4 100644
+--- a/drivers/acpi/apei/bert.c
++++ b/drivers/acpi/apei/bert.c
+@@ -29,6 +29,7 @@
+
+ #undef pr_fmt
+ #define pr_fmt(fmt) "BERT: " fmt
++#define ACPI_BERT_PRINT_MAX_LEN 1024
+
+ static int bert_disable;
+
+@@ -58,8 +59,11 @@ static void __init bert_print_all(struct acpi_bert_region *region,
+ }
+
+ pr_info_once("Error records from previous boot:\n");
+-
+- cper_estatus_print(KERN_INFO HW_ERR, estatus);
++ if (region_len < ACPI_BERT_PRINT_MAX_LEN)
++ cper_estatus_print(KERN_INFO HW_ERR, estatus);
++ else
++ pr_info_once("Max print length exceeded, table data is available at:\n"
++ "/sys/firmware/acpi/tables/data/BERT");
+
+ /*
+ * Because the boot error source is "one-time polled" type,
+@@ -77,7 +81,7 @@ static int __init setup_bert_disable(char *str)
+ {
+ bert_disable = 1;
+
+- return 0;
++ return 1;
+ }
+ __setup("bert_disable", setup_bert_disable);
+
+diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
+index 242f3c2d55330..698d67cee0527 100644
+--- a/drivers/acpi/apei/erst.c
++++ b/drivers/acpi/apei/erst.c
+@@ -891,7 +891,7 @@ EXPORT_SYMBOL_GPL(erst_clear);
+ static int __init setup_erst_disable(char *str)
+ {
+ erst_disable = 1;
+- return 0;
++ return 1;
+ }
+
+ __setup("erst_disable", setup_erst_disable);
+diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
+index 277f00b288d14..317bba602ad54 100644
+--- a/drivers/acpi/apei/hest.c
++++ b/drivers/acpi/apei/hest.c
+@@ -223,7 +223,7 @@ err:
+ static int __init setup_hest_disable(char *str)
+ {
+ hest_disable = HEST_DISABLED;
+- return 0;
++ return 1;
+ }
+
+ __setup("hest_disable", setup_hest_disable);
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 3b23fb775ac45..f2f8f05662deb 100644
--- a/drivers/acpi/arm64/iort.c
@@ -23775,10 +39252,10 @@ index 3b23fb775ac45..f2f8f05662deb 100644
if (pmcg->overflow_gsiv)
acpi_iort_register_irq(pmcg->overflow_gsiv, "overflow",
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
-index dae91f906cea9..ead0114f27c9f 100644
+index dae91f906cea9..56db7b4da5140 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
-@@ -53,6 +53,7 @@ static int battery_bix_broken_package;
+@@ -53,12 +53,17 @@ static int battery_bix_broken_package;
static int battery_notification_delay_ms;
static int battery_ac_is_broken;
static int battery_check_pmic = 1;
@@ -23786,7 +39263,17 @@ index dae91f906cea9..ead0114f27c9f 100644
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
-@@ -169,7 +170,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery)
+
+ static const struct acpi_device_id battery_device_ids[] = {
+ {"PNP0C0A", 0},
++
++ /* Microsoft Surface Go 3 */
++ {"MSHW0146", 0},
++
+ {"", 0},
+ };
+
+@@ -169,7 +174,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery)
return 1;
/* fallback to using design values for broken batteries */
@@ -23795,7 +39282,7 @@ index dae91f906cea9..ead0114f27c9f 100644
return 1;
/* we don't do any sort of metric based on percentages */
-@@ -217,6 +218,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
+@@ -217,6 +222,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (acpi_battery_is_charged(battery))
val->intval = POWER_SUPPLY_STATUS_FULL;
@@ -23804,7 +39291,7 @@ index dae91f906cea9..ead0114f27c9f 100644
else
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break;
-@@ -1111,6 +1114,12 @@ battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
+@@ -1111,6 +1118,12 @@ battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
return 0;
}
@@ -23817,7 +39304,7 @@ index dae91f906cea9..ead0114f27c9f 100644
static const struct dmi_system_id bat_dmi_table[] __initconst = {
{
/* NEC LZ750/LS */
-@@ -1155,6 +1164,19 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
+@@ -1155,6 +1168,27 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
},
},
@@ -23834,11 +39321,19 @@ index dae91f906cea9..ead0114f27c9f 100644
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
+ },
+ },
++ {
++ /* Microsoft Surface Go 3 */
++ .callback = battery_notification_delay_quirk,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
++ },
++ },
{},
};
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
-index fa923a9292244..dd535b4b9a160 100644
+index fa923a9292244..3500744e6862e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -98,8 +98,8 @@ int acpi_bus_get_status(struct acpi_device *device)
@@ -23852,8 +39347,49 @@ index fa923a9292244..dd535b4b9a160 100644
return 0;
}
+@@ -332,21 +332,32 @@ static void acpi_bus_osc_negotiate_platform_control(void)
+ if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
+ return;
+
+- kfree(context.ret.pointer);
++ capbuf_ret = context.ret.pointer;
++ if (context.ret.length <= OSC_SUPPORT_DWORD) {
++ kfree(context.ret.pointer);
++ return;
++ }
+
+- /* Now run _OSC again with query flag clear */
++ /*
++ * Now run _OSC again with query flag clear and with the caps
++ * supported by both the OS and the platform.
++ */
+ capbuf[OSC_QUERY_DWORD] = 0;
++ capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD];
++ kfree(context.ret.pointer);
+
+ if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
+ return;
+
+ capbuf_ret = context.ret.pointer;
+- osc_sb_apei_support_acked =
+- capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
+- osc_pc_lpi_support_confirmed =
+- capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
+- osc_sb_native_usb4_support_confirmed =
+- capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT;
++ if (context.ret.length > OSC_SUPPORT_DWORD) {
++ osc_sb_apei_support_acked =
++ capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
++ osc_pc_lpi_support_confirmed =
++ capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
++ osc_sb_native_usb4_support_confirmed =
++ capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT;
++ }
+
+ kfree(context.ret.pointer);
+ }
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
-index bd482108310cf..6fe28a2d387bd 100644
+index bd482108310cf..71b87c16f92da 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -411,7 +411,7 @@ bool acpi_cpc_valid(void)
@@ -23865,7 +39401,19 @@ index bd482108310cf..6fe28a2d387bd 100644
cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
if (!cpc_ptr)
return false;
-@@ -1011,7 +1011,14 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
+@@ -703,6 +703,11 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ cpc_obj = &out_obj->package.elements[0];
+ if (cpc_obj->type == ACPI_TYPE_INTEGER) {
+ num_ent = cpc_obj->integer.value;
++ if (num_ent <= 1) {
++ pr_debug("Unexpected _CPC NumEntries value (%d) for CPU:%d\n",
++ num_ent, pr->id);
++ goto out_free;
++ }
+ } else {
+ pr_debug("Unexpected entry type(%d) for NumEntries\n",
+ cpc_obj->type);
+@@ -1011,7 +1016,14 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
{
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
@@ -24251,21 +39799,84 @@ index f0ed4414edb1f..c95eedd58f5bf 100644
}
out:
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index f37fba9e5ba0b..aedcb92491f2e 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -789,9 +789,11 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
+ state->enter = acpi_idle_enter;
+
+ state->flags = 0;
+- if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) {
++ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 ||
++ cx->type == ACPI_STATE_C3) {
+ state->enter_dead = acpi_idle_play_dead;
+- drv->safe_state_index = count;
++ if (cx->type != ACPI_STATE_C3)
++ drv->safe_state_index = count;
+ }
+ /*
+ * Halt-induced C1 is not good for ->enter_s2idle, because it
+@@ -1075,6 +1077,11 @@ static int flatten_lpi_states(struct acpi_processor *pr,
+ return 0;
+ }
+
++int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
++{
++ return -EOPNOTSUPP;
++}
++
+ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
+ {
+ int ret, i;
+@@ -1083,6 +1090,11 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
+ struct acpi_device *d = NULL;
+ struct acpi_lpi_states_array info[2], *tmp, *prev, *curr;
+
++ /* make sure our architecture has support */
++ ret = acpi_processor_ffh_lpi_probe(pr->id);
++ if (ret == -EOPNOTSUPP)
++ return ret;
++
+ if (!osc_pc_lpi_support_confirmed)
+ return -EOPNOTSUPP;
+
+@@ -1134,11 +1146,6 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
+ return 0;
+ }
+
+-int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
+-{
+- return -ENODEV;
+-}
+-
+ int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
+ {
+ return -ENODEV;
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
-index e312ebaed8db4..781e312f45342 100644
+index e312ebaed8db4..11e4c930a9813 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
+@@ -685,7 +685,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
+ */
+ if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
+ if (index)
+- return -EINVAL;
++ return -ENOENT;
+
+ ret = acpi_bus_get_device(obj->reference.handle, &device);
+ if (ret)
@@ -1090,15 +1090,10 @@ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
/* All data nodes have parent pointer so just return that */
return to_acpi_data_node(fwnode)->parent;
} else if (is_acpi_device_node(fwnode)) {
- acpi_handle handle, parent_handle;
-+ struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
-
+-
- handle = to_acpi_device_node(fwnode)->handle;
- if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) {
- struct acpi_device *adev;
--
++ struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
+
- if (!acpi_bus_get_device(parent_handle, &adev))
- return acpi_fwnode_handle(adev);
- }
@@ -24411,6 +40022,134 @@ index 3023224515abe..7ae09e4b45927 100644
rearm_wake_irq(acpi_sci_irq);
}
+diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
+index 00c0ebaab29f7..6e23b76aef5dc 100644
+--- a/drivers/acpi/sysfs.c
++++ b/drivers/acpi/sysfs.c
+@@ -415,19 +415,30 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
+ loff_t offset, size_t count)
+ {
+ struct acpi_data_attr *data_attr;
+- void *base;
+- ssize_t rc;
++ void __iomem *base;
++ ssize_t size;
+
+ data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
++ size = data_attr->attr.size;
++
++ if (offset < 0)
++ return -EINVAL;
++
++ if (offset >= size)
++ return 0;
+
+- base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
++ if (count > size - offset)
++ count = size - offset;
++
++ base = acpi_os_map_iomem(data_attr->addr, size);
+ if (!base)
+ return -ENOMEM;
+- rc = memory_read_from_buffer(buf, count, &offset, base,
+- data_attr->attr.size);
+- acpi_os_unmap_memory(base, data_attr->attr.size);
+
+- return rc;
++ memcpy_fromio(buf, base + offset, count);
++
++ acpi_os_unmap_iomem(base, size);
++
++ return count;
+ }
+
+ static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 33474fd969913..7b9793cb55c50 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -409,6 +409,81 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
+ },
+ },
++ /*
++ * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a
++ * working native and video interface. However the default detection
++ * mechanism first registers the video interface before unregistering
++ * it again and switching to the native interface during boot. This
++ * results in a dangling SBIOS request for backlight change for some
++ * reason, causing the backlight to switch to ~2% once per boot on the
++ * first power cord connect or disconnect event. Setting the native
++ * interface explicitly circumvents this buggy behaviour, by avoiding
++ * the unregistering process.
++ */
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xRU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xRU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xRU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xRU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
++ DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xRU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
++ DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xNU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xNU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
++ },
++ },
++ {
++ .callback = video_detect_force_native,
++ .ident = "Clevo NL5xNU",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
++ DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
++ },
++ },
+
+ /*
+ * Desktops which falsely report a backlight and which our heuristics
diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index 1c48358b43ba3..e0185e841b2a3 100644
--- a/drivers/acpi/x86/s2idle.c
@@ -25115,7 +40854,7 @@ index 5b3fa2cbe7223..395772fa39432 100644
return rc;
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index eed65311b5d1d..24b67d78cb83d 100644
+index eed65311b5d1d..a0343b7c9addf 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2007,7 +2007,7 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
@@ -25168,7 +40907,17 @@ index eed65311b5d1d..24b67d78cb83d 100644
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
-@@ -4007,6 +4014,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
+@@ -3992,6 +3999,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
++ { "Samsung SSD 840 EVO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
++ ATA_HORKAGE_NO_DMA_LOG |
++ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Samsung SSD 840*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+@@ -4007,6 +4017,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* devices that don't properly handle TRIM commands */
{ "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, },
@@ -25270,6 +41019,36 @@ index f242157bc81bb..9d371859e81ed 100644
total += sr & 0x1FF;
udelay(15);
}
+diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
+index 361597d14c569..d45a75bfc0169 100644
+--- a/drivers/ata/pata_marvell.c
++++ b/drivers/ata/pata_marvell.c
+@@ -83,6 +83,8 @@ static int marvell_cable_detect(struct ata_port *ap)
+ switch(ap->port_no)
+ {
+ case 0:
++ if (!ap->ioaddr.bmdma_addr)
++ return ATA_CBL_PATA_UNK;
+ if (ioread8(ap->ioaddr.bmdma_addr + 1) & 1)
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
+diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
+index 338c2e50f7591..29e2b0dfba309 100644
+--- a/drivers/ata/sata_dwc_460ex.c
++++ b/drivers/ata/sata_dwc_460ex.c
+@@ -145,7 +145,11 @@ struct sata_dwc_device {
+ #endif
+ };
+
+-#define SATA_DWC_QCMD_MAX 32
++/*
++ * Allow one extra special slot for commands and DMA management
++ * to account for libata internal commands.
++ */
++#define SATA_DWC_QCMD_MAX (ATA_MAX_QUEUE + 1)
+
+ struct sata_dwc_device_port {
+ struct sata_dwc_device *hsdev;
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index e5838b23c9e0a..3b31a4f596d86 100644
--- a/drivers/ata/sata_fsl.c
@@ -25322,6 +41101,32 @@ index e5838b23c9e0a..3b31a4f596d86 100644
return 0;
}
+diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
+index 422753d52244b..a31ffe16e626f 100644
+--- a/drivers/atm/eni.c
++++ b/drivers/atm/eni.c
+@@ -1112,6 +1112,8 @@ DPRINTK("iovcnt = %d\n",skb_shinfo(skb)->nr_frags);
+ skb_data3 = skb->data[3];
+ paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
+ DMA_TO_DEVICE);
++ if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
++ return enq_next;
+ ENI_PRV_PADDR(skb) = paddr;
+ /* prepare DMA queue entries */
+ j = 0;
+diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
+index 3bc3c314a467b..4f67404fe64c7 100644
+--- a/drivers/atm/firestream.c
++++ b/drivers/atm/firestream.c
+@@ -1676,6 +1676,8 @@ static int fs_init(struct fs_dev *dev)
+ dev->hw_base = pci_resource_start(pci_dev, 0);
+
+ dev->base = ioremap(dev->hw_base, 0x1000);
++ if (!dev->base)
++ return 1;
+
+ reset_chip (dev);
+
diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 304accde365c8..6c010d4efa4ae 100644
--- a/drivers/auxdisplay/charlcd.c
@@ -25539,6 +41344,19 @@ index 38ba08628ccb3..2578b2d454397 100644
return 0;
}
+diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
+index 43407665918f3..ef4fc89f085d8 100644
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -609,7 +609,7 @@ void update_siblings_masks(unsigned int cpuid)
+ for_each_online_cpu(cpu) {
+ cpu_topo = &cpu_topology[cpu];
+
+- if (cpuid_topo->llc_id == cpu_topo->llc_id) {
++ if (cpu_topo->llc_id != -1 && cpuid_topo->llc_id == cpu_topo->llc_id) {
+ cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
+ cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
+ }
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 5e79299f6c3ff..870485cbbb87c 100644
--- a/drivers/base/component.c
@@ -25595,10 +41413,18 @@ index 249da496581a0..8e73a34e10055 100644
goto out;
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
-index 68ea1f949daa9..6b66306932016 100644
+index 68ea1f949daa9..95ae347df1373 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
-@@ -629,6 +629,9 @@ re_probe:
+@@ -296,6 +296,7 @@ int driver_deferred_probe_check_state(struct device *dev)
+
+ return -EPROBE_DEFER;
+ }
++EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state);
+
+ static void deferred_probe_timeout_work_func(struct work_struct *work)
+ {
+@@ -629,6 +630,9 @@ re_probe:
drv->remove(dev);
devres_release_all(dev);
@@ -25608,7 +41434,16 @@ index 68ea1f949daa9..6b66306932016 100644
driver_sysfs_remove(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
-@@ -1208,6 +1211,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
+@@ -806,7 +810,7 @@ static int __init save_async_options(char *buf)
+ pr_warn("Too long list of driver names for 'driver_async_probe'!\n");
+
+ strlcpy(async_probe_drv_names, buf, ASYNC_DRV_NAMES_MAX_LEN);
+- return 0;
++ return 1;
+ }
+ __setup("driver_async_probe=", save_async_options);
+
+@@ -1208,6 +1212,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
devres_release_all(dev);
arch_teardown_dma_ops(dev);
@@ -25638,7 +41473,7 @@ index 8be352ab4ddbf..fa13ad49d2116 100644
}
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
-index bdbedc6660a87..ef904b8b112e6 100644
+index bdbedc6660a87..04ede46f75123 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -100,12 +100,15 @@ static struct firmware_cache fw_cache;
@@ -25671,8 +41506,85 @@ index bdbedc6660a87..ef904b8b112e6 100644
}
}
+@@ -794,6 +795,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ size_t offset, u32 opt_flags)
+ {
+ struct firmware *fw = NULL;
++ struct cred *kern_cred = NULL;
++ const struct cred *old_cred;
+ bool nondirect = false;
+ int ret;
+
+@@ -810,6 +813,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ if (ret <= 0) /* error or already assigned */
+ goto out;
+
++ /*
++ * We are about to try to access the firmware file. Because we may have been
++ * called by a driver when serving an unrelated request from userland, we use
++ * the kernel credentials to read the file.
++ */
++ kern_cred = prepare_kernel_cred(NULL);
++ if (!kern_cred) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ old_cred = override_creds(kern_cred);
++
+ ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
+
+ /* Only full reads can support decompression, platform, and sysfs. */
+@@ -835,6 +850,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ } else
+ ret = assign_fw(fw, device);
+
++ revert_creds(old_cred);
++ put_cred(kern_cred);
++
+ out:
+ if (ret < 0) {
+ fw_abort_batch_reqs(fw);
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 365cd4a7f2397..60c38f9cf1a75 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -663,14 +663,16 @@ static int init_memory_block(unsigned long block_id, unsigned long state,
+ mem->nr_vmemmap_pages = nr_vmemmap_pages;
+ INIT_LIST_HEAD(&mem->group_next);
+
++ ret = register_memory(mem);
++ if (ret)
++ return ret;
++
+ if (group) {
+ mem->group = group;
+ list_add(&mem->group_next, &group->memory_blocks);
+ }
+
+- ret = register_memory(mem);
+-
+- return ret;
++ return 0;
+ }
+
+ static int add_memory_block(unsigned long base_section_nr)
+diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
+index 5db704f02e712..7e8039d1884cc 100644
+--- a/drivers/base/power/domain.c
++++ b/drivers/base/power/domain.c
+@@ -2058,9 +2058,9 @@ static int genpd_remove(struct generic_pm_domain *genpd)
+ kfree(link);
+ }
+
+- genpd_debug_remove(genpd);
+ list_del(&genpd->gpd_list_node);
+ genpd_unlock(genpd);
++ genpd_debug_remove(genpd);
+ cancel_work_sync(&genpd->power_off_work);
+ if (genpd_is_cpu_domain(genpd))
+ free_cpumask_var(genpd->cpus);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
-index cbea78e79f3df..6bce40e2506e5 100644
+index cbea78e79f3df..8c4819fe73d4c 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -711,6 +711,7 @@ static void dpm_noirq_resume_devices(pm_message_t state)
@@ -25922,6 +41834,26 @@ index cbea78e79f3df..6bce40e2506e5 100644
}
mutex_unlock(&dpm_list_mtx);
trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
+@@ -1991,7 +2022,9 @@ static bool pm_ops_is_empty(const struct dev_pm_ops *ops)
+
+ void device_pm_check_callbacks(struct device *dev)
+ {
+- spin_lock_irq(&dev->power.lock);
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->power.lock, flags);
+ dev->power.no_pm_callbacks =
+ (!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
+ !dev->bus->suspend && !dev->bus->resume)) &&
+@@ -2000,7 +2033,7 @@ void device_pm_check_callbacks(struct device *dev)
+ (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
+ (!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
+ !dev->driver->suspend && !dev->driver->resume));
+- spin_unlock_irq(&dev->power.lock);
++ spin_unlock_irqrestore(&dev->power.lock, flags);
+ }
+
+ bool dev_pm_skip_suspend(struct device *dev)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index ec94049442b99..44ae3909e64bb 100644
--- a/drivers/base/power/runtime.c
@@ -25986,6 +41918,23 @@ index ec94049442b99..44ae3909e64bb 100644
}
static bool pm_runtime_need_not_resume(struct device *dev)
+diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
+index 94665037f4a35..72b7a92337b18 100644
+--- a/drivers/base/power/trace.c
++++ b/drivers/base/power/trace.c
+@@ -120,7 +120,11 @@ static unsigned int read_magic_time(void)
+ struct rtc_time time;
+ unsigned int val;
+
+- mc146818_get_time(&time);
++ if (mc146818_get_time(&time) < 0) {
++ pr_err("Unable to read current time from RTC\n");
++ return 0;
++ }
++
+ pr_info("RTC time: %ptRt, date: %ptRd\n", &time, &time);
+ val = time.tm_year; /* 100 years */
+ if (val > 100)
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 99bda0da23a82..8666590201c9a 100644
--- a/drivers/base/power/wakeup.c
@@ -26141,11 +42090,58 @@ index c46f6a8e14d23..3ba1232ce8451 100644
nargs_prop, sizeof(u32),
&nargs_prop_val, 1);
if (error)
+diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
+index ab3e37aa1830c..f93cb989241cc 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -33,6 +33,22 @@ config BLK_DEV_FD
+ To compile this driver as a module, choose M here: the
+ module will be called floppy.
+
++config BLK_DEV_FD_RAWCMD
++ bool "Support for raw floppy disk commands (DEPRECATED)"
++ depends on BLK_DEV_FD
++ help
++ If you want to use actual physical floppies and expect to do
++ special low-level hardware accesses to them (access and use
++ non-standard formats, for example), then enable this.
++
++ Note that the code enabled by this option is rarely used and
++ might be unstable or insecure, and distros should not enable it.
++
++ Note: FDRAWCMD is deprecated and will be removed from the kernel
++ in the near future.
++
++ If unsure, say N.
++
+ config AMIGA_FLOPPY
+ tristate "Amiga floppy support"
+ depends on AMIGA
+diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
+index 8b1714021498c..1ed557cb5ed23 100644
+--- a/drivers/block/amiflop.c
++++ b/drivers/block/amiflop.c
+@@ -61,6 +61,7 @@
+ #include <linux/hdreg.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/fs.h>
+ #include <linux/blk-mq.h>
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
-index a093644ac39fb..aab48b292a3bb 100644
+index a093644ac39fb..82faaa4581579 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
-@@ -298,6 +298,7 @@ static struct atari_floppy_struct {
+@@ -68,6 +68,7 @@
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/blk-mq.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/completion.h>
+ #include <linux/wait.h>
+@@ -298,6 +299,7 @@ static struct atari_floppy_struct {
disk change detection) */
int flags; /* flags */
struct gendisk *disk[NUM_DISK_MINORS];
@@ -26153,7 +42149,7 @@ index a093644ac39fb..aab48b292a3bb 100644
int ref;
int type;
struct blk_mq_tag_set tag_set;
-@@ -456,10 +457,20 @@ static DEFINE_TIMER(fd_timer, check_change);
+@@ -456,10 +458,20 @@ static DEFINE_TIMER(fd_timer, check_change);
static void fd_end_request_cur(blk_status_t err)
{
@@ -26174,7 +42170,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
}
-@@ -653,9 +664,6 @@ static inline void copy_buffer(void *from, void *to)
+@@ -653,9 +665,6 @@ static inline void copy_buffer(void *from, void *to)
*p2++ = *p1++;
}
@@ -26184,7 +42180,7 @@ index a093644ac39fb..aab48b292a3bb 100644
/* General Interrupt Handling */
static void (*FloppyIRQHandler)( int status ) = NULL;
-@@ -700,12 +708,21 @@ static void fd_error( void )
+@@ -700,12 +709,21 @@ static void fd_error( void )
if (fd_request->error_count >= MAX_ERRORS) {
printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
fd_end_request_cur(BLK_STS_IOERR);
@@ -26206,7 +42202,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
-@@ -732,8 +749,10 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+@@ -732,8 +750,10 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
if (type) {
type--;
if (type >= NUM_DISK_MINORS ||
@@ -26218,7 +42214,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
q = unit[drive].disk[type]->queue;
-@@ -751,6 +770,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+@@ -751,6 +771,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
}
if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
@@ -26226,7 +42222,7 @@ index a093644ac39fb..aab48b292a3bb 100644
ret = -EINVAL;
goto out;
}
-@@ -791,6 +811,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+@@ -791,6 +812,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
wait_for_completion(&format_wait);
@@ -26234,7 +42230,7 @@ index a093644ac39fb..aab48b292a3bb 100644
ret = FormatError ? -EIO : 0;
out:
blk_mq_unquiesce_queue(q);
-@@ -825,6 +846,7 @@ static void do_fd_action( int drive )
+@@ -825,6 +847,7 @@ static void do_fd_action( int drive )
else {
/* all sectors finished */
fd_end_request_cur(BLK_STS_OK);
@@ -26242,7 +42238,7 @@ index a093644ac39fb..aab48b292a3bb 100644
return;
}
}
-@@ -1229,6 +1251,7 @@ static void fd_rwsec_done1(int status)
+@@ -1229,6 +1252,7 @@ static void fd_rwsec_done1(int status)
else {
/* all sectors finished */
fd_end_request_cur(BLK_STS_OK);
@@ -26250,7 +42246,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
return;
-@@ -1350,7 +1373,7 @@ static void fd_times_out(struct timer_list *unused)
+@@ -1350,7 +1374,7 @@ static void fd_times_out(struct timer_list *unused)
static void finish_fdc( void )
{
@@ -26259,7 +42255,7 @@ index a093644ac39fb..aab48b292a3bb 100644
finish_fdc_done( 0 );
}
else {
-@@ -1385,7 +1408,8 @@ static void finish_fdc_done( int dummy )
+@@ -1385,7 +1409,8 @@ static void finish_fdc_done( int dummy )
start_motor_off_timer();
local_irq_save(flags);
@@ -26269,7 +42265,7 @@ index a093644ac39fb..aab48b292a3bb 100644
local_irq_restore(flags);
DPRINT(("finish_fdc() finished\n"));
-@@ -1475,15 +1499,6 @@ static void setup_req_params( int drive )
+@@ -1475,15 +1500,6 @@ static void setup_req_params( int drive )
ReqTrack, ReqSector, (unsigned long)ReqData ));
}
@@ -26285,7 +42281,7 @@ index a093644ac39fb..aab48b292a3bb 100644
static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
-@@ -1491,6 +1506,10 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+@@ -1491,6 +1507,10 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
int drive = floppy - unit;
int type = floppy->type;
@@ -26296,7 +42292,7 @@ index a093644ac39fb..aab48b292a3bb 100644
spin_lock_irq(&ataflop_lock);
if (fd_request) {
spin_unlock_irq(&ataflop_lock);
-@@ -1511,6 +1530,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+@@ -1511,6 +1531,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
/* drive not connected */
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
fd_end_request_cur(BLK_STS_IOERR);
@@ -26304,7 +42300,7 @@ index a093644ac39fb..aab48b292a3bb 100644
goto out;
}
-@@ -1527,11 +1547,13 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+@@ -1527,11 +1548,13 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
if (--type >= NUM_DISK_MINORS) {
printk(KERN_WARNING "fd%d: invalid disk format", drive );
fd_end_request_cur(BLK_STS_IOERR);
@@ -26318,7 +42314,7 @@ index a093644ac39fb..aab48b292a3bb 100644
goto out;
}
type = minor2disktype[type].index;
-@@ -1550,8 +1572,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+@@ -1550,8 +1573,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
setup_req_params( drive );
do_fd_action( drive );
@@ -26327,7 +42323,7 @@ index a093644ac39fb..aab48b292a3bb 100644
atari_enable_irq( IRQ_MFP_FDC );
out:
-@@ -1634,6 +1654,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+@@ -1634,6 +1655,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
/* what if type > 0 here? Overwrite specified entry ? */
if (type) {
/* refuse to re-set a predefined type for now */
@@ -26335,7 +42331,7 @@ index a093644ac39fb..aab48b292a3bb 100644
return -EINVAL;
}
-@@ -1701,8 +1722,10 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+@@ -1701,8 +1723,10 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
/* sanity check */
if (setprm.track != dtp->blocks/dtp->spt/2 ||
@@ -26347,7 +42343,7 @@ index a093644ac39fb..aab48b292a3bb 100644
UDT = dtp;
set_capacity(disk, UDT->blocks);
-@@ -1962,7 +1985,6 @@ static const struct block_device_operations floppy_fops = {
+@@ -1962,7 +1986,6 @@ static const struct block_device_operations floppy_fops = {
static const struct blk_mq_ops ataflop_mq_ops = {
.queue_rq = ataflop_queue_rq,
@@ -26355,7 +42351,7 @@ index a093644ac39fb..aab48b292a3bb 100644
};
static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
-@@ -1986,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
+@@ -1986,8 +2009,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
return 0;
}
@@ -26364,7 +42360,7 @@ index a093644ac39fb..aab48b292a3bb 100644
static void ataflop_probe(dev_t dev)
{
int drive = MINOR(dev) & 3;
-@@ -1998,12 +2018,46 @@ static void ataflop_probe(dev_t dev)
+@@ -1998,12 +2019,46 @@ static void ataflop_probe(dev_t dev)
if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS)
return;
@@ -26414,7 +42410,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
static int __init atari_floppy_init (void)
-@@ -2015,11 +2069,6 @@ static int __init atari_floppy_init (void)
+@@ -2015,11 +2070,6 @@ static int __init atari_floppy_init (void)
/* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
return -ENODEV;
@@ -26426,7 +42422,7 @@ index a093644ac39fb..aab48b292a3bb 100644
for (i = 0; i < FD_MAX_UNITS; i++) {
memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set));
unit[i].tag_set.ops = &ataflop_mq_ops;
-@@ -2065,6 +2114,7 @@ static int __init atari_floppy_init (void)
+@@ -2065,6 +2115,7 @@ static int __init atari_floppy_init (void)
unit[i].track = -1;
unit[i].flags = 0;
add_disk(unit[i].disk[0]);
@@ -26434,7 +42430,7 @@ index a093644ac39fb..aab48b292a3bb 100644
}
printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
-@@ -2072,18 +2122,17 @@ static int __init atari_floppy_init (void)
+@@ -2072,18 +2123,17 @@ static int __init atari_floppy_init (void)
UseTrackbuffer ? "" : "no ");
config_types();
@@ -26461,7 +42457,7 @@ index a093644ac39fb..aab48b292a3bb 100644
return ret;
}
-@@ -2128,22 +2177,8 @@ __setup("floppy=", atari_floppy_setup);
+@@ -2128,22 +2178,8 @@ __setup("floppy=", atari_floppy_setup);
static void __exit atari_floppy_exit(void)
{
@@ -26485,10 +42481,384 @@ index a093644ac39fb..aab48b292a3bb 100644
}
module_init(atari_floppy_init)
+diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
+index 5d9181382ce19..0a5766a2f1618 100644
+--- a/drivers/block/drbd/drbd_int.h
++++ b/drivers/block/drbd/drbd_int.h
+@@ -1642,22 +1642,22 @@ struct sib_info {
+ };
+ void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
+
+-extern void notify_resource_state(struct sk_buff *,
++extern int notify_resource_state(struct sk_buff *,
+ unsigned int,
+ struct drbd_resource *,
+ struct resource_info *,
+ enum drbd_notification_type);
+-extern void notify_device_state(struct sk_buff *,
++extern int notify_device_state(struct sk_buff *,
+ unsigned int,
+ struct drbd_device *,
+ struct device_info *,
+ enum drbd_notification_type);
+-extern void notify_connection_state(struct sk_buff *,
++extern int notify_connection_state(struct sk_buff *,
+ unsigned int,
+ struct drbd_connection *,
+ struct connection_info *,
+ enum drbd_notification_type);
+-extern void notify_peer_device_state(struct sk_buff *,
++extern int notify_peer_device_state(struct sk_buff *,
+ unsigned int,
+ struct drbd_peer_device *,
+ struct peer_device_info *,
+diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
+index 55234a558e98b..6db0333b5b7a1 100644
+--- a/drivers/block/drbd/drbd_main.c
++++ b/drivers/block/drbd/drbd_main.c
+@@ -171,7 +171,7 @@ void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
+ unsigned int set_size)
+ {
+ struct drbd_request *r;
+- struct drbd_request *req = NULL;
++ struct drbd_request *req = NULL, *tmp = NULL;
+ int expect_epoch = 0;
+ int expect_size = 0;
+
+@@ -225,8 +225,11 @@ void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
+ * to catch requests being barrier-acked "unexpectedly".
+ * It usually should find the same req again, or some READ preceding it. */
+ list_for_each_entry(req, &connection->transfer_log, tl_requests)
+- if (req->epoch == expect_epoch)
++ if (req->epoch == expect_epoch) {
++ tmp = req;
+ break;
++ }
++ req = list_prepare_entry(tmp, &connection->transfer_log, tl_requests);
+ list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
+ if (req->epoch != expect_epoch)
+ break;
+@@ -2737,6 +2740,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
+ sprintf(disk->disk_name, "drbd%d", minor);
+ disk->private_data = device;
+
++ blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
+ blk_queue_write_cache(disk->queue, true, true);
+ /* Setting the max_hw_sectors to an odd value of 8kibyte here
+ This triggers a max_bio_size message upon first attach or connect */
+diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
+index 44ccf8b4f4b29..69184cf17b6ad 100644
+--- a/drivers/block/drbd/drbd_nl.c
++++ b/drivers/block/drbd/drbd_nl.c
+@@ -4617,7 +4617,7 @@ static int nla_put_notification_header(struct sk_buff *msg,
+ return drbd_notification_header_to_skb(msg, &nh, true);
+ }
+
+-void notify_resource_state(struct sk_buff *skb,
++int notify_resource_state(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_resource *resource,
+ struct resource_info *resource_info,
+@@ -4659,16 +4659,17 @@ void notify_resource_state(struct sk_buff *skb,
+ if (err && err != -ESRCH)
+ goto failed;
+ }
+- return;
++ return 0;
+
+ nla_put_failure:
+ nlmsg_free(skb);
+ failed:
+ drbd_err(resource, "Error %d while broadcasting event. Event seq:%u\n",
+ err, seq);
++ return err;
+ }
+
+-void notify_device_state(struct sk_buff *skb,
++int notify_device_state(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_device *device,
+ struct device_info *device_info,
+@@ -4708,16 +4709,17 @@ void notify_device_state(struct sk_buff *skb,
+ if (err && err != -ESRCH)
+ goto failed;
+ }
+- return;
++ return 0;
+
+ nla_put_failure:
+ nlmsg_free(skb);
+ failed:
+ drbd_err(device, "Error %d while broadcasting event. Event seq:%u\n",
+ err, seq);
++ return err;
+ }
+
+-void notify_connection_state(struct sk_buff *skb,
++int notify_connection_state(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_connection *connection,
+ struct connection_info *connection_info,
+@@ -4757,16 +4759,17 @@ void notify_connection_state(struct sk_buff *skb,
+ if (err && err != -ESRCH)
+ goto failed;
+ }
+- return;
++ return 0;
+
+ nla_put_failure:
+ nlmsg_free(skb);
+ failed:
+ drbd_err(connection, "Error %d while broadcasting event. Event seq:%u\n",
+ err, seq);
++ return err;
+ }
+
+-void notify_peer_device_state(struct sk_buff *skb,
++int notify_peer_device_state(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_peer_device *peer_device,
+ struct peer_device_info *peer_device_info,
+@@ -4807,13 +4810,14 @@ void notify_peer_device_state(struct sk_buff *skb,
+ if (err && err != -ESRCH)
+ goto failed;
+ }
+- return;
++ return 0;
+
+ nla_put_failure:
+ nlmsg_free(skb);
+ failed:
+ drbd_err(peer_device, "Error %d while broadcasting event. Event seq:%u\n",
+ err, seq);
++ return err;
+ }
+
+ void notify_helper(enum drbd_notification_type type,
+@@ -4864,7 +4868,7 @@ fail:
+ err, seq);
+ }
+
+-static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
++static int notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
+ {
+ struct drbd_genlmsghdr *dh;
+ int err;
+@@ -4878,11 +4882,12 @@ static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
+ if (nla_put_notification_header(skb, NOTIFY_EXISTS))
+ goto nla_put_failure;
+ genlmsg_end(skb, dh);
+- return;
++ return 0;
+
+ nla_put_failure:
+ nlmsg_free(skb);
+ pr_err("Error %d sending event. Event seq:%u\n", err, seq);
++ return err;
+ }
+
+ static void free_state_changes(struct list_head *list)
+@@ -4909,6 +4914,7 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+ unsigned int seq = cb->args[2];
+ unsigned int n;
+ enum drbd_notification_type flags = 0;
++ int err = 0;
+
+ /* There is no need for taking notification_mutex here: it doesn't
+ matter if the initial state events mix with later state chage
+@@ -4917,32 +4923,32 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+
+ cb->args[5]--;
+ if (cb->args[5] == 1) {
+- notify_initial_state_done(skb, seq);
++ err = notify_initial_state_done(skb, seq);
+ goto out;
+ }
+ n = cb->args[4]++;
+ if (cb->args[4] < cb->args[3])
+ flags |= NOTIFY_CONTINUES;
+ if (n < 1) {
+- notify_resource_state_change(skb, seq, state_change->resource,
++ err = notify_resource_state_change(skb, seq, state_change->resource,
+ NOTIFY_EXISTS | flags);
+ goto next;
+ }
+ n--;
+ if (n < state_change->n_connections) {
+- notify_connection_state_change(skb, seq, &state_change->connections[n],
++ err = notify_connection_state_change(skb, seq, &state_change->connections[n],
+ NOTIFY_EXISTS | flags);
+ goto next;
+ }
+ n -= state_change->n_connections;
+ if (n < state_change->n_devices) {
+- notify_device_state_change(skb, seq, &state_change->devices[n],
++ err = notify_device_state_change(skb, seq, &state_change->devices[n],
+ NOTIFY_EXISTS | flags);
+ goto next;
+ }
+ n -= state_change->n_devices;
+ if (n < state_change->n_devices * state_change->n_connections) {
+- notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
++ err = notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
+ NOTIFY_EXISTS | flags);
+ goto next;
+ }
+@@ -4957,7 +4963,10 @@ next:
+ cb->args[4] = 0;
+ }
+ out:
+- return skb->len;
++ if (err)
++ return err;
++ else
++ return skb->len;
+ }
+
+ int drbd_adm_get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
+index 5ca233644d705..47e0d105b462e 100644
+--- a/drivers/block/drbd/drbd_req.c
++++ b/drivers/block/drbd/drbd_req.c
+@@ -180,7 +180,8 @@ void start_new_tl_epoch(struct drbd_connection *connection)
+ void complete_master_bio(struct drbd_device *device,
+ struct bio_and_error *m)
+ {
+- m->bio->bi_status = errno_to_blk_status(m->error);
++ if (unlikely(m->error))
++ m->bio->bi_status = errno_to_blk_status(m->error);
+ bio_endio(m->bio);
+ dec_ap_bio(device);
+ }
+diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
+index b8a27818ab3f8..4ee11aef6672b 100644
+--- a/drivers/block/drbd/drbd_state.c
++++ b/drivers/block/drbd/drbd_state.c
+@@ -1537,7 +1537,7 @@ int drbd_bitmap_io_from_worker(struct drbd_device *device,
+ return rv;
+ }
+
+-void notify_resource_state_change(struct sk_buff *skb,
++int notify_resource_state_change(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_resource_state_change *resource_state_change,
+ enum drbd_notification_type type)
+@@ -1550,10 +1550,10 @@ void notify_resource_state_change(struct sk_buff *skb,
+ .res_susp_fen = resource_state_change->susp_fen[NEW],
+ };
+
+- notify_resource_state(skb, seq, resource, &resource_info, type);
++ return notify_resource_state(skb, seq, resource, &resource_info, type);
+ }
+
+-void notify_connection_state_change(struct sk_buff *skb,
++int notify_connection_state_change(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_connection_state_change *connection_state_change,
+ enum drbd_notification_type type)
+@@ -1564,10 +1564,10 @@ void notify_connection_state_change(struct sk_buff *skb,
+ .conn_role = connection_state_change->peer_role[NEW],
+ };
+
+- notify_connection_state(skb, seq, connection, &connection_info, type);
++ return notify_connection_state(skb, seq, connection, &connection_info, type);
+ }
+
+-void notify_device_state_change(struct sk_buff *skb,
++int notify_device_state_change(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_device_state_change *device_state_change,
+ enum drbd_notification_type type)
+@@ -1577,10 +1577,10 @@ void notify_device_state_change(struct sk_buff *skb,
+ .dev_disk_state = device_state_change->disk_state[NEW],
+ };
+
+- notify_device_state(skb, seq, device, &device_info, type);
++ return notify_device_state(skb, seq, device, &device_info, type);
+ }
+
+-void notify_peer_device_state_change(struct sk_buff *skb,
++int notify_peer_device_state_change(struct sk_buff *skb,
+ unsigned int seq,
+ struct drbd_peer_device_state_change *p,
+ enum drbd_notification_type type)
+@@ -1594,7 +1594,7 @@ void notify_peer_device_state_change(struct sk_buff *skb,
+ .peer_resync_susp_dependency = p->resync_susp_dependency[NEW],
+ };
+
+- notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
++ return notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
+ }
+
+ static void broadcast_state_change(struct drbd_state_change *state_change)
+@@ -1602,7 +1602,7 @@ static void broadcast_state_change(struct drbd_state_change *state_change)
+ struct drbd_resource_state_change *resource_state_change = &state_change->resource[0];
+ bool resource_state_has_changed;
+ unsigned int n_device, n_connection, n_peer_device, n_peer_devices;
+- void (*last_func)(struct sk_buff *, unsigned int, void *,
++ int (*last_func)(struct sk_buff *, unsigned int, void *,
+ enum drbd_notification_type) = NULL;
+ void *last_arg = NULL;
+
+diff --git a/drivers/block/drbd/drbd_state_change.h b/drivers/block/drbd/drbd_state_change.h
+index ba80f612d6abb..d5b0479bc9a66 100644
+--- a/drivers/block/drbd/drbd_state_change.h
++++ b/drivers/block/drbd/drbd_state_change.h
+@@ -44,19 +44,19 @@ extern struct drbd_state_change *remember_old_state(struct drbd_resource *, gfp_
+ extern void copy_old_to_new_state_change(struct drbd_state_change *);
+ extern void forget_state_change(struct drbd_state_change *);
+
+-extern void notify_resource_state_change(struct sk_buff *,
++extern int notify_resource_state_change(struct sk_buff *,
+ unsigned int,
+ struct drbd_resource_state_change *,
+ enum drbd_notification_type type);
+-extern void notify_connection_state_change(struct sk_buff *,
++extern int notify_connection_state_change(struct sk_buff *,
+ unsigned int,
+ struct drbd_connection_state_change *,
+ enum drbd_notification_type type);
+-extern void notify_device_state_change(struct sk_buff *,
++extern int notify_device_state_change(struct sk_buff *,
+ unsigned int,
+ struct drbd_device_state_change *,
+ enum drbd_notification_type type);
+-extern void notify_peer_device_state_change(struct sk_buff *,
++extern int notify_peer_device_state_change(struct sk_buff *,
+ unsigned int,
+ struct drbd_peer_device_state_change *,
+ enum drbd_notification_type type);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
-index fef79ea52e3ed..4a6a74177b3c9 100644
+index fef79ea52e3ed..db0b3e8982fe5 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
+@@ -184,6 +184,7 @@ static int print_unex = 1;
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
++#include <linux/major.h>
+ #include <linux/platform_device.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/mutex.h>
+@@ -508,8 +509,8 @@ static unsigned long fdc_busy;
+ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(command_done);
+
+-/* Errors during formatting are counted here. */
+-static int format_errors;
++/* errors encountered on the current (or last) request */
++static int floppy_errors;
+
+ /* Format request descriptor. */
+ static struct format_descr format_req;
+@@ -529,7 +530,6 @@ static struct format_descr format_req;
+ static char *floppy_track_buffer;
+ static int max_buffer_sectors;
+
+-static int *errors;
+ typedef void (*done_f)(int);
+ static const struct cont_t {
+ void (*interrupt)(void);
@@ -1014,7 +1014,7 @@ static DECLARE_DELAYED_WORK(fd_timer, fd_timer_workfn);
static void cancel_activity(void)
{
@@ -26498,7 +42868,67 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
cancel_work_sync(&floppy_work);
}
-@@ -3080,6 +3080,8 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr)
+@@ -1454,7 +1454,7 @@ static int interpret_errors(void)
+ if (drive_params[current_drive].flags & FTD_MSG)
+ DPRINT("Over/Underrun - retrying\n");
+ bad = 0;
+- } else if (*errors >= drive_params[current_drive].max_errors.reporting) {
++ } else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
+ print_errors();
+ }
+ if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
+@@ -2094,7 +2094,7 @@ static void bad_flp_intr(void)
+ if (!next_valid_format(current_drive))
+ return;
+ }
+- err_count = ++(*errors);
++ err_count = ++floppy_errors;
+ INFBOUND(write_errors[current_drive].badness, err_count);
+ if (err_count > drive_params[current_drive].max_errors.abort)
+ cont->done(0);
+@@ -2240,9 +2240,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
+ return -EINVAL;
+ }
+ format_req = *tmp_format_req;
+- format_errors = 0;
+ cont = &format_cont;
+- errors = &format_errors;
++ floppy_errors = 0;
+ ret = wait_til_done(redo_format, true);
+ if (ret == -EINTR)
+ return -EINTR;
+@@ -2760,10 +2759,11 @@ static int set_next_request(void)
+ current_req = list_first_entry_or_null(&floppy_reqs, struct request,
+ queuelist);
+ if (current_req) {
+- current_req->error_count = 0;
++ floppy_errors = 0;
+ list_del_init(&current_req->queuelist);
++ return 1;
+ }
+- return current_req != NULL;
++ return 0;
+ }
+
+ /* Starts or continues processing request. Will automatically unlock the
+@@ -2822,7 +2822,6 @@ do_request:
+ _floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
+ } else
+ probing = 0;
+- errors = &(current_req->error_count);
+ tmp = make_raw_rw_request();
+ if (tmp < 2) {
+ request_done(tmp);
+@@ -2983,6 +2982,8 @@ static const char *drive_name(int type, int drive)
+ return "(null)";
+ }
+
++#ifdef CONFIG_BLK_DEV_FD_RAWCMD
++
+ /* raw commands */
+ static void raw_cmd_done(int flag)
+ {
+@@ -3080,6 +3081,8 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr)
}
}
@@ -26507,7 +42937,7 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
static int raw_cmd_copyin(int cmd, void __user *param,
struct floppy_raw_cmd **rcmd)
{
-@@ -3107,7 +3109,7 @@ loop:
+@@ -3107,7 +3110,7 @@ loop:
ptr->resultcode = 0;
if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
@@ -26516,7 +42946,69 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
return -EINVAL;
ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length);
fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
-@@ -4478,6 +4480,7 @@ static const struct blk_mq_ops floppy_mq_ops = {
+@@ -3180,6 +3183,35 @@ static int raw_cmd_ioctl(int cmd, void __user *param)
+ return ret;
+ }
+
++static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
++ void __user *param)
++{
++ int ret;
++
++ pr_warn_once("Note: FDRAWCMD is deprecated and will be removed from the kernel in the near future.\n");
++
++ if (type)
++ return -EINVAL;
++ if (lock_fdc(drive))
++ return -EINTR;
++ set_floppy(drive);
++ ret = raw_cmd_ioctl(cmd, param);
++ if (ret == -EINTR)
++ return -EINTR;
++ process_fd_request();
++ return ret;
++}
++
++#else /* CONFIG_BLK_DEV_FD_RAWCMD */
++
++static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
++ void __user *param)
++{
++ return -EOPNOTSUPP;
++}
++
++#endif
++
+ static int invalidate_drive(struct block_device *bdev)
+ {
+ /* invalidate the buffer track to force a reread */
+@@ -3368,7 +3400,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
+ {
+ int drive = (long)bdev->bd_disk->private_data;
+ int type = ITYPE(drive_state[drive].fd_device);
+- int i;
+ int ret;
+ int size;
+ union inparam {
+@@ -3519,16 +3550,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
+ outparam = &write_errors[drive];
+ break;
+ case FDRAWCMD:
+- if (type)
+- return -EINVAL;
+- if (lock_fdc(drive))
+- return -EINTR;
+- set_floppy(drive);
+- i = raw_cmd_ioctl(cmd, (void __user *)param);
+- if (i == -EINTR)
+- return -EINTR;
+- process_fd_request();
+- return i;
++ return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param);
+ case FDTWADDLE:
+ if (lock_fdc(drive))
+ return -EINTR;
+@@ -4478,6 +4500,7 @@ static const struct blk_mq_ops floppy_mq_ops = {
};
static struct platform_device floppy_device[N_DRIVE];
@@ -26524,7 +43016,7 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
static bool floppy_available(int drive)
{
-@@ -4693,6 +4696,8 @@ static int __init do_floppy_init(void)
+@@ -4693,6 +4716,8 @@ static int __init do_floppy_init(void)
if (err)
goto out_remove_drives;
@@ -26533,7 +43025,7 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
device_add_disk(&floppy_device[drive].dev, disks[drive][0],
NULL);
}
-@@ -4703,7 +4708,8 @@ out_remove_drives:
+@@ -4703,7 +4728,8 @@ out_remove_drives:
while (drive--) {
if (floppy_available(drive)) {
del_gendisk(disks[drive][0]);
@@ -26543,7 +43035,7 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
}
}
out_release_dma:
-@@ -4946,7 +4952,8 @@ static void __exit floppy_module_exit(void)
+@@ -4946,7 +4972,8 @@ static void __exit floppy_module_exit(void)
if (disks[drive][i])
del_gendisk(disks[drive][i]);
}
@@ -26554,7 +43046,7 @@ index fef79ea52e3ed..4a6a74177b3c9 100644
for (i = 0; i < ARRAY_SIZE(floppy_type); i++) {
if (disks[drive][i])
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index 7bf4686af774e..92f9d32bfae5e 100644
+index 7bf4686af774e..8cba10aafadb3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -79,6 +79,7 @@
@@ -26585,6 +43077,45 @@ index 7bf4686af774e..92f9d32bfae5e 100644
/**
* loop_set_size() - sets device size and notifies userspace
* @lo: struct loop_device to set the size for
+@@ -856,33 +844,33 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
+
+ static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf)
+ {
+- return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset);
++ return sysfs_emit(buf, "%llu\n", (unsigned long long)lo->lo_offset);
+ }
+
+ static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf)
+ {
+- return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
++ return sysfs_emit(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
+ }
+
+ static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
+ {
+ int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR);
+
+- return sprintf(buf, "%s\n", autoclear ? "1" : "0");
++ return sysfs_emit(buf, "%s\n", autoclear ? "1" : "0");
+ }
+
+ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
+ {
+ int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN);
+
+- return sprintf(buf, "%s\n", partscan ? "1" : "0");
++ return sysfs_emit(buf, "%s\n", partscan ? "1" : "0");
+ }
+
+ static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
+ {
+ int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
+
+- return sprintf(buf, "%s\n", dio ? "1" : "0");
++ return sysfs_emit(buf, "%s\n", dio ? "1" : "0");
+ }
+
+ LOOP_ATTR_RO(backing_file);
@@ -952,8 +940,13 @@ static void loop_config_discard(struct loop_device *lo)
granularity = 0;
@@ -26640,8 +43171,21 @@ index 901855717cb53..ba61e72741eab 100644
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
/* Clean up the block layer. */
+diff --git a/drivers/block/n64cart.c b/drivers/block/n64cart.c
+index 26798da661bd4..bcaabf038947c 100644
+--- a/drivers/block/n64cart.c
++++ b/drivers/block/n64cart.c
+@@ -88,7 +88,7 @@ static blk_qc_t n64cart_submit_bio(struct bio *bio)
+ {
+ struct bio_vec bvec;
+ struct bvec_iter iter;
+- struct device *dev = bio->bi_disk->private_data;
++ struct device *dev = bio->bi_bdev->bd_disk->private_data;
+ u32 pos = bio->bi_iter.bi_sector << SECTOR_SHIFT;
+
+ bio_for_each_segment(bvec, bio, iter) {
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
-index 1183f7872b713..577c7dba5d78d 100644
+index 1183f7872b713..582b23befb5c4 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -122,10 +122,10 @@ struct nbd_device {
@@ -26665,6 +43209,15 @@ index 1183f7872b713..577c7dba5d78d 100644
}
static const struct device_attribute pid_attr = {
+@@ -254,7 +254,7 @@ static void nbd_dev_remove(struct nbd_device *nbd)
+ mutex_lock(&nbd_index_mutex);
+ idr_remove(&nbd_index_idr, nbd->index);
+ mutex_unlock(&nbd_index_mutex);
+-
++ destroy_workqueue(nbd->recv_workq);
+ kfree(nbd);
+ }
+
@@ -329,7 +329,7 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize,
nbd->config->bytesize = bytesize;
nbd->config->blksize_bits = __ffs(blksize);
@@ -26683,7 +43236,18 @@ index 1183f7872b713..577c7dba5d78d 100644
if (test_and_clear_bit(NBD_RT_HAS_BACKEND_FILE,
&config->runtime_flags)) {
device_remove_file(disk_to_dev(nbd->disk), &backend_attr);
-@@ -1282,7 +1282,7 @@ static int nbd_start_device(struct nbd_device *nbd)
+@@ -1260,10 +1260,6 @@ static void nbd_config_put(struct nbd_device *nbd)
+ kfree(nbd->config);
+ nbd->config = NULL;
+
+- if (nbd->recv_workq)
+- destroy_workqueue(nbd->recv_workq);
+- nbd->recv_workq = NULL;
+-
+ nbd->tag_set.timeout = 0;
+ nbd->disk->queue->limits.discard_granularity = 0;
+ nbd->disk->queue->limits.discard_alignment = 0;
+@@ -1282,7 +1278,7 @@ static int nbd_start_device(struct nbd_device *nbd)
int num_connections = config->num_connections;
int error = 0, i;
@@ -26692,16 +43256,25 @@ index 1183f7872b713..577c7dba5d78d 100644
return -EBUSY;
if (!config->socks)
return -EINVAL;
-@@ -1301,7 +1301,7 @@ static int nbd_start_device(struct nbd_device *nbd)
+@@ -1292,16 +1288,8 @@ static int nbd_start_device(struct nbd_device *nbd)
+ return -EINVAL;
}
+- nbd->recv_workq = alloc_workqueue("knbd%d-recv",
+- WQ_MEM_RECLAIM | WQ_HIGHPRI |
+- WQ_UNBOUND, 0, nbd->index);
+- if (!nbd->recv_workq) {
+- dev_err(disk_to_dev(nbd->disk), "Could not allocate knbd recv work queue.\n");
+- return -ENOMEM;
+- }
+-
blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections);
- nbd->task_recv = current;
+ nbd->pid = task_pid_nr(current);
nbd_parse_flags(nbd);
-@@ -1557,8 +1557,8 @@ static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
+@@ -1557,8 +1545,8 @@ static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
{
struct nbd_device *nbd = s->private;
@@ -26712,7 +43285,23 @@ index 1183f7872b713..577c7dba5d78d 100644
return 0;
}
-@@ -1749,11 +1749,11 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
+@@ -1725,6 +1713,15 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
+ }
+ nbd->disk = disk;
+
++ nbd->recv_workq = alloc_workqueue("nbd%d-recv",
++ WQ_MEM_RECLAIM | WQ_HIGHPRI |
++ WQ_UNBOUND, 0, nbd->index);
++ if (!nbd->recv_workq) {
++ dev_err(disk_to_dev(nbd->disk), "Could not allocate knbd recv work queue.\n");
++ err = -ENOMEM;
++ goto out_err_disk;
++ }
++
+ /*
+ * Tell the block layer that we are not a rotational device
+ */
+@@ -1749,20 +1746,22 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
disk->major = NBD_MAJOR;
/* Too big first_minor can cause duplicate creation of
@@ -26725,8 +43314,48 @@ index 1183f7872b713..577c7dba5d78d 100644
- if (disk->first_minor > 0xff) {
+ if (disk->first_minor < index || disk->first_minor > MINORMASK) {
err = -EINVAL;
- goto out_free_idr;
+- goto out_free_idr;
++ goto out_free_work;
}
+
+ disk->minors = 1 << part_shift;
+ disk->fops = &nbd_fops;
+ disk->private_data = nbd;
+ sprintf(disk->disk_name, "nbd%d", index);
+- add_disk(disk);
++ err = add_disk(disk);
++ if (err)
++ goto out_free_work;
+
+ /*
+ * Now publish the device.
+@@ -1771,6 +1770,10 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
+ nbd_total_devices++;
+ return nbd;
+
++out_free_work:
++ destroy_workqueue(nbd->recv_workq);
++out_err_disk:
++ blk_cleanup_disk(disk);
+ out_free_idr:
+ mutex_lock(&nbd_index_mutex);
+ idr_remove(&nbd_index_idr, index);
+@@ -2024,13 +2027,10 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
+ nbd_disconnect(nbd);
+ sock_shutdown(nbd);
+ /*
+- * Make sure recv thread has finished, so it does not drop the last
+- * config ref and try to destroy the workqueue from inside the work
+- * queue. And this also ensure that we can safely call nbd_clear_que()
++ * Make sure recv thread has finished, we can safely call nbd_clear_que()
+ * to cancel the inflight I/Os.
+ */
+- if (nbd->recv_workq)
+- flush_workqueue(nbd->recv_workq);
++ flush_workqueue(nbd->recv_workq);
+ nbd_clear_que(nbd);
+ nbd->task_setup = NULL;
+ mutex_unlock(&nbd->config_lock);
@@ -2135,7 +2135,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
mutex_lock(&nbd->config_lock);
config = nbd->config;
@@ -26749,11 +43378,73 @@ index e65c9d706f6fb..c4a52f33604dc 100644
}
del_gendisk(rbd_dev->disk);
+diff --git a/drivers/block/swim.c b/drivers/block/swim.c
+index 7ccc8d2a41bc6..3911d0833e1b9 100644
+--- a/drivers/block/swim.c
++++ b/drivers/block/swim.c
+@@ -16,6 +16,7 @@
+ #include <linux/fd.h>
+ #include <linux/slab.h>
+ #include <linux/blk-mq.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/hdreg.h>
+ #include <linux/kernel.h>
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 303caf2d17d0c..c0b8a26892a51 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -815,9 +815,17 @@ static int virtblk_probe(struct virtio_device *vdev)
+ err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
+ struct virtio_blk_config, blk_size,
+ &blk_size);
+- if (!err)
++ if (!err) {
++ err = blk_validate_block_size(blk_size);
++ if (err) {
++ dev_err(&vdev->dev,
++ "virtio_blk: invalid block size: 0x%x\n",
++ blk_size);
++ goto out_cleanup_disk;
++ }
++
+ blk_queue_logical_block_size(q, blk_size);
+- else
++ } else
+ blk_size = queue_logical_block_size(q);
+
+ /* Use topology information if available */
+@@ -859,9 +867,15 @@ static int virtblk_probe(struct virtio_device *vdev)
+
+ virtio_cread(vdev, struct virtio_blk_config, max_discard_seg,
+ &v);
++
++ /*
++ * max_discard_seg == 0 is out of spec but we always
++ * handled it.
++ */
++ if (!v)
++ v = sg_elems - 2;
+ blk_queue_max_discard_segments(q,
+- min_not_zero(v,
+- MAX_DISCARD_SEGMENTS));
++ min(v, MAX_DISCARD_SEGMENTS));
+
+ blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+ }
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
-index 72902104f1112..1becbbb3be139 100644
+index 72902104f1112..390817cf12212 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
-@@ -1290,7 +1290,8 @@ free_shadow:
+@@ -42,6 +42,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/scatterlist.h>
+ #include <linux/bitmap.h>
+@@ -1290,7 +1291,8 @@ free_shadow:
rinfo->ring_ref[i] = GRANT_INVALID_REF;
}
}
@@ -26763,7 +43454,7 @@ index 72902104f1112..1becbbb3be139 100644
rinfo->ring.sring = NULL;
if (rinfo->irq)
-@@ -1374,9 +1375,15 @@ static int blkif_get_final_status(enum blk_req_status s1,
+@@ -1374,9 +1376,15 @@ static int blkif_get_final_status(enum blk_req_status s1,
return BLKIF_RSP_OKAY;
}
@@ -26782,7 +43473,7 @@ index 72902104f1112..1becbbb3be139 100644
{
int i = 0;
struct scatterlist *sg;
-@@ -1399,7 +1406,7 @@ static bool blkif_completion(unsigned long *id,
+@@ -1399,7 +1407,7 @@ static bool blkif_completion(unsigned long *id,
/* Wait the second response if not yet here. */
if (s2->status < REQ_DONE)
@@ -26791,7 +43482,7 @@ index 72902104f1112..1becbbb3be139 100644
bret->status = blkif_get_final_status(s->status,
s2->status);
-@@ -1450,42 +1457,43 @@ static bool blkif_completion(unsigned long *id,
+@@ -1450,42 +1458,43 @@ static bool blkif_completion(unsigned long *id,
}
/* Add the persistent grant into the list of free grants */
for (i = 0; i < num_grant; i++) {
@@ -26849,7 +43540,7 @@ index 72902104f1112..1becbbb3be139 100644
/*
* Add the used indirect page back to the list of
* available pages for indirect grefs.
-@@ -1500,7 +1508,7 @@ static bool blkif_completion(unsigned long *id,
+@@ -1500,7 +1509,7 @@ static bool blkif_completion(unsigned long *id,
}
}
@@ -26858,7 +43549,7 @@ index 72902104f1112..1becbbb3be139 100644
}
static irqreturn_t blkif_interrupt(int irq, void *dev_id)
-@@ -1511,9 +1519,12 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+@@ -1511,9 +1520,12 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
unsigned long flags;
struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
struct blkfront_info *info = rinfo->dev_info;
@@ -26872,7 +43563,7 @@ index 72902104f1112..1becbbb3be139 100644
spin_lock_irqsave(&rinfo->ring_lock, flags);
again:
-@@ -1529,6 +1540,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+@@ -1529,6 +1541,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
unsigned long id;
unsigned int op;
@@ -26881,7 +43572,7 @@ index 72902104f1112..1becbbb3be139 100644
RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
id = bret.id;
-@@ -1561,12 +1574,17 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+@@ -1561,12 +1575,17 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
}
if (bret.operation != BLKIF_OP_DISCARD) {
@@ -26900,7 +43591,7 @@ index 72902104f1112..1becbbb3be139 100644
}
if (add_id_to_freelist(rinfo, id)) {
-@@ -1645,6 +1663,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+@@ -1645,6 +1664,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
@@ -26909,7 +43600,7 @@ index 72902104f1112..1becbbb3be139 100644
return IRQ_HANDLED;
err:
-@@ -1652,6 +1672,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+@@ -1652,6 +1673,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
@@ -26918,7 +43609,7 @@ index 72902104f1112..1becbbb3be139 100644
pr_alert("%s disabled for further use\n", info->gd->disk_name);
return IRQ_HANDLED;
}
-@@ -1669,8 +1691,7 @@ static int setup_blkring(struct xenbus_device *dev,
+@@ -1669,8 +1692,7 @@ static int setup_blkring(struct xenbus_device *dev,
for (i = 0; i < info->nr_ring_pages; i++)
rinfo->ring_ref[i] = GRANT_INVALID_REF;
@@ -26928,7 +43619,7 @@ index 72902104f1112..1becbbb3be139 100644
if (!sring) {
xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
return -ENOMEM;
-@@ -1680,7 +1701,7 @@ static int setup_blkring(struct xenbus_device *dev,
+@@ -1680,7 +1702,7 @@ static int setup_blkring(struct xenbus_device *dev,
err = xenbus_grant_ring(dev, rinfo->ring.sring, info->nr_ring_pages, gref);
if (err < 0) {
@@ -26937,7 +43628,7 @@ index 72902104f1112..1becbbb3be139 100644
rinfo->ring.sring = NULL;
goto fail;
}
-@@ -1691,8 +1712,8 @@ static int setup_blkring(struct xenbus_device *dev,
+@@ -1691,8 +1713,8 @@ static int setup_blkring(struct xenbus_device *dev,
if (err)
goto fail;
@@ -26948,7 +43639,7 @@ index 72902104f1112..1becbbb3be139 100644
if (err <= 0) {
xenbus_dev_fatal(dev, err,
"bind_evtchn_to_irqhandler failed");
-@@ -2119,7 +2140,7 @@ static void blkfront_closing(struct blkfront_info *info)
+@@ -2119,7 +2141,7 @@ static void blkfront_closing(struct blkfront_info *info)
/* No more blkif_request(). */
blk_mq_stop_hw_queues(info->rq);
@@ -26957,7 +43648,7 @@ index 72902104f1112..1becbbb3be139 100644
set_capacity(info->gd, 0);
for_each_rinfo(info, rinfo, i) {
-@@ -2520,11 +2541,10 @@ static void purge_persistent_grants(struct blkfront_info *info)
+@@ -2520,11 +2542,10 @@ static void purge_persistent_grants(struct blkfront_info *info)
list_for_each_entry_safe(gnt_list_entry, tmp, &rinfo->grants,
node) {
if (gnt_list_entry->gref == GRANT_INVALID_REF ||
@@ -27074,7 +43765,7 @@ index e4182acee488c..d9ceca7a7935c 100644
}
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
-index f1705b46fc889..e73d4c719b0ad 100644
+index f1705b46fc889..d122cc9739175 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -2193,8 +2193,15 @@ static int btintel_setup_combined(struct hci_dev *hdev)
@@ -27094,7 +43785,22 @@ index f1705b46fc889..e73d4c719b0ad 100644
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
-@@ -2263,12 +2270,6 @@ static int btintel_setup_combined(struct hci_dev *hdev)
+@@ -2256,19 +2263,18 @@ static int btintel_setup_combined(struct hci_dev *hdev)
+
+ /* Apply the device specific HCI quirks
+ *
+- * WBS for SdP - SdP and Stp have a same hw_varaint but
+- * different fw_variant
++ * WBS for SdP - For the Legacy ROM products, only SdP
++ * supports the WBS. But the version information is not
++ * enough to use here because the StP2 and SdP have same
++ * hw_variant and fw_variant. So, this flag is set by
++ * the transport driver (btusb) based on the HW info
++ * (idProduct)
+ */
+- if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22)
++ if (!btintel_test_flag(hdev,
++ INTEL_ROM_LEGACY_NO_WBS_SUPPORT))
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
&hdev->quirks);
@@ -27107,7 +43813,7 @@ index f1705b46fc889..e73d4c719b0ad 100644
err = btintel_legacy_rom_setup(hdev, &ver);
break;
case 0x0b: /* SfP */
-@@ -2329,10 +2330,14 @@ static int btintel_setup_combined(struct hci_dev *hdev)
+@@ -2329,10 +2335,14 @@ static int btintel_setup_combined(struct hci_dev *hdev)
case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* CcP */
@@ -27126,7 +43832,7 @@ index f1705b46fc889..e73d4c719b0ad 100644
*
* Also, it is not easy to convert TLV based version from the
* legacy version format.
-@@ -2344,6 +2349,20 @@ static int btintel_setup_combined(struct hci_dev *hdev)
+@@ -2344,6 +2354,20 @@ static int btintel_setup_combined(struct hci_dev *hdev)
err = btintel_read_version(hdev, &ver);
if (err)
return err;
@@ -27147,7 +43853,7 @@ index f1705b46fc889..e73d4c719b0ad 100644
err = btintel_bootloader_setup(hdev, &ver);
break;
case 0x17:
-@@ -2399,9 +2418,10 @@ static int btintel_shutdown_combined(struct hci_dev *hdev)
+@@ -2399,9 +2423,10 @@ static int btintel_shutdown_combined(struct hci_dev *hdev)
/* Some platforms have an issue with BT LED when the interface is
* down or BT radio is turned off, which takes 5 seconds to BT LED
@@ -27161,22 +43867,42 @@ index f1705b46fc889..e73d4c719b0ad 100644
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
-index aa64072bbe68d..704e3b7bcb77c 100644
+index aa64072bbe68d..2b85ebf633211 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
-@@ -145,7 +145,7 @@ enum {
+@@ -145,8 +145,9 @@ enum {
INTEL_FIRMWARE_FAILED,
INTEL_BOOTING,
INTEL_BROKEN_INITIAL_NCMD,
- INTEL_BROKEN_LED,
+ INTEL_BROKEN_SHUTDOWN_LED,
INTEL_ROM_LEGACY,
++ INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
__INTEL_NUM_FLAGS,
+ };
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
-index 9872ef18f9fea..1cbdeca1fdc4a 100644
+index 9872ef18f9fea..ff1f5dfbb6dbf 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
+@@ -981,6 +981,8 @@ static int btmtksdio_probe(struct sdio_func *func,
+ hdev->manufacturer = 70;
+ set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+
++ sdio_set_drvdata(func, bdev);
++
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ dev_err(&func->dev, "Can't register HCI device\n");
+@@ -988,8 +990,6 @@ static int btmtksdio_probe(struct sdio_func *func,
+ return err;
+ }
+
+- sdio_set_drvdata(func, bdev);
+-
+ /* pm_runtime_enable would be done after the firmware is being
+ * downloaded because the core layer probably already enables
+ * runtime PM for this func such as the case host->caps &
@@ -1042,6 +1042,8 @@ static int btmtksdio_runtime_suspend(struct device *dev)
if (!bdev)
return 0;
@@ -27230,18 +43956,20 @@ index e9d91d7c0db48..9ba22b13b4fa0 100644
/* Parse and handle the return WMT event */
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index 60d2fce59a71d..ac90392cce339 100644
+index 60d2fce59a71d..a68edbc7be0ff 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
-@@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
+@@ -59,7 +59,9 @@ static struct usb_driver btusb_driver;
#define BTUSB_WIDEBAND_SPEECH 0x400000
#define BTUSB_VALID_LE_STATES 0x800000
#define BTUSB_QCA_WCN6855 0x1000000
+#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED 0x2000000
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000
++#define BTUSB_INTEL_NO_WBS_SUPPORT 0x8000000
static const struct usb_device_id btusb_table[] = {
-@@ -295,6 +296,24 @@ static const struct usb_device_id blacklist_table[] = {
+ /* Generic Bluetooth USB device */
+@@ -295,6 +297,24 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
@@ -27266,15 +43994,17 @@ index 60d2fce59a71d..ac90392cce339 100644
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
-@@ -365,10 +384,13 @@ static const struct usb_device_id blacklist_table[] = {
+@@ -365,10 +385,15 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
- BTUSB_INTEL_BROKEN_INITIAL_NCMD },
- { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED },
++ BTUSB_INTEL_NO_WBS_SUPPORT |
+ BTUSB_INTEL_BROKEN_INITIAL_NCMD |
+ BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
+ { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED |
++ BTUSB_INTEL_NO_WBS_SUPPORT |
+ BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED },
- { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED },
@@ -27283,8 +44013,12 @@ index 60d2fce59a71d..ac90392cce339 100644
{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED },
/* Other Intel Bluetooth devices */
-@@ -384,6 +406,14 @@ static const struct usb_device_id blacklist_table[] = {
+@@ -382,8 +407,18 @@ static const struct usb_device_id blacklist_table[] = {
+ BTUSB_WIDEBAND_SPEECH },
+
/* Realtek 8852AE Bluetooth devices */
++ { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
++ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
@@ -27298,7 +44032,7 @@ index 60d2fce59a71d..ac90392cce339 100644
/* Realtek Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
-@@ -410,10 +440,21 @@ static const struct usb_device_id blacklist_table[] = {
+@@ -410,10 +445,21 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
@@ -27320,7 +44054,7 @@ index 60d2fce59a71d..ac90392cce339 100644
/* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
-@@ -433,6 +474,10 @@ static const struct usb_device_id blacklist_table[] = {
+@@ -433,9 +479,15 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
@@ -27331,7 +44065,12 @@ index 60d2fce59a71d..ac90392cce339 100644
/* Additional Realtek 8761BU Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
-@@ -451,10 +496,6 @@ static const struct usb_device_id blacklist_table[] = {
++ { USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
++ BTUSB_WIDEBAND_SPEECH },
+
+ /* Additional Realtek 8821AE Bluetooth devices */
+ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
+@@ -451,10 +503,6 @@ static const struct usb_device_id blacklist_table[] = {
/* Additional Realtek 8822CE Bluetooth devices */
{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@@ -27342,7 +44081,7 @@ index 60d2fce59a71d..ac90392cce339 100644
{ USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK |
-@@ -2217,6 +2258,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
+@@ -2217,6 +2265,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
if (!skb) {
hdev->stat.err_rx++;
@@ -27350,7 +44089,7 @@ index 60d2fce59a71d..ac90392cce339 100644
return;
}
-@@ -2237,6 +2279,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
+@@ -2237,6 +2286,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
data->evt_skb = skb_clone(skb, GFP_ATOMIC);
if (!data->evt_skb) {
kfree_skb(skb);
@@ -27358,7 +44097,7 @@ index 60d2fce59a71d..ac90392cce339 100644
return;
}
}
-@@ -2245,6 +2288,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
+@@ -2245,6 +2295,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
if (err < 0) {
kfree_skb(data->evt_skb);
data->evt_skb = NULL;
@@ -27366,7 +44105,7 @@ index 60d2fce59a71d..ac90392cce339 100644
return;
}
-@@ -2255,6 +2299,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
+@@ -2255,6 +2306,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
wake_up_bit(&data->flags,
BTUSB_TX_WAIT_VND_EVT);
}
@@ -27374,7 +44113,7 @@ index 60d2fce59a71d..ac90392cce339 100644
return;
} else if (urb->status == -ENOENT) {
/* Avoid suspend failed when usb_kill_urb */
-@@ -2275,6 +2320,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
+@@ -2275,6 +2327,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
usb_anchor_urb(urb, &data->ctrl_anchor);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
@@ -27382,7 +44121,7 @@ index 60d2fce59a71d..ac90392cce339 100644
/* -EPERM: urb is being killed;
* -ENODEV: device got disconnected
*/
-@@ -2515,6 +2561,7 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
+@@ -2515,6 +2568,7 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
} else {
bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)",
status);
@@ -27390,7 +44129,7 @@ index 60d2fce59a71d..ac90392cce339 100644
goto err_release_fw;
}
}
-@@ -2804,11 +2851,16 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
+@@ -2804,11 +2858,16 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
case 0x7668:
fwname = FIRMWARE_MT7668;
break;
@@ -27407,7 +44146,7 @@ index 60d2fce59a71d..ac90392cce339 100644
/* It's Device EndPoint Reset Option Register */
btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
-@@ -2828,6 +2880,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
+@@ -2828,6 +2887,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
}
hci_set_msft_opcode(hdev, 0xFD30);
@@ -27415,8 +44154,13 @@ index 60d2fce59a71d..ac90392cce339 100644
goto done;
default:
bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
-@@ -3808,6 +3861,9 @@ static int btusb_probe(struct usb_interface *intf,
+@@ -3806,8 +3866,14 @@ static int btusb_probe(struct usb_interface *intf,
+ hdev->send = btusb_send_frame_intel;
+ hdev->cmd_timeout = btusb_intel_cmd_timeout;
++ if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT)
++ btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT);
++
if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD)
btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
+
@@ -27444,7 +44188,7 @@ index ef54afa293574..7abf99f0ee399 100644
/* Initialize routing field to an unused value */
dev->pcm_int_params[0] = 0xff;
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
-index 0c0dedece59c5..d49a39d17d7dc 100644
+index 0c0dedece59c5..e0ea9d25bb393 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -587,9 +587,11 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
@@ -27462,7 +44206,22 @@ index 0c0dedece59c5..d49a39d17d7dc 100644
return 0;
}
-@@ -846,6 +848,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
+@@ -627,9 +629,11 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+ break;
+ }
+
+- pm_runtime_get_sync(&hu->serdev->dev);
+- pm_runtime_mark_last_busy(&hu->serdev->dev);
+- pm_runtime_put_autosuspend(&hu->serdev->dev);
++ if (hu->serdev) {
++ pm_runtime_get_sync(&hu->serdev->dev);
++ pm_runtime_mark_last_busy(&hu->serdev->dev);
++ pm_runtime_put_autosuspend(&hu->serdev->dev);
++ }
+
+ return 0;
+ }
+@@ -846,6 +850,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
h5->vnd = data->vnd;
}
@@ -27471,7 +44230,7 @@ index 0c0dedece59c5..d49a39d17d7dc 100644
h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(h5->enable_gpio))
-@@ -860,9 +864,6 @@ static int h5_serdev_probe(struct serdev_device *serdev)
+@@ -860,9 +866,6 @@ static int h5_serdev_probe(struct serdev_device *serdev)
if (err)
return err;
@@ -27481,7 +44240,7 @@ index 0c0dedece59c5..d49a39d17d7dc 100644
return 0;
}
-@@ -962,11 +963,13 @@ static void h5_btrtl_open(struct h5 *h5)
+@@ -962,11 +965,13 @@ static void h5_btrtl_open(struct h5 *h5)
serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN);
serdev_device_set_baudrate(h5->hu->serdev, 115200);
@@ -27500,7 +44259,7 @@ index 0c0dedece59c5..d49a39d17d7dc 100644
/* The controller needs up to 500ms to wakeup */
gpiod_set_value_cansleep(h5->enable_gpio, 1);
-@@ -976,7 +979,8 @@ static void h5_btrtl_open(struct h5 *h5)
+@@ -976,7 +981,8 @@ static void h5_btrtl_open(struct h5 *h5)
static void h5_btrtl_close(struct h5 *h5)
{
@@ -27550,6 +44309,27 @@ index 53deea2eb7b4d..8eb7fddfb9300 100644
dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
power_ctrl_enabled = false;
}
+diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
+index 3b00d82d36cf7..4cda890ce6470 100644
+--- a/drivers/bluetooth/hci_serdev.c
++++ b/drivers/bluetooth/hci_serdev.c
+@@ -305,6 +305,8 @@ int hci_uart_register_device(struct hci_uart *hu,
+ if (err)
+ return err;
+
++ percpu_init_rwsem(&hu->proto_lock);
++
+ err = p->open(hu);
+ if (err)
+ goto err_open;
+@@ -327,7 +329,6 @@ int hci_uart_register_device(struct hci_uart *hu,
+
+ INIT_WORK(&hu->init_ready, hci_uart_init_work);
+ INIT_WORK(&hu->write_work, hci_uart_write_work);
+- percpu_init_rwsem(&hu->proto_lock);
+
+ /* Only when vendor specific setup callback is provided, consider
+ * the manufacturer information valid. This avoids filling in the
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 8ab26dec5f6e8..8469f9876dd26 100644
--- a/drivers/bluetooth/hci_vhci.c
@@ -27577,10 +44357,160 @@ index 57908ce4fae85..076e4942a3f0e 100644
}
}
+diff --git a/drivers/bus/mhi/core/debugfs.c b/drivers/bus/mhi/core/debugfs.c
+index 858d7516410bb..d818586c229d2 100644
+--- a/drivers/bus/mhi/core/debugfs.c
++++ b/drivers/bus/mhi/core/debugfs.c
+@@ -60,16 +60,16 @@ static int mhi_debugfs_events_show(struct seq_file *m, void *d)
+ }
+
+ seq_printf(m, "Index: %d intmod count: %lu time: %lu",
+- i, (er_ctxt->intmod & EV_CTX_INTMODC_MASK) >>
++ i, (le32_to_cpu(er_ctxt->intmod) & EV_CTX_INTMODC_MASK) >>
+ EV_CTX_INTMODC_SHIFT,
+- (er_ctxt->intmod & EV_CTX_INTMODT_MASK) >>
++ (le32_to_cpu(er_ctxt->intmod) & EV_CTX_INTMODT_MASK) >>
+ EV_CTX_INTMODT_SHIFT);
+
+- seq_printf(m, " base: 0x%0llx len: 0x%llx", er_ctxt->rbase,
+- er_ctxt->rlen);
++ seq_printf(m, " base: 0x%0llx len: 0x%llx", le64_to_cpu(er_ctxt->rbase),
++ le64_to_cpu(er_ctxt->rlen));
+
+- seq_printf(m, " rp: 0x%llx wp: 0x%llx", er_ctxt->rp,
+- er_ctxt->wp);
++ seq_printf(m, " rp: 0x%llx wp: 0x%llx", le64_to_cpu(er_ctxt->rp),
++ le64_to_cpu(er_ctxt->wp));
+
+ seq_printf(m, " local rp: 0x%pK db: 0x%pad\n", ring->rp,
+ &mhi_event->db_cfg.db_val);
+@@ -106,18 +106,18 @@ static int mhi_debugfs_channels_show(struct seq_file *m, void *d)
+
+ seq_printf(m,
+ "%s(%u) state: 0x%lx brstmode: 0x%lx pollcfg: 0x%lx",
+- mhi_chan->name, mhi_chan->chan, (chan_ctxt->chcfg &
++ mhi_chan->name, mhi_chan->chan, (le32_to_cpu(chan_ctxt->chcfg) &
+ CHAN_CTX_CHSTATE_MASK) >> CHAN_CTX_CHSTATE_SHIFT,
+- (chan_ctxt->chcfg & CHAN_CTX_BRSTMODE_MASK) >>
+- CHAN_CTX_BRSTMODE_SHIFT, (chan_ctxt->chcfg &
++ (le32_to_cpu(chan_ctxt->chcfg) & CHAN_CTX_BRSTMODE_MASK) >>
++ CHAN_CTX_BRSTMODE_SHIFT, (le32_to_cpu(chan_ctxt->chcfg) &
+ CHAN_CTX_POLLCFG_MASK) >> CHAN_CTX_POLLCFG_SHIFT);
+
+- seq_printf(m, " type: 0x%x event ring: %u", chan_ctxt->chtype,
+- chan_ctxt->erindex);
++ seq_printf(m, " type: 0x%x event ring: %u", le32_to_cpu(chan_ctxt->chtype),
++ le32_to_cpu(chan_ctxt->erindex));
+
+ seq_printf(m, " base: 0x%llx len: 0x%llx rp: 0x%llx wp: 0x%llx",
+- chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->rp,
+- chan_ctxt->wp);
++ le64_to_cpu(chan_ctxt->rbase), le64_to_cpu(chan_ctxt->rlen),
++ le64_to_cpu(chan_ctxt->rp), le64_to_cpu(chan_ctxt->wp));
+
+ seq_printf(m, " local rp: 0x%pK local wp: 0x%pK db: 0x%pad\n",
+ ring->rp, ring->wp,
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
-index 5aaca6d0f52b2..f1ec344175928 100644
+index 5aaca6d0f52b2..4183945fc2c41 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
+@@ -290,17 +290,17 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+ if (mhi_chan->offload_ch)
+ continue;
+
+- tmp = chan_ctxt->chcfg;
++ tmp = le32_to_cpu(chan_ctxt->chcfg);
+ tmp &= ~CHAN_CTX_CHSTATE_MASK;
+ tmp |= (MHI_CH_STATE_DISABLED << CHAN_CTX_CHSTATE_SHIFT);
+ tmp &= ~CHAN_CTX_BRSTMODE_MASK;
+ tmp |= (mhi_chan->db_cfg.brstmode << CHAN_CTX_BRSTMODE_SHIFT);
+ tmp &= ~CHAN_CTX_POLLCFG_MASK;
+ tmp |= (mhi_chan->db_cfg.pollcfg << CHAN_CTX_POLLCFG_SHIFT);
+- chan_ctxt->chcfg = tmp;
++ chan_ctxt->chcfg = cpu_to_le32(tmp);
+
+- chan_ctxt->chtype = mhi_chan->type;
+- chan_ctxt->erindex = mhi_chan->er_index;
++ chan_ctxt->chtype = cpu_to_le32(mhi_chan->type);
++ chan_ctxt->erindex = cpu_to_le32(mhi_chan->er_index);
+
+ mhi_chan->ch_state = MHI_CH_STATE_DISABLED;
+ mhi_chan->tre_ring.db_addr = (void __iomem *)&chan_ctxt->wp;
+@@ -325,14 +325,14 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+ if (mhi_event->offload_ev)
+ continue;
+
+- tmp = er_ctxt->intmod;
++ tmp = le32_to_cpu(er_ctxt->intmod);
+ tmp &= ~EV_CTX_INTMODC_MASK;
+ tmp &= ~EV_CTX_INTMODT_MASK;
+ tmp |= (mhi_event->intmod << EV_CTX_INTMODT_SHIFT);
+- er_ctxt->intmod = tmp;
++ er_ctxt->intmod = cpu_to_le32(tmp);
+
+- er_ctxt->ertype = MHI_ER_TYPE_VALID;
+- er_ctxt->msivec = mhi_event->irq;
++ er_ctxt->ertype = cpu_to_le32(MHI_ER_TYPE_VALID);
++ er_ctxt->msivec = cpu_to_le32(mhi_event->irq);
+ mhi_event->db_cfg.db_mode = true;
+
+ ring->el_size = sizeof(struct mhi_tre);
+@@ -346,9 +346,9 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+ * ring is empty
+ */
+ ring->rp = ring->wp = ring->base;
+- er_ctxt->rbase = ring->iommu_base;
++ er_ctxt->rbase = cpu_to_le64(ring->iommu_base);
+ er_ctxt->rp = er_ctxt->wp = er_ctxt->rbase;
+- er_ctxt->rlen = ring->len;
++ er_ctxt->rlen = cpu_to_le64(ring->len);
+ ring->ctxt_wp = &er_ctxt->wp;
+ }
+
+@@ -375,9 +375,9 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+ goto error_alloc_cmd;
+
+ ring->rp = ring->wp = ring->base;
+- cmd_ctxt->rbase = ring->iommu_base;
++ cmd_ctxt->rbase = cpu_to_le64(ring->iommu_base);
+ cmd_ctxt->rp = cmd_ctxt->wp = cmd_ctxt->rbase;
+- cmd_ctxt->rlen = ring->len;
++ cmd_ctxt->rlen = cpu_to_le64(ring->len);
+ ring->ctxt_wp = &cmd_ctxt->wp;
+ }
+
+@@ -578,10 +578,10 @@ void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
+ chan_ctxt->rp = 0;
+ chan_ctxt->wp = 0;
+
+- tmp = chan_ctxt->chcfg;
++ tmp = le32_to_cpu(chan_ctxt->chcfg);
+ tmp &= ~CHAN_CTX_CHSTATE_MASK;
+ tmp |= (MHI_CH_STATE_DISABLED << CHAN_CTX_CHSTATE_SHIFT);
+- chan_ctxt->chcfg = tmp;
++ chan_ctxt->chcfg = cpu_to_le32(tmp);
+
+ /* Update to all cores */
+ smp_wmb();
+@@ -615,14 +615,14 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
+ return -ENOMEM;
+ }
+
+- tmp = chan_ctxt->chcfg;
++ tmp = le32_to_cpu(chan_ctxt->chcfg);
+ tmp &= ~CHAN_CTX_CHSTATE_MASK;
+ tmp |= (MHI_CH_STATE_ENABLED << CHAN_CTX_CHSTATE_SHIFT);
+- chan_ctxt->chcfg = tmp;
++ chan_ctxt->chcfg = cpu_to_le32(tmp);
+
+- chan_ctxt->rbase = tre_ring->iommu_base;
++ chan_ctxt->rbase = cpu_to_le64(tre_ring->iommu_base);
+ chan_ctxt->rp = chan_ctxt->wp = chan_ctxt->rbase;
+- chan_ctxt->rlen = tre_ring->len;
++ chan_ctxt->rlen = cpu_to_le64(tre_ring->len);
+ tre_ring->ctxt_wp = &chan_ctxt->wp;
+
+ tre_ring->rp = tre_ring->wp = tre_ring->base;
@@ -788,6 +788,7 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->offload_ch = ch_cfg->offload_channel;
mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch;
@@ -27589,10 +44519,310 @@ index 5aaca6d0f52b2..f1ec344175928 100644
/*
* If MHI host allocates buffers, then the channel direction
+diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h
+index 3a732afaf73ed..c02c4d48b744c 100644
+--- a/drivers/bus/mhi/core/internal.h
++++ b/drivers/bus/mhi/core/internal.h
+@@ -209,14 +209,14 @@ extern struct bus_type mhi_bus_type;
+ #define EV_CTX_INTMODT_MASK GENMASK(31, 16)
+ #define EV_CTX_INTMODT_SHIFT 16
+ struct mhi_event_ctxt {
+- __u32 intmod;
+- __u32 ertype;
+- __u32 msivec;
+-
+- __u64 rbase __packed __aligned(4);
+- __u64 rlen __packed __aligned(4);
+- __u64 rp __packed __aligned(4);
+- __u64 wp __packed __aligned(4);
++ __le32 intmod;
++ __le32 ertype;
++ __le32 msivec;
++
++ __le64 rbase __packed __aligned(4);
++ __le64 rlen __packed __aligned(4);
++ __le64 rp __packed __aligned(4);
++ __le64 wp __packed __aligned(4);
+ };
+
+ #define CHAN_CTX_CHSTATE_MASK GENMASK(7, 0)
+@@ -227,25 +227,25 @@ struct mhi_event_ctxt {
+ #define CHAN_CTX_POLLCFG_SHIFT 10
+ #define CHAN_CTX_RESERVED_MASK GENMASK(31, 16)
+ struct mhi_chan_ctxt {
+- __u32 chcfg;
+- __u32 chtype;
+- __u32 erindex;
+-
+- __u64 rbase __packed __aligned(4);
+- __u64 rlen __packed __aligned(4);
+- __u64 rp __packed __aligned(4);
+- __u64 wp __packed __aligned(4);
++ __le32 chcfg;
++ __le32 chtype;
++ __le32 erindex;
++
++ __le64 rbase __packed __aligned(4);
++ __le64 rlen __packed __aligned(4);
++ __le64 rp __packed __aligned(4);
++ __le64 wp __packed __aligned(4);
+ };
+
+ struct mhi_cmd_ctxt {
+- __u32 reserved0;
+- __u32 reserved1;
+- __u32 reserved2;
+-
+- __u64 rbase __packed __aligned(4);
+- __u64 rlen __packed __aligned(4);
+- __u64 rp __packed __aligned(4);
+- __u64 wp __packed __aligned(4);
++ __le32 reserved0;
++ __le32 reserved1;
++ __le32 reserved2;
++
++ __le64 rbase __packed __aligned(4);
++ __le64 rlen __packed __aligned(4);
++ __le64 rp __packed __aligned(4);
++ __le64 wp __packed __aligned(4);
+ };
+
+ struct mhi_ctxt {
+@@ -258,8 +258,8 @@ struct mhi_ctxt {
+ };
+
+ struct mhi_tre {
+- u64 ptr;
+- u32 dword[2];
++ __le64 ptr;
++ __le32 dword[2];
+ };
+
+ struct bhi_vec_entry {
+@@ -277,57 +277,58 @@ enum mhi_cmd_type {
+ /* No operation command */
+ #define MHI_TRE_CMD_NOOP_PTR (0)
+ #define MHI_TRE_CMD_NOOP_DWORD0 (0)
+-#define MHI_TRE_CMD_NOOP_DWORD1 (MHI_CMD_NOP << 16)
++#define MHI_TRE_CMD_NOOP_DWORD1 (cpu_to_le32(MHI_CMD_NOP << 16))
+
+ /* Channel reset command */
+ #define MHI_TRE_CMD_RESET_PTR (0)
+ #define MHI_TRE_CMD_RESET_DWORD0 (0)
+-#define MHI_TRE_CMD_RESET_DWORD1(chid) ((chid << 24) | \
+- (MHI_CMD_RESET_CHAN << 16))
++#define MHI_TRE_CMD_RESET_DWORD1(chid) (cpu_to_le32((chid << 24) | \
++ (MHI_CMD_RESET_CHAN << 16)))
+
+ /* Channel stop command */
+ #define MHI_TRE_CMD_STOP_PTR (0)
+ #define MHI_TRE_CMD_STOP_DWORD0 (0)
+-#define MHI_TRE_CMD_STOP_DWORD1(chid) ((chid << 24) | \
+- (MHI_CMD_STOP_CHAN << 16))
++#define MHI_TRE_CMD_STOP_DWORD1(chid) (cpu_to_le32((chid << 24) | \
++ (MHI_CMD_STOP_CHAN << 16)))
+
+ /* Channel start command */
+ #define MHI_TRE_CMD_START_PTR (0)
+ #define MHI_TRE_CMD_START_DWORD0 (0)
+-#define MHI_TRE_CMD_START_DWORD1(chid) ((chid << 24) | \
+- (MHI_CMD_START_CHAN << 16))
++#define MHI_TRE_CMD_START_DWORD1(chid) (cpu_to_le32((chid << 24) | \
++ (MHI_CMD_START_CHAN << 16)))
+
+-#define MHI_TRE_GET_CMD_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
+-#define MHI_TRE_GET_CMD_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
++#define MHI_TRE_GET_DWORD(tre, word) (le32_to_cpu((tre)->dword[(word)]))
++#define MHI_TRE_GET_CMD_CHID(tre) ((MHI_TRE_GET_DWORD(tre, 1) >> 24) & 0xFF)
++#define MHI_TRE_GET_CMD_TYPE(tre) ((MHI_TRE_GET_DWORD(tre, 1) >> 16) & 0xFF)
+
+ /* Event descriptor macros */
+-#define MHI_TRE_EV_PTR(ptr) (ptr)
+-#define MHI_TRE_EV_DWORD0(code, len) ((code << 24) | len)
+-#define MHI_TRE_EV_DWORD1(chid, type) ((chid << 24) | (type << 16))
+-#define MHI_TRE_GET_EV_PTR(tre) ((tre)->ptr)
+-#define MHI_TRE_GET_EV_CODE(tre) (((tre)->dword[0] >> 24) & 0xFF)
+-#define MHI_TRE_GET_EV_LEN(tre) ((tre)->dword[0] & 0xFFFF)
+-#define MHI_TRE_GET_EV_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
+-#define MHI_TRE_GET_EV_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
+-#define MHI_TRE_GET_EV_STATE(tre) (((tre)->dword[0] >> 24) & 0xFF)
+-#define MHI_TRE_GET_EV_EXECENV(tre) (((tre)->dword[0] >> 24) & 0xFF)
+-#define MHI_TRE_GET_EV_SEQ(tre) ((tre)->dword[0])
+-#define MHI_TRE_GET_EV_TIME(tre) ((tre)->ptr)
+-#define MHI_TRE_GET_EV_COOKIE(tre) lower_32_bits((tre)->ptr)
+-#define MHI_TRE_GET_EV_VEID(tre) (((tre)->dword[0] >> 16) & 0xFF)
+-#define MHI_TRE_GET_EV_LINKSPEED(tre) (((tre)->dword[1] >> 24) & 0xFF)
+-#define MHI_TRE_GET_EV_LINKWIDTH(tre) ((tre)->dword[0] & 0xFF)
++#define MHI_TRE_EV_PTR(ptr) (cpu_to_le64(ptr))
++#define MHI_TRE_EV_DWORD0(code, len) (cpu_to_le32((code << 24) | len))
++#define MHI_TRE_EV_DWORD1(chid, type) (cpu_to_le32((chid << 24) | (type << 16)))
++#define MHI_TRE_GET_EV_PTR(tre) (le64_to_cpu((tre)->ptr))
++#define MHI_TRE_GET_EV_CODE(tre) ((MHI_TRE_GET_DWORD(tre, 0) >> 24) & 0xFF)
++#define MHI_TRE_GET_EV_LEN(tre) (MHI_TRE_GET_DWORD(tre, 0) & 0xFFFF)
++#define MHI_TRE_GET_EV_CHID(tre) ((MHI_TRE_GET_DWORD(tre, 1) >> 24) & 0xFF)
++#define MHI_TRE_GET_EV_TYPE(tre) ((MHI_TRE_GET_DWORD(tre, 1) >> 16) & 0xFF)
++#define MHI_TRE_GET_EV_STATE(tre) ((MHI_TRE_GET_DWORD(tre, 0) >> 24) & 0xFF)
++#define MHI_TRE_GET_EV_EXECENV(tre) ((MHI_TRE_GET_DWORD(tre, 0) >> 24) & 0xFF)
++#define MHI_TRE_GET_EV_SEQ(tre) MHI_TRE_GET_DWORD(tre, 0)
++#define MHI_TRE_GET_EV_TIME(tre) (MHI_TRE_GET_EV_PTR(tre))
++#define MHI_TRE_GET_EV_COOKIE(tre) lower_32_bits(MHI_TRE_GET_EV_PTR(tre))
++#define MHI_TRE_GET_EV_VEID(tre) ((MHI_TRE_GET_DWORD(tre, 0) >> 16) & 0xFF)
++#define MHI_TRE_GET_EV_LINKSPEED(tre) ((MHI_TRE_GET_DWORD(tre, 1) >> 24) & 0xFF)
++#define MHI_TRE_GET_EV_LINKWIDTH(tre) (MHI_TRE_GET_DWORD(tre, 0) & 0xFF)
+
+ /* Transfer descriptor macros */
+-#define MHI_TRE_DATA_PTR(ptr) (ptr)
+-#define MHI_TRE_DATA_DWORD0(len) (len & MHI_MAX_MTU)
+-#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) ((2 << 16) | (bei << 10) \
+- | (ieot << 9) | (ieob << 8) | chain)
++#define MHI_TRE_DATA_PTR(ptr) (cpu_to_le64(ptr))
++#define MHI_TRE_DATA_DWORD0(len) (cpu_to_le32(len & MHI_MAX_MTU))
++#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) (cpu_to_le32((2 << 16) | (bei << 10) \
++ | (ieot << 9) | (ieob << 8) | chain))
+
+ /* RSC transfer descriptor macros */
+-#define MHI_RSCTRE_DATA_PTR(ptr, len) (((u64)len << 48) | ptr)
+-#define MHI_RSCTRE_DATA_DWORD0(cookie) (cookie)
+-#define MHI_RSCTRE_DATA_DWORD1 (MHI_PKT_TYPE_COALESCING << 16)
++#define MHI_RSCTRE_DATA_PTR(ptr, len) (cpu_to_le64(((u64)len << 48) | ptr))
++#define MHI_RSCTRE_DATA_DWORD0(cookie) (cpu_to_le32(cookie))
++#define MHI_RSCTRE_DATA_DWORD1 (cpu_to_le32(MHI_PKT_TYPE_COALESCING << 16))
+
+ enum mhi_pkt_type {
+ MHI_PKT_TYPE_INVALID = 0x0,
+@@ -499,7 +500,7 @@ struct state_transition {
+ struct mhi_ring {
+ dma_addr_t dma_handle;
+ dma_addr_t iommu_base;
+- u64 *ctxt_wp; /* point to ctxt wp */
++ __le64 *ctxt_wp; /* point to ctxt wp */
+ void *pre_aligned;
+ void *base;
+ void *rp;
+diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
+index b15c5bc37dd4f..9a94b8d66f575 100644
+--- a/drivers/bus/mhi/core/main.c
++++ b/drivers/bus/mhi/core/main.c
+@@ -114,7 +114,7 @@ void mhi_ring_er_db(struct mhi_event *mhi_event)
+ struct mhi_ring *ring = &mhi_event->ring;
+
+ mhi_event->db_cfg.process_db(mhi_event->mhi_cntrl, &mhi_event->db_cfg,
+- ring->db_addr, *ring->ctxt_wp);
++ ring->db_addr, le64_to_cpu(*ring->ctxt_wp));
+ }
+
+ void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd)
+@@ -123,7 +123,7 @@ void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd)
+ struct mhi_ring *ring = &mhi_cmd->ring;
+
+ db = ring->iommu_base + (ring->wp - ring->base);
+- *ring->ctxt_wp = db;
++ *ring->ctxt_wp = cpu_to_le64(db);
+ mhi_write_db(mhi_cntrl, ring->db_addr, db);
+ }
+
+@@ -140,7 +140,7 @@ void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,
+ * before letting h/w know there is new element to fetch.
+ */
+ dma_wmb();
+- *ring->ctxt_wp = db;
++ *ring->ctxt_wp = cpu_to_le64(db);
+
+ mhi_chan->db_cfg.process_db(mhi_cntrl, &mhi_chan->db_cfg,
+ ring->db_addr, db);
+@@ -432,7 +432,7 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
+ struct mhi_event_ctxt *er_ctxt =
+ &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+ struct mhi_ring *ev_ring = &mhi_event->ring;
+- dma_addr_t ptr = er_ctxt->rp;
++ dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+ void *dev_rp;
+
+ if (!is_valid_ring_ptr(ev_ring, ptr)) {
+@@ -537,14 +537,14 @@ static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl,
+
+ /* Update the WP */
+ ring->wp += ring->el_size;
+- ctxt_wp = *ring->ctxt_wp + ring->el_size;
++ ctxt_wp = le64_to_cpu(*ring->ctxt_wp) + ring->el_size;
+
+ if (ring->wp >= (ring->base + ring->len)) {
+ ring->wp = ring->base;
+ ctxt_wp = ring->iommu_base;
+ }
+
+- *ring->ctxt_wp = ctxt_wp;
++ *ring->ctxt_wp = cpu_to_le64(ctxt_wp);
+
+ /* Update the RP */
+ ring->rp += ring->el_size;
+@@ -801,7 +801,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
+ struct device *dev = &mhi_cntrl->mhi_dev->dev;
+ u32 chan;
+ int count = 0;
+- dma_addr_t ptr = er_ctxt->rp;
++ dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+
+ /*
+ * This is a quick check to avoid unnecessary event processing
+@@ -940,7 +940,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
+ mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring);
+ local_rp = ev_ring->rp;
+
+- ptr = er_ctxt->rp;
++ ptr = le64_to_cpu(er_ctxt->rp);
+ if (!is_valid_ring_ptr(ev_ring, ptr)) {
+ dev_err(&mhi_cntrl->mhi_dev->dev,
+ "Event ring rp points outside of the event ring\n");
+@@ -970,7 +970,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
+ int count = 0;
+ u32 chan;
+ struct mhi_chan *mhi_chan;
+- dma_addr_t ptr = er_ctxt->rp;
++ dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+
+ if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state)))
+ return -EIO;
+@@ -1011,7 +1011,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
+ mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring);
+ local_rp = ev_ring->rp;
+
+- ptr = er_ctxt->rp;
++ ptr = le64_to_cpu(er_ctxt->rp);
+ if (!is_valid_ring_ptr(ev_ring, ptr)) {
+ dev_err(&mhi_cntrl->mhi_dev->dev,
+ "Event ring rp points outside of the event ring\n");
+@@ -1529,7 +1529,7 @@ static void mhi_mark_stale_events(struct mhi_controller *mhi_cntrl,
+ /* mark all stale events related to channel as STALE event */
+ spin_lock_irqsave(&mhi_event->lock, flags);
+
+- ptr = er_ctxt->rp;
++ ptr = le64_to_cpu(er_ctxt->rp);
+ if (!is_valid_ring_ptr(ev_ring, ptr)) {
+ dev_err(&mhi_cntrl->mhi_dev->dev,
+ "Event ring rp points outside of the event ring\n");
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
-index fb99e3727155b..bb9a2043f3a20 100644
+index fb99e3727155b..1020268a075a5 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
+@@ -218,7 +218,7 @@ int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl)
+ continue;
+
+ ring->wp = ring->base + ring->len - ring->el_size;
+- *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size;
++ *ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size);
+ /* Update all cores */
+ smp_wmb();
+
+@@ -420,7 +420,7 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
+ continue;
+
+ ring->wp = ring->base + ring->len - ring->el_size;
+- *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size;
++ *ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size);
+ /* Update to all cores */
+ smp_wmb();
+
@@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
}
EXPORT_SYMBOL_GPL(mhi_pm_suspend);
@@ -27716,7 +44946,7 @@ index fb99e3727155b..bb9a2043f3a20 100644
mutex_unlock(&mhi_cntrl->pm_mutex);
diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
-index 59a4896a80309..d340d6864e13a 100644
+index 59a4896a80309..0982642a7907e 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -20,7 +20,7 @@
@@ -27728,7 +44958,15 @@ index 59a4896a80309..d340d6864e13a 100644
#define HEALTH_CHECK_PERIOD (HZ * 2)
-@@ -366,6 +366,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
+@@ -327,6 +327,7 @@ static const struct mhi_pci_dev_info mhi_quectel_em1xx_info = {
+ .config = &modem_quectel_em1xx_config,
+ .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+ .dma_data_width = 32,
++ .mru_default = 32768,
+ .sideband_wake = true,
+ };
+
+@@ -366,6 +367,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
.config = &modem_foxconn_sdx55_config,
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
.dma_data_width = 32,
@@ -27736,7 +44974,7 @@ index 59a4896a80309..d340d6864e13a 100644
.sideband_wake = false,
};
-@@ -401,6 +402,7 @@ static const struct mhi_pci_dev_info mhi_mv31_info = {
+@@ -401,6 +403,7 @@ static const struct mhi_pci_dev_info mhi_mv31_info = {
.config = &modem_mv31_config,
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
.dma_data_width = 32,
@@ -27744,20 +44982,51 @@ index 59a4896a80309..d340d6864e13a 100644
};
static const struct pci_device_id mhi_pci_id_table[] = {
-@@ -1018,7 +1020,7 @@ static int __maybe_unused mhi_pci_freeze(struct device *dev)
+@@ -1017,8 +1020,9 @@ static int __maybe_unused mhi_pci_freeze(struct device *dev)
+ * the intermediate restore kernel reinitializes MHI device with new
* context.
*/
++ flush_work(&mhi_pdev->recovery_work);
if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
- mhi_power_down(mhi_cntrl, false);
+ mhi_power_down(mhi_cntrl, true);
mhi_unprepare_after_power_down(mhi_cntrl);
}
+@@ -1042,6 +1046,7 @@ static const struct dev_pm_ops mhi_pci_pm_ops = {
+ .resume = mhi_pci_resume,
+ .freeze = mhi_pci_freeze,
+ .thaw = mhi_pci_restore,
++ .poweroff = mhi_pci_freeze,
+ .restore = mhi_pci_restore,
+ #endif
+ };
+diff --git a/drivers/bus/mips_cdmm.c b/drivers/bus/mips_cdmm.c
+index 626dedd110cbc..fca0d0669aa97 100644
+--- a/drivers/bus/mips_cdmm.c
++++ b/drivers/bus/mips_cdmm.c
+@@ -351,6 +351,7 @@ phys_addr_t __weak mips_cdmm_phys_base(void)
+ np = of_find_compatible_node(NULL, NULL, "mti,mips-cdmm");
+ if (np) {
+ err = of_address_to_resource(np, 0, &res);
++ of_node_put(np);
+ if (!err)
+ return res.start;
+ }
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
-index 6f225dddc74f4..4566e730ef2b8 100644
+index 6f225dddc74f4..60b082fe2ed02 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
-@@ -687,11 +687,11 @@ err_clk_disable:
+@@ -227,6 +227,8 @@ static struct sunxi_rsb_device *sunxi_rsb_device_create(struct sunxi_rsb *rsb,
+
+ dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev));
+
++ return rdev;
++
+ err_device_add:
+ put_device(&rdev->dev);
+
+@@ -687,11 +689,11 @@ err_clk_disable:
static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb)
{
@@ -27774,7 +45043,7 @@ index 6f225dddc74f4..4566e730ef2b8 100644
static int __maybe_unused sunxi_rsb_runtime_suspend(struct device *dev)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
-index 6a8b7fb5be58d..ebf22929ff328 100644
+index 6a8b7fb5be58d..00d46f3ae22fb 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -6,6 +6,7 @@
@@ -27852,7 +45121,8 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
+ }
+ error = -ETIMEDOUT;
+ }
-+
+
+- } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
+ return error;
+}
+
@@ -27862,8 +45132,7 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
+ u32 sysc_mask, rstval;
+
+ sysc_mask = BIT(ddata->cap->regbits->srst_shift);
-
-- } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
++
+ if (likely(!timekeeping_suspended)) {
error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata,
rstval, !(rstval & sysc_mask),
@@ -28042,7 +45311,36 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) {
disabled_module = list_entry(pos, struct sysc_address, node);
list_del(pos);
-@@ -3061,7 +3194,7 @@ static int sysc_probe(struct platform_device *pdev)
+@@ -3029,13 +3162,27 @@ static int sysc_check_disabled_devices(struct sysc *ddata)
+ */
+ static int sysc_check_active_timer(struct sysc *ddata)
+ {
++ int error;
++
+ if (ddata->cap->type != TI_SYSC_OMAP2_TIMER &&
+ ddata->cap->type != TI_SYSC_OMAP4_TIMER)
+ return 0;
+
++ /*
++ * Quirk for omap3 beagleboard revision A to B4 to use gpt12.
++ * Revision C and later are fixed with commit 23885389dbbb ("ARM:
++ * dts: Fix timer regression for beagleboard revision c"). This all
++ * can be dropped if we stop supporting old beagleboard revisions
++ * A to B4 at some point.
++ */
++ if (sysc_soc->soc == SOC_3430)
++ error = -ENXIO;
++ else
++ error = -EBUSY;
++
+ if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) &&
+ (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE))
+- return -ENXIO;
++ return error;
+
+ return 0;
+ }
+@@ -3061,7 +3208,7 @@ static int sysc_probe(struct platform_device *pdev)
ddata->dev = &pdev->dev;
platform_set_drvdata(pdev, ddata);
@@ -28051,7 +45349,7 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
if (error)
return error;
-@@ -3159,6 +3292,9 @@ static int sysc_probe(struct platform_device *pdev)
+@@ -3159,6 +3306,9 @@ static int sysc_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
}
@@ -28061,7 +45359,7 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
return 0;
err:
-@@ -3240,7 +3376,7 @@ static void __exit sysc_exit(void)
+@@ -3240,7 +3390,7 @@ static void __exit sysc_exit(void)
{
bus_unregister_notifier(&platform_bus_type, &sysc_nb);
platform_driver_unregister(&sysc_driver);
@@ -28070,6 +45368,19 @@ index 6a8b7fb5be58d..ebf22929ff328 100644
}
module_exit(sysc_exit);
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 740811893c570..55f48375e3fe5 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -449,6 +449,7 @@ config RANDOM_TRUST_BOOTLOADER
+ device randomness. Say Y here to assume the entropy provided by the
+ booloader is trustworthy so it will be added to the kernel's entropy
+ pool. Otherwise, say N here so it will be regarded as device input that
+- only mixes the entropy pool.
++ only mixes the entropy pool. This can also be configured at boot with
++ "random.trust_bootloader=on/off".
+
+ endmenu
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index ed3c4c42fc23b..d68d05d5d3838 100644
--- a/drivers/char/agp/parisc-agp.c
@@ -28101,6 +45412,325 @@ index ed3c4c42fc23b..d68d05d5d3838 100644
parisc_agp_init(void)
{
extern struct sba_device *sba_list;
+diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
+index 239eca4d68055..650c7d9180802 100644
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -414,7 +414,7 @@ config HW_RANDOM_MESON
+
+ config HW_RANDOM_CAVIUM
+ tristate "Cavium ThunderX Random Number Generator support"
+- depends on HW_RANDOM && PCI && (ARM64 || (COMPILE_TEST && 64BIT))
++ depends on HW_RANDOM && PCI && ARCH_THUNDER
+ default HW_RANDOM
+ help
+ This driver provides kernel-side support for the Random Number
+diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
+index ecb71c4317a50..8cf0ef501341e 100644
+--- a/drivers/char/hw_random/atmel-rng.c
++++ b/drivers/char/hw_random/atmel-rng.c
+@@ -114,6 +114,7 @@ static int atmel_trng_probe(struct platform_device *pdev)
+
+ err_register:
+ clk_disable_unprepare(trng->clk);
++ atmel_trng_disable(trng);
+ return ret;
+ }
+
+diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c
+index 3de4a6a443ef9..6f66919652bf5 100644
+--- a/drivers/char/hw_random/cavium-rng-vf.c
++++ b/drivers/char/hw_random/cavium-rng-vf.c
+@@ -1,10 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+- * Hardware Random Number Generator support for Cavium, Inc.
+- * Thunder processor family.
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
++ * Hardware Random Number Generator support.
++ * Cavium Thunder, Marvell OcteonTx/Tx2 processor families.
+ *
+ * Copyright (C) 2016 Cavium, Inc.
+ */
+@@ -15,16 +12,146 @@
+ #include <linux/pci.h>
+ #include <linux/pci_ids.h>
+
++#include <asm/arch_timer.h>
++
++/* PCI device IDs */
++#define PCI_DEVID_CAVIUM_RNG_PF 0xA018
++#define PCI_DEVID_CAVIUM_RNG_VF 0xA033
++
++#define HEALTH_STATUS_REG 0x38
++
++/* RST device info */
++#define PCI_DEVICE_ID_RST_OTX2 0xA085
++#define RST_BOOT_REG 0x1600ULL
++#define CLOCK_BASE_RATE 50000000ULL
++#define MSEC_TO_NSEC(x) (x * 1000000)
++
+ struct cavium_rng {
+ struct hwrng ops;
+ void __iomem *result;
++ void __iomem *pf_regbase;
++ struct pci_dev *pdev;
++ u64 clock_rate;
++ u64 prev_error;
++ u64 prev_time;
+ };
+
++static inline bool is_octeontx(struct pci_dev *pdev)
++{
++ if (midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX_83XX,
++ MIDR_CPU_VAR_REV(0, 0),
++ MIDR_CPU_VAR_REV(3, 0)) ||
++ midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX_81XX,
++ MIDR_CPU_VAR_REV(0, 0),
++ MIDR_CPU_VAR_REV(3, 0)) ||
++ midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX,
++ MIDR_CPU_VAR_REV(0, 0),
++ MIDR_CPU_VAR_REV(3, 0)))
++ return true;
++
++ return false;
++}
++
++static u64 rng_get_coprocessor_clkrate(void)
++{
++ u64 ret = CLOCK_BASE_RATE * 16; /* Assume 800Mhz as default */
++ struct pci_dev *pdev;
++ void __iomem *base;
++
++ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
++ PCI_DEVICE_ID_RST_OTX2, NULL);
++ if (!pdev)
++ goto error;
++
++ base = pci_ioremap_bar(pdev, 0);
++ if (!base)
++ goto error_put_pdev;
++
++ /* RST: PNR_MUL * 50Mhz gives clockrate */
++ ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT_REG) >> 33) & 0x3F);
++
++ iounmap(base);
++
++error_put_pdev:
++ pci_dev_put(pdev);
++
++error:
++ return ret;
++}
++
++static int check_rng_health(struct cavium_rng *rng)
++{
++ u64 cur_err, cur_time;
++ u64 status, cycles;
++ u64 time_elapsed;
++
++
++ /* Skip checking health for OcteonTx */
++ if (!rng->pf_regbase)
++ return 0;
++
++ status = readq(rng->pf_regbase + HEALTH_STATUS_REG);
++ if (status & BIT_ULL(0)) {
++ dev_err(&rng->pdev->dev, "HWRNG: Startup health test failed\n");
++ return -EIO;
++ }
++
++ cycles = status >> 1;
++ if (!cycles)
++ return 0;
++
++ cur_time = arch_timer_read_counter();
++
++ /* RNM_HEALTH_STATUS[CYCLES_SINCE_HEALTH_FAILURE]
++ * Number of coprocessor cycles times 2 since the last failure.
++ * This field doesn't get cleared/updated until another failure.
++ */
++ cycles = cycles / 2;
++ cur_err = (cycles * 1000000000) / rng->clock_rate; /* In nanosec */
++
++ /* Ignore errors that happenned a long time ago, these
++ * are most likely false positive errors.
++ */
++ if (cur_err > MSEC_TO_NSEC(10)) {
++ rng->prev_error = 0;
++ rng->prev_time = 0;
++ return 0;
++ }
++
++ if (rng->prev_error) {
++ /* Calculate time elapsed since last error
++ * '1' tick of CNTVCT is 10ns, since it runs at 100Mhz.
++ */
++ time_elapsed = (cur_time - rng->prev_time) * 10;
++ time_elapsed += rng->prev_error;
++
++ /* Check if current error is a new one or the old one itself.
++ * If error is a new one then consider there is a persistent
++ * issue with entropy, declare hardware failure.
++ */
++ if (cur_err < time_elapsed) {
++ dev_err(&rng->pdev->dev, "HWRNG failure detected\n");
++ rng->prev_error = cur_err;
++ rng->prev_time = cur_time;
++ return -EIO;
++ }
++ }
++
++ rng->prev_error = cur_err;
++ rng->prev_time = cur_time;
++ return 0;
++}
++
+ /* Read data from the RNG unit */
+ static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
+ {
+ struct cavium_rng *p = container_of(rng, struct cavium_rng, ops);
+ unsigned int size = max;
++ int err = 0;
++
++ err = check_rng_health(p);
++ if (err)
++ return err;
+
+ while (size >= 8) {
+ *((u64 *)dat) = readq(p->result);
+@@ -39,6 +166,39 @@ static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
+ return max;
+ }
+
++static int cavium_map_pf_regs(struct cavium_rng *rng)
++{
++ struct pci_dev *pdev;
++
++ /* Health status is not supported on 83xx, skip mapping PF CSRs */
++ if (is_octeontx(rng->pdev)) {
++ rng->pf_regbase = NULL;
++ return 0;
++ }
++
++ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
++ PCI_DEVID_CAVIUM_RNG_PF, NULL);
++ if (!pdev) {
++ dev_err(&pdev->dev, "Cannot find RNG PF device\n");
++ return -EIO;
++ }
++
++ rng->pf_regbase = ioremap(pci_resource_start(pdev, 0),
++ pci_resource_len(pdev, 0));
++ if (!rng->pf_regbase) {
++ dev_err(&pdev->dev, "Failed to map PF CSR region\n");
++ pci_dev_put(pdev);
++ return -ENOMEM;
++ }
++
++ pci_dev_put(pdev);
++
++ /* Get co-processor clock rate */
++ rng->clock_rate = rng_get_coprocessor_clkrate();
++
++ return 0;
++}
++
+ /* Map Cavium RNG to an HWRNG object */
+ static int cavium_rng_probe_vf(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+@@ -50,6 +210,8 @@ static int cavium_rng_probe_vf(struct pci_dev *pdev,
+ if (!rng)
+ return -ENOMEM;
+
++ rng->pdev = pdev;
++
+ /* Map the RNG result */
+ rng->result = pcim_iomap(pdev, 0, 0);
+ if (!rng->result) {
+@@ -67,6 +229,11 @@ static int cavium_rng_probe_vf(struct pci_dev *pdev,
+
+ pci_set_drvdata(pdev, rng);
+
++ /* Health status is available only at PF, hence map PF registers. */
++ ret = cavium_map_pf_regs(rng);
++ if (ret)
++ return ret;
++
+ ret = devm_hwrng_register(&pdev->dev, &rng->ops);
+ if (ret) {
+ dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
+@@ -76,10 +243,18 @@ static int cavium_rng_probe_vf(struct pci_dev *pdev,
+ return 0;
+ }
+
++/* Remove the VF */
++static void cavium_rng_remove_vf(struct pci_dev *pdev)
++{
++ struct cavium_rng *rng;
++
++ rng = pci_get_drvdata(pdev);
++ iounmap(rng->pf_regbase);
++}
+
+ static const struct pci_device_id cavium_rng_vf_id_table[] = {
+- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0},
+- {0,},
++ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CAVIUM_RNG_VF) },
++ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table);
+
+@@ -87,8 +262,9 @@ static struct pci_driver cavium_rng_vf_driver = {
+ .name = "cavium_rng_vf",
+ .id_table = cavium_rng_vf_id_table,
+ .probe = cavium_rng_probe_vf,
++ .remove = cavium_rng_remove_vf,
+ };
+ module_pci_driver(cavium_rng_vf_driver);
+
+ MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
+-MODULE_LICENSE("GPL");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c
+index 63d6e68c24d2f..b96579222408b 100644
+--- a/drivers/char/hw_random/cavium-rng.c
++++ b/drivers/char/hw_random/cavium-rng.c
+@@ -1,10 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+- * Hardware Random Number Generator support for Cavium Inc.
+- * Thunder processor family.
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
++ * Hardware Random Number Generator support.
++ * Cavium Thunder, Marvell OcteonTx/Tx2 processor families.
+ *
+ * Copyright (C) 2016 Cavium, Inc.
+ */
+@@ -91,4 +88,4 @@ static struct pci_driver cavium_rng_pf_driver = {
+
+ module_pci_driver(cavium_rng_pf_driver);
+ MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
+-MODULE_LICENSE("GPL");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index a3db27916256d..cfb085de876b7 100644
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -15,6 +15,7 @@
+ #include <linux/err.h>
+ #include <linux/fs.h>
+ #include <linux/hw_random.h>
++#include <linux/random.h>
+ #include <linux/kernel.h>
+ #include <linux/kthread.h>
+ #include <linux/sched/signal.h>
diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
index 8ad7b515a51b8..6c00ea0085553 100644
--- a/drivers/char/hw_random/mtk-rng.c
@@ -28121,6 +45751,27 @@ index 8ad7b515a51b8..6c00ea0085553 100644
#define MTK_RNG_PM_OPS (&mtk_rng_pm_ops)
#else /* CONFIG_PM */
#define MTK_RNG_PM_OPS NULL
+diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
+index 67947a19aa225..e8f9621e79541 100644
+--- a/drivers/char/hw_random/nomadik-rng.c
++++ b/drivers/char/hw_random/nomadik-rng.c
+@@ -65,14 +65,14 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
+ out_release:
+ amba_release_regions(dev);
+ out_clk:
+- clk_disable(rng_clk);
++ clk_disable_unprepare(rng_clk);
+ return ret;
+ }
+
+ static void nmk_rng_remove(struct amba_device *dev)
+ {
+ amba_release_regions(dev);
+- clk_disable(rng_clk);
++ clk_disable_unprepare(rng_clk);
+ }
+
+ static const struct amba_id nmk_rng_ids[] = {
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e96cb5c4f97a3..fe91090e04a46 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
@@ -28363,155 +46014,1629 @@ index 9ccb6b270b071..95164246afd1a 100644
diff --git a/drivers/char/random.c b/drivers/char/random.c
-index 605969ed0f965..ebe86de9d0acc 100644
+index 605969ed0f965..ca17a658c2147 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
-@@ -461,6 +461,7 @@ static struct crng_state primary_crng = {
- * its value (from 0->1->2).
+@@ -1,310 +1,26 @@
++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+ /*
+- * random.c -- A strong random number generator
+- *
+- * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+- * Rights Reserved.
+- *
++ * Copyright (C) 2017-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
+- *
+- * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
+- * rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- * notice, and the entire permission notice in its entirety,
+- * including the disclaimer of warranties.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * 3. The name of the author may not be used to endorse or promote
+- * products derived from this software without specific prior
+- * written permission.
+- *
+- * ALTERNATIVELY, this product may be distributed under the terms of
+- * the GNU General Public License, in which case the provisions of the GPL are
+- * required INSTEAD OF the above restrictions. (This clause is
+- * necessary due to a potential bad interaction between the GPL and
+- * the restrictions contained in a BSD-style copyright.)
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+- * DAMAGE.
+- */
+-
+-/*
+- * (now, with legal B.S. out of the way.....)
+- *
+- * This routine gathers environmental noise from device drivers, etc.,
+- * and returns good random numbers, suitable for cryptographic use.
+- * Besides the obvious cryptographic uses, these numbers are also good
+- * for seeding TCP sequence numbers, and other places where it is
+- * desirable to have numbers which are not only random, but hard to
+- * predict by an attacker.
+- *
+- * Theory of operation
+- * ===================
+- *
+- * Computers are very predictable devices. Hence it is extremely hard
+- * to produce truly random numbers on a computer --- as opposed to
+- * pseudo-random numbers, which can easily generated by using a
+- * algorithm. Unfortunately, it is very easy for attackers to guess
+- * the sequence of pseudo-random number generators, and for some
+- * applications this is not acceptable. So instead, we must try to
+- * gather "environmental noise" from the computer's environment, which
+- * must be hard for outside attackers to observe, and use that to
+- * generate random numbers. In a Unix environment, this is best done
+- * from inside the kernel.
+- *
+- * Sources of randomness from the environment include inter-keyboard
+- * timings, inter-interrupt timings from some interrupts, and other
+- * events which are both (a) non-deterministic and (b) hard for an
+- * outside observer to measure. Randomness from these sources are
+- * added to an "entropy pool", which is mixed using a CRC-like function.
+- * This is not cryptographically strong, but it is adequate assuming
+- * the randomness is not chosen maliciously, and it is fast enough that
+- * the overhead of doing it on every interrupt is very reasonable.
+- * As random bytes are mixed into the entropy pool, the routines keep
+- * an *estimate* of how many bits of randomness have been stored into
+- * the random number generator's internal state.
+- *
+- * When random bytes are desired, they are obtained by taking the SHA
+- * hash of the contents of the "entropy pool". The SHA hash avoids
+- * exposing the internal state of the entropy pool. It is believed to
+- * be computationally infeasible to derive any useful information
+- * about the input of SHA from its output. Even if it is possible to
+- * analyze SHA in some clever way, as long as the amount of data
+- * returned from the generator is less than the inherent entropy in
+- * the pool, the output data is totally unpredictable. For this
+- * reason, the routine decreases its internal estimate of how many
+- * bits of "true randomness" are contained in the entropy pool as it
+- * outputs random numbers.
+- *
+- * If this estimate goes to zero, the routine can still generate
+- * random numbers; however, an attacker may (at least in theory) be
+- * able to infer the future output of the generator from prior
+- * outputs. This requires successful cryptanalysis of SHA, which is
+- * not believed to be feasible, but there is a remote possibility.
+- * Nonetheless, these numbers should be useful for the vast majority
+- * of purposes.
+- *
+- * Exported interfaces ---- output
+- * ===============================
+- *
+- * There are four exported interfaces; two for use within the kernel,
+- * and two or use from userspace.
+- *
+- * Exported interfaces ---- userspace output
+- * -----------------------------------------
+- *
+- * The userspace interfaces are two character devices /dev/random and
+- * /dev/urandom. /dev/random is suitable for use when very high
+- * quality randomness is desired (for example, for key generation or
+- * one-time pads), as it will only return a maximum of the number of
+- * bits of randomness (as estimated by the random number generator)
+- * contained in the entropy pool.
+- *
+- * The /dev/urandom device does not have this limit, and will return
+- * as many bytes as are requested. As more and more random bytes are
+- * requested without giving time for the entropy pool to recharge,
+- * this will result in random numbers that are merely cryptographically
+- * strong. For many applications, however, this is acceptable.
+- *
+- * Exported interfaces ---- kernel output
+- * --------------------------------------
+- *
+- * The primary kernel interface is
+- *
+- * void get_random_bytes(void *buf, int nbytes);
+- *
+- * This interface will return the requested number of random bytes,
+- * and place it in the requested buffer. This is equivalent to a
+- * read from /dev/urandom.
+- *
+- * For less critical applications, there are the functions:
+- *
+- * u32 get_random_u32()
+- * u64 get_random_u64()
+- * unsigned int get_random_int()
+- * unsigned long get_random_long()
+- *
+- * These are produced by a cryptographic RNG seeded from get_random_bytes,
+- * and so do not deplete the entropy pool as much. These are recommended
+- * for most in-kernel operations *if the result is going to be stored in
+- * the kernel*.
+- *
+- * Specifically, the get_random_int() family do not attempt to do
+- * "anti-backtracking". If you capture the state of the kernel (e.g.
+- * by snapshotting the VM), you can figure out previous get_random_int()
+- * return values. But if the value is stored in the kernel anyway,
+- * this is not a problem.
+- *
+- * It *is* safe to expose get_random_int() output to attackers (e.g. as
+- * network cookies); given outputs 1..n, it's not feasible to predict
+- * outputs 0 or n+1. The only concern is an attacker who breaks into
+- * the kernel later; the get_random_int() engine is not reseeded as
+- * often as the get_random_bytes() one.
+- *
+- * get_random_bytes() is needed for keys that need to stay secret after
+- * they are erased from the kernel. For example, any key that will
+- * be wrapped and stored encrypted. And session encryption keys: we'd
+- * like to know that after the session is closed and the keys erased,
+- * the plaintext is unrecoverable to someone who recorded the ciphertext.
+- *
+- * But for network ports/cookies, stack canaries, PRNG seeds, address
+- * space layout randomization, session *authentication* keys, or other
+- * applications where the sensitive data is stored in the kernel in
+- * plaintext for as long as it's sensitive, the get_random_int() family
+- * is just fine.
+- *
+- * Consider ASLR. We want to keep the address space secret from an
+- * outside attacker while the process is running, but once the address
+- * space is torn down, it's of no use to an attacker any more. And it's
+- * stored in kernel data structures as long as it's alive, so worrying
+- * about an attacker's ability to extrapolate it from the get_random_int()
+- * CRNG is silly.
+- *
+- * Even some cryptographic keys are safe to generate with get_random_int().
+- * In particular, keys for SipHash are generally fine. Here, knowledge
+- * of the key authorizes you to do something to a kernel object (inject
+- * packets to a network connection, or flood a hash table), and the
+- * key is stored with the object being protected. Once it goes away,
+- * we no longer care if anyone knows the key.
+- *
+- * prandom_u32()
+- * -------------
+- *
+- * For even weaker applications, see the pseudorandom generator
+- * prandom_u32(), prandom_max(), and prandom_bytes(). If the random
+- * numbers aren't security-critical at all, these are *far* cheaper.
+- * Useful for self-tests, random error simulation, randomized backoffs,
+- * and any other application where you trust that nobody is trying to
+- * maliciously mess with you by guessing the "random" numbers.
+- *
+- * Exported interfaces ---- input
+- * ==============================
+- *
+- * The current exported interfaces for gathering environmental noise
+- * from the devices are:
+- *
+- * void add_device_randomness(const void *buf, unsigned int size);
+- * void add_input_randomness(unsigned int type, unsigned int code,
+- * unsigned int value);
+- * void add_interrupt_randomness(int irq, int irq_flags);
+- * void add_disk_randomness(struct gendisk *disk);
+- *
+- * add_device_randomness() is for adding data to the random pool that
+- * is likely to differ between two devices (or possibly even per boot).
+- * This would be things like MAC addresses or serial numbers, or the
+- * read-out of the RTC. This does *not* add any actual entropy to the
+- * pool, but it initializes the pool to different values for devices
+- * that might otherwise be identical and have very little entropy
+- * available to them (particularly common in the embedded world).
+- *
+- * add_input_randomness() uses the input layer interrupt timing, as well as
+- * the event type information from the hardware.
+- *
+- * add_interrupt_randomness() uses the interrupt timing as random
+- * inputs to the entropy pool. Using the cycle counters and the irq source
+- * as inputs, it feeds the randomness roughly once a second.
+- *
+- * add_disk_randomness() uses what amounts to the seek time of block
+- * layer request events, on a per-disk_devt basis, as input to the
+- * entropy pool. Note that high-speed solid state drives with very low
+- * seek times do not make for good sources of entropy, as their seek
+- * times are usually fairly consistent.
+- *
+- * All of these routines try to estimate how many bits of randomness a
+- * particular randomness source. They do this by keeping track of the
+- * first and second order deltas of the event timings.
+- *
+- * Ensuring unpredictability at system startup
+- * ============================================
+- *
+- * When any operating system starts up, it will go through a sequence
+- * of actions that are fairly predictable by an adversary, especially
+- * if the start-up does not involve interaction with a human operator.
+- * This reduces the actual number of bits of unpredictability in the
+- * entropy pool below the value in entropy_count. In order to
+- * counteract this effect, it helps to carry information in the
+- * entropy pool across shut-downs and start-ups. To do this, put the
+- * following lines an appropriate script which is run during the boot
+- * sequence:
+- *
+- * echo "Initializing random number generator..."
+- * random_seed=/var/run/random-seed
+- * # Carry a random seed from start-up to start-up
+- * # Load and then save the whole entropy pool
+- * if [ -f $random_seed ]; then
+- * cat $random_seed >/dev/urandom
+- * else
+- * touch $random_seed
+- * fi
+- * chmod 600 $random_seed
+- * dd if=/dev/urandom of=$random_seed count=1 bs=512
+- *
+- * and the following lines in an appropriate script which is run as
+- * the system is shutdown:
+- *
+- * # Carry a random seed from shut-down to start-up
+- * # Save the whole entropy pool
+- * echo "Saving random seed..."
+- * random_seed=/var/run/random-seed
+- * touch $random_seed
+- * chmod 600 $random_seed
+- * dd if=/dev/urandom of=$random_seed count=1 bs=512
+- *
+- * For example, on most modern systems using the System V init
+- * scripts, such code fragments would be found in
+- * /etc/rc.d/init.d/random. On older Linux systems, the correct script
+- * location might be in /etc/rcb.d/rc.local or /etc/rc.d/rc.0.
+- *
+- * Effectively, these commands cause the contents of the entropy pool
+- * to be saved at shut-down time and reloaded into the entropy pool at
+- * start-up. (The 'dd' in the addition to the bootup script is to
+- * make sure that /etc/random-seed is different for every start-up,
+- * even if the system crashes without executing rc.0.) Even with
+- * complete knowledge of the start-up activities, predicting the state
+- * of the entropy pool requires knowledge of the previous history of
+- * the system.
+- *
+- * Configuring the /dev/random driver under Linux
+- * ==============================================
+- *
+- * The /dev/random driver under Linux uses minor numbers 8 and 9 of
+- * the /dev/mem major number (#1). So if your system does not have
+- * /dev/random and /dev/urandom created already, they can be created
+- * by using the commands:
+- *
+- * mknod /dev/random c 1 8
+- * mknod /dev/urandom c 1 9
+- *
+- * Acknowledgements:
+- * =================
+- *
+- * Ideas for constructing this random number generator were derived
+- * from Pretty Good Privacy's random number generator, and from private
+- * discussions with Phil Karn. Colin Plumb provided a faster random
+- * number generator, which speed up the mixing function of the entropy
+- * pool, taken from PGPfone. Dale Worley has also contributed many
+- * useful ideas and suggestions to improve this driver.
+- *
+- * Any flaws in the design are solely my responsibility, and should
+- * not be attributed to the Phil, Colin, or any of authors of PGP.
+- *
+- * Further background information on this topic may be obtained from
+- * RFC 1750, "Randomness Recommendations for Security", by Donald
+- * Eastlake, Steve Crocker, and Jeff Schiller.
++ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All rights reserved.
++ *
++ * This driver produces cryptographically secure pseudorandom data. It is divided
++ * into roughly six sections, each with a section header:
++ *
++ * - Initialization and readiness waiting.
++ * - Fast key erasure RNG, the "crng".
++ * - Entropy accumulation and extraction routines.
++ * - Entropy collection routines.
++ * - Userspace reader/writer interfaces.
++ * - Sysctl interface.
++ *
++ * The high level overview is that there is one input pool, into which
++ * various pieces of data are hashed. Prior to initialization, some of that
++ * data is then "credited" as having a certain number of bits of entropy.
++ * When enough bits of entropy are available, the hash is finalized and
++ * handed as a key to a stream cipher that expands it indefinitely for
++ * various consumers. This key is periodically refreshed as the various
++ * entropy collectors, described below, add data to the input pool.
*/
- static int crng_init = 0;
-+static bool crng_need_final_init = false;
- #define crng_ready() (likely(crng_init > 1))
- static int crng_init_cnt = 0;
- static unsigned long crng_global_init_time = 0;
-@@ -828,6 +829,36 @@ static void __init crng_initialize_primary(struct crng_state *crng)
- crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
- }
-+static void crng_finalize_init(struct crng_state *crng)
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+@@ -327,7 +43,6 @@
+ #include <linux/spinlock.h>
+ #include <linux/kthread.h>
+ #include <linux/percpu.h>
+-#include <linux/fips.h>
+ #include <linux/ptrace.h>
+ #include <linux/workqueue.h>
+ #include <linux/irq.h>
+@@ -335,774 +50,809 @@
+ #include <linux/syscalls.h>
+ #include <linux/completion.h>
+ #include <linux/uuid.h>
++#include <linux/uaccess.h>
++#include <linux/siphash.h>
++#include <linux/uio.h>
+ #include <crypto/chacha.h>
+-#include <crypto/sha1.h>
+-
++#include <crypto/blake2s.h>
+ #include <asm/processor.h>
+-#include <linux/uaccess.h>
+ #include <asm/irq.h>
+ #include <asm/irq_regs.h>
+ #include <asm/io.h>
+
+-#define CREATE_TRACE_POINTS
+-#include <trace/events/random.h>
+-
+-/* #define ADD_INTERRUPT_BENCH */
++/*********************************************************************
++ *
++ * Initialization and readiness waiting.
++ *
++ * Much of the RNG infrastructure is devoted to various dependencies
++ * being able to wait until the RNG has collected enough entropy and
++ * is ready for safe consumption.
++ *
++ *********************************************************************/
+
+ /*
+- * Configuration information
++ * crng_init is protected by base_crng->lock, and only increases
++ * its value (from empty->early->ready).
+ */
+-#define INPUT_POOL_SHIFT 12
+-#define INPUT_POOL_WORDS (1 << (INPUT_POOL_SHIFT-5))
+-#define OUTPUT_POOL_SHIFT 10
+-#define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5))
+-#define EXTRACT_SIZE 10
+-
++static enum {
++ CRNG_EMPTY = 0, /* Little to no entropy collected */
++ CRNG_EARLY = 1, /* At least POOL_EARLY_BITS collected */
++ CRNG_READY = 2 /* Fully initialized with POOL_READY_BITS collected */
++} crng_init __read_mostly = CRNG_EMPTY;
++static DEFINE_STATIC_KEY_FALSE(crng_is_ready);
++#define crng_ready() (static_branch_likely(&crng_is_ready) || crng_init >= CRNG_READY)
++/* Various types of waiters for crng_init->CRNG_READY transition. */
++static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
++static struct fasync_struct *fasync;
++static DEFINE_SPINLOCK(random_ready_chain_lock);
++static RAW_NOTIFIER_HEAD(random_ready_chain);
+
+-#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
++/* Control how we warn userspace. */
++static struct ratelimit_state urandom_warning =
++ RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
++static int ratelimit_disable __read_mostly =
++ IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
++module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
++MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
+
+ /*
+- * To allow fractional bits to be tracked, the entropy_count field is
+- * denominated in units of 1/8th bits.
++ * Returns whether or not the input pool has been seeded and thus guaranteed
++ * to supply cryptographically secure random numbers. This applies to: the
++ * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
++ * ,u64,int,long} family of functions.
+ *
+- * 2*(ENTROPY_SHIFT + poolbitshift) must <= 31, or the multiply in
+- * credit_entropy_bits() needs to be 64 bits wide.
++ * Returns: true if the input pool has been seeded.
++ * false if the input pool has not been seeded.
+ */
+-#define ENTROPY_SHIFT 3
+-#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
++bool rng_is_initialized(void)
+{
-+ if (crng != &primary_crng || crng_init >= 2)
-+ return;
-+ if (!system_wq) {
-+ /* We can't call numa_crng_init until we have workqueues,
-+ * so mark this for processing later. */
-+ crng_need_final_init = true;
-+ return;
-+ }
++ return crng_ready();
++}
++EXPORT_SYMBOL(rng_is_initialized);
+
+-/*
+- * If the entropy count falls under this number of bits, then we
+- * should wake up processes which are selecting or polling on write
+- * access to /dev/random.
+- */
+-static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
++static void __cold crng_set_ready(struct work_struct *work)
++{
++ static_branch_enable(&crng_is_ready);
++}
+
-+ invalidate_batched_entropy();
-+ numa_crng_init();
-+ crng_init = 2;
-+ process_random_ready_list();
-+ wake_up_interruptible(&crng_init_wait);
-+ kill_fasync(&fasync, SIGIO, POLL_IN);
-+ pr_notice("crng init done\n");
-+ if (unseeded_warning.missed) {
-+ pr_notice("%d get_random_xx warning(s) missed due to ratelimiting\n",
-+ unseeded_warning.missed);
-+ unseeded_warning.missed = 0;
-+ }
-+ if (urandom_warning.missed) {
-+ pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
-+ urandom_warning.missed);
-+ urandom_warning.missed = 0;
++/* Used by wait_for_random_bytes(), and considered an entropy collector, below. */
++static void try_to_generate_entropy(void);
+
+ /*
+- * Originally, we used a primitive polynomial of degree .poolwords
+- * over GF(2). The taps for various sizes are defined below. They
+- * were chosen to be evenly spaced except for the last tap, which is 1
+- * to get the twisting happening as fast as possible.
+- *
+- * For the purposes of better mixing, we use the CRC-32 polynomial as
+- * well to make a (modified) twisted Generalized Feedback Shift
+- * Register. (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR
+- * generators. ACM Transactions on Modeling and Computer Simulation
+- * 2(3):179-194. Also see M. Matsumoto & Y. Kurita, 1994. Twisted
+- * GFSR generators II. ACM Transactions on Modeling and Computer
+- * Simulation 4:254-266)
+- *
+- * Thanks to Colin Plumb for suggesting this.
+- *
+- * The mixing operation is much less sensitive than the output hash,
+- * where we use SHA-1. All that we want of mixing operation is that
+- * it be a good non-cryptographic hash; i.e. it not produce collisions
+- * when fed "random" data of the sort we expect to see. As long as
+- * the pool state differs for different inputs, we have preserved the
+- * input entropy and done a good job. The fact that an intelligent
+- * attacker can construct inputs that will produce controlled
+- * alterations to the pool's state is not important because we don't
+- * consider such inputs to contribute any randomness. The only
+- * property we need with respect to them is that the attacker can't
+- * increase his/her knowledge of the pool's state. Since all
+- * additions are reversible (knowing the final state and the input,
+- * you can reconstruct the initial state), if an attacker has any
+- * uncertainty about the initial state, he/she can only shuffle that
+- * uncertainty about, but never cause any collisions (which would
+- * decrease the uncertainty).
++ * Wait for the input pool to be seeded and thus guaranteed to supply
++ * cryptographically secure random numbers. This applies to: the /dev/urandom
++ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
++ * family of functions. Using any of these functions without first calling
++ * this function forfeits the guarantee of security.
+ *
+- * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
+- * Videau in their paper, "The Linux Pseudorandom Number Generator
+- * Revisited" (see: http://eprint.iacr.org/2012/251.pdf). In their
+- * paper, they point out that we are not using a true Twisted GFSR,
+- * since Matsumoto & Kurita used a trinomial feedback polynomial (that
+- * is, with only three taps, instead of the six that we are using).
+- * As a result, the resulting polynomial is neither primitive nor
+- * irreducible, and hence does not have a maximal period over
+- * GF(2**32). They suggest a slight change to the generator
+- * polynomial which improves the resulting TGFSR polynomial to be
+- * irreducible, which we have made here.
++ * Returns: 0 if the input pool has been seeded.
++ * -ERESTARTSYS if the function was interrupted by a signal.
+ */
+-static const struct poolinfo {
+- int poolbitshift, poolwords, poolbytes, poolfracbits;
+-#define S(x) ilog2(x)+5, (x), (x)*4, (x) << (ENTROPY_SHIFT+5)
+- int tap1, tap2, tap3, tap4, tap5;
+-} poolinfo_table[] = {
+- /* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
+- /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
+- { S(128), 104, 76, 51, 25, 1 },
+-};
++int wait_for_random_bytes(void)
++{
++ while (!crng_ready()) {
++ int ret;
++
++ try_to_generate_entropy();
++ ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
++ if (ret)
++ return ret > 0 ? 0 : ret;
+ }
++ return 0;
++}
++EXPORT_SYMBOL(wait_for_random_bytes);
+
+ /*
+- * Static global variables
++ * Add a callback function that will be invoked when the input
++ * pool is initialised.
++ *
++ * returns: 0 if callback is successfully added
++ * -EALREADY if pool is already initialised (callback not called)
+ */
+-static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+-static struct fasync_struct *fasync;
+-
+-static DEFINE_SPINLOCK(random_ready_list_lock);
+-static LIST_HEAD(random_ready_list);
++int __cold register_random_ready_notifier(struct notifier_block *nb)
++{
++ unsigned long flags;
++ int ret = -EALREADY;
+
+-struct crng_state {
+- __u32 state[16];
+- unsigned long init_time;
+- spinlock_t lock;
+-};
++ if (crng_ready())
++ return ret;
+
+-static struct crng_state primary_crng = {
+- .lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
+-};
++ spin_lock_irqsave(&random_ready_chain_lock, flags);
++ if (!crng_ready())
++ ret = raw_notifier_chain_register(&random_ready_chain, nb);
++ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
++ return ret;
+}
++EXPORT_SYMBOL(register_random_ready_notifier);
+
+ /*
+- * crng_init = 0 --> Uninitialized
+- * 1 --> Initialized
+- * 2 --> Initialized from input_pool
+- *
+- * crng_init is protected by primary_crng->lock, and only increases
+- * its value (from 0->1->2).
++ * Delete a previously registered readiness callback function.
+ */
+-static int crng_init = 0;
+-#define crng_ready() (likely(crng_init > 1))
+-static int crng_init_cnt = 0;
+-static unsigned long crng_global_init_time = 0;
+-#define CRNG_INIT_CNT_THRESH (2*CHACHA_KEY_SIZE)
+-static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]);
+-static void _crng_backtrack_protect(struct crng_state *crng,
+- __u8 tmp[CHACHA_BLOCK_SIZE], int used);
+-static void process_random_ready_list(void);
+-static void _get_random_bytes(void *buf, int nbytes);
+-
+-static struct ratelimit_state unseeded_warning =
+- RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
+-static struct ratelimit_state urandom_warning =
+- RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
++int __cold unregister_random_ready_notifier(struct notifier_block *nb)
++{
++ unsigned long flags;
++ int ret;
+
+-static int ratelimit_disable __read_mostly;
++ spin_lock_irqsave(&random_ready_chain_lock, flags);
++ ret = raw_notifier_chain_unregister(&random_ready_chain, nb);
++ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
++ return ret;
++}
++EXPORT_SYMBOL(unregister_random_ready_notifier);
+
+-module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
+-MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
++static void __cold process_random_ready_list(void)
++{
++ unsigned long flags;
+
+-/**********************************************************************
++ spin_lock_irqsave(&random_ready_chain_lock, flags);
++ raw_notifier_call_chain(&random_ready_chain, 0, NULL);
++ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
++}
++
++#define warn_unseeded_randomness() \
++ if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
++ printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
++ __func__, (void *)_RET_IP_, crng_init)
++
+
- #ifdef CONFIG_NUMA
- static void do_numa_crng_init(struct work_struct *work)
++/*********************************************************************
+ *
+- * OS independent entropy store. Here are the functions which handle
+- * storing entropy in an entropy pool.
++ * Fast key erasure RNG, the "crng".
+ *
+- **********************************************************************/
++ * These functions expand entropy from the entropy extractor into
++ * long streams for external consumption using the "fast key erasure"
++ * RNG described at <https://blog.cr.yp.to/20170723-random.html>.
++ *
++ * There are a few exported interfaces for use by other drivers:
++ *
++ * void get_random_bytes(void *buf, size_t len)
++ * u32 get_random_u32()
++ * u64 get_random_u64()
++ * unsigned int get_random_int()
++ * unsigned long get_random_long()
++ *
++ * These interfaces will return the requested number of random bytes
++ * into the given buffer or as a return value. This is equivalent to
++ * a read from /dev/urandom. The u32, u64, int, and long family of
++ * functions may be higher performance for one-off random integers,
++ * because they do a bit of buffering and do not invoke reseeding
++ * until the buffer is emptied.
++ *
++ *********************************************************************/
+
+-struct entropy_store;
+-struct entropy_store {
+- /* read-only data: */
+- const struct poolinfo *poolinfo;
+- __u32 *pool;
+- const char *name;
++enum {
++ CRNG_RESEED_START_INTERVAL = HZ,
++ CRNG_RESEED_INTERVAL = 60 * HZ
++};
+
+- /* read-write data: */
++static struct {
++ u8 key[CHACHA_KEY_SIZE] __aligned(__alignof__(long));
++ unsigned long birth;
++ unsigned long generation;
+ spinlock_t lock;
+- unsigned short add_ptr;
+- unsigned short input_rotate;
+- int entropy_count;
+- unsigned int last_data_init:1;
+- __u8 last_data[EXTRACT_SIZE];
++} base_crng = {
++ .lock = __SPIN_LOCK_UNLOCKED(base_crng.lock)
+ };
+
+-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+- size_t nbytes, int min, int rsvd);
+-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
+- size_t nbytes, int fips);
+-
+-static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
+-static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
+-
+-static struct entropy_store input_pool = {
+- .poolinfo = &poolinfo_table[0],
+- .name = "input",
+- .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
+- .pool = input_pool_data
++struct crng {
++ u8 key[CHACHA_KEY_SIZE];
++ unsigned long generation;
++ local_lock_t lock;
+ };
+
+-static __u32 const twist_table[8] = {
+- 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+- 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+-
+-/*
+- * This function adds bytes into the entropy "pool". It does not
+- * update the entropy estimate. The caller should call
+- * credit_entropy_bits if this is appropriate.
+- *
+- * The pool is stirred with a primitive polynomial of the appropriate
+- * degree, and then twisted. We twist by three bits at a time because
+- * it's cheap to do so and helps slightly in the expected case where
+- * the entropy is concentrated in the low-order bits.
+- */
+-static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+- int nbytes)
+-{
+- unsigned long i, tap1, tap2, tap3, tap4, tap5;
+- int input_rotate;
+- int wordmask = r->poolinfo->poolwords - 1;
+- const char *bytes = in;
+- __u32 w;
+-
+- tap1 = r->poolinfo->tap1;
+- tap2 = r->poolinfo->tap2;
+- tap3 = r->poolinfo->tap3;
+- tap4 = r->poolinfo->tap4;
+- tap5 = r->poolinfo->tap5;
+-
+- input_rotate = r->input_rotate;
+- i = r->add_ptr;
+-
+- /* mix one byte at a time to simplify size handling and churn faster */
+- while (nbytes--) {
+- w = rol32(*bytes++, input_rotate);
+- i = (i - 1) & wordmask;
+-
+- /* XOR in the various taps */
+- w ^= r->pool[i];
+- w ^= r->pool[(i + tap1) & wordmask];
+- w ^= r->pool[(i + tap2) & wordmask];
+- w ^= r->pool[(i + tap3) & wordmask];
+- w ^= r->pool[(i + tap4) & wordmask];
+- w ^= r->pool[(i + tap5) & wordmask];
+-
+- /* Mix the result back in with a twist */
+- r->pool[i] = (w >> 3) ^ twist_table[w & 7];
+-
+- /*
+- * Normally, we add 7 bits of rotation to the pool.
+- * At the beginning of the pool, add an extra 7 bits
+- * rotation, so that successive passes spread the
+- * input bits across the pool evenly.
+- */
+- input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
+- }
+-
+- r->input_rotate = input_rotate;
+- r->add_ptr = i;
+-}
++static DEFINE_PER_CPU(struct crng, crngs) = {
++ .generation = ULONG_MAX,
++ .lock = INIT_LOCAL_LOCK(crngs.lock),
++};
+
+-static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+- int nbytes)
+-{
+- trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
+- _mix_pool_bytes(r, in, nbytes);
+-}
++/* Used by crng_reseed() and crng_make_state() to extract a new seed from the input pool. */
++static void extract_entropy(void *buf, size_t len);
+
+-static void mix_pool_bytes(struct entropy_store *r, const void *in,
+- int nbytes)
++/* This extracts a new crng key from the input pool. */
++static void crng_reseed(void)
{
-@@ -843,8 +874,8 @@ static void do_numa_crng_init(struct work_struct *work)
- crng_initialize_secondary(crng);
- pool[i] = crng;
+ unsigned long flags;
++ unsigned long next_gen;
++ u8 key[CHACHA_KEY_SIZE];
+
+- trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
+- spin_lock_irqsave(&r->lock, flags);
+- _mix_pool_bytes(r, in, nbytes);
+- spin_unlock_irqrestore(&r->lock, flags);
+-}
++ extract_entropy(key, sizeof(key));
+
+-struct fast_pool {
+- __u32 pool[4];
+- unsigned long last;
+- unsigned short reg_idx;
+- unsigned char count;
+-};
++ /*
++ * We copy the new key into the base_crng, overwriting the old one,
++ * and update the generation counter. We avoid hitting ULONG_MAX,
++ * because the per-cpu crngs are initialized to ULONG_MAX, so this
++ * forces new CPUs that come online to always initialize.
++ */
++ spin_lock_irqsave(&base_crng.lock, flags);
++ memcpy(base_crng.key, key, sizeof(base_crng.key));
++ next_gen = base_crng.generation + 1;
++ if (next_gen == ULONG_MAX)
++ ++next_gen;
++ WRITE_ONCE(base_crng.generation, next_gen);
++ WRITE_ONCE(base_crng.birth, jiffies);
++ if (!static_branch_likely(&crng_is_ready))
++ crng_init = CRNG_READY;
++ spin_unlock_irqrestore(&base_crng.lock, flags);
++ memzero_explicit(key, sizeof(key));
++}
+
+ /*
+- * This is a fast mixing routine used by the interrupt randomness
+- * collector. It's hardcoded for an 128 bit pool and assumes that any
+- * locks that might be needed are taken by the caller.
++ * This generates a ChaCha block using the provided key, and then
++ * immediately overwites that key with half the block. It returns
++ * the resultant ChaCha state to the user, along with the second
++ * half of the block containing 32 bytes of random data that may
++ * be used; random_data_len may not be greater than 32.
++ *
++ * The returned ChaCha state contains within it a copy of the old
++ * key value, at index 4, so the state should always be zeroed out
++ * immediately after using in order to maintain forward secrecy.
++ * If the state cannot be erased in a timely manner, then it is
++ * safer to set the random_data parameter to &chacha_state[4] so
++ * that this function overwrites it before returning.
+ */
+-static void fast_mix(struct fast_pool *f)
++static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
++ u32 chacha_state[CHACHA_STATE_WORDS],
++ u8 *random_data, size_t random_data_len)
+ {
+- __u32 a = f->pool[0], b = f->pool[1];
+- __u32 c = f->pool[2], d = f->pool[3];
+-
+- a += b; c += d;
+- b = rol32(b, 6); d = rol32(d, 27);
+- d ^= a; b ^= c;
++ u8 first_block[CHACHA_BLOCK_SIZE];
+
+- a += b; c += d;
+- b = rol32(b, 16); d = rol32(d, 14);
+- d ^= a; b ^= c;
++ BUG_ON(random_data_len > 32);
+
+- a += b; c += d;
+- b = rol32(b, 6); d = rol32(d, 27);
+- d ^= a; b ^= c;
++ chacha_init_consts(chacha_state);
++ memcpy(&chacha_state[4], key, CHACHA_KEY_SIZE);
++ memset(&chacha_state[12], 0, sizeof(u32) * 4);
++ chacha20_block(chacha_state, first_block);
+
+- a += b; c += d;
+- b = rol32(b, 16); d = rol32(d, 14);
+- d ^= a; b ^= c;
+-
+- f->pool[0] = a; f->pool[1] = b;
+- f->pool[2] = c; f->pool[3] = d;
+- f->count++;
++ memcpy(key, first_block, CHACHA_KEY_SIZE);
++ memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len);
++ memzero_explicit(first_block, sizeof(first_block));
+ }
+
+-static void process_random_ready_list(void)
++/*
++ * Return whether the crng seed is considered to be sufficiently old
++ * that a reseeding is needed. This happens if the last reseeding
++ * was CRNG_RESEED_INTERVAL ago, or during early boot, at an interval
++ * proportional to the uptime.
++ */
++static bool crng_has_old_seed(void)
+ {
+- unsigned long flags;
+- struct random_ready_callback *rdy, *tmp;
+-
+- spin_lock_irqsave(&random_ready_list_lock, flags);
+- list_for_each_entry_safe(rdy, tmp, &random_ready_list, list) {
+- struct module *owner = rdy->owner;
+-
+- list_del_init(&rdy->list);
+- rdy->func(rdy);
+- module_put(owner);
++ static bool early_boot = true;
++ unsigned long interval = CRNG_RESEED_INTERVAL;
++
++ if (unlikely(READ_ONCE(early_boot))) {
++ time64_t uptime = ktime_get_seconds();
++ if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
++ WRITE_ONCE(early_boot, false);
++ else
++ interval = max_t(unsigned int, CRNG_RESEED_START_INTERVAL,
++ (unsigned int)uptime / 2 * HZ);
}
-- mb();
-- if (cmpxchg(&crng_node_pool, NULL, pool)) {
-+ /* pairs with READ_ONCE() in select_crng() */
-+ if (cmpxchg_release(&crng_node_pool, NULL, pool) != NULL) {
- for_each_node(i)
- kfree(pool[i]);
- kfree(pool);
-@@ -857,18 +888,38 @@ static void numa_crng_init(void)
+- spin_unlock_irqrestore(&random_ready_list_lock, flags);
++ return time_is_before_jiffies(READ_ONCE(base_crng.birth) + interval);
+ }
+
+ /*
+- * Credit (or debit) the entropy store with n bits of entropy.
+- * Use credit_entropy_bits_safe() if the value comes from userspace
+- * or otherwise should be checked for extreme values.
++ * This function returns a ChaCha state that you may use for generating
++ * random data. It also returns up to 32 bytes on its own of random data
++ * that may be used; random_data_len may not be greater than 32.
+ */
+-static void credit_entropy_bits(struct entropy_store *r, int nbits)
++static void crng_make_state(u32 chacha_state[CHACHA_STATE_WORDS],
++ u8 *random_data, size_t random_data_len)
+ {
+- int entropy_count, orig;
+- const int pool_size = r->poolinfo->poolfracbits;
+- int nfrac = nbits << ENTROPY_SHIFT;
++ unsigned long flags;
++ struct crng *crng;
+
+- if (!nbits)
+- return;
++ BUG_ON(random_data_len > 32);
+
+-retry:
+- entropy_count = orig = READ_ONCE(r->entropy_count);
+- if (nfrac < 0) {
+- /* Debit */
+- entropy_count += nfrac;
+- } else {
+- /*
+- * Credit: we have to account for the possibility of
+- * overwriting already present entropy. Even in the
+- * ideal case of pure Shannon entropy, new contributions
+- * approach the full value asymptotically:
+- *
+- * entropy <- entropy + (pool_size - entropy) *
+- * (1 - exp(-add_entropy/pool_size))
+- *
+- * For add_entropy <= pool_size/2 then
+- * (1 - exp(-add_entropy/pool_size)) >=
+- * (add_entropy/pool_size)*0.7869...
+- * so we can approximate the exponential with
+- * 3/4*add_entropy/pool_size and still be on the
+- * safe side by adding at most pool_size/2 at a time.
+- *
+- * The use of pool_size-2 in the while statement is to
+- * prevent rounding artifacts from making the loop
+- * arbitrarily long; this limits the loop to log2(pool_size)*2
+- * turns no matter how large nbits is.
+- */
+- int pnfrac = nfrac;
+- const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
+- /* The +2 corresponds to the /4 in the denominator */
+-
+- do {
+- unsigned int anfrac = min(pnfrac, pool_size/2);
+- unsigned int add =
+- ((pool_size - entropy_count)*anfrac*3) >> s;
+-
+- entropy_count += add;
+- pnfrac -= anfrac;
+- } while (unlikely(entropy_count < pool_size-2 && pnfrac));
++ /*
++ * For the fast path, we check whether we're ready, unlocked first, and
++ * then re-check once locked later. In the case where we're really not
++ * ready, we do fast key erasure with the base_crng directly, extracting
++ * when crng_init is CRNG_EMPTY.
++ */
++ if (!crng_ready()) {
++ bool ready;
++
++ spin_lock_irqsave(&base_crng.lock, flags);
++ ready = crng_ready();
++ if (!ready) {
++ if (crng_init == CRNG_EMPTY)
++ extract_entropy(base_crng.key, sizeof(base_crng.key));
++ crng_fast_key_erasure(base_crng.key, chacha_state,
++ random_data, random_data_len);
++ }
++ spin_unlock_irqrestore(&base_crng.lock, flags);
++ if (!ready)
++ return;
+ }
+
+- if (WARN_ON(entropy_count < 0)) {
+- pr_warn("negative entropy/overflow: pool %s count %d\n",
+- r->name, entropy_count);
+- entropy_count = 0;
+- } else if (entropy_count > pool_size)
+- entropy_count = pool_size;
+- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+- goto retry;
+-
+- trace_credit_entropy_bits(r->name, nbits,
+- entropy_count >> ENTROPY_SHIFT, _RET_IP_);
++ /*
++ * If the base_crng is old enough, we reseed, which in turn bumps the
++ * generation counter that we check below.
++ */
++ if (unlikely(crng_has_old_seed()))
++ crng_reseed();
+
+- if (r == &input_pool) {
+- int entropy_bits = entropy_count >> ENTROPY_SHIFT;
++ local_lock_irqsave(&crngs.lock, flags);
++ crng = raw_cpu_ptr(&crngs);
+
+- if (crng_init < 2 && entropy_bits >= 128)
+- crng_reseed(&primary_crng, r);
++ /*
++ * If our per-cpu crng is older than the base_crng, then it means
++ * somebody reseeded the base_crng. In that case, we do fast key
++ * erasure on the base_crng, and use its output as the new key
++ * for our per-cpu crng. This brings us up to date with base_crng.
++ */
++ if (unlikely(crng->generation != READ_ONCE(base_crng.generation))) {
++ spin_lock(&base_crng.lock);
++ crng_fast_key_erasure(base_crng.key, chacha_state,
++ crng->key, sizeof(crng->key));
++ crng->generation = base_crng.generation;
++ spin_unlock(&base_crng.lock);
+ }
++
++ /*
++ * Finally, when we've made it this far, our per-cpu crng has an up
++ * to date key, and we can do fast key erasure with it to produce
++ * some random data and a ChaCha state for the caller. All other
++ * branches of this function are "unlikely", so most of the time we
++ * should wind up here immediately.
++ */
++ crng_fast_key_erasure(crng->key, chacha_state, random_data, random_data_len);
++ local_unlock_irqrestore(&crngs.lock, flags);
+ }
+
+-static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
++static void _get_random_bytes(void *buf, size_t len)
{
- schedule_work(&numa_crng_init_work);
+- const int nbits_max = r->poolinfo->poolwords * 32;
+-
+- if (nbits < 0)
+- return -EINVAL;
++ u32 chacha_state[CHACHA_STATE_WORDS];
++ u8 tmp[CHACHA_BLOCK_SIZE];
++ size_t first_block_len;
+
+- /* Cap the value to avoid overflows */
+- nbits = min(nbits, nbits_max);
++ if (!len)
++ return;
+
+- credit_entropy_bits(r, nbits);
+- return 0;
+-}
++ first_block_len = min_t(size_t, 32, len);
++ crng_make_state(chacha_state, buf, first_block_len);
++ len -= first_block_len;
++ buf += first_block_len;
+
+-/*********************************************************************
+- *
+- * CRNG using CHACHA20
+- *
+- *********************************************************************/
++ while (len) {
++ if (len < CHACHA_BLOCK_SIZE) {
++ chacha20_block(chacha_state, tmp);
++ memcpy(buf, tmp, len);
++ memzero_explicit(tmp, sizeof(tmp));
++ break;
++ }
+
+-#define CRNG_RESEED_INTERVAL (300*HZ)
++ chacha20_block(chacha_state, buf);
++ if (unlikely(chacha_state[12] == 0))
++ ++chacha_state[13];
++ len -= CHACHA_BLOCK_SIZE;
++ buf += CHACHA_BLOCK_SIZE;
++ }
+
+-static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
++ memzero_explicit(chacha_state, sizeof(chacha_state));
++}
+
+-#ifdef CONFIG_NUMA
+ /*
+- * Hack to deal with crazy userspace progams when they are all trying
+- * to access /dev/urandom in parallel. The programs are almost
+- * certainly doing something terribly wrong, but we'll work around
+- * their brain damage.
++ * This function is the exported kernel interface. It returns some
++ * number of good random numbers, suitable for key generation, seeding
++ * TCP sequence numbers, etc. It does not rely on the hardware random
++ * number generator. For random bytes direct from the hardware RNG
++ * (when available), use get_random_bytes_arch(). In order to ensure
++ * that the randomness provided by this function is okay, the function
++ * wait_for_random_bytes() should be called and return 0 at least once
++ * at any point prior.
+ */
+-static struct crng_state **crng_node_pool __read_mostly;
+-#endif
+-
+-static void invalidate_batched_entropy(void);
+-static void numa_crng_init(void);
+-
+-static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
+-static int __init parse_trust_cpu(char *arg)
++void get_random_bytes(void *buf, size_t len)
+ {
+- return kstrtobool(arg, &trust_cpu);
++ warn_unseeded_randomness();
++ _get_random_bytes(buf, len);
}
+-early_param("random.trust_cpu", parse_trust_cpu);
++EXPORT_SYMBOL(get_random_bytes);
+
+-static bool crng_init_try_arch(struct crng_state *crng)
++static ssize_t get_random_bytes_user(struct iov_iter *iter)
+ {
+- int i;
+- bool arch_init = true;
+- unsigned long rv;
+-
+- for (i = 4; i < 16; i++) {
+- if (!arch_get_random_seed_long(&rv) &&
+- !arch_get_random_long(&rv)) {
+- rv = random_get_entropy();
+- arch_init = false;
+- }
+- crng->state[i] ^= rv;
++ u32 chacha_state[CHACHA_STATE_WORDS];
++ u8 block[CHACHA_BLOCK_SIZE];
++ size_t ret = 0, copied;
+
-+static struct crng_state *select_crng(void)
-+{
-+ struct crng_state **pool;
-+ int nid = numa_node_id();
++ if (unlikely(!iov_iter_count(iter)))
++ return 0;
+
-+ /* pairs with cmpxchg_release() in do_numa_crng_init() */
-+ pool = READ_ONCE(crng_node_pool);
-+ if (pool && pool[nid])
-+ return pool[nid];
++ /*
++ * Immediately overwrite the ChaCha key at index 4 with random
++ * bytes, in case userspace causes copy_to_user() below to sleep
++ * forever, so that we still retain forward secrecy in that case.
++ */
++ crng_make_state(chacha_state, (u8 *)&chacha_state[4], CHACHA_KEY_SIZE);
++ /*
++ * However, if we're doing a read of len <= 32, we don't need to
++ * use chacha_state after, so we can simply return those bytes to
++ * the user directly.
++ */
++ if (iov_iter_count(iter) <= CHACHA_KEY_SIZE) {
++ ret = copy_to_iter(&chacha_state[4], CHACHA_KEY_SIZE, iter);
++ goto out_zero_chacha;
+ }
+
+- return arch_init;
+-}
++ for (;;) {
++ chacha20_block(chacha_state, block);
++ if (unlikely(chacha_state[12] == 0))
++ ++chacha_state[13];
+
+-static bool __init crng_init_try_arch_early(struct crng_state *crng)
+-{
+- int i;
+- bool arch_init = true;
+- unsigned long rv;
+-
+- for (i = 4; i < 16; i++) {
+- if (!arch_get_random_seed_long_early(&rv) &&
+- !arch_get_random_long_early(&rv)) {
+- rv = random_get_entropy();
+- arch_init = false;
++ copied = copy_to_iter(block, sizeof(block), iter);
++ ret += copied;
++ if (!iov_iter_count(iter) || copied != sizeof(block))
++ break;
+
-+ return &primary_crng;
-+}
- #else
- static void numa_crng_init(void) {}
++ BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
++ if (ret % PAGE_SIZE == 0) {
++ if (signal_pending(current))
++ break;
++ cond_resched();
+ }
+- crng->state[i] ^= rv;
+ }
+
+- return arch_init;
++ memzero_explicit(block, sizeof(block));
++out_zero_chacha:
++ memzero_explicit(chacha_state, sizeof(chacha_state));
++ return ret ? ret : -EFAULT;
+ }
+
+-static void __maybe_unused crng_initialize_secondary(struct crng_state *crng)
+-{
+- chacha_init_consts(crng->state);
+- _get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
+- crng_init_try_arch(crng);
+- crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+-}
++/*
++ * Batched entropy returns random integers. The quality of the random
++ * number is good as /dev/urandom. In order to ensure that the randomness
++ * provided by this function is okay, the function wait_for_random_bytes()
++ * should be called and return 0 at least once at any point prior.
++ */
+
+-static void __init crng_initialize_primary(struct crng_state *crng)
++#define DEFINE_BATCHED_ENTROPY(type) \
++struct batch_ ##type { \
++ /* \
++ * We make this 1.5x a ChaCha block, so that we get the \
++ * remaining 32 bytes from fast key erasure, plus one full \
++ * block from the detached ChaCha state. We can increase \
++ * the size of this later if needed so long as we keep the \
++ * formula of (integer_blocks + 0.5) * CHACHA_BLOCK_SIZE. \
++ */ \
++ type entropy[CHACHA_BLOCK_SIZE * 3 / (2 * sizeof(type))]; \
++ local_lock_t lock; \
++ unsigned long generation; \
++ unsigned int position; \
++}; \
++ \
++static DEFINE_PER_CPU(struct batch_ ##type, batched_entropy_ ##type) = { \
++ .lock = INIT_LOCAL_LOCK(batched_entropy_ ##type.lock), \
++ .position = UINT_MAX \
++}; \
++ \
++type get_random_ ##type(void) \
++{ \
++ type ret; \
++ unsigned long flags; \
++ struct batch_ ##type *batch; \
++ unsigned long next_gen; \
++ \
++ warn_unseeded_randomness(); \
++ \
++ if (!crng_ready()) { \
++ _get_random_bytes(&ret, sizeof(ret)); \
++ return ret; \
++ } \
++ \
++ local_lock_irqsave(&batched_entropy_ ##type.lock, flags); \
++ batch = raw_cpu_ptr(&batched_entropy_##type); \
++ \
++ next_gen = READ_ONCE(base_crng.generation); \
++ if (batch->position >= ARRAY_SIZE(batch->entropy) || \
++ next_gen != batch->generation) { \
++ _get_random_bytes(batch->entropy, sizeof(batch->entropy)); \
++ batch->position = 0; \
++ batch->generation = next_gen; \
++ } \
++ \
++ ret = batch->entropy[batch->position]; \
++ batch->entropy[batch->position] = 0; \
++ ++batch->position; \
++ local_unlock_irqrestore(&batched_entropy_ ##type.lock, flags); \
++ return ret; \
++} \
++EXPORT_SYMBOL(get_random_ ##type);
++
++DEFINE_BATCHED_ENTROPY(u64)
++DEFINE_BATCHED_ENTROPY(u32)
++
++#ifdef CONFIG_SMP
++/*
++ * This function is called when the CPU is coming up, with entry
++ * CPUHP_RANDOM_PREPARE, which comes before CPUHP_WORKQUEUE_PREP.
++ */
++int __cold random_prepare_cpu(unsigned int cpu)
+ {
+- chacha_init_consts(crng->state);
+- _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);
+- if (crng_init_try_arch_early(crng) && trust_cpu) {
+- invalidate_batched_entropy();
+- numa_crng_init();
+- crng_init = 2;
+- pr_notice("crng done (trusting CPU's manufacturer)\n");
+- }
+- crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
++ /*
++ * When the cpu comes back online, immediately invalidate both
++ * the per-cpu crng and all batches, so that we serve fresh
++ * randomness.
++ */
++ per_cpu_ptr(&crngs, cpu)->generation = ULONG_MAX;
++ per_cpu_ptr(&batched_entropy_u32, cpu)->position = UINT_MAX;
++ per_cpu_ptr(&batched_entropy_u64, cpu)->position = UINT_MAX;
++ return 0;
+ }
++#endif
+
+-#ifdef CONFIG_NUMA
+-static void do_numa_crng_init(struct work_struct *work)
++/*
++ * This function will use the architecture-specific hardware random
++ * number generator if it is available. It is not recommended for
++ * use. Use get_random_bytes() instead. It returns the number of
++ * bytes filled in.
++ */
++size_t __must_check get_random_bytes_arch(void *buf, size_t len)
+ {
+- int i;
+- struct crng_state *crng;
+- struct crng_state **pool;
+-
+- pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
+- for_each_online_node(i) {
+- crng = kmalloc_node(sizeof(struct crng_state),
+- GFP_KERNEL | __GFP_NOFAIL, i);
+- spin_lock_init(&crng->lock);
+- crng_initialize_secondary(crng);
+- pool[i] = crng;
+- }
+- mb();
+- if (cmpxchg(&crng_node_pool, NULL, pool)) {
+- for_each_node(i)
+- kfree(pool[i]);
+- kfree(pool);
++ size_t left = len;
++ u8 *p = buf;
+
-+static struct crng_state *select_crng(void)
-+{
-+ return &primary_crng;
-+}
- #endif
++ while (left) {
++ unsigned long v;
++ size_t block_len = min_t(size_t, left, sizeof(unsigned long));
++
++ if (!arch_get_random_long(&v))
++ break;
++
++ memcpy(p, &v, block_len);
++ p += block_len;
++ left -= block_len;
+ }
++
++ return len - left;
+ }
++EXPORT_SYMBOL(get_random_bytes_arch);
++
++
++/**********************************************************************
++ *
++ * Entropy accumulation and extraction routines.
++ *
++ * Callers may add entropy via:
++ *
++ * static void mix_pool_bytes(const void *buf, size_t len)
++ *
++ * After which, if added entropy should be credited:
++ *
++ * static void credit_init_bits(size_t bits)
++ *
++ * Finally, extract entropy via:
++ *
++ * static void extract_entropy(void *buf, size_t len)
++ *
++ **********************************************************************/
+
+-static DECLARE_WORK(numa_crng_init_work, do_numa_crng_init);
++enum {
++ POOL_BITS = BLAKE2S_HASH_SIZE * 8,
++ POOL_READY_BITS = POOL_BITS, /* When crng_init->CRNG_READY */
++ POOL_EARLY_BITS = POOL_READY_BITS / 2 /* When crng_init->CRNG_EARLY */
++};
+
+-static void numa_crng_init(void)
++static struct {
++ struct blake2s_state hash;
++ spinlock_t lock;
++ unsigned int init_bits;
++} input_pool = {
++ .hash.h = { BLAKE2S_IV0 ^ (0x01010000 | BLAKE2S_HASH_SIZE),
++ BLAKE2S_IV1, BLAKE2S_IV2, BLAKE2S_IV3, BLAKE2S_IV4,
++ BLAKE2S_IV5, BLAKE2S_IV6, BLAKE2S_IV7 },
++ .hash.outlen = BLAKE2S_HASH_SIZE,
++ .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
++};
++
++static void _mix_pool_bytes(const void *buf, size_t len)
+ {
+- schedule_work(&numa_crng_init_work);
++ blake2s_update(&input_pool.hash, buf, len);
+ }
+-#else
+-static void numa_crng_init(void) {}
+-#endif
/*
- * crng_fast_load() can be called by code in the interrupt service
+- * crng_fast_load() can be called by code in the interrupt service
- * path. So we can't afford to dilly-dally.
-+ * path. So we can't afford to dilly-dally. Returns the number of
-+ * bytes processed from cp.
++ * This function adds bytes into the input pool. It does not
++ * update the initialization bit counter; the caller should call
++ * credit_init_bits if this is appropriate.
*/
-static int crng_fast_load(const char *cp, size_t len)
-+static size_t crng_fast_load(const char *cp, size_t len)
++static void mix_pool_bytes(const void *buf, size_t len)
{
unsigned long flags;
- char *p;
-+ size_t ret = 0;
+- char *p;
- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
- return 0;
-@@ -879,7 +930,7 @@ static int crng_fast_load(const char *cp, size_t len)
- p = (unsigned char *) &primary_crng.state[4];
- while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
- p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
+- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
+- return 0;
+- if (crng_init != 0) {
+- spin_unlock_irqrestore(&primary_crng.lock, flags);
+- return 0;
+- }
+- p = (unsigned char *) &primary_crng.state[4];
+- while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
+- p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
- cp++; crng_init_cnt++; len--;
-+ cp++; crng_init_cnt++; len--; ret++;
- }
- spin_unlock_irqrestore(&primary_crng.lock, flags);
- if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
-@@ -887,7 +938,7 @@ static int crng_fast_load(const char *cp, size_t len)
- crng_init = 1;
- pr_notice("fast init done\n");
- }
+- }
+- spin_unlock_irqrestore(&primary_crng.lock, flags);
+- if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
+- invalidate_batched_entropy();
+- crng_init = 1;
+- pr_notice("fast init done\n");
+- }
- return 1;
-+ return ret;
++ spin_lock_irqsave(&input_pool.lock, flags);
++ _mix_pool_bytes(buf, len);
++ spin_unlock_irqrestore(&input_pool.lock, flags);
}
/*
-@@ -962,38 +1013,23 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
- crng->state[i+4] ^= buf.key[i] ^ rv;
- }
- memzero_explicit(&buf, sizeof(buf));
+- * crng_slow_load() is called by add_device_randomness, which has two
+- * attributes. (1) We can't trust the buffer passed to it is
+- * guaranteed to be unpredictable (so it might not have any entropy at
+- * all), and (2) it doesn't have the performance constraints of
+- * crng_fast_load().
+- *
+- * So we do something more comprehensive which is guaranteed to touch
+- * all of the primary_crng's state, and which uses a LFSR with a
+- * period of 255 as part of the mixing algorithm. Finally, we do
+- * *not* advance crng_init_cnt since buffer we may get may be something
+- * like a fixed DMI table (for example), which might very well be
+- * unique to the machine, but is otherwise unvarying.
++ * This is an HKDF-like construction for using the hashed collected entropy
++ * as a PRF key, that's then expanded block-by-block.
+ */
+-static int crng_slow_load(const char *cp, size_t len)
++static void extract_entropy(void *buf, size_t len)
+ {
+- unsigned long flags;
+- static unsigned char lfsr = 1;
+- unsigned char tmp;
+- unsigned i, max = CHACHA_KEY_SIZE;
+- const char * src_buf = cp;
+- char * dest_buf = (char *) &primary_crng.state[4];
+-
+- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
+- return 0;
+- if (crng_init != 0) {
+- spin_unlock_irqrestore(&primary_crng.lock, flags);
+- return 0;
++ unsigned long flags;
++ u8 seed[BLAKE2S_HASH_SIZE], next_key[BLAKE2S_HASH_SIZE];
++ struct {
++ unsigned long rdseed[32 / sizeof(long)];
++ size_t counter;
++ } block;
++ size_t i;
++
++ for (i = 0; i < ARRAY_SIZE(block.rdseed); ++i) {
++ if (!arch_get_random_seed_long(&block.rdseed[i]) &&
++ !arch_get_random_long(&block.rdseed[i]))
++ block.rdseed[i] = random_get_entropy();
+ }
+- if (len > max)
+- max = len;
+-
+- for (i = 0; i < max ; i++) {
+- tmp = lfsr;
+- lfsr >>= 1;
+- if (tmp & 1)
+- lfsr ^= 0xE1;
+- tmp = dest_buf[i % CHACHA_KEY_SIZE];
+- dest_buf[i % CHACHA_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
+- lfsr += (tmp << 3) | (tmp >> 5);
++
++ spin_lock_irqsave(&input_pool.lock, flags);
++
++ /* seed = HASHPRF(last_key, entropy_input) */
++ blake2s_final(&input_pool.hash, seed);
++
++ /* next_key = HASHPRF(seed, RDSEED || 0) */
++ block.counter = 0;
++ blake2s(next_key, (u8 *)&block, seed, sizeof(next_key), sizeof(block), sizeof(seed));
++ blake2s_init_key(&input_pool.hash, BLAKE2S_HASH_SIZE, next_key, sizeof(next_key));
++
++ spin_unlock_irqrestore(&input_pool.lock, flags);
++ memzero_explicit(next_key, sizeof(next_key));
++
++ while (len) {
++ i = min_t(size_t, len, BLAKE2S_HASH_SIZE);
++ /* output = HASHPRF(seed, RDSEED || ++counter) */
++ ++block.counter;
++ blake2s(buf, (u8 *)&block, seed, i, sizeof(block), sizeof(seed));
++ len -= i;
++ buf += i;
+ }
+- spin_unlock_irqrestore(&primary_crng.lock, flags);
+- return 1;
++
++ memzero_explicit(seed, sizeof(seed));
++ memzero_explicit(&block, sizeof(block));
+ }
+
+-static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
++#define credit_init_bits(bits) if (!crng_ready()) _credit_init_bits(bits)
++
++static void __cold _credit_init_bits(size_t bits)
+ {
+- unsigned long flags;
+- int i, num;
+- union {
+- __u8 block[CHACHA_BLOCK_SIZE];
+- __u32 key[8];
+- } buf;
+-
+- if (r) {
+- num = extract_entropy(r, &buf, 32, 16, 0);
+- if (num == 0)
+- return;
+- } else {
+- _extract_crng(&primary_crng, buf.block);
+- _crng_backtrack_protect(&primary_crng, buf.block,
+- CHACHA_KEY_SIZE);
+- }
+- spin_lock_irqsave(&crng->lock, flags);
+- for (i = 0; i < 8; i++) {
+- unsigned long rv;
+- if (!arch_get_random_seed_long(&rv) &&
+- !arch_get_random_long(&rv))
+- rv = random_get_entropy();
+- crng->state[i+4] ^= buf.key[i] ^ rv;
+- }
+- memzero_explicit(&buf, sizeof(buf));
- crng->init_time = jiffies;
-+ WRITE_ONCE(crng->init_time, jiffies);
- spin_unlock_irqrestore(&crng->lock, flags);
+- spin_unlock_irqrestore(&crng->lock, flags);
- if (crng == &primary_crng && crng_init < 2) {
- invalidate_batched_entropy();
- numa_crng_init();
- crng_init = 2;
-- process_random_ready_list();
-- wake_up_interruptible(&crng_init_wait);
-- kill_fasync(&fasync, SIGIO, POLL_IN);
-- pr_notice("crng init done\n");
++ static struct execute_work set_ready;
++ unsigned int new, orig, add;
++ unsigned long flags;
++
++ if (!bits)
++ return;
++
++ add = min_t(size_t, bits, POOL_BITS);
++
++ do {
++ orig = READ_ONCE(input_pool.init_bits);
++ new = min_t(unsigned int, POOL_BITS, orig + add);
++ } while (cmpxchg(&input_pool.init_bits, orig, new) != orig);
++
++ if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
++ crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
++ execute_in_process_context(crng_set_ready, &set_ready);
+ process_random_ready_list();
+ wake_up_interruptible(&crng_init_wait);
+ kill_fasync(&fasync, SIGIO, POLL_IN);
+ pr_notice("crng init done\n");
- if (unseeded_warning.missed) {
- pr_notice("%d get_random_xx warning(s) missed due to ratelimiting\n",
- unseeded_warning.missed);
- unseeded_warning.missed = 0;
- }
- if (urandom_warning.missed) {
-- pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
-- urandom_warning.missed);
++ if (urandom_warning.missed)
+ pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
+ urandom_warning.missed);
- urandom_warning.missed = 0;
-- }
-- }
-+ crng_finalize_init(crng);
++ } else if (orig < POOL_EARLY_BITS && new >= POOL_EARLY_BITS) {
++ spin_lock_irqsave(&base_crng.lock, flags);
++ /* Check if crng_init is CRNG_EMPTY, to avoid race with crng_reseed(). */
++ if (crng_init == CRNG_EMPTY) {
++ extract_entropy(base_crng.key, sizeof(base_crng.key));
++ crng_init = CRNG_EARLY;
+ }
++ spin_unlock_irqrestore(&base_crng.lock, flags);
+ }
}
- static void _extract_crng(struct crng_state *crng,
- __u8 out[CHACHA_BLOCK_SIZE])
+-static void _extract_crng(struct crng_state *crng,
+- __u8 out[CHACHA_BLOCK_SIZE])
++
++/**********************************************************************
++ *
++ * Entropy collection routines.
++ *
++ * The following exported functions are used for pushing entropy into
++ * the above entropy accumulation routines:
++ *
++ * void add_device_randomness(const void *buf, size_t len);
++ * void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
++ * void add_bootloader_randomness(const void *buf, size_t len);
++ * void add_interrupt_randomness(int irq);
++ * void add_input_randomness(unsigned int type, unsigned int code, unsigned int value);
++ * void add_disk_randomness(struct gendisk *disk);
++ *
++ * add_device_randomness() adds data to the input pool that
++ * is likely to differ between two devices (or possibly even per boot).
++ * This would be things like MAC addresses or serial numbers, or the
++ * read-out of the RTC. This does *not* credit any actual entropy to
++ * the pool, but it initializes the pool to different values for devices
++ * that might otherwise be identical and have very little entropy
++ * available to them (particularly common in the embedded world).
++ *
++ * add_hwgenerator_randomness() is for true hardware RNGs, and will credit
++ * entropy as specified by the caller. If the entropy pool is full it will
++ * block until more entropy is needed.
++ *
++ * add_bootloader_randomness() is called by bootloader drivers, such as EFI
++ * and device tree, and credits its input depending on whether or not the
++ * configuration option CONFIG_RANDOM_TRUST_BOOTLOADER is set.
++ *
++ * add_interrupt_randomness() uses the interrupt timing as random
++ * inputs to the entropy pool. Using the cycle counters and the irq source
++ * as inputs, it feeds the input pool roughly once a second or after 64
++ * interrupts, crediting 1 bit of entropy for whichever comes first.
++ *
++ * add_input_randomness() uses the input layer interrupt timing, as well
++ * as the event type information from the hardware.
++ *
++ * add_disk_randomness() uses what amounts to the seek time of block
++ * layer request events, on a per-disk_devt basis, as input to the
++ * entropy pool. Note that high-speed solid state drives with very low
++ * seek times do not make for good sources of entropy, as their seek
++ * times are usually fairly consistent.
++ *
++ * The last two routines try to estimate how many bits of entropy
++ * to credit. They do this by keeping track of the first and second
++ * order deltas of the event timings.
++ *
++ **********************************************************************/
++
++static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
++static bool trust_bootloader __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER);
++static int __init parse_trust_cpu(char *arg)
{
- unsigned long v, flags;
-
@@ -28519,21 +47644,18 @@ index 605969ed0f965..ebe86de9d0acc 100644
- (time_after(crng_global_init_time, crng->init_time) ||
- time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
- crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
-+ unsigned long v, flags, init_time;
-+
-+ if (crng_ready()) {
-+ init_time = READ_ONCE(crng->init_time);
-+ if (time_after(READ_ONCE(crng_global_init_time), init_time) ||
-+ time_after(jiffies, init_time + CRNG_RESEED_INTERVAL))
-+ crng_reseed(crng, crng == &primary_crng ?
-+ &input_pool : NULL);
-+ }
- spin_lock_irqsave(&crng->lock, flags);
- if (arch_get_random_long(&v))
- crng->state[14] ^= v;
-@@ -1005,15 +1041,7 @@ static void _extract_crng(struct crng_state *crng,
-
- static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE])
+- spin_lock_irqsave(&crng->lock, flags);
+- if (arch_get_random_long(&v))
+- crng->state[14] ^= v;
+- chacha20_block(&crng->state[0], out);
+- if (crng->state[12] == 0)
+- crng->state[13]++;
+- spin_unlock_irqrestore(&crng->lock, flags);
++ return kstrtobool(arg, &trust_cpu);
+ }
+-
+-static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE])
++static int __init parse_trust_bootloader(char *arg)
{
- struct crng_state *crng = NULL;
-
@@ -28544,94 +47666,1828 @@ index 605969ed0f965..ebe86de9d0acc 100644
-#endif
- crng = &primary_crng;
- _extract_crng(crng, out);
-+ _extract_crng(select_crng(), out);
++ return kstrtobool(arg, &trust_bootloader);
}
++early_param("random.trust_cpu", parse_trust_cpu);
++early_param("random.trust_bootloader", parse_trust_bootloader);
/*
-@@ -1042,15 +1070,7 @@ static void _crng_backtrack_protect(struct crng_state *crng,
-
- static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used)
+- * Use the leftover bytes from the CRNG block output (if there is
+- * enough) to mutate the CRNG key to provide backtracking protection.
++ * The first collection of entropy occurs at system boot while interrupts
++ * are still turned off. Here we push in latent entropy, RDSEED, a timestamp,
++ * utsname(), and the command line. Depending on the above configuration knob,
++ * RDSEED may be considered sufficient for initialization. Note that much
++ * earlier setup may already have pushed entropy into the input pool by the
++ * time we get here.
+ */
+-static void _crng_backtrack_protect(struct crng_state *crng,
+- __u8 tmp[CHACHA_BLOCK_SIZE], int used)
+-{
+- unsigned long flags;
+- __u32 *s, *d;
+- int i;
+-
+- used = round_up(used, sizeof(__u32));
+- if (used + CHACHA_KEY_SIZE > CHACHA_BLOCK_SIZE) {
+- extract_crng(tmp);
+- used = 0;
+- }
+- spin_lock_irqsave(&crng->lock, flags);
+- s = (__u32 *) &tmp[used];
+- d = &crng->state[4];
+- for (i=0; i < 8; i++)
+- *d++ ^= *s++;
+- spin_unlock_irqrestore(&crng->lock, flags);
+-}
+-
+-static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used)
++int __init random_init(const char *command_line)
{
- struct crng_state *crng = NULL;
--
++ ktime_t now = ktime_get_real();
++ unsigned int i, arch_bytes;
++ unsigned long entropy;
+
-#ifdef CONFIG_NUMA
- if (crng_node_pool)
- crng = crng_node_pool[numa_node_id()];
- if (crng == NULL)
--#endif
++#if defined(LATENT_ENTROPY_PLUGIN)
++ static const u8 compiletime_seed[BLAKE2S_BLOCK_SIZE] __initconst __latent_entropy;
++ _mix_pool_bytes(compiletime_seed, sizeof(compiletime_seed));
+ #endif
- crng = &primary_crng;
- _crng_backtrack_protect(crng, tmp, used);
-+ _crng_backtrack_protect(select_crng(), tmp, used);
+-}
+
+-static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+-{
+- ssize_t ret = 0, i = CHACHA_BLOCK_SIZE;
+- __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
+- int large_request = (nbytes > 256);
+-
+- while (nbytes) {
+- if (large_request && need_resched()) {
+- if (signal_pending(current)) {
+- if (ret == 0)
+- ret = -ERESTARTSYS;
+- break;
+- }
+- schedule();
++ for (i = 0, arch_bytes = BLAKE2S_BLOCK_SIZE;
++ i < BLAKE2S_BLOCK_SIZE; i += sizeof(entropy)) {
++ if (!arch_get_random_seed_long_early(&entropy) &&
++ !arch_get_random_long_early(&entropy)) {
++ entropy = random_get_entropy();
++ arch_bytes -= sizeof(entropy);
+ }
+-
+- extract_crng(tmp);
+- i = min_t(int, nbytes, CHACHA_BLOCK_SIZE);
+- if (copy_to_user(buf, tmp, i)) {
+- ret = -EFAULT;
+- break;
+- }
+-
+- nbytes -= i;
+- buf += i;
+- ret += i;
++ _mix_pool_bytes(&entropy, sizeof(entropy));
+ }
+- crng_backtrack_protect(tmp, i);
++ _mix_pool_bytes(&now, sizeof(now));
++ _mix_pool_bytes(utsname(), sizeof(*(utsname())));
++ _mix_pool_bytes(command_line, strlen(command_line));
++ add_latent_entropy();
+
+- /* Wipe data just written to memory */
+- memzero_explicit(tmp, sizeof(tmp));
++ if (crng_ready())
++ crng_reseed();
++ else if (trust_cpu)
++ credit_init_bits(arch_bytes * 8);
+
+- return ret;
++ return 0;
+ }
+
+-
+-/*********************************************************************
+- *
+- * Entropy input management
+- *
+- *********************************************************************/
+-
+-/* There is one of these per entropy source */
+-struct timer_rand_state {
+- cycles_t last_time;
+- long last_delta, last_delta2;
+-};
+-
+-#define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
+-
+ /*
+ * Add device- or boot-specific data to the input pool to help
+ * initialize it.
+@@ -1111,681 +861,271 @@ struct timer_rand_state {
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ */
+-void add_device_randomness(const void *buf, unsigned int size)
++void add_device_randomness(const void *buf, size_t len)
+ {
+- unsigned long time = random_get_entropy() ^ jiffies;
++ unsigned long entropy = random_get_entropy();
+ unsigned long flags;
+
+- if (!crng_ready() && size)
+- crng_slow_load(buf, size);
+-
+- trace_add_device_randomness(size, _RET_IP_);
+ spin_lock_irqsave(&input_pool.lock, flags);
+- _mix_pool_bytes(&input_pool, buf, size);
+- _mix_pool_bytes(&input_pool, &time, sizeof(time));
++ _mix_pool_bytes(&entropy, sizeof(entropy));
++ _mix_pool_bytes(buf, len);
+ spin_unlock_irqrestore(&input_pool.lock, flags);
}
+ EXPORT_SYMBOL(add_device_randomness);
+
+-static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
+-
+ /*
+- * This function adds entropy to the entropy "pool" by using timing
+- * delays. It uses the timer_rand_state structure to make an estimate
+- * of how many bits of entropy this call has added to the pool.
+- *
+- * The number "num" is also added to the pool - it should somehow describe
+- * the type of event which just happened. This is currently 0-255 for
+- * keyboard scan codes, and 256 upwards for interrupts.
+- *
++ * Interface for in-kernel drivers of true hardware RNGs.
++ * Those devices may produce endless random bits and will be throttled
++ * when our pool is full.
+ */
+-static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
++void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy)
+ {
+- struct entropy_store *r;
+- struct {
+- long jiffies;
+- unsigned cycles;
+- unsigned num;
+- } sample;
+- long delta, delta2, delta3;
+-
+- sample.jiffies = jiffies;
+- sample.cycles = random_get_entropy();
+- sample.num = num;
+- r = &input_pool;
+- mix_pool_bytes(r, &sample, sizeof(sample));
++ mix_pool_bytes(buf, len);
++ credit_init_bits(entropy);
- static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
-@@ -1269,7 +1289,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
- if (unlikely(crng_init == 0)) {
- if ((fast_pool->count >= 64) &&
- crng_fast_load((char *) fast_pool->pool,
+ /*
+- * Calculate number of bits of randomness we probably added.
+- * We take into account the first, second and third-order deltas
+- * in order to make our estimate.
++ * Throttle writing to once every CRNG_RESEED_INTERVAL, unless
++ * we're not yet initialized.
+ */
+- delta = sample.jiffies - READ_ONCE(state->last_time);
+- WRITE_ONCE(state->last_time, sample.jiffies);
+-
+- delta2 = delta - READ_ONCE(state->last_delta);
+- WRITE_ONCE(state->last_delta, delta);
+-
+- delta3 = delta2 - READ_ONCE(state->last_delta2);
+- WRITE_ONCE(state->last_delta2, delta2);
+-
+- if (delta < 0)
+- delta = -delta;
+- if (delta2 < 0)
+- delta2 = -delta2;
+- if (delta3 < 0)
+- delta3 = -delta3;
+- if (delta > delta2)
+- delta = delta2;
+- if (delta > delta3)
+- delta = delta3;
+-
+- /*
+- * delta is now minimum absolute delta.
+- * Round down by 1 bit on general principles,
+- * and limit entropy estimate to 12 bits.
+- */
+- credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
++ if (!kthread_should_stop() && crng_ready())
++ schedule_timeout_interruptible(CRNG_RESEED_INTERVAL);
+ }
++EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+-void add_input_randomness(unsigned int type, unsigned int code,
+- unsigned int value)
++/*
++ * Handle random seed passed by bootloader, and credit it if
++ * CONFIG_RANDOM_TRUST_BOOTLOADER is set.
++ */
++void __cold add_bootloader_randomness(const void *buf, size_t len)
+ {
+- static unsigned char last_value;
+-
+- /* ignore autorepeat and the like */
+- if (value == last_value)
+- return;
+-
+- last_value = value;
+- add_timer_randomness(&input_timer_state,
+- (type << 4) ^ code ^ (code >> 4) ^ value);
+- trace_add_input_randomness(ENTROPY_BITS(&input_pool));
++ mix_pool_bytes(buf, len);
++ if (trust_bootloader)
++ credit_init_bits(len * 8);
+ }
+-EXPORT_SYMBOL_GPL(add_input_randomness);
+-
+-static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+-
+-#ifdef ADD_INTERRUPT_BENCH
+-static unsigned long avg_cycles, avg_deviation;
++EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+-#define AVG_SHIFT 8 /* Exponential average factor k=1/256 */
+-#define FIXED_1_2 (1 << (AVG_SHIFT-1))
++struct fast_pool {
++ struct work_struct mix;
++ unsigned long pool[4];
++ unsigned long last;
++ unsigned int count;
++};
+
+-static void add_interrupt_bench(cycles_t start)
+-{
+- long delta = random_get_entropy() - start;
+-
+- /* Use a weighted moving average */
+- delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
+- avg_cycles += delta;
+- /* And average deviation */
+- delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
+- avg_deviation += delta;
+-}
++static DEFINE_PER_CPU(struct fast_pool, irq_randomness) = {
++#ifdef CONFIG_64BIT
++#define FASTMIX_PERM SIPHASH_PERMUTATION
++ .pool = { SIPHASH_CONST_0, SIPHASH_CONST_1, SIPHASH_CONST_2, SIPHASH_CONST_3 }
+ #else
+-#define add_interrupt_bench(x)
++#define FASTMIX_PERM HSIPHASH_PERMUTATION
++ .pool = { HSIPHASH_CONST_0, HSIPHASH_CONST_1, HSIPHASH_CONST_2, HSIPHASH_CONST_3 }
+ #endif
+-
+-static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
+-{
+- __u32 *ptr = (__u32 *) regs;
+- unsigned int idx;
+-
+- if (regs == NULL)
+- return 0;
+- idx = READ_ONCE(f->reg_idx);
+- if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
+- idx = 0;
+- ptr += idx++;
+- WRITE_ONCE(f->reg_idx, idx);
+- return *ptr;
+-}
+-
+-void add_interrupt_randomness(int irq, int irq_flags)
+-{
+- struct entropy_store *r;
+- struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
+- struct pt_regs *regs = get_irq_regs();
+- unsigned long now = jiffies;
+- cycles_t cycles = random_get_entropy();
+- __u32 c_high, j_high;
+- __u64 ip;
+-
+- if (cycles == 0)
+- cycles = get_reg(fast_pool, regs);
+- c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
+- j_high = (sizeof(now) > 4) ? now >> 32 : 0;
+- fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
+- fast_pool->pool[1] ^= now ^ c_high;
+- ip = regs ? instruction_pointer(regs) : _RET_IP_;
+- fast_pool->pool[2] ^= ip;
+- fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
+- get_reg(fast_pool, regs);
+-
+- fast_mix(fast_pool);
+- add_interrupt_bench(cycles);
+-
+- if (unlikely(crng_init == 0)) {
+- if ((fast_pool->count >= 64) &&
+- crng_fast_load((char *) fast_pool->pool,
- sizeof(fast_pool->pool))) {
-+ sizeof(fast_pool->pool)) > 0) {
- fast_pool->count = 0;
- fast_pool->last = now;
- }
-@@ -1775,6 +1795,8 @@ static void __init init_std_data(struct entropy_store *r)
- int __init rand_initialize(void)
- {
- init_std_data(&input_pool);
-+ if (crng_need_final_init)
-+ crng_finalize_init(&primary_crng);
- crng_initialize_primary(&primary_crng);
- crng_global_init_time = jiffies;
- if (ratelimit_disable) {
-@@ -1941,7 +1963,10 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
- */
+- fast_pool->count = 0;
+- fast_pool->last = now;
+- }
+- return;
+- }
+-
+- if ((fast_pool->count < 64) &&
+- !time_after(now, fast_pool->last + HZ))
+- return;
+-
+- r = &input_pool;
+- if (!spin_trylock(&r->lock))
+- return;
+-
+- fast_pool->last = now;
+- __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+- spin_unlock(&r->lock);
+-
+- fast_pool->count = 0;
+-
+- /* award one bit for the contents of the fast pool */
+- credit_entropy_bits(r, 1);
+-}
+-EXPORT_SYMBOL_GPL(add_interrupt_randomness);
+-
+-#ifdef CONFIG_BLOCK
+-void add_disk_randomness(struct gendisk *disk)
+-{
+- if (!disk || !disk->random)
+- return;
+- /* first major is 1, so we get >= 0x200 here */
+- add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
+- trace_add_disk_randomness(disk_devt(disk), ENTROPY_BITS(&input_pool));
+-}
+-EXPORT_SYMBOL_GPL(add_disk_randomness);
+-#endif
+-
+-/*********************************************************************
+- *
+- * Entropy extraction routines
+- *
+- *********************************************************************/
++};
+
+ /*
+- * This function decides how many bytes to actually take from the
+- * given pool, and also debits the entropy count accordingly.
++ * This is [Half]SipHash-1-x, starting from an empty key. Because
++ * the key is fixed, it assumes that its inputs are non-malicious,
++ * and therefore this has no security on its own. s represents the
++ * four-word SipHash state, while v represents a two-word input.
+ */
+-static size_t account(struct entropy_store *r, size_t nbytes, int min,
+- int reserved)
++static void fast_mix(unsigned long s[4], unsigned long v1, unsigned long v2)
+ {
+- int entropy_count, orig, have_bytes;
+- size_t ibytes, nfrac;
+-
+- BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
+-
+- /* Can we pull enough? */
+-retry:
+- entropy_count = orig = READ_ONCE(r->entropy_count);
+- ibytes = nbytes;
+- /* never pull more than available */
+- have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
+-
+- if ((have_bytes -= reserved) < 0)
+- have_bytes = 0;
+- ibytes = min_t(size_t, ibytes, have_bytes);
+- if (ibytes < min)
+- ibytes = 0;
+-
+- if (WARN_ON(entropy_count < 0)) {
+- pr_warn("negative entropy count: pool %s count %d\n",
+- r->name, entropy_count);
+- entropy_count = 0;
+- }
+- nfrac = ibytes << (ENTROPY_SHIFT + 3);
+- if ((size_t) entropy_count > nfrac)
+- entropy_count -= nfrac;
+- else
+- entropy_count = 0;
+-
+- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+- goto retry;
+-
+- trace_debit_entropy(r->name, 8 * ibytes);
+- if (ibytes && ENTROPY_BITS(r) < random_write_wakeup_bits) {
+- wake_up_interruptible(&random_write_wait);
+- kill_fasync(&fasync, SIGIO, POLL_OUT);
+- }
+-
+- return ibytes;
++ s[3] ^= v1;
++ FASTMIX_PERM(s[0], s[1], s[2], s[3]);
++ s[0] ^= v1;
++ s[3] ^= v2;
++ FASTMIX_PERM(s[0], s[1], s[2], s[3]);
++ s[0] ^= v2;
+ }
+
++#ifdef CONFIG_SMP
+ /*
+- * This function does the actual extraction for extract_entropy.
+- *
+- * Note: we assume that .poolwords is a multiple of 16 words.
++ * This function is called when the CPU has just come online, with
++ * entry CPUHP_AP_RANDOM_ONLINE, just after CPUHP_AP_WORKQUEUE_ONLINE.
+ */
+-static void extract_buf(struct entropy_store *r, __u8 *out)
++int __cold random_online_cpu(unsigned int cpu)
+ {
+- int i;
+- union {
+- __u32 w[5];
+- unsigned long l[LONGS(20)];
+- } hash;
+- __u32 workspace[SHA1_WORKSPACE_WORDS];
+- unsigned long flags;
+-
+ /*
+- * If we have an architectural hardware random number
+- * generator, use it for SHA's initial vector
++ * During CPU shutdown and before CPU onlining, add_interrupt_
++ * randomness() may schedule mix_interrupt_randomness(), and
++ * set the MIX_INFLIGHT flag. However, because the worker can
++ * be scheduled on a different CPU during this period, that
++ * flag will never be cleared. For that reason, we zero out
++ * the flag here, which runs just after workqueues are onlined
++ * for the CPU again. This also has the effect of setting the
++ * irq randomness count to zero so that new accumulated irqs
++ * are fresh.
+ */
+- sha1_init(hash.w);
+- for (i = 0; i < LONGS(20); i++) {
+- unsigned long v;
+- if (!arch_get_random_long(&v))
+- break;
+- hash.l[i] = v;
+- }
+-
+- /* Generate a hash across the pool, 16 words (512 bits) at a time */
+- spin_lock_irqsave(&r->lock, flags);
+- for (i = 0; i < r->poolinfo->poolwords; i += 16)
+- sha1_transform(hash.w, (__u8 *)(r->pool + i), workspace);
++ per_cpu_ptr(&irq_randomness, cpu)->count = 0;
++ return 0;
++}
++#endif
+
++static void mix_interrupt_randomness(struct work_struct *work)
++{
++ struct fast_pool *fast_pool = container_of(work, struct fast_pool, mix);
+ /*
+- * We mix the hash back into the pool to prevent backtracking
+- * attacks (where the attacker knows the state of the pool
+- * plus the current outputs, and attempts to find previous
+- * ouputs), unless the hash function can be inverted. By
+- * mixing at least a SHA1 worth of hash data back, we make
+- * brute-forcing the feedback as hard as brute-forcing the
+- * hash.
++ * The size of the copied stack pool is explicitly 2 longs so that we
++ * only ever ingest half of the siphash output each time, retaining
++ * the other half as the next "key" that carries over. The entropy is
++ * supposed to be sufficiently dispersed between bits so on average
++ * we don't wind up "losing" some.
+ */
+- __mix_pool_bytes(r, hash.w, sizeof(hash.w));
+- spin_unlock_irqrestore(&r->lock, flags);
++ unsigned long pool[2];
++ unsigned int count;
+
+- memzero_explicit(workspace, sizeof(workspace));
++ /* Check to see if we're running on the wrong CPU due to hotplug. */
++ local_irq_disable();
++ if (fast_pool != this_cpu_ptr(&irq_randomness)) {
++ local_irq_enable();
++ return;
++ }
+
+ /*
+- * In case the hash function has some recognizable output
+- * pattern, we fold it in half. Thus, we always feed back
+- * twice as much data as we output.
++ * Copy the pool to the stack so that the mixer always has a
++ * consistent view, before we reenable irqs again.
+ */
+- hash.w[0] ^= hash.w[3];
+- hash.w[1] ^= hash.w[4];
+- hash.w[2] ^= rol32(hash.w[2], 16);
+-
+- memcpy(out, &hash, EXTRACT_SIZE);
+- memzero_explicit(&hash, sizeof(hash));
+-}
+-
+-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
+- size_t nbytes, int fips)
+-{
+- ssize_t ret = 0, i;
+- __u8 tmp[EXTRACT_SIZE];
+- unsigned long flags;
+-
+- while (nbytes) {
+- extract_buf(r, tmp);
+-
+- if (fips) {
+- spin_lock_irqsave(&r->lock, flags);
+- if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+- panic("Hardware RNG duplicated output!\n");
+- memcpy(r->last_data, tmp, EXTRACT_SIZE);
+- spin_unlock_irqrestore(&r->lock, flags);
+- }
+- i = min_t(int, nbytes, EXTRACT_SIZE);
+- memcpy(buf, tmp, i);
+- nbytes -= i;
+- buf += i;
+- ret += i;
+- }
++ memcpy(pool, fast_pool->pool, sizeof(pool));
++ count = fast_pool->count;
++ fast_pool->count = 0;
++ fast_pool->last = jiffies;
++ local_irq_enable();
+
+- /* Wipe data just returned from memory */
+- memzero_explicit(tmp, sizeof(tmp));
++ mix_pool_bytes(pool, sizeof(pool));
++ credit_init_bits(max(1u, (count & U16_MAX) / 64));
+
+- return ret;
++ memzero_explicit(pool, sizeof(pool));
+ }
+
+-/*
+- * This function extracts randomness from the "entropy pool", and
+- * returns it in a buffer.
+- *
+- * The min parameter specifies the minimum amount we can pull before
+- * failing to avoid races that defeat catastrophic reseeding while the
+- * reserved parameter indicates how much entropy we must leave in the
+- * pool after each pull to avoid starving other readers.
+- */
+-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+- size_t nbytes, int min, int reserved)
++void add_interrupt_randomness(int irq)
+ {
+- __u8 tmp[EXTRACT_SIZE];
+- unsigned long flags;
++ enum { MIX_INFLIGHT = 1U << 31 };
++ unsigned long entropy = random_get_entropy();
++ struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
++ struct pt_regs *regs = get_irq_regs();
++ unsigned int new_count;
+
+- /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
+- if (fips_enabled) {
+- spin_lock_irqsave(&r->lock, flags);
+- if (!r->last_data_init) {
+- r->last_data_init = 1;
+- spin_unlock_irqrestore(&r->lock, flags);
+- trace_extract_entropy(r->name, EXTRACT_SIZE,
+- ENTROPY_BITS(r), _RET_IP_);
+- extract_buf(r, tmp);
+- spin_lock_irqsave(&r->lock, flags);
+- memcpy(r->last_data, tmp, EXTRACT_SIZE);
+- }
+- spin_unlock_irqrestore(&r->lock, flags);
+- }
+-
+- trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
+- nbytes = account(r, nbytes, min, reserved);
+-
+- return _extract_entropy(r, buf, nbytes, fips_enabled);
+-}
++ fast_mix(fast_pool->pool, entropy,
++ (regs ? instruction_pointer(regs) : _RET_IP_) ^ swab(irq));
++ new_count = ++fast_pool->count;
+
+-#define warn_unseeded_randomness(previous) \
+- _warn_unseeded_randomness(__func__, (void *) _RET_IP_, (previous))
+-
+-static void _warn_unseeded_randomness(const char *func_name, void *caller,
+- void **previous)
+-{
+-#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+- const bool print_once = false;
+-#else
+- static bool print_once __read_mostly;
+-#endif
+-
+- if (print_once ||
+- crng_ready() ||
+- (previous && (caller == READ_ONCE(*previous))))
++ if (new_count & MIX_INFLIGHT)
+ return;
+- WRITE_ONCE(*previous, caller);
+-#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+- print_once = true;
+-#endif
+- if (__ratelimit(&unseeded_warning))
+- printk_deferred(KERN_NOTICE "random: %s called from %pS "
+- "with crng_init=%d\n", func_name, caller,
+- crng_init);
+-}
+
+-/*
+- * This function is the exported kernel interface. It returns some
+- * number of good random numbers, suitable for key generation, seeding
+- * TCP sequence numbers, etc. It does not rely on the hardware random
+- * number generator. For random bytes direct from the hardware RNG
+- * (when available), use get_random_bytes_arch(). In order to ensure
+- * that the randomness provided by this function is okay, the function
+- * wait_for_random_bytes() should be called and return 0 at least once
+- * at any point prior.
+- */
+-static void _get_random_bytes(void *buf, int nbytes)
+-{
+- __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
+-
+- trace_get_random_bytes(nbytes, _RET_IP_);
+-
+- while (nbytes >= CHACHA_BLOCK_SIZE) {
+- extract_crng(buf);
+- buf += CHACHA_BLOCK_SIZE;
+- nbytes -= CHACHA_BLOCK_SIZE;
+- }
+-
+- if (nbytes > 0) {
+- extract_crng(tmp);
+- memcpy(buf, tmp, nbytes);
+- crng_backtrack_protect(tmp, nbytes);
+- } else
+- crng_backtrack_protect(tmp, CHACHA_BLOCK_SIZE);
+- memzero_explicit(tmp, sizeof(tmp));
+-}
+-
+-void get_random_bytes(void *buf, int nbytes)
+-{
+- static void *previous;
+-
+- warn_unseeded_randomness(&previous);
+- _get_random_bytes(buf, nbytes);
+-}
+-EXPORT_SYMBOL(get_random_bytes);
+-
+-
+-/*
+- * Each time the timer fires, we expect that we got an unpredictable
+- * jump in the cycle counter. Even if the timer is running on another
+- * CPU, the timer activity will be touching the stack of the CPU that is
+- * generating entropy..
+- *
+- * Note that we don't re-arm the timer in the timer itself - we are
+- * happy to be scheduled away, since that just makes the load more
+- * complex, but we do not want the timer to keep ticking unless the
+- * entropy loop is running.
+- *
+- * So the re-arming always happens in the entropy loop itself.
+- */
+-static void entropy_timer(struct timer_list *t)
+-{
+- credit_entropy_bits(&input_pool, 1);
+-}
+-
+-/*
+- * If we have an actual cycle counter, see if we can
+- * generate enough entropy with timing noise
+- */
+-static void try_to_generate_entropy(void)
+-{
+- struct {
+- unsigned long now;
+- struct timer_list timer;
+- } stack;
+-
+- stack.now = random_get_entropy();
+-
+- /* Slow counter - or none. Don't even bother */
+- if (stack.now == random_get_entropy())
++ if (new_count < 64 && !time_is_before_jiffies(fast_pool->last + HZ))
+ return;
+
+- timer_setup_on_stack(&stack.timer, entropy_timer, 0);
+- while (!crng_ready()) {
+- if (!timer_pending(&stack.timer))
+- mod_timer(&stack.timer, jiffies+1);
+- mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
+- schedule();
+- stack.now = random_get_entropy();
+- }
+-
+- del_timer_sync(&stack.timer);
+- destroy_timer_on_stack(&stack.timer);
+- mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
++ if (unlikely(!fast_pool->mix.func))
++ INIT_WORK(&fast_pool->mix, mix_interrupt_randomness);
++ fast_pool->count |= MIX_INFLIGHT;
++ queue_work_on(raw_smp_processor_id(), system_highpri_wq, &fast_pool->mix);
+ }
++EXPORT_SYMBOL_GPL(add_interrupt_randomness);
+
+-/*
+- * Wait for the urandom pool to be seeded and thus guaranteed to supply
+- * cryptographically secure random numbers. This applies to: the /dev/urandom
+- * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+- * family of functions. Using any of these functions without first calling
+- * this function forfeits the guarantee of security.
+- *
+- * Returns: 0 if the urandom pool has been seeded.
+- * -ERESTARTSYS if the function was interrupted by a signal.
+- */
+-int wait_for_random_bytes(void)
+-{
+- if (likely(crng_ready()))
+- return 0;
+-
+- do {
+- int ret;
+- ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
+- if (ret)
+- return ret > 0 ? 0 : ret;
+-
+- try_to_generate_entropy();
+- } while (!crng_ready());
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(wait_for_random_bytes);
+-
+-/*
+- * Returns whether or not the urandom pool has been seeded and thus guaranteed
+- * to supply cryptographically secure random numbers. This applies to: the
+- * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
+- * ,u64,int,long} family of functions.
+- *
+- * Returns: true if the urandom pool has been seeded.
+- * false if the urandom pool has not been seeded.
+- */
+-bool rng_is_initialized(void)
+-{
+- return crng_ready();
+-}
+-EXPORT_SYMBOL(rng_is_initialized);
++/* There is one of these per entropy source */
++struct timer_rand_state {
++ unsigned long last_time;
++ long last_delta, last_delta2;
++};
+
+ /*
+- * Add a callback function that will be invoked when the nonblocking
+- * pool is initialised.
+- *
+- * returns: 0 if callback is successfully added
+- * -EALREADY if pool is already initialised (callback not called)
+- * -ENOENT if module for callback is not alive
++ * This function adds entropy to the entropy "pool" by using timing
++ * delays. It uses the timer_rand_state structure to make an estimate
++ * of how many bits of entropy this call has added to the pool. The
++ * value "num" is also added to the pool; it should somehow describe
++ * the type of event that just happened.
+ */
+-int add_random_ready_callback(struct random_ready_callback *rdy)
++static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
+ {
+- struct module *owner;
+- unsigned long flags;
+- int err = -EALREADY;
+-
+- if (crng_ready())
+- return err;
++ unsigned long entropy = random_get_entropy(), now = jiffies, flags;
++ long delta, delta2, delta3;
++ unsigned int bits;
+
+- owner = rdy->owner;
+- if (!try_module_get(owner))
+- return -ENOENT;
++ /*
++ * If we're in a hard IRQ, add_interrupt_randomness() will be called
++ * sometime after, so mix into the fast pool.
++ */
++ if (in_hardirq()) {
++ fast_mix(this_cpu_ptr(&irq_randomness)->pool, entropy, num);
++ } else {
++ spin_lock_irqsave(&input_pool.lock, flags);
++ _mix_pool_bytes(&entropy, sizeof(entropy));
++ _mix_pool_bytes(&num, sizeof(num));
++ spin_unlock_irqrestore(&input_pool.lock, flags);
++ }
+
+- spin_lock_irqsave(&random_ready_list_lock, flags);
+ if (crng_ready())
+- goto out;
+-
+- owner = NULL;
+-
+- list_add(&rdy->list, &random_ready_list);
+- err = 0;
+-
+-out:
+- spin_unlock_irqrestore(&random_ready_list_lock, flags);
+-
+- module_put(owner);
+-
+- return err;
+-}
+-EXPORT_SYMBOL(add_random_ready_callback);
+-
+-/*
+- * Delete a previously registered readiness callback function.
+- */
+-void del_random_ready_callback(struct random_ready_callback *rdy)
+-{
+- unsigned long flags;
+- struct module *owner = NULL;
+-
+- spin_lock_irqsave(&random_ready_list_lock, flags);
+- if (!list_empty(&rdy->list)) {
+- list_del_init(&rdy->list);
+- owner = rdy->owner;
+- }
+- spin_unlock_irqrestore(&random_ready_list_lock, flags);
++ return;
+
+- module_put(owner);
+-}
+-EXPORT_SYMBOL(del_random_ready_callback);
++ /*
++ * Calculate number of bits of randomness we probably added.
++ * We take into account the first, second and third-order deltas
++ * in order to make our estimate.
++ */
++ delta = now - READ_ONCE(state->last_time);
++ WRITE_ONCE(state->last_time, now);
+
+-/*
+- * This function will use the architecture-specific hardware random
+- * number generator if it is available. The arch-specific hw RNG will
+- * almost certainly be faster than what we can do in software, but it
+- * is impossible to verify that it is implemented securely (as
+- * opposed, to, say, the AES encryption of a sequence number using a
+- * key known by the NSA). So it's useful if we need the speed, but
+- * only if we're willing to trust the hardware manufacturer not to
+- * have put in a back door.
+- *
+- * Return number of bytes filled in.
+- */
+-int __must_check get_random_bytes_arch(void *buf, int nbytes)
+-{
+- int left = nbytes;
+- char *p = buf;
++ delta2 = delta - READ_ONCE(state->last_delta);
++ WRITE_ONCE(state->last_delta, delta);
+
+- trace_get_random_bytes_arch(left, _RET_IP_);
+- while (left) {
+- unsigned long v;
+- int chunk = min_t(int, left, sizeof(unsigned long));
++ delta3 = delta2 - READ_ONCE(state->last_delta2);
++ WRITE_ONCE(state->last_delta2, delta2);
+
+- if (!arch_get_random_long(&v))
+- break;
++ if (delta < 0)
++ delta = -delta;
++ if (delta2 < 0)
++ delta2 = -delta2;
++ if (delta3 < 0)
++ delta3 = -delta3;
++ if (delta > delta2)
++ delta = delta2;
++ if (delta > delta3)
++ delta = delta3;
+
+- memcpy(p, &v, chunk);
+- p += chunk;
+- left -= chunk;
+- }
++ /*
++ * delta is now minimum absolute delta. Round down by 1 bit
++ * on general principles, and limit entropy estimate to 11 bits.
++ */
++ bits = min(fls(delta >> 1), 11);
+
+- return nbytes - left;
++ /*
++ * As mentioned above, if we're in a hard IRQ, add_interrupt_randomness()
++ * will run after this, which uses a different crediting scheme of 1 bit
++ * per every 64 interrupts. In order to let that function do accounting
++ * close to the one in this function, we credit a full 64/64 bit per bit,
++ * and then subtract one to account for the extra one added.
++ */
++ if (in_hardirq())
++ this_cpu_ptr(&irq_randomness)->count += max(1u, bits * 64) - 1;
++ else
++ _credit_init_bits(bits);
+ }
+-EXPORT_SYMBOL(get_random_bytes_arch);
+
+-/*
+- * init_std_data - initialize pool with system data
+- *
+- * @r: pool to initialize
+- *
+- * This function clears the pool's entropy count and mixes some system
+- * data into the pool to prepare it for use. The pool is not cleared
+- * as that can only decrease the entropy in the pool.
+- */
+-static void __init init_std_data(struct entropy_store *r)
++void add_input_randomness(unsigned int type, unsigned int code, unsigned int value)
+ {
+- int i;
+- ktime_t now = ktime_get_real();
+- unsigned long rv;
+-
+- mix_pool_bytes(r, &now, sizeof(now));
+- for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+- if (!arch_get_random_seed_long(&rv) &&
+- !arch_get_random_long(&rv))
+- rv = random_get_entropy();
+- mix_pool_bytes(r, &rv, sizeof(rv));
+- }
+- mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
++ static unsigned char last_value;
++ static struct timer_rand_state input_timer_state = { INITIAL_JIFFIES };
++
++ /* Ignore autorepeat and the like. */
++ if (value == last_value)
++ return;
++
++ last_value = value;
++ add_timer_randomness(&input_timer_state,
++ (type << 4) ^ code ^ (code >> 4) ^ value);
+ }
++EXPORT_SYMBOL_GPL(add_input_randomness);
+
+-/*
+- * Note that setup_arch() may call add_device_randomness()
+- * long before we get here. This allows seeding of the pools
+- * with some platform dependent data very early in the boot
+- * process. But it limits our options here. We must use
+- * statically allocated structures that already have all
+- * initializations complete at compile time. We should also
+- * take care not to overwrite the precious per platform data
+- * we were given.
+- */
+-int __init rand_initialize(void)
++#ifdef CONFIG_BLOCK
++void add_disk_randomness(struct gendisk *disk)
+ {
+- init_std_data(&input_pool);
+- crng_initialize_primary(&primary_crng);
+- crng_global_init_time = jiffies;
+- if (ratelimit_disable) {
+- urandom_warning.interval = 0;
+- unseeded_warning.interval = 0;
+- }
+- return 0;
++ if (!disk || !disk->random)
++ return;
++ /* First major is 1, so we get >= 0x200 here. */
++ add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
+ }
++EXPORT_SYMBOL_GPL(add_disk_randomness);
+
+-#ifdef CONFIG_BLOCK
+-void rand_initialize_disk(struct gendisk *disk)
++void __cold rand_initialize_disk(struct gendisk *disk)
+ {
+ struct timer_rand_state *state;
+
+@@ -1801,116 +1141,189 @@ void rand_initialize_disk(struct gendisk *disk)
+ }
+ #endif
+
+-static ssize_t
+-urandom_read_nowarn(struct file *file, char __user *buf, size_t nbytes,
+- loff_t *ppos)
++/*
++ * Each time the timer fires, we expect that we got an unpredictable
++ * jump in the cycle counter. Even if the timer is running on another
++ * CPU, the timer activity will be touching the stack of the CPU that is
++ * generating entropy..
++ *
++ * Note that we don't re-arm the timer in the timer itself - we are
++ * happy to be scheduled away, since that just makes the load more
++ * complex, but we do not want the timer to keep ticking unless the
++ * entropy loop is running.
++ *
++ * So the re-arming always happens in the entropy loop itself.
++ */
++static void __cold entropy_timer(struct timer_list *t)
+ {
+- int ret;
+-
+- nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
+- ret = extract_crng_user(buf, nbytes);
+- trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool));
+- return ret;
++ credit_init_bits(1);
+ }
+
+-static ssize_t
+-urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
++/*
++ * If we have an actual cycle counter, see if we can
++ * generate enough entropy with timing noise
++ */
++static void __cold try_to_generate_entropy(void)
+ {
+- unsigned long flags;
+- static int maxwarn = 10;
++ struct {
++ unsigned long entropy;
++ struct timer_list timer;
++ } stack;
++
++ stack.entropy = random_get_entropy();
++
++ /* Slow counter - or none. Don't even bother */
++ if (stack.entropy == random_get_entropy())
++ return;
+
+- if (!crng_ready() && maxwarn > 0) {
+- maxwarn--;
+- if (__ratelimit(&urandom_warning))
+- pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
+- current->comm, nbytes);
+- spin_lock_irqsave(&primary_crng.lock, flags);
+- crng_init_cnt = 0;
+- spin_unlock_irqrestore(&primary_crng.lock, flags);
++ timer_setup_on_stack(&stack.timer, entropy_timer, 0);
++ while (!crng_ready() && !signal_pending(current)) {
++ if (!timer_pending(&stack.timer))
++ mod_timer(&stack.timer, jiffies + 1);
++ mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
++ schedule();
++ stack.entropy = random_get_entropy();
+ }
+
+- return urandom_read_nowarn(file, buf, nbytes, ppos);
++ del_timer_sync(&stack.timer);
++ destroy_timer_on_stack(&stack.timer);
++ mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
+ }
+
+-static ssize_t
+-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
++
++/**********************************************************************
++ *
++ * Userspace reader/writer interfaces.
++ *
++ * getrandom(2) is the primary modern interface into the RNG and should
++ * be used in preference to anything else.
++ *
++ * Reading from /dev/random has the same functionality as calling
++ * getrandom(2) with flags=0. In earlier versions, however, it had
++ * vastly different semantics and should therefore be avoided, to
++ * prevent backwards compatibility issues.
++ *
++ * Reading from /dev/urandom has the same functionality as calling
++ * getrandom(2) with flags=GRND_INSECURE. Because it does not block
++ * waiting for the RNG to be ready, it should not be used.
++ *
++ * Writing to either /dev/random or /dev/urandom adds entropy to
++ * the input pool but does not credit it.
++ *
++ * Polling on /dev/random indicates when the RNG is initialized, on
++ * the read side, and when it wants new entropy, on the write side.
++ *
++ * Both /dev/random and /dev/urandom have the same set of ioctls for
++ * adding entropy, getting the entropy count, zeroing the count, and
++ * reseeding the crng.
++ *
++ **********************************************************************/
++
++SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags)
+ {
++ struct iov_iter iter;
++ struct iovec iov;
+ int ret;
+
+- ret = wait_for_random_bytes();
+- if (ret != 0)
++ if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
++ return -EINVAL;
++
++ /*
++ * Requesting insecure and blocking randomness at the same time makes
++ * no sense.
++ */
++ if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
++ return -EINVAL;
++
++ if (!crng_ready() && !(flags & GRND_INSECURE)) {
++ if (flags & GRND_NONBLOCK)
++ return -EAGAIN;
++ ret = wait_for_random_bytes();
++ if (unlikely(ret))
++ return ret;
++ }
++
++ ret = import_single_range(READ, ubuf, len, &iov, &iter);
++ if (unlikely(ret))
+ return ret;
+- return urandom_read_nowarn(file, buf, nbytes, ppos);
++ return get_random_bytes_user(&iter);
+ }
+
+-static __poll_t
+-random_poll(struct file *file, poll_table * wait)
++static __poll_t random_poll(struct file *file, poll_table *wait)
+ {
+- __poll_t mask;
+-
+ poll_wait(file, &crng_init_wait, wait);
+- poll_wait(file, &random_write_wait, wait);
+- mask = 0;
+- if (crng_ready())
+- mask |= EPOLLIN | EPOLLRDNORM;
+- if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
+- mask |= EPOLLOUT | EPOLLWRNORM;
+- return mask;
++ return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
+ }
+
+-static int
+-write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
++static ssize_t write_pool_user(struct iov_iter *iter)
+ {
+- size_t bytes;
+- __u32 t, buf[16];
+- const char __user *p = buffer;
++ u8 block[BLAKE2S_BLOCK_SIZE];
++ ssize_t ret = 0;
++ size_t copied;
+
+- while (count > 0) {
+- int b, i = 0;
++ if (unlikely(!iov_iter_count(iter)))
++ return 0;
+
+- bytes = min(count, sizeof(buf));
+- if (copy_from_user(&buf, p, bytes))
+- return -EFAULT;
++ for (;;) {
++ copied = copy_from_iter(block, sizeof(block), iter);
++ ret += copied;
++ mix_pool_bytes(block, copied);
++ if (!iov_iter_count(iter) || copied != sizeof(block))
++ break;
+
+- for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) {
+- if (!arch_get_random_int(&t))
++ BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
++ if (ret % PAGE_SIZE == 0) {
++ if (signal_pending(current))
+ break;
+- buf[i] ^= t;
++ cond_resched();
+ }
++ }
++
++ memzero_explicit(block, sizeof(block));
++ return ret ? ret : -EFAULT;
++}
++
++static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
++{
++ return write_pool_user(iter);
++}
+
+- count -= bytes;
+- p += bytes;
++static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
++{
++ static int maxwarn = 10;
+
+- mix_pool_bytes(r, buf, bytes);
+- cond_resched();
++ if (!crng_ready()) {
++ if (!ratelimit_disable && maxwarn <= 0)
++ ++urandom_warning.missed;
++ else if (ratelimit_disable || __ratelimit(&urandom_warning)) {
++ --maxwarn;
++ pr_notice("%s: uninitialized urandom read (%zu bytes read)\n",
++ current->comm, iov_iter_count(iter));
++ }
+ }
+
+- return 0;
++ return get_random_bytes_user(iter);
+ }
+
+-static ssize_t random_write(struct file *file, const char __user *buffer,
+- size_t count, loff_t *ppos)
++static ssize_t random_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
+ {
+- size_t ret;
++ int ret;
+
+- ret = write_pool(&input_pool, buffer, count);
+- if (ret)
++ ret = wait_for_random_bytes();
++ if (ret != 0)
+ return ret;
+-
+- return (ssize_t)count;
++ return get_random_bytes_user(iter);
+ }
+
+ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ {
+- int size, ent_count;
+ int __user *p = (int __user *)arg;
+- int retval;
++ int ent_count;
+
+ switch (cmd) {
+ case RNDGETENTCNT:
+- /* inherently racy, no point locking */
+- ent_count = ENTROPY_BITS(&input_pool);
+- if (put_user(ent_count, p))
++ /* Inherently racy, no point locking. */
++ if (put_user(input_pool.init_bits, p))
+ return -EFAULT;
+ return 0;
+ case RNDADDTOENTCNT:
+@@ -1918,38 +1331,48 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ return -EPERM;
+ if (get_user(ent_count, p))
+ return -EFAULT;
+- return credit_entropy_bits_safe(&input_pool, ent_count);
+- case RNDADDENTROPY:
++ if (ent_count < 0)
++ return -EINVAL;
++ credit_init_bits(ent_count);
++ return 0;
++ case RNDADDENTROPY: {
++ struct iov_iter iter;
++ struct iovec iov;
++ ssize_t ret;
++ int len;
++
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (get_user(ent_count, p++))
+ return -EFAULT;
+ if (ent_count < 0)
+ return -EINVAL;
+- if (get_user(size, p++))
++ if (get_user(len, p++))
++ return -EFAULT;
++ ret = import_single_range(WRITE, p, len, &iov, &iter);
++ if (unlikely(ret))
++ return ret;
++ ret = write_pool_user(&iter);
++ if (unlikely(ret < 0))
++ return ret;
++ /* Since we're crediting, enforce that it was all written into the pool. */
++ if (unlikely(ret != len))
+ return -EFAULT;
+- retval = write_pool(&input_pool, (const char __user *)p,
+- size);
+- if (retval < 0)
+- return retval;
+- return credit_entropy_bits_safe(&input_pool, ent_count);
++ credit_init_bits(ent_count);
++ return 0;
++ }
+ case RNDZAPENTCNT:
+ case RNDCLEARPOOL:
+- /*
+- * Clear the entropy pool counters. We no longer clear
+- * the entropy pool, as that's silly.
+- */
++ /* No longer has any effect. */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- input_pool.entropy_count = 0;
-+ if (xchg(&input_pool.entropy_count, 0) && random_write_wakeup_bits) {
-+ wake_up_interruptible(&random_write_wait);
-+ kill_fasync(&fasync, SIGIO, POLL_OUT);
-+ }
return 0;
case RNDRESEEDCRNG:
if (!capable(CAP_SYS_ADMIN))
-@@ -1949,7 +1974,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
- if (crng_init < 2)
+ return -EPERM;
+- if (crng_init < 2)
++ if (!crng_ready())
return -ENODATA;
- crng_reseed(&primary_crng, &input_pool);
+- crng_reseed(&primary_crng, &input_pool);
- crng_global_init_time = jiffies - 1;
-+ WRITE_ONCE(crng_global_init_time, jiffies - 1);
++ crng_reseed();
return 0;
default:
return -EINVAL;
-@@ -2275,15 +2300,19 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
- struct entropy_store *poolp = &input_pool;
+@@ -1962,55 +1385,56 @@ static int random_fasync(int fd, struct file *filp, int on)
+ }
+
+ const struct file_operations random_fops = {
+- .read = random_read,
+- .write = random_write,
+- .poll = random_poll,
++ .read_iter = random_read_iter,
++ .write_iter = random_write_iter,
++ .poll = random_poll,
+ .unlocked_ioctl = random_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .fasync = random_fasync,
+ .llseek = noop_llseek,
++ .splice_read = generic_file_splice_read,
++ .splice_write = iter_file_splice_write,
+ };
- if (unlikely(crng_init == 0)) {
-- crng_fast_load(buffer, count);
-- return;
-+ size_t ret = crng_fast_load(buffer, count);
-+ count -= ret;
-+ buffer += ret;
-+ if (!count || crng_init == 0)
-+ return;
+ const struct file_operations urandom_fops = {
+- .read = urandom_read,
+- .write = random_write,
++ .read_iter = urandom_read_iter,
++ .write_iter = random_write_iter,
+ .unlocked_ioctl = random_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .fasync = random_fasync,
+ .llseek = noop_llseek,
++ .splice_read = generic_file_splice_read,
++ .splice_write = iter_file_splice_write,
+ };
+
+-SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+- unsigned int, flags)
+-{
+- int ret;
+-
+- if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE))
+- return -EINVAL;
+-
+- /*
+- * Requesting insecure and blocking randomness at the same time makes
+- * no sense.
+- */
+- if ((flags & (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
+- return -EINVAL;
+-
+- if (count > INT_MAX)
+- count = INT_MAX;
+-
+- if (!(flags & GRND_INSECURE) && !crng_ready()) {
+- if (flags & GRND_NONBLOCK)
+- return -EAGAIN;
+- ret = wait_for_random_bytes();
+- if (unlikely(ret))
+- return ret;
+- }
+- return urandom_read_nowarn(NULL, buf, count, NULL);
+-}
+
+ /********************************************************************
+ *
+- * Sysctl interface
++ * Sysctl interface.
++ *
++ * These are partly unused legacy knobs with dummy values to not break
++ * userspace and partly still useful things. They are usually accessible
++ * in /proc/sys/kernel/random/ and are as follows:
++ *
++ * - boot_id - a UUID representing the current boot.
++ *
++ * - uuid - a random UUID, different each time the file is read.
++ *
++ * - poolsize - the number of bits of entropy that the input pool can
++ * hold, tied to the POOL_BITS constant.
++ *
++ * - entropy_avail - the number of bits of entropy currently in the
++ * input pool. Always <= poolsize.
++ *
++ * - write_wakeup_threshold - the amount of entropy in the input pool
++ * below which write polls to /dev/random will unblock, requesting
++ * more entropy, tied to the POOL_READY_BITS constant. It is writable
++ * to avoid breaking old userspaces, but writing to it does not
++ * change any behavior of the RNG.
++ *
++ * - urandom_min_reseed_secs - fixed to the value CRNG_RESEED_INTERVAL.
++ * It is writable to avoid breaking old userspaces, but writing
++ * to it does not change any behavior of the RNG.
+ *
+ ********************************************************************/
+
+@@ -2018,25 +1442,28 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+
+ #include <linux/sysctl.h>
+
+-static int min_write_thresh;
+-static int max_write_thresh = INPUT_POOL_WORDS * 32;
+-static int random_min_urandom_seed = 60;
+-static char sysctl_bootid[16];
++static int sysctl_random_min_urandom_seed = CRNG_RESEED_INTERVAL / HZ;
++static int sysctl_random_write_wakeup_bits = POOL_READY_BITS;
++static int sysctl_poolsize = POOL_BITS;
++static u8 sysctl_bootid[UUID_SIZE];
+
+ /*
+ * This function is used to return both the bootid UUID, and random
+- * UUID. The difference is in whether table->data is NULL; if it is,
++ * UUID. The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+- *
+- * If the user accesses this via the proc interface, the UUID will be
+- * returned as an ASCII string in the standard UUID format; if via the
+- * sysctl system call, as 16 bytes of binary data.
+ */
+-static int proc_do_uuid(struct ctl_table *table, int write,
+- void *buffer, size_t *lenp, loff_t *ppos)
++static int proc_do_uuid(struct ctl_table *table, int write, void *buf,
++ size_t *lenp, loff_t *ppos)
+ {
+- struct ctl_table fake_table;
+- unsigned char buf[64], tmp_uuid[16], *uuid;
++ u8 tmp_uuid[UUID_SIZE], *uuid;
++ char uuid_string[UUID_STRING_LEN + 1];
++ struct ctl_table fake_table = {
++ .data = uuid_string,
++ .maxlen = UUID_STRING_LEN
++ };
++
++ if (write)
++ return -EPERM;
+
+ uuid = table->data;
+ if (!uuid) {
+@@ -2051,32 +1478,17 @@ static int proc_do_uuid(struct ctl_table *table, int write,
+ spin_unlock(&bootid_spinlock);
}
- /* Suspend writing if we're above the trickle threshold.
- * We'll be woken up again once below random_write_wakeup_thresh,
- * or when the calling thread is about to terminate.
- */
+- sprintf(buf, "%pU", uuid);
+-
+- fake_table.data = buf;
+- fake_table.maxlen = sizeof(buf);
+-
+- return proc_dostring(&fake_table, write, buffer, lenp, ppos);
++ snprintf(uuid_string, sizeof(uuid_string), "%pU", uuid);
++ return proc_dostring(&fake_table, 0, buf, lenp, ppos);
+ }
+
+-/*
+- * Return entropy available scaled to integral bits
+- */
+-static int proc_do_entropy(struct ctl_table *table, int write,
+- void *buffer, size_t *lenp, loff_t *ppos)
++/* The same as proc_dointvec, but writes don't change anything. */
++static int proc_do_rointvec(struct ctl_table *table, int write, void *buf,
++ size_t *lenp, loff_t *ppos)
+ {
+- struct ctl_table fake_table;
+- int entropy_count;
+-
+- entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
+-
+- fake_table.data = &entropy_count;
+- fake_table.maxlen = sizeof(entropy_count);
+-
+- return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
++ return write ? 0 : proc_dointvec(table, 0, buf, lenp, ppos);
+ }
+
+-static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
+ extern struct ctl_table random_table[];
+ struct ctl_table random_table[] = {
+ {
+@@ -2088,218 +1500,36 @@ struct ctl_table random_table[] = {
+ },
+ {
+ .procname = "entropy_avail",
++ .data = &input_pool.init_bits,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+- .proc_handler = proc_do_entropy,
+- .data = &input_pool.entropy_count,
++ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "write_wakeup_threshold",
+- .data = &random_write_wakeup_bits,
++ .data = &sysctl_random_write_wakeup_bits,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec_minmax,
+- .extra1 = &min_write_thresh,
+- .extra2 = &max_write_thresh,
++ .proc_handler = proc_do_rointvec,
+ },
+ {
+ .procname = "urandom_min_reseed_secs",
+- .data = &random_min_urandom_seed,
++ .data = &sysctl_random_min_urandom_seed,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = proc_do_rointvec,
+ },
+ {
+ .procname = "boot_id",
+ .data = &sysctl_bootid,
+- .maxlen = 16,
+ .mode = 0444,
+ .proc_handler = proc_do_uuid,
+ },
+ {
+ .procname = "uuid",
+- .maxlen = 16,
+ .mode = 0444,
+ .proc_handler = proc_do_uuid,
+ },
+-#ifdef ADD_INTERRUPT_BENCH
+- {
+- .procname = "add_interrupt_avg_cycles",
+- .data = &avg_cycles,
+- .maxlen = sizeof(avg_cycles),
+- .mode = 0444,
+- .proc_handler = proc_doulongvec_minmax,
+- },
+- {
+- .procname = "add_interrupt_avg_deviation",
+- .data = &avg_deviation,
+- .maxlen = sizeof(avg_deviation),
+- .mode = 0444,
+- .proc_handler = proc_doulongvec_minmax,
+- },
+-#endif
+ { }
+ };
+-#endif /* CONFIG_SYSCTL */
+-
+-struct batched_entropy {
+- union {
+- u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)];
+- u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
+- };
+- unsigned int position;
+- spinlock_t batch_lock;
+-};
+-
+-/*
+- * Get a random word for internal kernel use only. The quality of the random
+- * number is good as /dev/urandom, but there is no backtrack protection, with
+- * the goal of being quite fast and not depleting entropy. In order to ensure
+- * that the randomness provided by this function is okay, the function
+- * wait_for_random_bytes() should be called and return 0 at least once at any
+- * point prior.
+- */
+-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+-};
+-
+-u64 get_random_u64(void)
+-{
+- u64 ret;
+- unsigned long flags;
+- struct batched_entropy *batch;
+- static void *previous;
+-
+- warn_unseeded_randomness(&previous);
+-
+- batch = raw_cpu_ptr(&batched_entropy_u64);
+- spin_lock_irqsave(&batch->batch_lock, flags);
+- if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+- extract_crng((u8 *)batch->entropy_u64);
+- batch->position = 0;
+- }
+- ret = batch->entropy_u64[batch->position++];
+- spin_unlock_irqrestore(&batch->batch_lock, flags);
+- return ret;
+-}
+-EXPORT_SYMBOL(get_random_u64);
+-
+-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+-};
+-u32 get_random_u32(void)
+-{
+- u32 ret;
+- unsigned long flags;
+- struct batched_entropy *batch;
+- static void *previous;
+-
+- warn_unseeded_randomness(&previous);
+-
+- batch = raw_cpu_ptr(&batched_entropy_u32);
+- spin_lock_irqsave(&batch->batch_lock, flags);
+- if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+- extract_crng((u8 *)batch->entropy_u32);
+- batch->position = 0;
+- }
+- ret = batch->entropy_u32[batch->position++];
+- spin_unlock_irqrestore(&batch->batch_lock, flags);
+- return ret;
+-}
+-EXPORT_SYMBOL(get_random_u32);
+-
+-/* It's important to invalidate all potential batched entropy that might
+- * be stored before the crng is initialized, which we can do lazily by
+- * simply resetting the counter to zero so that it's re-extracted on the
+- * next usage. */
+-static void invalidate_batched_entropy(void)
+-{
+- int cpu;
+- unsigned long flags;
+-
+- for_each_possible_cpu (cpu) {
+- struct batched_entropy *batched_entropy;
+-
+- batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+- spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+- batched_entropy->position = 0;
+- spin_unlock(&batched_entropy->batch_lock);
+-
+- batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+- spin_lock(&batched_entropy->batch_lock);
+- batched_entropy->position = 0;
+- spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+- }
+-}
+-
+-/**
+- * randomize_page - Generate a random, page aligned address
+- * @start: The smallest acceptable address the caller will take.
+- * @range: The size of the area, starting at @start, within which the
+- * random address must fall.
+- *
+- * If @start + @range would overflow, @range is capped.
+- *
+- * NOTE: Historical use of randomize_range, which this replaces, presumed that
+- * @start was already page aligned. We now align it regardless.
+- *
+- * Return: A page aligned address within [start, start + range). On error,
+- * @start is returned.
+- */
+-unsigned long
+-randomize_page(unsigned long start, unsigned long range)
+-{
+- if (!PAGE_ALIGNED(start)) {
+- range -= PAGE_ALIGN(start) - start;
+- start = PAGE_ALIGN(start);
+- }
+-
+- if (start > ULONG_MAX - range)
+- range = ULONG_MAX - start;
+-
+- range >>= PAGE_SHIFT;
+-
+- if (range == 0)
+- return start;
+-
+- return start + (get_random_long() % range << PAGE_SHIFT);
+-}
+-
+-/* Interface for in-kernel drivers of true hardware RNGs.
+- * Those devices may produce endless random bits and will be throttled
+- * when our pool is full.
+- */
+-void add_hwgenerator_randomness(const char *buffer, size_t count,
+- size_t entropy)
+-{
+- struct entropy_store *poolp = &input_pool;
+-
+- if (unlikely(crng_init == 0)) {
+- crng_fast_load(buffer, count);
+- return;
+- }
+-
+- /* Suspend writing if we're above the trickle threshold.
+- * We'll be woken up again once below random_write_wakeup_thresh,
+- * or when the calling thread is about to terminate.
+- */
- wait_event_interruptible(random_write_wait, kthread_should_stop() ||
-+ wait_event_interruptible(random_write_wait,
-+ !system_wq || kthread_should_stop() ||
- ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
- mix_pool_bytes(poolp, buffer, count);
- credit_entropy_bits(poolp, entropy);
+- ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+- mix_pool_bytes(poolp, buffer, count);
+- credit_entropy_bits(poolp, entropy);
+-}
+-EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+-
+-/* Handle random seed passed by bootloader.
+- * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+- * it would be regarded as device data.
+- * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+- */
+-void add_bootloader_randomness(const void *buf, unsigned int size)
+-{
+- if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+- add_hwgenerator_randomness(buf, size, size * 8);
+- else
+- add_device_randomness(buf, size);
+-}
+-EXPORT_SYMBOL_GPL(add_bootloader_randomness);
++#endif /* CONFIG_SYSCTL */
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
-index ddaeceb7e1091..df37e7b6a10a5 100644
+index ddaeceb7e1091..65d800ecc9964 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
-@@ -474,13 +474,21 @@ static void tpm_del_char_device(struct tpm_chip *chip)
+@@ -274,14 +274,6 @@ static void tpm_dev_release(struct device *dev)
+ kfree(chip);
+ }
+
+-static void tpm_devs_release(struct device *dev)
+-{
+- struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
+-
+- /* release the master device reference */
+- put_device(&chip->dev);
+-}
+-
+ /**
+ * tpm_class_shutdown() - prepare the TPM device for loss of power.
+ * @dev: device to which the chip is associated.
+@@ -344,7 +336,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
+ chip->dev_num = rc;
+
+ device_initialize(&chip->dev);
+- device_initialize(&chip->devs);
+
+ chip->dev.class = tpm_class;
+ chip->dev.class->shutdown_pre = tpm_class_shutdown;
+@@ -352,29 +343,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
+ chip->dev.parent = pdev;
+ chip->dev.groups = chip->groups;
+
+- chip->devs.parent = pdev;
+- chip->devs.class = tpmrm_class;
+- chip->devs.release = tpm_devs_release;
+- /* get extra reference on main device to hold on
+- * behalf of devs. This holds the chip structure
+- * while cdevs is in use. The corresponding put
+- * is in the tpm_devs_release (TPM2 only)
+- */
+- if (chip->flags & TPM_CHIP_FLAG_TPM2)
+- get_device(&chip->dev);
+-
+ if (chip->dev_num == 0)
+ chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
+ else
+ chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
+
+- chip->devs.devt =
+- MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
+-
+ rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
+- if (rc)
+- goto out;
+- rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
+ if (rc)
+ goto out;
+
+@@ -382,9 +356,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
+ chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
+
+ cdev_init(&chip->cdev, &tpm_fops);
+- cdev_init(&chip->cdevs, &tpmrm_fops);
+ chip->cdev.owner = THIS_MODULE;
+- chip->cdevs.owner = THIS_MODULE;
+
+ rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
+ if (rc) {
+@@ -396,7 +368,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
+ return chip;
+
+ out:
+- put_device(&chip->devs);
+ put_device(&chip->dev);
+ return ERR_PTR(rc);
+ }
+@@ -445,14 +416,9 @@ static int tpm_add_char_device(struct tpm_chip *chip)
+ }
+
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+- rc = cdev_device_add(&chip->cdevs, &chip->devs);
+- if (rc) {
+- dev_err(&chip->devs,
+- "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
+- dev_name(&chip->devs), MAJOR(chip->devs.devt),
+- MINOR(chip->devs.devt), rc);
+- return rc;
+- }
++ rc = tpm_devs_add(chip);
++ if (rc)
++ goto err_del_cdev;
+ }
+
+ /* Make the chip available. */
+@@ -460,6 +426,10 @@ static int tpm_add_char_device(struct tpm_chip *chip)
+ idr_replace(&dev_nums_idr, chip, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
++ return 0;
++
++err_del_cdev:
++ cdev_device_del(&chip->cdev, &chip->dev);
+ return rc;
+ }
+
+@@ -474,13 +444,21 @@ static void tpm_del_char_device(struct tpm_chip *chip)
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
@@ -28658,10 +49514,68 @@ index ddaeceb7e1091..df37e7b6a10a5 100644
up_write(&chip->ops_sem);
}
+@@ -641,7 +619,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
+ hwrng_unregister(&chip->hwrng);
+ tpm_bios_log_teardown(chip);
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+- cdev_device_del(&chip->cdevs, &chip->devs);
++ tpm_devs_remove(chip);
+ tpm_del_char_device(chip);
+ }
+ EXPORT_SYMBOL_GPL(tpm_chip_unregister);
+diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c
+index c08cbb306636b..dc4c0a0a51290 100644
+--- a/drivers/char/tpm/tpm-dev-common.c
++++ b/drivers/char/tpm/tpm-dev-common.c
+@@ -69,7 +69,13 @@ static void tpm_dev_async_work(struct work_struct *work)
+ ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
+ sizeof(priv->data_buffer));
+ tpm_put_ops(priv->chip);
+- if (ret > 0) {
++
++ /*
++ * If ret is > 0 then tpm_dev_transmit returned the size of the
++ * response. If ret is < 0 then tpm_dev_transmit failed and
++ * returned an error code.
++ */
++ if (ret != 0) {
+ priv->response_length = ret;
+ mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
+ }
+diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
+index 283f78211c3a7..2163c6ee0d364 100644
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -234,6 +234,8 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
+ size_t cmdsiz);
+ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf,
+ size_t *bufsiz);
++int tpm_devs_add(struct tpm_chip *chip);
++void tpm_devs_remove(struct tpm_chip *chip);
+
+ void tpm_bios_log_setup(struct tpm_chip *chip);
+ void tpm_bios_log_teardown(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
-index 784b8b3cb903f..97e916856cf3e 100644
+index 784b8b3cb903f..ffb35f0154c16 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
+@@ -58,12 +58,12 @@ int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
+
+ void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
+ {
+- mutex_lock(&chip->tpm_mutex);
+- if (!tpm_chip_start(chip)) {
++
++ if (tpm_try_get_ops(chip) == 0) {
+ tpm2_flush_sessions(chip, space);
+- tpm_chip_stop(chip);
++ tpm_put_ops(chip);
+ }
+- mutex_unlock(&chip->tpm_mutex);
++
+ kfree(space->context_buf);
+ kfree(space->session_buf);
+ }
@@ -455,6 +455,9 @@ static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp,
if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES)
return 0;
@@ -28672,6 +49586,75 @@ index 784b8b3cb903f..97e916856cf3e 100644
if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count))
return -EFAULT;
+@@ -571,3 +574,68 @@ out:
+ dev_err(&chip->dev, "%s: error %d\n", __func__, rc);
+ return rc;
+ }
++
++/*
++ * Put the reference to the main device.
++ */
++static void tpm_devs_release(struct device *dev)
++{
++ struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
++
++ /* release the master device reference */
++ put_device(&chip->dev);
++}
++
++/*
++ * Remove the device file for exposed TPM spaces and release the device
++ * reference. This may also release the reference to the master device.
++ */
++void tpm_devs_remove(struct tpm_chip *chip)
++{
++ cdev_device_del(&chip->cdevs, &chip->devs);
++ put_device(&chip->devs);
++}
++
++/*
++ * Add a device file to expose TPM spaces. Also take a reference to the
++ * main device.
++ */
++int tpm_devs_add(struct tpm_chip *chip)
++{
++ int rc;
++
++ device_initialize(&chip->devs);
++ chip->devs.parent = chip->dev.parent;
++ chip->devs.class = tpmrm_class;
++
++ /*
++ * Get extra reference on main device to hold on behalf of devs.
++ * This holds the chip structure while cdevs is in use. The
++ * corresponding put is in the tpm_devs_release.
++ */
++ get_device(&chip->dev);
++ chip->devs.release = tpm_devs_release;
++ chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
++ cdev_init(&chip->cdevs, &tpmrm_fops);
++ chip->cdevs.owner = THIS_MODULE;
++
++ rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
++ if (rc)
++ goto err_put_devs;
++
++ rc = cdev_device_add(&chip->cdevs, &chip->devs);
++ if (rc) {
++ dev_err(&chip->devs,
++ "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
++ dev_name(&chip->devs), MAJOR(chip->devs.devt),
++ MINOR(chip->devs.devt), rc);
++ goto err_put_devs;
++ }
++
++ return 0;
++
++err_put_devs:
++ put_device(&chip->devs);
++
++ return rc;
++}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 69579efb247b3..dc56b976d8162 100644
--- a/drivers/char/tpm/tpm_tis_core.c
@@ -28783,6 +49766,53 @@ index 54584b4b00d19..aaa59a00eeaef 100644
{ "cr50", (unsigned long)cr50_spi_probe },
{}
};
+diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
+index 7eaf303a7a86f..77bc993d75130 100644
+--- a/drivers/char/virtio_console.c
++++ b/drivers/char/virtio_console.c
+@@ -1956,6 +1956,13 @@ static void virtcons_remove(struct virtio_device *vdev)
+ list_del(&portdev->list);
+ spin_unlock_irq(&pdrvdata_lock);
+
++ /* Device is going away, exit any polling for buffers */
++ virtio_break_device(vdev);
++ if (use_multiport(portdev))
++ flush_work(&portdev->control_work);
++ else
++ flush_work(&portdev->config_work);
++
+ /* Disable interrupts for vqs */
+ vdev->config->reset(vdev);
+ /* Finish up work that's lined up */
+@@ -2229,7 +2236,7 @@ static struct virtio_driver virtio_rproc_serial = {
+ .remove = virtcons_remove,
+ };
+
+-static int __init init(void)
++static int __init virtio_console_init(void)
+ {
+ int err;
+
+@@ -2264,7 +2271,7 @@ free:
+ return err;
+ }
+
+-static void __exit fini(void)
++static void __exit virtio_console_fini(void)
+ {
+ reclaim_dma_bufs();
+
+@@ -2274,8 +2281,8 @@ static void __exit fini(void)
+ class_destroy(pdrvdata.class);
+ debugfs_remove_recursive(pdrvdata.debugfs_dir);
+ }
+-module_init(init);
+-module_exit(fini);
++module_init(virtio_console_init);
++module_exit(virtio_console_fini);
+
+ MODULE_DESCRIPTION("Virtio console driver");
+ MODULE_LICENSE("GPL");
diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c
index e7f88f35c7028..dc3551796e5ed 100644
--- a/drivers/char/xillybus/xillyusb.c
@@ -28795,6 +49825,46 @@ index e7f88f35c7028..dc3551796e5ed 100644
return -ENOMEM;
}
+diff --git a/drivers/clk/actions/owl-s700.c b/drivers/clk/actions/owl-s700.c
+index a2f34d13fb543..6ea7da1d6d755 100644
+--- a/drivers/clk/actions/owl-s700.c
++++ b/drivers/clk/actions/owl-s700.c
+@@ -162,6 +162,7 @@ static struct clk_div_table hdmia_div_table[] = {
+
+ static struct clk_div_table rmii_div_table[] = {
+ {0, 4}, {1, 10},
++ {0, 0}
+ };
+
+ /* divider clocks */
+diff --git a/drivers/clk/actions/owl-s900.c b/drivers/clk/actions/owl-s900.c
+index 790890978424a..5144ada2c7e1a 100644
+--- a/drivers/clk/actions/owl-s900.c
++++ b/drivers/clk/actions/owl-s900.c
+@@ -140,7 +140,7 @@ static struct clk_div_table rmii_ref_div_table[] = {
+
+ static struct clk_div_table usb3_mac_div_table[] = {
+ { 1, 2 }, { 2, 3 }, { 3, 4 },
+- { 0, 8 },
++ { 0, 0 }
+ };
+
+ static struct clk_div_table i2s_div_table[] = {
+diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
+index b656d25a97678..fe772baeb15ff 100644
+--- a/drivers/clk/at91/clk-generated.c
++++ b/drivers/clk/at91/clk-generated.c
+@@ -106,6 +106,10 @@ static void clk_generated_best_diff(struct clk_rate_request *req,
+ tmp_rate = parent_rate;
+ else
+ tmp_rate = parent_rate / div;
++
++ if (tmp_rate < req->min_rate || tmp_rate > req->max_rate)
++ return;
++
+ tmp_diff = abs(req->rate - tmp_rate);
+
+ if (*best_diff < 0 || *best_diff >= tmp_diff) {
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index a80427980bf73..04d0dd8385945 100644
--- a/drivers/clk/at91/clk-master.c
@@ -28858,9 +49928,30 @@ index 20ee9dccee787..b40035b011d0a 100644
of_node_put(np);
if (IS_ERR(pmcreg))
diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
-index cf8c079aa086a..019e712f90d6f 100644
+index cf8c079aa086a..9eed97a299d0f 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
+@@ -687,16 +687,16 @@ static const struct {
+ { .n = "pdmc0_gclk",
+ .id = 68,
+ .r = { .max = 50000000 },
+- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+- .pp_mux_table = { 5, 8, },
++ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
++ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pdmc1_gclk",
+ .id = 69,
+ .r = { .max = 50000000, },
+- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+- .pp_mux_table = { 5, 8, },
++ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
++ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
@@ -982,16 +982,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
}
@@ -29035,11 +50126,59 @@ index e6d6599d310a1..fad78a22218e8 100644
return PTR_ERR(hw);
}
+diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c
+index a2c6486ef1708..f8417ee2961aa 100644
+--- a/drivers/clk/clk-clps711x.c
++++ b/drivers/clk/clk-clps711x.c
+@@ -28,11 +28,13 @@ static const struct clk_div_table spi_div_table[] = {
+ { .val = 1, .div = 8, },
+ { .val = 2, .div = 2, },
+ { .val = 3, .div = 1, },
++ { /* sentinel */ }
+ };
+
+ static const struct clk_div_table timer_div_table[] = {
+ { .val = 0, .div = 256, },
+ { .val = 1, .div = 1, },
++ { /* sentinel */ }
+ };
+
+ struct clps711x_clk {
diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c
-index 57ae183982d8c..f7b41366666e5 100644
+index 57ae183982d8c..4de098b6b0d4e 100644
--- a/drivers/clk/clk-si5341.c
+++ b/drivers/clk/clk-si5341.c
-@@ -1740,7 +1740,7 @@ static int si5341_probe(struct i2c_client *client,
+@@ -798,6 +798,15 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw,
+ u32 r_divider;
+ u8 r[3];
+
++ err = regmap_read(output->data->regmap,
++ SI5341_OUT_CONFIG(output), &val);
++ if (err < 0)
++ return err;
++
++ /* If SI5341_OUT_CFG_RDIV_FORCE2 is set, r_divider is 2 */
++ if (val & SI5341_OUT_CFG_RDIV_FORCE2)
++ return parent_rate / 2;
++
+ err = regmap_bulk_read(output->data->regmap,
+ SI5341_OUT_R_REG(output), r, 3);
+ if (err < 0)
+@@ -814,13 +823,6 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw,
+ r_divider += 1;
+ r_divider <<= 1;
+
+- err = regmap_read(output->data->regmap,
+- SI5341_OUT_CONFIG(output), &val);
+- if (err < 0)
+- return err;
+-
+- if (val & SI5341_OUT_CFG_RDIV_FORCE2)
+- r_divider = 2;
+
+ return parent_rate / r_divider;
+ }
+@@ -1740,7 +1742,7 @@ static int si5341_probe(struct i2c_client *client,
clk_prepare(data->clk[i].hw.clk);
}
@@ -29085,10 +50224,55 @@ index af46176ad0539..473dfe632cc57 100644
};
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
-index 65508eb89ec99..ac11cefc31911 100644
+index 65508eb89ec99..d6dc58bd07b33 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
-@@ -3340,6 +3340,24 @@ static int __init clk_debug_init(void)
+@@ -631,6 +631,24 @@ static void clk_core_get_boundaries(struct clk_core *core,
+ *max_rate = min(*max_rate, clk_user->max_rate);
+ }
+
++static bool clk_core_check_boundaries(struct clk_core *core,
++ unsigned long min_rate,
++ unsigned long max_rate)
++{
++ struct clk *user;
++
++ lockdep_assert_held(&prepare_lock);
++
++ if (min_rate > core->max_rate || max_rate < core->min_rate)
++ return false;
++
++ hlist_for_each_entry(user, &core->clks, clks_node)
++ if (min_rate > user->max_rate || max_rate < user->min_rate)
++ return false;
++
++ return true;
++}
++
+ void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
+ unsigned long max_rate)
+ {
+@@ -2347,6 +2365,11 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+ clk->min_rate = min;
+ clk->max_rate = max;
+
++ if (!clk_core_check_boundaries(clk->core, min, max)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
+ rate = clk_core_get_rate_nolock(clk->core);
+ if (rate < min || rate > max) {
+ /*
+@@ -2375,6 +2398,7 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+ }
+ }
+
++out:
+ if (clk->exclusive_count)
+ clk_core_rate_protect(clk->core);
+
+@@ -3340,6 +3364,24 @@ static int __init clk_debug_init(void)
{
struct clk_core *core;
@@ -29113,7 +50297,27 @@ index 65508eb89ec99..ac11cefc31911 100644
rootdir = debugfs_create_dir("clk", NULL);
debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
-@@ -3415,6 +3433,14 @@ static int __clk_core_init(struct clk_core *core)
+@@ -3392,6 +3434,19 @@ static void clk_core_reparent_orphans_nolock(void)
+ __clk_set_parent_after(orphan, parent, NULL);
+ __clk_recalc_accuracies(orphan);
+ __clk_recalc_rates(orphan, 0);
++
++ /*
++ * __clk_init_parent() will set the initial req_rate to
++ * 0 if the clock doesn't have clk_ops::recalc_rate and
++ * is an orphan when it's registered.
++ *
++ * 'req_rate' is used by clk_set_rate_range() and
++ * clk_put() to trigger a clk_set_rate() call whenever
++ * the boundaries are modified. Let's make sure
++ * 'req_rate' is set to something non-zero so that
++ * clk_set_rate_range() doesn't drop the frequency.
++ */
++ orphan->req_rate = orphan->rate;
+ }
+ }
+ }
+@@ -3415,6 +3470,14 @@ static int __clk_core_init(struct clk_core *core)
clk_prepare_lock();
@@ -29128,7 +50332,7 @@ index 65508eb89ec99..ac11cefc31911 100644
ret = clk_pm_runtime_get(core);
if (ret)
goto unlock;
-@@ -3579,8 +3605,10 @@ static int __clk_core_init(struct clk_core *core)
+@@ -3579,8 +3642,10 @@ static int __clk_core_init(struct clk_core *core)
out:
clk_pm_runtime_put(core);
unlock:
@@ -29140,7 +50344,18 @@ index 65508eb89ec99..ac11cefc31911 100644
clk_prepare_unlock();
-@@ -3844,7 +3872,6 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+@@ -3702,8 +3767,9 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
+ struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
+ {
+ struct device *dev = hw->core->dev;
++ const char *name = dev ? dev_name(dev) : NULL;
+
+- return clk_hw_create_clk(dev, hw, dev_name(dev), con_id);
++ return clk_hw_create_clk(dev, hw, name, con_id);
+ }
+ EXPORT_SYMBOL(clk_hw_get_clk);
+
+@@ -3844,7 +3910,6 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
core->num_parents = init->num_parents;
core->min_rate = 0;
core->max_rate = ULONG_MAX;
@@ -29148,7 +50363,7 @@ index 65508eb89ec99..ac11cefc31911 100644
ret = clk_core_populate_parent_map(core, init);
if (ret)
-@@ -3862,7 +3889,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+@@ -3862,7 +3927,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
goto fail_create_clk;
}
@@ -29157,6 +50372,21 @@ index 65508eb89ec99..ac11cefc31911 100644
ret = __clk_core_init(core);
if (!ret)
+diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c
+index 56012a3d02192..9ea1a80acbe8b 100644
+--- a/drivers/clk/hisilicon/clk-hi3559a.c
++++ b/drivers/clk/hisilicon/clk-hi3559a.c
+@@ -611,8 +611,8 @@ static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = {
+
+
+ /* shub div clk */
+-static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}};
+-static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}};
++static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}, {/*sentinel*/}};
++static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}, {/*sentinel*/}};
+
+ static struct hisi_divider_clock hi3559av100_shub_div_clks[] = {
+ { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2,
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index 5dbb6a9377324..206e4c43f68f8 100644
--- a/drivers/clk/imx/clk-imx6ul.c
@@ -29177,6 +50407,18 @@ index 5dbb6a9377324..206e4c43f68f8 100644
hws[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
hws[IMX6UL_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
+index c4e0f1c07192f..3f6fd7ef2a68f 100644
+--- a/drivers/clk/imx/clk-imx7d.c
++++ b/drivers/clk/imx/clk-imx7d.c
+@@ -849,7 +849,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
+ hws[IMX7D_WDOG4_ROOT_CLK] = imx_clk_hw_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
+ hws[IMX7D_KPP_ROOT_CLK] = imx_clk_hw_gate4("kpp_root_clk", "ipg_root_clk", base + 0x4aa0, 0);
+ hws[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_hw_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
+- hws[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_hw_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
+ hws[IMX7D_WRCLK_ROOT_CLK] = imx_clk_hw_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+ hws[IMX7D_USB_CTRL_CLK] = imx_clk_hw_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
+ hws[IMX7D_USB_PHY1_CLK] = imx_clk_hw_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index c55577604e16a..021355a247081 100644
--- a/drivers/clk/imx/clk-imx8mn.c
@@ -29195,9 +50437,18 @@ index c55577604e16a..021355a247081 100644
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
"video_pll1_out", "osc_32k", };
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
-index d3e905cf867d7..b23758083ce52 100644
+index d3e905cf867d7..5e31a6a24b3a3 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
+@@ -248,7 +248,7 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev,
+
+ for (i = 0; i < count; i++) {
+ idx = bit_offset[i] / 4;
+- if (idx > IMX_LPCG_MAX_CLKS) {
++ if (idx >= IMX_LPCG_MAX_CLKS) {
+ dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
+ i);
+ ret = -EINVAL;
@@ -370,7 +370,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
.probe = imx8qxp_lpcg_clk_probe,
};
@@ -29260,6 +50511,18 @@ index 5154b0cf8ad6c..66ff141da0a42 100644
},
[JZ4725B_CLK_SPI] = {
+diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c
+index 703f87622cf5f..1ebf740380efb 100644
+--- a/drivers/clk/loongson1/clk-loongson1c.c
++++ b/drivers/clk/loongson1/clk-loongson1c.c
+@@ -37,6 +37,7 @@ static const struct clk_div_table ahb_div_table[] = {
+ [1] = { .val = 1, .div = 4 },
+ [2] = { .val = 2, .div = 3 },
+ [3] = { .val = 3, .div = 3 },
++ [4] = { /* sentinel */ }
+ };
+
+ void __init ls1x_clk_init(void)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index d6eed760327d0..608e0e8ca49a8 100644
--- a/drivers/clk/meson/gxbb.c
@@ -29409,6 +50672,46 @@ index eaedcceb766f9..8f65b9bdafce4 100644
clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);
clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
+index e1b1b426fae4b..f675fd969c4de 100644
+--- a/drivers/clk/qcom/clk-rcg2.c
++++ b/drivers/clk/qcom/clk-rcg2.c
+@@ -264,7 +264,7 @@ static int clk_rcg2_determine_floor_rate(struct clk_hw *hw,
+
+ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
+ {
+- u32 cfg, mask;
++ u32 cfg, mask, d_val, not2d_val, n_minus_m;
+ struct clk_hw *hw = &rcg->clkr.hw;
+ int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+
+@@ -283,8 +283,17 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
+ if (ret)
+ return ret;
+
++ /* Calculate 2d value */
++ d_val = f->n;
++
++ n_minus_m = f->n - f->m;
++ n_minus_m *= 2;
++
++ d_val = clamp_t(u32, d_val, f->m, n_minus_m);
++ not2d_val = ~d_val & mask;
++
+ ret = regmap_update_bits(rcg->clkr.regmap,
+- RCG_D_OFFSET(rcg), mask, ~f->n);
++ RCG_D_OFFSET(rcg), mask, not2d_val);
+ if (ret)
+ return ret;
+ }
+@@ -720,6 +729,7 @@ static const struct frac_entry frac_table_pixel[] = {
+ { 2, 9 },
+ { 4, 9 },
+ { 1, 1 },
++ { 2, 3 },
+ { }
+ };
+
diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c
index b2d00b4519634..45d9cca28064f 100644
--- a/drivers/clk/qcom/clk-regmap-mux.c
@@ -29458,6 +50761,158 @@ index bb39a7e106d8a..9c8f7b798d9fc 100644
extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
const char *name, unsigned long rate);
+diff --git a/drivers/clk/qcom/dispcc-sc7180.c b/drivers/clk/qcom/dispcc-sc7180.c
+index 538e4963c9152..5d2ae297e7413 100644
+--- a/drivers/clk/qcom/dispcc-sc7180.c
++++ b/drivers/clk/qcom/dispcc-sc7180.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2019, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2019, 2022, The Linux Foundation. All rights reserved.
+ */
+
+ #include <linux/clk-provider.h>
+@@ -625,6 +625,9 @@ static struct clk_branch disp_cc_mdss_vsync_clk = {
+
+ static struct gdsc mdss_gdsc = {
+ .gdscr = 0x3000,
++ .en_rest_wait_val = 0x2,
++ .en_few_wait_val = 0x2,
++ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+diff --git a/drivers/clk/qcom/dispcc-sc7280.c b/drivers/clk/qcom/dispcc-sc7280.c
+index 4ef4ae231794b..ad596d567f6ab 100644
+--- a/drivers/clk/qcom/dispcc-sc7280.c
++++ b/drivers/clk/qcom/dispcc-sc7280.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2021, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2021-2022, The Linux Foundation. All rights reserved.
+ */
+
+ #include <linux/clk-provider.h>
+@@ -787,6 +787,9 @@ static struct clk_branch disp_cc_sleep_clk = {
+
+ static struct gdsc disp_cc_mdss_core_gdsc = {
+ .gdscr = 0x1004,
++ .en_rest_wait_val = 0x2,
++ .en_few_wait_val = 0x2,
++ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "disp_cc_mdss_core_gdsc",
+ },
+diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c
+index bf9ffe1a1cf47..73c5feea9818b 100644
+--- a/drivers/clk/qcom/dispcc-sm8250.c
++++ b/drivers/clk/qcom/dispcc-sm8250.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2018-2020, 2022, The Linux Foundation. All rights reserved.
+ */
+
+ #include <linux/clk-provider.h>
+@@ -1125,6 +1125,9 @@ static struct clk_branch disp_cc_mdss_vsync_clk = {
+
+ static struct gdsc mdss_gdsc = {
+ .gdscr = 0x3000,
++ .en_rest_wait_val = 0x2,
++ .en_few_wait_val = 0x2,
++ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
+index 108fe27bee10f..541016db3c4bb 100644
+--- a/drivers/clk/qcom/gcc-ipq8074.c
++++ b/drivers/clk/qcom/gcc-ipq8074.c
+@@ -60,11 +60,6 @@ static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
+ { P_GPLL0_DIV2, 4 },
+ };
+
+-static const char * const gcc_xo_gpll0[] = {
+- "xo",
+- "gpll0",
+-};
+-
+ static const struct parent_map gcc_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+@@ -956,6 +951,11 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+ },
+ };
+
++static const struct clk_parent_data gcc_xo_gpll0[] = {
++ { .fw_name = "xo" },
++ { .hw = &gpll0.clkr.hw },
++};
++
+ static const struct freq_tbl ftbl_pcie_axi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+@@ -969,7 +969,7 @@ static struct clk_rcg2 pcie0_axi_clk_src = {
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie0_axi_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1016,7 +1016,7 @@ static struct clk_rcg2 pcie1_axi_clk_src = {
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie1_axi_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1074,7 +1074,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
+ .num_parents = 4,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+
+@@ -1330,7 +1330,7 @@ static struct clk_rcg2 nss_ce_clk_src = {
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "nss_ce_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+@@ -4329,8 +4329,7 @@ static struct clk_rcg2 pcie0_rchng_clk_src = {
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie0_rchng_clk_src",
+- .parent_hws = (const struct clk_hw *[]) {
+- &gpll0.clkr.hw },
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c
+index 144d2ba7a9bef..463a444c8a7e4 100644
+--- a/drivers/clk/qcom/gcc-msm8994.c
++++ b/drivers/clk/qcom/gcc-msm8994.c
+@@ -108,6 +108,7 @@ static struct clk_alpha_pll gpll4_early = {
+
+ static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x1dc0,
++ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data)
+ {
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index 3c3a7ff045621..9b1674b28d45d 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
@@ -29526,6 +50981,88 @@ index 543cfab7561f9..431b55bb0d2f7 100644
},
};
+diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
+index 4ece326ea233e..cf23cfd7e4674 100644
+--- a/drivers/clk/qcom/gdsc.c
++++ b/drivers/clk/qcom/gdsc.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved.
+ */
+
+ #include <linux/bitops.h>
+@@ -34,9 +34,14 @@
+ #define CFG_GDSCR_OFFSET 0x4
+
+ /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+-#define EN_REST_WAIT_VAL (0x2 << 20)
+-#define EN_FEW_WAIT_VAL (0x8 << 16)
+-#define CLK_DIS_WAIT_VAL (0x2 << 12)
++#define EN_REST_WAIT_VAL 0x2
++#define EN_FEW_WAIT_VAL 0x8
++#define CLK_DIS_WAIT_VAL 0x2
++
++/* Transition delay shifts */
++#define EN_REST_WAIT_SHIFT 20
++#define EN_FEW_WAIT_SHIFT 16
++#define CLK_DIS_WAIT_SHIFT 12
+
+ #define RETAIN_MEM BIT(14)
+ #define RETAIN_PERIPH BIT(13)
+@@ -341,7 +346,18 @@ static int gdsc_init(struct gdsc *sc)
+ */
+ mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK |
+ EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK;
+- val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
++
++ if (!sc->en_rest_wait_val)
++ sc->en_rest_wait_val = EN_REST_WAIT_VAL;
++ if (!sc->en_few_wait_val)
++ sc->en_few_wait_val = EN_FEW_WAIT_VAL;
++ if (!sc->clk_dis_wait_val)
++ sc->clk_dis_wait_val = CLK_DIS_WAIT_VAL;
++
++ val = sc->en_rest_wait_val << EN_REST_WAIT_SHIFT |
++ sc->en_few_wait_val << EN_FEW_WAIT_SHIFT |
++ sc->clk_dis_wait_val << CLK_DIS_WAIT_SHIFT;
++
+ ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val);
+ if (ret)
+ return ret;
+diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
+index 5bb396b344d16..762f1b5e1ec51 100644
+--- a/drivers/clk/qcom/gdsc.h
++++ b/drivers/clk/qcom/gdsc.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0-only */
+ /*
+- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved.
+ */
+
+ #ifndef __QCOM_GDSC_H__
+@@ -22,6 +22,9 @@ struct reset_controller_dev;
+ * @cxcs: offsets of branch registers to toggle mem/periph bits in
+ * @cxc_count: number of @cxcs
+ * @pwrsts: Possible powerdomain power states
++ * @en_rest_wait_val: transition delay value for receiving enr ack signal
++ * @en_few_wait_val: transition delay value for receiving enf ack signal
++ * @clk_dis_wait_val: transition delay value for halting clock
+ * @resets: ids of resets associated with this gdsc
+ * @reset_count: number of @resets
+ * @rcdev: reset controller
+@@ -35,6 +38,9 @@ struct gdsc {
+ unsigned int clamp_io_ctrl;
+ unsigned int *cxcs;
+ unsigned int cxc_count;
++ unsigned int en_rest_wait_val;
++ unsigned int en_few_wait_val;
++ unsigned int clk_dis_wait_val;
+ const u8 pwrsts;
+ /* Powerdomain allowable state bitfields */
+ #define PWRSTS_OFF BIT(0)
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 761922ea5db76..1c92e73cd2b8c 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
@@ -29566,6 +51103,48 @@ index 761922ea5db76..1c92e73cd2b8c 100644
}
static int __init rzg2l_cpg_probe(struct platform_device *pdev)
+diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
+index 75ca855e720df..6e5440841d1ee 100644
+--- a/drivers/clk/rockchip/clk-rk3568.c
++++ b/drivers/clk/rockchip/clk-rk3568.c
+@@ -1038,13 +1038,13 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
+ RK3568_CLKGATE_CON(20), 8, GFLAGS),
+ GATE(HCLK_VOP, "hclk_vop", "hclk_vo", 0,
+ RK3568_CLKGATE_CON(20), 9, GFLAGS),
+- COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
++ COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(39), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 10, GFLAGS),
+- COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
++ COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(40), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 11, GFLAGS),
+- COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, 0,
++ COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(41), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 12, GFLAGS),
+ GATE(CLK_VOP_PWM, "clk_vop_pwm", "xin24m", 0,
+diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
+index b7be7e11b0dfe..bb8a844309bf5 100644
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -180,6 +180,7 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n)
+ {
++ struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long p_rate, p_parent_rate;
+ struct clk_hw *p_parent;
+
+@@ -190,6 +191,8 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
+ *parent_rate = p_parent_rate;
+ }
+
++ fd->flags |= CLK_FRAC_DIVIDER_POWER_OF_TWO_PS;
++
+ clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
+ }
+
diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
index f32366d9336e7..bd9a8782fec3d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
@@ -30007,6 +51586,74 @@ index 04e7a12200a21..98a1834b58bb4 100644
+ const struct sunxi_ccu_desc *desc);
#endif /* _COMMON_H_ */
+diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c
+index 542b31d6e96dd..636bcf2439ef2 100644
+--- a/drivers/clk/sunxi/clk-sun9i-mmc.c
++++ b/drivers/clk/sunxi/clk-sun9i-mmc.c
+@@ -109,6 +109,8 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev)
+ spin_lock_init(&data->lock);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r)
++ return -EINVAL;
+ /* one clock/reset pair per word */
+ count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH);
+ data->membase = devm_ioremap_resource(&pdev->dev, r);
+diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c
+index 74c1d894cca86..219c80653dbdb 100644
+--- a/drivers/clk/tegra/clk-tegra124-emc.c
++++ b/drivers/clk/tegra/clk-tegra124-emc.c
+@@ -198,6 +198,7 @@ static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra)
+
+ tegra->emc = platform_get_drvdata(pdev);
+ if (!tegra->emc) {
++ put_device(&pdev->dev);
+ pr_err("%s: cannot find EMC driver\n", __func__);
+ return NULL;
+ }
+diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
+index 3da33c786d77c..29eafab4353ef 100644
+--- a/drivers/clk/ti/clk.c
++++ b/drivers/clk/ti/clk.c
+@@ -131,7 +131,7 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
+ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+ {
+ struct ti_dt_clk *c;
+- struct device_node *node, *parent;
++ struct device_node *node, *parent, *child;
+ struct clk *clk;
+ struct of_phandle_args clkspec;
+ char buf[64];
+@@ -171,10 +171,13 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+ node = of_find_node_by_name(NULL, buf);
+ if (num_args && compat_mode) {
+ parent = node;
+- node = of_get_child_by_name(parent, "clock");
+- if (!node)
+- node = of_get_child_by_name(parent, "clk");
+- of_node_put(parent);
++ child = of_get_child_by_name(parent, "clock");
++ if (!child)
++ child = of_get_child_by_name(parent, "clk");
++ if (child) {
++ of_node_put(parent);
++ node = child;
++ }
+ }
+
+ clkspec.np = node;
+diff --git a/drivers/clk/uniphier/clk-uniphier-fixed-rate.c b/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
+index 5319cd3804801..3bc55ab75314b 100644
+--- a/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
++++ b/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
+@@ -24,6 +24,7 @@ struct clk_hw *uniphier_clk_register_fixed_rate(struct device *dev,
+
+ init.name = name;
+ init.ops = &clk_fixed_rate_ops;
++ init.flags = 0;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 0f5e3983951a8..08f8cb944a2ac 100644
--- a/drivers/clocksource/Kconfig
@@ -30019,6 +51666,23 @@ index 0f5e3983951a8..08f8cb944a2ac 100644
config CLKBLD_I8253
def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK
+diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
+index eb596ff9e7bb3..279ddff81ab49 100644
+--- a/drivers/clocksource/acpi_pm.c
++++ b/drivers/clocksource/acpi_pm.c
+@@ -229,8 +229,10 @@ static int __init parse_pmtmr(char *arg)
+ int ret;
+
+ ret = kstrtouint(arg, 16, &base);
+- if (ret)
+- return ret;
++ if (ret) {
++ pr_warn("PMTMR: invalid 'pmtmr=' value: '%s'\n", arg);
++ return 1;
++ }
+
+ pr_info("PMTMR IOPort override: 0x%04x -> 0x%04x\n", pmtmr_ioport,
+ base);
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index 3819ef5b70989..3245eb0c602d2 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
@@ -30032,8 +51696,140 @@ index 3819ef5b70989..3245eb0c602d2 100644
!of_property_read_u32(np, "clock-frequency", rate))
return 0;
+diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
+index 5e3e96d3d1b98..cc2a961ddd3be 100644
+--- a/drivers/clocksource/exynos_mct.c
++++ b/drivers/clocksource/exynos_mct.c
+@@ -504,11 +504,14 @@ static int exynos4_mct_dying_cpu(unsigned int cpu)
+ return 0;
+ }
+
+-static int __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
++static int __init exynos4_timer_resources(struct device_node *np)
+ {
+- int err, cpu;
+ struct clk *mct_clk, *tick_clk;
+
++ reg_base = of_iomap(np, 0);
++ if (!reg_base)
++ panic("%s: unable to ioremap mct address space\n", __func__);
++
+ tick_clk = of_clk_get_by_name(np, "fin_pll");
+ if (IS_ERR(tick_clk))
+ panic("%s: unable to determine tick clock rate\n", __func__);
+@@ -519,9 +522,32 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
+ panic("%s: unable to retrieve mct clock instance\n", __func__);
+ clk_prepare_enable(mct_clk);
+
+- reg_base = base;
+- if (!reg_base)
+- panic("%s: unable to ioremap mct address space\n", __func__);
++ return 0;
++}
++
++static int __init exynos4_timer_interrupts(struct device_node *np,
++ unsigned int int_type)
++{
++ int nr_irqs, i, err, cpu;
++
++ mct_int_type = int_type;
++
++ /* This driver uses only one global timer interrupt */
++ mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
++
++ /*
++ * Find out the number of local irqs specified. The local
++ * timer irqs are specified after the four global timer
++ * irqs are specified.
++ */
++ nr_irqs = of_irq_count(np);
++ if (nr_irqs > ARRAY_SIZE(mct_irqs)) {
++ pr_err("exynos-mct: too many (%d) interrupts configured in DT\n",
++ nr_irqs);
++ nr_irqs = ARRAY_SIZE(mct_irqs);
++ }
++ for (i = MCT_L0_IRQ; i < nr_irqs; i++)
++ mct_irqs[i] = irq_of_parse_and_map(np, i);
+
+ if (mct_int_type == MCT_INT_PPI) {
+
+@@ -532,11 +558,14 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
+ mct_irqs[MCT_L0_IRQ], err);
+ } else {
+ for_each_possible_cpu(cpu) {
+- int mct_irq = mct_irqs[MCT_L0_IRQ + cpu];
++ int mct_irq;
+ struct mct_clock_event_device *pcpu_mevt =
+ per_cpu_ptr(&percpu_mct_tick, cpu);
+
+ pcpu_mevt->evt.irq = -1;
++ if (MCT_L0_IRQ + cpu >= ARRAY_SIZE(mct_irqs))
++ break;
++ mct_irq = mct_irqs[MCT_L0_IRQ + cpu];
+
+ irq_set_status_flags(mct_irq, IRQ_NOAUTOEN);
+ if (request_irq(mct_irq,
+@@ -581,24 +610,13 @@ out_irq:
+
+ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
+ {
+- u32 nr_irqs, i;
+ int ret;
+
+- mct_int_type = int_type;
+-
+- /* This driver uses only one global timer interrupt */
+- mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+-
+- /*
+- * Find out the number of local irqs specified. The local
+- * timer irqs are specified after the four global timer
+- * irqs are specified.
+- */
+- nr_irqs = of_irq_count(np);
+- for (i = MCT_L0_IRQ; i < nr_irqs; i++)
+- mct_irqs[i] = irq_of_parse_and_map(np, i);
++ ret = exynos4_timer_resources(np);
++ if (ret)
++ return ret;
+
+- ret = exynos4_timer_resources(np, of_iomap(np, 0));
++ ret = exynos4_timer_interrupts(np, int_type);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/clocksource/timer-microchip-pit64b.c b/drivers/clocksource/timer-microchip-pit64b.c
+index cfa4ec7ef3968..790d2c9b42a70 100644
+--- a/drivers/clocksource/timer-microchip-pit64b.c
++++ b/drivers/clocksource/timer-microchip-pit64b.c
+@@ -165,7 +165,7 @@ static u64 mchp_pit64b_clksrc_read(struct clocksource *cs)
+ return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
+ }
+
+-static u64 mchp_pit64b_sched_read_clk(void)
++static u64 notrace mchp_pit64b_sched_read_clk(void)
+ {
+ return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
+ }
+diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c
+index 529cc6a51cdb3..c3f54d9912be7 100644
+--- a/drivers/clocksource/timer-of.c
++++ b/drivers/clocksource/timer-of.c
+@@ -157,9 +157,9 @@ static __init int timer_of_base_init(struct device_node *np,
+ of_base->base = of_base->name ?
+ of_io_request_and_map(np, of_base->index, of_base->name) :
+ of_iomap(np, of_base->index);
+- if (IS_ERR(of_base->base)) {
+- pr_err("Failed to iomap (%s)\n", of_base->name);
+- return PTR_ERR(of_base->base);
++ if (IS_ERR_OR_NULL(of_base->base)) {
++ pr_err("Failed to iomap (%s:%s)\n", np->name, of_base->name);
++ return of_base->base ? PTR_ERR(of_base->base) : -ENOMEM;
+ }
+
+ return 0;
diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
-index b6f97960d8ee0..1fccb457fcc54 100644
+index b6f97960d8ee0..2737407ff0698 100644
--- a/drivers/clocksource/timer-ti-dm-systimer.c
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
@@ -241,8 +241,7 @@ static void __init dmtimer_systimer_assign_alwon(void)
@@ -30046,6 +51842,18 @@ index b6f97960d8ee0..1fccb457fcc54 100644
quirk_unreliable_oscillator = true;
counter_32k = -ENODEV;
}
+@@ -695,9 +694,9 @@ static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa)
+ return 0;
+ }
+
+- if (pa == 0x48034000) /* dra7 dmtimer3 */
++ if (pa == 0x4882c000) /* dra7 dmtimer15 */
+ return dmtimer_percpu_timer_init(np, 0);
+- else if (pa == 0x48036000) /* dra7 dmtimer4 */
++ else if (pa == 0x4882e000) /* dra7 dmtimer16 */
+ return dmtimer_percpu_timer_init(np, 1);
+
+ return 0;
diff --git a/drivers/comedi/drivers/dt9812.c b/drivers/comedi/drivers/dt9812.c
index 634f57730c1e0..704b04d2980d3 100644
--- a/drivers/comedi/drivers/dt9812.c
@@ -30333,6 +52141,92 @@ index 9f920819cd742..4b00a9ea611ab 100644
devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL);
if (!devpriv->usb_tx_buf)
return -ENOMEM;
+diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
+index d4c27022b9c9b..e0ff09d66c96b 100644
+--- a/drivers/cpufreq/cppc_cpufreq.c
++++ b/drivers/cpufreq/cppc_cpufreq.c
+@@ -303,52 +303,48 @@ static u64 cppc_get_dmi_max_khz(void)
+
+ /*
+ * If CPPC lowest_freq and nominal_freq registers are exposed then we can
+- * use them to convert perf to freq and vice versa
+- *
+- * If the perf/freq point lies between Nominal and Lowest, we can treat
+- * (Low perf, Low freq) and (Nom Perf, Nom freq) as 2D co-ordinates of a line
+- * and extrapolate the rest
+- * For perf/freq > Nominal, we use the ratio perf:freq at Nominal for conversion
++ * use them to convert perf to freq and vice versa. The conversion is
++ * extrapolated as an affine function passing by the 2 points:
++ * - (Low perf, Low freq)
++ * - (Nominal perf, Nominal perf)
+ */
+ static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu_data,
+ unsigned int perf)
+ {
+ struct cppc_perf_caps *caps = &cpu_data->perf_caps;
++ s64 retval, offset = 0;
+ static u64 max_khz;
+ u64 mul, div;
+
+ if (caps->lowest_freq && caps->nominal_freq) {
+- if (perf >= caps->nominal_perf) {
+- mul = caps->nominal_freq;
+- div = caps->nominal_perf;
+- } else {
+- mul = caps->nominal_freq - caps->lowest_freq;
+- div = caps->nominal_perf - caps->lowest_perf;
+- }
++ mul = caps->nominal_freq - caps->lowest_freq;
++ div = caps->nominal_perf - caps->lowest_perf;
++ offset = caps->nominal_freq - div64_u64(caps->nominal_perf * mul, div);
+ } else {
+ if (!max_khz)
+ max_khz = cppc_get_dmi_max_khz();
+ mul = max_khz;
+ div = caps->highest_perf;
+ }
+- return (u64)perf * mul / div;
++
++ retval = offset + div64_u64(perf * mul, div);
++ if (retval >= 0)
++ return retval;
++ return 0;
+ }
+
+ static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data,
+ unsigned int freq)
+ {
+ struct cppc_perf_caps *caps = &cpu_data->perf_caps;
++ s64 retval, offset = 0;
+ static u64 max_khz;
+ u64 mul, div;
+
+ if (caps->lowest_freq && caps->nominal_freq) {
+- if (freq >= caps->nominal_freq) {
+- mul = caps->nominal_perf;
+- div = caps->nominal_freq;
+- } else {
+- mul = caps->lowest_perf;
+- div = caps->lowest_freq;
+- }
++ mul = caps->nominal_perf - caps->lowest_perf;
++ div = caps->nominal_freq - caps->lowest_freq;
++ offset = caps->nominal_perf - div64_u64(caps->nominal_freq * mul, div);
+ } else {
+ if (!max_khz)
+ max_khz = cppc_get_dmi_max_khz();
+@@ -356,7 +352,10 @@ static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data,
+ div = max_khz;
+ }
+
+- return (u64)freq * mul / div;
++ retval = offset + div64_u64(freq * mul, div);
++ if (retval >= 0)
++ return retval;
++ return 0;
+ }
+
+ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 5782b15a8caad..eeac6d8092298 100644
--- a/drivers/cpufreq/cpufreq.c
@@ -30403,10 +52297,34 @@ index 5782b15a8caad..eeac6d8092298 100644
policy->cached_target_freq = UINT_MAX;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
-index 8c176b7dae415..e15c3bc17a55c 100644
+index 8c176b7dae415..8a2c6b58b6524 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
-@@ -537,7 +537,8 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
+@@ -335,6 +335,8 @@ static void intel_pstste_sched_itmt_work_fn(struct work_struct *work)
+
+ static DECLARE_WORK(sched_itmt_work, intel_pstste_sched_itmt_work_fn);
+
++#define CPPC_MAX_PERF U8_MAX
++
+ static void intel_pstate_set_itmt_prio(int cpu)
+ {
+ struct cppc_perf_caps cppc_perf;
+@@ -345,6 +347,14 @@ static void intel_pstate_set_itmt_prio(int cpu)
+ if (ret)
+ return;
+
++ /*
++ * On some systems with overclocking enabled, CPPC.highest_perf is hardcoded to 0xff.
++ * In this case we can't use CPPC.highest_perf to enable ITMT.
++ * In this case we can look at MSR_HWP_CAPABILITIES bits [8:0] to decide.
++ */
++ if (cppc_perf.highest_perf == CPPC_MAX_PERF)
++ cppc_perf.highest_perf = HWP_HIGHEST_PERF(READ_ONCE(all_cpu_data[cpu]->hwp_cap_cached));
++
+ /*
+ * The priorities can be set regardless of whether or not
+ * sched_set_itmt_support(true) has been called and it is valid to
+@@ -537,7 +547,8 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
* scaling factor is too high, so recompute it to make the HWP_CAP
* highest performance correspond to the maximum turbo frequency.
*/
@@ -30416,7 +52334,7 @@ index 8c176b7dae415..e15c3bc17a55c 100644
cpu->pstate.turbo_freq = turbo_freq;
scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate);
cpu->pstate.scaling = scaling;
-@@ -998,9 +999,22 @@ static void intel_pstate_hwp_offline(struct cpudata *cpu)
+@@ -998,9 +1009,22 @@ static void intel_pstate_hwp_offline(struct cpudata *cpu)
*/
value &= ~GENMASK_ULL(31, 24);
value |= HWP_ENERGY_PERF_PREFERENCE(cpu->epp_cached);
@@ -30440,7 +52358,7 @@ index 8c176b7dae415..e15c3bc17a55c 100644
value &= ~GENMASK_ULL(31, 0);
min_perf = HWP_LOWEST_PERF(READ_ONCE(cpu->hwp_cap_cached));
-@@ -2241,6 +2255,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
+@@ -2241,6 +2265,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
X86_MATCH(BROADWELL_D, core_funcs),
X86_MATCH(BROADWELL_X, core_funcs),
X86_MATCH(SKYLAKE_X, core_funcs),
@@ -30448,7 +52366,7 @@ index 8c176b7dae415..e15c3bc17a55c 100644
{}
};
-@@ -2902,6 +2917,27 @@ static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+@@ -2902,6 +2927,27 @@ static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy)
return intel_pstate_cpu_exit(policy);
}
@@ -30476,7 +52394,7 @@ index 8c176b7dae415..e15c3bc17a55c 100644
static struct cpufreq_driver intel_cpufreq = {
.flags = CPUFREQ_CONST_LOOPS,
.verify = intel_cpufreq_verify_policy,
-@@ -2911,7 +2947,7 @@ static struct cpufreq_driver intel_cpufreq = {
+@@ -2911,7 +2957,7 @@ static struct cpufreq_driver intel_cpufreq = {
.exit = intel_cpufreq_cpu_exit,
.offline = intel_cpufreq_cpu_offline,
.online = intel_pstate_cpu_online,
@@ -30486,10 +52404,66 @@ index 8c176b7dae415..e15c3bc17a55c 100644
.update_limits = intel_pstate_update_limits,
.name = "intel_cpufreq",
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
-index a2be0df7e1747..35d93361fda1a 100644
+index a2be0df7e1747..bb2f59fd0de43 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
-@@ -304,7 +304,8 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
+@@ -24,12 +24,16 @@
+ #define CLK_HW_DIV 2
+ #define LUT_TURBO_IND 1
+
++#define GT_IRQ_STATUS BIT(2)
++
+ #define HZ_PER_KHZ 1000
+
+ struct qcom_cpufreq_soc_data {
+ u32 reg_enable;
++ u32 reg_domain_state;
+ u32 reg_freq_lut;
+ u32 reg_volt_lut;
++ u32 reg_intr_clr;
+ u32 reg_current_vote;
+ u32 reg_perf_state;
+ u8 lut_row_size;
+@@ -266,28 +270,31 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
+ }
+ }
+
+-static unsigned int qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
++static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
+ {
+- unsigned int val = readl_relaxed(data->base + data->soc_data->reg_current_vote);
++ unsigned int lval;
++
++ if (data->soc_data->reg_current_vote)
++ lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff;
++ else
++ lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff;
+
+- return (val & 0x3FF) * 19200;
++ return lval * xo_rate;
+ }
+
+ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
+ {
+ unsigned long max_capacity, capacity, freq_hz, throttled_freq;
+ struct cpufreq_policy *policy = data->policy;
+- int cpu = cpumask_first(policy->cpus);
++ int cpu = cpumask_first(policy->related_cpus);
+ struct device *dev = get_cpu_device(cpu);
+ struct dev_pm_opp *opp;
+- unsigned int freq;
+
+ /*
+ * Get the h/w throttled frequency, normalize it using the
+ * registered opp table and use it to calculate thermal pressure.
+ */
+- freq = qcom_lmh_get_throttle_freq(data);
+- freq_hz = freq * HZ_PER_KHZ;
++ freq_hz = qcom_lmh_get_throttle_freq(data);
+
+ opp = dev_pm_opp_find_freq_floor(dev, &freq_hz);
+ if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE)
+@@ -304,7 +311,8 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
if (capacity > max_capacity)
capacity = max_capacity;
@@ -30499,7 +52473,7 @@ index a2be0df7e1747..35d93361fda1a 100644
/*
* In the unlikely case policy is unregistered do not enable
-@@ -342,9 +343,9 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
+@@ -342,9 +350,13 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
/* Disable interrupt and enable polling */
disable_irq_nosync(c_data->throttle_irq);
@@ -30507,10 +52481,54 @@ index a2be0df7e1747..35d93361fda1a 100644
+ schedule_delayed_work(&c_data->throttle_work, 0);
- return 0;
++ if (c_data->soc_data->reg_intr_clr)
++ writel_relaxed(GT_IRQ_STATUS,
++ c_data->base + c_data->soc_data->reg_intr_clr);
++
+ return IRQ_HANDLED;
}
static const struct qcom_cpufreq_soc_data qcom_soc_data = {
+@@ -358,8 +370,10 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
+
+ static const struct qcom_cpufreq_soc_data epss_soc_data = {
+ .reg_enable = 0x0,
++ .reg_domain_state = 0x20,
+ .reg_freq_lut = 0x100,
+ .reg_volt_lut = 0x200,
++ .reg_intr_clr = 0x308,
+ .reg_perf_state = 0x320,
+ .lut_row_size = 4,
+ };
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index d1744b5d96190..6dfa86971a757 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -130,7 +130,7 @@ static void get_krait_bin_format_b(struct device *cpu_dev,
+ }
+
+ /* Check PVS_BLOW_STATUS */
+- pte_efuse = *(((u32 *)buf) + 4);
++ pte_efuse = *(((u32 *)buf) + 1);
+ pte_efuse &= BIT(21);
+ if (pte_efuse) {
+ dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs);
+diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+index 2deed8d8773fa..75e1bf3a08f7c 100644
+--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
++++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+@@ -98,8 +98,10 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ ret = sun50i_cpufreq_get_efuse(&speed);
+- if (ret)
++ if (ret) {
++ kfree(opp_tables);
+ return ret;
++ }
+
+ snprintf(name, MAX_NAME_LEN, "speed%d", speed);
+
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 53ec9585ccd44..469e18547d06c 100644
--- a/drivers/cpuidle/sysfs.c
@@ -30551,6 +52569,119 @@ index 53ec9585ccd44..469e18547d06c 100644
kobject_uevent(&kdev->kobj, KOBJ_ADD);
return 0;
+diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+index 54ae8d16e4931..35e3cadccac2b 100644
+--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
++++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+@@ -11,6 +11,7 @@
+ * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ */
+
++#include <linux/bottom_half.h>
+ #include <linux/crypto.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/io.h>
+@@ -283,7 +284,9 @@ static int sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq)
+
+ flow = rctx->flow;
+ err = sun8i_ce_run_task(ce, flow, crypto_tfm_alg_name(breq->base.tfm));
++ local_bh_disable();
+ crypto_finalize_skcipher_request(engine, breq, err);
++ local_bh_enable();
+ return 0;
+ }
+
+diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
+index 88194718a806c..859b7522faaac 100644
+--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
++++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
+@@ -9,6 +9,7 @@
+ *
+ * You could find the datasheet in Documentation/arm/sunxi.rst
+ */
++#include <linux/bottom_half.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/scatterlist.h>
+@@ -414,6 +415,8 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
+ theend:
+ kfree(buf);
+ kfree(result);
++ local_bh_disable();
+ crypto_finalize_hash_request(engine, breq, err);
++ local_bh_enable();
+ return 0;
+ }
+diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
+index 9ef1c85c4aaa5..554e400d41cad 100644
+--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
+@@ -11,6 +11,7 @@
+ * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ */
+
++#include <linux/bottom_half.h>
+ #include <linux/crypto.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/io.h>
+@@ -274,7 +275,9 @@ static int sun8i_ss_handle_cipher_request(struct crypto_engine *engine, void *ar
+ struct skcipher_request *breq = container_of(areq, struct skcipher_request, base);
+
+ err = sun8i_ss_cipher(breq);
++ local_bh_disable();
+ crypto_finalize_skcipher_request(engine, breq, err);
++ local_bh_enable();
+
+ return 0;
+ }
+diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
+index 80e89066dbd1a..319fe3279a716 100644
+--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
+@@ -30,6 +30,8 @@
+ static const struct ss_variant ss_a80_variant = {
+ .alg_cipher = { SS_ALG_AES, SS_ALG_DES, SS_ALG_3DES,
+ },
++ .alg_hash = { SS_ID_NOTSUPP, SS_ID_NOTSUPP, SS_ID_NOTSUPP, SS_ID_NOTSUPP,
++ },
+ .op_mode = { SS_OP_ECB, SS_OP_CBC,
+ },
+ .ss_clks = {
+diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
+index 3c073eb3db038..1a71ed49d2333 100644
+--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
+@@ -9,6 +9,7 @@
+ *
+ * You could find the datasheet in Documentation/arm/sunxi.rst
+ */
++#include <linux/bottom_half.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/scatterlist.h>
+@@ -442,6 +443,8 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq)
+ theend:
+ kfree(pad);
+ kfree(result);
++ local_bh_disable();
+ crypto_finalize_hash_request(engine, breq, err);
++ local_bh_enable();
+ return 0;
+ }
+diff --git a/drivers/crypto/amlogic/amlogic-gxl-cipher.c b/drivers/crypto/amlogic/amlogic-gxl-cipher.c
+index c6865cbd334b2..e79514fce731f 100644
+--- a/drivers/crypto/amlogic/amlogic-gxl-cipher.c
++++ b/drivers/crypto/amlogic/amlogic-gxl-cipher.c
+@@ -265,7 +265,9 @@ static int meson_handle_cipher_request(struct crypto_engine *engine,
+ struct skcipher_request *breq = container_of(areq, struct skcipher_request, base);
+
+ err = meson_cipher(breq);
++ local_bh_disable();
+ crypto_finalize_skcipher_request(engine, breq, err);
++ local_bh_enable();
+
+ return 0;
+ }
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9391ccc03382d..fe05584031914 100644
--- a/drivers/crypto/atmel-aes.c
@@ -30714,8 +52845,49 @@ index af61f3a2c0d46..3738625c02509 100644
/*
* caam_perfmon - Performance Monitor/Secure Memory Status/
* CAAM Global Status/Component Version IDs
+diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c
+index d718db224be42..7d4b4ad1db1f3 100644
+--- a/drivers/crypto/ccp/ccp-dmaengine.c
++++ b/drivers/crypto/ccp/ccp-dmaengine.c
+@@ -632,6 +632,20 @@ static int ccp_terminate_all(struct dma_chan *dma_chan)
+ return 0;
+ }
+
++static void ccp_dma_release(struct ccp_device *ccp)
++{
++ struct ccp_dma_chan *chan;
++ struct dma_chan *dma_chan;
++ unsigned int i;
++
++ for (i = 0; i < ccp->cmd_q_count; i++) {
++ chan = ccp->ccp_dma_chan + i;
++ dma_chan = &chan->dma_chan;
++ tasklet_kill(&chan->cleanup_tasklet);
++ list_del_rcu(&dma_chan->device_node);
++ }
++}
++
+ int ccp_dmaengine_register(struct ccp_device *ccp)
+ {
+ struct ccp_dma_chan *chan;
+@@ -736,6 +750,7 @@ int ccp_dmaengine_register(struct ccp_device *ccp)
+ return 0;
+
+ err_reg:
++ ccp_dma_release(ccp);
+ kmem_cache_destroy(ccp->dma_desc_cache);
+
+ err_cache:
+@@ -752,6 +767,7 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp)
+ return;
+
+ dma_async_device_unregister(dma_dev);
++ ccp_dma_release(ccp);
+
+ kmem_cache_destroy(ccp->dma_desc_cache);
+ kmem_cache_destroy(ccp->dma_cmd_cache);
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
-index 2ecb0e1f65d8d..e2806ca3300a8 100644
+index 2ecb0e1f65d8d..5040726fc119c 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -241,7 +241,7 @@ static int __sev_platform_init_locked(int *error)
@@ -30723,7 +52895,7 @@ index 2ecb0e1f65d8d..e2806ca3300a8 100644
struct sev_data_init data;
struct sev_device *sev;
- int rc = 0;
-+ int psp_ret, rc = 0;
++ int psp_ret = -1, rc = 0;
if (!psp || !psp->sev_data)
return -ENODEV;
@@ -30769,6 +52941,38 @@ index 2ecb0e1f65d8d..e2806ca3300a8 100644
if (rc) {
dev_err(sev->dev, "SEV: failed to INIT error %#x\n", error);
return;
+diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c
+index a5e041d9d2cf1..11e0278c8631d 100644
+--- a/drivers/crypto/ccree/cc_buffer_mgr.c
++++ b/drivers/crypto/ccree/cc_buffer_mgr.c
+@@ -258,6 +258,13 @@ static int cc_map_sg(struct device *dev, struct scatterlist *sg,
+ {
+ int ret = 0;
+
++ if (!nbytes) {
++ *mapped_nents = 0;
++ *lbytes = 0;
++ *nents = 0;
++ return 0;
++ }
++
+ *nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes);
+ if (*nents > max_sg_nents) {
+ *nents = 0;
+diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c
+index 78833491f534d..309da6334a0a0 100644
+--- a/drivers/crypto/ccree/cc_cipher.c
++++ b/drivers/crypto/ccree/cc_cipher.c
+@@ -257,8 +257,8 @@ static void cc_cipher_exit(struct crypto_tfm *tfm)
+ &ctx_p->user.key_dma_addr);
+
+ /* Free key buffer in context */
+- kfree_sensitive(ctx_p->user.key);
+ dev_dbg(dev, "Free key buffer in context. key=@%p\n", ctx_p->user.key);
++ kfree_sensitive(ctx_p->user.key);
+ }
+
+ struct tdes_keys {
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c
index e599ac6dc162a..790fa9058a36d 100644
--- a/drivers/crypto/ccree/cc_driver.c
@@ -30783,6 +52987,20 @@ index e599ac6dc162a..790fa9058a36d 100644
/* compute CC_AXIM_CACHE_PARAMS */
cache_params = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS));
+diff --git a/drivers/crypto/gemini/sl3516-ce-cipher.c b/drivers/crypto/gemini/sl3516-ce-cipher.c
+index c1c2b1d866639..f2be0a7d7f7ac 100644
+--- a/drivers/crypto/gemini/sl3516-ce-cipher.c
++++ b/drivers/crypto/gemini/sl3516-ce-cipher.c
+@@ -264,7 +264,9 @@ static int sl3516_ce_handle_cipher_request(struct crypto_engine *engine, void *a
+ struct skcipher_request *breq = container_of(areq, struct skcipher_request, base);
+
+ err = sl3516_ce_cipher(breq);
++ local_bh_disable();
+ crypto_finalize_skcipher_request(engine, breq, err);
++ local_bh_enable();
+
+ return 0;
+ }
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index a032c192ef1d6..7ba7641723a0b 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -30797,9 +53015,18 @@ index a032c192ef1d6..7ba7641723a0b 100644
hpre_curve25519_src_modulo_p(ptr);
}
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
-index 369562d34d66a..ff1122153fbec 100644
+index 369562d34d66a..b616d2d8e7736 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
+@@ -4107,7 +4107,7 @@ static void qm_vf_get_qos(struct hisi_qm *qm, u32 fun_num)
+ static int qm_vf_read_qos(struct hisi_qm *qm)
+ {
+ int cnt = 0;
+- int ret;
++ int ret = -EINVAL;
+
+ /* reset mailbox qos val */
+ qm->mb_qos = 0;
@@ -5986,7 +5986,7 @@ int hisi_qm_resume(struct device *dev)
if (ret)
pci_err(pdev, "failed to start qm(%d)\n", ret);
@@ -30809,6 +53036,68 @@ index 369562d34d66a..ff1122153fbec 100644
}
EXPORT_SYMBOL_GPL(hisi_qm_resume);
+diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
+index 6a45bd23b3635..090920ed50c8f 100644
+--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
+@@ -2284,9 +2284,10 @@ static int sec_aead_soft_crypto(struct sec_ctx *ctx,
+ struct aead_request *aead_req,
+ bool encrypt)
+ {
+- struct aead_request *subreq = aead_request_ctx(aead_req);
+ struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
+ struct device *dev = ctx->dev;
++ struct aead_request *subreq;
++ int ret;
+
+ /* Kunpeng920 aead mode not support input 0 size */
+ if (!a_ctx->fallback_aead_tfm) {
+@@ -2294,6 +2295,10 @@ static int sec_aead_soft_crypto(struct sec_ctx *ctx,
+ return -EINVAL;
+ }
+
++ subreq = aead_request_alloc(a_ctx->fallback_aead_tfm, GFP_KERNEL);
++ if (!subreq)
++ return -ENOMEM;
++
+ aead_request_set_tfm(subreq, a_ctx->fallback_aead_tfm);
+ aead_request_set_callback(subreq, aead_req->base.flags,
+ aead_req->base.complete, aead_req->base.data);
+@@ -2301,8 +2306,13 @@ static int sec_aead_soft_crypto(struct sec_ctx *ctx,
+ aead_req->cryptlen, aead_req->iv);
+ aead_request_set_ad(subreq, aead_req->assoclen);
+
+- return encrypt ? crypto_aead_encrypt(subreq) :
+- crypto_aead_decrypt(subreq);
++ if (encrypt)
++ ret = crypto_aead_encrypt(subreq);
++ else
++ ret = crypto_aead_decrypt(subreq);
++ aead_request_free(subreq);
++
++ return ret;
+ }
+
+ static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
+diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
+index 90551bf38b523..03d239cfdf8c6 100644
+--- a/drivers/crypto/hisilicon/sec2/sec_main.c
++++ b/drivers/crypto/hisilicon/sec2/sec_main.c
+@@ -443,9 +443,11 @@ static int sec_engine_init(struct hisi_qm *qm)
+
+ writel(SEC_SAA_ENABLE, qm->io_base + SEC_SAA_EN_REG);
+
+- /* Enable sm4 extra mode, as ctr/ecb */
+- writel_relaxed(SEC_BD_ERR_CHK_EN0,
+- qm->io_base + SEC_BD_ERR_CHK_EN_REG0);
++ /* HW V2 enable sm4 extra mode, as ctr/ecb */
++ if (qm->ver < QM_HW_V3)
++ writel_relaxed(SEC_BD_ERR_CHK_EN0,
++ qm->io_base + SEC_BD_ERR_CHK_EN_REG0);
++
+ /* Enable sm4 xts mode multiple iv */
+ writel_relaxed(SEC_BD_ERR_CHK_EN1,
+ qm->io_base + SEC_BD_ERR_CHK_EN_REG1);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
index 146a55ac4b9b0..be1ad55a208f6 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
@@ -30845,7 +53134,7 @@ index dff34b3ec09e1..7c1b92aaab398 100644
eng_grp->g->engs_num);
return bmap;
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
-index a72723455df72..877a948469bd1 100644
+index a72723455df72..570074e23b60e 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
@@ -1274,6 +1274,7 @@ static int aead_do_fallback(struct aead_request *req, bool is_enc)
@@ -30856,6 +53145,42 @@ index a72723455df72..877a948469bd1 100644
ret = is_enc ? crypto_aead_encrypt(&rctx->fbk_req) :
crypto_aead_decrypt(&rctx->fbk_req);
} else {
+@@ -1633,16 +1634,13 @@ static inline int cpt_register_algs(void)
+ {
+ int i, err = 0;
+
+- if (!IS_ENABLED(CONFIG_DM_CRYPT)) {
+- for (i = 0; i < ARRAY_SIZE(otx2_cpt_skciphers); i++)
+- otx2_cpt_skciphers[i].base.cra_flags &=
+- ~CRYPTO_ALG_DEAD;
++ for (i = 0; i < ARRAY_SIZE(otx2_cpt_skciphers); i++)
++ otx2_cpt_skciphers[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
+
+- err = crypto_register_skciphers(otx2_cpt_skciphers,
+- ARRAY_SIZE(otx2_cpt_skciphers));
+- if (err)
+- return err;
+- }
++ err = crypto_register_skciphers(otx2_cpt_skciphers,
++ ARRAY_SIZE(otx2_cpt_skciphers));
++ if (err)
++ return err;
+
+ for (i = 0; i < ARRAY_SIZE(otx2_cpt_aeads); i++)
+ otx2_cpt_aeads[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
+diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
+index d19e5ffb5104b..d6f9e2fe863d7 100644
+--- a/drivers/crypto/mxs-dcp.c
++++ b/drivers/crypto/mxs-dcp.c
+@@ -331,7 +331,7 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
+ memset(key + AES_KEYSIZE_128, 0, AES_KEYSIZE_128);
+ }
+
+- for_each_sg(req->src, src, sg_nents(src), i) {
++ for_each_sg(req->src, src, sg_nents(req->src), i) {
+ src_buf = sg_virt(src);
+ len = sg_dma_len(src);
+ tlen += len;
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 9b968ac4ee7b6..a196bb8b17010 100644
--- a/drivers/crypto/omap-aes.c
@@ -30945,6 +53270,24 @@ index 4fe2a776293c2..924bac6feb372 100644
/* Firmware Binaries */
#define ADF_4XXX_FW "qat_4xxx.bin"
#define ADF_4XXX_MMP "qat_4xxx_mmp.bin"
+diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c
+index 359fb7989dfbf..8fd44703115f2 100644
+--- a/drivers/crypto/qat/qat_4xxx/adf_drv.c
++++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c
+@@ -52,6 +52,13 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
+ if (ret)
+ goto err;
+
++ /* Temporarily set the number of crypto instances to zero to avoid
++ * registering the crypto algorithms.
++ * This will be removed when the algorithms will support the
++ * CRYPTO_TFM_REQ_MAY_BACKLOG flag
++ */
++ instances = 0;
++
+ for (i = 0; i < instances; i++) {
+ val = i;
+ bank = i * 2;
diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h
index 38c0af6d4e43e..580566cfcb04c 100644
--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h
@@ -31095,6 +53438,24 @@ index 7828a6573f3e2..2e300c255ab94 100644
/* Re-enable PF2VF interrupts */
adf_enable_pf2vf_interrupts(accel_dev);
return;
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c
+index ece6776fbd53d..3efbb38836010 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.c
++++ b/drivers/crypto/qat/qat_common/qat_crypto.c
+@@ -136,6 +136,13 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev)
+ if (ret)
+ goto err;
+
++ /* Temporarily set the number of crypto instances to zero to avoid
++ * registering the crypto algorithms.
++ * This will be removed when the algorithms will support the
++ * CRYPTO_TFM_REQ_MAY_BACKLOG flag
++ */
++ instances = 0;
++
+ for (i = 0; i < instances; i++) {
+ val = i;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i);
diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c
index 290e2446a2f35..97a530171f07a 100644
--- a/drivers/crypto/qce/aead.c
@@ -31137,6 +53498,72 @@ index 8ff10928f581d..3d27cd5210ef5 100644
return ret;
}
+diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
+index 99ba8d51d1020..031b5f701a0a3 100644
+--- a/drivers/crypto/qcom-rng.c
++++ b/drivers/crypto/qcom-rng.c
+@@ -8,6 +8,7 @@
+ #include <linux/clk.h>
+ #include <linux/crypto.h>
+ #include <linux/io.h>
++#include <linux/iopoll.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+@@ -43,16 +44,19 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
+ {
+ unsigned int currsize = 0;
+ u32 val;
++ int ret;
+
+ /* read random data from hardware */
+ do {
+- val = readl_relaxed(rng->base + PRNG_STATUS);
+- if (!(val & PRNG_STATUS_DATA_AVAIL))
+- break;
++ ret = readl_poll_timeout(rng->base + PRNG_STATUS, val,
++ val & PRNG_STATUS_DATA_AVAIL,
++ 200, 10000);
++ if (ret)
++ return ret;
+
+ val = readl_relaxed(rng->base + PRNG_DATA_OUT);
+ if (!val)
+- break;
++ return -EINVAL;
+
+ if ((max - currsize) >= WORD_SZ) {
+ memcpy(data, &val, WORD_SZ);
+@@ -65,7 +69,7 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
+ }
+ } while (currsize < max);
+
+- return currsize;
++ return 0;
+ }
+
+ static int qcom_rng_generate(struct crypto_rng *tfm,
+@@ -87,7 +91,7 @@ static int qcom_rng_generate(struct crypto_rng *tfm,
+ mutex_unlock(&rng->lock);
+ clk_disable_unprepare(rng->clk);
+
+- return 0;
++ return ret;
+ }
+
+ static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
+diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c
+index 1cece1a7d3f00..5bbf0d2722e11 100644
+--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c
++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c
+@@ -506,7 +506,6 @@ struct rk_crypto_tmp rk_ecb_des3_ede_alg = {
+ .exit = rk_ablk_exit_tfm,
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+- .ivsize = DES_BLOCK_SIZE,
+ .setkey = rk_tdes_setkey,
+ .encrypt = rk_des3_ede_ecb_encrypt,
+ .decrypt = rk_des3_ede_ecb_decrypt,
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 55aa3a71169b0..7717e9e5977bb 100644
--- a/drivers/crypto/s5p-sss.c
@@ -31151,7 +53578,7 @@ index 55aa3a71169b0..7717e9e5977bb 100644
/*
* Note: HASH and PRNG uses the same registers in secss, avoid
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
-index 75867c0b00172..be1bf39a317de 100644
+index 75867c0b00172..90a920e7f6642 100644
--- a/drivers/crypto/stm32/stm32-crc32.c
+++ b/drivers/crypto/stm32/stm32-crc32.c
@@ -279,7 +279,7 @@ static struct shash_alg algs[] = {
@@ -31172,6 +53599,18 @@ index 75867c0b00172..be1bf39a317de 100644
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
+@@ -384,8 +384,10 @@ static int stm32_crc_remove(struct platform_device *pdev)
+ struct stm32_crc *crc = platform_get_drvdata(pdev);
+ int ret = pm_runtime_get_sync(crc->dev);
+
+- if (ret < 0)
++ if (ret < 0) {
++ pm_runtime_put_noidle(crc->dev);
+ return ret;
++ }
+
+ spin_lock(&crc_list.lock);
+ list_del(&crc->list);
diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c
index 7389a0536ff02..81eb136b6c11d 100644
--- a/drivers/crypto/stm32/stm32-cryp.c
@@ -32648,6 +55087,49 @@ index 389de9e3302d5..d33006d43f761 100644
stm32_hash_write(hdev, HASH_IMR, *preg++);
stm32_hash_write(hdev, HASH_STR, *preg++);
+diff --git a/drivers/crypto/vmx/Kconfig b/drivers/crypto/vmx/Kconfig
+index c85fab7ef0bdd..b2c28b87f14b3 100644
+--- a/drivers/crypto/vmx/Kconfig
++++ b/drivers/crypto/vmx/Kconfig
+@@ -2,7 +2,11 @@
+ config CRYPTO_DEV_VMX_ENCRYPT
+ tristate "Encryption acceleration support on P8 CPU"
+ depends on CRYPTO_DEV_VMX
++ select CRYPTO_AES
++ select CRYPTO_CBC
++ select CRYPTO_CTR
+ select CRYPTO_GHASH
++ select CRYPTO_XTS
+ default m
+ help
+ Support for VMX cryptographic acceleration instructions on Power8 CPU.
+diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
+index 41de4a136ecd7..2e7027a3fef3b 100644
+--- a/drivers/cxl/core/regs.c
++++ b/drivers/cxl/core/regs.c
+@@ -35,7 +35,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
+ struct cxl_component_reg_map *map)
+ {
+ int cap, cap_count;
+- u64 cap_array;
++ u32 cap_array;
+
+ *map = (struct cxl_component_reg_map) { 0 };
+
+@@ -45,11 +45,11 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
+ */
+ base += CXL_CM_OFFSET;
+
+- cap_array = readq(base + CXL_CM_CAP_HDR_OFFSET);
++ cap_array = readl(base + CXL_CM_CAP_HDR_OFFSET);
+
+ if (FIELD_GET(CXL_CM_CAP_HDR_ID_MASK, cap_array) != CM_CAP_HDR_CAP_ID) {
+ dev_err(dev,
+- "Couldn't locate the CXL.cache and CXL.mem capability array header./n");
++ "Couldn't locate the CXL.cache and CXL.mem capability array header.\n");
+ return;
+ }
+
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 8e45aa07d662f..5444b5a7fd3c4 100644
--- a/drivers/cxl/pci.c
@@ -32702,8 +55184,20 @@ index 9652c3ee41e7f..2bb2f9a0499f7 100644
return 0;
}
+diff --git a/drivers/dax/super.c b/drivers/dax/super.c
+index fc89e91beea7c..7610e4a9ac4e2 100644
+--- a/drivers/dax/super.c
++++ b/drivers/dax/super.c
+@@ -678,6 +678,7 @@ static int dax_fs_init(void)
+ static void dax_fs_exit(void)
+ {
+ kern_unmount(dax_mnt);
++ rcu_barrier();
+ kmem_cache_destroy(dax_cache);
+ }
+
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
-index 63d32261b63ff..61e20ae7b08b7 100644
+index 63d32261b63ff..f9217e300eea9 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -74,7 +74,7 @@ static void dma_buf_release(struct dentry *dentry)
@@ -32909,7 +55403,29 @@ index 63d32261b63ff..61e20ae7b08b7 100644
return events;
}
-@@ -565,8 +554,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
+@@ -447,6 +436,7 @@ static inline int is_dma_buf_file(struct file *file)
+
+ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
+ {
++ static atomic64_t dmabuf_inode = ATOMIC64_INIT(0);
+ struct file *file;
+ struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb);
+
+@@ -456,6 +446,13 @@ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
+ inode->i_size = dmabuf->size;
+ inode_set_bytes(inode, dmabuf->size);
+
++ /*
++ * The ->i_ino acquired from get_next_ino() is not unique thus
++ * not suitable for using it as dentry name by dmabuf stats.
++ * Override ->i_ino with the unique and dmabuffs specific
++ * value.
++ */
++ inode->i_ino = atomic64_add_return(1, &dmabuf_inode);
+ file = alloc_file_pseudo(inode, dma_buf_mnt, "dmabuf",
+ flags, &dma_buf_fops);
+ if (IS_ERR(file))
+@@ -565,8 +562,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
dmabuf->owner = exp_info->owner;
spin_lock_init(&dmabuf->name_lock);
init_waitqueue_head(&dmabuf->poll);
@@ -32920,6 +55436,28 @@ index 63d32261b63ff..61e20ae7b08b7 100644
if (!resv) {
resv = (struct dma_resv *)&dmabuf[1];
+@@ -583,10 +580,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
+ file->f_mode |= FMODE_LSEEK;
+ dmabuf->file = file;
+
+- ret = dma_buf_stats_setup(dmabuf);
+- if (ret)
+- goto err_sysfs;
+-
+ mutex_init(&dmabuf->lock);
+ INIT_LIST_HEAD(&dmabuf->attachments);
+
+@@ -594,6 +587,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
+ list_add(&dmabuf->list_node, &db_list.head);
+ mutex_unlock(&db_list.lock);
+
++ ret = dma_buf_stats_setup(dmabuf);
++ if (ret)
++ goto err_sysfs;
++
+ return dmabuf;
+
+ err_sysfs:
diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c
index d3fbd950be944..3e07f961e2f3d 100644
--- a/drivers/dma-buf/dma-fence-array.c
@@ -33000,8 +55538,23 @@ index 23a7e74ef9666..8660508f3684f 100644
struct page *page = sg_page(sg);
__free_pages(page, compound_order(page));
+diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
+index c57a609db75be..e7330684d3b82 100644
+--- a/drivers/dma-buf/udmabuf.c
++++ b/drivers/dma-buf/udmabuf.c
+@@ -190,6 +190,10 @@ static long udmabuf_create(struct miscdevice *device,
+ if (ubuf->pagecount > pglimit)
+ goto err;
+ }
++
++ if (!ubuf->pagecount)
++ goto err;
++
+ ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
+ GFP_KERNEL);
+ if (!ubuf->pages) {
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
-index ab78e0f6afd70..8177aed160060 100644
+index ab78e0f6afd70..177a537971a1b 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -99,6 +99,7 @@
@@ -33083,7 +55636,34 @@ index ab78e0f6afd70..8177aed160060 100644
return cookie;
}
-@@ -1623,14 +1621,17 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
+@@ -1452,7 +1450,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ {
+ struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
+ struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
+- struct at_xdmac_desc *desc, *_desc;
++ struct at_xdmac_desc *desc, *_desc, *iter;
+ struct list_head *descs_list;
+ enum dma_status ret;
+ int residue, retry;
+@@ -1567,11 +1565,13 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ * microblock.
+ */
+ descs_list = &desc->descs_list;
+- list_for_each_entry_safe(desc, _desc, descs_list, desc_node) {
+- dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
+- residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth;
+- if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
++ list_for_each_entry_safe(iter, _desc, descs_list, desc_node) {
++ dwidth = at_xdmac_get_dwidth(iter->lld.mbr_cfg);
++ residue -= (iter->lld.mbr_ubc & 0xffffff) << dwidth;
++ if ((iter->lld.mbr_nda & 0xfffffffc) == cur_nda) {
++ desc = iter;
+ break;
++ }
+ }
+ residue += cur_ubc << dwidth;
+
+@@ -1623,14 +1623,17 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
struct at_xdmac_desc *desc;
struct dma_async_tx_descriptor *txd;
@@ -33108,7 +55688,7 @@ index ab78e0f6afd70..8177aed160060 100644
}
static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)
-@@ -1784,11 +1785,9 @@ static void at_xdmac_issue_pending(struct dma_chan *chan)
+@@ -1784,11 +1787,9 @@ static void at_xdmac_issue_pending(struct dma_chan *chan)
dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__);
@@ -33123,7 +55703,7 @@ index ab78e0f6afd70..8177aed160060 100644
return;
}
-@@ -1926,6 +1925,30 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan)
+@@ -1926,6 +1927,30 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan)
return;
}
@@ -33154,7 +55734,7 @@ index ab78e0f6afd70..8177aed160060 100644
#ifdef CONFIG_PM
static int atmel_xdmac_prepare(struct device *dev)
{
-@@ -1975,6 +1998,7 @@ static int atmel_xdmac_resume(struct device *dev)
+@@ -1975,6 +2000,7 @@ static int atmel_xdmac_resume(struct device *dev)
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct at_xdmac_chan *atchan;
struct dma_chan *chan, *_chan;
@@ -33162,7 +55742,7 @@ index ab78e0f6afd70..8177aed160060 100644
int i;
int ret;
-@@ -1982,6 +2006,8 @@ static int atmel_xdmac_resume(struct device *dev)
+@@ -1982,6 +2008,8 @@ static int atmel_xdmac_resume(struct device *dev)
if (ret)
return ret;
@@ -33171,7 +55751,7 @@ index ab78e0f6afd70..8177aed160060 100644
/* Clear pending interrupts. */
for (i = 0; i < atxdmac->dma.chancnt; i++) {
atchan = &atxdmac->chan[i];
-@@ -2007,30 +2033,6 @@ static int atmel_xdmac_resume(struct device *dev)
+@@ -2007,30 +2035,6 @@ static int atmel_xdmac_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
@@ -33326,8 +55906,39 @@ index 1bfbd64b13717..53f16d3f00294 100644
}
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
+diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
+index 329fc2e57b703..b5b8f8181e776 100644
+--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
++++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
+@@ -415,8 +415,11 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
+ (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
+ /* Linked list */
+ #ifdef CONFIG_64BIT
+- SET_CH_64(dw, chan->dir, chan->id, llp.reg,
+- chunk->ll_region.paddr);
++ /* llp is not aligned on 64bit -> keep 32bit accesses */
++ SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
++ lower_32_bits(chunk->ll_region.paddr));
++ SET_CH_32(dw, chan->dir, chan->id, llp.msb,
++ upper_32_bits(chunk->ll_region.paddr));
+ #else /* CONFIG_64BIT */
+ SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
+ lower_32_bits(chunk->ll_region.paddr));
+diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c
+index c855a0e4f9ff4..f680e9b40bf77 100644
+--- a/drivers/dma/hisi_dma.c
++++ b/drivers/dma/hisi_dma.c
+@@ -30,7 +30,7 @@
+ #define HISI_DMA_MODE 0x217c
+ #define HISI_DMA_OFFSET 0x100
+
+-#define HISI_DMA_MSI_NUM 30
++#define HISI_DMA_MSI_NUM 32
+ #define HISI_DMA_CHAN_NUM 30
+ #define HISI_DMA_Q_DEPTH_VAL 1024
+
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
-index 83a5ff2ecf2a0..b468ca36d3a01 100644
+index 83a5ff2ecf2a0..e622245c93804 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -394,8 +394,6 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
@@ -33339,7 +55950,7 @@ index 83a5ff2ecf2a0..b468ca36d3a01 100644
wq->threshold = 0;
wq->priority = 0;
wq->ats_dis = 0;
-@@ -404,6 +402,15 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
+@@ -404,6 +402,14 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
memset(wq->name, 0, WQ_NAME_SIZE);
}
@@ -33347,7 +55958,6 @@ index 83a5ff2ecf2a0..b468ca36d3a01 100644
+{
+ lockdep_assert_held(&wq->wq_lock);
+
-+ idxd_wq_disable_cleanup(wq);
+ wq->size = 0;
+ wq->group = NULL;
+}
@@ -33355,7 +55965,7 @@ index 83a5ff2ecf2a0..b468ca36d3a01 100644
static void idxd_wq_ref_release(struct percpu_ref *ref)
{
struct idxd_wq *wq = container_of(ref, struct idxd_wq, wq_active);
-@@ -427,7 +434,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq)
+@@ -427,7 +433,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq)
{
percpu_ref_kill(&wq->wq_active);
wait_for_completion(&wq->wq_dead);
@@ -33363,7 +55973,7 @@ index 83a5ff2ecf2a0..b468ca36d3a01 100644
}
/* Device control bits */
-@@ -584,6 +590,8 @@ void idxd_device_reset(struct idxd_device *idxd)
+@@ -584,6 +589,8 @@ void idxd_device_reset(struct idxd_device *idxd)
spin_lock(&idxd->dev_lock);
idxd_device_clear_state(idxd);
idxd->state = IDXD_DEV_DISABLED;
@@ -33372,14 +55982,86 @@ index 83a5ff2ecf2a0..b468ca36d3a01 100644
spin_unlock(&idxd->dev_lock);
}
-@@ -710,6 +718,7 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd)
+@@ -692,11 +699,16 @@ static void idxd_groups_clear_state(struct idxd_device *idxd)
+ memset(&group->grpcfg, 0, sizeof(group->grpcfg));
+ group->num_engines = 0;
+ group->num_wqs = 0;
+- group->use_token_limit = false;
+- group->tokens_allowed = 0;
+- group->tokens_reserved = 0;
+- group->tc_a = -1;
+- group->tc_b = -1;
++ group->use_rdbuf_limit = false;
++ group->rdbufs_allowed = 0;
++ group->rdbufs_reserved = 0;
++ if (idxd->hw.version < DEVICE_VERSION_2 && !tc_override) {
++ group->tc_a = 1;
++ group->tc_b = 1;
++ } else {
++ group->tc_a = -1;
++ group->tc_b = -1;
++ }
+ }
+ }
- if (wq->state == IDXD_WQ_ENABLED) {
+@@ -712,11 +724,15 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd)
idxd_wq_disable_cleanup(wq);
-+ idxd_wq_device_reset_cleanup(wq);
wq->state = IDXD_WQ_DISABLED;
}
++ idxd_wq_device_reset_cleanup(wq);
}
+ }
+
+ void idxd_device_clear_state(struct idxd_device *idxd)
+ {
++ if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
++ return;
++
+ idxd_groups_clear_state(idxd);
+ idxd_engines_clear_state(idxd);
+ idxd_device_wqs_clear_state(idxd);
+@@ -791,10 +807,10 @@ static int idxd_groups_config_write(struct idxd_device *idxd)
+ int i;
+ struct device *dev = &idxd->pdev->dev;
+
+- /* Setup bandwidth token limit */
+- if (idxd->token_limit) {
++ /* Setup bandwidth rdbuf limit */
++ if (idxd->hw.gen_cap.config_en && idxd->rdbuf_limit) {
+ reg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
+- reg.token_limit = idxd->token_limit;
++ reg.rdbuf_limit = idxd->rdbuf_limit;
+ iowrite32(reg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
+ }
+
+@@ -935,13 +951,12 @@ static void idxd_group_flags_setup(struct idxd_device *idxd)
+ group->tc_b = group->grpcfg.flags.tc_b = 1;
+ else
+ group->grpcfg.flags.tc_b = group->tc_b;
+- group->grpcfg.flags.use_token_limit = group->use_token_limit;
+- group->grpcfg.flags.tokens_reserved = group->tokens_reserved;
+- if (group->tokens_allowed)
+- group->grpcfg.flags.tokens_allowed =
+- group->tokens_allowed;
++ group->grpcfg.flags.use_rdbuf_limit = group->use_rdbuf_limit;
++ group->grpcfg.flags.rdbufs_reserved = group->rdbufs_reserved;
++ if (group->rdbufs_allowed)
++ group->grpcfg.flags.rdbufs_allowed = group->rdbufs_allowed;
+ else
+- group->grpcfg.flags.tokens_allowed = idxd->max_tokens;
++ group->grpcfg.flags.rdbufs_allowed = idxd->max_rdbufs;
+ }
+ }
+
+@@ -1136,7 +1151,7 @@ int idxd_device_load_config(struct idxd_device *idxd)
+ int i, rc;
+
+ reg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
+- idxd->token_limit = reg.token_limit;
++ idxd->rdbuf_limit = reg.rdbuf_limit;
+
+ for (i = 0; i < idxd->max_groups; i++) {
+ struct idxd_group *group = idxd->groups[i];
diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c
index e0f056c1d1f56..c39e9483206ad 100644
--- a/drivers/dma/idxd/dma.c
@@ -33404,10 +56086,55 @@ index e0f056c1d1f56..c39e9483206ad 100644
mutex_unlock(&wq->wq_lock);
}
+diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
+index bfcb03329f778..833af18a99ee5 100644
+--- a/drivers/dma/idxd/idxd.h
++++ b/drivers/dma/idxd/idxd.h
+@@ -84,9 +84,9 @@ struct idxd_group {
+ int id;
+ int num_engines;
+ int num_wqs;
+- bool use_token_limit;
+- u8 tokens_allowed;
+- u8 tokens_reserved;
++ bool use_rdbuf_limit;
++ u8 rdbufs_allowed;
++ u8 rdbufs_reserved;
+ int tc_a;
+ int tc_b;
+ };
+@@ -278,11 +278,11 @@ struct idxd_device {
+ u32 max_batch_size;
+ int max_groups;
+ int max_engines;
+- int max_tokens;
++ int max_rdbufs;
+ int max_wqs;
+ int max_wq_size;
+- int token_limit;
+- int nr_tokens; /* non-reserved tokens */
++ int rdbuf_limit;
++ int nr_rdbufs; /* non-reserved read buffers */
+ unsigned int wqcfg_size;
+
+ union sw_err_reg sw_err;
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
-index eb09bc591c316..7bf03f371ce19 100644
+index eb09bc591c316..6263d9825250b 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
+@@ -464,9 +464,9 @@ static void idxd_read_caps(struct idxd_device *idxd)
+ dev_dbg(dev, "group_cap: %#llx\n", idxd->hw.group_cap.bits);
+ idxd->max_groups = idxd->hw.group_cap.num_groups;
+ dev_dbg(dev, "max groups: %u\n", idxd->max_groups);
+- idxd->max_tokens = idxd->hw.group_cap.total_tokens;
+- dev_dbg(dev, "max tokens: %u\n", idxd->max_tokens);
+- idxd->nr_tokens = idxd->max_tokens;
++ idxd->max_rdbufs = idxd->hw.group_cap.total_rdbufs;
++ dev_dbg(dev, "max read buffers: %u\n", idxd->max_rdbufs);
++ idxd->nr_rdbufs = idxd->max_rdbufs;
+
+ /* read engine capabilities */
+ idxd->hw.engine_cap.bits =
@@ -797,11 +797,19 @@ static void idxd_remove(struct pci_dev *pdev)
int msixcnt = pci_msix_vec_count(pdev);
int i;
@@ -33474,9 +56201,31 @@ index ca88fa7a328e7..6d6af0dc3c0ec 100644
dev_err(&idxd->pdev->dev,
"idxd halted, need %s.\n",
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
-index ffc7550a77eeb..97ffb06de9b0d 100644
+index ffc7550a77eeb..c0961c1ac161d 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
+@@ -65,9 +65,9 @@ union wq_cap_reg {
+ union group_cap_reg {
+ struct {
+ u64 num_groups:8;
+- u64 total_tokens:8;
+- u64 token_en:1;
+- u64 token_limit:1;
++ u64 total_rdbufs:8; /* formerly total_tokens */
++ u64 rdbuf_ctrl:1; /* formerly token_en */
++ u64 rdbuf_limit:1; /* formerly token_limit */
+ u64 rsvd:46;
+ };
+ u64 bits;
+@@ -111,7 +111,7 @@ union offsets_reg {
+ #define IDXD_GENCFG_OFFSET 0x80
+ union gencfg_reg {
+ struct {
+- u32 token_limit:8;
++ u32 rdbuf_limit:8;
+ u32 rsvd:4;
+ u32 user_int_en:1;
+ u32 rsvd2:19;
@@ -158,6 +158,7 @@ enum idxd_device_reset_type {
#define IDXD_INTC_CMD 0x02
#define IDXD_INTC_OCCUPY 0x04
@@ -33485,6 +56234,20 @@ index ffc7550a77eeb..97ffb06de9b0d 100644
#define IDXD_CMD_OFFSET 0xa0
union idxd_command_reg {
+@@ -287,10 +288,10 @@ union group_flags {
+ u32 tc_a:3;
+ u32 tc_b:3;
+ u32 rsvd:1;
+- u32 use_token_limit:1;
+- u32 tokens_reserved:8;
++ u32 use_rdbuf_limit:1;
++ u32 rdbufs_reserved:8;
+ u32 rsvd2:4;
+- u32 tokens_allowed:8;
++ u32 rdbufs_allowed:8;
+ u32 rsvd3:4;
+ };
+ u32 bits;
diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c
index de76fb4abac24..83452fbbb168b 100644
--- a/drivers/dma/idxd/submit.c
@@ -33528,6 +56291,273 @@ index de76fb4abac24..83452fbbb168b 100644
}
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
+diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
+index a9025be940db2..33d94c67fedb9 100644
+--- a/drivers/dma/idxd/sysfs.c
++++ b/drivers/dma/idxd/sysfs.c
+@@ -99,17 +99,17 @@ struct device_type idxd_engine_device_type = {
+
+ /* Group attributes */
+
+-static void idxd_set_free_tokens(struct idxd_device *idxd)
++static void idxd_set_free_rdbufs(struct idxd_device *idxd)
+ {
+- int i, tokens;
++ int i, rdbufs;
+
+- for (i = 0, tokens = 0; i < idxd->max_groups; i++) {
++ for (i = 0, rdbufs = 0; i < idxd->max_groups; i++) {
+ struct idxd_group *g = idxd->groups[i];
+
+- tokens += g->tokens_reserved;
++ rdbufs += g->rdbufs_reserved;
+ }
+
+- idxd->nr_tokens = idxd->max_tokens - tokens;
++ idxd->nr_rdbufs = idxd->max_rdbufs - rdbufs;
+ }
+
+ static ssize_t group_tokens_reserved_show(struct device *dev,
+@@ -118,7 +118,7 @@ static ssize_t group_tokens_reserved_show(struct device *dev,
+ {
+ struct idxd_group *group = confdev_to_group(dev);
+
+- return sysfs_emit(buf, "%u\n", group->tokens_reserved);
++ return sysfs_emit(buf, "%u\n", group->rdbufs_reserved);
+ }
+
+ static ssize_t group_tokens_reserved_store(struct device *dev,
+@@ -143,14 +143,14 @@ static ssize_t group_tokens_reserved_store(struct device *dev,
+ if (idxd->state == IDXD_DEV_ENABLED)
+ return -EPERM;
+
+- if (val > idxd->max_tokens)
++ if (val > idxd->max_rdbufs)
+ return -EINVAL;
+
+- if (val > idxd->nr_tokens + group->tokens_reserved)
++ if (val > idxd->nr_rdbufs + group->rdbufs_reserved)
+ return -EINVAL;
+
+- group->tokens_reserved = val;
+- idxd_set_free_tokens(idxd);
++ group->rdbufs_reserved = val;
++ idxd_set_free_rdbufs(idxd);
+ return count;
+ }
+
+@@ -164,7 +164,7 @@ static ssize_t group_tokens_allowed_show(struct device *dev,
+ {
+ struct idxd_group *group = confdev_to_group(dev);
+
+- return sysfs_emit(buf, "%u\n", group->tokens_allowed);
++ return sysfs_emit(buf, "%u\n", group->rdbufs_allowed);
+ }
+
+ static ssize_t group_tokens_allowed_store(struct device *dev,
+@@ -190,10 +190,10 @@ static ssize_t group_tokens_allowed_store(struct device *dev,
+ return -EPERM;
+
+ if (val < 4 * group->num_engines ||
+- val > group->tokens_reserved + idxd->nr_tokens)
++ val > group->rdbufs_reserved + idxd->nr_rdbufs)
+ return -EINVAL;
+
+- group->tokens_allowed = val;
++ group->rdbufs_allowed = val;
+ return count;
+ }
+
+@@ -207,7 +207,7 @@ static ssize_t group_use_token_limit_show(struct device *dev,
+ {
+ struct idxd_group *group = confdev_to_group(dev);
+
+- return sysfs_emit(buf, "%u\n", group->use_token_limit);
++ return sysfs_emit(buf, "%u\n", group->use_rdbuf_limit);
+ }
+
+ static ssize_t group_use_token_limit_store(struct device *dev,
+@@ -232,10 +232,10 @@ static ssize_t group_use_token_limit_store(struct device *dev,
+ if (idxd->state == IDXD_DEV_ENABLED)
+ return -EPERM;
+
+- if (idxd->token_limit == 0)
++ if (idxd->rdbuf_limit == 0)
+ return -EPERM;
+
+- group->use_token_limit = !!val;
++ group->use_rdbuf_limit = !!val;
+ return count;
+ }
+
+@@ -842,6 +842,9 @@ static ssize_t wq_max_transfer_size_store(struct device *dev, struct device_attr
+ u64 xfer_size;
+ int rc;
+
++ if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
++ return -EPERM;
++
+ if (wq->state != IDXD_WQ_DISABLED)
+ return -EPERM;
+
+@@ -876,6 +879,9 @@ static ssize_t wq_max_batch_size_store(struct device *dev, struct device_attribu
+ u64 batch_size;
+ int rc;
+
++ if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
++ return -EPERM;
++
+ if (wq->state != IDXD_WQ_DISABLED)
+ return -EPERM;
+
+@@ -1161,7 +1167,7 @@ static ssize_t max_tokens_show(struct device *dev,
+ {
+ struct idxd_device *idxd = confdev_to_idxd(dev);
+
+- return sysfs_emit(buf, "%u\n", idxd->max_tokens);
++ return sysfs_emit(buf, "%u\n", idxd->max_rdbufs);
+ }
+ static DEVICE_ATTR_RO(max_tokens);
+
+@@ -1170,7 +1176,7 @@ static ssize_t token_limit_show(struct device *dev,
+ {
+ struct idxd_device *idxd = confdev_to_idxd(dev);
+
+- return sysfs_emit(buf, "%u\n", idxd->token_limit);
++ return sysfs_emit(buf, "%u\n", idxd->rdbuf_limit);
+ }
+
+ static ssize_t token_limit_store(struct device *dev,
+@@ -1191,13 +1197,13 @@ static ssize_t token_limit_store(struct device *dev,
+ if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
+ return -EPERM;
+
+- if (!idxd->hw.group_cap.token_limit)
++ if (!idxd->hw.group_cap.rdbuf_limit)
+ return -EPERM;
+
+- if (val > idxd->hw.group_cap.total_tokens)
++ if (val > idxd->hw.group_cap.total_rdbufs)
+ return -EINVAL;
+
+- idxd->token_limit = val;
++ idxd->rdbuf_limit = val;
+ return count;
+ }
+ static DEVICE_ATTR_RW(token_limit);
+diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
+index cacc725ca5459..2300d965a3f44 100644
+--- a/drivers/dma/imx-sdma.c
++++ b/drivers/dma/imx-sdma.c
+@@ -198,12 +198,12 @@ struct sdma_script_start_addrs {
+ s32 per_2_firi_addr;
+ s32 mcu_2_firi_addr;
+ s32 uart_2_per_addr;
+- s32 uart_2_mcu_ram_addr;
++ s32 uart_2_mcu_addr;
+ s32 per_2_app_addr;
+ s32 mcu_2_app_addr;
+ s32 per_2_per_addr;
+ s32 uartsh_2_per_addr;
+- s32 uartsh_2_mcu_ram_addr;
++ s32 uartsh_2_mcu_addr;
+ s32 per_2_shp_addr;
+ s32 mcu_2_shp_addr;
+ s32 ata_2_mcu_addr;
+@@ -232,8 +232,8 @@ struct sdma_script_start_addrs {
+ s32 mcu_2_ecspi_addr;
+ s32 mcu_2_sai_addr;
+ s32 sai_2_mcu_addr;
+- s32 uart_2_mcu_addr;
+- s32 uartsh_2_mcu_addr;
++ s32 uart_2_mcu_rom_addr;
++ s32 uartsh_2_mcu_rom_addr;
+ /* End of v3 array */
+ s32 mcu_2_zqspi_addr;
+ /* End of v4 array */
+@@ -1780,17 +1780,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
+ saddr_arr[i] = addr_arr[i];
+
+ /*
+- * get uart_2_mcu_addr/uartsh_2_mcu_addr rom script specially because
+- * they are now replaced by uart_2_mcu_ram_addr/uartsh_2_mcu_ram_addr
+- * to be compatible with legacy freescale/nxp sdma firmware, and they
+- * are located in the bottom part of sdma_script_start_addrs which are
+- * beyond the SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1.
++ * For compatibility with NXP internal legacy kernel before 4.19 which
++ * is based on uart ram script and mainline kernel based on uart rom
++ * script, both uart ram/rom scripts are present in newer sdma
++ * firmware. Use the rom versions if they are present (V3 or newer).
+ */
+- if (addr->uart_2_mcu_addr)
+- sdma->script_addrs->uart_2_mcu_addr = addr->uart_2_mcu_addr;
+- if (addr->uartsh_2_mcu_addr)
+- sdma->script_addrs->uartsh_2_mcu_addr = addr->uartsh_2_mcu_addr;
+-
++ if (sdma->script_number >= SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3) {
++ if (addr->uart_2_mcu_rom_addr)
++ sdma->script_addrs->uart_2_mcu_addr = addr->uart_2_mcu_rom_addr;
++ if (addr->uartsh_2_mcu_rom_addr)
++ sdma->script_addrs->uartsh_2_mcu_addr = addr->uartsh_2_mcu_rom_addr;
++ }
+ }
+
+ static void sdma_load_firmware(const struct firmware *fw, void *context)
+@@ -1869,7 +1869,7 @@ static int sdma_event_remap(struct sdma_engine *sdma)
+ u32 reg, val, shift, num_map, i;
+ int ret = 0;
+
+- if (IS_ERR(np) || IS_ERR(gpr_np))
++ if (IS_ERR(np) || !gpr_np)
+ goto out;
+
+ event_remap = of_find_property(np, propname, NULL);
+@@ -1917,7 +1917,7 @@ static int sdma_event_remap(struct sdma_engine *sdma)
+ }
+
+ out:
+- if (!IS_ERR(gpr_np))
++ if (gpr_np)
+ of_node_put(gpr_np);
+
+ return ret;
+diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
+index 375e7e647df6b..a1517ef1f4a01 100644
+--- a/drivers/dma/mediatek/mtk-uart-apdma.c
++++ b/drivers/dma/mediatek/mtk-uart-apdma.c
+@@ -274,7 +274,7 @@ static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan)
+ unsigned int status;
+ int ret;
+
+- ret = pm_runtime_get_sync(mtkd->ddev.dev);
++ ret = pm_runtime_resume_and_get(mtkd->ddev.dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(chan->device->dev);
+ return ret;
+@@ -288,18 +288,21 @@ static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan)
+ ret = readx_poll_timeout(readl, c->base + VFF_EN,
+ status, !status, 10, 100);
+ if (ret)
+- return ret;
++ goto err_pm;
+
+ ret = request_irq(c->irq, mtk_uart_apdma_irq_handler,
+ IRQF_TRIGGER_NONE, KBUILD_MODNAME, chan);
+ if (ret < 0) {
+ dev_err(chan->device->dev, "Can't request dma IRQ\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_pm;
+ }
+
+ if (mtkd->support_33bits)
+ mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B);
+
++err_pm:
++ pm_runtime_put_noidle(mtkd->ddev.dev);
+ return ret;
+ }
+
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 89f1814ff27a0..26d11885c50ec 100644
--- a/drivers/dma/mmp_pdma.c
@@ -33635,22 +56665,6 @@ index 6885b3dcd7a97..f4c46b3b6d9d7 100644
ret = rcar_dmac_parse_of(&pdev->dev, dmac);
if (ret < 0)
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-index 7f72b3f4cd1ae..19ac95c0098f0 100644
---- a/drivers/dma/sh/shdma-base.c
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -115,8 +115,10 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
- ret = pm_runtime_get(schan->dev);
-
- spin_unlock_irq(&schan->chan_lock);
-- if (ret < 0)
-+ if (ret < 0) {
- dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret);
-+ pm_runtime_put(schan->dev);
-+ }
-
- pm_runtime_barrier(schan->dev);
-
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index 962b6e05287b5..d95c421877fb7 100644
--- a/drivers/dma/st_fdma.c
@@ -34033,10 +57047,44 @@ index 4c626fcd4dcbb..1522d4aa2ca62 100644
static u64 knl_get_tolm(struct sbridge_pvt *pvt)
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
-index 7d08627e738b3..a5486d86fdd2f 100644
+index 7d08627e738b3..8557781bb8dce 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
-@@ -1352,8 +1352,7 @@ static int mc_probe(struct platform_device *pdev)
+@@ -163,6 +163,11 @@
+ #define ECC_STAT_CECNT_SHIFT 8
+ #define ECC_STAT_BITNUM_MASK 0x7F
+
++/* ECC error count register definitions */
++#define ECC_ERRCNT_UECNT_MASK 0xFFFF0000
++#define ECC_ERRCNT_UECNT_SHIFT 16
++#define ECC_ERRCNT_CECNT_MASK 0xFFFF
++
+ /* DDR QOS Interrupt register definitions */
+ #define DDR_QOS_IRQ_STAT_OFST 0x20200
+ #define DDR_QOSUE_MASK 0x4
+@@ -418,15 +423,16 @@ static int zynqmp_get_error_info(struct synps_edac_priv *priv)
+ base = priv->baseaddr;
+ p = &priv->stat;
+
++ regval = readl(base + ECC_ERRCNT_OFST);
++ p->ce_cnt = regval & ECC_ERRCNT_CECNT_MASK;
++ p->ue_cnt = (regval & ECC_ERRCNT_UECNT_MASK) >> ECC_ERRCNT_UECNT_SHIFT;
++ if (!p->ce_cnt)
++ goto ue_err;
++
+ regval = readl(base + ECC_STAT_OFST);
+ if (!regval)
+ return 1;
+
+- p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+- p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+- if (!p->ce_cnt)
+- goto ue_err;
+-
+ p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+ regval = readl(base + ECC_CEADDR0_OFST);
+@@ -1352,8 +1358,7 @@ static int mc_probe(struct platform_device *pdev)
}
}
@@ -34059,6 +57107,203 @@ index 2ccd1db5e98ff..7197f9fa02457 100644
goto out_err;
}
rc = devm_request_irq(&pdev->dev, irq,
+diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
+index 54be88167c60b..f3b3953cac834 100644
+--- a/drivers/firewire/core-card.c
++++ b/drivers/firewire/core-card.c
+@@ -668,6 +668,7 @@ EXPORT_SYMBOL_GPL(fw_card_release);
+ void fw_core_remove_card(struct fw_card *card)
+ {
+ struct fw_card_driver dummy_driver = dummy_driver_template;
++ unsigned long flags;
+
+ card->driver->update_phy_reg(card, 4,
+ PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
+@@ -682,7 +683,9 @@ void fw_core_remove_card(struct fw_card *card)
+ dummy_driver.stop_iso = card->driver->stop_iso;
+ card->driver = &dummy_driver;
+
++ spin_lock_irqsave(&card->lock, flags);
+ fw_destroy_nodes(card);
++ spin_unlock_irqrestore(&card->lock, flags);
+
+ /* Wait for all users, especially device workqueue jobs, to finish. */
+ fw_card_put(card);
+diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
+index fb6c651214f32..b0cc3f1e9bb00 100644
+--- a/drivers/firewire/core-cdev.c
++++ b/drivers/firewire/core-cdev.c
+@@ -1480,6 +1480,7 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
+ {
+ struct outbound_phy_packet_event *e =
+ container_of(packet, struct outbound_phy_packet_event, p);
++ struct client *e_client;
+
+ switch (status) {
+ /* expected: */
+@@ -1496,9 +1497,10 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
+ }
+ e->phy_packet.data[0] = packet->timestamp;
+
++ e_client = e->client;
+ queue_event(e->client, &e->event, &e->phy_packet,
+ sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);
+- client_put(e->client);
++ client_put(e_client);
+ }
+
+ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
+diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
+index b63d55f5ebd33..f40c815343812 100644
+--- a/drivers/firewire/core-topology.c
++++ b/drivers/firewire/core-topology.c
+@@ -375,16 +375,13 @@ static void report_found_node(struct fw_card *card,
+ card->bm_retries = 0;
+ }
+
++/* Must be called with card->lock held */
+ void fw_destroy_nodes(struct fw_card *card)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->lock, flags);
+ card->color++;
+ if (card->local_node != NULL)
+ for_each_fw_node(card, card->local_node, report_lost_node);
+ card->local_node = NULL;
+- spin_unlock_irqrestore(&card->lock, flags);
+ }
+
+ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
+@@ -510,6 +507,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
+ struct fw_node *local_node;
+ unsigned long flags;
+
++ spin_lock_irqsave(&card->lock, flags);
++
+ /*
+ * If the selfID buffer is not the immediate successor of the
+ * previously processed one, we cannot reliably compare the
+@@ -521,8 +520,6 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
+ card->bm_retries = 0;
+ }
+
+- spin_lock_irqsave(&card->lock, flags);
+-
+ card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
+ card->node_id = node_id;
+ /*
+diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
+index ac487c96bb717..6c20815cc8d16 100644
+--- a/drivers/firewire/core-transaction.c
++++ b/drivers/firewire/core-transaction.c
+@@ -73,24 +73,25 @@ static int try_cancel_split_timeout(struct fw_transaction *t)
+ static int close_transaction(struct fw_transaction *transaction,
+ struct fw_card *card, int rcode)
+ {
+- struct fw_transaction *t;
++ struct fw_transaction *t = NULL, *iter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry(t, &card->transaction_list, link) {
+- if (t == transaction) {
+- if (!try_cancel_split_timeout(t)) {
++ list_for_each_entry(iter, &card->transaction_list, link) {
++ if (iter == transaction) {
++ if (!try_cancel_split_timeout(iter)) {
+ spin_unlock_irqrestore(&card->lock, flags);
+ goto timed_out;
+ }
+- list_del_init(&t->link);
+- card->tlabel_mask &= ~(1ULL << t->tlabel);
++ list_del_init(&iter->link);
++ card->tlabel_mask &= ~(1ULL << iter->tlabel);
++ t = iter;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+
+- if (&t->link != &card->transaction_list) {
++ if (t) {
+ t->callback(card, rcode, NULL, 0, t->callback_data);
+ return 0;
+ }
+@@ -935,7 +936,7 @@ EXPORT_SYMBOL(fw_core_handle_request);
+
+ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+ {
+- struct fw_transaction *t;
++ struct fw_transaction *t = NULL, *iter;
+ unsigned long flags;
+ u32 *data;
+ size_t data_length;
+@@ -947,20 +948,21 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+ rcode = HEADER_GET_RCODE(p->header[1]);
+
+ spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry(t, &card->transaction_list, link) {
+- if (t->node_id == source && t->tlabel == tlabel) {
+- if (!try_cancel_split_timeout(t)) {
++ list_for_each_entry(iter, &card->transaction_list, link) {
++ if (iter->node_id == source && iter->tlabel == tlabel) {
++ if (!try_cancel_split_timeout(iter)) {
+ spin_unlock_irqrestore(&card->lock, flags);
+ goto timed_out;
+ }
+- list_del_init(&t->link);
+- card->tlabel_mask &= ~(1ULL << t->tlabel);
++ list_del_init(&iter->link);
++ card->tlabel_mask &= ~(1ULL << iter->tlabel);
++ t = iter;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+
+- if (&t->link == &card->transaction_list) {
++ if (!t) {
+ timed_out:
+ fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
+ source, tlabel);
+diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
+index 4d5054211550b..2ceed9287435f 100644
+--- a/drivers/firewire/sbp2.c
++++ b/drivers/firewire/sbp2.c
+@@ -408,7 +408,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
+ void *payload, size_t length, void *callback_data)
+ {
+ struct sbp2_logical_unit *lu = callback_data;
+- struct sbp2_orb *orb;
++ struct sbp2_orb *orb = NULL, *iter;
+ struct sbp2_status status;
+ unsigned long flags;
+
+@@ -433,17 +433,18 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
+
+ /* Lookup the orb corresponding to this status write. */
+ spin_lock_irqsave(&lu->tgt->lock, flags);
+- list_for_each_entry(orb, &lu->orb_list, link) {
++ list_for_each_entry(iter, &lu->orb_list, link) {
+ if (STATUS_GET_ORB_HIGH(status) == 0 &&
+- STATUS_GET_ORB_LOW(status) == orb->request_bus) {
+- orb->rcode = RCODE_COMPLETE;
+- list_del(&orb->link);
++ STATUS_GET_ORB_LOW(status) == iter->request_bus) {
++ iter->rcode = RCODE_COMPLETE;
++ list_del(&iter->link);
++ orb = iter;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&lu->tgt->lock, flags);
+
+- if (&orb->link != &lu->orb_list) {
++ if (orb) {
+ orb->callback(orb, &status);
+ kref_put(&orb->kref, free_orb); /* orb callback reference */
+ } else {
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index de416f9e79213..f5219334fd3a5 100644
--- a/drivers/firmware/arm_scmi/base.c
@@ -34101,11 +57346,35 @@ index de416f9e79213..f5219334fd3a5 100644
ph->xops->xfer_put(ph, t);
+diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
+index 35b56c8ba0c0e..492f3a9197ec2 100644
+--- a/drivers/firmware/arm_scmi/clock.c
++++ b/drivers/firmware/arm_scmi/clock.c
+@@ -204,7 +204,8 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
+
+ if (rate_discrete && rate) {
+ clk->list.num_rates = tot_rate_cnt;
+- sort(rate, tot_rate_cnt, sizeof(*rate), rate_cmp_func, NULL);
++ sort(clk->list.rates, tot_rate_cnt, sizeof(*rate),
++ rate_cmp_func, NULL);
+ }
+
+ clk->rate_discrete = rate_discrete;
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
-index b406b3f78f467..d76bab3aaac45 100644
+index b406b3f78f467..e815b8f987393 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
-@@ -2112,7 +2112,7 @@ static void __exit scmi_driver_exit(void)
+@@ -652,7 +652,8 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
+
+ xfer = scmi_xfer_command_acquire(cinfo, msg_hdr);
+ if (IS_ERR(xfer)) {
+- scmi_clear_channel(info, cinfo);
++ if (MSG_XTRACT_TYPE(msg_hdr) == MSG_TYPE_DELAYED_RESP)
++ scmi_clear_channel(info, cinfo);
+ return;
+ }
+
+@@ -2112,7 +2113,7 @@ static void __exit scmi_driver_exit(void)
}
module_exit(scmi_driver_exit);
@@ -34197,6 +57466,19 @@ index a5048956a0be9..ac08e819088bb 100644
ret = ph->xops->do_xfer(ph, tl);
if (ret)
break;
+diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c
+index 4c3201e290e29..ea84108035eb0 100644
+--- a/drivers/firmware/efi/apple-properties.c
++++ b/drivers/firmware/efi/apple-properties.c
+@@ -24,7 +24,7 @@ static bool dump_properties __initdata;
+ static int __init dump_properties_enable(char *arg)
+ {
+ dump_properties = true;
+- return 0;
++ return 1;
+ }
+
+ __setup("dump_apple_properties", dump_properties_enable);
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index b19ce1a83f91a..b2c829e95bd14 100644
--- a/drivers/firmware/efi/efi-init.c
@@ -34213,10 +57495,32 @@ index b19ce1a83f91a..b2c829e95bd14 100644
efi_esrt_init();
efi_mokvar_table_init();
+diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
+index 0ef086e43090b..7e771c56c13c6 100644
+--- a/drivers/firmware/efi/efi-pstore.c
++++ b/drivers/firmware/efi/efi-pstore.c
+@@ -266,7 +266,7 @@ static int efi_pstore_write(struct pstore_record *record)
+ efi_name[i] = name[i];
+
+ ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
+- preemptible(), record->size, record->psi->buf);
++ false, record->size, record->psi->buf);
+
+ if (record->reason == KMSG_DUMP_OOPS && try_module_get(THIS_MODULE))
+ if (!schedule_work(&efivar_work))
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
-index 847f33ffc4aed..9fa86288b78a9 100644
+index 847f33ffc4aed..e3df82d5d37a8 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
+@@ -209,7 +209,7 @@ static int __init efivar_ssdt_setup(char *str)
+ memcpy(efivar_ssdt, str, strlen(str));
+ else
+ pr_warn("efivar_ssdt: name too long: %s\n", str);
+- return 0;
++ return 1;
+ }
+ __setup("efivar_ssdt=", efivar_ssdt_setup);
+
@@ -719,6 +719,13 @@ void __init efi_systab_report_header(const efi_table_hdr_t *systab_hdr,
systab_hdr->revision >> 16,
systab_hdr->revision & 0xffff,
@@ -34326,7 +57630,7 @@ index abdc8a6a39631..cae590bd08f27 100644
up(&efivars_lock);
return -ENOSPC;
diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
-index 97968aece54f8..931544c9f63d4 100644
+index 97968aece54f8..983e07dc022ed 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -3,9 +3,9 @@ menuconfig GOOGLE_FIRMWARE
@@ -34342,6 +57646,15 @@ index 97968aece54f8..931544c9f63d4 100644
if GOOGLE_FIRMWARE
+@@ -21,7 +21,7 @@ config GOOGLE_SMI
+
+ config GOOGLE_COREBOOT_TABLE
+ tristate "Coreboot Table Access"
+- depends on ACPI || OF
++ depends on HAS_IOMEM && (ACPI || OF)
+ help
+ This option enables the coreboot_table module, which provides other
+ firmware modules access to the coreboot table. The coreboot table
diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c
index 9a369a2eda71d..116eb465cdb42 100644
--- a/drivers/firmware/psci/psci_checker.c
@@ -34356,7 +57669,7 @@ index 9a369a2eda71d..116eb465cdb42 100644
if (!cpu_groups) {
free_cpumask_var(tmp);
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
-index 2ee97bab74409..27a64de919817 100644
+index 2ee97bab74409..2b5214d5c0daf 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -252,7 +252,7 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
@@ -34368,6 +57681,19 @@ index 2ee97bab74409..27a64de919817 100644
}
ret = qcom_scm_call(dev, &desc, &res);
+@@ -749,12 +749,6 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+ };
+ int ret;
+
+- desc.args[0] = addr;
+- desc.args[1] = size;
+- desc.args[2] = spare;
+- desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
+- QCOM_SCM_VAL);
+-
+ ret = qcom_scm_call(__scm->dev, &desc, NULL);
+
+ /* the pg table has been initialized already, ignore the error */
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 172c751a4f6c2..f08e056ed0ae4 100644
--- a/drivers/firmware/qemu_fw_cfg.c
@@ -34470,29 +57796,198 @@ index 581aa5e9b0778..dd7c3d5e8b0bb 100644
pr_info("ARCH_SOC_ID not implemented, skipping ....\n");
return 0;
}
+diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
+index 2a7687911c097..53c7e3f8cfde2 100644
+--- a/drivers/firmware/stratix10-svc.c
++++ b/drivers/firmware/stratix10-svc.c
+@@ -477,7 +477,7 @@ static int svc_normal_to_secure_thread(void *data)
+ case INTEL_SIP_SMC_RSU_ERROR:
+ pr_err("%s: STATUS_ERROR\n", __func__);
+ cbdata->status = BIT(SVC_STATUS_ERROR);
+- cbdata->kaddr1 = NULL;
++ cbdata->kaddr1 = &res.a1;
+ cbdata->kaddr2 = NULL;
+ cbdata->kaddr3 = NULL;
+ pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata);
diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
-index b86761904949c..303a491e520d1 100644
+index b86761904949c..757cc8b9f3de9 100644
--- a/drivers/firmware/sysfb_simplefb.c
+++ b/drivers/firmware/sysfb_simplefb.c
-@@ -113,12 +113,16 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
- sysfb_apply_efi_quirks(pd);
+@@ -114,11 +114,20 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
ret = platform_device_add_resources(pd, &res, 1);
-- if (ret)
-+ if (ret) {
-+ platform_device_put(pd);
- return ret;
-+ }
+ if (ret)
+- return ret;
++ goto err_put_device;
ret = platform_device_add_data(pd, mode, sizeof(*mode));
-- if (ret)
-+ if (ret) {
-+ platform_device_put(pd);
- return ret;
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+- return platform_device_add(pd);
++ ret = platform_device_add(pd);
++ if (ret)
++ goto err_put_device;
++
++ return 0;
++
++err_put_device:
++ platform_device_put(pd);
++
++ return ret;
+ }
+diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
+index 8606e55c1721c..0bed2fab80558 100644
+--- a/drivers/fsi/fsi-master-aspeed.c
++++ b/drivers/fsi/fsi-master-aspeed.c
+@@ -542,25 +542,28 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
+ return rc;
+ }
+
+- aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL);
++ aspeed = kzalloc(sizeof(*aspeed), GFP_KERNEL);
+ if (!aspeed)
+ return -ENOMEM;
+
+ aspeed->dev = &pdev->dev;
+
+ aspeed->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(aspeed->base))
+- return PTR_ERR(aspeed->base);
++ if (IS_ERR(aspeed->base)) {
++ rc = PTR_ERR(aspeed->base);
++ goto err_free_aspeed;
+ }
- return platform_device_add(pd);
+ aspeed->clk = devm_clk_get(aspeed->dev, NULL);
+ if (IS_ERR(aspeed->clk)) {
+ dev_err(aspeed->dev, "couldn't get clock\n");
+- return PTR_ERR(aspeed->clk);
++ rc = PTR_ERR(aspeed->clk);
++ goto err_free_aspeed;
+ }
+ rc = clk_prepare_enable(aspeed->clk);
+ if (rc) {
+ dev_err(aspeed->dev, "couldn't enable clock\n");
+- return rc;
++ goto err_free_aspeed;
+ }
+
+ rc = setup_cfam_reset(aspeed);
+@@ -595,7 +598,7 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
+ rc = opb_readl(aspeed, ctrl_base + FSI_MVER, &raw);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to read hub version\n");
+- return rc;
++ goto err_release;
+ }
+
+ reg = be32_to_cpu(raw);
+@@ -634,6 +637,8 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
+
+ err_release:
+ clk_disable_unprepare(aspeed->clk);
++err_free_aspeed:
++ kfree(aspeed);
+ return rc;
}
+
+diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
+index da1486bb6a144..bcb756dc98663 100644
+--- a/drivers/fsi/fsi-scom.c
++++ b/drivers/fsi/fsi-scom.c
+@@ -145,7 +145,7 @@ static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
+ uint64_t addr, uint32_t *status)
+ {
+ uint64_t ind_data, ind_addr;
+- int rc, retries, err = 0;
++ int rc, err;
+
+ if (value & ~XSCOM_DATA_IND_DATA)
+ return -EINVAL;
+@@ -156,19 +156,14 @@ static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
+ if (rc || (*status & SCOM_STATUS_ANY_ERR))
+ return rc;
+
+- for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
+- rc = __get_scom(scom, &ind_data, addr, status);
+- if (rc || (*status & SCOM_STATUS_ANY_ERR))
+- return rc;
++ rc = __get_scom(scom, &ind_data, addr, status);
++ if (rc || (*status & SCOM_STATUS_ANY_ERR))
++ return rc;
+
+- err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
+- *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
+- if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
+- return 0;
++ err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
++ *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
+
+- msleep(1);
+- }
+- return rc;
++ return 0;
+ }
+
+ static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
+@@ -188,7 +183,7 @@ static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
+ uint64_t addr, uint32_t *status)
+ {
+ uint64_t ind_data, ind_addr;
+- int rc, retries, err = 0;
++ int rc, err;
+
+ ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
+ ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
+@@ -196,21 +191,15 @@ static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
+ if (rc || (*status & SCOM_STATUS_ANY_ERR))
+ return rc;
+
+- for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
+- rc = __get_scom(scom, &ind_data, addr, status);
+- if (rc || (*status & SCOM_STATUS_ANY_ERR))
+- return rc;
+-
+- err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
+- *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
+- *value = ind_data & XSCOM_DATA_IND_DATA;
++ rc = __get_scom(scom, &ind_data, addr, status);
++ if (rc || (*status & SCOM_STATUS_ANY_ERR))
++ return rc;
+
+- if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
+- return 0;
++ err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
++ *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
++ *value = ind_data & XSCOM_DATA_IND_DATA;
+
+- msleep(1);
+- }
+- return rc;
++ return 0;
+ }
+
+ static int raw_put_scom(struct scom_device *scom, uint64_t value,
+@@ -289,7 +278,7 @@ static int put_scom(struct scom_device *scom, uint64_t value,
+ int rc;
+
+ rc = raw_put_scom(scom, value, addr, &status);
+- if (rc == -ENODEV)
++ if (rc)
+ return rc;
+
+ rc = handle_fsi2pib_status(scom, status);
+@@ -308,7 +297,7 @@ static int get_scom(struct scom_device *scom, uint64_t *value,
+ int rc;
+
+ rc = raw_get_scom(scom, value, addr, &status);
+- if (rc == -ENODEV)
++ if (rc)
+ return rc;
+
+ rc = handle_fsi2pib_status(scom, status);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index fae5141251e5d..947474f6abb45 100644
--- a/drivers/gpio/Kconfig
@@ -35018,6 +58513,52 @@ index 70d6ae20b1da5..a964e25ea6206 100644
mpc8xxx_gc->irq = irq_domain_create_linear(fwnode,
MPC8XXX_GPIO_PINS,
+diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
+index 8f429d9f36616..1448dc874dfc3 100644
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -707,6 +707,9 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ unsigned long flags;
+ unsigned int on, off;
+
++ if (state->polarity != PWM_POLARITY_NORMAL)
++ return -EINVAL;
++
+ val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
+ do_div(val, NSEC_PER_SEC);
+ if (val > UINT_MAX + 1ULL)
+@@ -871,13 +874,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
+ mvpwm->chip.dev = dev;
+ mvpwm->chip.ops = &mvebu_pwm_ops;
+ mvpwm->chip.npwm = mvchip->chip.ngpio;
+- /*
+- * There may already be some PWM allocated, so we can't force
+- * mvpwm->chip.base to a fixed point like mvchip->chip.base.
+- * So, we let pwmchip_add() do the numbering and take the next free
+- * region.
+- */
+- mvpwm->chip.base = -1;
+
+ spin_lock_init(&mvpwm->lock);
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index d2fe76f3f34fd..8726921a11294 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -762,11 +762,11 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin
+ bitmap_xor(cur_stat, new_stat, old_stat, gc->ngpio);
+ bitmap_and(trigger, cur_stat, chip->irq_mask, gc->ngpio);
+
++ bitmap_copy(chip->irq_stat, new_stat, gc->ngpio);
++
+ if (bitmap_empty(trigger, gc->ngpio))
+ return false;
+
+- bitmap_copy(chip->irq_stat, new_stat, gc->ngpio);
+-
+ bitmap_and(cur_stat, chip->irq_trig_fall, old_stat, gc->ngpio);
+ bitmap_and(old_stat, chip->irq_trig_raise, new_stat, gc->ngpio);
+ bitmap_or(new_stat, old_stat, cur_stat, gc->ngpio);
diff --git a/drivers/gpio/gpio-realtek-otto.c b/drivers/gpio/gpio-realtek-otto.c
index eeeb39bc171dc..bd75401b549d1 100644
--- a/drivers/gpio/gpio-realtek-otto.c
@@ -35167,6 +58708,77 @@ index c99858f40a27e..00762de3d4096 100644
void __iomem *base;
u32 value;
+diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c
+index d885032cf814d..d918d2df4de2c 100644
+--- a/drivers/gpio/gpio-ts4900.c
++++ b/drivers/gpio/gpio-ts4900.c
+@@ -1,7 +1,7 @@
+ /*
+ * Digital I/O driver for Technologic Systems I2C FPGA Core
+ *
+- * Copyright (C) 2015 Technologic Systems
++ * Copyright (C) 2015, 2018 Technologic Systems
+ * Copyright (C) 2016 Savoir-Faire Linux
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -55,19 +55,33 @@ static int ts4900_gpio_direction_input(struct gpio_chip *chip,
+ {
+ struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
+
+- /*
+- * This will clear the output enable bit, the other bits are
+- * dontcare when this is cleared
++ /* Only clear the OE bit here, requires a RMW. Prevents potential issue
++ * with OE and data getting to the physical pin at different times.
+ */
+- return regmap_write(priv->regmap, offset, 0);
++ return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0);
+ }
+
+ static int ts4900_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+ {
+ struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
++ unsigned int reg;
+ int ret;
+
++ /* If changing from an input to an output, we need to first set the
++ * proper data bit to what is requested and then set OE bit. This
++ * prevents a glitch that can occur on the IO line
++ */
++ regmap_read(priv->regmap, offset, &reg);
++ if (!(reg & TS4900_GPIO_OE)) {
++ if (value)
++ reg = TS4900_GPIO_OUT;
++ else
++ reg &= ~TS4900_GPIO_OUT;
++
++ regmap_write(priv->regmap, offset, reg);
++ }
++
+ if (value)
+ ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
+ TS4900_GPIO_OUT);
+diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
+index e0f2b67558e74..47e191e11c696 100644
+--- a/drivers/gpio/gpio-vf610.c
++++ b/drivers/gpio/gpio-vf610.c
+@@ -125,9 +125,13 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+ {
+ struct vf610_gpio_port *port = gpiochip_get_data(chip);
+ unsigned long mask = BIT(gpio);
++ u32 val;
+
+- if (port->sdata && port->sdata->have_paddr)
+- vf610_gpio_writel(mask, port->gpio_base + GPIO_PDDR);
++ if (port->sdata && port->sdata->have_paddr) {
++ val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
++ val |= mask;
++ vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
++ }
+
+ vf610_gpio_set(chip, gpio, value);
+
diff --git a/drivers/gpio/gpio-virtio.c b/drivers/gpio/gpio-virtio.c
index d24f1c9264bc9..dd3b23c9580b1 100644
--- a/drivers/gpio/gpio-virtio.c
@@ -35184,11 +58796,78 @@ index d24f1c9264bc9..dd3b23c9580b1 100644
if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) {
dev_err(dev, "GPIO request failed: %d\n", gpio);
+diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c
+index 47455810bdb91..e6534ea1eaa7a 100644
+--- a/drivers/gpio/gpio-visconti.c
++++ b/drivers/gpio/gpio-visconti.c
+@@ -130,7 +130,6 @@ static int visconti_gpio_probe(struct platform_device *pdev)
+ struct gpio_irq_chip *girq;
+ struct irq_domain *parent;
+ struct device_node *irq_parent;
+- struct fwnode_handle *fwnode;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+@@ -150,14 +149,12 @@ static int visconti_gpio_probe(struct platform_device *pdev)
+ }
+
+ parent = irq_find_host(irq_parent);
++ of_node_put(irq_parent);
+ if (!parent) {
+ dev_err(dev, "No IRQ parent domain\n");
+ return -ENODEV;
+ }
+
+- fwnode = of_node_to_fwnode(irq_parent);
+- of_node_put(irq_parent);
+-
+ ret = bgpio_init(&priv->gpio_chip, dev, 4,
+ priv->base + GPIO_IDATA,
+ priv->base + GPIO_OSET,
+@@ -180,7 +177,7 @@ static int visconti_gpio_probe(struct platform_device *pdev)
+
+ girq = &priv->gpio_chip.irq;
+ girq->chip = irq_chip;
+- girq->fwnode = fwnode;
++ girq->fwnode = of_node_to_fwnode(dev->of_node);
+ girq->parent_domain = parent;
+ girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq;
+ girq->populate_parent_alloc_arg = visconti_gpio_populate_parent_fwspec;
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
-index 47712b6903b51..d040c72fea582 100644
+index 47712b6903b51..53be0bdf2bc38 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
-@@ -1059,10 +1059,17 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind
+@@ -311,7 +311,8 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
+ if (IS_ERR(desc))
+ return desc;
+
+- ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout);
++ /* ACPI uses hundredths of milliseconds units */
++ ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout * 10);
+ if (ret)
+ dev_warn(chip->parent,
+ "Failed to set debounce-timeout for pin 0x%04X, err %d\n",
+@@ -391,8 +392,8 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
+ pin = agpio->pin_table[0];
+
+ if (pin <= 255) {
+- char ev_name[5];
+- sprintf(ev_name, "_%c%02hhX",
++ char ev_name[8];
++ sprintf(ev_name, "_%c%02X",
+ agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
+ pin);
+ if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
+@@ -1052,17 +1053,25 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind
+ if (ret < 0)
+ return ret;
+
+- ret = gpio_set_debounce_timeout(desc, info.debounce);
++ /* ACPI uses hundredths of milliseconds units */
++ ret = gpio_set_debounce_timeout(desc, info.debounce * 10);
+ if (ret)
+ return ret;
+
irq_flags = acpi_dev_get_irq_type(info.triggering,
info.polarity);
@@ -35241,6 +58920,19 @@ index c7b5446d01fd2..ffa0256cad5a0 100644
if (ret)
goto out_free_le;
le->desc = desc;
+diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
+index 0ad288ab6262d..a5b34c2487679 100644
+--- a/drivers/gpio/gpiolib-of.c
++++ b/drivers/gpio/gpiolib-of.c
+@@ -912,7 +912,7 @@ static void of_gpiochip_init_valid_mask(struct gpio_chip *chip)
+ i, &start);
+ of_property_read_u32_index(np, "gpio-reserved-ranges",
+ i + 1, &count);
+- if (start >= chip->ngpio || start + count >= chip->ngpio)
++ if (start >= chip->ngpio || start + count > chip->ngpio)
+ continue;
+
+ bitmap_clear(chip->valid_mask, start, count);
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 4098bc7f88b7e..44c1ad51b3fe9 100644
--- a/drivers/gpio/gpiolib-sysfs.c
@@ -35260,6 +58952,77 @@ index 4098bc7f88b7e..44c1ad51b3fe9 100644
status = gpiod_set_transitory(desc, false);
if (!status) {
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index d1b9b721218f2..320baed949ee8 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1368,6 +1368,16 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
+ {
+ struct irq_domain *domain = gc->irq.domain;
+
++#ifdef CONFIG_GPIOLIB_IRQCHIP
++ /*
++ * Avoid race condition with other code, which tries to lookup
++ * an IRQ before the irqchip has been properly registered,
++ * i.e. while gpiochip is still being brought up.
++ */
++ if (!gc->irq.initialized)
++ return -EPROBE_DEFER;
++#endif
++
+ if (!gpiochip_irqchip_irq_valid(gc, offset))
+ return -ENXIO;
+
+@@ -1550,6 +1560,15 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
+
+ gpiochip_set_irq_hooks(gc);
+
++ /*
++ * Using barrier() here to prevent compiler from reordering
++ * gc->irq.initialized before initialization of above
++ * GPIO chip irq members.
++ */
++ barrier();
++
++ gc->irq.initialized = true;
++
+ acpi_gpiochip_request_interrupts(gc);
+
+ return 0;
+@@ -2186,6 +2205,16 @@ static int gpio_set_bias(struct gpio_desc *desc)
+ return gpio_set_config_with_argument_optional(desc, bias, arg);
+ }
+
++/**
++ * gpio_set_debounce_timeout() - Set debounce timeout
++ * @desc: GPIO descriptor to set the debounce timeout
++ * @debounce: Debounce timeout in microseconds
++ *
++ * The function calls the certain GPIO driver to set debounce timeout
++ * in the hardware.
++ *
++ * Returns 0 on success, or negative error code otherwise.
++ */
+ int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce)
+ {
+ return gpio_set_config_with_argument_optional(desc,
+@@ -3106,6 +3135,16 @@ int gpiod_to_irq(const struct gpio_desc *desc)
+
+ return retirq;
+ }
++#ifdef CONFIG_GPIOLIB_IRQCHIP
++ if (gc->irq.chip) {
++ /*
++ * Avoid race condition with other code, which tries to lookup
++ * an IRQ before the irqchip has been properly registered,
++ * i.e. while gpiochip is still being brought up.
++ */
++ return -EPROBE_DEFER;
++ }
++#endif
+ return -ENXIO;
+ }
+ EXPORT_SYMBOL_GPL(gpiod_to_irq);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 30bc3f80f83e6..c31f4626915de 100644
--- a/drivers/gpio/gpiolib.h
@@ -35283,8 +59046,20 @@ index 30bc3f80f83e6..c31f4626915de 100644
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags);
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
+diff --git a/drivers/gpu/drm/amd/amdgpu/ObjectID.h b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+index 5b393622f5920..a0f0a17e224fe 100644
+--- a/drivers/gpu/drm/amd/amdgpu/ObjectID.h
++++ b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+@@ -119,6 +119,7 @@
+ #define CONNECTOR_OBJECT_ID_eDP 0x14
+ #define CONNECTOR_OBJECT_ID_MXM 0x15
+ #define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
++#define CONNECTOR_OBJECT_ID_USBC 0x17
+
+ /* deleted */
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
-index 269437b013280..7e73ac6fb21db 100644
+index 269437b013280..2eebefd26fa82 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1069,6 +1069,7 @@ struct amdgpu_device {
@@ -35317,15 +59092,17 @@ index 269437b013280..7e73ac6fb21db 100644
static inline void amdgpu_acpi_detect(void) { }
static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
-@@ -1412,6 +1409,14 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
+@@ -1412,6 +1409,16 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
enum amdgpu_ss ss_state) { return 0; }
#endif
+#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
+bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
++bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
+bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
+#else
+static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
++static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
+static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
+#endif
+
@@ -35333,10 +59110,10 @@ index 269437b013280..7e73ac6fb21db 100644
uint64_t addr, struct amdgpu_bo **bo,
struct amdgpu_bo_va_mapping **mapping);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
-index 4811b0faafd9a..0e12315fa0cb8 100644
+index 4811b0faafd9a..98ac53ee6bb55 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
-@@ -1031,6 +1031,20 @@ void amdgpu_acpi_detect(void)
+@@ -1031,6 +1031,34 @@ void amdgpu_acpi_detect(void)
}
}
@@ -35354,10 +59131,24 @@ index 4811b0faafd9a..0e12315fa0cb8 100644
+ (pm_suspend_target_state == PM_SUSPEND_MEM);
+}
+
++/**
++ * amdgpu_acpi_should_gpu_reset
++ *
++ * @adev: amdgpu_device_pointer
++ *
++ * returns true if should reset GPU, false if not
++ */
++bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
++{
++ if (adev->flags & AMD_IS_APU)
++ return false;
++ return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
++}
++
/**
* amdgpu_acpi_is_s0ix_active
*
-@@ -1040,11 +1054,24 @@ void amdgpu_acpi_detect(void)
+@@ -1040,11 +1068,24 @@ void amdgpu_acpi_detect(void)
*/
bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
{
@@ -35446,9 +59237,18 @@ index c905a4cfc173d..044b41f0bfd9c 100644
static inline struct amdgpu_bo_list_entry *
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
-index b9c11c2b2885a..df1f9b88a53f9 100644
+index b9c11c2b2885a..a09876bb7ec8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+@@ -175,7 +175,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
+
+ /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
+ if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
+- if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
++ if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
+ (mode_clock * 5/4 <= max_tmds_clock))
+ bpc = 10;
+ else
@@ -387,6 +387,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
native_mode->vdisplay != 0 &&
native_mode->clock != 0) {
@@ -35477,8 +59277,20 @@ index b9c11c2b2885a..df1f9b88a53f9 100644
return ret;
}
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index 913f9eaa9cd65..aa823f1541992 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1508,6 +1508,7 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
+ return 0;
+
+ default:
++ dma_fence_put(fence);
+ return -EINVAL;
+ }
+ }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
-index 463b9c0283f7e..ec30d81586a79 100644
+index 463b9c0283f7e..348629ea0e153 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -27,7 +27,6 @@
@@ -35575,7 +59387,36 @@ index 463b9c0283f7e..ec30d81586a79 100644
/**
* amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
-@@ -1588,7 +1509,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
+@@ -1255,7 +1176,7 @@ static int amdgpu_debugfs_evict_vram(void *data, u64 *val)
+ return r;
+ }
+
+- *val = amdgpu_bo_evict_vram(adev);
++ *val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
+
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
+@@ -1268,17 +1189,15 @@ static int amdgpu_debugfs_evict_gtt(void *data, u64 *val)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ struct drm_device *dev = adev_to_drm(adev);
+- struct ttm_resource_manager *man;
+ int r;
+
+ r = pm_runtime_get_sync(dev->dev);
+ if (r < 0) {
+- pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
++ pm_runtime_put_autosuspend(dev->dev);
+ return r;
+ }
+
+- man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
+- *val = ttm_resource_manager_evict_all(&adev->mman.bdev, man);
++ *val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT);
+
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
+@@ -1588,7 +1507,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
}
amdgpu_ras_debugfs_create_all(adev);
@@ -35604,10 +59445,46 @@ index 141a8474e24f2..8b641f40fdf66 100644
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
-int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
-index af9bdf16eefd4..1545884dc703e 100644
+index af9bdf16eefd4..a926b5ebbfdf5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
-@@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
+@@ -30,6 +30,7 @@
+ #include <linux/module.h>
+ #include <linux/console.h>
+ #include <linux/slab.h>
++#include <linux/pci.h>
+
+ #include <drm/drm_atomic_helper.h>
+ #include <drm/drm_probe_helper.h>
+@@ -2069,6 +2070,8 @@ out:
+ */
+ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
+ {
++ struct drm_device *dev = adev_to_drm(adev);
++ struct pci_dev *parent;
+ int i, r;
+
+ amdgpu_device_enable_virtual_display(adev);
+@@ -2168,6 +2171,18 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
+ return -EINVAL;
+ }
+
++ if (amdgpu_has_atpx() &&
++ (amdgpu_is_atpx_hybrid() ||
++ amdgpu_has_atpx_dgpu_power_cntl()) &&
++ ((adev->flags & AMD_IS_APU) == 0) &&
++ !pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
++ adev->flags |= AMD_IS_PX;
++
++ if (!(adev->flags & AMD_IS_APU)) {
++ parent = pci_upstream_bridge(adev->pdev);
++ adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
++ }
++
+ amdgpu_amdkfd_device_probe(adev);
+
+ adev->pm.pp_feature = amdgpu_pp_feature_mask;
+@@ -2394,6 +2409,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (r)
goto init_failed;
@@ -35618,7 +59495,7 @@ index af9bdf16eefd4..1545884dc703e 100644
r = amdgpu_device_ip_hw_init_phase1(adev);
if (r)
goto init_failed;
-@@ -2432,10 +2436,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
+@@ -2432,10 +2451,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (!adev->gmc.xgmi.pending_reset)
amdgpu_amdkfd_device_init(adev);
@@ -35629,7 +59506,7 @@ index af9bdf16eefd4..1545884dc703e 100644
amdgpu_fru_get_product_info(adev);
init_failed:
-@@ -2745,6 +2745,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
+@@ -2745,6 +2760,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = false;
}
@@ -35641,7 +59518,7 @@ index af9bdf16eefd4..1545884dc703e 100644
return 0;
}
-@@ -2805,10 +2810,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
+@@ -2805,10 +2825,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
amdgpu_ras_fini(adev);
@@ -35652,7 +59529,7 @@ index af9bdf16eefd4..1545884dc703e 100644
return 0;
}
-@@ -3531,6 +3532,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
+@@ -3531,6 +3547,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->rmmio_size = pci_resource_len(adev->pdev, 2);
}
@@ -35662,7 +59539,7 @@ index af9bdf16eefd4..1545884dc703e 100644
adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
if (adev->rmmio == NULL) {
return -ENOMEM;
-@@ -3850,7 +3854,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
+@@ -3850,7 +3869,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
/* disable all interrupts */
amdgpu_irq_disable_all(adev);
if (adev->mode_info.mode_config_initialized){
@@ -35671,7 +59548,7 @@ index af9bdf16eefd4..1545884dc703e 100644
drm_helper_force_disable_all(adev_to_drm(adev));
else
drm_atomic_helper_shutdown(adev_to_drm(adev));
-@@ -3876,8 +3880,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
+@@ -3876,8 +3895,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
{
@@ -35681,7 +59558,56 @@ index af9bdf16eefd4..1545884dc703e 100644
release_firmware(adev->firmware.gpu_info_fw);
adev->firmware.gpu_info_fw = NULL;
adev->accel_working = false;
-@@ -4466,10 +4470,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
+@@ -3909,6 +3928,25 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
+
+ }
+
++/**
++ * amdgpu_device_evict_resources - evict device resources
++ * @adev: amdgpu device object
++ *
++ * Evicts all ttm device resources(vram BOs, gart table) from the lru list
++ * of the vram memory type. Mainly used for evicting device resources
++ * at suspend time.
++ *
++ */
++static void amdgpu_device_evict_resources(struct amdgpu_device *adev)
++{
++ /* No need to evict vram on APUs for suspend to ram or s2idle */
++ if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU))
++ return;
++
++ if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM))
++ DRM_WARN("evicting device resources failed\n");
++
++}
+
+ /*
+ * Suspend & resume.
+@@ -3949,17 +3987,16 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
+ if (!adev->in_s0ix)
+ amdgpu_amdkfd_suspend(adev, adev->in_runpm);
+
+- /* evict vram memory */
+- amdgpu_bo_evict_vram(adev);
++ /* First evict vram memory */
++ amdgpu_device_evict_resources(adev);
+
+ amdgpu_fence_driver_hw_fini(adev);
+
+ amdgpu_device_ip_suspend_phase2(adev);
+- /* evict remaining vram memory
+- * This second call to evict vram is to evict the gart page table
+- * using the CPU.
++ /* This second call to evict device resources is to evict
++ * the gart page table using the CPU.
+ */
+- amdgpu_bo_evict_vram(adev);
++ amdgpu_device_evict_resources(adev);
+
+ return 0;
+ }
+@@ -4466,10 +4503,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
if (reset_context->reset_req_dev == adev)
job = reset_context->job;
@@ -35692,7 +59618,7 @@ index af9bdf16eefd4..1545884dc703e 100644
if (amdgpu_sriov_vf(adev)) {
/* stop the data exchange thread */
amdgpu_virt_fini_data_exchange(adev);
-@@ -5130,7 +5130,7 @@ skip_hw_reset:
+@@ -5130,7 +5163,7 @@ skip_hw_reset:
drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res);
}
@@ -35701,6 +59627,24 @@ index af9bdf16eefd4..1545884dc703e 100644
drm_helper_resume_force_mode(adev_to_drm(tmp_adev));
}
+@@ -5610,7 +5643,7 @@ void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
+ struct amdgpu_ring *ring)
+ {
+ #ifdef CONFIG_X86_64
+- if (adev->flags & AMD_IS_APU)
++ if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
+ return;
+ #endif
+ if (adev->gmc.xgmi.connected_to_cpu)
+@@ -5626,7 +5659,7 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
+ struct amdgpu_ring *ring)
+ {
+ #ifdef CONFIG_X86_64
+- if (adev->flags & AMD_IS_APU)
++ if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
+ return;
+ #endif
+ if (adev->gmc.xgmi.connected_to_cpu)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index ada7bc19118ac..a919f5daacd91 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -35798,6 +59742,19 @@ index ada7bc19118ac..a919f5daacd91 100644
+ }
return 0;
}
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+index dc50c05f23fc2..5c08047adb594 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+@@ -1145,7 +1145,7 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev,
+ if (ret)
+ return ret;
+
+- if (!dev->mode_config.allow_fb_modifiers) {
++ if (!dev->mode_config.allow_fb_modifiers && !adev->enable_virtual_display) {
+ drm_WARN_ONCE(dev, adev->family >= AMDGPU_FAMILY_AI,
+ "GFX9+ requires FB check based on format modifier\n");
+ ret = check_tiling_flags_gfx6(rfb);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index ae6ab93c868b8..7444484a12bf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -35812,7 +59769,7 @@ index ae6ab93c868b8..7444484a12bf8 100644
r = ttm_bo_validate(&bo->tbo, &placement, &ctx);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
-index f18240f873878..5a7fef324c820 100644
+index f18240f873878..129661f728bf2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -38,6 +38,7 @@
@@ -35823,6 +59780,15 @@ index f18240f873878..5a7fef324c820 100644
#include "amdgpu.h"
#include "amdgpu_irq.h"
+@@ -679,7 +680,7 @@ MODULE_PARM_DESC(sched_policy,
+ * Maximum number of processes that HWS can schedule concurrently. The maximum is the
+ * number of VMIDs assigned to the HWS, which is also the default.
+ */
+-int hws_max_conc_proc = 8;
++int hws_max_conc_proc = -1;
+ module_param(hws_max_conc_proc, int, 0444);
+ MODULE_PARM_DESC(hws_max_conc_proc,
+ "Max # processes HWS can execute concurrently when sched_policy=0 (0 = no concurrency, #VMIDs for KFD = Maximum(default))");
@@ -890,6 +891,717 @@ MODULE_PARM_DESC(smu_pptable_id,
"specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
@@ -36630,19 +60596,45 @@ index f18240f873878..5a7fef324c820 100644
return 0;
}
-@@ -1498,7 +2253,10 @@ static int amdgpu_pmops_suspend(struct device *dev)
- adev->in_s3 = true;
- r = amdgpu_device_suspend(drm_dev, true);
- adev->in_s3 = false;
--
-+ if (r)
-+ return r;
-+ if (!adev->in_s0ix)
-+ r = amdgpu_asic_reset(adev);
+@@ -1491,15 +2246,23 @@ static int amdgpu_pmops_suspend(struct device *dev)
+ {
+ struct drm_device *drm_dev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(drm_dev);
+- int r;
+
+ if (amdgpu_acpi_is_s0ix_active(adev))
+ adev->in_s0ix = true;
+- adev->in_s3 = true;
+- r = amdgpu_device_suspend(drm_dev, true);
+- adev->in_s3 = false;
++ else
++ adev->in_s3 = true;
++ return amdgpu_device_suspend(drm_dev, true);
++}
+
+- return r;
++static int amdgpu_pmops_suspend_noirq(struct device *dev)
++{
++ struct drm_device *drm_dev = dev_get_drvdata(dev);
++ struct amdgpu_device *adev = drm_to_adev(drm_dev);
++
++ if (amdgpu_acpi_should_gpu_reset(adev))
++ return amdgpu_asic_reset(adev);
++
++ return 0;
+ }
+
+ static int amdgpu_pmops_resume(struct device *dev)
+@@ -1511,6 +2274,8 @@ static int amdgpu_pmops_resume(struct device *dev)
+ r = amdgpu_device_resume(drm_dev, true);
+ if (amdgpu_acpi_is_s0ix_active(adev))
+ adev->in_s0ix = false;
++ else
++ adev->in_s3 = false;
return r;
}
-@@ -1575,12 +2333,27 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
+@@ -1575,12 +2340,27 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
if (amdgpu_device_supports_px(drm_dev))
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -36670,6 +60662,14 @@ index f18240f873878..5a7fef324c820 100644
if (amdgpu_device_supports_px(drm_dev)) {
/* Only need to handle PCI state in the driver for ATPX
* PCI core handles it for _PR3.
+@@ -1719,6 +2499,7 @@ static const struct dev_pm_ops amdgpu_pm_ops = {
+ .prepare = amdgpu_pmops_prepare,
+ .complete = amdgpu_pmops_complete,
+ .suspend = amdgpu_pmops_suspend,
++ .suspend_noirq = amdgpu_pmops_suspend_noirq,
+ .resume = amdgpu_pmops_resume,
+ .freeze = amdgpu_pmops_freeze,
+ .thaw = amdgpu_pmops_thaw,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 8d682befe0d68..14499f0de32dc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -36709,6 +60709,19 @@ index d6aa032890ee8..a1e63ba4c54a5 100644
drm_dev_exit(idx);
} else {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+index 1916ec84dd71f..e7845df6cad22 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+@@ -266,7 +266,7 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
+ * adev->gfx.mec.num_pipe_per_mec
+ * adev->gfx.mec.num_queue_per_pipe;
+
+- while (queue_bit-- >= 0) {
++ while (--queue_bit >= 0) {
+ if (test_bit(queue_bit, adev->gfx.mec.queue_bitmap))
+ continue;
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
index f3d62e196901a..0c7963dfacad1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
@@ -36743,10 +60756,32 @@ index cc2e0c9cfe0a1..4f3c62adccbde 100644
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
-index 7e45640fbee02..09a2fe8390591 100644
+index 7e45640fbee02..6744427577b36 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
-@@ -206,6 +206,12 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
+@@ -152,21 +152,10 @@ static void amdgpu_get_audio_func(struct amdgpu_device *adev)
+ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
+ {
+ struct drm_device *dev;
+- struct pci_dev *parent;
+ int r, acpi_status;
+
+ dev = adev_to_drm(adev);
+
+- if (amdgpu_has_atpx() &&
+- (amdgpu_is_atpx_hybrid() ||
+- amdgpu_has_atpx_dgpu_power_cntl()) &&
+- ((flags & AMD_IS_APU) == 0) &&
+- !pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
+- flags |= AMD_IS_PX;
+-
+- parent = pci_upstream_bridge(adev->pdev);
+- adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
+-
+ /* amdgpu_device_init should report only fatal error
+ * like memory allocation failure or iomapping failure,
+ * or memory manager initialization failure, it must
+@@ -206,6 +195,12 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
adev->runpm = true;
break;
}
@@ -36759,6 +60794,62 @@ index 7e45640fbee02..09a2fe8390591 100644
if (adev->runpm)
dev_info(adev->dev, "Using BACO for runtime pm\n");
}
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 01a78c7865367..41d0b3a7b65d8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -1038,29 +1038,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo)
+ }
+ }
+
+-/**
+- * amdgpu_bo_evict_vram - evict VRAM buffers
+- * @adev: amdgpu device object
+- *
+- * Evicts all VRAM buffers on the lru list of the memory type.
+- * Mainly used for evicting vram at suspend time.
+- *
+- * Returns:
+- * 0 for success or a negative error code on failure.
+- */
+-int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
+-{
+- struct ttm_resource_manager *man;
+-
+- if (adev->in_s3 && (adev->flags & AMD_IS_APU)) {
+- /* No need to evict vram on APUs for suspend to ram */
+- return 0;
+- }
+-
+- man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
+- return ttm_resource_manager_evict_all(&adev->mman.bdev, man);
+-}
+-
+ static const char *amdgpu_vram_names[] = {
+ "UNKNOWN",
+ "GDDR1",
+@@ -1343,7 +1320,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
+ !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE))
+ return;
+
+- dma_resv_lock(bo->base.resv, NULL);
++ if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
++ return;
+
+ r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence);
+ if (!WARN_ON(r)) {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+index 9d6c001c15f89..d8ef8a53a562d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+@@ -304,7 +304,6 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain);
+ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
+ u64 min_offset, u64 max_offset);
+ void amdgpu_bo_unpin(struct amdgpu_bo *bo);
+-int amdgpu_bo_evict_vram(struct amdgpu_device *adev);
+ int amdgpu_bo_init(struct amdgpu_device *adev);
+ void amdgpu_bo_fini(struct amdgpu_device *adev);
+ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 9b41cb8c3de54..86e2090bbd6e0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -36781,7 +60872,7 @@ index 9b41cb8c3de54..86e2090bbd6e0 100644
* For ASICs with DF Cstate management centralized
* to PMFW, TMR setup should be performed after PMFW
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
-index 94126dc396888..8132f66177c27 100644
+index 94126dc396888..51c76d6322c94 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1892,7 +1892,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
@@ -36793,6 +60884,77 @@ index 94126dc396888..8132f66177c27 100644
DRM_ERROR("Trying to move memory with ring turned off.\n");
return -EINVAL;
}
+@@ -2036,6 +2036,36 @@ error_free:
+ return r;
+ }
+
++/**
++ * amdgpu_ttm_evict_resources - evict memory buffers
++ * @adev: amdgpu device object
++ * @mem_type: evicted BO's memory type
++ *
++ * Evicts all @mem_type buffers on the lru list of the memory type.
++ *
++ * Returns:
++ * 0 for success or a negative error code on failure.
++ */
++int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type)
++{
++ struct ttm_resource_manager *man;
++
++ switch (mem_type) {
++ case TTM_PL_VRAM:
++ case TTM_PL_TT:
++ case AMDGPU_PL_GWS:
++ case AMDGPU_PL_GDS:
++ case AMDGPU_PL_OA:
++ man = ttm_manager_type(&adev->mman.bdev, mem_type);
++ break;
++ default:
++ DRM_ERROR("Trying to evict invalid memory type\n");
++ return -EINVAL;
++ }
++
++ return ttm_resource_manager_evict_all(&adev->mman.bdev, man);
++}
++
+ #if defined(CONFIG_DEBUG_FS)
+
+ static int amdgpu_mm_vram_table_show(struct seq_file *m, void *unused)
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+index 3205fd5200601..639c7b41e30b9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+@@ -190,6 +190,7 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
+ uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem);
+ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
+ struct ttm_resource *mem);
++int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type);
+
+ void amdgpu_ttm_debugfs_init(struct amdgpu_device *adev);
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+index ca058fbcccd43..16787c675f35e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -24,6 +24,7 @@
+ #include <linux/module.h>
+
+ #include <drm/drm_drv.h>
++#include <xen/xen.h>
+
+ #include "amdgpu.h"
+ #include "amdgpu_ras.h"
+@@ -694,7 +695,8 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev)
+ adev->virt.caps |= AMDGPU_SRIOV_CAPS_ENABLE_IOV;
+
+ if (!reg) {
+- if (is_virtual_machine()) /* passthrough mode exclus sriov mod */
++ /* passthrough mode exclus sriov mod */
++ if (is_virtual_machine() && !xen_initial_domain())
+ adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
+ }
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index ce982afeff913..7d58bf410be05 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -36905,7 +61067,7 @@ index 16dbe593cba2e..970d59a21005a 100644
default:
preempt_disable();
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
-index 025184a556ee6..c39e53a41f13a 100644
+index 025184a556ee6..db27fcf87cd04 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -140,6 +140,11 @@ MODULE_FIRMWARE("amdgpu/aldebaran_rlc.bin");
@@ -36920,7 +61082,16 @@ index 025184a556ee6..c39e53a41f13a 100644
enum ta_ras_gfx_subblock {
/*CPC*/
TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0,
-@@ -3056,8 +3061,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
+@@ -1267,6 +1272,8 @@ static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = {
+ { 0x1002, 0x15dd, 0x103c, 0x83e7, 0xd3 },
+ /* GFXOFF is unstable on C6 parts with a VBIOS 113-RAVEN-114 */
+ { 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc6 },
++ /* Apple MacBook Pro (15-inch, 2019) Radeon Pro Vega 20 4 GB */
++ { 0x1002, 0x69af, 0x106b, 0x019a, 0xc0 },
+ { 0, 0, 0, 0, 0 },
+ };
+
+@@ -3056,8 +3063,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
AMD_PG_SUPPORT_CP |
AMD_PG_SUPPORT_GDS |
AMD_PG_SUPPORT_RLC_SMU_HS)) {
@@ -36931,7 +61102,7 @@ index 025184a556ee6..c39e53a41f13a 100644
gfx_v9_0_init_gfx_power_gating(adev);
}
}
-@@ -4228,19 +4233,38 @@ failed_kiq_read:
+@@ -4228,19 +4235,38 @@ failed_kiq_read:
static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
{
@@ -37018,9 +61189,18 @@ index 1a374ec0514a5..9328991e8807f 100644
MTYPE, MTYPE_UC); /* UC, uncached */
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
-index e47104a1f5596..3c01be6610144 100644
+index e47104a1f5596..93a4da4284ede 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+@@ -788,7 +788,7 @@ static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
+ adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
+
+ #ifdef CONFIG_X86_64
+- if (adev->flags & AMD_IS_APU) {
++ if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) {
+ adev->gmc.aper_base = adev->gfxhub.funcs->get_mc_fb_offset(adev);
+ adev->gmc.aper_size = adev->gmc.real_vram_size;
+ }
@@ -1021,10 +1021,14 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
return -EINVAL;
}
@@ -37055,8 +61235,24 @@ index 0e81e03e9b498..0fe714f54cca9 100644
r = gmc_v6_0_init_microcode(adev);
if (r) {
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+index 0a50fdaced7e5..63c47f61d0dfd 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+@@ -381,8 +381,9 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
+ adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
+
+ #ifdef CONFIG_X86_64
+- if (adev->flags & AMD_IS_APU &&
+- adev->gmc.real_vram_size > adev->gmc.aper_size) {
++ if ((adev->flags & AMD_IS_APU) &&
++ adev->gmc.real_vram_size > adev->gmc.aper_size &&
++ !amdgpu_passthrough(adev)) {
+ adev->gmc.aper_base = ((u64)RREG32(mmMC_VM_FB_OFFSET)) << 22;
+ adev->gmc.aper_size = adev->gmc.real_vram_size;
+ }
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
-index 492ebed2915be..63b890f1e8afb 100644
+index 492ebed2915be..bef9610084f10 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -515,10 +515,10 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev)
@@ -37089,8 +61285,17 @@ index 492ebed2915be..63b890f1e8afb 100644
if (!(adev->flags & AMD_IS_APU)) {
r = amdgpu_device_resize_fb_bar(adev);
+@@ -574,7 +581,7 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
+ adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
+
+ #ifdef CONFIG_X86_64
+- if (adev->flags & AMD_IS_APU) {
++ if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) {
+ adev->gmc.aper_base = ((u64)RREG32(mmMC_VM_FB_OFFSET)) << 22;
+ adev->gmc.aper_size = adev->gmc.real_vram_size;
+ }
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
-index 5551359d5dfdc..c67e212443429 100644
+index 5551359d5dfdc..0e731016921be 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -72,6 +72,9 @@
@@ -37135,6 +61340,24 @@ index 5551359d5dfdc..c67e212443429 100644
case CHIP_VEGA10:
case CHIP_VEGA12:
case CHIP_VEGA20:
+@@ -1375,7 +1387,7 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
+ */
+
+ /* check whether both host-gpu and gpu-gpu xgmi links exist */
+- if ((adev->flags & AMD_IS_APU) ||
++ if (((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) ||
+ (adev->gmc.xgmi.supported &&
+ adev->gmc.xgmi.connected_to_cpu)) {
+ adev->gmc.aper_base =
+@@ -1640,7 +1652,7 @@ static int gmc_v9_0_sw_fini(void *handle)
+ amdgpu_gem_force_release(adev);
+ amdgpu_vm_manager_fini(adev);
+ amdgpu_gart_table_vram_free(adev);
+- amdgpu_bo_unref(&adev->gmc.pdb0_bo);
++ amdgpu_bo_free_kernel(&adev->gmc.pdb0_bo, NULL, &adev->gmc.ptr_pdb0);
+ amdgpu_bo_fini(adev);
+
+ return 0;
@@ -1708,10 +1720,14 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
return -EINVAL;
}
@@ -37717,6 +61940,33 @@ index e0c0c3734432e..a0956d8623770 100644
if (amdgpu_sriov_vf(adev))
amdgpu_virt_free_mm_table(adev);
+diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+index 3d18aab88b4e2..6e56bef4fdf81 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+@@ -601,8 +601,8 @@ static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)), 0, indirect);
+
+ /* VCN global tiling registers */
+- WREG32_SOC15_DPG_MODE(0, SOC15_DPG_MODE_OFFSET(
+- UVD, 0, mmUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
++ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
++ UVD, inst_idx, mmUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
+ }
+
+ static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+@@ -1508,8 +1508,11 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
+
+ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+ {
++ struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
+ uint32_t tmp;
+
++ vcn_v3_0_pause_dpg_mode(adev, 0, &state);
++
+ /* Wait for power status to be 1 */
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index fe9a7cc8d9eb0..6645ebbd2696c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -37732,8 +61982,26 @@ index fe9a7cc8d9eb0..6645ebbd2696c 100644
if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
dev_info(adev->dev, "BACO reset\n");
r = amdgpu_dpm_baco_reset(adev);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 86afd37b098d6..6688129df240e 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -1807,13 +1807,9 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
+ if (!args->start_addr || !args->size)
+ return -EINVAL;
+
+- mutex_lock(&p->mutex);
+-
+ r = svm_ioctl(p, args->op, args->start_addr, args->size, args->nattr,
+ args->attrs);
+
+- mutex_unlock(&p->mutex);
+-
+ return r;
+ }
+ #else
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
-index cfedfb1e8596c..c33d689f29e8e 100644
+index cfedfb1e8596c..e574aa32a111d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1060,6 +1060,9 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
@@ -37746,11 +62014,39 @@ index cfedfb1e8596c..c33d689f29e8e 100644
props2->node_from = id_to;
props2->node_to = id_from;
props2->kobj = NULL;
+@@ -1560,7 +1563,7 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size)
+ /* Fetch the CRAT table from ACPI */
+ status = acpi_get_table(CRAT_SIGNATURE, 0, &crat_table);
+ if (status == AE_NOT_FOUND) {
+- pr_warn("CRAT table not found\n");
++ pr_info("CRAT table not found\n");
+ return -ENODATA;
+ } else if (ACPI_FAILURE(status)) {
+ const char *err = acpi_format_exception(status);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
-index 4a416231b24c8..88c483f699894 100644
+index 4a416231b24c8..660eb7097cfc0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
-@@ -916,6 +916,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
+@@ -834,15 +834,10 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
+ }
+
+ /* Verify module parameters regarding mapped process number*/
+- if ((hws_max_conc_proc < 0)
+- || (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) {
+- dev_err(kfd_device,
+- "hws_max_conc_proc %d must be between 0 and %d, use %d instead\n",
+- hws_max_conc_proc, kfd->vm_info.vmid_num_kfd,
+- kfd->vm_info.vmid_num_kfd);
++ if (hws_max_conc_proc >= 0)
++ kfd->max_proc_per_quantum = min((u32)hws_max_conc_proc, kfd->vm_info.vmid_num_kfd);
++ else
+ kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
+- } else
+- kfd->max_proc_per_quantum = hws_max_conc_proc;
+
+ /* calculate max size of mqds needed for queues */
+ size = max_num_of_queues_per_device *
+@@ -916,6 +911,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd_double_confirm_iommu_support(kfd);
if (kfd_iommu_device_init(kfd)) {
@@ -37758,7 +62054,7 @@ index 4a416231b24c8..88c483f699894 100644
dev_err(kfd_device, "Error initializing iommuv2\n");
goto device_iommu_error;
}
-@@ -924,6 +925,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
+@@ -924,6 +920,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
svm_migrate_init((struct amdgpu_device *)kfd->kgd);
@@ -37769,9 +62065,134 @@ index 4a416231b24c8..88c483f699894 100644
goto kfd_resume_error;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
-index f8fce9d05f50c..4f2e0cc8a51a8 100644
+index f8fce9d05f50c..442857f3bde77 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -138,19 +138,33 @@ void program_sh_mem_settings(struct device_queue_manager *dqm,
+ }
+
+ static void increment_queue_count(struct device_queue_manager *dqm,
+- enum kfd_queue_type type)
++ struct qcm_process_device *qpd,
++ struct queue *q)
+ {
+ dqm->active_queue_count++;
+- if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ)
++ if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
++ q->properties.type == KFD_QUEUE_TYPE_DIQ)
+ dqm->active_cp_queue_count++;
++
++ if (q->properties.is_gws) {
++ dqm->gws_queue_count++;
++ qpd->mapped_gws_queue = true;
++ }
+ }
+
+ static void decrement_queue_count(struct device_queue_manager *dqm,
+- enum kfd_queue_type type)
++ struct qcm_process_device *qpd,
++ struct queue *q)
+ {
+ dqm->active_queue_count--;
+- if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ)
++ if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
++ q->properties.type == KFD_QUEUE_TYPE_DIQ)
+ dqm->active_cp_queue_count--;
++
++ if (q->properties.is_gws) {
++ dqm->gws_queue_count--;
++ qpd->mapped_gws_queue = false;
++ }
+ }
+
+ static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q)
+@@ -390,7 +404,7 @@ add_queue_to_list:
+ list_add(&q->list, &qpd->queues_list);
+ qpd->queue_count++;
+ if (q->properties.is_active)
+- increment_queue_count(dqm, q->properties.type);
++ increment_queue_count(dqm, qpd, q);
+
+ /*
+ * Unconditionally increment this counter, regardless of the queue's
+@@ -515,13 +529,8 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm,
+ deallocate_vmid(dqm, qpd, q);
+ }
+ qpd->queue_count--;
+- if (q->properties.is_active) {
+- decrement_queue_count(dqm, q->properties.type);
+- if (q->properties.is_gws) {
+- dqm->gws_queue_count--;
+- qpd->mapped_gws_queue = false;
+- }
+- }
++ if (q->properties.is_active)
++ decrement_queue_count(dqm, qpd, q);
+
+ return retval;
+ }
+@@ -613,12 +622,11 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
+ * dqm->active_queue_count to determine whether a new runlist must be
+ * uploaded.
+ */
+- if (q->properties.is_active && !prev_active)
+- increment_queue_count(dqm, q->properties.type);
+- else if (!q->properties.is_active && prev_active)
+- decrement_queue_count(dqm, q->properties.type);
+-
+- if (q->gws && !q->properties.is_gws) {
++ if (q->properties.is_active && !prev_active) {
++ increment_queue_count(dqm, &pdd->qpd, q);
++ } else if (!q->properties.is_active && prev_active) {
++ decrement_queue_count(dqm, &pdd->qpd, q);
++ } else if (q->gws && !q->properties.is_gws) {
+ if (q->properties.is_active) {
+ dqm->gws_queue_count++;
+ pdd->qpd.mapped_gws_queue = true;
+@@ -680,11 +688,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm,
+ mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
+ q->properties.type)];
+ q->properties.is_active = false;
+- decrement_queue_count(dqm, q->properties.type);
+- if (q->properties.is_gws) {
+- dqm->gws_queue_count--;
+- qpd->mapped_gws_queue = false;
+- }
++ decrement_queue_count(dqm, qpd, q);
+
+ if (WARN_ONCE(!dqm->sched_running, "Evict when stopped\n"))
+ continue;
+@@ -730,7 +734,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
+ continue;
+
+ q->properties.is_active = false;
+- decrement_queue_count(dqm, q->properties.type);
++ decrement_queue_count(dqm, qpd, q);
+ }
+ pdd->last_evict_timestamp = get_jiffies_64();
+ retval = execute_queues_cpsch(dqm,
+@@ -801,11 +805,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
+ mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
+ q->properties.type)];
+ q->properties.is_active = true;
+- increment_queue_count(dqm, q->properties.type);
+- if (q->properties.is_gws) {
+- dqm->gws_queue_count++;
+- qpd->mapped_gws_queue = true;
+- }
++ increment_queue_count(dqm, qpd, q);
+
+ if (WARN_ONCE(!dqm->sched_running, "Restore when stopped\n"))
+ continue;
+@@ -863,7 +863,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
+ continue;
+
+ q->properties.is_active = true;
+- increment_queue_count(dqm, q->properties.type);
++ increment_queue_count(dqm, &pdd->qpd, q);
+ }
+ retval = execute_queues_cpsch(dqm,
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
@@ -1225,6 +1225,11 @@ static int stop_cpsch(struct device_queue_manager *dqm)
bool hanging;
@@ -37784,6 +62205,129 @@ index f8fce9d05f50c..4f2e0cc8a51a8 100644
if (!dqm->is_hws_hang)
unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
hanging = dqm->is_hws_hang || dqm->is_resetting;
+@@ -1260,7 +1265,7 @@ static int create_kernel_queue_cpsch(struct device_queue_manager *dqm,
+ dqm->total_queue_count);
+
+ list_add(&kq->list, &qpd->priv_queue_list);
+- increment_queue_count(dqm, kq->queue->properties.type);
++ increment_queue_count(dqm, qpd, kq->queue);
+ qpd->is_debug = true;
+ execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ dqm_unlock(dqm);
+@@ -1274,7 +1279,7 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm,
+ {
+ dqm_lock(dqm);
+ list_del(&kq->list);
+- decrement_queue_count(dqm, kq->queue->properties.type);
++ decrement_queue_count(dqm, qpd, kq->queue);
+ qpd->is_debug = false;
+ execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
+ /*
+@@ -1341,7 +1346,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
+ qpd->queue_count++;
+
+ if (q->properties.is_active) {
+- increment_queue_count(dqm, q->properties.type);
++ increment_queue_count(dqm, qpd, q);
+
+ execute_queues_cpsch(dqm,
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+@@ -1543,15 +1548,11 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
+ list_del(&q->list);
+ qpd->queue_count--;
+ if (q->properties.is_active) {
+- decrement_queue_count(dqm, q->properties.type);
++ decrement_queue_count(dqm, qpd, q);
+ retval = execute_queues_cpsch(dqm,
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ if (retval == -ETIME)
+ qpd->reset_wavefronts = true;
+- if (q->properties.is_gws) {
+- dqm->gws_queue_count--;
+- qpd->mapped_gws_queue = false;
+- }
+ }
+
+ /*
+@@ -1742,7 +1743,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
+ /* Clean all kernel queues */
+ list_for_each_entry_safe(kq, kq_next, &qpd->priv_queue_list, list) {
+ list_del(&kq->list);
+- decrement_queue_count(dqm, kq->queue->properties.type);
++ decrement_queue_count(dqm, qpd, kq->queue);
+ qpd->is_debug = false;
+ dqm->total_queue_count--;
+ filter = KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES;
+@@ -1755,13 +1756,8 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
+ else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
+ deallocate_sdma_queue(dqm, q);
+
+- if (q->properties.is_active) {
+- decrement_queue_count(dqm, q->properties.type);
+- if (q->properties.is_gws) {
+- dqm->gws_queue_count--;
+- qpd->mapped_gws_queue = false;
+- }
+- }
++ if (q->properties.is_active)
++ decrement_queue_count(dqm, qpd, q);
+
+ dqm->total_queue_count--;
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+index 3eea4edee355d..b8bdd796cd911 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+@@ -531,6 +531,8 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
+ event_waiters = kmalloc_array(num_events,
+ sizeof(struct kfd_event_waiter),
+ GFP_KERNEL);
++ if (!event_waiters)
++ return NULL;
+
+ for (i = 0; (event_waiters) && (i < num_events) ; i++) {
+ init_wait(&event_waiters[i].wait);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+index ed4bc5f844ce7..766b3660c8c86 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+@@ -270,15 +270,6 @@ int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd)
+ return ret;
+ }
+
+- ret = anon_inode_getfd(kfd_smi_name, &kfd_smi_ev_fops, (void *)client,
+- O_RDWR);
+- if (ret < 0) {
+- kfifo_free(&client->fifo);
+- kfree(client);
+- return ret;
+- }
+- *fd = ret;
+-
+ init_waitqueue_head(&client->wait_queue);
+ spin_lock_init(&client->lock);
+ client->events = 0;
+@@ -288,5 +279,20 @@ int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd)
+ list_add_rcu(&client->list, &dev->smi_clients);
+ spin_unlock(&dev->smi_lock);
+
++ ret = anon_inode_getfd(kfd_smi_name, &kfd_smi_ev_fops, (void *)client,
++ O_RDWR);
++ if (ret < 0) {
++ spin_lock(&dev->smi_lock);
++ list_del_rcu(&client->list);
++ spin_unlock(&dev->smi_lock);
++
++ synchronize_rcu();
++
++ kfifo_free(&client->fifo);
++ kfree(client);
++ return ret;
++ }
++ *fd = ret;
++
+ return 0;
+ }
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 9d0f65a90002d..830809b694dd9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -38072,7 +62616,7 @@ index 9d0f65a90002d..830809b694dd9 100644
&p->svms, start, start + size - 1, r);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-index 1ea31dcc7a8b0..cd611444ad177 100644
+index 1ea31dcc7a8b0..ec75613618b19 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1141,8 +1141,15 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
@@ -38124,7 +62668,17 @@ index 1ea31dcc7a8b0..cd611444ad177 100644
/* Before powering on DC we need to re-initialize DMUB. */
r = dm_dmub_hw_init(adev);
if (r)
-@@ -3213,7 +3227,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
+@@ -2282,7 +2296,8 @@ static int dm_resume(void *handle)
+ * this is the case when traversing through already created
+ * MST connectors, should be skipped
+ */
+- if (aconnector->mst_port)
++ if (aconnector->dc_link &&
++ aconnector->dc_link->type == dc_connection_mst_branch)
+ continue;
+
+ mutex_lock(&aconnector->hpd_lock);
+@@ -3213,7 +3228,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
/* Use GRPH_PFLIP interrupt */
for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT;
@@ -38133,7 +62687,26 @@ index 1ea31dcc7a8b0..cd611444ad177 100644
i++) {
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->pageflip_irq);
if (r) {
-@@ -3798,6 +3812,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+@@ -3508,7 +3523,7 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
+ max - min);
+ }
+
+-static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
++static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+ int bl_idx,
+ u32 user_brightness)
+ {
+@@ -3536,7 +3551,8 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+ DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
+ }
+
+- return rc ? 0 : 1;
++ if (rc)
++ dm->actual_brightness[bl_idx] = user_brightness;
+ }
+
+ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+@@ -3798,6 +3814,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
#endif
@@ -38143,7 +62716,7 @@ index 1ea31dcc7a8b0..cd611444ad177 100644
/* loops over all connectors on the board */
for (i = 0; i < link_cnt; i++) {
struct dc_link *link = NULL;
-@@ -3839,8 +3856,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+@@ -3839,8 +3858,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link);
@@ -38161,7 +62734,7 @@ index 1ea31dcc7a8b0..cd611444ad177 100644
}
-@@ -5587,6 +5613,7 @@ static void update_dsc_caps(struct amdgpu_dm_connector *aconnector,
+@@ -5587,6 +5615,7 @@ static void update_dsc_caps(struct amdgpu_dm_connector *aconnector,
struct dsc_dec_dpcd_caps *dsc_caps)
{
stream->timing.flags.DSC = 0;
@@ -38169,6 +62742,58 @@ index 1ea31dcc7a8b0..cd611444ad177 100644
if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
+@@ -7527,6 +7556,9 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
+ mode = amdgpu_dm_create_common_mode(encoder,
+ common_modes[i].name, common_modes[i].w,
+ common_modes[i].h);
++ if (!mode)
++ continue;
++
+ drm_mode_probed_add(connector, mode);
+ amdgpu_dm_connector->num_modes++;
+ }
+@@ -9286,7 +9318,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
+ /* restore the backlight level */
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (dm->backlight_dev[i] &&
+- (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
++ (dm->actual_brightness[i] != dm->brightness[i]))
+ amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+ }
+ #endif
+@@ -10196,10 +10228,13 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
+ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
+ {
+ struct drm_connector *connector;
+- struct drm_connector_state *conn_state;
++ struct drm_connector_state *conn_state, *old_conn_state;
+ struct amdgpu_dm_connector *aconnector = NULL;
+ int i;
+- for_each_new_connector_in_state(state, connector, conn_state, i) {
++ for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
++ if (!conn_state->crtc)
++ conn_state = old_conn_state;
++
+ if (conn_state->crtc != crtc)
+ continue;
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+index d1d353a7c77d3..46d6e65f6bd48 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -446,6 +446,12 @@ struct amdgpu_display_manager {
+ * cached backlight values.
+ */
+ u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
++ /**
++ * @actual_brightness:
++ *
++ * last successfully applied backlight values.
++ */
++ u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
+ };
+
+ enum dsc_clock_force_state {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index cce062adc4391..8a441a22c46ec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -38189,10 +62814,22 @@ index cce062adc4391..8a441a22c46ec 100644
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-index 8080bba5b7a76..e94ddd5e7b638 100644
+index 8080bba5b7a76..5c9f5214bc4e9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-@@ -247,6 +247,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
+@@ -229,8 +229,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -247,6 +249,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
{
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
struct dc_link *link = connector->dc_link;
@@ -38200,7 +62837,7 @@ index 8080bba5b7a76..e94ddd5e7b638 100644
struct dc_link_settings prefer_link_settings;
char *wr_buf = NULL;
const uint32_t wr_buf_size = 40;
-@@ -313,7 +314,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
+@@ -313,7 +316,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
prefer_link_settings.lane_count = param[0];
prefer_link_settings.link_rate = param[1];
@@ -38209,7 +62846,211 @@ index 8080bba5b7a76..e94ddd5e7b638 100644
kfree(wr_buf);
return size;
-@@ -2907,10 +2908,13 @@ static int crc_win_update_set(void *data, u64 val)
+@@ -387,8 +390,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user((*(rd_buf + result)), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -1315,8 +1320,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -1332,8 +1339,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -1502,8 +1511,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -1519,8 +1530,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -1687,8 +1700,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -1704,8 +1719,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -1868,8 +1885,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -1885,8 +1904,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -2044,8 +2065,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -2061,8 +2084,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -2101,8 +2126,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -2118,8 +2145,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -2173,8 +2202,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -2190,8 +2221,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -2245,8 +2278,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
+ break;
+ }
+
+- if (!pipe_ctx)
++ if (!pipe_ctx) {
++ kfree(rd_buf);
+ return -ENXIO;
++ }
+
+ dsc = pipe_ctx->stream_res.dsc;
+ if (dsc)
+@@ -2262,8 +2297,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
+ break;
+
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+
+ buf += 1;
+ size -= 1;
+@@ -2907,10 +2944,13 @@ static int crc_win_update_set(void *data, u64 val)
struct amdgpu_device *adev = drm_to_adev(new_crtc->dev);
struct crc_rd_work *crc_rd_wrk = adev->dm.crc_rd_wrk;
@@ -38224,6 +63065,30 @@ index 8080bba5b7a76..e94ddd5e7b638 100644
old_crtc = crc_rd_wrk->crtc;
old_acrtc = to_amdgpu_crtc(old_crtc);
}
+@@ -3250,8 +3290,10 @@ static ssize_t dcc_en_bits_read(
+ dc->hwss.get_dcc_en_bits(dc, dcc_en_bits);
+
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
+- if (!rd_buf)
++ if (!rd_buf) {
++ kfree(dcc_en_bits);
+ return -ENOMEM;
++ }
+
+ for (i = 0; i < num_pipes; i++)
+ offset += snprintf(rd_buf + offset, rd_buf_size - offset,
+@@ -3264,8 +3306,10 @@ static ssize_t dcc_en_bits_read(
+ if (*pos >= rd_buf_size)
+ break;
+ r = put_user(*(rd_buf + result), buf);
+- if (r)
++ if (r) {
++ kfree(rd_buf);
+ return r; /* r = -EFAULT */
++ }
+ buf += 1;
+ size -= 1;
+ *pos += 1;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 6fee12c91ef59..d793eec69d61e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -38330,6 +63195,23 @@ index 7af0d58c231b6..74885ff77f96a 100644
if (!aconnector->dsc_aux)
return false;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+index 70a554f1e725a..7072fb2ec07fa 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+@@ -74,10 +74,8 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
+
+ link = stream->link;
+
+- psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version;
+-
+- if (psr_config.psr_version > 0) {
+- psr_config.psr_exit_link_training_required = 0x1;
++ if (link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) {
++ psr_config.psr_version = link->psr_settings.psr_version;
+ psr_config.psr_frame_capture_indication_req = 0;
+ psr_config.psr_rfb_setup_time = 0x37;
+ psr_config.psr_sdp_transmit_line_num_deadline = 0x20;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index bb31541f80723..6420527fe476c 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -38547,9 +63429,18 @@ index 1e44b13c1c7de..3c4205248efc2 100644
&old_downspread.raw, sizeof(old_downspread));
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
-index 6d655e158267a..605b96873d8cd 100644
+index 6d655e158267a..05f81d44aa6c2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+@@ -3118,7 +3118,7 @@ static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video
+ &dpcd_pattern_type.value,
+ sizeof(dpcd_pattern_type));
+
+- channel_count = dpcd_test_mode.bits.channel_count + 1;
++ channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
+
+ // read pattern periods for requested channels when sawTooth pattern is requested
+ if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
@@ -3650,7 +3650,9 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
lttpr_dpcd_data,
sizeof(lttpr_dpcd_data));
@@ -38598,21 +63489,31 @@ index 6d655e158267a..605b96873d8cd 100644
dm_error("dpcd write failed to set fec_ready");
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
-index a60396d5be445..7ae409f7dcf8d 100644
+index a60396d5be445..82f1f27baaf38 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
-@@ -1623,6 +1623,10 @@ bool dc_is_stream_unchanged(
+@@ -1599,6 +1599,9 @@ static bool are_stream_backends_same(
+ if (is_timing_changed(stream_a, stream_b))
+ return false;
+
++ if (stream_a->signal != stream_b->signal)
++ return false;
++
+ if (stream_a->dpms_off != stream_b->dpms_off)
+ return false;
+
+@@ -1623,6 +1626,10 @@ bool dc_is_stream_unchanged(
if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
return false;
-+ // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks
-+ if (old_stream->audio_info.mode_count != stream->audio_info.mode_count)
++ /*compare audio info*/
++ if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0)
+ return false;
+
return true;
}
-@@ -1795,9 +1799,6 @@ enum dc_status dc_remove_stream_from_ctx(
+@@ -1795,9 +1802,6 @@ enum dc_status dc_remove_stream_from_ctx(
dc->res_pool,
del_pipe->stream_res.stream_enc,
false);
@@ -38634,11 +63535,68 @@ index 3ab52d9a82cf6..e0f58fab5e8ed 100644
};
struct dc_bug_wa {
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+index f4f423d0b8c3f..80595d7f060c3 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+@@ -940,6 +940,7 @@ static const struct hubbub_funcs hubbub1_funcs = {
+ .program_watermarks = hubbub1_program_watermarks,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
++ .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
+ };
+
+ void hubbub1_construct(struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
-index df8a7718a85fc..3af49cdf89ebd 100644
+index df8a7718a85fc..93f31e4aeecb3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
-@@ -1522,7 +1522,7 @@ void dcn10_power_down_on_boot(struct dc *dc)
+@@ -1052,9 +1052,13 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc)
+
+ void dcn10_verify_allow_pstate_change_high(struct dc *dc)
+ {
++ struct hubbub *hubbub = dc->res_pool->hubbub;
+ static bool should_log_hw_state; /* prevent hw state log by default */
+
+- if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
++ if (!hubbub->funcs->verify_allow_pstate_change_high)
++ return;
++
++ if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) {
+ int i = 0;
+
+ if (should_log_hw_state)
+@@ -1063,8 +1067,8 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc)
+ TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
+ BREAK_TO_DEBUGGER();
+ if (dcn10_hw_wa_force_recovery(dc)) {
+- /*check again*/
+- if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
++ /*check again*/
++ if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub))
+ BREAK_TO_DEBUGGER();
+ }
+ }
+@@ -1435,6 +1439,9 @@ void dcn10_init_hw(struct dc *dc)
+ }
+ }
+
++ if (hws->funcs.enable_power_gating_plane)
++ hws->funcs.enable_power_gating_plane(dc->hwseq, true);
++
+ /* If taking control over from VBIOS, we may want to optimize our first
+ * mode set, so we need to skip powering down pipes until we know which
+ * pipes we want to use.
+@@ -1487,8 +1494,6 @@ void dcn10_init_hw(struct dc *dc)
+
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+- if (hws->funcs.enable_power_gating_plane)
+- hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+
+ if (dc->clk_mgr->funcs->notify_wm_ranges)
+ dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+@@ -1522,7 +1527,7 @@ void dcn10_power_down_on_boot(struct dc *dc)
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
@@ -38647,6 +63605,30 @@ index df8a7718a85fc..3af49cdf89ebd 100644
link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
dc->hwss.power_down) {
dc->hwss.power_down(dc);
+@@ -2455,14 +2460,18 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ struct mpc *mpc = dc->res_pool->mpc;
+ struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
+
+- if (per_pixel_alpha)
+- blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+- else
+- blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+-
+ blnd_cfg.overlap_only = false;
+ blnd_cfg.global_gain = 0xff;
+
++ if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
++ blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
++ } else if (per_pixel_alpha) {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
++ } else {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
++ }
++
+ if (pipe_ctx->plane_state->global_alpha)
+ blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
+ else
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
index 34001a30d449a..10e613ec7d24f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
@@ -38659,6 +63641,34 @@ index 34001a30d449a..10e613ec7d24f 100644
.set_backlight_level = dce110_set_backlight_level,
.set_abm_immediate_disable = dce110_set_abm_immediate_disable,
.set_pipe = dce110_set_pipe,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+index a47ba1d45be92..9f8d7f92300bb 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+@@ -2297,14 +2297,18 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ struct mpc *mpc = dc->res_pool->mpc;
+ struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
+
+- if (per_pixel_alpha)
+- blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+- else
+- blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+-
+ blnd_cfg.overlap_only = false;
+ blnd_cfg.global_gain = 0xff;
+
++ if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
++ blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
++ } else if (per_pixel_alpha) {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
++ } else {
++ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
++ }
++
+ if (pipe_ctx->plane_state->global_alpha)
+ blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
+ else
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index e3e01b17c164e..ede11eb120d4f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -38732,23 +63742,53 @@ index e3e01b17c164e..ede11eb120d4f 100644
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
-index fbbdf99761838..92a308ad1213c 100644
+index fbbdf99761838..5b8274b8c3845 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
-@@ -874,7 +874,7 @@ static const struct dc_debug_options debug_defaults_drv = {
- .clock_trace = true,
- .disable_pplib_clock_request = true,
- .min_disp_clk_khz = 100000,
-- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
-+ .pipe_split_policy = MPC_SPLIT_DYNAMIC,
- .force_single_disp_pipe_split = false,
- .disable_dcc = DCC_ENABLE,
- .vsr_support = true,
+@@ -1428,6 +1428,7 @@ static struct clock_source *dcn21_clock_source_create(
+ return &clk_src->base;
+ }
+
++ kfree(clk_src);
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
+index f4414de96acc5..152c9c5733f1c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
+@@ -448,6 +448,7 @@ static const struct hubbub_funcs hubbub30_funcs = {
+ .program_watermarks = hubbub3_program_watermarks,
+ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
++ .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
+ .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
+ .force_pstate_change_control = hubbub3_force_pstate_change_control,
+ .init_watermarks = hubbub3_init_watermarks,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
-index fafed1e4a998d..0950784bafa49 100644
+index fafed1e4a998d..f834573758113 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
-@@ -1002,7 +1002,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
+@@ -570,6 +570,9 @@ void dcn30_init_hw(struct dc *dc)
+ }
+ }
+
++ if (hws->funcs.enable_power_gating_plane)
++ hws->funcs.enable_power_gating_plane(dc->hwseq, true);
++
+ /* If taking control over from VBIOS, we may want to optimize our first
+ * mode set, so we need to skip powering down pipes until we know which
+ * pipes we want to use.
+@@ -647,8 +650,6 @@ void dcn30_init_hw(struct dc *dc)
+
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+- if (hws->funcs.enable_power_gating_plane)
+- hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+
+ if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+ dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+@@ -1002,7 +1003,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
/* turning off DPG */
pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false);
for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
@@ -38797,6 +63837,18 @@ index a0de309475a97..0294d0cc47595 100644
if (pipe_cnt == 0)
goto validate_out;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
+index 1e3bd2e9cdcc4..a046664e20316 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
+@@ -60,6 +60,7 @@ static const struct hubbub_funcs hubbub301_funcs = {
+ .program_watermarks = hubbub3_program_watermarks,
+ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
++ .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
+ .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
+ .force_pstate_change_control = hubbub3_force_pstate_change_control,
+ .hubbub_read_state = hubbub2_read_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
index 912285fdce18e..dea358b01791c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -38945,10 +63997,18 @@ index dd38796ba30ad..589ddab61c2a9 100644
.disable_dcc = DCC_ENABLE,
.vsr_support = true,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
-index 90c73a1cb9861..5e3bcaf12cac4 100644
+index 90c73a1cb9861..208d2dc8b1d1a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
-@@ -138,8 +138,11 @@ static uint32_t convert_and_clamp(
+@@ -24,6 +24,7 @@
+ */
+
+
++#include <linux/delay.h>
+ #include "dcn30/dcn30_hubbub.h"
+ #include "dcn31_hubbub.h"
+ #include "dm_services.h"
+@@ -138,8 +139,11 @@ static uint32_t convert_and_clamp(
ret_val = wm_ns * refclk_mhz;
ret_val /= 1000;
@@ -38961,7 +64021,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
return ret_val;
}
-@@ -159,7 +162,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -159,7 +163,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) {
hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
@@ -38970,7 +64030,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
-@@ -193,7 +196,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -193,7 +197,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) {
hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
@@ -38979,7 +64039,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
} else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns)
-@@ -203,7 +206,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -203,7 +207,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) {
hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
@@ -38988,7 +64048,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
-@@ -237,7 +240,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -237,7 +241,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) {
hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
@@ -38997,7 +64057,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
} else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns)
-@@ -247,7 +250,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -247,7 +251,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) {
hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
@@ -39006,7 +64066,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
-@@ -281,7 +284,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -281,7 +285,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) {
hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;
prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,
@@ -39015,7 +64075,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);
} else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns)
-@@ -291,7 +294,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -291,7 +295,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) {
hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
@@ -39024,7 +64084,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
-@@ -325,7 +328,7 @@ static bool hubbub31_program_urgent_watermarks(
+@@ -325,7 +329,7 @@ static bool hubbub31_program_urgent_watermarks(
if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) {
hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
@@ -39033,7 +64093,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
} else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns)
-@@ -351,7 +354,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -351,7 +355,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -39042,7 +64102,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
-@@ -367,7 +370,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -367,7 +371,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_exit_ns,
@@ -39051,7 +64111,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
-@@ -383,7 +386,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -383,7 +387,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns,
@@ -39060,7 +64120,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"
-@@ -399,7 +402,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -399,7 +403,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_exit_z8_ns,
@@ -39069,7 +64129,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"
-@@ -416,7 +419,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -416,7 +420,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -39078,7 +64138,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
-@@ -432,7 +435,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -432,7 +436,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_exit_ns,
@@ -39087,7 +64147,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
-@@ -448,7 +451,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -448,7 +452,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns,
@@ -39096,7 +64156,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"
-@@ -464,7 +467,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -464,7 +468,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_exit_z8_ns,
@@ -39105,7 +64165,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"
-@@ -481,7 +484,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -481,7 +485,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -39114,7 +64174,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
-@@ -497,7 +500,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -497,7 +501,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_exit_ns,
@@ -39123,7 +64183,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
-@@ -513,7 +516,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -513,7 +517,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns,
@@ -39132,7 +64192,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"
-@@ -529,7 +532,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -529,7 +533,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_exit_z8_ns,
@@ -39141,7 +64201,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"
-@@ -546,7 +549,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -546,7 +550,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -39150,7 +64210,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
-@@ -562,7 +565,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -562,7 +566,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_exit_ns,
@@ -39159,7 +64219,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
-@@ -578,7 +581,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -578,7 +582,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns,
@@ -39168,7 +64228,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"
-@@ -594,7 +597,7 @@ static bool hubbub31_program_stutter_watermarks(
+@@ -594,7 +598,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_exit_z8_ns,
@@ -39177,7 +64237,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"
-@@ -625,7 +628,7 @@ static bool hubbub31_program_pstate_watermarks(
+@@ -625,7 +629,7 @@ static bool hubbub31_program_pstate_watermarks(
watermarks->a.cstate_pstate.pstate_change_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.pstate_change_ns,
@@ -39186,7 +64246,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
-@@ -642,7 +645,7 @@ static bool hubbub31_program_pstate_watermarks(
+@@ -642,7 +646,7 @@ static bool hubbub31_program_pstate_watermarks(
watermarks->b.cstate_pstate.pstate_change_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.pstate_change_ns,
@@ -39195,7 +64255,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
-@@ -659,7 +662,7 @@ static bool hubbub31_program_pstate_watermarks(
+@@ -659,7 +663,7 @@ static bool hubbub31_program_pstate_watermarks(
watermarks->c.cstate_pstate.pstate_change_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.pstate_change_ns,
@@ -39204,7 +64264,7 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
-@@ -676,7 +679,7 @@ static bool hubbub31_program_pstate_watermarks(
+@@ -676,7 +680,7 @@ static bool hubbub31_program_pstate_watermarks(
watermarks->d.cstate_pstate.pstate_change_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.pstate_change_ns,
@@ -39213,6 +64273,111 @@ index 90c73a1cb9861..5e3bcaf12cac4 100644
REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
+@@ -946,6 +950,65 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,
+ }
+ }
+
++static bool hubbub31_verify_allow_pstate_change_high(struct hubbub *hubbub)
++{
++ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
++
++ /*
++ * Pstate latency is ~20us so if we wait over 40us and pstate allow
++ * still not asserted, we are probably stuck and going to hang
++ */
++ const unsigned int pstate_wait_timeout_us = 100;
++ const unsigned int pstate_wait_expected_timeout_us = 40;
++
++ static unsigned int max_sampled_pstate_wait_us; /* data collection */
++ static bool forced_pstate_allow; /* help with revert wa */
++
++ unsigned int debug_data = 0;
++ unsigned int i;
++
++ if (forced_pstate_allow) {
++ /* we hacked to force pstate allow to prevent hang last time
++ * we verify_allow_pstate_change_high. so disable force
++ * here so we can check status
++ */
++ REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
++ DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
++ DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
++ forced_pstate_allow = false;
++ }
++
++ REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub2->debug_test_index_pstate);
++
++ for (i = 0; i < pstate_wait_timeout_us; i++) {
++ debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
++
++ /* Debug bit is specific to ASIC. */
++ if (debug_data & (1 << 26)) {
++ if (i > pstate_wait_expected_timeout_us)
++ DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i);
++ return true;
++ }
++ if (max_sampled_pstate_wait_us < i)
++ max_sampled_pstate_wait_us = i;
++
++ udelay(1);
++ }
++
++ /* force pstate allow to prevent system hang
++ * and break to debugger to investigate
++ */
++ REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
++ DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
++ DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
++ forced_pstate_allow = true;
++
++ DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
++ debug_data);
++
++ return false;
++}
++
+ static const struct hubbub_funcs hubbub31_funcs = {
+ .update_dchub = hubbub2_update_dchub,
+ .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
+@@ -958,6 +1021,7 @@ static const struct hubbub_funcs hubbub31_funcs = {
+ .program_watermarks = hubbub31_program_watermarks,
+ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
++ .verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high,
+ .program_det_size = dcn31_program_det_size,
+ .program_compbuf_size = dcn31_program_compbuf_size,
+ .init_crb = dcn31_init_crb,
+@@ -979,5 +1043,7 @@ void hubbub31_construct(struct dcn20_hubbub *hubbub31,
+ hubbub31->detile_buf_size = det_size_kb * 1024;
+ hubbub31->pixel_chunk_size = pixel_chunk_size_kb * 1024;
+ hubbub31->crb_size_segs = config_return_buffer_size_kb / DCN31_CRB_SEGMENT_SIZE_KB;
++
++ hubbub31->debug_test_index_pstate = 0x6;
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
+index 3afa1159a5f7d..b72d080b302a1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
+@@ -204,6 +204,9 @@ void dcn31_init_hw(struct dc *dc)
+ }
+ }
+
++ if (hws->funcs.enable_power_gating_plane)
++ hws->funcs.enable_power_gating_plane(dc->hwseq, true);
++
+ /* If taking control over from VBIOS, we may want to optimize our first
+ * mode set, so we need to skip powering down pipes until we know which
+ * pipes we want to use.
+@@ -287,8 +290,6 @@ void dcn31_init_hw(struct dc *dc)
+
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+- if (hws->funcs.enable_power_gating_plane)
+- hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+
+ if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+ dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
index 40011cd3c8ef0..4e9fe090b770a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -39227,7 +64392,7 @@ index 40011cd3c8ef0..4e9fe090b770a 100644
};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
-index 79e92ecca96c1..d4fe5352421fc 100644
+index 79e92ecca96c1..a5ef9d5e7685f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -352,6 +352,14 @@ static const struct dce110_clk_src_regs clk_src_regs[] = {
@@ -39264,6 +64429,15 @@ index 79e92ecca96c1..d4fe5352421fc 100644
.force_single_disp_pipe_split = false,
.disable_dcc = DCC_ENABLE,
.vsr_support = true,
+@@ -931,7 +940,7 @@ static const struct dc_debug_options debug_defaults_drv = {
+ .max_downscale_src_width = 4096,/*upto true 4K*/
+ .disable_pplib_wm_range = false,
+ .scl_reset_length10 = true,
+- .sanity_checks = false,
++ .sanity_checks = true,
+ .underflow_assert_delay_us = 0xFFFFFFFF,
+ .dwb_fi_phase = -1, // -1 = disable,
+ .dmub_command_table = true,
@@ -2019,14 +2028,27 @@ static bool dcn31_resource_construct(
dcn30_clock_source_create(ctx, ctx->dc_bios,
CLOCK_SOURCE_COMBO_PHY_PLL1,
@@ -42213,6 +67387,51 @@ index ef830aded5b1c..1e19dd674e5a2 100644
#include <drm/drm_dsc.h>
#include "dscc_types.h"
#include "rc_calc.h"
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+index 713f5558f5e17..9195dec294c2d 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+@@ -154,6 +154,8 @@ struct hubbub_funcs {
+ bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub);
+ void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow);
+
++ bool (*verify_allow_pstate_change_high)(struct hubbub *hubbub);
++
+ void (*apply_DEDCN21_147_wa)(struct hubbub *hubbub);
+
+ void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub);
+diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+index ed54e1c819bed..a728087b3f3d6 100644
+--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
++++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+@@ -266,14 +266,6 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = {
+ .funcs = &pflip_irq_info_funcs\
+ }
+
+-#define vupdate_int_entry(reg_num)\
+- [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+- IRQ_REG_ENTRY(OTG, reg_num,\
+- OTG_GLOBAL_SYNC_STATUS, VUPDATE_INT_EN,\
+- OTG_GLOBAL_SYNC_STATUS, VUPDATE_EVENT_CLEAR),\
+- .funcs = &vblank_irq_info_funcs\
+- }
+-
+ /* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
+ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
+ */
+@@ -402,12 +394,6 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = {
+ dc_underflow_int_entry(6),
+ [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
+ [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
+- vupdate_int_entry(0),
+- vupdate_int_entry(1),
+- vupdate_int_entry(2),
+- vupdate_int_entry(3),
+- vupdate_int_entry(4),
+- vupdate_int_entry(5),
+ vupdate_no_lock_int_entry(0),
+ vupdate_no_lock_int_entry(1),
+ vupdate_no_lock_int_entry(2),
diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h
index 571fcf23cea92..a3a9ea077f505 100644
--- a/drivers/gpu/drm/amd/display/include/logger_types.h
@@ -42227,6 +67446,29 @@ index 571fcf23cea92..a3a9ea077f505 100644
struct dal_logger;
+diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+index 57f198de5e2cb..4e075b01d48bb 100644
+--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+@@ -100,7 +100,8 @@ enum vsc_packet_revision {
+ //PB7 = MD0
+ #define MASK_VTEM_MD0__VRR_EN 0x01
+ #define MASK_VTEM_MD0__M_CONST 0x02
+-#define MASK_VTEM_MD0__RESERVED2 0x0C
++#define MASK_VTEM_MD0__QMS_EN 0x04
++#define MASK_VTEM_MD0__RESERVED2 0x08
+ #define MASK_VTEM_MD0__FVA_FACTOR_M1 0xF0
+
+ //MD1
+@@ -109,7 +110,7 @@ enum vsc_packet_revision {
+ //MD2
+ #define MASK_VTEM_MD2__BASE_REFRESH_RATE_98 0x03
+ #define MASK_VTEM_MD2__RB 0x04
+-#define MASK_VTEM_MD2__RESERVED3 0xF8
++#define MASK_VTEM_MD2__NEXT_TFR 0xF8
+
+ //MD3
+ #define MASK_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index 257f280d3d53f..bd077ea224a40 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
@@ -42302,7 +67544,7 @@ index 7ec4331e67f26..a486769b66c6a 100644
uint32_t signature; /* Table Signature */
uint32_t version; /* Table Version */
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
-index 03581d5b18360..08362d506534b 100644
+index 03581d5b18360..a68496b3f9296 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
@@ -42329,16 +67571,34 @@ index 03581d5b18360..08362d506534b 100644
return ret;
}
+@@ -1035,6 +1045,17 @@ bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
+
+ if (!pp_funcs || !pp_funcs->get_asic_baco_capability)
+ return false;
++ /* Don't use baco for reset in S3.
++ * This is a workaround for some platforms
++ * where entering BACO during suspend
++ * seems to cause reboots or hangs.
++ * This might be related to the fact that BACO controls
++ * power to the whole GPU including devices like audio and USB.
++ * Powering down/up everything may adversely affect these other
++ * devices. Needs more investigation.
++ */
++ if (adev->in_s3)
++ return false;
+
+ if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap))
+ return false;
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
-index 249cb0aeb5ae4..640db5020ccc3 100644
+index 249cb0aeb5ae4..6aaf1230655f4 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -2117,6 +2117,12 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
}
}
-+ /* setting should not be allowed from VF */
-+ if (amdgpu_sriov_vf(adev)) {
++ /* setting should not be allowed from VF if not in one VF mode */
++ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) {
+ dev_attr->attr.mode &= ~S_IWUGO;
+ dev_attr->store = NULL;
+ }
@@ -42383,9 +67643,39 @@ index 98f1b3d8c1d59..16e3f72d31b9f 100644
#define R600_SSTU_DFLT 0
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
-index 1de3ae77e03ed..1f406f21b452f 100644
+index 1de3ae77e03ed..cf74621f94a75 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
+@@ -773,13 +773,13 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetHardMinFclkByFreq,
+ hwmgr->display_config->num_display > 3 ?
+- data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk :
++ (data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk / 100) :
+ min_mclk,
+ NULL);
+
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetHardMinSocclkByFreq,
+- data->clock_vol_info.vdd_dep_on_socclk->entries[0].clk,
++ data->clock_vol_info.vdd_dep_on_socclk->entries[0].clk / 100,
+ NULL);
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetHardMinVcn,
+@@ -792,11 +792,11 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
+ NULL);
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetSoftMaxFclkByFreq,
+- data->clock_vol_info.vdd_dep_on_fclk->entries[index_fclk].clk,
++ data->clock_vol_info.vdd_dep_on_fclk->entries[index_fclk].clk / 100,
+ NULL);
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetSoftMaxSocclkByFreq,
+- data->clock_vol_info.vdd_dep_on_socclk->entries[index_socclk].clk,
++ data->clock_vol_info.vdd_dep_on_socclk->entries[index_socclk].clk / 100,
+ NULL);
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetSoftMaxVcn,
@@ -1036,13 +1036,13 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
else
i = 1;
@@ -42930,26 +68220,19 @@ index 0cf39c1244b1c..85d55ab4e369f 100644
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
-index 04863a7971155..6dc83cfad9d84 100644
+index 04863a7971155..952a8aa69b9ee 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
-@@ -1386,8 +1386,14 @@ static int smu_disable_dpms(struct smu_context *smu)
+@@ -138,7 +138,7 @@ int smu_get_dpm_freq_range(struct smu_context *smu,
+ uint32_t *min,
+ uint32_t *max)
{
- struct amdgpu_device *adev = smu->adev;
- int ret = 0;
-+ /*
-+ * TODO: (adev->in_suspend && !adev->in_s0ix) is added to pair
-+ * the workaround which always reset the asic in suspend.
-+ * It's likely that workaround will be dropped in the future.
-+ * Then the change here should be dropped together.
-+ */
- bool use_baco = !smu->is_apu &&
-- ((amdgpu_in_reset(adev) &&
-+ (((amdgpu_in_reset(adev) || (adev->in_suspend && !adev->in_s0ix)) &&
- (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
- ((adev->in_runpm || adev->in_s4) && amdgpu_asic_supports_baco(adev)));
+- int ret = 0;
++ int ret = -ENOTSUPP;
-@@ -1536,9 +1542,7 @@ static int smu_suspend(void *handle)
+ if (!min && !max)
+ return -EINVAL;
+@@ -1536,9 +1536,7 @@ static int smu_suspend(void *handle)
smu->watermarks_bitmap &= ~(WATERMARKS_LOADED);
@@ -42960,7 +68243,7 @@ index 04863a7971155..6dc83cfad9d84 100644
return 0;
}
-@@ -1569,8 +1573,7 @@ static int smu_resume(void *handle)
+@@ -1569,8 +1567,7 @@ static int smu_resume(void *handle)
return ret;
}
@@ -43363,6 +68646,31 @@ index a403657151ba1..0e1a843608e43 100644
if (ret)
dev_err(smu->adev->dev, "Failed to mode reset!\n");
+diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
+index 21909642ee4ca..8fbb25913327c 100644
+--- a/drivers/gpu/drm/armada/armada_gem.c
++++ b/drivers/gpu/drm/armada/armada_gem.c
+@@ -336,7 +336,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+ struct drm_armada_gem_pwrite *args = data;
+ struct armada_gem_object *dobj;
+ char __user *ptr;
+- int ret;
++ int ret = 0;
+
+ DRM_DEBUG_DRIVER("handle %u off %u size %u ptr 0x%llx\n",
+ args->handle, args->offset, args->size, args->ptr);
+@@ -349,9 +349,8 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+ if (!access_ok(ptr, args->size))
+ return -EFAULT;
+
+- ret = fault_in_pages_readable(ptr, args->size);
+- if (ret)
+- return ret;
++ if (fault_in_readable(ptr, args->size))
++ return -EFAULT;
+
+ dobj = armada_gem_object_lookup(file, args->handle);
+ if (dobj == NULL)
diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
index b53fee6f1c170..65f172807a0d5 100644
--- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
@@ -43405,6 +68713,93 @@ index d9eb353a4bf09..dbe1cc620f6e6 100644
{1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
AST2500PreCatchCRT), 60, 1, 0x3A },
+diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
+index 431b6e12a81fe..68ec45abc1fbf 100644
+--- a/drivers/gpu/drm/bridge/Kconfig
++++ b/drivers/gpu/drm/bridge/Kconfig
+@@ -8,7 +8,6 @@ config DRM_BRIDGE
+ config DRM_PANEL_BRIDGE
+ def_bool y
+ depends on DRM_BRIDGE
+- depends on DRM_KMS_HELPER
+ select DRM_PANEL
+ help
+ DRM bridge wrapper of DRM panels
+@@ -30,6 +29,7 @@ config DRM_CDNS_DSI
+ config DRM_CHIPONE_ICN6211
+ tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
+ depends on OF
++ select DRM_KMS_HELPER
+ select DRM_MIPI_DSI
+ select DRM_PANEL_BRIDGE
+ help
+diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
+index 05e3abb5a0c9a..1b00dfda6e0d9 100644
+--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
+@@ -169,6 +169,7 @@
+ #define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
+ #define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
+
++#define ADV7535_REG_POWER2_HPD_OVERRIDE BIT(6)
+ #define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0
+ #define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
+ #define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40
+diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+index 76555ae64e9ce..c02f3ec60b04c 100644
+--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+@@ -351,11 +351,17 @@ static void __adv7511_power_on(struct adv7511 *adv7511)
+ * from standby or are enabled. When the HPD goes low the adv7511 is
+ * reset and the outputs are disabled which might cause the monitor to
+ * go to standby again. To avoid this we ignore the HPD pin for the
+- * first few seconds after enabling the output.
++ * first few seconds after enabling the output. On the other hand
++ * adv7535 require to enable HPD Override bit for proper HPD.
+ */
+- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+- ADV7511_REG_POWER2_HPD_SRC_MASK,
+- ADV7511_REG_POWER2_HPD_SRC_NONE);
++ if (adv7511->type == ADV7535)
++ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
++ ADV7535_REG_POWER2_HPD_OVERRIDE,
++ ADV7535_REG_POWER2_HPD_OVERRIDE);
++ else
++ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
++ ADV7511_REG_POWER2_HPD_SRC_MASK,
++ ADV7511_REG_POWER2_HPD_SRC_NONE);
+ }
+
+ static void adv7511_power_on(struct adv7511 *adv7511)
+@@ -375,6 +381,10 @@ static void adv7511_power_on(struct adv7511 *adv7511)
+ static void __adv7511_power_off(struct adv7511 *adv7511)
+ {
+ /* TODO: setup additional power down modes */
++ if (adv7511->type == ADV7535)
++ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
++ ADV7535_REG_POWER2_HPD_OVERRIDE, 0);
++
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+ ADV7511_POWER_POWER_DOWN,
+ ADV7511_POWER_POWER_DOWN);
+@@ -672,9 +682,14 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
+ status = connector_status_disconnected;
+ } else {
+ /* Renable HPD sensing */
+- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+- ADV7511_REG_POWER2_HPD_SRC_MASK,
+- ADV7511_REG_POWER2_HPD_SRC_BOTH);
++ if (adv7511->type == ADV7535)
++ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
++ ADV7535_REG_POWER2_HPD_OVERRIDE,
++ ADV7535_REG_POWER2_HPD_OVERRIDE);
++ else
++ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
++ ADV7511_REG_POWER2_HPD_SRC_MASK,
++ ADV7511_REG_POWER2_HPD_SRC_BOTH);
+ }
+
+ adv7511->status = status;
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index cab6c8b92efd4..6a4f20fccf841 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -43434,7 +68829,7 @@ index cab6c8b92efd4..6a4f20fccf841 100644
dev_warn(dp->dev, "Failed to apply PSR %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
-index 14d73fb1dd15b..ea414cd349b5c 100644
+index 14d73fb1dd15b..392a9c56e9a00 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -720,7 +720,7 @@ static int edid_read(struct anx7625_data *ctx,
@@ -43455,7 +68850,7 @@ index 14d73fb1dd15b..ea414cd349b5c 100644
}
static int segments_edid_read(struct anx7625_data *ctx,
-@@ -785,7 +785,7 @@ static int segments_edid_read(struct anx7625_data *ctx,
+@@ -785,13 +785,14 @@ static int segments_edid_read(struct anx7625_data *ctx,
if (cnt > EDID_TRY_CNT)
return -EIO;
@@ -43464,7 +68859,15 @@ index 14d73fb1dd15b..ea414cd349b5c 100644
}
static int sp_tx_edid_read(struct anx7625_data *ctx,
-@@ -887,7 +887,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
+ u8 *pedid_blocks_buf)
+ {
+- u8 offset, edid_pos;
++ u8 offset;
++ int edid_pos;
+ int count, blocks_num;
+ u8 pblock_buf[MAX_DPCD_BUFFER_SIZE];
+ u8 i, j;
+@@ -887,7 +888,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
}
/* Reset aux channel */
@@ -43477,6 +68880,18 @@ index 14d73fb1dd15b..ea414cd349b5c 100644
return (blocks_num + 1);
}
+diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
+index e6e331071a00d..dd57b104aec3a 100644
+--- a/drivers/gpu/drm/bridge/cdns-dsi.c
++++ b/drivers/gpu/drm/bridge/cdns-dsi.c
+@@ -1286,6 +1286,7 @@ static const struct of_device_id cdns_dsi_of_match[] = {
+ { .compatible = "cdns,dsi" },
+ { },
+ };
++MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
+
+ static struct platform_driver cdns_dsi_platform_driver = {
+ .probe = cdns_dsi_drm_probe,
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index 05eb759da6fc6..847a0dce7f1d3 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
@@ -43627,7 +69042,7 @@ index d2808c4a6fb1c..cce98bf2a4e73 100644
static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c)
diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
-index ed8ac5059cd26..af07eeb47ca02 100644
+index ed8ac5059cd26..691039aba87f4 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -7,6 +7,7 @@
@@ -43668,7 +69083,52 @@ index ed8ac5059cd26..af07eeb47ca02 100644
DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_post: 0x%x\n", cycles);
nwl_dsi_write(dsi, NWL_DSI_CFG_T_POST, cycles);
cycles = ps2bc(dsi, cfg->hs_exit);
-@@ -939,6 +937,40 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
+@@ -863,18 +861,19 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ memcpy(&dsi->mode, adjusted_mode, sizeof(dsi->mode));
+ drm_mode_debug_printmodeline(adjusted_mode);
+
+- pm_runtime_get_sync(dev);
++ if (pm_runtime_resume_and_get(dev) < 0)
++ return;
+
+ if (clk_prepare_enable(dsi->lcdif_clk) < 0)
+- return;
++ goto runtime_put;
+ if (clk_prepare_enable(dsi->core_clk) < 0)
+- return;
++ goto runtime_put;
+
+ /* Step 1 from DSI reset-out instructions */
+ ret = reset_control_deassert(dsi->rst_pclk);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "Failed to deassert PCLK: %d\n", ret);
+- return;
++ goto runtime_put;
+ }
+
+ /* Step 2 from DSI reset-out instructions */
+@@ -884,13 +883,18 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ ret = reset_control_deassert(dsi->rst_esc);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "Failed to deassert ESC: %d\n", ret);
+- return;
++ goto runtime_put;
+ }
+ ret = reset_control_deassert(dsi->rst_byte);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "Failed to deassert BYTE: %d\n", ret);
+- return;
++ goto runtime_put;
+ }
++
++ return;
++
++runtime_put:
++ pm_runtime_put_sync(dev);
+ }
+
+ static void
+@@ -939,6 +943,40 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0);
}
@@ -43709,7 +69169,7 @@ index ed8ac5059cd26..af07eeb47ca02 100644
static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-@@ -946,6 +978,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {
+@@ -946,6 +984,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {
.atomic_check = nwl_dsi_bridge_atomic_check,
.atomic_enable = nwl_dsi_bridge_atomic_enable,
.atomic_disable = nwl_dsi_bridge_atomic_disable,
@@ -43717,6 +69177,27 @@ index ed8ac5059cd26..af07eeb47ca02 100644
.mode_set = nwl_dsi_bridge_mode_set,
.mode_valid = nwl_dsi_bridge_mode_valid,
.attach = nwl_dsi_bridge_attach,
+@@ -1171,6 +1210,7 @@ static int nwl_dsi_probe(struct platform_device *pdev)
+
+ ret = nwl_dsi_select_input(dsi);
+ if (ret < 0) {
++ pm_runtime_disable(dev);
+ mipi_dsi_host_unregister(&dsi->dsi_host);
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
+index 843265d7f1b12..ec7745c31da07 100644
+--- a/drivers/gpu/drm/bridge/sil-sii8620.c
++++ b/drivers/gpu/drm/bridge/sil-sii8620.c
+@@ -2120,7 +2120,7 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx)
+ if (ret) {
+ dev_err(ctx->dev, "Failed to register RC device\n");
+ ctx->error = ret;
+- rc_free_device(ctx->rc_dev);
++ rc_free_device(rc_dev);
+ return;
+ }
+ ctx->rc_dev = rc_dev;
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
index d0db1acf11d73..7d2ed0ed2fe26 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
@@ -43786,7 +69267,7 @@ index feb04f127b550..f50b47ac11a82 100644
}
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
-index f08d0fded61f7..e1211a5b334ba 100644
+index f08d0fded61f7..25d58dcfc87e1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -757,6 +757,14 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
@@ -43804,7 +69285,19 @@ index f08d0fded61f7..e1211a5b334ba 100644
static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi)
{
hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
-@@ -3431,7 +3439,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
+@@ -2543,8 +2551,9 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+ if (!output_fmts)
+ return NULL;
+
+- /* If dw-hdmi is the only bridge, avoid negociating with ourselves */
+- if (list_is_singular(&bridge->encoder->bridge_chain)) {
++ /* If dw-hdmi is the first or only bridge, avoid negociating with ourselves */
++ if (list_is_singular(&bridge->encoder->bridge_chain) ||
++ list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain)) {
+ *num_output_fmts = 1;
+ output_fmts[0] = MEDIA_BUS_FMT_FIXED;
+
+@@ -3431,7 +3440,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
audio.base = hdmi->regs;
audio.irq = irq;
audio.hdmi = hdmi;
@@ -43813,7 +69306,7 @@ index f08d0fded61f7..e1211a5b334ba 100644
hdmi->enable_audio = dw_hdmi_ahb_audio_enable;
hdmi->disable_audio = dw_hdmi_ahb_audio_disable;
-@@ -3444,7 +3452,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
+@@ -3444,7 +3453,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
struct dw_hdmi_i2s_audio_data audio;
audio.hdmi = hdmi;
@@ -43822,6 +69315,18 @@ index f08d0fded61f7..e1211a5b334ba 100644
audio.write = hdmi_writeb;
audio.read = hdmi_readb;
hdmi->enable_audio = dw_hdmi_i2s_audio_enable;
+diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+index e44e18a0112af..56c3fd08c6a0b 100644
+--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
++++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+@@ -1199,6 +1199,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
+ ret = mipi_dsi_host_register(&dsi->dsi_host);
+ if (ret) {
+ dev_err(dev, "Failed to register MIPI host: %d\n", ret);
++ pm_runtime_disable(dev);
+ dw_mipi_dsi_debugfs_remove(dsi);
+ return ERR_PTR(ret);
+ }
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 41d48a393e7f5..45a5f1e48f0ef 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -43927,6 +69432,20 @@ index 909f318331816..f195c70131373 100644
state->enable = true;
drm_dbg_atomic(crtc->dev,
"Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
+index 2ba257b1ae208..e9b7926d9b663 100644
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -2233,6 +2233,9 @@ EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal);
+ void drm_connector_set_vrr_capable_property(
+ struct drm_connector *connector, bool capable)
+ {
++ if (!connector->vrr_capable_property)
++ return;
++
+ drm_object_property_set_value(&connector->base,
+ connector->vrr_capable_property,
+ capable);
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 6d0f2c447f3b9..7bb24523a7493 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
@@ -43988,6 +69507,18 @@ index 6d0f2c447f3b9..7bb24523a7493 100644
}
ret = drm_edp_backlight_set_level(aux, bl, level);
+diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
+index 86d13d6bc4631..b3e3babe18c0e 100644
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -4834,6 +4834,7 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
+
+ mst_edid = drm_dp_mst_get_edid(port->connector, mgr, port);
+ drm_edid_get_monitor_name(mst_edid, name, namelen);
++ kfree(mst_edid);
+ }
+
+ /**
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a5097467ba5c..b3a1636d1b984 100644
--- a/drivers/gpu/drm/drm_drv.c
@@ -44020,10 +69551,63 @@ index 7a5097467ba5c..b3a1636d1b984 100644
ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
if (ret)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
-index ea9a79bc95839..6ad4361a5cbc7 100644
+index ea9a79bc95839..ee6f44f9a81c3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
-@@ -5205,6 +5205,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
+@@ -4776,7 +4776,8 @@ bool drm_detect_monitor_audio(struct edid *edid)
+ if (!edid_ext)
+ goto end;
+
+- has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
++ has_audio = (edid_ext[0] == CEA_EXT &&
++ (edid_ext[3] & EDID_BASIC_AUDIO) != 0);
+
+ if (has_audio) {
+ DRM_DEBUG_KMS("Monitor has basic audio support\n");
+@@ -5003,21 +5004,21 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
+
+ if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
+ dc_bpc = 10;
+- info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
++ info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_30;
+ DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
+ connector->name);
+ }
+
+ if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
+ dc_bpc = 12;
+- info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;
++ info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_36;
+ DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
+ connector->name);
+ }
+
+ if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
+ dc_bpc = 16;
+- info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;
++ info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_48;
+ DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
+ connector->name);
+ }
+@@ -5032,16 +5033,9 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
+ connector->name, dc_bpc);
+ info->bpc = dc_bpc;
+
+- /*
+- * Deep color support mandates RGB444 support for all video
+- * modes and forbids YCRCB422 support for all video modes per
+- * HDMI 1.3 spec.
+- */
+- info->color_formats = DRM_COLOR_FORMAT_RGB444;
+-
+ /* YCRCB444 is optional according to spec. */
+ if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
+- info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
++ info->edid_hdmi_ycbcr444_dc_modes = info->edid_hdmi_rgb444_dc_modes;
+ DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
+ connector->name);
+ }
+@@ -5205,6 +5199,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
return quirks;
@@ -44031,7 +69615,7 @@ index ea9a79bc95839..6ad4361a5cbc7 100644
drm_parse_cea_ext(connector, edid);
/*
-@@ -5253,7 +5254,6 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
+@@ -5253,7 +5248,6 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
connector->name, info->bpc);
@@ -44040,7 +69624,7 @@ index ea9a79bc95839..6ad4361a5cbc7 100644
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
-index 8e7a124d6c5a3..22bf690910b25 100644
+index 8e7a124d6c5a3..ed589e7182bb4 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1743,7 +1743,13 @@ void drm_fb_helper_fill_info(struct fb_info *info,
@@ -44058,6 +69642,39 @@ index 8e7a124d6c5a3..22bf690910b25 100644
fb_helper->dev->driver->name);
}
+@@ -2340,6 +2346,7 @@ static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ fbi->fbops = &drm_fbdev_fb_ops;
+ fbi->screen_size = fb->height * fb->pitches[0];
+ fbi->fix.smem_len = fbi->screen_size;
++ fbi->flags = FBINFO_DEFAULT;
+
+ drm_fb_helper_fill_info(fbi, fb_helper, sizes);
+
+@@ -2347,19 +2354,21 @@ static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ fbi->screen_buffer = vzalloc(fbi->screen_size);
+ if (!fbi->screen_buffer)
+ return -ENOMEM;
++ fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
+
+ fbi->fbdefio = &drm_fbdev_defio;
+-
+ fb_deferred_io_init(fbi);
+ } else {
+ /* buffer is mapped for HW framebuffer */
+ ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
+ if (ret)
+ return ret;
+- if (map.is_iomem)
++ if (map.is_iomem) {
+ fbi->screen_base = map.vaddr_iomem;
+- else
++ } else {
+ fbi->screen_buffer = map.vaddr;
++ fbi->flags |= FBINFO_VIRTFB;
++ }
+
+ /*
+ * Shamelessly leak the physical address to user-space. As
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index d53388199f34c..6533efa840204 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -44087,7 +69704,7 @@ index d53388199f34c..6533efa840204 100644
cma_obj = to_drm_gem_cma_obj(obj);
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
-index e1b2ce4921ae7..448c2f2d803a6 100644
+index e1b2ce4921ae7..f5ab891731d0b 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -109,6 +109,18 @@ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
@@ -44109,7 +69726,20 @@ index e1b2ce4921ae7..448c2f2d803a6 100644
static const struct dmi_system_id orientation_data[] = {
{ /* Acer One 10 (S1003) */
.matches = {
-@@ -205,6 +217,13 @@ static const struct dmi_system_id orientation_data[] = {
+@@ -154,6 +166,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
+ },
+ .driver_data = (void *)&lcd720x1280_rightside_up,
++ }, { /* GPD Win Max */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1619-01"),
++ },
++ .driver_data = (void *)&lcd800x1280_rightside_up,
+ }, { /*
+ * GPD Pocket, note that the the DMI data is less generic then
+ * it seems, devices with a board-vendor of "AMI Corporation"
+@@ -205,6 +223,13 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
},
.driver_data = (void *)&itworks_tw891,
@@ -44123,7 +69753,7 @@ index e1b2ce4921ae7..448c2f2d803a6 100644
}, { /*
* Lenovo Ideapad Miix 310 laptop, only some production batches
* have a portrait screen, the resolution checks makes the quirk
-@@ -223,12 +242,23 @@ static const struct dmi_system_id orientation_data[] = {
+@@ -223,12 +248,23 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
@@ -44149,7 +69779,7 @@ index e1b2ce4921ae7..448c2f2d803a6 100644
.driver_data = (void *)&lcd1200x1920_rightside_up,
}, { /* OneGX1 Pro */
.matches = {
-@@ -237,6 +267,25 @@ static const struct dmi_system_id orientation_data[] = {
+@@ -237,6 +273,25 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),
},
.driver_data = (void *)&onegx1_pro,
@@ -44208,7 +69838,7 @@ index deb23dbec8b52..d6c7f4f9a7a29 100644
}
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
-index c9a9d74f338c1..c313a5b4549c4 100644
+index c9a9d74f338c1..7e48dcd1bee4d 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -404,8 +404,17 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
@@ -44230,6 +69860,92 @@ index c9a9d74f338c1..c313a5b4549c4 100644
dma_fence_put(*fence);
} else {
ret = -EINVAL;
+@@ -844,12 +853,57 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+ &args->handle);
+ }
+
++
++/*
++ * Try to flatten a dma_fence_chain into a dma_fence_array so that it can be
++ * added as timeline fence to a chain again.
++ */
++static int drm_syncobj_flatten_chain(struct dma_fence **f)
++{
++ struct dma_fence_chain *chain = to_dma_fence_chain(*f);
++ struct dma_fence *tmp, **fences;
++ struct dma_fence_array *array;
++ unsigned int count;
++
++ if (!chain)
++ return 0;
++
++ count = 0;
++ dma_fence_chain_for_each(tmp, &chain->base)
++ ++count;
++
++ fences = kmalloc_array(count, sizeof(*fences), GFP_KERNEL);
++ if (!fences)
++ return -ENOMEM;
++
++ count = 0;
++ dma_fence_chain_for_each(tmp, &chain->base)
++ fences[count++] = dma_fence_get(tmp);
++
++ array = dma_fence_array_create(count, fences,
++ dma_fence_context_alloc(1),
++ 1, false);
++ if (!array)
++ goto free_fences;
++
++ dma_fence_put(*f);
++ *f = &array->base;
++ return 0;
++
++free_fences:
++ while (count--)
++ dma_fence_put(fences[count]);
++
++ kfree(fences);
++ return -ENOMEM;
++}
++
+ static int drm_syncobj_transfer_to_timeline(struct drm_file *file_private,
+ struct drm_syncobj_transfer *args)
+ {
+ struct drm_syncobj *timeline_syncobj = NULL;
+- struct dma_fence *fence;
+ struct dma_fence_chain *chain;
++ struct dma_fence *fence;
+ int ret;
+
+ timeline_syncobj = drm_syncobj_find(file_private, args->dst_handle);
+@@ -860,16 +914,22 @@ static int drm_syncobj_transfer_to_timeline(struct drm_file *file_private,
+ args->src_point, args->flags,
+ &fence);
+ if (ret)
+- goto err;
++ goto err_put_timeline;
++
++ ret = drm_syncobj_flatten_chain(&fence);
++ if (ret)
++ goto err_free_fence;
++
+ chain = dma_fence_chain_alloc();
+ if (!chain) {
+ ret = -ENOMEM;
+- goto err1;
++ goto err_free_fence;
+ }
++
+ drm_syncobj_add_point(timeline_syncobj, chain, fence, args->dst_point);
+-err1:
++err_free_fence:
+ dma_fence_put(fence);
+-err:
++err_put_timeline:
+ drm_syncobj_put(timeline_syncobj);
+
+ return ret;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 486259e154aff..90488ab8c6d8e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -44504,7 +70220,7 @@ index fd71346aac7bc..32d5a556b7eac 100644
}
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
-index 4b94256d73197..7144c76ac9701 100644
+index 4b94256d73197..ea48620f76d9c 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -681,6 +681,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
@@ -44545,7 +70261,17 @@ index 4b94256d73197..7144c76ac9701 100644
return 0;
ret = intel_atomic_lock_global_state(&new_bw_state->base);
-@@ -814,7 +829,6 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
+@@ -804,7 +819,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
+ * cause.
+ */
+ if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
+- allowed_points = BIT(max_bw_point);
++ allowed_points &= ADLS_PSF_PT_MASK;
++ allowed_points |= BIT(max_bw_point);
+ drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n",
+ max_bw_point);
+ }
+@@ -814,7 +830,6 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
*/
new_bw_state->qgv_points_mask = ~allowed_points & mask;
@@ -44626,7 +70352,7 @@ index ba2c08f1a797c..876620455ed31 100644
};
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
-index 17f44ffea5866..625ce6975eeba 100644
+index 17f44ffea5866..c9b051ab18e02 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -84,6 +84,7 @@
@@ -44820,6 +70546,17 @@ index 17f44ffea5866..625ce6975eeba 100644
/* returns HPLL frequency in kHz */
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
{
+@@ -1833,8 +1658,8 @@ static void fixup_plane_bitmasks(struct intel_crtc_state *crtc_state)
+ }
+ }
+
+-static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
+- struct intel_plane *plane)
++void intel_plane_disable_noatomic(struct intel_crtc *crtc,
++ struct intel_plane *plane)
+ {
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc_state *crtc_state =
@@ -1879,49 +1704,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
intel_wait_for_vblank(dev_priv, crtc->pipe);
}
@@ -44870,6 +70607,27 @@ index 17f44ffea5866..625ce6975eeba 100644
static bool
intel_reuse_initial_plane_obj(struct drm_i915_private *i915,
const struct intel_initial_plane_config *plane_config,
+@@ -13435,6 +13217,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
+ vlv_wm_sanitize(dev_priv);
+ } else if (DISPLAY_VER(dev_priv) >= 9) {
+ skl_wm_get_hw_state(dev_priv);
++ skl_wm_sanitize(dev_priv);
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
+ ilk_wm_get_hw_state(dev_priv);
+ }
+diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
+index 284936f0ddab2..6a7a91b380805 100644
+--- a/drivers/gpu/drm/i915/display/intel_display.h
++++ b/drivers/gpu/drm/i915/display/intel_display.h
+@@ -629,6 +629,8 @@ void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
+ struct intel_encoder *
+ intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
+ const struct intel_crtc_state *crtc_state);
++void intel_plane_disable_noatomic(struct intel_crtc *crtc,
++ struct intel_plane *plane);
+
+ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
+ int color_plane);
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 8fdacb252bb19..b136a0fc0963b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -44897,10 +70655,68 @@ index 6beeeeba1bed2..b56850d964919 100644
enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
-index b3c8e1c450efb..73076737add75 100644
+index b3c8e1c450efb..0e04d4dd1c132 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
-@@ -606,7 +606,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv,
+@@ -375,6 +375,44 @@ static void dmc_set_fw_offset(struct intel_dmc *dmc,
+ }
+ }
+
++static bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc,
++ const u32 *mmioaddr, u32 mmio_count,
++ int header_ver, u8 dmc_id)
++{
++ struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
++ u32 start_range, end_range;
++ int i;
++
++ if (dmc_id >= DMC_FW_MAX) {
++ drm_warn(&i915->drm, "Unsupported firmware id %u\n", dmc_id);
++ return false;
++ }
++
++ if (header_ver == 1) {
++ start_range = DMC_MMIO_START_RANGE;
++ end_range = DMC_MMIO_END_RANGE;
++ } else if (dmc_id == DMC_FW_MAIN) {
++ start_range = TGL_MAIN_MMIO_START;
++ end_range = TGL_MAIN_MMIO_END;
++ } else if (DISPLAY_VER(i915) >= 13) {
++ start_range = ADLP_PIPE_MMIO_START;
++ end_range = ADLP_PIPE_MMIO_END;
++ } else if (DISPLAY_VER(i915) >= 12) {
++ start_range = TGL_PIPE_MMIO_START(dmc_id);
++ end_range = TGL_PIPE_MMIO_END(dmc_id);
++ } else {
++ drm_warn(&i915->drm, "Unknown mmio range for sanity check");
++ return false;
++ }
++
++ for (i = 0; i < mmio_count; i++) {
++ if (mmioaddr[i] < start_range || mmioaddr[i] > end_range)
++ return false;
++ }
++
++ return true;
++}
++
+ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
+ const struct intel_dmc_header_base *dmc_header,
+ size_t rem_size, u8 dmc_id)
+@@ -444,6 +482,12 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
+ return 0;
+ }
+
++ if (!dmc_mmio_addr_sanity_check(dmc, mmioaddr, mmio_count,
++ dmc_header->header_ver, dmc_id)) {
++ drm_err(&i915->drm, "DMC firmware has Wrong MMIO Addresses\n");
++ return 0;
++ }
++
+ for (i = 0; i < mmio_count; i++) {
+ dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i]);
+ dmc_info->mmiodata[i] = mmiodata[i];
+@@ -606,7 +650,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv,
continue;
offset = readcount + dmc->dmc_info[id].dmc_offset * 4;
@@ -44910,7 +70726,7 @@ index b3c8e1c450efb..73076737add75 100644
continue;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
-index 5cf152be44877..dbff4b6aa22bf 100644
+index 5cf152be44877..631cf7d4323c8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -29,6 +29,7 @@
@@ -45061,6 +70877,15 @@ index 5cf152be44877..dbff4b6aa22bf 100644
intel_dp->reset_link_params = false;
}
+@@ -4617,7 +4599,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
+ struct intel_dp *intel_dp = &dig_port->dp;
+
+ if (dig_port->base.type == INTEL_OUTPUT_EDP &&
+- (long_hpd || !intel_pps_have_power(intel_dp))) {
++ (long_hpd || !intel_pps_have_panel_power_or_vdd(intel_dp))) {
+ /*
+ * vdd off can generate a long/short pulse on eDP which
+ * would require vdd on to handle it, and thus we
@@ -4716,432 +4698,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
drm_connector_attach_vrr_capable_property(connector);
}
@@ -45534,7 +71359,7 @@ index 680631b5b4378..3dd6ebc2f6b14 100644
+
#endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
-index 6ac568617ef37..c82f8febe7303 100644
+index 6ac568617ef37..e7b90863aa43d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -35,6 +35,7 @@
@@ -45545,7 +71370,22 @@ index 6ac568617ef37..c82f8febe7303 100644
#include "intel_dp_aux_backlight.h"
#include "intel_panel.h"
-@@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
+@@ -95,6 +96,14 @@
+
+ #define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1 0x359
+
++enum intel_dp_aux_backlight_modparam {
++ INTEL_DP_AUX_BACKLIGHT_AUTO = -1,
++ INTEL_DP_AUX_BACKLIGHT_OFF = 0,
++ INTEL_DP_AUX_BACKLIGHT_ON = 1,
++ INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2,
++ INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3,
++};
++
+ /* Intel EDP backlight callbacks */
+ static bool
+ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
+@@ -106,6 +115,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
int ret;
u8 tcon_cap[4];
@@ -45554,7 +71394,32 @@ index 6ac568617ef37..c82f8febe7303 100644
ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap));
if (ret != sizeof(tcon_cap))
return false;
-@@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state,
+@@ -122,6 +133,24 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
+ return false;
+ }
+
++ /*
++ * If we don't have HDR static metadata there is no way to
++ * runtime detect used range for nits based control. For now
++ * do not use Intel proprietary eDP backlight control if we
++ * don't have this data in panel EDID. In case we find panel
++ * which supports only nits based control, but doesn't provide
++ * HDR static metadata we need to start maintaining table of
++ * ranges for such panels.
++ */
++ if (i915->params.enable_dpcd_backlight != INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL &&
++ !(connector->base.hdr_sink_metadata.hdmi_type1.metadata_type &
++ BIT(HDMI_STATIC_METADATA_TYPE1))) {
++ drm_info(&i915->drm,
++ "Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d. needs this, please file a _new_ bug report on drm/i915, see " FDO_BUG_URL " for details.\n",
++ INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL);
++ return false;
++ }
++
+ panel->backlight.edp.intel.sdr_uses_aux =
+ tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP;
+
+@@ -204,6 +233,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state,
int ret;
u8 old_ctrl, ctrl;
@@ -45563,6 +71428,21 @@ index 6ac568617ef37..c82f8febe7303 100644
ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl);
if (ret != 1) {
drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret);
+@@ -368,14 +399,6 @@ static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = {
+ .get = intel_dp_aux_vesa_get_backlight,
+ };
+
+-enum intel_dp_aux_backlight_modparam {
+- INTEL_DP_AUX_BACKLIGHT_AUTO = -1,
+- INTEL_DP_AUX_BACKLIGHT_OFF = 0,
+- INTEL_DP_AUX_BACKLIGHT_ON = 1,
+- INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2,
+- INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3,
+-};
+-
+ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
+ {
+ struct drm_device *dev = connector->base.dev;
diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
new file mode 100644
index 0000000000000..22acd945a9e47
@@ -46381,7 +72261,7 @@ index 8e75debcce1a9..e4834d84ce5e3 100644
/**
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
-index b04685bb6439c..c3787512295dd 100644
+index b04685bb6439c..926ddc6599f5e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -53,21 +53,20 @@
@@ -46428,16 +72308,50 @@ index b04685bb6439c..c3787512295dd 100644
drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n",
enable ? "Enabling" : "Disabling");
-@@ -1830,7 +1830,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
+@@ -1830,7 +1830,8 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
int clock, bool respect_downstream_limits,
bool has_hdmi_sink)
{
- struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi));
+ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi);
++ enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port);
if (clock < 25000)
return MODE_CLOCK_LOW;
-@@ -1946,8 +1946,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
+@@ -1851,6 +1852,14 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
+ if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
+ return MODE_CLOCK_RANGE;
+
++ /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */
++ if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200)
++ return MODE_CLOCK_RANGE;
++
++ /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */
++ if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800)
++ return MODE_CLOCK_RANGE;
++
+ /*
+ * SNPS PHYs' MPLLB table-based programming can only handle a fixed
+ * set of link rates.
+@@ -1892,7 +1901,7 @@ static bool intel_hdmi_bpc_possible(struct drm_connector *connector,
+ if (ycbcr420_output)
+ return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
+ else
+- return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36;
++ return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36;
+ case 10:
+ if (DISPLAY_VER(i915) < 11)
+ return false;
+@@ -1903,7 +1912,7 @@ static bool intel_hdmi_bpc_possible(struct drm_connector *connector,
+ if (ycbcr420_output)
+ return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
+ else
+- return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30;
++ return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30;
+ case 8:
+ return true;
+ default:
+@@ -1946,8 +1955,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
@@ -46447,7 +72361,7 @@ index b04685bb6439c..c3787512295dd 100644
enum drm_mode_status status;
int clock = mode->clock;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
-@@ -2260,6 +2259,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
+@@ -2260,6 +2268,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
return 0;
}
@@ -46517,6 +72431,112 @@ index 7e3f5c6ca4846..dfa5f18171e3b 100644
if (rec->dst_x < pipe_config->pipe_src_w &&
rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w &&
rec->dst_y < pipe_config->pipe_src_h &&
+diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
+index a36ec4a818ff5..466bf6820641d 100644
+--- a/drivers/gpu/drm/i915/display/intel_pps.c
++++ b/drivers/gpu/drm/i915/display/intel_pps.c
+@@ -1074,14 +1074,14 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
+ edp_panel_vdd_schedule_off(intel_dp);
+ }
+
+-bool intel_pps_have_power(struct intel_dp *intel_dp)
++bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp)
+ {
+ intel_wakeref_t wakeref;
+ bool have_power = false;
+
+ with_intel_pps_lock(intel_dp, wakeref) {
+- have_power = edp_have_panel_power(intel_dp) &&
+- edp_have_panel_vdd(intel_dp);
++ have_power = edp_have_panel_power(intel_dp) ||
++ edp_have_panel_vdd(intel_dp);
+ }
+
+ return have_power;
+diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
+index fbbcca782e7b6..9fe7be4fe867e 100644
+--- a/drivers/gpu/drm/i915/display/intel_pps.h
++++ b/drivers/gpu/drm/i915/display/intel_pps.h
+@@ -36,7 +36,7 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp);
+ void intel_pps_on(struct intel_dp *intel_dp);
+ void intel_pps_off(struct intel_dp *intel_dp);
+ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
+-bool intel_pps_have_power(struct intel_dp *intel_dp);
++bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp);
+ void intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
+
+ void intel_pps_init(struct intel_dp *intel_dp);
+diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
+index 1b0daf649e823..a3d0c57ec0f0b 100644
+--- a/drivers/gpu/drm/i915/display/intel_psr.c
++++ b/drivers/gpu/drm/i915/display/intel_psr.c
+@@ -936,6 +936,20 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
+ return false;
+ }
+
++ /* Wa_16011303918:adl-p */
++ if (crtc_state->vrr.enable &&
++ IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) {
++ drm_dbg_kms(&dev_priv->drm,
++ "PSR2 not enabled, not compatible with HW stepping + VRR\n");
++ return false;
++ }
++
++ if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) {
++ drm_dbg_kms(&dev_priv->drm,
++ "PSR2 not enabled, PSR2 SDP indication do not fit in hblank\n");
++ return false;
++ }
++
+ if (HAS_PSR2_SEL_FETCH(dev_priv)) {
+ if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) &&
+ !HAS_PSR_HW_TRACKING(dev_priv)) {
+@@ -949,12 +963,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
+ if (!crtc_state->enable_psr2_sel_fetch &&
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 HW tracking is not supported this Display stepping\n");
+- return false;
++ goto unsupported;
+ }
+
+ if (!psr2_granularity_check(intel_dp, crtc_state)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, SU granularity not compatible\n");
+- return false;
++ goto unsupported;
+ }
+
+ if (!crtc_state->enable_psr2_sel_fetch &&
+@@ -963,25 +977,15 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
+ "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n",
+ crtc_hdisplay, crtc_vdisplay,
+ psr_max_h, psr_max_v);
+- return false;
+- }
+-
+- if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) {
+- drm_dbg_kms(&dev_priv->drm,
+- "PSR2 not enabled, PSR2 SDP indication do not fit in hblank\n");
+- return false;
+- }
+-
+- /* Wa_16011303918:adl-p */
+- if (crtc_state->vrr.enable &&
+- IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) {
+- drm_dbg_kms(&dev_priv->drm,
+- "PSR2 not enabled, not compatible with HW stepping + VRR\n");
+- return false;
++ goto unsupported;
+ }
+
+ tgl_dc3co_exitline_compute_config(intel_dp, crtc_state);
+ return true;
++
++unsupported:
++ crtc_state->enable_psr2_sel_fetch = false;
++ return false;
+ }
+
+ void intel_psr_compute_config(struct intel_dp *intel_dp,
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index 18b52b64af955..536b319ffe5ba 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -46547,6 +72567,28 @@ index 3ffece568ed98..0e885440be242 100644
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
"Port %s: PHY in TCCOLD, assuming not complete\n",
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+index 5130e8ed95647..28e07040cf47a 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+@@ -66,7 +66,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ * mmap ioctl is disallowed for all discrete platforms,
+ * and for all platforms with GRAPHICS_VER > 12.
+ */
+- if (IS_DGFX(i915) || GRAPHICS_VER(i915) > 12)
++ if (IS_DGFX(i915) || GRAPHICS_VER_FULL(i915) > IP_VER(12, 0))
+ return -EOPNOTSUPP;
+
+ if (args->flags & ~(I915_MMAP_WC))
+@@ -438,7 +438,7 @@ vm_access(struct vm_area_struct *area, unsigned long addr,
+ return -EACCES;
+
+ addr -= area->vm_start;
+- if (addr >= obj->base.size)
++ if (range_overflows_t(u64, addr, len, obj->base.size))
+ return -EINVAL;
+
+ i915_gem_ww_ctx_init(&ww, true);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 2471f36aaff38..3012cbe5b0b7c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -47135,7 +73177,7 @@ index 1bbd09ad52873..1ad7259fb1f0c 100644
static const struct intel_device_info tgl_info = {
GEN12_FEATURES,
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
-index 9023d4ecf3b37..c65473fc90935 100644
+index 9023d4ecf3b37..3c70aa5229e5a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2669,6 +2669,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
@@ -47163,6 +73205,38 @@ index 9023d4ecf3b37..c65473fc90935 100644
#define GEN12_AUX_ERR_DBG _MMIO(0x43f4)
#define FPGA_DBG _MMIO(0x42300)
+@@ -7447,7 +7458,7 @@ enum {
+ #define _SEL_FETCH_PLANE_BASE_6_A 0x70940
+ #define _SEL_FETCH_PLANE_BASE_7_A 0x70960
+ #define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880
+-#define _SEL_FETCH_PLANE_BASE_1_B 0x70990
++#define _SEL_FETCH_PLANE_BASE_1_B 0x71890
+
+ #define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \
+ _SEL_FETCH_PLANE_BASE_1_A, \
+@@ -7807,6 +7818,22 @@ enum {
+ /* MMIO address range for DMC program (0x80000 - 0x82FFF) */
+ #define DMC_MMIO_START_RANGE 0x80000
+ #define DMC_MMIO_END_RANGE 0x8FFFF
++#define DMC_V1_MMIO_START_RANGE 0x80000
++#define TGL_MAIN_MMIO_START 0x8F000
++#define TGL_MAIN_MMIO_END 0x8FFFF
++#define _TGL_PIPEA_MMIO_START 0x92000
++#define _TGL_PIPEA_MMIO_END 0x93FFF
++#define _TGL_PIPEB_MMIO_START 0x96000
++#define _TGL_PIPEB_MMIO_END 0x97FFF
++#define ADLP_PIPE_MMIO_START 0x5F000
++#define ADLP_PIPE_MMIO_END 0x5FFFF
++
++#define TGL_PIPE_MMIO_START(dmc_id) _PICK_EVEN(((dmc_id) - 1), _TGL_PIPEA_MMIO_START,\
++ _TGL_PIPEB_MMIO_START)
++
++#define TGL_PIPE_MMIO_END(dmc_id) _PICK_EVEN(((dmc_id) - 1), _TGL_PIPEA_MMIO_END,\
++ _TGL_PIPEB_MMIO_END)
++
+ #define SKL_DMC_DC3_DC5_COUNT _MMIO(0x80030)
+ #define SKL_DMC_DC5_DC6_COUNT _MMIO(0x8002C)
+ #define BXT_DMC_DC3_DC5_COUNT _MMIO(0x80038)
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 4b7fc4647e460..dfd20060812bc 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
@@ -47215,7 +73289,7 @@ index 7c0d83d292dcc..994c56fcb1991 100644
#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index a725792d5248b..9c5e4758947b6 100644
+index a725792d5248b..57c1dda76b94a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3063,9 +3063,9 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)
@@ -47231,7 +73305,17 @@ index a725792d5248b..9c5e4758947b6 100644
if (!changed)
return;
-@@ -4020,6 +4020,17 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state)
+@@ -3713,8 +3713,7 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
+ MISSING_CASE(DISPLAY_VER(dev_priv));
+ }
+
+- /* Default to an unusable block time */
+- dev_priv->sagv_block_time_us = -1;
++ dev_priv->sagv_block_time_us = 0;
+ }
+
+ /*
+@@ -4020,6 +4019,17 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state)
return ret;
}
@@ -47249,7 +73333,7 @@ index a725792d5248b..9c5e4758947b6 100644
for_each_new_intel_crtc_in_state(state, crtc,
new_crtc_state, i) {
struct skl_pipe_wm *pipe_wm = &new_crtc_state->wm.skl.optimal;
-@@ -4035,17 +4046,6 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state)
+@@ -4035,17 +4045,6 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state)
intel_can_enable_sagv(dev_priv, new_bw_state);
}
@@ -47267,7 +73351,7 @@ index a725792d5248b..9c5e4758947b6 100644
return 0;
}
-@@ -4708,6 +4708,10 @@ static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = {
+@@ -4708,6 +4707,10 @@ static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = {
};
static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
@@ -47278,7 +73362,7 @@ index a725792d5248b..9c5e4758947b6 100644
{
.active_pipes = BIT(PIPE_A),
.dbuf_mask = {
-@@ -4722,6 +4726,20 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
+@@ -4722,6 +4725,20 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
},
.join_mbus = true,
},
@@ -47299,7 +73383,7 @@ index a725792d5248b..9c5e4758947b6 100644
{
.active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
.dbuf_mask = {
-@@ -4826,7 +4844,7 @@ static bool check_mbus_joined(u8 active_pipes,
+@@ -4826,7 +4843,7 @@ static bool check_mbus_joined(u8 active_pipes,
{
int i;
@@ -47308,7 +73392,7 @@ index a725792d5248b..9c5e4758947b6 100644
if (dbuf_slices[i].active_pipes == active_pipes)
return dbuf_slices[i].join_mbus;
}
-@@ -4838,13 +4856,14 @@ static bool adlp_check_mbus_joined(u8 active_pipes)
+@@ -4838,13 +4855,14 @@ static bool adlp_check_mbus_joined(u8 active_pipes)
return check_mbus_joined(active_pipes, adlp_allowed_dbufs);
}
@@ -47326,7 +73410,7 @@ index a725792d5248b..9c5e4758947b6 100644
return dbuf_slices[i].dbuf_mask[pipe];
}
return 0;
-@@ -4855,7 +4874,7 @@ static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes,
+@@ -4855,7 +4873,7 @@ static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes,
* returns correspondent DBuf slice mask as stated in BSpec for particular
* platform.
*/
@@ -47335,7 +73419,7 @@ index a725792d5248b..9c5e4758947b6 100644
{
/*
* FIXME: For ICL this is still a bit unclear as prev BSpec revision
-@@ -4869,37 +4888,41 @@ static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
+@@ -4869,37 +4887,41 @@ static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
* still here - we will need it once those additional constraints
* pop up.
*/
@@ -47389,7 +73473,28 @@ index a725792d5248b..9c5e4758947b6 100644
/*
* For anything else just return one slice yet.
* Should be extended for other platforms.
-@@ -6110,11 +6133,16 @@ skl_compute_ddb(struct intel_atomic_state *state)
+@@ -5612,7 +5634,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
+ result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1;
+ result->enable = true;
+
+- if (DISPLAY_VER(dev_priv) < 12)
++ if (DISPLAY_VER(dev_priv) < 12 && dev_priv->sagv_block_time_us)
+ result->can_sagv = latency >= dev_priv->sagv_block_time_us;
+ }
+
+@@ -5643,7 +5665,10 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state,
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0;
+ struct skl_wm_level *levels = plane_wm->wm;
+- unsigned int latency = dev_priv->wm.skl_latency[0] + dev_priv->sagv_block_time_us;
++ unsigned int latency = 0;
++
++ if (dev_priv->sagv_block_time_us)
++ latency = dev_priv->sagv_block_time_us + dev_priv->wm.skl_latency[0];
+
+ skl_compute_plane_wm(crtc_state, 0, latency,
+ wm_params, &levels[0],
+@@ -6110,11 +6135,16 @@ skl_compute_ddb(struct intel_atomic_state *state)
return ret;
}
@@ -47407,7 +73512,7 @@ index a725792d5248b..9c5e4758947b6 100644
if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe])
continue;
-@@ -6126,9 +6154,6 @@ skl_compute_ddb(struct intel_atomic_state *state)
+@@ -6126,9 +6156,6 @@ skl_compute_ddb(struct intel_atomic_state *state)
new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state);
@@ -47417,7 +73522,7 @@ index a725792d5248b..9c5e4758947b6 100644
if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices ||
old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
-@@ -6609,6 +6634,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
+@@ -6609,6 +6636,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
enum pipe pipe = crtc->pipe;
unsigned int mbus_offset;
enum plane_id plane_id;
@@ -47425,7 +73530,7 @@ index a725792d5248b..9c5e4758947b6 100644
skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal;
-@@ -6628,19 +6654,22 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
+@@ -6628,19 +6656,22 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_uv);
}
@@ -47452,6 +73557,93 @@ index a725792d5248b..9c5e4758947b6 100644
drm_dbg_kms(&dev_priv->drm,
"[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n",
crtc->base.base.id, crtc->base.name,
+@@ -6652,6 +6683,74 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
+ dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices;
+ }
+
++static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
++{
++ const struct intel_dbuf_state *dbuf_state =
++ to_intel_dbuf_state(i915->dbuf.obj.state);
++ struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
++ struct intel_crtc *crtc;
++
++ for_each_intel_crtc(&i915->drm, crtc) {
++ const struct intel_crtc_state *crtc_state =
++ to_intel_crtc_state(crtc->base.state);
++
++ entries[crtc->pipe] = crtc_state->wm.skl.ddb;
++ }
++
++ for_each_intel_crtc(&i915->drm, crtc) {
++ const struct intel_crtc_state *crtc_state =
++ to_intel_crtc_state(crtc->base.state);
++ u8 slices;
++
++ slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
++ dbuf_state->joined_mbus);
++ if (dbuf_state->slices[crtc->pipe] & ~slices)
++ return true;
++
++ if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
++ I915_MAX_PIPES, crtc->pipe))
++ return true;
++ }
++
++ return false;
++}
++
++void skl_wm_sanitize(struct drm_i915_private *i915)
++{
++ struct intel_crtc *crtc;
++
++ /*
++ * On TGL/RKL (at least) the BIOS likes to assign the planes
++ * to the wrong DBUF slices. This will cause an infinite loop
++ * in skl_commit_modeset_enables() as it can't find a way to
++ * transition between the old bogus DBUF layout to the new
++ * proper DBUF layout without DBUF allocation overlaps between
++ * the planes (which cannot be allowed or else the hardware
++ * may hang). If we detect a bogus DBUF layout just turn off
++ * all the planes so that skl_commit_modeset_enables() can
++ * simply ignore them.
++ */
++ if (!skl_dbuf_is_misconfigured(i915))
++ return;
++
++ drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
++
++ for_each_intel_crtc(&i915->drm, crtc) {
++ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
++ const struct intel_plane_state *plane_state =
++ to_intel_plane_state(plane->base.state);
++ struct intel_crtc_state *crtc_state =
++ to_intel_crtc_state(crtc->base.state);
++
++ if (plane_state->uapi.visible)
++ intel_plane_disable_noatomic(crtc, plane);
++
++ drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
++
++ memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
++ }
++}
++
+ static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
+ {
+ struct drm_device *dev = crtc->base.dev;
+diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
+index 91f23b7f0af2e..79d89fe22d8c8 100644
+--- a/drivers/gpu/drm/i915/intel_pm.h
++++ b/drivers/gpu/drm/i915/intel_pm.h
+@@ -48,6 +48,7 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
+ struct skl_pipe_wm *out);
+ void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
+ void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
++void skl_wm_sanitize(struct drm_i915_private *dev_priv);
+ bool intel_can_enable_sagv(struct drm_i915_private *dev_priv,
+ const struct intel_bw_state *bw_state);
+ void intel_sagv_pre_plane_update(struct intel_atomic_state *state);
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 6b38bc2811c1b..de8d0558389c4 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
@@ -47523,6 +73715,35 @@ index 3c0b0a8b5250d..4c63209dcf530 100644
void intel_uncore_forcewake_flush(struct intel_uncore *uncore,
enum forcewake_domains fw_domains);
+diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
+index 87428fb23d9ff..a2277a0d6d06f 100644
+--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
++++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
+@@ -222,6 +222,7 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev)
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match = of_match_node(dw_hdmi_imx_dt_ids, np);
+ struct imx_hdmi *hdmi;
++ int ret;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+@@ -243,10 +244,15 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev)
+ hdmi->bridge = of_drm_find_bridge(np);
+ if (!hdmi->bridge) {
+ dev_err(hdmi->dev, "Unable to find bridge\n");
++ dw_hdmi_remove(hdmi->hdmi);
+ return -ENODEV;
+ }
+
+- return component_add(&pdev->dev, &dw_hdmi_imx_ops);
++ ret = component_add(&pdev->dev, &dw_hdmi_imx_ops);
++ if (ret)
++ dw_hdmi_remove(hdmi->hdmi);
++
++ return ret;
+ }
+
+ static int dw_hdmi_imx_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 9558e9e1b431b..cb685fe2039b4 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
@@ -47543,6 +73764,50 @@ index 9558e9e1b431b..cb685fe2039b4 100644
}
static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
+diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
+index e5078d03020d9..fb0e951248f68 100644
+--- a/drivers/gpu/drm/imx/imx-ldb.c
++++ b/drivers/gpu/drm/imx/imx-ldb.c
+@@ -572,6 +572,8 @@ static int imx_ldb_panel_ddc(struct device *dev,
+ edidp = of_get_property(child, "edid", &edid_len);
+ if (edidp) {
+ channel->edid = kmemdup(edidp, edid_len, GFP_KERNEL);
++ if (!channel->edid)
++ return -ENOMEM;
+ } else if (!channel->panel) {
+ /* fallback to display-timings node */
+ ret = of_get_drm_display_mode(child,
+diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
+index a8aba0141ce71..63ba2ad846791 100644
+--- a/drivers/gpu/drm/imx/parallel-display.c
++++ b/drivers/gpu/drm/imx/parallel-display.c
+@@ -75,8 +75,10 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
+ ret = of_get_drm_display_mode(np, &imxpd->mode,
+ &imxpd->bus_flags,
+ OF_USE_NATIVE_MODE);
+- if (ret)
++ if (ret) {
++ drm_mode_destroy(connector->dev, mode);
+ return ret;
++ }
+
+ drm_mode_copy(mode, &imxpd->mode);
+ mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+@@ -217,14 +219,6 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
+ if (!imx_pd_format_supported(bus_fmt))
+ return -EINVAL;
+
+- if (bus_flags &
+- ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
+- DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
+- DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)) {
+- dev_warn(imxpd->dev, "invalid bus_flags (%x)\n", bus_flags);
+- return -EINVAL;
+- }
+-
+ bridge_state->output_bus_cfg.flags = bus_flags;
+ bridge_state->input_bus_cfg.flags = bus_flags;
+ imx_crtc_state->bus_flags = bus_flags;
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 00404ba4126dd..2735b8eb35376 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
@@ -47620,6 +73885,1128 @@ index 5838c44cbf6f0..3196189429bcf 100644
if (mode->clock < 27000)
return MODE_CLOCK_LOW;
+diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
+index 28a519cdf66b8..523fce45f16ba 100644
+--- a/drivers/gpu/drm/meson/Makefile
++++ b/drivers/gpu/drm/meson/Makefile
+@@ -2,6 +2,7 @@
+ meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
+ meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_overlay.o
+ meson-drm-y += meson_rdma.o meson_osd_afbcd.o
++meson-drm-y += meson_encoder_hdmi.o
+
+ obj-$(CONFIG_DRM_MESON) += meson-drm.o
+ obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
+diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
+index bc0d60df04ae4..c98525d60df5b 100644
+--- a/drivers/gpu/drm/meson/meson_drv.c
++++ b/drivers/gpu/drm/meson/meson_drv.c
+@@ -32,6 +32,7 @@
+ #include "meson_osd_afbcd.h"
+ #include "meson_registers.h"
+ #include "meson_venc_cvbs.h"
++#include "meson_encoder_hdmi.h"
+ #include "meson_viu.h"
+ #include "meson_vpp.h"
+ #include "meson_rdma.h"
+@@ -206,8 +207,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
+ priv->compat = match->compat;
+ priv->afbcd.ops = match->afbcd_ops;
+
+- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu");
+- regs = devm_ioremap_resource(dev, res);
++ regs = devm_platform_ioremap_resource_byname(pdev, "vpu");
+ if (IS_ERR(regs)) {
+ ret = PTR_ERR(regs);
+ goto free_drm;
+@@ -302,38 +302,42 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
+ if (priv->afbcd.ops) {
+ ret = priv->afbcd.ops->init(priv);
+ if (ret)
+- return ret;
++ goto free_drm;
+ }
+
+ /* Encoder Initialization */
+
+ ret = meson_venc_cvbs_create(priv);
+ if (ret)
+- goto free_drm;
++ goto exit_afbcd;
+
+ if (has_components) {
+ ret = component_bind_all(drm->dev, drm);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't bind all components\n");
+- goto free_drm;
++ goto exit_afbcd;
+ }
+ }
+
++ ret = meson_encoder_hdmi_init(priv);
++ if (ret)
++ goto exit_afbcd;
++
+ ret = meson_plane_create(priv);
+ if (ret)
+- goto free_drm;
++ goto exit_afbcd;
+
+ ret = meson_overlay_create(priv);
+ if (ret)
+- goto free_drm;
++ goto exit_afbcd;
+
+ ret = meson_crtc_create(priv);
+ if (ret)
+- goto free_drm;
++ goto exit_afbcd;
+
+ ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
+ if (ret)
+- goto free_drm;
++ goto exit_afbcd;
+
+ drm_mode_config_reset(drm);
+
+@@ -351,6 +355,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
+
+ uninstall_irq:
+ free_irq(priv->vsync_irq, drm);
++exit_afbcd:
++ if (priv->afbcd.ops)
++ priv->afbcd.ops->exit(priv);
+ free_drm:
+ drm_dev_put(drm);
+
+@@ -381,10 +388,8 @@ static void meson_drv_unbind(struct device *dev)
+ free_irq(priv->vsync_irq, drm);
+ drm_dev_put(drm);
+
+- if (priv->afbcd.ops) {
+- priv->afbcd.ops->reset(priv);
+- meson_rdma_free(priv);
+- }
++ if (priv->afbcd.ops)
++ priv->afbcd.ops->exit(priv);
+ }
+
+ static const struct component_master_ops meson_drv_master_ops = {
+diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+index 2ed87cfdd7353..fb540a503efed 100644
+--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+@@ -22,14 +22,11 @@
+ #include <drm/drm_probe_helper.h>
+ #include <drm/drm_print.h>
+
+-#include <linux/media-bus-format.h>
+ #include <linux/videodev2.h>
+
+ #include "meson_drv.h"
+ #include "meson_dw_hdmi.h"
+ #include "meson_registers.h"
+-#include "meson_vclk.h"
+-#include "meson_venc.h"
+
+ #define DRIVER_NAME "meson-dw-hdmi"
+ #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
+@@ -135,8 +132,6 @@ struct meson_dw_hdmi_data {
+ };
+
+ struct meson_dw_hdmi {
+- struct drm_encoder encoder;
+- struct drm_bridge bridge;
+ struct dw_hdmi_plat_data dw_plat_data;
+ struct meson_drm *priv;
+ struct device *dev;
+@@ -148,12 +143,8 @@ struct meson_dw_hdmi {
+ struct regulator *hdmi_supply;
+ u32 irq_stat;
+ struct dw_hdmi *hdmi;
+- unsigned long output_bus_fmt;
++ struct drm_bridge *bridge;
+ };
+-#define encoder_to_meson_dw_hdmi(x) \
+- container_of(x, struct meson_dw_hdmi, encoder)
+-#define bridge_to_meson_dw_hdmi(x) \
+- container_of(x, struct meson_dw_hdmi, bridge)
+
+ static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
+ const char *compat)
+@@ -295,14 +286,14 @@ static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
+
+ /* Setup PHY bandwidth modes */
+ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
+- const struct drm_display_mode *mode)
++ const struct drm_display_mode *mode,
++ bool mode_is_420)
+ {
+ struct meson_drm *priv = dw_hdmi->priv;
+ unsigned int pixel_clock = mode->clock;
+
+ /* For 420, pixel clock is half unlike venc clock */
+- if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+- pixel_clock /= 2;
++ if (mode_is_420) pixel_clock /= 2;
+
+ if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
+ dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
+@@ -374,68 +365,25 @@ static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
+ mdelay(2);
+ }
+
+-static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
+- const struct drm_display_mode *mode)
+-{
+- struct meson_drm *priv = dw_hdmi->priv;
+- int vic = drm_match_cea_mode(mode);
+- unsigned int phy_freq;
+- unsigned int vclk_freq;
+- unsigned int venc_freq;
+- unsigned int hdmi_freq;
+-
+- vclk_freq = mode->clock;
+-
+- /* For 420, pixel clock is half unlike venc clock */
+- if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+- vclk_freq /= 2;
+-
+- /* TMDS clock is pixel_clock * 10 */
+- phy_freq = vclk_freq * 10;
+-
+- if (!vic) {
+- meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
+- vclk_freq, vclk_freq, vclk_freq, false);
+- return;
+- }
+-
+- /* 480i/576i needs global pixel doubling */
+- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+- vclk_freq *= 2;
+-
+- venc_freq = vclk_freq;
+- hdmi_freq = vclk_freq;
+-
+- /* VENC double pixels for 1080i, 720p and YUV420 modes */
+- if (meson_venc_hdmi_venc_repeat(vic) ||
+- dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+- venc_freq *= 2;
+-
+- vclk_freq = max(venc_freq, hdmi_freq);
+-
+- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+- venc_freq /= 2;
+-
+- DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
+- phy_freq, vclk_freq, venc_freq, hdmi_freq,
+- priv->venc.hdmi_use_enci);
+-
+- meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
+- venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
+-}
+-
+ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+ const struct drm_display_info *display,
+ const struct drm_display_mode *mode)
+ {
+ struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
++ bool is_hdmi2_sink = display->hdmi.scdc.supported;
+ struct meson_drm *priv = dw_hdmi->priv;
+ unsigned int wr_clk =
+ readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
++ bool mode_is_420 = false;
+
+ DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
+ mode->clock > 340000 ? 40 : 10);
+
++ if (drm_mode_is_420_only(display, mode) ||
++ (!is_hdmi2_sink &&
++ drm_mode_is_420_also(display, mode)))
++ mode_is_420 = true;
++
+ /* Enable clocks */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
+
+@@ -457,8 +405,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
+
+ /* TMDS pattern setup */
+- if (mode->clock > 340000 &&
+- dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
++ if (mode->clock > 340000 && !mode_is_420) {
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
+ 0);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
+@@ -476,7 +423,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
+
+ /* Setup PHY parameters */
+- meson_hdmi_phy_setup_mode(dw_hdmi, mode);
++ meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420);
+
+ /* Setup PHY */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+@@ -622,214 +569,15 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
+ dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
+ hpd_connected);
+
+- drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
++ drm_helper_hpd_irq_event(dw_hdmi->bridge->dev);
++ drm_bridge_hpd_notify(dw_hdmi->bridge,
++ hpd_connected ? connector_status_connected
++ : connector_status_disconnected);
+ }
+
+ return IRQ_HANDLED;
+ }
+
+-static enum drm_mode_status
+-dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
+- const struct drm_display_info *display_info,
+- const struct drm_display_mode *mode)
+-{
+- struct meson_dw_hdmi *dw_hdmi = data;
+- struct meson_drm *priv = dw_hdmi->priv;
+- bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
+- unsigned int phy_freq;
+- unsigned int vclk_freq;
+- unsigned int venc_freq;
+- unsigned int hdmi_freq;
+- int vic = drm_match_cea_mode(mode);
+- enum drm_mode_status status;
+-
+- DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
+-
+- /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
+- if (display_info->max_tmds_clock &&
+- mode->clock > display_info->max_tmds_clock &&
+- !drm_mode_is_420_only(display_info, mode) &&
+- !drm_mode_is_420_also(display_info, mode))
+- return MODE_BAD;
+-
+- /* Check against non-VIC supported modes */
+- if (!vic) {
+- status = meson_venc_hdmi_supported_mode(mode);
+- if (status != MODE_OK)
+- return status;
+-
+- return meson_vclk_dmt_supported_freq(priv, mode->clock);
+- /* Check against supported VIC modes */
+- } else if (!meson_venc_hdmi_supported_vic(vic))
+- return MODE_BAD;
+-
+- vclk_freq = mode->clock;
+-
+- /* For 420, pixel clock is half unlike venc clock */
+- if (drm_mode_is_420_only(display_info, mode) ||
+- (!is_hdmi2_sink &&
+- drm_mode_is_420_also(display_info, mode)))
+- vclk_freq /= 2;
+-
+- /* TMDS clock is pixel_clock * 10 */
+- phy_freq = vclk_freq * 10;
+-
+- /* 480i/576i needs global pixel doubling */
+- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+- vclk_freq *= 2;
+-
+- venc_freq = vclk_freq;
+- hdmi_freq = vclk_freq;
+-
+- /* VENC double pixels for 1080i, 720p and YUV420 modes */
+- if (meson_venc_hdmi_venc_repeat(vic) ||
+- drm_mode_is_420_only(display_info, mode) ||
+- (!is_hdmi2_sink &&
+- drm_mode_is_420_also(display_info, mode)))
+- venc_freq *= 2;
+-
+- vclk_freq = max(venc_freq, hdmi_freq);
+-
+- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+- venc_freq /= 2;
+-
+- dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
+- __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
+-
+- return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
+-}
+-
+-/* Encoder */
+-
+-static const u32 meson_dw_hdmi_out_bus_fmts[] = {
+- MEDIA_BUS_FMT_YUV8_1X24,
+- MEDIA_BUS_FMT_UYYVYY8_0_5X24,
+-};
+-
+-static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
+-{
+- drm_encoder_cleanup(encoder);
+-}
+-
+-static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
+- .destroy = meson_venc_hdmi_encoder_destroy,
+-};
+-
+-static u32 *
+-meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
+- struct drm_bridge_state *bridge_state,
+- struct drm_crtc_state *crtc_state,
+- struct drm_connector_state *conn_state,
+- u32 output_fmt,
+- unsigned int *num_input_fmts)
+-{
+- u32 *input_fmts = NULL;
+- int i;
+-
+- *num_input_fmts = 0;
+-
+- for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
+- if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
+- *num_input_fmts = 1;
+- input_fmts = kcalloc(*num_input_fmts,
+- sizeof(*input_fmts),
+- GFP_KERNEL);
+- if (!input_fmts)
+- return NULL;
+-
+- input_fmts[0] = output_fmt;
+-
+- break;
+- }
+- }
+-
+- return input_fmts;
+-}
+-
+-static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
+- struct drm_bridge_state *bridge_state,
+- struct drm_crtc_state *crtc_state,
+- struct drm_connector_state *conn_state)
+-{
+- struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
+-
+- dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
+-
+- DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
+-
+- return 0;
+-}
+-
+-static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
+-{
+- struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
+- struct meson_drm *priv = dw_hdmi->priv;
+-
+- DRM_DEBUG_DRIVER("\n");
+-
+- writel_bits_relaxed(0x3, 0,
+- priv->io_base + _REG(VPU_HDMI_SETTING));
+-
+- writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+- writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+-}
+-
+-static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
+-{
+- struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
+- struct meson_drm *priv = dw_hdmi->priv;
+-
+- DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
+-
+- if (priv->venc.hdmi_use_enci)
+- writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+- else
+- writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
+-}
+-
+-static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
+- const struct drm_display_mode *mode,
+- const struct drm_display_mode *adjusted_mode)
+-{
+- struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
+- struct meson_drm *priv = dw_hdmi->priv;
+- int vic = drm_match_cea_mode(mode);
+- unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
+- bool yuv420_mode = false;
+-
+- DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
+-
+- if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
+- ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
+- yuv420_mode = true;
+- }
+-
+- /* VENC + VENC-DVI Mode setup */
+- meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
+-
+- /* VCLK Set clock */
+- dw_hdmi_set_vclk(dw_hdmi, mode);
+-
+- if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+- /* Setup YUV420 to HDMI-TX, no 10bit diphering */
+- writel_relaxed(2 | (2 << 2),
+- priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+- else
+- /* Setup YUV444 to HDMI-TX, no 10bit diphering */
+- writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+-}
+-
+-static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
+- .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+- .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+- .atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
+- .atomic_reset = drm_atomic_helper_bridge_reset,
+- .atomic_check = meson_venc_hdmi_encoder_atomic_check,
+- .enable = meson_venc_hdmi_encoder_enable,
+- .disable = meson_venc_hdmi_encoder_disable,
+- .mode_set = meson_venc_hdmi_encoder_mode_set,
+-};
+-
+ /* DW HDMI Regmap */
+
+ static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
+@@ -876,28 +624,6 @@ static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
+ .dwc_write = dw_hdmi_g12a_dwc_write,
+ };
+
+-static bool meson_hdmi_connector_is_available(struct device *dev)
+-{
+- struct device_node *ep, *remote;
+-
+- /* HDMI Connector is on the second port, first endpoint */
+- ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
+- if (!ep)
+- return false;
+-
+- /* If the endpoint node exists, consider it enabled */
+- remote = of_graph_get_remote_port(ep);
+- if (remote) {
+- of_node_put(ep);
+- return true;
+- }
+-
+- of_node_put(ep);
+- of_node_put(remote);
+-
+- return false;
+-}
+-
+ static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
+ {
+ struct meson_drm *priv = meson_dw_hdmi->priv;
+@@ -976,19 +702,11 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+ struct drm_device *drm = data;
+ struct meson_drm *priv = drm->dev_private;
+ struct dw_hdmi_plat_data *dw_plat_data;
+- struct drm_bridge *next_bridge;
+- struct drm_encoder *encoder;
+- struct resource *res;
+ int irq;
+ int ret;
+
+ DRM_DEBUG_DRIVER("\n");
+
+- if (!meson_hdmi_connector_is_available(dev)) {
+- dev_info(drm->dev, "HDMI Output connector not available\n");
+- return -ENODEV;
+- }
+-
+ match = of_device_get_match_data(&pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "failed to get match data\n");
+@@ -1004,7 +722,6 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+ meson_dw_hdmi->dev = dev;
+ meson_dw_hdmi->data = match;
+ dw_plat_data = &meson_dw_hdmi->dw_plat_data;
+- encoder = &meson_dw_hdmi->encoder;
+
+ meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
+ if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
+@@ -1042,8 +759,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+ return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
+ }
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
++ meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(meson_dw_hdmi->hdmitx))
+ return PTR_ERR(meson_dw_hdmi->hdmitx);
+
+@@ -1076,28 +792,11 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+ return ret;
+ }
+
+- /* Encoder */
+-
+- ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
+- DRM_MODE_ENCODER_TMDS, "meson_hdmi");
+- if (ret) {
+- dev_err(priv->dev, "Failed to init HDMI encoder\n");
+- return ret;
+- }
+-
+- meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
+- drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
+-
+- encoder->possible_crtcs = BIT(0);
+-
+ meson_dw_hdmi_init(meson_dw_hdmi);
+
+- DRM_DEBUG_DRIVER("encoder initialized\n");
+-
+ /* Bridge / Connector */
+
+ dw_plat_data->priv_data = meson_dw_hdmi;
+- dw_plat_data->mode_valid = dw_hdmi_mode_valid;
+ dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
+ dw_plat_data->phy_name = "meson_dw_hdmi_phy";
+ dw_plat_data->phy_data = meson_dw_hdmi;
+@@ -1112,15 +811,11 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+
+ platform_set_drvdata(pdev, meson_dw_hdmi);
+
+- meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
+- &meson_dw_hdmi->dw_plat_data);
++ meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev, &meson_dw_hdmi->dw_plat_data);
+ if (IS_ERR(meson_dw_hdmi->hdmi))
+ return PTR_ERR(meson_dw_hdmi->hdmi);
+
+- next_bridge = of_drm_find_bridge(pdev->dev.of_node);
+- if (next_bridge)
+- drm_bridge_attach(encoder, next_bridge,
+- &meson_dw_hdmi->bridge, 0);
++ meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node);
+
+ DRM_DEBUG_DRIVER("HDMI controller initialized\n");
+
+diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+new file mode 100644
+index 0000000000000..db332fa4cd548
+--- /dev/null
++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+@@ -0,0 +1,370 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Copyright (C) 2016 BayLibre, SAS
++ * Author: Neil Armstrong <narmstrong@baylibre.com>
++ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
++ */
++
++#include <linux/clk.h>
++#include <linux/component.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/of_graph.h>
++#include <linux/regulator/consumer.h>
++#include <linux/reset.h>
++
++#include <drm/drm_atomic_helper.h>
++#include <drm/drm_bridge.h>
++#include <drm/drm_device.h>
++#include <drm/drm_edid.h>
++#include <drm/drm_probe_helper.h>
++#include <drm/drm_simple_kms_helper.h>
++
++#include <linux/media-bus-format.h>
++#include <linux/videodev2.h>
++
++#include "meson_drv.h"
++#include "meson_registers.h"
++#include "meson_vclk.h"
++#include "meson_venc.h"
++#include "meson_encoder_hdmi.h"
++
++struct meson_encoder_hdmi {
++ struct drm_encoder encoder;
++ struct drm_bridge bridge;
++ struct drm_bridge *next_bridge;
++ struct meson_drm *priv;
++ unsigned long output_bus_fmt;
++};
++
++#define bridge_to_meson_encoder_hdmi(x) \
++ container_of(x, struct meson_encoder_hdmi, bridge)
++
++static int meson_encoder_hdmi_attach(struct drm_bridge *bridge,
++ enum drm_bridge_attach_flags flags)
++{
++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
++
++ return drm_bridge_attach(bridge->encoder, encoder_hdmi->next_bridge,
++ &encoder_hdmi->bridge, flags);
++}
++
++static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
++ const struct drm_display_mode *mode)
++{
++ struct meson_drm *priv = encoder_hdmi->priv;
++ int vic = drm_match_cea_mode(mode);
++ unsigned int phy_freq;
++ unsigned int vclk_freq;
++ unsigned int venc_freq;
++ unsigned int hdmi_freq;
++
++ vclk_freq = mode->clock;
++
++ /* For 420, pixel clock is half unlike venc clock */
++ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
++ vclk_freq /= 2;
++
++ /* TMDS clock is pixel_clock * 10 */
++ phy_freq = vclk_freq * 10;
++
++ if (!vic) {
++ meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
++ vclk_freq, vclk_freq, vclk_freq, false);
++ return;
++ }
++
++ /* 480i/576i needs global pixel doubling */
++ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
++ vclk_freq *= 2;
++
++ venc_freq = vclk_freq;
++ hdmi_freq = vclk_freq;
++
++ /* VENC double pixels for 1080i, 720p and YUV420 modes */
++ if (meson_venc_hdmi_venc_repeat(vic) ||
++ encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
++ venc_freq *= 2;
++
++ vclk_freq = max(venc_freq, hdmi_freq);
++
++ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
++ venc_freq /= 2;
++
++ dev_dbg(priv->dev, "vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
++ phy_freq, vclk_freq, venc_freq, hdmi_freq,
++ priv->venc.hdmi_use_enci);
++
++ meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
++ venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
++}
++
++static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bridge,
++ const struct drm_display_info *display_info,
++ const struct drm_display_mode *mode)
++{
++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
++ struct meson_drm *priv = encoder_hdmi->priv;
++ bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
++ unsigned int phy_freq;
++ unsigned int vclk_freq;
++ unsigned int venc_freq;
++ unsigned int hdmi_freq;
++ int vic = drm_match_cea_mode(mode);
++ enum drm_mode_status status;
++
++ dev_dbg(priv->dev, "Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
++
++ /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
++ if (display_info->max_tmds_clock &&
++ mode->clock > display_info->max_tmds_clock &&
++ !drm_mode_is_420_only(display_info, mode) &&
++ !drm_mode_is_420_also(display_info, mode))
++ return MODE_BAD;
++
++ /* Check against non-VIC supported modes */
++ if (!vic) {
++ status = meson_venc_hdmi_supported_mode(mode);
++ if (status != MODE_OK)
++ return status;
++
++ return meson_vclk_dmt_supported_freq(priv, mode->clock);
++ /* Check against supported VIC modes */
++ } else if (!meson_venc_hdmi_supported_vic(vic))
++ return MODE_BAD;
++
++ vclk_freq = mode->clock;
++
++ /* For 420, pixel clock is half unlike venc clock */
++ if (drm_mode_is_420_only(display_info, mode) ||
++ (!is_hdmi2_sink &&
++ drm_mode_is_420_also(display_info, mode)))
++ vclk_freq /= 2;
++
++ /* TMDS clock is pixel_clock * 10 */
++ phy_freq = vclk_freq * 10;
++
++ /* 480i/576i needs global pixel doubling */
++ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
++ vclk_freq *= 2;
++
++ venc_freq = vclk_freq;
++ hdmi_freq = vclk_freq;
++
++ /* VENC double pixels for 1080i, 720p and YUV420 modes */
++ if (meson_venc_hdmi_venc_repeat(vic) ||
++ drm_mode_is_420_only(display_info, mode) ||
++ (!is_hdmi2_sink &&
++ drm_mode_is_420_also(display_info, mode)))
++ venc_freq *= 2;
++
++ vclk_freq = max(venc_freq, hdmi_freq);
++
++ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
++ venc_freq /= 2;
++
++ dev_dbg(priv->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
++ __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
++
++ return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
++}
++
++static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state)
++{
++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
++ struct drm_atomic_state *state = bridge_state->base.state;
++ unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
++ struct meson_drm *priv = encoder_hdmi->priv;
++ struct drm_connector_state *conn_state;
++ const struct drm_display_mode *mode;
++ struct drm_crtc_state *crtc_state;
++ struct drm_connector *connector;
++ bool yuv420_mode = false;
++ int vic;
++
++ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
++ if (WARN_ON(!connector))
++ return;
++
++ conn_state = drm_atomic_get_new_connector_state(state, connector);
++ if (WARN_ON(!conn_state))
++ return;
++
++ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
++ if (WARN_ON(!crtc_state))
++ return;
++
++ mode = &crtc_state->adjusted_mode;
++
++ vic = drm_match_cea_mode(mode);
++
++ dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic);
++
++ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
++ ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
++ yuv420_mode = true;
++ }
++
++ /* VENC + VENC-DVI Mode setup */
++ meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
++
++ /* VCLK Set clock */
++ meson_encoder_hdmi_set_vclk(encoder_hdmi, mode);
++
++ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
++ /* Setup YUV420 to HDMI-TX, no 10bit diphering */
++ writel_relaxed(2 | (2 << 2),
++ priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
++ else
++ /* Setup YUV444 to HDMI-TX, no 10bit diphering */
++ writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
++
++ dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
++
++ if (priv->venc.hdmi_use_enci)
++ writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
++ else
++ writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
++}
++
++static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state)
++{
++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
++ struct meson_drm *priv = encoder_hdmi->priv;
++
++ writel_bits_relaxed(0x3, 0,
++ priv->io_base + _REG(VPU_HDMI_SETTING));
++
++ writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
++ writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
++}
++
++static const u32 meson_encoder_hdmi_out_bus_fmts[] = {
++ MEDIA_BUS_FMT_YUV8_1X24,
++ MEDIA_BUS_FMT_UYYVYY8_0_5X24,
++};
++
++static u32 *
++meson_encoder_hdmi_get_inp_bus_fmts(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state,
++ struct drm_crtc_state *crtc_state,
++ struct drm_connector_state *conn_state,
++ u32 output_fmt,
++ unsigned int *num_input_fmts)
++{
++ u32 *input_fmts = NULL;
++ int i;
++
++ *num_input_fmts = 0;
++
++ for (i = 0 ; i < ARRAY_SIZE(meson_encoder_hdmi_out_bus_fmts) ; ++i) {
++ if (output_fmt == meson_encoder_hdmi_out_bus_fmts[i]) {
++ *num_input_fmts = 1;
++ input_fmts = kcalloc(*num_input_fmts,
++ sizeof(*input_fmts),
++ GFP_KERNEL);
++ if (!input_fmts)
++ return NULL;
++
++ input_fmts[0] = output_fmt;
++
++ break;
++ }
++ }
++
++ return input_fmts;
++}
++
++static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state,
++ struct drm_crtc_state *crtc_state,
++ struct drm_connector_state *conn_state)
++{
++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
++ struct drm_connector_state *old_conn_state =
++ drm_atomic_get_old_connector_state(conn_state->state, conn_state->connector);
++ struct meson_drm *priv = encoder_hdmi->priv;
++
++ encoder_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
++
++ dev_dbg(priv->dev, "output_bus_fmt %lx\n", encoder_hdmi->output_bus_fmt);
++
++ if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, conn_state))
++ crtc_state->mode_changed = true;
++
++ return 0;
++}
++
++static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = {
++ .attach = meson_encoder_hdmi_attach,
++ .mode_valid = meson_encoder_hdmi_mode_valid,
++ .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,
++ .atomic_check = meson_encoder_hdmi_atomic_check,
++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
++ .atomic_reset = drm_atomic_helper_bridge_reset,
++};
++
++int meson_encoder_hdmi_init(struct meson_drm *priv)
++{
++ struct meson_encoder_hdmi *meson_encoder_hdmi;
++ struct device_node *remote;
++ int ret;
++
++ meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL);
++ if (!meson_encoder_hdmi)
++ return -ENOMEM;
++
++ /* HDMI Transceiver Bridge */
++ remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0);
++ if (!remote) {
++ dev_err(priv->dev, "HDMI transceiver device is disabled");
++ return 0;
++ }
++
++ 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;
++ }
++
++ /* 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;
++
++ drm_bridge_add(&meson_encoder_hdmi->bridge);
++
++ meson_encoder_hdmi->priv = priv;
++
++ /* Encoder */
++ ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder,
++ DRM_MODE_ENCODER_TMDS);
++ if (ret) {
++ dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret);
++ return ret;
++ }
++
++ 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);
++ if (ret) {
++ dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
++ return ret;
++ }
++
++ /*
++ * We should have now in place:
++ * encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[dw-hdmi connector]
++ */
++
++ dev_dbg(priv->dev, "HDMI encoder initialized\n");
++
++ return 0;
++}
+diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.h b/drivers/gpu/drm/meson/meson_encoder_hdmi.h
+new file mode 100644
+index 0000000000000..ed19494f09563
+--- /dev/null
++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.h
+@@ -0,0 +1,12 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * Copyright (C) 2021 BayLibre, SAS
++ * Author: Neil Armstrong <narmstrong@baylibre.com>
++ */
++
++#ifndef __MESON_ENCODER_HDMI_H
++#define __MESON_ENCODER_HDMI_H
++
++int meson_encoder_hdmi_init(struct meson_drm *priv);
++
++#endif /* __MESON_ENCODER_HDMI_H */
+diff --git a/drivers/gpu/drm/meson/meson_osd_afbcd.c b/drivers/gpu/drm/meson/meson_osd_afbcd.c
+index ffc6b584dbf85..0cdbe899402f8 100644
+--- a/drivers/gpu/drm/meson/meson_osd_afbcd.c
++++ b/drivers/gpu/drm/meson/meson_osd_afbcd.c
+@@ -79,11 +79,6 @@ static bool meson_gxm_afbcd_supported_fmt(u64 modifier, uint32_t format)
+ return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;
+ }
+
+-static int meson_gxm_afbcd_init(struct meson_drm *priv)
+-{
+- return 0;
+-}
+-
+ static int meson_gxm_afbcd_reset(struct meson_drm *priv)
+ {
+ writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,
+@@ -93,6 +88,16 @@ static int meson_gxm_afbcd_reset(struct meson_drm *priv)
+ return 0;
+ }
+
++static int meson_gxm_afbcd_init(struct meson_drm *priv)
++{
++ return 0;
++}
++
++static void meson_gxm_afbcd_exit(struct meson_drm *priv)
++{
++ meson_gxm_afbcd_reset(priv);
++}
++
+ static int meson_gxm_afbcd_enable(struct meson_drm *priv)
+ {
+ writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |
+@@ -172,6 +177,7 @@ static int meson_gxm_afbcd_setup(struct meson_drm *priv)
+
+ struct meson_afbcd_ops meson_afbcd_gxm_ops = {
+ .init = meson_gxm_afbcd_init,
++ .exit = meson_gxm_afbcd_exit,
+ .reset = meson_gxm_afbcd_reset,
+ .enable = meson_gxm_afbcd_enable,
+ .disable = meson_gxm_afbcd_disable,
+@@ -269,6 +275,18 @@ static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format)
+ return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
+ }
+
++static int meson_g12a_afbcd_reset(struct meson_drm *priv)
++{
++ meson_rdma_reset(priv);
++
++ meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
++ VIU_SW_RESET_G12A_OSD1_AFBCD,
++ VIU_SW_RESET);
++ meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
++
++ return 0;
++}
++
+ static int meson_g12a_afbcd_init(struct meson_drm *priv)
+ {
+ int ret;
+@@ -286,16 +304,10 @@ static int meson_g12a_afbcd_init(struct meson_drm *priv)
+ return 0;
+ }
+
+-static int meson_g12a_afbcd_reset(struct meson_drm *priv)
++static void meson_g12a_afbcd_exit(struct meson_drm *priv)
+ {
+- meson_rdma_reset(priv);
+-
+- meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
+- VIU_SW_RESET_G12A_OSD1_AFBCD,
+- VIU_SW_RESET);
+- meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
+-
+- return 0;
++ meson_g12a_afbcd_reset(priv);
++ meson_rdma_free(priv);
+ }
+
+ static int meson_g12a_afbcd_enable(struct meson_drm *priv)
+@@ -380,6 +392,7 @@ static int meson_g12a_afbcd_setup(struct meson_drm *priv)
+
+ struct meson_afbcd_ops meson_afbcd_g12a_ops = {
+ .init = meson_g12a_afbcd_init,
++ .exit = meson_g12a_afbcd_exit,
+ .reset = meson_g12a_afbcd_reset,
+ .enable = meson_g12a_afbcd_enable,
+ .disable = meson_g12a_afbcd_disable,
+diff --git a/drivers/gpu/drm/meson/meson_osd_afbcd.h b/drivers/gpu/drm/meson/meson_osd_afbcd.h
+index 5e5523304f42f..e77ddeb6416f3 100644
+--- a/drivers/gpu/drm/meson/meson_osd_afbcd.h
++++ b/drivers/gpu/drm/meson/meson_osd_afbcd.h
+@@ -14,6 +14,7 @@
+
+ struct meson_afbcd_ops {
+ int (*init)(struct meson_drm *priv);
++ void (*exit)(struct meson_drm *priv);
+ int (*reset)(struct meson_drm *priv);
+ int (*enable)(struct meson_drm *priv);
+ int (*disable)(struct meson_drm *priv);
+diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
+index fd98e8bbc5500..2c7271f545dcc 100644
+--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
++++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
+@@ -529,7 +529,10 @@ static void mgag200_set_format_regs(struct mga_device *mdev,
+ WREG_GFX(3, 0x00);
+ WREG_GFX(4, 0x00);
+ WREG_GFX(5, 0x40);
+- WREG_GFX(6, 0x05);
++ /* GCTL6 should be 0x05, but we configure memmapsl to 0xb8000 (text mode),
++ * so that it doesn't hang when running kexec/kdump on G200_SE rev42.
++ */
++ WREG_GFX(6, 0x0d);
+ WREG_GFX(7, 0x0f);
+ WREG_GFX(8, 0x0f);
+
+diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
+index e9ae22b4f8138..52be08b744ade 100644
+--- a/drivers/gpu/drm/mgag200/mgag200_pll.c
++++ b/drivers/gpu/drm/mgag200/mgag200_pll.c
+@@ -404,9 +404,9 @@ mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pl
+ udelay(50);
+
+ /* program pixel pll register */
+- WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+- WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+- WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
++ WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
++ WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
++ WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
+
+ udelay(50);
+
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 3ddf739a6f9b8..c49b239231190 100644
--- a/drivers/gpu/drm/msm/Kconfig
@@ -47660,10 +75047,38 @@ index 8b73f70766a47..4347a104755a9 100644
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
-index 267a880811d65..b681c45520bbd 100644
+index 267a880811d65..9b41e2f82fc23 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
-@@ -1424,17 +1424,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
+@@ -658,19 +658,23 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
+ {
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ const u32 *regs = a6xx_protect;
+- unsigned i, count = ARRAY_SIZE(a6xx_protect), count_max = 32;
+-
+- BUILD_BUG_ON(ARRAY_SIZE(a6xx_protect) > 32);
+- BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48);
++ unsigned i, count, count_max;
+
+ if (adreno_is_a650(adreno_gpu)) {
+ regs = a650_protect;
+ count = ARRAY_SIZE(a650_protect);
+ count_max = 48;
++ BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48);
+ } else if (adreno_is_a660_family(adreno_gpu)) {
+ regs = a660_protect;
+ count = ARRAY_SIZE(a660_protect);
+ count_max = 48;
++ BUILD_BUG_ON(ARRAY_SIZE(a660_protect) > 48);
++ } else {
++ regs = a6xx_protect;
++ count = ARRAY_SIZE(a6xx_protect);
++ count_max = 32;
++ BUILD_BUG_ON(ARRAY_SIZE(a6xx_protect) > 32);
+ }
+
+ /*
+@@ -1424,17 +1428,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
@@ -47690,7 +75105,7 @@ index 267a880811d65..b681c45520bbd 100644
}
/*
-@@ -1471,13 +1478,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
+@@ -1471,13 +1482,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
}
gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval);
@@ -47704,7 +75119,7 @@ index 267a880811d65..b681c45520bbd 100644
}
static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu)
-@@ -1557,6 +1557,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
+@@ -1557,6 +1561,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
for (i = 0; i < gpu->nr_rings; i++)
a6xx_gpu->shadow[i] = 0;
@@ -47713,6 +75128,15 @@ index 267a880811d65..b681c45520bbd 100644
return 0;
}
+@@ -1705,7 +1711,7 @@ a6xx_create_private_address_space(struct msm_gpu *gpu)
+ return ERR_CAST(mmu);
+
+ return msm_gem_address_space_create(mmu,
+- "gpu", 0x100000000ULL, 0x1ffffffffULL);
++ "gpu", 0x100000000ULL, SZ_4G);
+ }
+
+ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index e8f65cd8eca6e..bfac7e47cb396 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -47732,6 +75156,19 @@ index e8f65cd8eca6e..bfac7e47cb396 100644
/* Get the CX GMU registers from AHB */
_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0],
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+index 0e9d3fa1544be..6bde3e234ec81 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+@@ -1107,7 +1107,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
+ }
+
+
+- if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort &&
++ if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS &&
+ dpu_enc->cur_master->hw_mdptop &&
+ dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select)
+ dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select(
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
index a98e964c3b6fa..355894a3b48c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
@@ -47810,6 +75247,53 @@ index ae48f41821cfe..93d916858d5ad 100644
aspace = msm_gem_address_space_create(mmu, "dpu1",
0x1000, 0x100000000 - 0x1000);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+index f9c83d6e427ad..24fbaf562d418 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+@@ -35,6 +35,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
+ {
+ int i;
+
++ for (i = 0; i < ARRAY_SIZE(rm->dspp_blks); i++) {
++ struct dpu_hw_dspp *hw;
++
++ if (rm->dspp_blks[i]) {
++ hw = to_dpu_hw_dspp(rm->dspp_blks[i]);
++ dpu_hw_dspp_destroy(hw);
++ }
++ }
+ for (i = 0; i < ARRAY_SIZE(rm->pingpong_blks); i++) {
+ struct dpu_hw_pingpong *hw;
+
+diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+index c6b69afcbac89..50e854207c70a 100644
+--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+@@ -90,7 +90,10 @@ static void mdp5_plane_reset(struct drm_plane *plane)
+ __drm_atomic_helper_plane_destroy_state(plane->state);
+
+ kfree(to_mdp5_plane_state(plane->state));
++ plane->state = NULL;
+ mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL);
++ if (!mdp5_state)
++ return;
+
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+ mdp5_state->base.zpos = STAGE_BASE;
+diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
+index cabe15190ec18..369e57f73a470 100644
+--- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
++++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
+@@ -169,6 +169,8 @@ void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len,
+ va_list va;
+
+ new_blk = kzalloc(sizeof(struct msm_disp_state_block), GFP_KERNEL);
++ if (!new_blk)
++ return;
+
+ va_start(va, fmt);
+
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index eb40d8413bca9..6d36f63c33388 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -47869,6 +75353,67 @@ index eb40d8413bca9..6d36f63c33388 100644
}
int dp_aux_register(struct drm_dp_aux *dp_aux)
+diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+index 62e75dc8afc63..4af281d97493f 100644
+--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+@@ -1744,6 +1744,9 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
+ /* end with failure */
+ break; /* lane == 1 already */
+ }
++
++ /* stop link training before start re training */
++ dp_ctrl_clear_training_pattern(ctrl);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
+index a0392e4d8134c..d5198b435638c 100644
+--- a/drivers/gpu/drm/msm/dp/dp_display.c
++++ b/drivers/gpu/drm/msm/dp/dp_display.c
+@@ -1442,6 +1442,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
+ struct drm_encoder *encoder)
+ {
+ struct msm_drm_private *priv;
++ struct dp_display_private *dp_priv;
+ int ret;
+
+ if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
+@@ -1450,6 +1451,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
+ priv = dev->dev_private;
+ dp_display->drm_dev = dev;
+
++ dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
++
+ ret = dp_display_request_irq(dp_display);
+ if (ret) {
+ DRM_ERROR("request_irq failed, ret=%d\n", ret);
+@@ -1467,6 +1470,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
+ return ret;
+ }
+
++ dp_priv->panel->connector = dp_display->connector;
++
+ priv->connectors[priv->num_connectors++] = dp_display->connector;
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
+index 2181b60e1d1d8..62b742e701d2c 100644
+--- a/drivers/gpu/drm/msm/dp/dp_panel.c
++++ b/drivers/gpu/drm/msm/dp/dp_panel.c
+@@ -206,12 +206,6 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
+ rc = -ETIMEDOUT;
+ goto end;
+ }
+-
+- /* fail safe edid */
+- mutex_lock(&connector->dev->mode_config.mutex);
+- if (drm_add_modes_noedid(connector, 640, 480))
+- drm_set_preferred_mode(connector, 640, 480);
+- mutex_unlock(&connector->dev->mode_config.mutex);
+ }
+
+ if (panel->aux_cfg_update_done) {
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 75ae3008b68f4..122fadcf7cc1e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
@@ -47926,7 +75471,7 @@ index b50db91cb8a7e..a63666e59d19e 100644
struct msm_dsi_phy_shared_timings *phy_shared_timings,
bool is_bonded_dsi, struct msm_dsi_phy *phy);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
-index c86b5090fae60..dc85974c78975 100644
+index c86b5090fae60..eea679a52e863 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -115,16 +115,16 @@ struct msm_dsi_host {
@@ -48034,7 +75579,7 @@ index c86b5090fae60..dc85974c78975 100644
+
+ /* do not autoenable, will be enabled later */
+ ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq,
-+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
++ IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
+ "dsi_isr", msm_host);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ%u: %d\n",
@@ -48093,7 +75638,7 @@ index c86b5090fae60..dc85974c78975 100644
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
-index c41d39f5b7cf4..fa4c396df6a92 100644
+index c41d39f5b7cf4..6e43672f58078 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
@@ -48133,7 +75678,12 @@ index c41d39f5b7cf4..fa4c396df6a92 100644
/* Save PHY status if it is a clock source */
msm_dsi_phy_pll_save_state(msm_dsi->phy);
-@@ -631,23 +647,6 @@ fail:
+@@ -627,27 +643,10 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
+ return connector;
+
+ fail:
+- connector->funcs->destroy(msm_dsi->connector);
++ connector->funcs->destroy(connector);
return ERR_PTR(ret);
}
@@ -48177,6 +75727,116 @@ index 8c65ef6968caf..a878b8b079c64 100644
ret = dsi_phy_enable_resource(phy);
if (ret) {
DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n",
+diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+index d8128f50b0dd5..0b782cc18b3f4 100644
+--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+@@ -562,7 +562,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov
+ char clk_name[32], parent[32], vco_name[32];
+ char parent2[32], parent3[32], parent4[32];
+ struct clk_init_data vco_init = {
+- .parent_names = (const char *[]){ "xo" },
++ .parent_data = &(const struct clk_parent_data) {
++ .fw_name = "ref",
++ },
+ .num_parents = 1,
+ .name = vco_name,
+ .flags = CLK_IGNORE_UNUSED,
+diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+index 5b4e991f220d6..1c1e9861b93f7 100644
+--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+@@ -804,7 +804,9 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov
+ {
+ char clk_name[32], parent[32], vco_name[32];
+ struct clk_init_data vco_init = {
+- .parent_names = (const char *[]){ "xo" },
++ .parent_data = &(const struct clk_parent_data) {
++ .fw_name = "ref",
++ },
+ .num_parents = 1,
+ .name = vco_name,
+ .flags = CLK_IGNORE_UNUSED,
+diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+index 2da673a2add69..48eab80b548e1 100644
+--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+@@ -521,7 +521,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
+ {
+ char clk_name[32], parent1[32], parent2[32], vco_name[32];
+ struct clk_init_data vco_init = {
+- .parent_names = (const char *[]){ "xo" },
++ .parent_data = &(const struct clk_parent_data) {
++ .fw_name = "ref", .name = "xo",
++ },
+ .num_parents = 1,
+ .name = vco_name,
+ .flags = CLK_IGNORE_UNUSED,
+diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+index 71ed4aa0dc67e..fc56cdcc9ad64 100644
+--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+@@ -385,7 +385,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
+ {
+ char *clk_name, *parent_name, *vco_name;
+ struct clk_init_data vco_init = {
+- .parent_names = (const char *[]){ "pxo" },
++ .parent_data = &(const struct clk_parent_data) {
++ .fw_name = "ref",
++ },
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED,
+ .ops = &clk_ops_dsi_pll_28nm_vco,
+diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+index cb297b08458e4..8cc1ef8199ac9 100644
+--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+@@ -590,7 +590,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
+ char clk_name[32], parent[32], vco_name[32];
+ char parent2[32], parent3[32], parent4[32];
+ struct clk_init_data vco_init = {
+- .parent_names = (const char *[]){ "bi_tcxo" },
++ .parent_data = &(const struct clk_parent_data) {
++ .fw_name = "ref",
++ },
+ .num_parents = 1,
+ .name = vco_name,
+ .flags = CLK_IGNORE_UNUSED,
+@@ -864,20 +866,26 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
+ /* Alter PHY configurations if data rate less than 1.5GHZ*/
+ less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000);
+
+- /* For C-PHY, no low power settings for lower clk rate */
+- if (phy->cphy_mode)
+- less_than_1500_mhz = false;
+-
+ if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
+ vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
+- glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
+- glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
++ if (phy->cphy_mode) {
++ glbl_rescode_top_ctrl = 0x00;
++ glbl_rescode_bot_ctrl = 0x3c;
++ } else {
++ glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
++ glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
++ }
+ glbl_str_swi_cal_sel_ctrl = 0x00;
+ glbl_hstx_str_ctrl_0 = 0x88;
+ } else {
+ vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59;
+- glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;
+- glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88;
++ if (phy->cphy_mode) {
++ glbl_str_swi_cal_sel_ctrl = 0x03;
++ glbl_hstx_str_ctrl_0 = 0x66;
++ } else {
++ glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;
++ glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88;
++ }
+ glbl_rescode_top_ctrl = 0x03;
+ glbl_rescode_bot_ctrl = 0x3c;
+ }
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 737453b6e5966..94f948ef279d1 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -48301,10 +75961,18 @@ index d4e09703a87db..bbf999c665174 100644
return ret;
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
-index 22308a1b66fc3..cb52ac01e5122 100644
+index 22308a1b66fc3..d280dd64744de 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
-@@ -1055,8 +1055,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
+@@ -937,6 +937,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m,
+ get_pid_task(aspace->pid, PIDTYPE_PID);
+ if (task) {
+ comm = kstrdup(task->comm, GFP_KERNEL);
++ put_task_struct(task);
+ } else {
+ comm = NULL;
+ }
+@@ -1055,8 +1056,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -48314,7 +75982,7 @@ index 22308a1b66fc3..cb52ac01e5122 100644
vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags));
return 0;
-@@ -1132,6 +1131,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
+@@ -1132,6 +1132,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
msm_obj->flags = flags;
msm_obj->madv = MSM_MADV_WILLNEED;
@@ -48322,7 +75990,7 @@ index 22308a1b66fc3..cb52ac01e5122 100644
INIT_LIST_HEAD(&msm_obj->vmas);
*obj = &msm_obj->base;
-@@ -1166,7 +1166,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32
+@@ -1166,7 +1167,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32
ret = msm_gem_new_impl(dev, size, flags, &obj);
if (ret)
@@ -48331,7 +75999,7 @@ index 22308a1b66fc3..cb52ac01e5122 100644
msm_obj = to_msm_bo(obj);
-@@ -1250,7 +1250,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
+@@ -1250,7 +1251,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
if (ret)
@@ -48483,6 +76151,71 @@ index 7739f46470d3e..99fee4d8cd318 100644
if (!disp)
return -ENOMEM;
+diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
+index 1cbd71abc80aa..aa8ed08fe9a7c 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
++++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
+@@ -46,8 +46,9 @@ static bool
+ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
+ struct nouveau_backlight *bl)
+ {
+- const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
+- if (nb < 0 || nb >= 100)
++ const int nb = ida_alloc_max(&bl_ida, 99, GFP_KERNEL);
++
++ if (nb < 0)
+ return false;
+ if (nb > 0)
+ snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
+@@ -101,7 +102,6 @@ nv40_backlight_init(struct nouveau_encoder *encoder,
+ if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
+ return -ENODEV;
+
+- props->type = BACKLIGHT_RAW;
+ props->max_brightness = 31;
+ *ops = &nv40_bl_ops;
+ return 0;
+@@ -294,7 +294,8 @@ nv50_backlight_init(struct nouveau_backlight *bl,
+ struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
+ struct nvif_object *device = &drm->client.device.object;
+
+- if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
++ if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)) ||
++ nv_conn->base.status != connector_status_connected)
+ return -ENODEV;
+
+ if (nv_conn->type == DCB_CONNECTOR_eDP) {
+@@ -339,7 +340,6 @@ nv50_backlight_init(struct nouveau_backlight *bl,
+ else
+ *ops = &nva3_bl_ops;
+
+- props->type = BACKLIGHT_RAW;
+ props->max_brightness = 100;
+
+ return 0;
+@@ -407,11 +407,12 @@ nouveau_backlight_init(struct drm_connector *connector)
+ goto fail_alloc;
+ }
+
++ props.type = BACKLIGHT_RAW;
+ bl->dev = backlight_device_register(backlight_name, connector->kdev,
+ nv_encoder, ops, &props);
+ if (IS_ERR(bl->dev)) {
+ if (bl->id >= 0)
+- ida_simple_remove(&bl_ida, bl->id);
++ ida_free(&bl_ida, bl->id);
+ ret = PTR_ERR(bl->dev);
+ goto fail_alloc;
+ }
+@@ -439,7 +440,7 @@ nouveau_backlight_fini(struct drm_connector *connector)
+ return;
+
+ if (bl->id >= 0)
+- ida_simple_remove(&bl_ida, bl->id);
++ ida_free(&bl_ida, bl->id);
+
+ backlight_device_unregister(bl->dev);
+ nv_conn->backlight = NULL;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 6109cd9e33991..e7efd9ede8e4b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -48761,6 +76494,19 @@ index ca75c5f6ecaf8..88d262ba648cf 100644
subdev = nvkm_device_subdev(device, (type), (j)); \
if (ret) { \
nvkm_subdev_del(&subdev); \
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+index d0d52c1d4aee0..950a3de3e1166 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+@@ -123,7 +123,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
+
+ mutex_init(&tdev->iommu.mutex);
+
+- if (iommu_present(&platform_bus_type)) {
++ if (device_iommu_mapped(dev)) {
+ tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
+ if (!tdev->iommu.domain)
+ goto error;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c
index 6e3c450eaacef..3ff49344abc77 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c
@@ -48832,6 +76578,27 @@ index fb9132a39bb1a..fd97a935a380e 100644
}
return 0;
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
+index 667fa016496ee..a6ea89a5d51ab 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
+@@ -142,11 +142,12 @@ nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver,
+
+ hsfw->imem_size = desc->code_size;
+ hsfw->imem_tag = desc->start_tag;
+- hsfw->imem = kmalloc(desc->code_size, GFP_KERNEL);
+- memcpy(hsfw->imem, data + desc->code_off, desc->code_size);
+-
++ hsfw->imem = kmemdup(data + desc->code_off, desc->code_size, GFP_KERNEL);
+ nvkm_firmware_put(fw);
+- return 0;
++ if (!hsfw->imem)
++ return -ENOMEM;
++ else
++ return 0;
+ }
+
+ int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c
index d0f52d59fc2f9..64e423dddd9e7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c
@@ -48962,10 +76729,10 @@ index 5968c7696596c..40439e329aa9f 100644
.reset = gf100_pmu_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
-index 148706977eec7..e1772211b0a4b 100644
+index 148706977eec7..612310d5d4812 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
-@@ -211,7 +211,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
+@@ -211,11 +211,12 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
static const struct nvkm_pmu_func
gm20b_pmu = {
@@ -48974,10 +76741,24 @@ index 148706977eec7..e1772211b0a4b 100644
.enabled = gf100_pmu_enabled,
.intr = gt215_pmu_intr,
.recv = gm20b_pmu_recv,
+ .initmsg = gm20b_pmu_initmsg,
++ .reset = gf100_pmu_reset,
+ };
+
+ #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
-index 00da1b873ce81..6bf7fc1bd1e3b 100644
+index 00da1b873ce81..1a6f9c3af5ecd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
+@@ -23,7 +23,7 @@
+ */
+ #include "priv.h"
+
+-static void
++void
+ gp102_pmu_reset(struct nvkm_pmu *pmu)
+ {
+ struct nvkm_device *device = pmu->subdev.device;
@@ -39,7 +39,7 @@ gp102_pmu_enabled(struct nvkm_pmu *pmu)
static const struct nvkm_pmu_func
@@ -48988,10 +76769,10 @@ index 00da1b873ce81..6bf7fc1bd1e3b 100644
.reset = gp102_pmu_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
-index 461f722656e24..ba1583bb618b2 100644
+index 461f722656e24..94cfb1791af6e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
-@@ -78,7 +78,7 @@ gp10b_pmu_acr = {
+@@ -78,11 +78,12 @@ gp10b_pmu_acr = {
static const struct nvkm_pmu_func
gp10b_pmu = {
@@ -49000,11 +76781,20 @@ index 461f722656e24..ba1583bb618b2 100644
.enabled = gf100_pmu_enabled,
.intr = gt215_pmu_intr,
.recv = gm20b_pmu_recv,
+ .initmsg = gm20b_pmu_initmsg,
++ .reset = gp102_pmu_reset,
+ };
+
+ #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
-index e7860d1773539..bcaade758ff72 100644
+index e7860d1773539..21abf31f44420 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
-@@ -44,6 +44,8 @@ void gf100_pmu_reset(struct nvkm_pmu *);
+@@ -41,9 +41,12 @@ int gt215_pmu_send(struct nvkm_pmu *, u32[2], u32, u32, u32, u32);
+
+ bool gf100_pmu_enabled(struct nvkm_pmu *);
+ void gf100_pmu_reset(struct nvkm_pmu *);
++void gp102_pmu_reset(struct nvkm_pmu *pmu);
void gk110_pmu_pgob(struct nvkm_pmu *, bool);
@@ -49013,6 +76803,19 @@ index e7860d1773539..bcaade758ff72 100644
void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64);
void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
int gm20b_pmu_acr_boot(struct nvkm_falcon *);
+diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
+index 418638e6e3b0a..af1402d83d51c 100644
+--- a/drivers/gpu/drm/panel/Kconfig
++++ b/drivers/gpu/drm/panel/Kconfig
+@@ -83,6 +83,8 @@ config DRM_PANEL_SIMPLE
+ depends on PM
+ select VIDEOMODE_HELPERS
+ select DRM_DP_AUX_BUS
++ select DRM_DP_HELPER
++ select DRM_KMS_HELPER
+ help
+ DRM panel driver for dumb panels that need at most a regulator and
+ a GPIO to be powered up. Optionally a backlight can be attached so
diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
index 581661b506f81..f9c1f7bc8218c 100644
--- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
@@ -49032,6 +76835,22 @@ index 581661b506f81..f9c1f7bc8218c 100644
}
static int feiyang_dsi_remove(struct mipi_dsi_device *dsi)
+diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+index 2c3378a259b1e..e1542451ef9d0 100644
+--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
++++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+@@ -612,8 +612,10 @@ static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
+ int ret;
+
+ vcc = devm_regulator_get_optional(dev, "vcc");
+- if (IS_ERR(vcc))
++ if (IS_ERR(vcc)) {
+ dev_err(dev, "get optional vcc failed\n");
++ vcc = NULL;
++ }
+
+ dbidev = devm_drm_dev_alloc(dev, &ili9341_dbi_driver,
+ struct mipi_dbi_dev, drm);
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index aea3162253914..f194b62e290ca 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -49136,6 +76955,51 @@ index 3c20beeb17819..3991f5d950af4 100644
}
static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
+diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
+index 46029c5610c80..145047e193946 100644
+--- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
++++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
+@@ -229,7 +229,7 @@ static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts,
+
+ ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
+ if (ret)
+- dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret);
++ dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
+ }
+
+ static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val)
+@@ -265,7 +265,7 @@ static int rpi_touchscreen_noop(struct drm_panel *panel)
+ return 0;
+ }
+
+-static int rpi_touchscreen_enable(struct drm_panel *panel)
++static int rpi_touchscreen_prepare(struct drm_panel *panel)
+ {
+ struct rpi_touchscreen *ts = panel_to_ts(panel);
+ int i;
+@@ -295,6 +295,13 @@ static int rpi_touchscreen_enable(struct drm_panel *panel)
+ rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01);
+ msleep(100);
+
++ return 0;
++}
++
++static int rpi_touchscreen_enable(struct drm_panel *panel)
++{
++ struct rpi_touchscreen *ts = panel_to_ts(panel);
++
+ /* Turn on the backlight. */
+ rpi_touchscreen_i2c_write(ts, REG_PWM, 255);
+
+@@ -349,7 +356,7 @@ static int rpi_touchscreen_get_modes(struct drm_panel *panel,
+ static const struct drm_panel_funcs rpi_touchscreen_funcs = {
+ .disable = rpi_touchscreen_disable,
+ .unprepare = rpi_touchscreen_noop,
+- .prepare = rpi_touchscreen_noop,
++ .prepare = rpi_touchscreen_prepare,
+ .enable = rpi_touchscreen_enable,
+ .get_modes = rpi_touchscreen_get_modes,
+ };
diff --git a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
index a3782830ae3c4..1fb579a574d9f 100644
--- a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
@@ -49199,7 +77063,7 @@ index b937e24dac8e0..25829a0a8e801 100644
static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
-index 9b6c4e6c38a1b..b7b654f2dfd90 100644
+index 9b6c4e6c38a1b..f9242c19b4582 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -721,6 +721,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc,
@@ -49210,6 +77074,32 @@ index 9b6c4e6c38a1b..b7b654f2dfd90 100644
} else {
if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
panel_simple_parse_panel_timing_node(dev, panel, &dt);
+@@ -2509,7 +2510,7 @@ static const struct display_timing innolux_g070y2_l01_timing = {
+ static const struct panel_desc innolux_g070y2_l01 = {
+ .timings = &innolux_g070y2_l01_timing,
+ .num_timings = 1,
+- .bpc = 6,
++ .bpc = 8,
+ .size = {
+ .width = 152,
+ .height = 91,
+diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
+index bbe628b306ee3..f8355de6e335d 100644
+--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
++++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
+@@ -360,8 +360,11 @@ int panfrost_gpu_init(struct panfrost_device *pfdev)
+
+ panfrost_gpu_init_features(pfdev);
+
+- dma_set_mask_and_coherent(pfdev->dev,
++ err = dma_set_mask_and_coherent(pfdev->dev,
+ DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features)));
++ if (err)
++ return err;
++
+ dma_set_max_seg_size(pfdev->dev, UINT_MAX);
+
+ irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu");
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 0fce73b9a6469..70bd84b7ef2b0 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -49224,6 +77114,19 @@ index 0fce73b9a6469..70bd84b7ef2b0 100644
return;
if (!radeon_encoder->enc_priv)
+diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
+index 607ad5620bd99..1546abcadacf4 100644
+--- a/drivers/gpu/drm/radeon/radeon_connectors.c
++++ b/drivers/gpu/drm/radeon/radeon_connectors.c
+@@ -204,7 +204,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
+
+ /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
+ if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
+- if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
++ if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
+ (mode_clock * 5/4 <= max_tmds_clock))
+ bpc = 10;
+ else
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 458f92a708879..a36a4f2c76b09 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
@@ -49620,6 +77523,22 @@ index ca7cc82125cbc..8c873fcd0e99f 100644
.type = DRM_PLANE_TYPE_CURSOR },
};
+diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
+index 6b4759ed6bfd4..c491429f1a029 100644
+--- a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
++++ b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
+@@ -131,8 +131,10 @@ sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
+ return false;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+- if (!txmsg)
++ if (!txmsg) {
++ kfree(out);
+ return false;
++ }
+
+ drm_dp_encode_sideband_req(in, txmsg);
+ ret = drm_dp_decode_sideband_req(txmsg, out);
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5755f0432e774..8c796de53222c 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
@@ -49632,6 +77551,32 @@ index 5755f0432e774..8c796de53222c 100644
select PHY_SUN6I_MIPI_DPHY
help
Choose this option if you want have an Allwinner SoC with
+diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
+index edb60ae0a9b75..faecc2935039b 100644
+--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
++++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
+@@ -222,13 +222,11 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
+
+ /* Set the physical address of the buffer in memory */
+ paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
+- paddr -= PHYS_OFFSET;
+ DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr);
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
+
+ if (fb->format->num_planes > 1) {
+ paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1);
+- paddr -= PHYS_OFFSET;
+ DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr);
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
+ paddr);
+@@ -236,7 +234,6 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
+
+ if (fb->format->num_planes > 2) {
+ paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2);
+- paddr -= PHYS_OFFSET;
+ DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr);
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG,
+ paddr);
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h
index a55a38ad849c1..022cafa6c06cb 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
@@ -49663,6 +77608,25 @@ index b64d93da651d2..5e2b0175df36f 100644
hdmi->phy = phy;
+diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
+index 145833a9d82d4..5b3fbee186713 100644
+--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
+@@ -111,10 +111,10 @@
+ /* format 13 is semi-planar YUV411 VUVU */
+ #define SUN8I_MIXER_FBFMT_YUV411 14
+ /* format 15 doesn't exist */
+-/* format 16 is P010 YVU */
+-#define SUN8I_MIXER_FBFMT_P010_YUV 17
+-/* format 18 is P210 YVU */
+-#define SUN8I_MIXER_FBFMT_P210_YUV 19
++#define SUN8I_MIXER_FBFMT_P010_YUV 16
++/* format 17 is P010 YVU */
++#define SUN8I_MIXER_FBFMT_P210_YUV 18
++/* format 19 is P210 YVU */
+ /* format 20 is packed YVU444 10-bit */
+ /* format 21 is packed YUV444 10-bit */
+
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 8d37d6b00562a..611cd8dad46ed 100644
--- a/drivers/gpu/drm/tegra/drm.c
@@ -49696,6 +77660,22 @@ index 8d37d6b00562a..611cd8dad46ed 100644
/*
* If the host1x client is already attached to an IOMMU domain that is
* not the shared IOMMU domain, don't try to attach it to a different
+diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
+index f46d377f0c304..de1333dc0d867 100644
+--- a/drivers/gpu/drm/tegra/dsi.c
++++ b/drivers/gpu/drm/tegra/dsi.c
+@@ -1538,8 +1538,10 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
+ dsi->slave = platform_get_drvdata(gangster);
+ of_node_put(np);
+
+- if (!dsi->slave)
++ if (!dsi->slave) {
++ put_device(&gangster->dev);
+ return -EPROBE_DEFER;
++ }
+
+ dsi->slave->master = dsi;
+ }
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index de288cba39055..ba3722f1b8651 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
@@ -49827,7 +77807,7 @@ index c02010ff2b7f2..da4af53719917 100644
virt = tegra_drm_alloc(tegra, size, &iova);
}
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
-index 481b48bde0473..5a6e89825bc2f 100644
+index 481b48bde0473..3e3f9ba1e8858 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -458,7 +458,7 @@ static struct drm_display_mode simpledrm_mode(unsigned int width,
@@ -49839,6 +77819,16 @@ index 481b48bde0473..5a6e89825bc2f 100644
drm_mode_set_name(&mode);
return mode;
+@@ -779,6 +779,9 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev)
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
++ drm_connector_set_panel_orientation_with_quirk(connector,
++ DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
++ mode->hdisplay, mode->vdisplay);
+
+ formats = simpledrm_device_formats(sdev, &nformats);
+
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index bb9e02c31946e..900edaf5d68ee 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
@@ -50010,8 +78000,34 @@ index 3750fd2161317..930574ad2bca9 100644
if (ret < 1) {
DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
kfree(read_buff);
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
+index 9403c3b36aca6..6407a006d6ec4 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -221,6 +221,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
+ int ret;
+ u32 mmu_debug;
+ u32 ident1;
++ u64 mask;
+
+
+ v3d = devm_drm_dev_alloc(dev, &v3d_drm_driver, struct v3d_dev, drm);
+@@ -240,8 +241,11 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
+ return ret;
+
+ mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
+- dma_set_mask_and_coherent(dev,
+- DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)));
++ mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
++ ret = dma_set_mask_and_coherent(dev, mask);
++ if (ret)
++ return ret;
++
+ v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
+
+ ident1 = V3D_READ(V3D_HUB_IDENT1);
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
-index 5689da118197e..772b5831bcc6f 100644
+index 5689da118197e..805d6f6cba0e2 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -197,8 +197,8 @@ v3d_clean_caches(struct v3d_dev *v3d)
@@ -50025,6 +78041,40 @@ index 5689da118197e..772b5831bcc6f 100644
}
mutex_lock(&v3d->cache_clean_lock);
+@@ -625,7 +625,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+
+ if (!render->base.perfmon) {
+ ret = -ENOENT;
+- goto fail;
++ goto fail_perfmon;
+ }
+ }
+
+@@ -678,6 +678,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
++fail_perfmon:
+ drm_gem_unlock_reservations(last_job->bo,
+ last_job->bo_count, &acquire_ctx);
+ fail:
+@@ -854,7 +855,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
+ args->perfmon_id);
+ if (!job->base.perfmon) {
+ ret = -ENOENT;
+- goto fail;
++ goto fail_perfmon;
+ }
+ }
+
+@@ -886,6 +887,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
++fail_perfmon:
+ drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,
+ &acquire_ctx);
+ fail:
diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c
index f28779715ccda..c9e8b3a63c621 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_main.c
@@ -50214,9 +78264,18 @@ index ef73e0aaf7261..4b550ebd9572d 100644
void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state);
void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
-index a185027911ce5..d09c1ea60c04e 100644
+index a185027911ce5..ca85063166609 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
+@@ -846,7 +846,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
+ unsigned long phy_clock;
+ int ret;
+
+- ret = pm_runtime_get_sync(dev);
++ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
+ DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port);
+ return;
@@ -1262,7 +1262,6 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
@@ -50259,10 +78318,18 @@ index a185027911ce5..d09c1ea60c04e 100644
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
-index ed8a4b7f8b6e2..9170d948b4483 100644
+index ed8a4b7f8b6e2..ef7bea7c43a0f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -94,6 +94,7 @@
+@@ -38,6 +38,7 @@
+ #include <drm/drm_scdc_helper.h>
+ #include <linux/clk.h>
+ #include <linux/component.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/of_address.h>
+ #include <linux/of_gpio.h>
+@@ -94,6 +95,7 @@
# define VC4_HD_M_SW_RST BIT(2)
# define VC4_HD_M_ENABLE BIT(0)
@@ -50270,7 +78337,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
#define CEC_CLOCK_FREQ 40000
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
-@@ -161,12 +162,16 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
+@@ -161,12 +163,16 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
#endif
@@ -50287,7 +78354,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
if (vc4_hdmi->hpd_gpio &&
gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) {
connected = true;
-@@ -187,10 +192,13 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+@@ -187,10 +193,13 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
}
}
@@ -50301,7 +78368,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
return connector_status_disconnected;
}
-@@ -627,7 +635,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
+@@ -627,7 +636,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
vc4_hdmi->variant->phy_disable(vc4_hdmi);
clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
@@ -50309,7 +78376,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
clk_disable_unprepare(vc4_hdmi->pixel_clock);
ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
-@@ -893,28 +900,10 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+@@ -893,28 +901,10 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
conn_state_to_vc4_hdmi_conn_state(conn_state);
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
@@ -50340,7 +78407,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
/*
* As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
* be faster than pixel clock, infinitesimally faster, tested in
-@@ -938,13 +927,25 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+@@ -938,13 +928,25 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
return;
}
@@ -50370,7 +78437,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
vc4_hdmi_cec_update_clk_div(vc4_hdmi);
if (pixel_rate > 297000000)
-@@ -957,17 +958,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+@@ -957,17 +959,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate);
if (ret) {
DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
@@ -50390,7 +78457,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
}
if (vc4_hdmi->variant->phy_init)
-@@ -980,6 +977,15 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
+@@ -980,6 +978,15 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
if (vc4_hdmi->variant->set_timings)
vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
@@ -50406,7 +78473,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
}
static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
-@@ -1084,6 +1090,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+@@ -1084,6 +1091,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
unsigned long long tmds_rate;
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
@@ -50414,7 +78481,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return -EINVAL;
-@@ -1131,6 +1138,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
+@@ -1131,6 +1139,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
@@ -50422,7 +78489,28 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
-@@ -2098,6 +2106,27 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+@@ -1514,6 +1523,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
+ dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev));
+ return PTR_ERR(codec_pdev);
+ }
++ vc4_hdmi->audio.codec_pdev = codec_pdev;
+
+ dai_link->cpus = &vc4_hdmi->audio.cpu;
+ dai_link->codecs = &vc4_hdmi->audio.codec;
+@@ -1553,6 +1563,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
+
+ }
+
++static void vc4_hdmi_audio_exit(struct vc4_hdmi *vc4_hdmi)
++{
++ platform_device_unregister(vc4_hdmi->audio.codec_pdev);
++ vc4_hdmi->audio.codec_pdev = NULL;
++}
++
+ static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv)
+ {
+ struct vc4_hdmi *vc4_hdmi = priv;
+@@ -2098,6 +2114,27 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
return 0;
}
@@ -50450,7 +78538,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{
const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
-@@ -2161,6 +2190,31 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+@@ -2161,6 +2198,31 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
vc4_hdmi->disable_4kp60 = true;
}
@@ -50482,7 +78570,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
if (vc4_hdmi->variant->reset)
vc4_hdmi->variant->reset(vc4_hdmi);
-@@ -2172,8 +2226,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+@@ -2172,8 +2234,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
}
@@ -50491,7 +78579,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
-@@ -2197,6 +2249,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+@@ -2197,6 +2257,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
vc4_hdmi_debugfs_regs,
vc4_hdmi);
@@ -50500,7 +78588,7 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
return 0;
err_free_cec:
-@@ -2207,6 +2261,7 @@ err_destroy_conn:
+@@ -2207,6 +2269,7 @@ err_destroy_conn:
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
err_destroy_encoder:
drm_encoder_cleanup(encoder);
@@ -50508,7 +78596,15 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
pm_runtime_disable(dev);
err_put_ddc:
put_device(&vc4_hdmi->ddc->dev);
-@@ -2352,11 +2407,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = {
+@@ -2243,6 +2306,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
+ kfree(vc4_hdmi->hdmi_regset.regs);
+ kfree(vc4_hdmi->hd_regset.regs);
+
++ vc4_hdmi_audio_exit(vc4_hdmi);
+ vc4_hdmi_cec_exit(vc4_hdmi);
+ vc4_hdmi_hotplug_exit(vc4_hdmi);
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
+@@ -2352,11 +2416,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = {
{}
};
@@ -50527,6 +78623,18 @@ index ed8a4b7f8b6e2..9170d948b4483 100644
+ .pm = &vc4_hdmi_pm_ops,
},
};
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
+index 33e9f665ab8e4..c0492da736833 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
+@@ -113,6 +113,7 @@ struct vc4_hdmi_audio {
+ struct snd_soc_dai_link_component platform;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct hdmi_audio_infoframe infoframe;
++ struct platform_device *codec_pdev;
+ bool streaming;
+ };
+
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index c239045e05d6f..604933e20e6a2 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -50735,6 +78843,20 @@ index 2fc7f4b5fa098..9809ca3e29451 100644
txp->pdev = pdev;
+diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
+index 2de61b63ef91d..48d3c9955f0dd 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
++++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
+@@ -248,6 +248,9 @@ void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs)
+ {
+ u32 i;
+
++ if (!objs)
++ return;
++
+ for (i = 0; i < objs->nents; i++)
+ drm_gem_object_put(objs->objs[i]);
+ virtio_gpu_array_free(objs);
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 2e71e91278b45..93a41d018dca6 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -50937,7 +79059,7 @@ index c50dba7744854..7b0d617ebcb1e 100644
+
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
-index 67db472d3493c..a3bfbb6c3e14a 100644
+index 67db472d3493c..162dfeb1cc5ad 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
@@ -145,6 +145,13 @@ struct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv)
@@ -50954,6 +79076,34 @@ index 67db472d3493c..a3bfbb6c3e14a 100644
return fifo;
}
+@@ -521,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
+ *seqno = atomic_add_return(1, &dev_priv->marker_seq);
+ } while (*seqno == 0);
+
+- if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) {
++ if (!vmw_has_fences(dev_priv)) {
+
+ /*
+ * Don't request hardware to send a fence. The
+@@ -668,11 +675,14 @@ int vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv,
+ */
+ bool vmw_cmd_supported(struct vmw_private *vmw)
+ {
+- if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
+- SVGA_CAP_CMD_BUFFERS_2)) != 0)
+- return true;
++ bool has_cmdbufs =
++ (vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
++ SVGA_CAP_CMD_BUFFERS_2)) != 0;
++ if (vmw_is_svga_v3(vmw))
++ return (has_cmdbufs &&
++ (vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0);
+ /*
+ * We have FIFO cmd's
+ */
+- return vmw->fifo_mem != NULL;
++ return has_cmdbufs || vmw->fifo_mem != NULL;
+ }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index ab9a1750e1dff..8449d09c06f7a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -51071,7 +79221,7 @@ index ab9a1750e1dff..8449d09c06f7a 100644
static int __init vmwgfx_init(void)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
-index a833751099b55..f9f28516ffb41 100644
+index a833751099b55..288e883177bea 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -59,11 +59,8 @@
@@ -51154,6 +79304,19 @@ index a833751099b55..f9f28516ffb41 100644
/**
* VMW_DEBUG_KMS - Debug output for kernel mode-setting
+@@ -1684,4 +1677,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw,
+ outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT);
+ }
+
++static inline bool vmw_has_fences(struct vmw_private *vmw)
++{
++ if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
++ SVGA_CAP_CMD_BUFFERS_2)) != 0)
++ return true;
++ return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
++}
++
+ #endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 5f2ffa9de5c8f..9144e8f88c812 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -51239,11 +79402,84 @@ index 5f2ffa9de5c8f..9144e8f88c812 100644
out_unlock_binding:
mutex_unlock(&dev_priv->binding_mutex);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+index d18c6a56e3dca..f18ed03a8b2d6 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+@@ -490,7 +490,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,
+
+ static int vmw_fb_kms_framebuffer(struct fb_info *info)
+ {
+- struct drm_mode_fb_cmd2 mode_cmd;
++ struct drm_mode_fb_cmd2 mode_cmd = {0};
+ struct vmw_fb_par *par = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ struct drm_framebuffer *cur_fb;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
-index 9fe12329a4d58..b4d9d7258a546 100644
+index 9fe12329a4d58..b32ddbb992de2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
-@@ -1159,7 +1159,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+@@ -85,6 +85,22 @@ fman_from_fence(struct vmw_fence_obj *fence)
+ return container_of(fence->base.lock, struct vmw_fence_manager, lock);
+ }
+
++static u32 vmw_fence_goal_read(struct vmw_private *vmw)
++{
++ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
++ return vmw_read(vmw, SVGA_REG_FENCE_GOAL);
++ else
++ return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL);
++}
++
++static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value)
++{
++ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
++ vmw_write(vmw, SVGA_REG_FENCE_GOAL, value);
++ else
++ vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value);
++}
++
+ /*
+ * Note on fencing subsystem usage of irqs:
+ * Typically the vmw_fences_update function is called
+@@ -400,7 +416,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
+ if (likely(!fman->seqno_valid))
+ return false;
+
+- goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
++ goal_seqno = vmw_fence_goal_read(fman->dev_priv);
+ if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
+ return false;
+
+@@ -408,9 +424,8 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
+ list_for_each_entry(fence, &fman->fence_list, head) {
+ if (!list_empty(&fence->seq_passed_actions)) {
+ fman->seqno_valid = true;
+- vmw_fifo_mem_write(fman->dev_priv,
+- SVGA_FIFO_FENCE_GOAL,
+- fence->base.seqno);
++ vmw_fence_goal_write(fman->dev_priv,
++ fence->base.seqno);
+ break;
+ }
+ }
+@@ -442,13 +457,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
+ if (dma_fence_is_signaled_locked(&fence->base))
+ return false;
+
+- goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
++ goal_seqno = vmw_fence_goal_read(fman->dev_priv);
+ if (likely(fman->seqno_valid &&
+ goal_seqno - fence->base.seqno < VMW_FENCE_WRAP))
+ return false;
+
+- vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL,
+- fence->base.seqno);
++ vmw_fence_goal_write(fman->dev_priv, fence->base.seqno);
+ fman->seqno_valid = true;
+
+ return true;
+@@ -1159,7 +1173,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
}
vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
@@ -51252,11 +79488,131 @@ index 9fe12329a4d58..b4d9d7258a546 100644
vmw_fence_obj_unreference(&fence);
return 0;
out_no_create:
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+index c5191de365ca1..fe4732bf2c9d2 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+@@ -32,6 +32,14 @@
+
+ #define VMW_FENCE_WRAP (1 << 24)
+
++static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw)
++{
++ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
++ return SVGA_IRQFLAG_REG_FENCE_GOAL;
++ else
++ return SVGA_IRQFLAG_FENCE_GOAL;
++}
++
+ /**
+ * vmw_thread_fn - Deferred (process context) irq handler
+ *
+@@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg)
+ wake_up_all(&dev_priv->fifo_queue);
+
+ if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
+- SVGA_IRQFLAG_FENCE_GOAL)) &&
++ vmw_irqflag_fence_goal(dev_priv))) &&
+ !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending))
+ ret = IRQ_WAKE_THREAD;
+
+@@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv,
+ if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
+ return true;
+
+- if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) &&
+- vmw_fifo_idle(dev_priv, seqno))
++ if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno))
+ return true;
+
+ /**
+@@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
+ unsigned long timeout)
+ {
+ struct vmw_fifo_state *fifo_state = dev_priv->fifo;
++ bool fifo_down = false;
+
+ uint32_t count = 0;
+ uint32_t signal_seq;
+@@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
+ */
+
+ if (fifo_idle) {
+- down_read(&fifo_state->rwsem);
+ if (dev_priv->cman) {
+ ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
+ 10*HZ);
+ if (ret)
+ goto out_err;
++ } else if (fifo_state) {
++ down_read(&fifo_state->rwsem);
++ fifo_down = true;
+ }
+ }
+
+@@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
+ }
+ }
+ finish_wait(&dev_priv->fence_queue, &__wait);
+- if (ret == 0 && fifo_idle)
++ if (ret == 0 && fifo_idle && fifo_state)
+ vmw_fence_write(dev_priv, signal_seq);
+
+ wake_up_all(&dev_priv->fence_queue);
+ out_err:
+- if (fifo_idle)
++ if (fifo_down)
+ up_read(&fifo_state->rwsem);
+
+ return ret;
+@@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+
+ void vmw_goal_waiter_add(struct vmw_private *dev_priv)
+ {
+- vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
++ vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
+ &dev_priv->goal_queue_waiters);
+ }
+
+ void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
+ {
+- vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
++ vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
+ &dev_priv->goal_queue_waiters);
+ }
+
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
-index 74fa419092138..14e8f665b13be 100644
+index 74fa419092138..50c64e7813be1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
-@@ -2516,7 +2516,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
+@@ -1336,7 +1336,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
+ ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
+ mode_cmd,
+ is_bo_proxy);
+-
+ /*
+ * vmw_create_bo_proxy() adds a reference that is no longer
+ * needed
+@@ -1398,13 +1397,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
+ ret = vmw_user_lookup_handle(dev_priv, tfile,
+ mode_cmd->handles[0],
+ &surface, &bo);
+- if (ret)
++ if (ret) {
++ DRM_ERROR("Invalid buffer object handle %u (0x%x).\n",
++ mode_cmd->handles[0], mode_cmd->handles[0]);
+ goto err_out;
++ }
+
+
+ if (!bo &&
+ !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) {
+- DRM_ERROR("Surface size cannot exceed %dx%d",
++ DRM_ERROR("Surface size cannot exceed %dx%d\n",
+ dev_priv->texture_max_width,
+ dev_priv->texture_max_height);
+ goto err_out;
+@@ -2516,7 +2518,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
if (file_priv)
vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
ret, user_fence_rep, fence,
@@ -51856,7 +80212,7 @@ index 6dab94adf25e5..6815b4db17c1b 100644
help
Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
-index fbb6447b8659e..3872e4cd26989 100644
+index fbb6447b8659e..fc9f54282f7d6 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -18,6 +18,10 @@
@@ -51888,6 +80244,14 @@ index fbb6447b8659e..3872e4cd26989 100644
/*
* We may not always want to enable IOMMU support (for example if the
* host1x firewall is already enabled and we don't support addressing
+@@ -511,6 +526,7 @@ static int host1x_remove(struct platform_device *pdev)
+ host1x_syncpt_deinit(host);
+ reset_control_assert(host->rst);
+ clk_disable_unprepare(host->clk);
++ host1x_channel_list_free(&host->channel_list);
+ host1x_iommu_exit(host);
+
+ return 0;
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index d198a10848c6b..a89a408182e60 100644
--- a/drivers/gpu/host1x/syncpt.c
@@ -51922,6 +80286,42 @@ index d198a10848c6b..a89a408182e60 100644
if (!timeout) {
err = -EAGAIN;
+diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
+index 666223c6bec4d..0a34e0ab4fe60 100644
+--- a/drivers/gpu/ipu-v3/ipu-di.c
++++ b/drivers/gpu/ipu-v3/ipu-di.c
+@@ -447,8 +447,9 @@ static void ipu_di_config_clock(struct ipu_di *di,
+
+ error = rate / (sig->mode.pixelclock / 1000);
+
+- dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %d.%u%%\n",
+- rate, div, (signed)(error - 1000) / 10, error % 10);
++ dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %c%d.%d%%\n",
++ rate, div, error < 1000 ? '-' : '+',
++ abs(error - 1000) / 10, abs(error - 1000) % 10);
+
+ /* Allow a 1% error */
+ if (error < 1010 && error >= 990) {
+diff --git a/drivers/greybus/svc.c b/drivers/greybus/svc.c
+index ce7740ef449ba..51d0875a34800 100644
+--- a/drivers/greybus/svc.c
++++ b/drivers/greybus/svc.c
+@@ -866,8 +866,14 @@ static int gb_svc_hello(struct gb_operation *op)
+
+ gb_svc_debugfs_init(svc);
+
+- return gb_svc_queue_deferred_request(op);
++ ret = gb_svc_queue_deferred_request(op);
++ if (ret)
++ goto err_remove_debugfs;
++
++ return 0;
+
++err_remove_debugfs:
++ gb_svc_debugfs_exit(svc);
+ err_unregister_device:
+ gb_svc_watchdog_destroy(svc);
+ device_del(&svc->dev);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3c33bf572d6d3..9235ab7161e3a 100644
--- a/drivers/hid/Kconfig
@@ -51970,8 +80370,30 @@ index 3c33bf572d6d3..9235ab7161e3a 100644
help
Support for Samsung InfraRed remote control or keyboards.
+diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+index 840fd075c56f1..6284db50ec9bf 100644
+--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
++++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+@@ -226,6 +226,17 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
+ dev_dbg(dev, "sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
+ }
++ if (privdata->mp2_ops->discovery_status &&
++ privdata->mp2_ops->discovery_status(privdata) == 0) {
++ amd_sfh_hid_client_deinit(privdata);
++ for (i = 0; i < cl_data->num_hid_devices; i++) {
++ devm_kfree(dev, cl_data->feature_report[i]);
++ devm_kfree(dev, in_data->input_report[i]);
++ devm_kfree(dev, cl_data->report_descr[i]);
++ }
++ dev_warn(dev, "Failed to discover, sensors not enabled\n");
++ return -EOPNOTSUPP;
++ }
+ schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
+ return 0;
+
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
-index 05c007b213f24..561bb27f42b10 100644
+index 05c007b213f24..ae8f1f2536e94 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -36,11 +36,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_
@@ -51988,7 +80410,7 @@ index 05c007b213f24..561bb27f42b10 100644
return cmd_resp.response_v2.response;
return SENSOR_DISABLED;
-@@ -88,6 +88,44 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
+@@ -88,6 +88,50 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
}
@@ -52030,10 +80452,16 @@ index 05c007b213f24..561bb27f42b10 100644
+ return 0;
+}
+
++static int amd_sfh_dis_sts_v2(struct amd_mp2_dev *privdata)
++{
++ return (readl(privdata->mmio + AMD_P2C_MSG(1)) &
++ SENSOR_DISCOVERY_STATUS_MASK) >> SENSOR_DISCOVERY_STATUS_SHIFT;
++}
++
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{
union sfh_cmd_param cmd_param;
-@@ -192,6 +230,8 @@ static void amd_mp2_pci_remove(void *privdata)
+@@ -192,6 +236,8 @@ static void amd_mp2_pci_remove(void *privdata)
struct amd_mp2_dev *mp2 = privdata;
amd_sfh_hid_client_deinit(privdata);
mp2->mp2_ops->stop_all(mp2);
@@ -52042,16 +80470,17 @@ index 05c007b213f24..561bb27f42b10 100644
}
static const struct amd_mp2_ops amd_sfh_ops_v2 = {
-@@ -199,6 +239,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
+@@ -199,6 +245,9 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
.stop = amd_stop_sensor_v2,
.stop_all = amd_stop_all_sensor_v2,
.response = amd_sfh_wait_response_v2,
+ .clear_intr = amd_sfh_clear_intr_v2,
+ .init_intr = amd_sfh_irq_init_v2,
++ .discovery_status = amd_sfh_dis_sts_v2,
};
static const struct amd_mp2_ops amd_sfh_ops = {
-@@ -224,6 +266,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
+@@ -224,6 +273,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
}
}
@@ -52066,7 +80495,7 @@ index 05c007b213f24..561bb27f42b10 100644
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct amd_mp2_dev *privdata;
-@@ -257,9 +307,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
+@@ -257,9 +314,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
mp2_select_ops(privdata);
@@ -52088,7 +80517,7 @@ index 05c007b213f24..561bb27f42b10 100644
return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
}
-@@ -287,6 +348,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
+@@ -287,6 +355,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
}
}
@@ -52098,7 +80527,7 @@ index 05c007b213f24..561bb27f42b10 100644
return 0;
}
-@@ -310,6 +374,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
+@@ -310,6 +381,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
}
}
@@ -52109,10 +80538,20 @@ index 05c007b213f24..561bb27f42b10 100644
}
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
-index 1ff6f83cb6fd1..00fc083dc1239 100644
+index 1ff6f83cb6fd1..2d3203d3daeb3 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
-@@ -48,7 +48,7 @@ union sfh_cmd_base {
+@@ -38,6 +38,9 @@
+
+ #define AMD_SFH_IDLE_LOOP 200
+
++#define SENSOR_DISCOVERY_STATUS_MASK GENMASK(5, 3)
++#define SENSOR_DISCOVERY_STATUS_SHIFT 3
++
+ /* SFH Command register */
+ union sfh_cmd_base {
+ u32 ul;
+@@ -48,7 +51,7 @@ union sfh_cmd_base {
} s;
struct {
u32 cmd_id : 4;
@@ -52121,12 +80560,13 @@ index 1ff6f83cb6fd1..00fc083dc1239 100644
u32 rsvd1 : 3;
u32 length : 7;
u32 mem_type : 1;
-@@ -140,5 +140,7 @@ struct amd_mp2_ops {
+@@ -140,5 +143,8 @@ struct amd_mp2_ops {
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
void (*stop_all)(struct amd_mp2_dev *privdata);
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
+ void (*clear_intr)(struct amd_mp2_dev *privdata);
+ int (*init_intr)(struct amd_mp2_dev *privdata);
++ int (*discovery_status)(struct amd_mp2_dev *privdata);
};
#endif
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
@@ -52270,27 +80710,38 @@ index 021049805bb71..3091355d48df6 100644
return (intf->altsetting->desc.bInterfaceNumber !=
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
-index 383dfda8c12fc..9b42b0cdeef06 100644
+index 383dfda8c12fc..2876cb6a7dcab 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
-@@ -230,6 +230,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
+@@ -228,15 +228,16 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ {
+ struct elo_priv *priv;
int ret;
- struct usb_device *udev;
-
+- struct usb_device *udev;
++
+ if (!hid_is_usb(hdev))
+ return -EINVAL;
-+
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
-@@ -259,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
- return 0;
- err_free:
-+ usb_put_dev(udev);
+ INIT_DELAYED_WORK(&priv->work, elo_work);
+- udev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
+- priv->usbdev = usb_get_dev(udev);
++ priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
+
+ hid_set_drvdata(hdev, priv);
+
+@@ -267,8 +268,6 @@ static void elo_remove(struct hid_device *hdev)
+ {
+ struct elo_priv *priv = hid_get_drvdata(hdev);
+
+- usb_put_dev(priv->usbdev);
+-
+ hid_hw_stop(hdev);
+ cancel_delayed_work_sync(&priv->work);
kfree(priv);
- return ret;
- }
diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
index 4ef1c3b8094ea..183eeb3863b38 100644
--- a/drivers/hid/hid-ft260.c
@@ -52523,10 +80974,18 @@ index d40af911df635..fb3f7258009c2 100644
if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
(iface_num != 0)) {
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
-index a0017b010c342..7106b921b53cf 100644
+index a0017b010c342..c358778e070bc 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
-@@ -1777,7 +1777,7 @@ static int logi_dj_probe(struct hid_device *hdev,
+@@ -1068,6 +1068,7 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
+ workitem.reports_supported |= STD_KEYBOARD;
+ break;
+ case 0x0f:
++ case 0x11:
+ device_type = "eQUAD Lightspeed 1.2";
+ logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+ workitem.reports_supported |= STD_KEYBOARD;
+@@ -1777,7 +1778,7 @@ static int logi_dj_probe(struct hid_device *hdev,
case recvr_type_bluetooth: no_dj_interfaces = 2; break;
case recvr_type_dinovo: no_dj_interfaces = 2; break;
}
@@ -53012,10 +81471,33 @@ index d1b107d547f54..60ec2b29d54de 100644
static void sony_remove(struct hid_device *hdev)
diff --git a/drivers/hid/hid-thrustmaster.c b/drivers/hid/hid-thrustmaster.c
-index d44550aa88057..0c92b7f9b8b81 100644
+index d44550aa88057..a28c3e5756506 100644
--- a/drivers/hid/hid-thrustmaster.c
+++ b/drivers/hid/hid-thrustmaster.c
-@@ -274,6 +274,9 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i
+@@ -64,7 +64,9 @@ struct tm_wheel_info {
+ */
+ static const struct tm_wheel_info tm_wheels_infos[] = {
+ {0x0306, 0x0006, "Thrustmaster T150RS"},
++ {0x0200, 0x0005, "Thrustmaster T300RS (Missing Attachment)"},
+ {0x0206, 0x0005, "Thrustmaster T300RS"},
++ {0x0209, 0x0005, "Thrustmaster T300RS (Open Wheel Attachment)"},
+ {0x0204, 0x0005, "Thrustmaster T300 Ferrari Alcantara Edition"},
+ {0x0002, 0x0002, "Thrustmaster T500RS"}
+ //{0x0407, 0x0001, "Thrustmaster TMX"}
+@@ -158,6 +160,12 @@ static void thrustmaster_interrupts(struct hid_device *hdev)
+ return;
+ }
+
++ if (usbif->cur_altsetting->desc.bNumEndpoints < 2) {
++ kfree(send_buf);
++ hid_err(hdev, "Wrong number of endpoints?\n");
++ return;
++ }
++
+ ep = &usbif->cur_altsetting->endpoint[1];
+ b_ep = ep->desc.bEndpointAddress;
+
+@@ -274,6 +282,9 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i
int ret = 0;
struct tm_wheel *tm_wheel = 0;
@@ -53183,7 +81665,7 @@ index 3d67b748a3b95..3e70f969fb849 100644
* Set replacement report descriptor if the original matches the
* specified size. Otherwise keep interface unchanged.
diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c
-index cd7ada48b1d9f..576518e704ee6 100644
+index cd7ada48b1d9f..d57ec17670379 100644
--- a/drivers/hid/hid-vivaldi.c
+++ b/drivers/hid/hid-vivaldi.c
@@ -57,6 +57,9 @@ static int vivaldi_probe(struct hid_device *hdev,
@@ -53256,6 +81738,15 @@ index cd7ada48b1d9f..576518e704ee6 100644
report_len, 0);
if (ret) {
dev_warn(&hdev->dev, "failed to report feature %d\n",
+@@ -118,7 +143,7 @@ out:
+ static int vivaldi_input_configured(struct hid_device *hdev,
+ struct hid_input *hidinput)
+ {
+- return sysfs_create_group(&hdev->dev.kobj, &input_attribute_group);
++ return devm_device_add_group(&hdev->dev, &input_attribute_group);
+ }
+
+ static const struct hid_device_id vivaldi_table[] = {
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index a6f0257a26de3..b96ae15e0ad91 100644
--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
@@ -53270,10 +81761,66 @@ index a6f0257a26de3..b96ae15e0ad91 100644
static const struct acpi_device_id i2c_hid_acpi_match[] = {
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
-index 517141138b007..4804d71e5293a 100644
+index 517141138b007..65c1f20ec420a 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
-@@ -912,7 +912,7 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid)
+@@ -615,6 +615,17 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
+ if (report_type == HID_OUTPUT_REPORT)
+ return -EINVAL;
+
++ /*
++ * In case of unnumbered reports the response from the device will
++ * not have the report ID that the upper layers expect, so we need
++ * to stash it the buffer ourselves and adjust the data size.
++ */
++ if (!report_number) {
++ buf[0] = 0;
++ buf++;
++ count--;
++ }
++
+ /* +2 bytes to include the size of the reply in the query buffer */
+ ask_count = min(count + 2, (size_t)ihid->bufsize);
+
+@@ -636,6 +647,9 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
+ count = min(count, ret_count - 2);
+ memcpy(buf, ihid->rawbuf + 2, count);
+
++ if (!report_number)
++ count++;
++
+ return count;
+ }
+
+@@ -652,17 +666,19 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
+
+ mutex_lock(&ihid->reset_lock);
+
+- if (report_id) {
+- buf++;
+- count--;
+- }
+-
++ /*
++ * Note that both numbered and unnumbered reports passed here
++ * are supposed to have report ID stored in the 1st byte of the
++ * buffer, so we strip it off unconditionally before passing payload
++ * to i2c_hid_set_or_send_report which takes care of encoding
++ * everything properly.
++ */
+ ret = i2c_hid_set_or_send_report(client,
+ report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
+- report_id, buf, count, use_data);
++ report_id, buf + 1, count - 1, use_data);
+
+- if (report_id && ret >= 0)
+- ret++; /* add report_id to the number of transfered bytes */
++ if (ret >= 0)
++ ret++; /* add report_id to the number of transferred bytes */
+
+ mutex_unlock(&ihid->reset_lock);
+
+@@ -912,7 +928,7 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid)
}
int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
@@ -53282,7 +81829,7 @@ index 517141138b007..4804d71e5293a 100644
{
int ret;
struct i2c_hid *ihid;
-@@ -1009,6 +1009,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
+@@ -1009,6 +1025,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
goto err_mem_free;
}
@@ -53444,6 +81991,66 @@ index 1c5039081db27..8e9d9450cb835 100644
}
} else {
/*
+diff --git a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
+index 1b486f2627477..6b511fadf7ad2 100644
+--- a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
++++ b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
+@@ -657,21 +657,12 @@ static int ish_fw_xfer_direct_dma(struct ishtp_cl_data *client_data,
+ */
+ payload_max_size &= ~(L1_CACHE_BYTES - 1);
+
+- dma_buf = kmalloc(payload_max_size, GFP_KERNEL | GFP_DMA32);
++ dma_buf = dma_alloc_coherent(devc, payload_max_size, &dma_buf_phy, GFP_KERNEL);
+ if (!dma_buf) {
+ client_data->flag_retry = true;
+ return -ENOMEM;
+ }
+
+- dma_buf_phy = dma_map_single(devc, dma_buf, payload_max_size,
+- DMA_TO_DEVICE);
+- if (dma_mapping_error(devc, dma_buf_phy)) {
+- dev_err(cl_data_to_dev(client_data), "DMA map failed\n");
+- client_data->flag_retry = true;
+- rv = -ENOMEM;
+- goto end_err_dma_buf_release;
+- }
+-
+ ldr_xfer_dma_frag.fragment.hdr.command = LOADER_CMD_XFER_FRAGMENT;
+ ldr_xfer_dma_frag.fragment.xfer_mode = LOADER_XFER_MODE_DIRECT_DMA;
+ ldr_xfer_dma_frag.ddr_phys_addr = (u64)dma_buf_phy;
+@@ -691,14 +682,7 @@ static int ish_fw_xfer_direct_dma(struct ishtp_cl_data *client_data,
+ ldr_xfer_dma_frag.fragment.size = fragment_size;
+ memcpy(dma_buf, &fw->data[fragment_offset], fragment_size);
+
+- dma_sync_single_for_device(devc, dma_buf_phy,
+- payload_max_size,
+- DMA_TO_DEVICE);
+-
+- /*
+- * Flush cache here because the dma_sync_single_for_device()
+- * does not do for x86.
+- */
++ /* Flush cache to be sure the data is in main memory. */
+ clflush_cache_range(dma_buf, payload_max_size);
+
+ dev_dbg(cl_data_to_dev(client_data),
+@@ -721,15 +705,8 @@ static int ish_fw_xfer_direct_dma(struct ishtp_cl_data *client_data,
+ fragment_offset += fragment_size;
+ }
+
+- dma_unmap_single(devc, dma_buf_phy, payload_max_size, DMA_TO_DEVICE);
+- kfree(dma_buf);
+- return 0;
+-
+ end_err_resp_buf_release:
+- /* Free ISH buffer if not done already, in error case */
+- dma_unmap_single(devc, dma_buf_phy, payload_max_size, DMA_TO_DEVICE);
+-end_err_dma_buf_release:
+- kfree(dma_buf);
++ dma_free_coherent(devc, payload_max_size, dma_buf, dma_buf_phy);
+ return rv;
+ }
+
diff --git a/drivers/hid/surface-hid/surface_hid.c b/drivers/hid/surface-hid/surface_hid.c
index a3a70e4f3f6c9..d4aa8c81903ae 100644
--- a/drivers/hid/surface-hid/surface_hid.c
@@ -53715,8 +82322,50 @@ index ec90713564e32..884066109699c 100644
}
return cl;
+diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
+index d1123ceb38f3f..9a074cbdef78c 100644
+--- a/drivers/hv/Kconfig
++++ b/drivers/hv/Kconfig
+@@ -18,6 +18,7 @@ config HYPERV_TIMER
+ config HYPERV_UTILS
+ tristate "Microsoft Hyper-V Utilities driver"
+ depends on HYPERV && CONNECTOR && NLS
++ depends on PTP_1588_CLOCK_OPTIONAL
+ help
+ Select this option to enable the Hyper-V Utilities.
+
+diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
+index 142308526ec6a..ce76fc3827998 100644
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -380,7 +380,7 @@ void vmbus_channel_map_relid(struct vmbus_channel *channel)
+ * execute:
+ *
+ * (a) In the "normal (i.e., not resuming from hibernation)" path,
+- * the full barrier in smp_store_mb() guarantees that the store
++ * the full barrier in virt_store_mb() guarantees that the store
+ * is propagated to all CPUs before the add_channel_work work
+ * is queued. In turn, add_channel_work is queued before the
+ * channel's ring buffer is allocated/initialized and the
+@@ -392,14 +392,14 @@ void vmbus_channel_map_relid(struct vmbus_channel *channel)
+ * recv_int_page before retrieving the channel pointer from the
+ * array of channels.
+ *
+- * (b) In the "resuming from hibernation" path, the smp_store_mb()
++ * (b) In the "resuming from hibernation" path, the virt_store_mb()
+ * guarantees that the store is propagated to all CPUs before
+ * the VMBus connection is marked as ready for the resume event
+ * (cf. check_ready_for_resume_event()). The interrupt handler
+ * of the VMBus driver and vmbus_chan_sched() can not run before
+ * vmbus_bus_resume() has completed execution (cf. resume_noirq).
+ */
+- smp_store_mb(
++ virt_store_mb(
+ vmbus_connection.channels[channel->offermsg.child_relid],
+ channel);
+ }
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
-index 7f11ea07d698f..f2d05bff42453 100644
+index 7f11ea07d698f..3cf334c46c312 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -480,7 +480,7 @@ module_param(pressure_report_delay, uint, (S_IRUGO | S_IWUSR));
@@ -53728,7 +82377,55 @@ index 7f11ea07d698f..f2d05bff42453 100644
/*
* Driver specific state.
-@@ -1660,6 +1660,13 @@ static int balloon_connect_vsp(struct hv_device *dev)
+@@ -1563,7 +1563,7 @@ static void balloon_onchannelcallback(void *context)
+ break;
+
+ default:
+- pr_warn("Unhandled message: type: %d\n", dm_hdr->type);
++ pr_warn_ratelimited("Unhandled message: type: %d\n", dm_hdr->type);
+
+ }
+ }
+@@ -1653,6 +1653,38 @@ static void disable_page_reporting(void)
+ }
+ }
+
++static int ballooning_enabled(void)
++{
++ /*
++ * Disable ballooning if the page size is not 4k (HV_HYP_PAGE_SIZE),
++ * since currently it's unclear to us whether an unballoon request can
++ * make sure all page ranges are guest page size aligned.
++ */
++ if (PAGE_SIZE != HV_HYP_PAGE_SIZE) {
++ pr_info("Ballooning disabled because page size is not 4096 bytes\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static int hot_add_enabled(void)
++{
++ /*
++ * Disable hot add on ARM64, because we currently rely on
++ * memory_add_physaddr_to_nid() to get a node id of a hot add range,
++ * however ARM64's memory_add_physaddr_to_nid() always return 0 and
++ * DM_MEM_HOT_ADD_REQUEST doesn't have the NUMA node information for
++ * add_memory().
++ */
++ if (IS_ENABLED(CONFIG_ARM64)) {
++ pr_info("Memory hot add disabled on ARM64\n");
++ return 0;
++ }
++
++ return 1;
++}
++
+ static int balloon_connect_vsp(struct hv_device *dev)
+ {
+ struct dm_version_request version_req;
+@@ -1660,6 +1692,13 @@ static int balloon_connect_vsp(struct hv_device *dev)
unsigned long t;
int ret;
@@ -53742,11 +82439,98 @@ index 7f11ea07d698f..f2d05bff42453 100644
ret = vmbus_open(dev->channel, dm_ring_size, dm_ring_size, NULL, 0,
balloon_onchannelcallback, dev);
if (ret)
+@@ -1717,8 +1756,8 @@ static int balloon_connect_vsp(struct hv_device *dev)
+ * currently still requires the bits to be set, so we have to add code
+ * to fail the host's hot-add and balloon up/down requests, if any.
+ */
+- cap_msg.caps.cap_bits.balloon = 1;
+- cap_msg.caps.cap_bits.hot_add = 1;
++ cap_msg.caps.cap_bits.balloon = ballooning_enabled();
++ cap_msg.caps.cap_bits.hot_add = hot_add_enabled();
+
+ /*
+ * Specify our alignment requirements as it relates
+diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
+index 314015d9e912d..f4091143213b0 100644
+--- a/drivers/hv/ring_buffer.c
++++ b/drivers/hv/ring_buffer.c
+@@ -408,7 +408,16 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
+ static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
+ {
+ u32 priv_read_loc = rbi->priv_read_index;
+- u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
++ u32 write_loc;
++
++ /*
++ * The Hyper-V host writes the packet data, then uses
++ * store_release() to update the write_index. Use load_acquire()
++ * here to prevent loads of the packet data from being re-ordered
++ * before the read of the write_index and potentially getting
++ * stale data.
++ */
++ write_loc = virt_load_acquire(&rbi->ring_buffer->write_index);
+
+ if (write_loc >= priv_read_loc)
+ return write_loc - priv_read_loc;
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
-index 392c1ac4f8193..44bd0b6ff5059 100644
+index 392c1ac4f8193..50d9113f54025 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
-@@ -2027,8 +2027,10 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
+@@ -76,8 +76,8 @@ static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
+
+ /*
+ * Hyper-V should be notified only once about a panic. If we will be
+- * doing hyperv_report_panic_msg() later with kmsg data, don't do
+- * the notification here.
++ * doing hv_kmsg_dump() with kmsg data later, don't do the notification
++ * here.
+ */
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
+ && hyperv_report_reg()) {
+@@ -99,8 +99,8 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
+
+ /*
+ * Hyper-V should be notified only once about a panic. If we will be
+- * doing hyperv_report_panic_msg() later with kmsg data, don't do
+- * the notification here.
++ * doing hv_kmsg_dump() with kmsg data later, don't do the notification
++ * here.
+ */
+ if (hyperv_report_reg())
+ hyperv_report_panic(regs, val, true);
+@@ -1381,7 +1381,7 @@ static void vmbus_isr(void)
+ tasklet_schedule(&hv_cpu->msg_dpc);
+ }
+
+- add_interrupt_randomness(vmbus_interrupt, 0);
++ add_interrupt_randomness(vmbus_interrupt);
+ }
+
+ static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id)
+@@ -1545,14 +1545,20 @@ static int vmbus_bus_init(void)
+ if (ret)
+ goto err_connect;
+
++ if (hv_is_isolation_supported())
++ sysctl_record_panic_msg = 0;
++
+ /*
+ * Only register if the crash MSRs are available
+ */
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ u64 hyperv_crash_ctl;
+ /*
+- * Sysctl registration is not fatal, since by default
+- * reporting is enabled.
++ * Panic message recording (sysctl_record_panic_msg)
++ * is enabled by default in non-isolated guests and
++ * disabled by default in isolated guests; the panic
++ * message recording won't be available in isolated
++ * guests should the following registration fail.
+ */
+ hv_ctl_table_hdr = register_sysctl_table(hv_root_table);
+ if (!hv_ctl_table_hdr)
+@@ -2027,8 +2033,10 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
kobj->kset = dev->channels_kset;
ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL,
"%u", relid);
@@ -53758,7 +82542,7 @@ index 392c1ac4f8193..44bd0b6ff5059 100644
ret = sysfs_create_group(kobj, &vmbus_chan_group);
-@@ -2037,6 +2039,7 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
+@@ -2037,6 +2045,7 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
* The calling functions' error handling paths will cleanup the
* empty channel directory.
*/
@@ -53766,10 +82550,37 @@ index 392c1ac4f8193..44bd0b6ff5059 100644
dev_err(device, "Unable to set up channel sysfs files\n");
return ret;
}
+@@ -2773,10 +2782,15 @@ static void __exit vmbus_exit(void)
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ kmsg_dump_unregister(&hv_kmsg_dumper);
+ unregister_die_notifier(&hyperv_die_block);
+- atomic_notifier_chain_unregister(&panic_notifier_list,
+- &hyperv_panic_block);
+ }
+
++ /*
++ * The panic notifier is always registered, hence we should
++ * also unconditionally unregister it here as well.
++ */
++ atomic_notifier_chain_unregister(&panic_notifier_list,
++ &hyperv_panic_block);
++
+ free_page((unsigned long)hv_panic_page);
+ unregister_sysctl_table(hv_ctl_table_hdr);
+ hv_ctl_table_hdr = NULL;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index c4578e8f34bb5..ccdaeafed0bb7 100644
+index c4578e8f34bb5..51f1caa10d113 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
+@@ -944,7 +944,7 @@ config SENSORS_LTC4261
+
+ config SENSORS_LTQ_CPUTEMP
+ bool "Lantiq cpu temperature sensor driver"
+- depends on LANTIQ
++ depends on SOC_XWAY
+ help
+ If you say yes here you get support for the temperature
+ sensor inside your CPU.
@@ -1317,7 +1317,7 @@ config SENSORS_LM90
Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658,
MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696,
@@ -53780,9 +82591,30 @@ index c4578e8f34bb5..ccdaeafed0bb7 100644
This driver can also be built as a module. If so, the module
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
-index d519aca4a9d64..fb6d14d213a18 100644
+index d519aca4a9d64..c67cd037a93fd 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
+@@ -19,6 +19,7 @@
+ #include <linux/log2.h>
+ #include <linux/kthread.h>
+ #include <linux/regmap.h>
++#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/util_macros.h>
+
+@@ -294,11 +295,10 @@ static int adt7470_update_thread(void *p)
+ adt7470_read_temperatures(data);
+ mutex_unlock(&data->lock);
+
+- set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop())
+ break;
+
+- schedule_timeout(msecs_to_jiffies(data->auto_update_interval));
++ schedule_timeout_interruptible(msecs_to_jiffies(data->auto_update_interval));
+ }
+
+ return 0;
@@ -662,6 +662,9 @@ static int adt7470_fan_write(struct device *dev, u32 attr, int channel, long val
struct adt7470_data *data = dev_get_drvdata(dev);
int err;
@@ -53864,6 +82696,22 @@ index 774c1b0715d91..9cb1c3588038f 100644
}
#else
+diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
+index 4dec793fd07d5..94b35723ee7ad 100644
+--- a/drivers/hwmon/f71882fg.c
++++ b/drivers/hwmon/f71882fg.c
+@@ -1577,8 +1577,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ temp *= 125;
+ if (sign)
+ temp -= 128000;
+- } else
+- temp = data->temp[nr] * 1000;
++ } else {
++ temp = ((s8)data->temp[nr]) * 1000;
++ }
+
+ return sprintf(buf, "%d\n", temp);
+ }
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 8d3b1dae31df1..3ae961986fc31 100644
--- a/drivers/hwmon/hwmon.c
@@ -54513,6 +83361,89 @@ index d209e0afc2caa..66d3e88b54172 100644
.R = -3,
},
[PSC_TEMPERATURE] = {
+diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
+index e0aa8aa46d8c4..ef3a8ecde4dfc 100644
+--- a/drivers/hwmon/pmbus/pmbus.h
++++ b/drivers/hwmon/pmbus/pmbus.h
+@@ -319,6 +319,7 @@ enum pmbus_fan_mode { percent = 0, rpm };
+ /*
+ * STATUS_VOUT, STATUS_INPUT
+ */
++#define PB_VOLTAGE_VIN_OFF BIT(3)
+ #define PB_VOLTAGE_UV_FAULT BIT(4)
+ #define PB_VOLTAGE_UV_WARNING BIT(5)
+ #define PB_VOLTAGE_OV_WARNING BIT(6)
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index 776ee2237be20..5f8f824d997f8 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -911,6 +911,11 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+ pmbus_update_sensor_data(client, s2);
+
+ regval = status & mask;
++ if (regval) {
++ ret = pmbus_write_byte_data(client, page, reg, regval);
++ if (ret)
++ goto unlock;
++ }
+ if (s1 && s2) {
+ s64 v1, v2;
+
+@@ -1368,7 +1373,7 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ .reg = PMBUS_VIN_UV_FAULT_LIMIT,
+ .attr = "lcrit",
+ .alarm = "lcrit_alarm",
+- .sbit = PB_VOLTAGE_UV_FAULT,
++ .sbit = PB_VOLTAGE_UV_FAULT | PB_VOLTAGE_VIN_OFF,
+ }, {
+ .reg = PMBUS_VIN_OV_WARN_LIMIT,
+ .attr = "max",
+@@ -2321,6 +2326,9 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
+ data->has_status_word = true;
+ }
+
++ /* Make sure PEC is disabled, will be enabled later if needed */
++ client->flags &= ~I2C_CLIENT_PEC;
++
+ /* Enable PEC if the controller and bus supports it */
+ if (!(data->flags & PMBUS_NO_CAPABILITY)) {
+ ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
+@@ -2386,10 +2394,14 @@ static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
+ {
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
++ struct pmbus_data *data = i2c_get_clientdata(client);
+ u8 page = rdev_get_id(rdev);
+ int ret;
+
++ mutex_lock(&data->update_lock);
+ ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
++ mutex_unlock(&data->update_lock);
++
+ if (ret < 0)
+ return ret;
+
+@@ -2400,11 +2412,17 @@ static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
+ {
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
++ struct pmbus_data *data = i2c_get_clientdata(client);
+ u8 page = rdev_get_id(rdev);
++ int ret;
+
+- return pmbus_update_byte_data(client, page, PMBUS_OPERATION,
+- PB_OPERATION_CONTROL_ON,
+- enable ? PB_OPERATION_CONTROL_ON : 0);
++ mutex_lock(&data->update_lock);
++ ret = pmbus_update_byte_data(client, page, PMBUS_OPERATION,
++ PB_OPERATION_CONTROL_ON,
++ enable ? PB_OPERATION_CONTROL_ON : 0);
++ mutex_unlock(&data->update_lock);
++
++ return ret;
+ }
+
+ static int pmbus_regulator_enable(struct regulator_dev *rdev)
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 17518b4cab1b0..f12b9a28a232d 100644
--- a/drivers/hwmon/pwm-fan.c
@@ -54526,6 +83457,45 @@ index 17518b4cab1b0..f12b9a28a232d 100644
pwm_init_state(ctx->pwm, &ctx->pwm_state);
/*
+diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
+index 40cdadad35e52..f85eede6d7663 100644
+--- a/drivers/hwmon/sch56xx-common.c
++++ b/drivers/hwmon/sch56xx-common.c
+@@ -422,7 +422,7 @@ void sch56xx_watchdog_register(struct device *parent, u16 addr, u32 revision,
+ data->wddev.max_timeout = 255 * 60;
+ watchdog_set_nowayout(&data->wddev, nowayout);
+ if (output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)
+- set_bit(WDOG_ACTIVE, &data->wddev.status);
++ set_bit(WDOG_HW_RUNNING, &data->wddev.status);
+
+ /* Since the watchdog uses a downcounter there is no register to read
+ the BIOS set timeout from (if any was set at all) ->
+diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
+index 9dc210b55e69b..48466b0a4bb05 100644
+--- a/drivers/hwmon/tmp401.c
++++ b/drivers/hwmon/tmp401.c
+@@ -730,10 +730,21 @@ static int tmp401_probe(struct i2c_client *client)
+ return 0;
+ }
+
++static const struct of_device_id __maybe_unused tmp4xx_of_match[] = {
++ { .compatible = "ti,tmp401", },
++ { .compatible = "ti,tmp411", },
++ { .compatible = "ti,tmp431", },
++ { .compatible = "ti,tmp432", },
++ { .compatible = "ti,tmp435", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, tmp4xx_of_match);
++
+ static struct i2c_driver tmp401_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "tmp401",
++ .of_match_table = of_match_ptr(tmp4xx_of_match),
+ },
+ .probe_new = tmp401_probe,
+ .id_table = tmp401_id,
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index e2a3620cbf489..8988b2ed2ea6f 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -54539,6 +83509,38 @@ index e2a3620cbf489..8988b2ed2ea6f 100644
return 0;
/* not disabled this call */
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+index a0640fa5c55bd..57e94424a8d65 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+@@ -367,8 +367,12 @@ static ssize_t mode_store(struct device *dev,
+ mode = ETM_MODE_QELEM(config->mode);
+ /* start by clearing QE bits */
+ config->cfg &= ~(BIT(13) | BIT(14));
+- /* if supported, Q elements with instruction counts are enabled */
+- if ((mode & BIT(0)) && (drvdata->q_support & BIT(0)))
++ /*
++ * if supported, Q elements with instruction counts are enabled.
++ * Always set the low bit for any requested mode. Valid combos are
++ * 0b00, 0b01 and 0b11.
++ */
++ if (mode && drvdata->q_support)
+ config->cfg |= BIT(13);
+ /*
+ * if supported, Q elements with and without instruction
+diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
+index 43054568430f2..c30989e0675f5 100644
+--- a/drivers/hwtracing/coresight/coresight-syscfg.c
++++ b/drivers/hwtracing/coresight/coresight-syscfg.c
+@@ -791,7 +791,7 @@ static int cscfg_create_device(void)
+
+ err = device_register(dev);
+ if (err)
+- cscfg_dev_release(dev);
++ put_device(dev);
+
+ create_dev_exit_unlock:
+ mutex_unlock(&cscfg_mutex);
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 1768684968797..7dddb85b90591 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
@@ -54606,7 +83608,7 @@ index e17790fe35a74..fea403431f228 100644
If you say yes to this option, support will be included for the
built-in I2C interface on the Qualcomm SoCs.
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
-index 37443edbf7546..ad3b124a2e376 100644
+index 37443edbf7546..f72c6576d8a36 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -23,6 +23,11 @@
@@ -54621,7 +83623,44 @@ index 37443edbf7546..ad3b124a2e376 100644
#define BCM2835_I2C_CLKT 0x1c
#define BCM2835_I2C_C_READ BIT(0)
-@@ -477,6 +482,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
+@@ -402,7 +407,7 @@ static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
+ static int bcm2835_i2c_probe(struct platform_device *pdev)
+ {
+ struct bcm2835_i2c_dev *i2c_dev;
+- struct resource *mem, *irq;
++ struct resource *mem;
+ int ret;
+ struct i2c_adapter *adap;
+ struct clk *mclk;
+@@ -449,21 +454,20 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
+ ret = clk_prepare_enable(i2c_dev->bus_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't prepare clock");
+- return ret;
++ goto err_put_exclusive_rate;
+ }
+
+- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+- if (!irq) {
+- dev_err(&pdev->dev, "No IRQ resource\n");
+- return -ENODEV;
++ i2c_dev->irq = platform_get_irq(pdev, 0);
++ if (i2c_dev->irq < 0) {
++ ret = i2c_dev->irq;
++ goto err_disable_unprepare_clk;
+ }
+- i2c_dev->irq = irq->start;
+
+ ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
+ dev_name(&pdev->dev), i2c_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not request IRQ\n");
+- return -ENODEV;
++ goto err_disable_unprepare_clk;
+ }
+
+ adap = &i2c_dev->adapter;
+@@ -477,11 +481,26 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
adap->dev.of_node = pdev->dev.of_node;
adap->quirks = of_device_get_match_data(&pdev->dev);
@@ -54634,6 +83673,21 @@ index 37443edbf7546..ad3b124a2e376 100644
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
ret = i2c_add_adapter(adap);
+ if (ret)
+- free_irq(i2c_dev->irq, i2c_dev);
++ goto err_free_irq;
++
++ return 0;
++
++err_free_irq:
++ free_irq(i2c_dev->irq, i2c_dev);
++err_disable_unprepare_clk:
++ clk_disable_unprepare(i2c_dev->bus_clk);
++err_put_exclusive_rate:
++ clk_rate_exclusive_put(i2c_dev->bus_clk);
+
+ return ret;
+ }
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 490ee3962645d..b00f35c0b0662 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
@@ -54741,6 +83795,35 @@ index 89ae78ef1a1cc..98e39a17fb830 100644
res = &tco_res[1];
if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
+diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
+index ef73a42577cc7..07eb819072c4f 100644
+--- a/drivers/i2c/busses/i2c-meson.c
++++ b/drivers/i2c/busses/i2c-meson.c
+@@ -465,18 +465,18 @@ static int meson_i2c_probe(struct platform_device *pdev)
+ */
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
+
+- ret = i2c_add_adapter(&i2c->adap);
+- if (ret < 0) {
+- clk_disable_unprepare(i2c->clk);
+- return ret;
+- }
+-
+ /* Disable filtering */
+ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR,
+ REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0);
+
+ meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
+
++ ret = i2c_add_adapter(&i2c->adap);
++ if (ret < 0) {
++ clk_disable_unprepare(i2c->clk);
++ return ret;
++ }
++
+ return 0;
+ }
+
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a6ea1eb1394e1..6c698c10d3cdb 100644
--- a/drivers/i2c/busses/i2c-mpc.c
@@ -54842,6 +83925,377 @@ index 7d4b3eb7077ad..72acda59eb399 100644
[OFFSET_DEBUGCTRL] = 0xe8,
[OFFSET_FIFO_STAT] = 0xf4,
[OFFSET_FIFO_THRESH] = 0xf8,
+diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c
+index 45fe4a7fe0c03..901f0fb04fee4 100644
+--- a/drivers/i2c/busses/i2c-mt7621.c
++++ b/drivers/i2c/busses/i2c-mt7621.c
+@@ -304,7 +304,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
+
+ if (i2c->bus_freq == 0) {
+ dev_warn(i2c->dev, "clock-frequency 0 not supported\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_disable_clk;
+ }
+
+ adap = &i2c->adap;
+@@ -322,10 +323,15 @@ static int mtk_i2c_probe(struct platform_device *pdev)
+
+ ret = i2c_add_adapter(adap);
+ if (ret < 0)
+- return ret;
++ goto err_disable_clk;
+
+ dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000);
+
++ return 0;
++
++err_disable_clk:
++ clk_disable_unprepare(i2c->clk);
++
+ return ret;
+ }
+
+diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
+index 20f2772c0e79b..2c909522f0f38 100644
+--- a/drivers/i2c/busses/i2c-pasemi.c
++++ b/drivers/i2c/busses/i2c-pasemi.c
+@@ -137,6 +137,12 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
+
+ TXFIFO_WR(smbus, msg->buf[msg->len-1] |
+ (stop ? MTXFIFO_STOP : 0));
++
++ if (stop) {
++ err = pasemi_smb_waitready(smbus);
++ if (err)
++ goto reset_out;
++ }
+ }
+
+ return 0;
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index 8c1b31ed0c429..ac8e7d60672a1 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -77,6 +77,7 @@
+
+ /* SB800 constants */
+ #define SB800_PIIX4_SMB_IDX 0xcd6
++#define SB800_PIIX4_SMB_MAP_SIZE 2
+
+ #define KERNCZ_IMC_IDX 0x3e
+ #define KERNCZ_IMC_DATA 0x3f
+@@ -97,6 +98,9 @@
+ #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
+ #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
+
++#define SB800_PIIX4_FCH_PM_ADDR 0xFED80300
++#define SB800_PIIX4_FCH_PM_SIZE 8
++
+ /* insmod parameters */
+
+ /* If force is set to anything different from 0, we forcibly enable the
+@@ -155,6 +159,12 @@ static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
+ };
+ static const char *piix4_aux_port_name_sb800 = " port 1";
+
++struct sb800_mmio_cfg {
++ void __iomem *addr;
++ struct resource *res;
++ bool use_mmio;
++};
++
+ struct i2c_piix4_adapdata {
+ unsigned short smba;
+
+@@ -162,8 +172,75 @@ struct i2c_piix4_adapdata {
+ bool sb800_main;
+ bool notify_imc;
+ u8 port; /* Port number, shifted */
++ struct sb800_mmio_cfg mmio_cfg;
+ };
+
++static int piix4_sb800_region_request(struct device *dev,
++ struct sb800_mmio_cfg *mmio_cfg)
++{
++ if (mmio_cfg->use_mmio) {
++ struct resource *res;
++ void __iomem *addr;
++
++ res = request_mem_region_muxed(SB800_PIIX4_FCH_PM_ADDR,
++ SB800_PIIX4_FCH_PM_SIZE,
++ "sb800_piix4_smb");
++ if (!res) {
++ dev_err(dev,
++ "SMBus base address memory region 0x%x already in use.\n",
++ SB800_PIIX4_FCH_PM_ADDR);
++ return -EBUSY;
++ }
++
++ addr = ioremap(SB800_PIIX4_FCH_PM_ADDR,
++ SB800_PIIX4_FCH_PM_SIZE);
++ if (!addr) {
++ release_resource(res);
++ dev_err(dev, "SMBus base address mapping failed.\n");
++ return -ENOMEM;
++ }
++
++ mmio_cfg->res = res;
++ mmio_cfg->addr = addr;
++
++ return 0;
++ }
++
++ if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
++ "sb800_piix4_smb")) {
++ dev_err(dev,
++ "SMBus base address index region 0x%x already in use.\n",
++ SB800_PIIX4_SMB_IDX);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
++static void piix4_sb800_region_release(struct device *dev,
++ struct sb800_mmio_cfg *mmio_cfg)
++{
++ if (mmio_cfg->use_mmio) {
++ iounmap(mmio_cfg->addr);
++ release_resource(mmio_cfg->res);
++ return;
++ }
++
++ release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
++}
++
++static bool piix4_sb800_use_mmio(struct pci_dev *PIIX4_dev)
++{
++ /*
++ * cd6h/cd7h port I/O accesses can be disabled on AMD processors
++ * w/ SMBus PCI revision ID 0x51 or greater. MMIO is supported on
++ * the same processors and is the recommended access method.
++ */
++ return (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
++ PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
++ PIIX4_dev->revision >= 0x51);
++}
++
+ static int piix4_setup(struct pci_dev *PIIX4_dev,
+ const struct pci_device_id *id)
+ {
+@@ -263,12 +340,61 @@ static int piix4_setup(struct pci_dev *PIIX4_dev,
+ return piix4_smba;
+ }
+
++static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev,
++ u8 smb_en,
++ u8 aux,
++ u8 *smb_en_status,
++ unsigned short *piix4_smba)
++{
++ struct sb800_mmio_cfg mmio_cfg;
++ u8 smba_en_lo;
++ u8 smba_en_hi;
++ int retval;
++
++ mmio_cfg.use_mmio = piix4_sb800_use_mmio(PIIX4_dev);
++ retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
++ if (retval)
++ return retval;
++
++ if (mmio_cfg.use_mmio) {
++ smba_en_lo = ioread8(mmio_cfg.addr);
++ smba_en_hi = ioread8(mmio_cfg.addr + 1);
++ } else {
++ outb_p(smb_en, SB800_PIIX4_SMB_IDX);
++ smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
++ outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
++ smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
++ }
++
++ piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
++
++ if (!smb_en) {
++ *smb_en_status = smba_en_lo & 0x10;
++ *piix4_smba = smba_en_hi << 8;
++ if (aux)
++ *piix4_smba |= 0x20;
++ } else {
++ *smb_en_status = smba_en_lo & 0x01;
++ *piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
++ }
++
++ if (!*smb_en_status) {
++ dev_err(&PIIX4_dev->dev,
++ "SMBus Host Controller not enabled!\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
+ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+ const struct pci_device_id *id, u8 aux)
+ {
+ unsigned short piix4_smba;
+- u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status, port_sel;
++ u8 smb_en, smb_en_status, port_sel;
+ u8 i2ccfg, i2ccfg_offset = 0x10;
++ struct sb800_mmio_cfg mmio_cfg;
++ int retval;
+
+ /* SB800 and later SMBus does not support forcing address */
+ if (force || force_addr) {
+@@ -290,35 +416,11 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+ else
+ smb_en = (aux) ? 0x28 : 0x2c;
+
+- if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
+- dev_err(&PIIX4_dev->dev,
+- "SMB base address index region 0x%x already in use.\n",
+- SB800_PIIX4_SMB_IDX);
+- return -EBUSY;
+- }
+-
+- outb_p(smb_en, SB800_PIIX4_SMB_IDX);
+- smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+- outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+- smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
++ retval = piix4_setup_sb800_smba(PIIX4_dev, smb_en, aux, &smb_en_status,
++ &piix4_smba);
+
+- release_region(SB800_PIIX4_SMB_IDX, 2);
+-
+- if (!smb_en) {
+- smb_en_status = smba_en_lo & 0x10;
+- piix4_smba = smba_en_hi << 8;
+- if (aux)
+- piix4_smba |= 0x20;
+- } else {
+- smb_en_status = smba_en_lo & 0x01;
+- piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
+- }
+-
+- if (!smb_en_status) {
+- dev_err(&PIIX4_dev->dev,
+- "SMBus Host Controller not enabled!\n");
+- return -ENODEV;
+- }
++ if (retval)
++ return retval;
+
+ if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+ return -ENODEV;
+@@ -371,10 +473,11 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+ piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+ }
+ } else {
+- if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
+- "sb800_piix4_smb")) {
++ mmio_cfg.use_mmio = piix4_sb800_use_mmio(PIIX4_dev);
++ retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
++ if (retval) {
+ release_region(piix4_smba, SMBIOSIZE);
+- return -EBUSY;
++ return retval;
+ }
+
+ outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
+@@ -384,7 +487,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+ SB800_PIIX4_PORT_IDX;
+ piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
+ piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+- release_region(SB800_PIIX4_SMB_IDX, 2);
++ piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
+ }
+
+ dev_info(&PIIX4_dev->dev,
+@@ -662,6 +765,29 @@ static void piix4_imc_wakeup(void)
+ release_region(KERNCZ_IMC_IDX, 2);
+ }
+
++static int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
++{
++ u8 smba_en_lo, val;
++
++ if (mmio_cfg->use_mmio) {
++ smba_en_lo = ioread8(mmio_cfg->addr + piix4_port_sel_sb800);
++ val = (smba_en_lo & ~piix4_port_mask_sb800) | port;
++ if (smba_en_lo != val)
++ iowrite8(val, mmio_cfg->addr + piix4_port_sel_sb800);
++
++ return (smba_en_lo & piix4_port_mask_sb800);
++ }
++
++ outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
++ smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
++
++ val = (smba_en_lo & ~piix4_port_mask_sb800) | port;
++ if (smba_en_lo != val)
++ outb_p(val, SB800_PIIX4_SMB_IDX + 1);
++
++ return (smba_en_lo & piix4_port_mask_sb800);
++}
++
+ /*
+ * Handles access to multiple SMBus ports on the SB800.
+ * The port is selected by bits 2:1 of the smb_en register (0x2c).
+@@ -678,12 +804,12 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
+ unsigned short piix4_smba = adapdata->smba;
+ int retries = MAX_TIMEOUT;
+ int smbslvcnt;
+- u8 smba_en_lo;
+- u8 port;
++ u8 prev_port;
+ int retval;
+
+- if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
+- return -EBUSY;
++ retval = piix4_sb800_region_request(&adap->dev, &adapdata->mmio_cfg);
++ if (retval)
++ return retval;
+
+ /* Request the SMBUS semaphore, avoid conflicts with the IMC */
+ smbslvcnt = inb_p(SMBSLVCNT);
+@@ -738,18 +864,12 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
+ }
+ }
+
+- outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
+- smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-
+- port = adapdata->port;
+- if ((smba_en_lo & piix4_port_mask_sb800) != port)
+- outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port,
+- SB800_PIIX4_SMB_IDX + 1);
++ prev_port = piix4_sb800_port_sel(adapdata->port, &adapdata->mmio_cfg);
+
+ retval = piix4_access(adap, addr, flags, read_write,
+ command, size, data);
+
+- outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
++ piix4_sb800_port_sel(prev_port, &adapdata->mmio_cfg);
+
+ /* Release the semaphore */
+ outb_p(smbslvcnt | 0x20, SMBSLVCNT);
+@@ -758,7 +878,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
+ piix4_imc_wakeup();
+
+ release:
+- release_region(SB800_PIIX4_SMB_IDX, 2);
++ piix4_sb800_region_release(&adap->dev, &adapdata->mmio_cfg);
+ return retval;
+ }
+
+@@ -836,6 +956,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
+ return -ENOMEM;
+ }
+
++ adapdata->mmio_cfg.use_mmio = piix4_sb800_use_mmio(dev);
+ adapdata->smba = smba;
+ adapdata->sb800_main = sb800_main;
+ adapdata->port = port << piix4_port_shift_sb800;
diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c
index c1de8eb66169f..cf54f1cb4c57a 100644
--- a/drivers/i2c/busses/i2c-qcom-cci.c
@@ -55125,6 +84579,27 @@ index f10a603b13fb0..5cb21d7da05b6 100644
ret = virtio_i2c_setup_vqs(vi);
if (ret)
return ret;
+diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
+index bb93db98404ef..612343771ce25 100644
+--- a/drivers/i2c/busses/i2c-xiic.c
++++ b/drivers/i2c/busses/i2c-xiic.c
+@@ -756,7 +756,6 @@ static const struct i2c_adapter_quirks xiic_quirks = {
+
+ static const struct i2c_adapter xiic_adapter = {
+ .owner = THIS_MODULE,
+- .name = DRIVER_NAME,
+ .class = I2C_CLASS_DEPRECATED,
+ .algo = &xiic_algorithm,
+ .quirks = &xiic_quirks,
+@@ -793,6 +792,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &pdev->dev;
+ i2c->adap.dev.of_node = pdev->dev.of_node;
++ snprintf(i2c->adap.name, sizeof(i2c->adap.name),
++ DRIVER_NAME " %s", pdev->name);
+
+ mutex_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wait);
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
index 126d1393e548b..9ce20652d4942 100644
--- a/drivers/i2c/busses/i2c-xlr.c
@@ -55296,7 +84771,7 @@ index 54964fbe3f033..cfbef70e8ba70 100644
EXPORT_SYMBOL_GPL(i2c_bus_type);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
-index bce0e8bb78520..cf5d049342ead 100644
+index bce0e8bb78520..6fd2b6718b086 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -535,6 +535,9 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo
@@ -55309,6 +84784,57 @@ index bce0e8bb78520..cf5d049342ead 100644
if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
return -EINVAL;
+@@ -665,16 +668,21 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+ i2c_dev->dev.class = i2c_dev_class;
+ i2c_dev->dev.parent = &adap->dev;
+ i2c_dev->dev.release = i2cdev_dev_release;
+- dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
++
++ res = dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
++ if (res)
++ goto err_put_i2c_dev;
+
+ res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
+- if (res) {
+- put_i2c_dev(i2c_dev, false);
+- return res;
+- }
++ if (res)
++ goto err_put_i2c_dev;
+
+ pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr);
+ return 0;
++
++err_put_i2c_dev:
++ put_i2c_dev(i2c_dev, false);
++ return res;
+ }
+
+ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c
+index 5365199a31f41..f7a7405d4350a 100644
+--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c
++++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c
+@@ -261,7 +261,7 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
+
+ err = device_create_file(&pdev->dev, &dev_attr_available_masters);
+ if (err)
+- goto err_rollback;
++ goto err_rollback_activation;
+
+ err = device_create_file(&pdev->dev, &dev_attr_current_master);
+ if (err)
+@@ -271,8 +271,9 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
+
+ err_rollback_available:
+ device_remove_file(&pdev->dev, &dev_attr_available_masters);
+-err_rollback:
++err_rollback_activation:
+ i2c_demux_deactivate_master(priv);
++err_rollback:
+ for (j = 0; j < i; j++) {
+ of_node_put(priv->chan[j].parent_np);
+ of_changeset_destroy(&priv->chan[j].chgset);
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index c3b4c677b4429..dfe18dcd008d4 100644
--- a/drivers/i3c/master.c
@@ -55496,10 +85022,66 @@ index bf7ed9e7d00f4..e56ecc075014e 100644
return IRQ_HANDLED;
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
-index 715b8138fb715..09c7f10fefb6e 100644
+index 715b8138fb715..21a99467f3646 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
-@@ -1470,7 +1470,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev)
+@@ -176,6 +176,7 @@ static const struct mma8452_event_regs trans_ev_regs = {
+ * @enabled_events: event flags enabled and handled by this driver
+ */
+ struct mma_chip_info {
++ const char *name;
+ u8 chip_id;
+ const struct iio_chan_spec *channels;
+ int num_channels;
+@@ -1301,6 +1302,7 @@ enum {
+
+ static const struct mma_chip_info mma_chip_info_table[] = {
+ [mma8451] = {
++ .name = "mma8451",
+ .chip_id = MMA8451_DEVICE_ID,
+ .channels = mma8451_channels,
+ .num_channels = ARRAY_SIZE(mma8451_channels),
+@@ -1325,6 +1327,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
+ MMA8452_INT_FF_MT,
+ },
+ [mma8452] = {
++ .name = "mma8452",
+ .chip_id = MMA8452_DEVICE_ID,
+ .channels = mma8452_channels,
+ .num_channels = ARRAY_SIZE(mma8452_channels),
+@@ -1341,6 +1344,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
+ MMA8452_INT_FF_MT,
+ },
+ [mma8453] = {
++ .name = "mma8453",
+ .chip_id = MMA8453_DEVICE_ID,
+ .channels = mma8453_channels,
+ .num_channels = ARRAY_SIZE(mma8453_channels),
+@@ -1357,6 +1361,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
+ MMA8452_INT_FF_MT,
+ },
+ [mma8652] = {
++ .name = "mma8652",
+ .chip_id = MMA8652_DEVICE_ID,
+ .channels = mma8652_channels,
+ .num_channels = ARRAY_SIZE(mma8652_channels),
+@@ -1366,6 +1371,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
+ .enabled_events = MMA8452_INT_FF_MT,
+ },
+ [mma8653] = {
++ .name = "mma8653",
+ .chip_id = MMA8653_DEVICE_ID,
+ .channels = mma8653_channels,
+ .num_channels = ARRAY_SIZE(mma8653_channels),
+@@ -1380,6 +1386,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
+ .enabled_events = MMA8452_INT_FF_MT,
+ },
+ [fxls8471] = {
++ .name = "fxls8471",
+ .chip_id = FXLS8471_DEVICE_ID,
+ .channels = mma8451_channels,
+ .num_channels = ARRAY_SIZE(mma8451_channels),
+@@ -1470,7 +1477,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev)
if (ret)
return ret;
@@ -55508,6 +85090,59 @@ index 715b8138fb715..09c7f10fefb6e 100644
return 0;
}
+@@ -1522,13 +1529,6 @@ static int mma8452_probe(struct i2c_client *client,
+ struct mma8452_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+- const struct of_device_id *match;
+-
+- match = of_match_device(mma8452_dt_ids, &client->dev);
+- if (!match) {
+- dev_err(&client->dev, "unknown device model\n");
+- return -ENODEV;
+- }
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+@@ -1537,7 +1537,14 @@ static int mma8452_probe(struct i2c_client *client,
+ data = iio_priv(indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+- data->chip_info = match->data;
++
++ data->chip_info = device_get_match_data(&client->dev);
++ if (!data->chip_info && id) {
++ data->chip_info = &mma_chip_info_table[id->driver_data];
++ } else {
++ dev_err(&client->dev, "unknown device model\n");
++ return -ENODEV;
++ }
+
+ data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(data->vdd_reg))
+@@ -1581,11 +1588,11 @@ static int mma8452_probe(struct i2c_client *client,
+ }
+
+ dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
+- match->compatible, data->chip_info->chip_id);
++ data->chip_info->name, data->chip_info->chip_id);
+
+ i2c_set_clientdata(client, indio_dev);
+ indio_dev->info = &mma8452_info;
+- indio_dev->name = id->name;
++ indio_dev->name = data->chip_info->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = data->chip_info->channels;
+ indio_dev->num_channels = data->chip_info->num_channels;
+@@ -1810,7 +1817,7 @@ MODULE_DEVICE_TABLE(i2c, mma8452_id);
+ static struct i2c_driver mma8452_driver = {
+ .driver = {
+ .name = "mma8452",
+- .of_match_table = of_match_ptr(mma8452_dt_ids),
++ .of_match_table = mma8452_dt_ids,
+ .pm = &mma8452_pm_ops,
+ },
+ .probe = mma8452_probe,
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index 4c359fb054801..c53a3398b14c4 100644
--- a/drivers/iio/accel/mma9551.c
@@ -55858,10 +85493,59 @@ index 170950d5dd499..e8fc4d01f30b6 100644
size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx);
priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL);
+diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
+index c6416ad795ca4..256177b15c511 100644
+--- a/drivers/iio/adc/twl6030-gpadc.c
++++ b/drivers/iio/adc/twl6030-gpadc.c
+@@ -911,6 +911,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ twl6030_gpadc_irq_handler,
+ IRQF_ONESHOT, "twl6030_gpadc", indio_dev);
++ if (ret)
++ return ret;
+
+ ret = twl6030_gpadc_enable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
+ if (ret < 0) {
+diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
+index 774eb3044edd8..271d73e420c42 100644
+--- a/drivers/iio/afe/iio-rescale.c
++++ b/drivers/iio/afe/iio-rescale.c
+@@ -39,7 +39,7 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
+ int *val, int *val2, long mask)
+ {
+ struct rescale *rescale = iio_priv(indio_dev);
+- unsigned long long tmp;
++ s64 tmp;
+ int ret;
+
+ switch (mask) {
+@@ -77,10 +77,10 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
+ *val2 = rescale->denominator;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_VAL_FRACTIONAL_LOG2:
+- tmp = *val * 1000000000LL;
+- do_div(tmp, rescale->denominator);
++ tmp = (s64)*val * 1000000000LL;
++ tmp = div_s64(tmp, rescale->denominator);
+ tmp *= rescale->numerator;
+- do_div(tmp, 1000000000LL);
++ tmp = div_s64(tmp, 1000000000LL);
+ *val = tmp;
+ return ret;
+ default:
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
-index 488ec69967d67..e50718422411d 100644
+index 488ec69967d67..cafb8c7790154 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
+@@ -178,7 +178,7 @@ static int ad5446_read_raw(struct iio_dev *indio_dev,
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+- *val = st->cached_val;
++ *val = st->cached_val >> chan->scan_type.shift;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->vref_mv;
@@ -531,8 +531,15 @@ static int ad5622_write(struct ad5446_state *st, unsigned val)
{
struct i2c_client *client = to_i2c_client(st->dev);
@@ -55879,6 +85563,19 @@ index 488ec69967d67..e50718422411d 100644
}
/*
+diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
+index 0405e92b9e8c3..987264410278c 100644
+--- a/drivers/iio/dac/ad5592r-base.c
++++ b/drivers/iio/dac/ad5592r-base.c
+@@ -523,7 +523,7 @@ static int ad5592r_alloc_channels(struct iio_dev *iio_dev)
+ if (!ret)
+ st->channel_modes[reg] = tmp;
+
+- fwnode_property_read_u32(child, "adi,off-state", &tmp);
++ ret = fwnode_property_read_u32(child, "adi,off-state", &tmp);
+ if (!ret)
+ st->channel_offstate[reg] = tmp;
+ }
diff --git a/drivers/iio/dac/ad5766.c b/drivers/iio/dac/ad5766.c
index 3104ec32dfaca..dafda84fdea35 100644
--- a/drivers/iio/dac/ad5766.c
@@ -56060,6 +85757,88 @@ index ed129321a14da..f9b4540db1f43 100644
if (ret)
return ret;
+diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
+index 824b5124a5f55..01336105792ee 100644
+--- a/drivers/iio/imu/bmi160/bmi160_core.c
++++ b/drivers/iio/imu/bmi160/bmi160_core.c
+@@ -730,7 +730,7 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
+
+ ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET);
+ if (ret)
+- return ret;
++ goto disable_regulator;
+
+ usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1);
+
+@@ -741,29 +741,37 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
+ if (use_spi) {
+ ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val);
+ if (ret)
+- return ret;
++ goto disable_regulator;
+ }
+
+ ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val);
+ if (ret) {
+ dev_err(dev, "Error reading chip id\n");
+- return ret;
++ goto disable_regulator;
+ }
+ if (val != BMI160_CHIP_ID_VAL) {
+ dev_err(dev, "Wrong chip id, got %x expected %x\n",
+ val, BMI160_CHIP_ID_VAL);
+- return -ENODEV;
++ ret = -ENODEV;
++ goto disable_regulator;
+ }
+
+ ret = bmi160_set_mode(data, BMI160_ACCEL, true);
+ if (ret)
+- return ret;
++ goto disable_regulator;
+
+ ret = bmi160_set_mode(data, BMI160_GYRO, true);
+ if (ret)
+- return ret;
++ goto disable_accel;
+
+ return 0;
++
++disable_accel:
++ bmi160_set_mode(data, BMI160_ACCEL, false);
++
++disable_regulator:
++ regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies);
++ return ret;
+ }
+
+ static int bmi160_data_rdy_trigger_set_state(struct iio_trigger *trig,
+diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+index 85b1934cec60e..53891010a91de 100644
+--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+@@ -18,12 +18,15 @@ static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+ unsigned int mask, val;
+ int ret;
+
+- /* setup interface registers */
+- ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+- INV_ICM42600_INTF_CONFIG6_MASK,
+- INV_ICM42600_INTF_CONFIG6_I3C_EN);
+- if (ret)
+- return ret;
++ /*
++ * setup interface registers
++ * This register write to REG_INTF_CONFIG6 enables a spike filter that
++ * is impacting the line and can prevent the I2C ACK to be seen by the
++ * controller. So we don't test the return value.
++ */
++ regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
++ INV_ICM42600_INTF_CONFIG6_MASK,
++ INV_ICM42600_INTF_CONFIG6_I3C_EN);
+
+ ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+ INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index 1dabfd615dabf..f89724481df93 100644
--- a/drivers/iio/imu/kmx61.c
@@ -56338,6 +86117,70 @@ index b23caa2f2aa1f..f504ed351b3e2 100644
return trig;
+diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
+index 391a3380a1d10..b5966365d769c 100644
+--- a/drivers/iio/inkern.c
++++ b/drivers/iio/inkern.c
+@@ -578,28 +578,50 @@ EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
+ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
+ int raw, int *processed, unsigned int scale)
+ {
+- int scale_type, scale_val, scale_val2, offset;
++ int scale_type, scale_val, scale_val2;
++ int offset_type, offset_val, offset_val2;
+ s64 raw64 = raw;
+- int ret;
+
+- ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET);
+- if (ret >= 0)
+- raw64 += offset;
++ offset_type = iio_channel_read(chan, &offset_val, &offset_val2,
++ IIO_CHAN_INFO_OFFSET);
++ if (offset_type >= 0) {
++ switch (offset_type) {
++ case IIO_VAL_INT:
++ break;
++ case IIO_VAL_INT_PLUS_MICRO:
++ case IIO_VAL_INT_PLUS_NANO:
++ /*
++ * Both IIO_VAL_INT_PLUS_MICRO and IIO_VAL_INT_PLUS_NANO
++ * implicitely truncate the offset to it's integer form.
++ */
++ break;
++ case IIO_VAL_FRACTIONAL:
++ offset_val /= offset_val2;
++ break;
++ case IIO_VAL_FRACTIONAL_LOG2:
++ offset_val >>= offset_val2;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ raw64 += offset_val;
++ }
+
+ scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
+ IIO_CHAN_INFO_SCALE);
+ if (scale_type < 0) {
+ /*
+- * Just pass raw values as processed if no scaling is
+- * available.
++ * If no channel scaling is available apply consumer scale to
++ * raw value and return.
+ */
+- *processed = raw;
++ *processed = raw * scale;
+ return 0;
+ }
+
+ switch (scale_type) {
+ case IIO_VAL_INT:
+- *processed = raw64 * scale_val;
++ *processed = raw64 * scale_val * scale;
+ break;
+ case IIO_VAL_INT_PLUS_MICRO:
+ if (scale_val2 < 0)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 1830221da48d2..f0bd0ad34f222 100644
--- a/drivers/iio/light/ltr501.c
@@ -56375,6 +86218,18 @@ index 07e91846307c7..fc63856ed54de 100644
mutex_unlock(&data->lock);
return IRQ_HANDLED;
+diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
+index 42b8a2680e3aa..1509fd0cbb50f 100644
+--- a/drivers/iio/magnetometer/ak8975.c
++++ b/drivers/iio/magnetometer/ak8975.c
+@@ -389,6 +389,7 @@ static int ak8975_power_on(const struct ak8975_data *data)
+ if (ret) {
+ dev_warn(&data->client->dev,
+ "Failed to enable specified Vid supply\n");
++ regulator_disable(data->vdd);
+ return ret;
+ }
+
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index f96f531753495..3d4d21f979fab 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
@@ -56488,10 +86343,27 @@ index 33083877cd19d..4353b749ecef2 100644
MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
-index c903b74f46a46..35f0d5e7533d6 100644
+index c903b74f46a46..1c107d6d03b99 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
-@@ -3322,7 +3322,7 @@ static int cm_lap_handler(struct cm_work *work)
+@@ -2824,6 +2824,7 @@ static int cm_dreq_handler(struct cm_work *work)
+ switch (cm_id_priv->id.state) {
+ case IB_CM_REP_SENT:
+ case IB_CM_DREQ_SENT:
++ case IB_CM_MRA_REP_RCVD:
+ ib_cancel_mad(cm_id_priv->msg);
+ break;
+ case IB_CM_ESTABLISHED:
+@@ -2831,8 +2832,6 @@ static int cm_dreq_handler(struct cm_work *work)
+ cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
+ ib_cancel_mad(cm_id_priv->msg);
+ break;
+- case IB_CM_MRA_REP_RCVD:
+- break;
+ case IB_CM_TIMEWAIT:
+ atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
+ [CM_DREQ_COUNTER]);
+@@ -3322,7 +3321,7 @@ static int cm_lap_handler(struct cm_work *work)
ret = cm_init_av_by_path(param->alternate_path, NULL, &alt_av);
if (ret) {
rdma_destroy_ah_attr(&ah_attr);
@@ -56501,7 +86373,7 @@ index c903b74f46a46..35f0d5e7533d6 100644
spin_lock_irq(&cm_id_priv->lock);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
-index 704ce595542c5..db7b5de3bc76b 100644
+index 704ce595542c5..a814dabcdff43 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -67,8 +67,8 @@ static const char * const cma_events[] = {
@@ -56569,6 +86441,15 @@ index 704ce595542c5..db7b5de3bc76b 100644
cancel_work_sync(&mc->iboe_join.work);
}
+@@ -2632,7 +2640,7 @@ int rdma_set_ack_timeout(struct rdma_cm_id *id, u8 timeout)
+ {
+ struct rdma_id_private *id_priv;
+
+- if (id->qp_type != IB_QPT_RC)
++ if (id->qp_type != IB_QPT_RC && id->qp_type != IB_QPT_XRC_INI)
+ return -EINVAL;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
@@ -3360,22 +3368,30 @@ err:
static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
const struct sockaddr *dst_addr)
@@ -56821,7 +86702,7 @@ index 2f2c7646fce17..a02916a3a79ce 100644
data[i] = &uapi->notsupp_method;
uapi->write_methods = data;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
-index 89a2b21976d63..20a46d8731455 100644
+index 89a2b21976d63..59e20936b8007 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1232,6 +1232,9 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
@@ -56834,6 +86715,14 @@ index 89a2b21976d63..20a46d8731455 100644
rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
+@@ -2150,6 +2153,7 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ return mr;
+
+ mr->device = pd->device;
++ mr->type = IB_MR_TYPE_USER;
+ mr->pd = pd;
+ mr->dm = NULL;
+ atomic_inc(&pd->usecnt);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 408dfbcc47b5e..b7ec3a3926785 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -57143,6 +87032,30 @@ index e594a961f513e..3e475814b6fa6 100644
netdev->priv_destructor = hfi1_ipoib_netdev_dtor;
netdev->needs_free_netdev = true;
+diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c
+index 876cc78a22cca..7333646021bb8 100644
+--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
++++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
+@@ -80,6 +80,9 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
+ unsigned long flags;
+ struct list_head del_list;
+
++ /* Prevent freeing of mm until we are completely finished. */
++ mmgrab(handler->mn.mm);
++
+ /* Unregister first so we don't get any more notifications. */
+ mmu_notifier_unregister(&handler->mn, handler->mn.mm);
+
+@@ -102,6 +105,9 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
+
+ do_remove(handler, &del_list);
+
++ /* Now the mm may be freed. */
++ mmdrop(handler->mn.mm);
++
+ kfree(handler);
+ }
+
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index 2b6c24b7b5865..f07d328689d3d 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
@@ -57157,6 +87070,20 @@ index 2b6c24b7b5865..f07d328689d3d 100644
rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id,
sdma_rht_params);
+diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
+index 26bea51869bf0..ef8e0bdacb516 100644
+--- a/drivers/infiniband/hw/hfi1/verbs.c
++++ b/drivers/infiniband/hw/hfi1/verbs.c
+@@ -1397,8 +1397,7 @@ static int query_port(struct rvt_dev_info *rdi, u32 port_num,
+ 4096 : hfi1_max_mtu), IB_MTU_4096);
+ props->active_mtu = !valid_ib_mtu(ppd->ibmtu) ? props->max_mtu :
+ mtu_to_enum(ppd->ibmtu, IB_MTU_4096);
+- props->phys_mtu = HFI1_CAP_IS_KSET(AIP) ? hfi1_max_mtu :
+- ib_mtu_enum_to_int(props->max_mtu);
++ props->phys_mtu = hfi1_max_mtu;
+
+ return 0;
+ }
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index d5f3faa1627a4..96fe73ba689c1 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -57401,8 +87328,135 @@ index 6eee9deadd122..e64ef6903fb4f 100644
srq->wrid = NULL;
}
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 6dea0a49d1718..632f65e53b63f 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2305,10 +2305,8 @@ err:
+ return NULL;
+ }
+
+-static void irdma_cm_node_free_cb(struct rcu_head *rcu_head)
++static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+ {
+- struct irdma_cm_node *cm_node =
+- container_of(rcu_head, struct irdma_cm_node, rcu_head);
+ struct irdma_cm_core *cm_core = cm_node->cm_core;
+ struct irdma_qp *iwqp;
+ struct irdma_cm_info nfo;
+@@ -2356,7 +2354,6 @@ static void irdma_cm_node_free_cb(struct rcu_head *rcu_head)
+ }
+
+ cm_core->cm_free_ah(cm_node);
+- kfree(cm_node);
+ }
+
+ /**
+@@ -2384,8 +2381,9 @@ void irdma_rem_ref_cm_node(struct irdma_cm_node *cm_node)
+
+ spin_unlock_irqrestore(&cm_core->ht_lock, flags);
+
+- /* wait for all list walkers to exit their grace period */
+- call_rcu(&cm_node->rcu_head, irdma_cm_node_free_cb);
++ irdma_destroy_connection(cm_node);
++
++ kfree_rcu(cm_node, rcu_head);
+ }
+
+ /**
+@@ -3244,15 +3242,10 @@ enum irdma_status_code irdma_setup_cm_core(struct irdma_device *iwdev,
+ */
+ void irdma_cleanup_cm_core(struct irdma_cm_core *cm_core)
+ {
+- unsigned long flags;
+-
+ if (!cm_core)
+ return;
+
+- spin_lock_irqsave(&cm_core->ht_lock, flags);
+- if (timer_pending(&cm_core->tcp_timer))
+- del_timer_sync(&cm_core->tcp_timer);
+- spin_unlock_irqrestore(&cm_core->ht_lock, flags);
++ del_timer_sync(&cm_core->tcp_timer);
+
+ destroy_workqueue(cm_core->event_wq);
+ cm_core->dev->ws_reset(&cm_core->iwdev->vsi);
+@@ -3465,12 +3458,6 @@ static void irdma_cm_disconn_true(struct irdma_qp *iwqp)
+ }
+
+ cm_id = iwqp->cm_id;
+- /* make sure we havent already closed this connection */
+- if (!cm_id) {
+- spin_unlock_irqrestore(&iwqp->lock, flags);
+- return;
+- }
+-
+ original_hw_tcp_state = iwqp->hw_tcp_state;
+ original_ibqp_state = iwqp->ibqp_state;
+ last_ae = iwqp->last_aeq;
+@@ -3492,11 +3479,11 @@ static void irdma_cm_disconn_true(struct irdma_qp *iwqp)
+ disconn_status = -ECONNRESET;
+ }
+
+- if ((original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED ||
+- original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT ||
+- last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE ||
+- last_ae == IRDMA_AE_BAD_CLOSE ||
+- last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset)) {
++ if (original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED ||
++ original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT ||
++ last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE ||
++ last_ae == IRDMA_AE_BAD_CLOSE ||
++ last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset || !cm_id) {
+ issue_close = 1;
+ iwqp->cm_id = NULL;
+ qp->term_flags = 0;
+diff --git a/drivers/infiniband/hw/irdma/ctrl.c b/drivers/infiniband/hw/irdma/ctrl.c
+index f1e5515256e0a..1ac7067e21be1 100644
+--- a/drivers/infiniband/hw/irdma/ctrl.c
++++ b/drivers/infiniband/hw/irdma/ctrl.c
+@@ -431,7 +431,7 @@ enum irdma_status_code irdma_sc_qp_create(struct irdma_sc_qp *qp, struct irdma_c
+
+ cqp = qp->dev->cqp;
+ if (qp->qp_uk.qp_id < cqp->dev->hw_attrs.min_hw_qp_id ||
+- qp->qp_uk.qp_id > (cqp->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_QP].max_cnt - 1))
++ qp->qp_uk.qp_id >= (cqp->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_QP].max_cnt))
+ return IRDMA_ERR_INVALID_QP_ID;
+
+ wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
+@@ -2551,10 +2551,10 @@ static enum irdma_status_code irdma_sc_cq_create(struct irdma_sc_cq *cq,
+ enum irdma_status_code ret_code = 0;
+
+ cqp = cq->dev->cqp;
+- if (cq->cq_uk.cq_id > (cqp->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].max_cnt - 1))
++ if (cq->cq_uk.cq_id >= (cqp->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].max_cnt))
+ return IRDMA_ERR_INVALID_CQ_ID;
+
+- if (cq->ceq_id > (cq->dev->hmc_fpm_misc.max_ceqs - 1))
++ if (cq->ceq_id >= (cq->dev->hmc_fpm_misc.max_ceqs))
+ return IRDMA_ERR_INVALID_CEQ_ID;
+
+ ceq = cq->dev->ceq[cq->ceq_id];
+@@ -3656,7 +3656,7 @@ enum irdma_status_code irdma_sc_ceq_init(struct irdma_sc_ceq *ceq,
+ info->elem_cnt > info->dev->hw_attrs.max_hw_ceq_size)
+ return IRDMA_ERR_INVALID_SIZE;
+
+- if (info->ceq_id > (info->dev->hmc_fpm_misc.max_ceqs - 1))
++ if (info->ceq_id >= (info->dev->hmc_fpm_misc.max_ceqs))
+ return IRDMA_ERR_INVALID_CEQ_ID;
+ pble_obj_cnt = info->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_PBLE].cnt;
+
+@@ -4205,7 +4205,7 @@ enum irdma_status_code irdma_sc_ccq_init(struct irdma_sc_cq *cq,
+ info->num_elem > info->dev->hw_attrs.uk_attrs.max_hw_cq_size)
+ return IRDMA_ERR_INVALID_SIZE;
+
+- if (info->ceq_id > (info->dev->hmc_fpm_misc.max_ceqs - 1))
++ if (info->ceq_id >= (info->dev->hmc_fpm_misc.max_ceqs ))
+ return IRDMA_ERR_INVALID_CEQ_ID;
+
+ pble_obj_cnt = info->dev->hmc_info->hmc_obj[IRDMA_HMC_IW_PBLE].cnt;
diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c
-index 7de525a5ccf8c..aa119441eb45c 100644
+index 7de525a5ccf8c..4f763e552eae8 100644
--- a/drivers/infiniband/hw/irdma/hw.c
+++ b/drivers/infiniband/hw/irdma/hw.c
@@ -60,6 +60,8 @@ static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq)
@@ -57440,11 +87494,52 @@ index 7de525a5ccf8c..aa119441eb45c 100644
default:
qp->flush_code = FLUSH_FATAL_ERR;
break;
+@@ -1603,7 +1608,7 @@ static enum irdma_status_code irdma_initialize_dev(struct irdma_pci_f *rf)
+ info.fpm_commit_buf = mem.va;
+
+ info.bar0 = rf->hw.hw_addr;
+- info.hmc_fn_id = PCI_FUNC(rf->pcidev->devfn);
++ info.hmc_fn_id = rf->pf_id;
+ info.hw = &rf->hw;
+ status = irdma_sc_dev_init(rf->rdma_ver, &rf->sc_dev, &info);
+ if (status)
+diff --git a/drivers/infiniband/hw/irdma/i40iw_if.c b/drivers/infiniband/hw/irdma/i40iw_if.c
+index d219f64b2c3d5..a6f758b61b0c4 100644
+--- a/drivers/infiniband/hw/irdma/i40iw_if.c
++++ b/drivers/infiniband/hw/irdma/i40iw_if.c
+@@ -77,6 +77,7 @@ static void i40iw_fill_device_info(struct irdma_device *iwdev, struct i40e_info
+ rf->rdma_ver = IRDMA_GEN_1;
+ rf->gen_ops.request_reset = i40iw_request_reset;
+ rf->pcidev = cdev_info->pcidev;
++ rf->pf_id = cdev_info->fid;
+ rf->hw.hw_addr = cdev_info->hw_addr;
+ rf->cdev = cdev_info;
+ rf->msix_count = cdev_info->msix_count;
+diff --git a/drivers/infiniband/hw/irdma/main.c b/drivers/infiniband/hw/irdma/main.c
+index 51a41359e0b41..c556a36e76703 100644
+--- a/drivers/infiniband/hw/irdma/main.c
++++ b/drivers/infiniband/hw/irdma/main.c
+@@ -226,6 +226,7 @@ static void irdma_fill_device_info(struct irdma_device *iwdev, struct ice_pf *pf
+ rf->hw.hw_addr = pf->hw.hw_addr;
+ rf->pcidev = pf->pdev;
+ rf->msix_count = pf->num_rdma_msix;
++ rf->pf_id = pf->hw.pf_id;
+ rf->msix_entries = &pf->msix_entries[pf->rdma_base_vector];
+ rf->default_vsi.vsi_idx = vsi->vsi_num;
+ rf->protocol_used = IRDMA_ROCE_PROTOCOL_ONLY;
diff --git a/drivers/infiniband/hw/irdma/main.h b/drivers/infiniband/hw/irdma/main.h
-index b678fe712447e..8b215f3cee891 100644
+index b678fe712447e..454b4b370386c 100644
--- a/drivers/infiniband/hw/irdma/main.h
+++ b/drivers/infiniband/hw/irdma/main.h
-@@ -541,6 +541,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd,
+@@ -257,6 +257,7 @@ struct irdma_pci_f {
+ u8 *mem_rsrc;
+ u8 rdma_ver;
+ u8 rst_to;
++ u8 pf_id;
+ enum irdma_protocol_used protocol_used;
+ u32 sd_type;
+ u32 msix_count;
+@@ -541,6 +542,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd,
void (*callback_fcn)(struct irdma_cqp_request *cqp_request),
void *cb_param);
void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request);
@@ -57502,10 +87597,145 @@ index e1b3b8118a2ca..aa20827dcc9de 100644
};
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
-index ac91ea5296db9..feebfe6bf31ad 100644
+index ac91ea5296db9..85d4212f59dbc 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
-@@ -2284,15 +2284,10 @@ enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm,
+@@ -150,31 +150,35 @@ int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event,
+ void *ptr)
+ {
+ struct in_ifaddr *ifa = ptr;
+- struct net_device *netdev = ifa->ifa_dev->dev;
++ struct net_device *real_dev, *netdev = ifa->ifa_dev->dev;
+ struct irdma_device *iwdev;
+ struct ib_device *ibdev;
+ u32 local_ipaddr;
+
+- ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_IRDMA);
++ real_dev = rdma_vlan_dev_real_dev(netdev);
++ if (!real_dev)
++ real_dev = netdev;
++
++ ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA);
+ if (!ibdev)
+ return NOTIFY_DONE;
+
+ iwdev = to_iwdev(ibdev);
+ local_ipaddr = ntohl(ifa->ifa_address);
+ ibdev_dbg(&iwdev->ibdev,
+- "DEV: netdev %p event %lu local_ip=%pI4 MAC=%pM\n", netdev,
+- event, &local_ipaddr, netdev->dev_addr);
++ "DEV: netdev %p event %lu local_ip=%pI4 MAC=%pM\n", real_dev,
++ event, &local_ipaddr, real_dev->dev_addr);
+ switch (event) {
+ case NETDEV_DOWN:
+- irdma_manage_arp_cache(iwdev->rf, netdev->dev_addr,
++ irdma_manage_arp_cache(iwdev->rf, real_dev->dev_addr,
+ &local_ipaddr, true, IRDMA_ARP_DELETE);
+- irdma_if_notify(iwdev, netdev, &local_ipaddr, true, false);
++ irdma_if_notify(iwdev, real_dev, &local_ipaddr, true, false);
+ irdma_gid_change_event(&iwdev->ibdev);
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGEADDR:
+- irdma_add_arp(iwdev->rf, &local_ipaddr, true, netdev->dev_addr);
+- irdma_if_notify(iwdev, netdev, &local_ipaddr, true, true);
++ irdma_add_arp(iwdev->rf, &local_ipaddr, true, real_dev->dev_addr);
++ irdma_if_notify(iwdev, real_dev, &local_ipaddr, true, true);
+ irdma_gid_change_event(&iwdev->ibdev);
+ break;
+ default:
+@@ -196,32 +200,36 @@ int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event,
+ void *ptr)
+ {
+ struct inet6_ifaddr *ifa = ptr;
+- struct net_device *netdev = ifa->idev->dev;
++ struct net_device *real_dev, *netdev = ifa->idev->dev;
+ struct irdma_device *iwdev;
+ struct ib_device *ibdev;
+ u32 local_ipaddr6[4];
+
+- ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_IRDMA);
++ real_dev = rdma_vlan_dev_real_dev(netdev);
++ if (!real_dev)
++ real_dev = netdev;
++
++ ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA);
+ if (!ibdev)
+ return NOTIFY_DONE;
+
+ iwdev = to_iwdev(ibdev);
+ irdma_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32);
+ ibdev_dbg(&iwdev->ibdev,
+- "DEV: netdev %p event %lu local_ip=%pI6 MAC=%pM\n", netdev,
+- event, local_ipaddr6, netdev->dev_addr);
++ "DEV: netdev %p event %lu local_ip=%pI6 MAC=%pM\n", real_dev,
++ event, local_ipaddr6, real_dev->dev_addr);
+ switch (event) {
+ case NETDEV_DOWN:
+- irdma_manage_arp_cache(iwdev->rf, netdev->dev_addr,
++ irdma_manage_arp_cache(iwdev->rf, real_dev->dev_addr,
+ local_ipaddr6, false, IRDMA_ARP_DELETE);
+- irdma_if_notify(iwdev, netdev, local_ipaddr6, false, false);
++ irdma_if_notify(iwdev, real_dev, local_ipaddr6, false, false);
+ irdma_gid_change_event(&iwdev->ibdev);
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGEADDR:
+ irdma_add_arp(iwdev->rf, local_ipaddr6, false,
+- netdev->dev_addr);
+- irdma_if_notify(iwdev, netdev, local_ipaddr6, false, true);
++ real_dev->dev_addr);
++ irdma_if_notify(iwdev, real_dev, local_ipaddr6, false, true);
+ irdma_gid_change_event(&iwdev->ibdev);
+ break;
+ default:
+@@ -243,21 +251,23 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
+ void *ptr)
+ {
+ struct neighbour *neigh = ptr;
++ struct net_device *real_dev, *netdev = (struct net_device *)neigh->dev;
+ struct irdma_device *iwdev;
+ struct ib_device *ibdev;
+ __be32 *p;
+ u32 local_ipaddr[4] = {};
+ bool ipv4 = true;
+
+- ibdev = ib_device_get_by_netdev((struct net_device *)neigh->dev,
+- RDMA_DRIVER_IRDMA);
+- if (!ibdev)
+- return NOTIFY_DONE;
+-
+- iwdev = to_iwdev(ibdev);
+-
+ switch (event) {
+ case NETEVENT_NEIGH_UPDATE:
++ real_dev = rdma_vlan_dev_real_dev(netdev);
++ if (!real_dev)
++ real_dev = netdev;
++ ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA);
++ if (!ibdev)
++ return NOTIFY_DONE;
++
++ iwdev = to_iwdev(ibdev);
+ p = (__be32 *)neigh->primary_key;
+ if (neigh->tbl->family == AF_INET6) {
+ ipv4 = false;
+@@ -278,13 +288,12 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
+ irdma_manage_arp_cache(iwdev->rf, neigh->ha,
+ local_ipaddr, ipv4,
+ IRDMA_ARP_DELETE);
++ ib_device_put(ibdev);
+ break;
+ default:
+ break;
+ }
+
+- ib_device_put(ibdev);
+-
+ return NOTIFY_DONE;
+ }
+
+@@ -2284,15 +2293,10 @@ enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm,
sizeofbitmap = (u64)pchunk->size >> pprm->pble_shift;
@@ -57523,7 +87753,7 @@ index ac91ea5296db9..feebfe6bf31ad 100644
pchunk->sizeofbitmap = sizeofbitmap;
/* each pble is 8 bytes hence shift by 3 */
pprm->total_pble_alloc += pchunk->size >> 3;
-@@ -2536,3 +2531,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event)
+@@ -2536,3 +2540,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event)
ibevent.element.qp = &iwqp->ibqp;
iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context);
}
@@ -57543,9 +87773,43 @@ index ac91ea5296db9..feebfe6bf31ad 100644
+ return polarity != ukcq->polarity;
+}
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
-index 102dc9342f2a2..8bbc4620a97a2 100644
+index 102dc9342f2a2..8a3ac4257e867 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1617,13 +1617,13 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+
+ if (issue_modify_qp && iwqp->ibqp_state > IB_QPS_RTS) {
+ if (dont_wait) {
+- if (iwqp->cm_id && iwqp->hw_tcp_state) {
++ if (iwqp->hw_tcp_state) {
+ spin_lock_irqsave(&iwqp->lock, flags);
+ iwqp->hw_tcp_state = IRDMA_TCP_STATE_CLOSED;
+ iwqp->last_aeq = IRDMA_AE_RESET_SENT;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+- irdma_cm_disconn(iwqp);
+ }
++ irdma_cm_disconn(iwqp);
+ } else {
+ int close_timer_started;
+
+@@ -2506,7 +2506,7 @@ static int irdma_dealloc_mw(struct ib_mw *ibmw)
+ cqp_info = &cqp_request->info;
+ info = &cqp_info->in.u.dealloc_stag.info;
+ memset(info, 0, sizeof(*info));
+- info->pd_id = iwpd->sc_pd.pd_id & 0x00007fff;
++ info->pd_id = iwpd->sc_pd.pd_id;
+ info->stag_idx = ibmw->rkey >> IRDMA_CQPSQ_STAG_IDX_S;
+ info->mr = false;
+ cqp_info->cqp_cmd = IRDMA_OP_DEALLOC_STAG;
+@@ -3018,7 +3018,7 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
+ cqp_info = &cqp_request->info;
+ info = &cqp_info->in.u.dealloc_stag.info;
+ memset(info, 0, sizeof(*info));
+- info->pd_id = iwpd->sc_pd.pd_id & 0x00007fff;
++ info->pd_id = iwpd->sc_pd.pd_id;
+ info->stag_idx = ib_mr->rkey >> IRDMA_CQPSQ_STAG_IDX_S;
+ info->mr = true;
+ if (iwpbl->pbl_allocated)
@@ -3604,18 +3604,31 @@ static int irdma_req_notify_cq(struct ib_cq *ibcq,
struct irdma_cq *iwcq;
struct irdma_cq_uk *ukcq;
@@ -57657,6 +87921,55 @@ index 8662f462e2a5f..3a1a4ac9dd33d 100644
}
err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp);
+diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
+index e95967aefe788..21beded40066d 100644
+--- a/drivers/infiniband/hw/mlx5/devx.c
++++ b/drivers/infiniband/hw/mlx5/devx.c
+@@ -1891,8 +1891,10 @@ subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
+ key_level2,
+ obj_event,
+ GFP_KERNEL);
+- if (err)
++ if (err) {
++ kfree(obj_event);
+ return err;
++ }
+ INIT_LIST_HEAD(&obj_event->obj_sub_list);
+ }
+
+diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
+index 22e2f4d79743d..cf203f879d340 100644
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -536,8 +536,10 @@ static void __cache_work_func(struct mlx5_cache_ent *ent)
+ spin_lock_irq(&ent->lock);
+ if (ent->disabled)
+ goto out;
+- if (need_delay)
++ if (need_delay) {
+ queue_delayed_work(cache->wq, &ent->dwork, 300 * HZ);
++ goto out;
++ }
+ remove_cache_mr_locked(ent);
+ queue_adjust_cache_locked(ent);
+ }
+@@ -580,6 +582,8 @@ struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
+ ent = &cache->ent[entry];
+ spin_lock_irq(&ent->lock);
+ if (list_empty(&ent->head)) {
++ queue_adjust_cache_locked(ent);
++ ent->miss++;
+ spin_unlock_irq(&ent->lock);
+ mr = create_cache_mr(ent);
+ if (IS_ERR(mr))
+@@ -631,6 +635,7 @@ static void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
+ {
+ struct mlx5_cache_ent *ent = mr->cache_ent;
+
++ WRITE_ONCE(dev->cache.last_add, jiffies);
+ spin_lock_irq(&ent->lock);
+ list_add_tail(&mr->list, &ent->head);
+ ent->available_mrs++;
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index dcb3653db72d7..f652d083ff20f 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
@@ -57729,7 +88042,7 @@ index ac11943a5ddb0..bf2f30d67949d 100644
pkt->addrlimit = addrlimit;
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
-index 3305f2744bfaa..ae50b56e89132 100644
+index 3305f2744bfaa..8ef112f883a77 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -3073,6 +3073,8 @@ do_write:
@@ -57741,6 +88054,19 @@ index 3305f2744bfaa..ae50b56e89132 100644
if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64),
wqe->atomic_wr.remote_addr,
wqe->atomic_wr.rkey,
+@@ -3188,7 +3190,11 @@ serr_no_r_lock:
+ spin_lock_irqsave(&sqp->s_lock, flags);
+ rvt_send_complete(sqp, wqe, send_status);
+ if (sqp->ibqp.qp_type == IB_QPT_RC) {
+- int lastwqe = rvt_error_qp(sqp, IB_WC_WR_FLUSH_ERR);
++ int lastwqe;
++
++ spin_lock(&sqp->r_lock);
++ lastwqe = rvt_error_qp(sqp, IB_WC_WR_FLUSH_ERR);
++ spin_unlock(&sqp->r_lock);
+
+ sqp->s_flags &= ~RVT_S_BUSY;
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
index f0c954575bdec..4fd73b51fabf2 100644
--- a/drivers/infiniband/sw/rxe/rxe_loc.h
@@ -58032,6 +88358,35 @@ index 3894197a82f62..fc996fd31e589 100644
break;
case IB_WR_BIND_MW:
ret = rxe_bind_mw(qp, wqe);
+diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
+index 5501227ddc650..8ed172ab0beb4 100644
+--- a/drivers/infiniband/sw/rxe/rxe_resp.c
++++ b/drivers/infiniband/sw/rxe/rxe_resp.c
+@@ -830,6 +830,10 @@ static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
+ return RESPST_ERR_INVALIDATE_RKEY;
+ }
+
++ if (pkt->mask & RXE_END_MASK)
++ /* We successfully processed this new request. */
++ qp->resp.msn++;
++
+ /* next expected psn, read handles this separately */
+ qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
+ qp->resp.ack_psn = qp->resp.psn;
+@@ -837,11 +841,9 @@ static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
+ qp->resp.opcode = pkt->opcode;
+ qp->resp.status = IB_WC_SUCCESS;
+
+- if (pkt->mask & RXE_COMP_MASK) {
+- /* We successfully processed this new request. */
+- qp->resp.msn++;
++ if (pkt->mask & RXE_COMP_MASK)
+ return RESPST_COMPLETE;
+- } else if (qp_type(qp) == IB_QPT_RC)
++ else if (qp_type(qp) == IB_QPT_RC)
+ return RESPST_ACKNOWLEDGE;
+ else
+ return RESPST_CLEANUP;
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index ac2a2148027f4..d90b1d77de347 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -58100,6 +88455,29 @@ index 368959ae9a8cc..df03d84c6868a 100644
if (READ_ONCE(orq_e->flags) == 0)
return orq_e;
+diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
+index 7a5ed86ffc9f9..18a64ccbb0e58 100644
+--- a/drivers/infiniband/sw/siw/siw_cm.c
++++ b/drivers/infiniband/sw/siw/siw_cm.c
+@@ -968,14 +968,15 @@ static void siw_accept_newconn(struct siw_cep *cep)
+
+ siw_cep_set_inuse(new_cep);
+ rv = siw_proc_mpareq(new_cep);
+- siw_cep_set_free(new_cep);
+-
+ if (rv != -EAGAIN) {
+ siw_cep_put(cep);
+ new_cep->listen_cep = NULL;
+- if (rv)
++ if (rv) {
++ siw_cep_set_free(new_cep);
+ goto error;
++ }
+ }
++ siw_cep_set_free(new_cep);
+ }
+ return;
+
diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c
index 60116f20653c7..875ea6f1b04a2 100644
--- a/drivers/infiniband/sw/siw/siw_qp_rx.c
@@ -58296,22 +88674,42 @@ index 71eda91e810cf..5d416ec228717 100644
kfree(host);
diff --git a/drivers/input/input.c b/drivers/input/input.c
-index ccaeb24263854..c3139bc2aa0db 100644
+index ccaeb24263854..ba246fabc6c17 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
-@@ -2285,6 +2285,12 @@ int input_register_device(struct input_dev *dev)
- /* KEY_RESERVED is not supposed to be transmitted to userspace. */
- __clear_bit(KEY_RESERVED, dev->keybit);
-
-+ /* Buttonpads should not map BTN_RIGHT and/or BTN_MIDDLE. */
-+ if (test_bit(INPUT_PROP_BUTTONPAD, dev->propbit)) {
-+ __clear_bit(BTN_RIGHT, dev->keybit);
-+ __clear_bit(BTN_MIDDLE, dev->keybit);
+@@ -47,6 +47,17 @@ static DEFINE_MUTEX(input_mutex);
+
+ static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
+
++static const unsigned int input_max_code[EV_CNT] = {
++ [EV_KEY] = KEY_MAX,
++ [EV_REL] = REL_MAX,
++ [EV_ABS] = ABS_MAX,
++ [EV_MSC] = MSC_MAX,
++ [EV_SW] = SW_MAX,
++ [EV_LED] = LED_MAX,
++ [EV_SND] = SND_MAX,
++ [EV_FF] = FF_MAX,
++};
++
+ static inline int is_event_supported(unsigned int code,
+ unsigned long *bm, unsigned int max)
+ {
+@@ -2074,6 +2085,14 @@ EXPORT_SYMBOL(input_get_timestamp);
+ */
+ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
+ {
++ if (type < EV_CNT && input_max_code[type] &&
++ code > input_max_code[type]) {
++ pr_err("%s: invalid code %u for type %u\n", __func__, code,
++ type);
++ dump_stack();
++ return;
+ }
+
- /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
- input_cleanse_bitmasks(dev);
-
+ switch (type) {
+ case EV_KEY:
+ __set_bit(code, dev->keybit);
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6c554c11a7ac3..ea58805c480fa 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
@@ -58368,6 +88766,19 @@ index e75650e98c9ef..e402915cc0c00 100644
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the keypad on your Samsung mobile
+diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
+index 43375b38ee592..8a7ce41b8c56e 100644
+--- a/drivers/input/keyboard/omap4-keypad.c
++++ b/drivers/input/keyboard/omap4-keypad.c
+@@ -393,7 +393,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
+ * revision register.
+ */
+ error = pm_runtime_get_sync(dev);
+- if (error) {
++ if (error < 0) {
+ dev_err(dev, "pm_runtime_get_sync() failed\n");
+ pm_runtime_put_noidle(dev);
+ return error;
diff --git a/drivers/input/misc/ariel-pwrbutton.c b/drivers/input/misc/ariel-pwrbutton.c
index 17bbaac8b80c8..cdc80715b5fd6 100644
--- a/drivers/input/misc/ariel-pwrbutton.c
@@ -58856,6 +89267,30 @@ index 0b9f1d0a8f8b0..3fc0a89cc785c 100644
err_platform_exit:
i8042_platform_exit();
return err;
+diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
+index fcb1b646436a5..1581f6ef09279 100644
+--- a/drivers/input/tablet/aiptek.c
++++ b/drivers/input/tablet/aiptek.c
+@@ -1787,15 +1787,13 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+ input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
+
+- /* Verify that a device really has an endpoint */
+- if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
++ err = usb_find_common_endpoints(intf->cur_altsetting,
++ NULL, NULL, &endpoint, NULL);
++ if (err) {
+ dev_err(&intf->dev,
+- "interface has %d endpoints, but must have minimum 1\n",
+- intf->cur_altsetting->desc.bNumEndpoints);
+- err = -EINVAL;
++ "interface has no int in endpoints, but must have minimum 1\n");
+ goto fail3;
+ }
+- endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+ /* Go set up our URB, which is called when the tablet receives
+ * input.
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 05de92c0293bc..eb66cd2689b7c 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -58952,6 +89387,22 @@ index 4f53d3c57e698..5051a1766aac6 100644
{ .id = "927", .data = &gt911_chip_data },
{ .id = "928", .data = &gt911_chip_data },
+diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
+index 30576a5f2f045..f437eefec94ad 100644
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -420,9 +420,9 @@ static int ili210x_i2c_probe(struct i2c_client *client,
+ if (error)
+ return error;
+
+- usleep_range(50, 100);
++ usleep_range(12000, 15000);
+ gpiod_set_value_cansleep(reset_gpio, 0);
+- msleep(100);
++ msleep(160);
+ }
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 6abae665ca71d..9d1dea6996a22 100644
--- a/drivers/input/touchscreen/st1232.c
@@ -58965,6 +89416,35 @@ index 6abae665ca71d..9d1dea6996a22 100644
error = st1232_ts_read_data(ts, REG_STATUS, 1);
if (!error) {
switch (ts->read_buf[0]) {
+diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
+index bc11203c9cf78..72e0b767e1ba4 100644
+--- a/drivers/input/touchscreen/stmfts.c
++++ b/drivers/input/touchscreen/stmfts.c
+@@ -339,11 +339,11 @@ static int stmfts_input_open(struct input_dev *dev)
+
+ err = pm_runtime_get_sync(&sdata->client->dev);
+ if (err < 0)
+- return err;
++ goto out;
+
+ err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_ON);
+ if (err)
+- return err;
++ goto out;
+
+ mutex_lock(&sdata->mutex);
+ sdata->running = true;
+@@ -366,7 +366,9 @@ static int stmfts_input_open(struct input_dev *dev)
+ "failed to enable touchkey\n");
+ }
+
+- return 0;
++out:
++ pm_runtime_put_noidle(&sdata->client->dev);
++ return err;
+ }
+
+ static void stmfts_input_close(struct input_dev *dev)
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 83e685557a197..cfc943423241f 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -58992,10 +89472,83 @@ index 83e685557a197..cfc943423241f 100644
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
STEPCONFIG_OPENDLY);
diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c
-index b8d901099378d..1e70b8d2a8d79 100644
+index b8d901099378d..400957f4c8c9c 100644
--- a/drivers/input/touchscreen/zinitix.c
+++ b/drivers/input/touchscreen/zinitix.c
-@@ -488,6 +488,15 @@ static int zinitix_ts_probe(struct i2c_client *client)
+@@ -135,7 +135,7 @@ struct point_coord {
+
+ struct touch_event {
+ __le16 status;
+- u8 finger_cnt;
++ u8 finger_mask;
+ u8 time_stamp;
+ struct point_coord point_coord[MAX_SUPPORTED_FINGER_NUM];
+ };
+@@ -311,11 +311,32 @@ static int zinitix_send_power_on_sequence(struct bt541_ts_data *bt541)
+ static void zinitix_report_finger(struct bt541_ts_data *bt541, int slot,
+ const struct point_coord *p)
+ {
++ u16 x, y;
++
++ if (unlikely(!(p->sub_status &
++ (SUB_BIT_UP | SUB_BIT_DOWN | SUB_BIT_MOVE)))) {
++ dev_dbg(&bt541->client->dev, "unknown finger event %#02x\n",
++ p->sub_status);
++ return;
++ }
++
++ x = le16_to_cpu(p->x);
++ y = le16_to_cpu(p->y);
++
+ input_mt_slot(bt541->input_dev, slot);
+- input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER, true);
+- touchscreen_report_pos(bt541->input_dev, &bt541->prop,
+- le16_to_cpu(p->x), le16_to_cpu(p->y), true);
+- input_report_abs(bt541->input_dev, ABS_MT_TOUCH_MAJOR, p->width);
++ if (input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER,
++ !(p->sub_status & SUB_BIT_UP))) {
++ touchscreen_report_pos(bt541->input_dev,
++ &bt541->prop, x, y, true);
++ input_report_abs(bt541->input_dev,
++ ABS_MT_TOUCH_MAJOR, p->width);
++ dev_dbg(&bt541->client->dev, "finger %d %s (%u, %u)\n",
++ slot, p->sub_status & SUB_BIT_DOWN ? "down" : "move",
++ x, y);
++ } else {
++ dev_dbg(&bt541->client->dev, "finger %d up (%u, %u)\n",
++ slot, x, y);
++ }
+ }
+
+ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler)
+@@ -323,6 +344,7 @@ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler)
+ struct bt541_ts_data *bt541 = bt541_handler;
+ struct i2c_client *client = bt541->client;
+ struct touch_event touch_event;
++ unsigned long finger_mask;
+ int error;
+ int i;
+
+@@ -335,10 +357,14 @@ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler)
+ goto out;
+ }
+
+- for (i = 0; i < MAX_SUPPORTED_FINGER_NUM; i++)
+- if (touch_event.point_coord[i].sub_status & SUB_BIT_EXIST)
+- zinitix_report_finger(bt541, i,
+- &touch_event.point_coord[i]);
++ finger_mask = touch_event.finger_mask;
++ for_each_set_bit(i, &finger_mask, MAX_SUPPORTED_FINGER_NUM) {
++ const struct point_coord *p = &touch_event.point_coord[i];
++
++ /* Only process contacts that are actually reported */
++ if (p->sub_status & SUB_BIT_EXIST)
++ zinitix_report_finger(bt541, i, p);
++ }
+
+ input_mt_sync_frame(bt541->input_dev);
+ input_sync(bt541->input_dev);
+@@ -488,6 +514,15 @@ static int zinitix_ts_probe(struct i2c_client *client)
return error;
}
@@ -59011,7 +89564,7 @@ index b8d901099378d..1e70b8d2a8d79 100644
error = zinitix_init_input_dev(bt541);
if (error) {
dev_err(&client->dev,
-@@ -513,15 +522,6 @@ static int zinitix_ts_probe(struct i2c_client *client)
+@@ -513,15 +548,6 @@ static int zinitix_ts_probe(struct i2c_client *client)
return -EINVAL;
}
@@ -59027,6 +89580,27 @@ index b8d901099378d..1e70b8d2a8d79 100644
return 0;
}
+diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
+index 9050ca1f4285c..808f6e7a80482 100644
+--- a/drivers/interconnect/core.c
++++ b/drivers/interconnect/core.c
+@@ -1087,9 +1087,15 @@ static int of_count_icc_providers(struct device_node *np)
+ {
+ struct device_node *child;
+ int count = 0;
++ const struct of_device_id __maybe_unused ignore_list[] = {
++ { .compatible = "qcom,sc7180-ipa-virt" },
++ { .compatible = "qcom,sdx55-ipa-virt" },
++ {}
++ };
+
+ for_each_available_child_of_node(np, child) {
+- if (of_property_read_bool(child, "#interconnect-cells"))
++ if (of_property_read_bool(child, "#interconnect-cells") &&
++ likely(!of_match_node(ignore_list, child)))
+ count++;
+ count += of_count_icc_providers(child);
+ }
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 54de49ca7808a..ddf1805ded0c0 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
@@ -59039,6 +89613,66 @@ index 54de49ca7808a..ddf1805ded0c0 100644
if (qn->rate == rate)
return 0;
+diff --git a/drivers/interconnect/qcom/sdx55.c b/drivers/interconnect/qcom/sdx55.c
+index 03d604f84cc57..e3ac25a997b71 100644
+--- a/drivers/interconnect/qcom/sdx55.c
++++ b/drivers/interconnect/qcom/sdx55.c
+@@ -18,7 +18,6 @@
+ #include "icc-rpmh.h"
+ #include "sdx55.h"
+
+-DEFINE_QNODE(ipa_core_master, SDX55_MASTER_IPA_CORE, 1, 8, SDX55_SLAVE_IPA_CORE);
+ DEFINE_QNODE(llcc_mc, SDX55_MASTER_LLCC, 4, 4, SDX55_SLAVE_EBI_CH0);
+ DEFINE_QNODE(acm_tcu, SDX55_MASTER_TCU_0, 1, 8, SDX55_SLAVE_LLCC, SDX55_SLAVE_MEM_NOC_SNOC, SDX55_SLAVE_MEM_NOC_PCIE_SNOC);
+ DEFINE_QNODE(qnm_snoc_gc, SDX55_MASTER_SNOC_GC_MEM_NOC, 1, 8, SDX55_SLAVE_LLCC);
+@@ -40,7 +39,6 @@ DEFINE_QNODE(xm_pcie, SDX55_MASTER_PCIE, 1, 8, SDX55_SLAVE_ANOC_SNOC);
+ DEFINE_QNODE(xm_qdss_etr, SDX55_MASTER_QDSS_ETR, 1, 8, SDX55_SLAVE_SNOC_CFG, SDX55_SLAVE_EMAC_CFG, SDX55_SLAVE_USB3, SDX55_SLAVE_AOSS, SDX55_SLAVE_SPMI_FETCHER, SDX55_SLAVE_QDSS_CFG, SDX55_SLAVE_PDM, SDX55_SLAVE_SNOC_MEM_NOC_GC, SDX55_SLAVE_TCSR, SDX55_SLAVE_CNOC_DDRSS, SDX55_SLAVE_SPMI_VGI_COEX, SDX55_SLAVE_QPIC, SDX55_SLAVE_OCIMEM, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_USB3_PHY_CFG, SDX55_SLAVE_AOP, SDX55_SLAVE_BLSP_1, SDX55_SLAVE_SDCC_1, SDX55_SLAVE_CNOC_MSS, SDX55_SLAVE_PCIE_PARF, SDX55_SLAVE_ECC_CFG, SDX55_SLAVE_AUDIO, SDX55_SLAVE_AOSS, SDX55_SLAVE_PRNG, SDX55_SLAVE_CRYPTO_0_CFG, SDX55_SLAVE_TCU, SDX55_SLAVE_CLK_CTL, SDX55_SLAVE_IMEM_CFG);
+ DEFINE_QNODE(xm_sdc1, SDX55_MASTER_SDCC_1, 1, 8, SDX55_SLAVE_AOSS, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_ANOC_SNOC, SDX55_SLAVE_AOP, SDX55_SLAVE_AUDIO);
+ DEFINE_QNODE(xm_usb3, SDX55_MASTER_USB3, 1, 8, SDX55_SLAVE_ANOC_SNOC);
+-DEFINE_QNODE(ipa_core_slave, SDX55_SLAVE_IPA_CORE, 1, 8);
+ DEFINE_QNODE(ebi, SDX55_SLAVE_EBI_CH0, 1, 4);
+ DEFINE_QNODE(qns_llcc, SDX55_SLAVE_LLCC, 1, 16, SDX55_SLAVE_EBI_CH0);
+ DEFINE_QNODE(qns_memnoc_snoc, SDX55_SLAVE_MEM_NOC_SNOC, 1, 8, SDX55_MASTER_MEM_NOC_SNOC);
+@@ -82,7 +80,6 @@ DEFINE_QNODE(xs_sys_tcu_cfg, SDX55_SLAVE_TCU, 1, 8);
+ DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi);
+ DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc);
+ DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto);
+-DEFINE_QBCM(bcm_ip0, "IP0", false, &ipa_core_slave);
+ DEFINE_QBCM(bcm_pn0, "PN0", false, &qhm_snoc_cfg);
+ DEFINE_QBCM(bcm_sh3, "SH3", false, &xm_apps_rdwr);
+ DEFINE_QBCM(bcm_sh4, "SH4", false, &qns_memnoc_snoc, &qns_sys_pcie);
+@@ -219,22 +216,6 @@ static const struct qcom_icc_desc sdx55_system_noc = {
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+ };
+
+-static struct qcom_icc_bcm *ipa_virt_bcms[] = {
+- &bcm_ip0,
+-};
+-
+-static struct qcom_icc_node *ipa_virt_nodes[] = {
+- [MASTER_IPA_CORE] = &ipa_core_master,
+- [SLAVE_IPA_CORE] = &ipa_core_slave,
+-};
+-
+-static const struct qcom_icc_desc sdx55_ipa_virt = {
+- .nodes = ipa_virt_nodes,
+- .num_nodes = ARRAY_SIZE(ipa_virt_nodes),
+- .bcms = ipa_virt_bcms,
+- .num_bcms = ARRAY_SIZE(ipa_virt_bcms),
+-};
+-
+ static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sdx55-mc-virt",
+ .data = &sdx55_mc_virt},
+@@ -242,8 +223,6 @@ static const struct of_device_id qnoc_of_match[] = {
+ .data = &sdx55_mem_noc},
+ { .compatible = "qcom,sdx55-system-noc",
+ .data = &sdx55_system_noc},
+- { .compatible = "qcom,sdx55-ipa-virt",
+- .data = &sdx55_ipa_virt},
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, qnoc_of_match);
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 416815a525d67..bb95edf74415b 100644
--- a/drivers/iommu/amd/amd_iommu.h
@@ -59392,7 +90026,7 @@ index a9e568276c99f..a45c5536d2506 100644
out:
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
-index fdfa39ec2a4d4..ad69eeb5ac5ba 100644
+index fdfa39ec2a4d4..baba4571c8152 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -70,6 +70,8 @@
@@ -59414,6 +90048,119 @@ index fdfa39ec2a4d4..ad69eeb5ac5ba 100644
/* clear any pending errors before the interrupt is unmasked */
writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR);
+@@ -752,6 +757,7 @@ static const struct iommu_ops apple_dart_iommu_ops = {
+ .of_xlate = apple_dart_of_xlate,
+ .def_domain_type = apple_dart_def_domain_type,
+ .pgsize_bitmap = -1UL, /* Restricted during dart probe */
++ .owner = THIS_MODULE,
+ };
+
+ static irqreturn_t apple_dart_irq(int irq, void *dev)
+@@ -827,16 +833,15 @@ static int apple_dart_probe(struct platform_device *pdev)
+ dart->dev = dev;
+ spin_lock_init(&dart->lock);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ dart->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
++ if (IS_ERR(dart->regs))
++ return PTR_ERR(dart->regs);
++
+ if (resource_size(res) < 0x4000) {
+ dev_err(dev, "MMIO region too small (%pr)\n", res);
+ return -EINVAL;
+ }
+
+- dart->regs = devm_ioremap_resource(dev, res);
+- if (IS_ERR(dart->regs))
+- return PTR_ERR(dart->regs);
+-
+ dart->irq = platform_get_irq(pdev, 0);
+ if (dart->irq < 0)
+ return -ENODEV;
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+index ee66d1f4cb81e..f763c1430d152 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+@@ -183,7 +183,14 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
+ {
+ struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
+ struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
+- size_t size = end - start + 1;
++ size_t size;
++
++ /*
++ * The mm_types defines vm_end as the first byte after the end address,
++ * different from IOMMU subsystem using the last address of an address
++ * range. So do a simple translation here by calculating size correctly.
++ */
++ size = end - start;
+
+ if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM))
+ arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+index a388e318f86e0..430315135cff7 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+@@ -1552,6 +1552,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
+ dev_info(smmu->dev, "\t0x%016llx\n",
+ (unsigned long long)evt[i]);
+
++ cond_resched();
+ }
+
+ /*
+diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+index 01e9b50b10a18..87bf522b9d2ee 100644
+--- a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
++++ b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+@@ -258,6 +258,34 @@ static void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct devi
+ dev_name(dev), err);
+ }
+
++static int nvidia_smmu_init_context(struct arm_smmu_domain *smmu_domain,
++ struct io_pgtable_cfg *pgtbl_cfg,
++ struct device *dev)
++{
++ struct arm_smmu_device *smmu = smmu_domain->smmu;
++ const struct device_node *np = smmu->dev->of_node;
++
++ /*
++ * Tegra194 and Tegra234 SoCs have the erratum that causes walk cache
++ * entries to not be invalidated correctly. The problem is that the walk
++ * cache index generated for IOVA is not same across translation and
++ * invalidation requests. This is leading to page faults when PMD entry
++ * is released during unmap and populated with new PTE table during
++ * subsequent map request. Disabling large page mappings avoids the
++ * release of PMD entry and avoid translations seeing stale PMD entry in
++ * walk cache.
++ * Fix this by limiting the page mappings to PAGE_SIZE on Tegra194 and
++ * Tegra234.
++ */
++ if (of_device_is_compatible(np, "nvidia,tegra234-smmu") ||
++ of_device_is_compatible(np, "nvidia,tegra194-smmu")) {
++ smmu->pgsize_bitmap = PAGE_SIZE;
++ pgtbl_cfg->pgsize_bitmap = smmu->pgsize_bitmap;
++ }
++
++ return 0;
++}
++
+ static const struct arm_smmu_impl nvidia_smmu_impl = {
+ .read_reg = nvidia_smmu_read_reg,
+ .write_reg = nvidia_smmu_write_reg,
+@@ -268,10 +296,12 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
+ .global_fault = nvidia_smmu_global_fault,
+ .context_fault = nvidia_smmu_context_fault,
+ .probe_finalize = nvidia_smmu_probe_finalize,
++ .init_context = nvidia_smmu_init_context,
+ };
+
+ static const struct arm_smmu_impl nvidia_smmu_single_impl = {
+ .probe_finalize = nvidia_smmu_probe_finalize,
++ .init_context = nvidia_smmu_init_context,
+ };
+
+ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 55690af1b25d0..c998960495b4e 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -59428,20 +90175,117 @@ index 55690af1b25d0..c998960495b4e 100644
}
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
-index 896bea04c347e..2d60216440009 100644
+index 896bea04c347e..276b6fcc80ad9 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
-@@ -593,6 +593,9 @@ static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys,
- memset(padding_start, 0, padding_size);
- }
+@@ -317,6 +317,11 @@ static bool dev_is_untrusted(struct device *dev)
+ return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
+ }
-+ if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+ arch_sync_dma_for_device(phys, org_size, dir);
++static bool dev_use_swiotlb(struct device *dev)
++{
++ return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
++}
+
- iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask);
- if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys))
- swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs);
-@@ -828,17 +831,13 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev,
+ /* sysfs updates are serialised by the mutex of the group owning @domain */
+ int iommu_dma_init_fq(struct iommu_domain *domain)
+ {
+@@ -510,23 +515,6 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
+ iommu_dma_free_iova(cookie, dma_addr, size, &iotlb_gather);
+ }
+
+-static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
+- size_t size, enum dma_data_direction dir,
+- unsigned long attrs)
+-{
+- struct iommu_domain *domain = iommu_get_dma_domain(dev);
+- phys_addr_t phys;
+-
+- phys = iommu_iova_to_phys(domain, dma_addr);
+- if (WARN_ON(!phys))
+- return;
+-
+- __iommu_dma_unmap(dev, dma_addr, size);
+-
+- if (unlikely(is_swiotlb_buffer(dev, phys)))
+- swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
+-}
+-
+ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+ size_t size, int prot, u64 dma_mask)
+ {
+@@ -553,52 +541,6 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+ return iova + iova_off;
+ }
+
+-static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys,
+- size_t org_size, dma_addr_t dma_mask, bool coherent,
+- enum dma_data_direction dir, unsigned long attrs)
+-{
+- int prot = dma_info_to_prot(dir, coherent, attrs);
+- struct iommu_domain *domain = iommu_get_dma_domain(dev);
+- struct iommu_dma_cookie *cookie = domain->iova_cookie;
+- struct iova_domain *iovad = &cookie->iovad;
+- size_t aligned_size = org_size;
+- void *padding_start;
+- size_t padding_size;
+- dma_addr_t iova;
+-
+- /*
+- * If both the physical buffer start address and size are
+- * page aligned, we don't need to use a bounce page.
+- */
+- if (IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev) &&
+- iova_offset(iovad, phys | org_size)) {
+- aligned_size = iova_align(iovad, org_size);
+- phys = swiotlb_tbl_map_single(dev, phys, org_size,
+- aligned_size, dir, attrs);
+-
+- if (phys == DMA_MAPPING_ERROR)
+- return DMA_MAPPING_ERROR;
+-
+- /* Cleanup the padding area. */
+- padding_start = phys_to_virt(phys);
+- padding_size = aligned_size;
+-
+- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+- (dir == DMA_TO_DEVICE ||
+- dir == DMA_BIDIRECTIONAL)) {
+- padding_start += org_size;
+- padding_size -= org_size;
+- }
+-
+- memset(padding_start, 0, padding_size);
+- }
+-
+- iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask);
+- if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys))
+- swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs);
+- return iova;
+-}
+-
+ static void __iommu_dma_free_pages(struct page **pages, int count)
+ {
+ while (count--)
+@@ -794,7 +736,7 @@ static void iommu_dma_sync_single_for_cpu(struct device *dev,
+ {
+ phys_addr_t phys;
+
+- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
++ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev))
+ return;
+
+ phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
+@@ -810,7 +752,7 @@ static void iommu_dma_sync_single_for_device(struct device *dev,
+ {
+ phys_addr_t phys;
+
+- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev))
++ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev))
+ return;
+
+ phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
+@@ -828,17 +770,13 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sg;
int i;
@@ -59450,7 +90294,7 @@ index 896bea04c347e..2d60216440009 100644
-
- for_each_sg(sgl, sg, nelems, i) {
- if (!dev_is_dma_coherent(dev))
-+ if (dev_is_untrusted(dev))
++ if (dev_use_swiotlb(dev))
+ for_each_sg(sgl, sg, nelems, i)
+ iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg),
+ sg->length, dir);
@@ -59465,7 +90309,7 @@ index 896bea04c347e..2d60216440009 100644
}
static void iommu_dma_sync_sg_for_device(struct device *dev,
-@@ -848,17 +847,14 @@ static void iommu_dma_sync_sg_for_device(struct device *dev,
+@@ -848,17 +786,14 @@ static void iommu_dma_sync_sg_for_device(struct device *dev,
struct scatterlist *sg;
int i;
@@ -59478,7 +90322,7 @@ index 896bea04c347e..2d60216440009 100644
- sg->length, dir);
-
- if (!dev_is_dma_coherent(dev))
-+ if (dev_is_untrusted(dev))
++ if (dev_use_swiotlb(dev))
+ for_each_sg(sgl, sg, nelems, i)
+ iommu_dma_sync_single_for_device(dev,
+ sg_dma_address(sg),
@@ -59490,23 +90334,104 @@ index 896bea04c347e..2d60216440009 100644
}
static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
-@@ -867,14 +863,9 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+@@ -867,22 +802,66 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
{
phys_addr_t phys = page_to_phys(page) + offset;
bool coherent = dev_is_dma_coherent(dev);
- dma_addr_t dma_handle;
++ int prot = dma_info_to_prot(dir, coherent, attrs);
++ struct iommu_domain *domain = iommu_get_dma_domain(dev);
++ struct iommu_dma_cookie *cookie = domain->iova_cookie;
++ struct iova_domain *iovad = &cookie->iovad;
++ dma_addr_t iova, dma_mask = dma_get_mask(dev);
++
++ /*
++ * If both the physical buffer start address and size are
++ * page aligned, we don't need to use a bounce page.
++ */
++ if (dev_use_swiotlb(dev) && iova_offset(iovad, phys | size)) {
++ void *padding_start;
++ size_t padding_size, aligned_size;
++
++ aligned_size = iova_align(iovad, size);
++ phys = swiotlb_tbl_map_single(dev, phys, size, aligned_size,
++ iova_mask(iovad), dir, attrs);
++
++ if (phys == DMA_MAPPING_ERROR)
++ return DMA_MAPPING_ERROR;
- dma_handle = __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev),
-+ return __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev),
- coherent, dir, attrs);
+- coherent, dir, attrs);
- if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
- dma_handle != DMA_MAPPING_ERROR)
-- arch_sync_dma_for_device(phys, size, dir);
++ /* Cleanup the padding area. */
++ padding_start = phys_to_virt(phys);
++ padding_size = aligned_size;
++
++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
++ (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) {
++ padding_start += size;
++ padding_size -= size;
++ }
++
++ memset(padding_start, 0, padding_size);
++ }
++
++ if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+ arch_sync_dma_for_device(phys, size, dir);
- return dma_handle;
++
++ iova = __iommu_dma_map(dev, phys, size, prot, dma_mask);
++ if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys))
++ swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
++ return iova;
}
static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
-@@ -1016,15 +1007,16 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
+ {
+- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+- iommu_dma_sync_single_for_cpu(dev, dma_handle, size, dir);
+- __iommu_dma_unmap_swiotlb(dev, dma_handle, size, dir, attrs);
++ struct iommu_domain *domain = iommu_get_dma_domain(dev);
++ phys_addr_t phys;
++
++ phys = iommu_iova_to_phys(domain, dma_handle);
++ if (WARN_ON(!phys))
++ return;
++
++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && !dev_is_dma_coherent(dev))
++ arch_sync_dma_for_cpu(phys, size, dir);
++
++ __iommu_dma_unmap(dev, dma_handle, size);
++
++ if (unlikely(is_swiotlb_buffer(dev, phys)))
++ swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
+ }
+
+ /*
+@@ -967,7 +946,7 @@ static void iommu_dma_unmap_sg_swiotlb(struct device *dev, struct scatterlist *s
+ int i;
+
+ for_each_sg(sg, s, nents, i)
+- __iommu_dma_unmap_swiotlb(dev, sg_dma_address(s),
++ iommu_dma_unmap_page(dev, sg_dma_address(s),
+ sg_dma_len(s), dir, attrs);
+ }
+
+@@ -978,9 +957,8 @@ static int iommu_dma_map_sg_swiotlb(struct device *dev, struct scatterlist *sg,
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+- sg_dma_address(s) = __iommu_dma_map_swiotlb(dev, sg_phys(s),
+- s->length, dma_get_mask(dev),
+- dev_is_dma_coherent(dev), dir, attrs);
++ sg_dma_address(s) = iommu_dma_map_page(dev, sg_page(s),
++ s->offset, s->length, dir, attrs);
+ if (sg_dma_address(s) == DMA_MAPPING_ERROR)
+ goto out_unmap;
+ sg_dma_len(s) = s->length;
+@@ -1016,15 +994,16 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
if (static_branch_unlikely(&iommu_deferred_attach_enabled)) {
ret = iommu_deferred_attach(dev, domain);
@@ -59515,20 +90440,39 @@ index 896bea04c347e..2d60216440009 100644
+ goto out;
}
++ if (dev_use_swiotlb(dev))
++ return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs);
++
+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+ iommu_dma_sync_sg_for_device(dev, sg, nents, dir);
+
+- if (dev_is_untrusted(dev))
+- return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs);
+-
+ /*
+ * Work out how much IOVA space we need, and align the segments to
+ * IOVA granules for the IOMMU driver to handle. With some clever
+@@ -1097,14 +1076,14 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ struct scatterlist *tmp;
+ int i;
+
- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-- iommu_dma_sync_sg_for_device(dev, sg, nents, dir);
+- iommu_dma_sync_sg_for_cpu(dev, sg, nents, dir);
-
- if (dev_is_untrusted(dev))
- return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs);
+- if (dev_is_untrusted(dev)) {
++ if (dev_use_swiotlb(dev)) {
+ iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs);
+ return;
+ }
+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+ iommu_dma_sync_sg_for_device(dev, sg, nents, dir);
++ iommu_dma_sync_sg_for_cpu(dev, sg, nents, dir);
+
/*
- * Work out how much IOVA space we need, and align the segments to
- * IOVA granules for the IOMMU driver to handle. With some clever
+ * The scatterlist segments are mapped into a single
+ * contiguous IOVA allocation, so this is incredibly easy.
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
-index d75f59ae28e6e..0b3076144beb7 100644
+index d75f59ae28e6e..91a5c75966f32 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -412,6 +412,7 @@ static int __init intel_iommu_setup(char *str)
@@ -59581,7 +90525,50 @@ index d75f59ae28e6e..0b3076144beb7 100644
} while (!first_pte_in_page(++pte) && pfn <= last_pfn);
if (first_pte)
-@@ -2649,7 +2651,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
+@@ -1635,7 +1637,8 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
+ unsigned long pfn, unsigned int pages,
+ int ih, int map)
+ {
+- unsigned int mask = ilog2(__roundup_pow_of_two(pages));
++ unsigned int aligned_pages = __roundup_pow_of_two(pages);
++ unsigned int mask = ilog2(aligned_pages);
+ uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
+ u16 did = domain->iommu_did[iommu->seq_id];
+
+@@ -1647,10 +1650,30 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
+ if (domain_use_first_level(domain)) {
+ domain_flush_piotlb(iommu, domain, addr, pages, ih);
+ } else {
++ unsigned long bitmask = aligned_pages - 1;
++
++ /*
++ * PSI masks the low order bits of the base address. If the
++ * address isn't aligned to the mask, then compute a mask value
++ * needed to ensure the target range is flushed.
++ */
++ if (unlikely(bitmask & pfn)) {
++ unsigned long end_pfn = pfn + pages - 1, shared_bits;
++
++ /*
++ * Since end_pfn <= pfn + bitmask, the only way bits
++ * higher than bitmask can differ in pfn and end_pfn is
++ * by carrying. This means after masking out bitmask,
++ * high bits starting with the first set bit in
++ * shared_bits are all equal in both pfn and end_pfn.
++ */
++ shared_bits = ~(pfn ^ end_pfn) & ~bitmask;
++ mask = shared_bits ? __ffs(shared_bits) : BITS_PER_LONG;
++ }
++
+ /*
+ * Fallback to domain selective flush if no PSI support or
+- * the size is too big. PSI requires page size to be 2 ^ x,
+- * and the base address is naturally aligned to the size.
++ * the size is too big.
+ */
+ if (!cap_pgsel_inv(iommu->cap) ||
+ mask > cap_max_amask_val(iommu->cap))
+@@ -2649,7 +2672,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
spin_unlock_irqrestore(&device_domain_lock, flags);
/* PASID table is mandatory for a PCI device in scalable mode. */
@@ -59629,6 +90616,21 @@ index f912fe45bea2c..a673195978843 100644
out_free_bitmap:
bitmap_free(bitmap);
out_free_pages:
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index 0c228787704f3..3a9468b1d2c3c 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -978,6 +978,10 @@ bad_req:
+ goto bad_req;
+ }
+
++ /* Drop Stop Marker message. No need for a response. */
++ if (unlikely(req->lpig && !req->rd_req && !req->wr_req))
++ goto prq_advance;
++
+ if (!svm || svm->pasid != req->pasid) {
+ /*
+ * It can't go away, because the driver is not permitted
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index bfb6acb651e5f..be066c1503d37 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
@@ -59732,7 +90734,7 @@ index 3303d707bab4b..7f409e9eea4b7 100644
if (ops->probe_finalize)
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
-index 9e8bc802ac053..920fcc27c9a1e 100644
+index 9e8bc802ac053..cae5a73ff518c 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -83,8 +83,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
@@ -59745,8 +90747,37 @@ index 9e8bc802ac053..920fcc27c9a1e 100644
fq_destroy_all_entries(iovad);
+@@ -155,10 +154,11 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
+ cached_iova = to_iova(iovad->cached32_node);
+ if (free == cached_iova ||
+ (free->pfn_hi < iovad->dma_32bit_pfn &&
+- free->pfn_lo >= cached_iova->pfn_lo)) {
++ free->pfn_lo >= cached_iova->pfn_lo))
+ iovad->cached32_node = rb_next(&free->node);
++
++ if (free->pfn_lo < iovad->dma_32bit_pfn)
+ iovad->max32_alloc_size = iovad->dma_32bit_pfn;
+- }
+
+ cached_iova = to_iova(iovad->cached_node);
+ if (free->pfn_lo >= cached_iova->pfn_lo)
+diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
+index d38ff29a76e8f..96708cd2757f7 100644
+--- a/drivers/iommu/ipmmu-vmsa.c
++++ b/drivers/iommu/ipmmu-vmsa.c
+@@ -982,7 +982,9 @@ static int ipmmu_probe(struct platform_device *pdev)
+ bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+ mmu->features = of_device_get_match_data(&pdev->dev);
+ memset(mmu->utlb_ctx, IPMMU_CTX_INVALID, mmu->features->num_utlbs);
+- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
++ if (ret)
++ return ret;
+
+ /* Map I/O memory and request IRQ. */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
-index d837adfd1da55..25b834104790c 100644
+index d837adfd1da55..5971a11686662 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -550,7 +550,9 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -59760,6 +90791,157 @@ index d837adfd1da55..25b834104790c 100644
pa &= ~BIT_ULL(32);
return pa;
+@@ -560,22 +562,52 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
+ {
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct mtk_iommu_data *data;
++ struct device_link *link;
++ struct device *larbdev;
++ unsigned int larbid, larbidx, i;
+
+ if (!fwspec || fwspec->ops != &mtk_iommu_ops)
+ return ERR_PTR(-ENODEV); /* Not a iommu client device */
+
+ data = dev_iommu_priv_get(dev);
+
++ /*
++ * Link the consumer device with the smi-larb device(supplier).
++ * The device that connects with each a larb is a independent HW.
++ * All the ports in each a device should be in the same larbs.
++ */
++ larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
++ for (i = 1; i < fwspec->num_ids; i++) {
++ larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]);
++ if (larbid != larbidx) {
++ dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
++ larbid, larbidx);
++ return ERR_PTR(-EINVAL);
++ }
++ }
++ larbdev = data->larb_imu[larbid].dev;
++ link = device_link_add(dev, larbdev,
++ DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
++ if (!link)
++ dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
+ return &data->iommu;
+ }
+
+ static void mtk_iommu_release_device(struct device *dev)
+ {
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
++ struct mtk_iommu_data *data;
++ struct device *larbdev;
++ unsigned int larbid;
+
+ if (!fwspec || fwspec->ops != &mtk_iommu_ops)
+ return;
+
++ data = dev_iommu_priv_get(dev);
++ larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
++ larbdev = data->larb_imu[larbid].dev;
++ device_link_remove(dev, larbdev);
++
+ iommu_fwspec_free(dev);
+ }
+
+@@ -846,7 +878,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
+ plarbdev = of_find_device_by_node(larbnode);
+ if (!plarbdev) {
+ of_node_put(larbnode);
+- return -EPROBE_DEFER;
++ return -ENODEV;
+ }
+ data->larb_imu[id].dev = &plarbdev->dev;
+
+diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
+index be22fcf988cee..bc7ee90b9373d 100644
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -423,7 +423,18 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct of_phandle_args iommu_spec;
+ struct mtk_iommu_data *data;
+- int err, idx = 0;
++ int err, idx = 0, larbid, larbidx;
++ struct device_link *link;
++ struct device *larbdev;
++
++ /*
++ * In the deferred case, free the existed fwspec.
++ * Always initialize the fwspec internally.
++ */
++ if (fwspec) {
++ iommu_fwspec_free(dev);
++ fwspec = dev_iommu_fwspec_get(dev);
++ }
+
+ while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+ "#iommu-cells",
+@@ -444,6 +455,23 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
+
+ data = dev_iommu_priv_get(dev);
+
++ /* Link the consumer device with the smi-larb device(supplier) */
++ larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
++ for (idx = 1; idx < fwspec->num_ids; idx++) {
++ larbidx = mt2701_m4u_to_larb(fwspec->ids[idx]);
++ if (larbid != larbidx) {
++ dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
++ larbid, larbidx);
++ return ERR_PTR(-EINVAL);
++ }
++ }
++
++ larbdev = data->larb_imu[larbid].dev;
++ link = device_link_add(dev, larbdev,
++ DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
++ if (!link)
++ dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
++
+ return &data->iommu;
+ }
+
+@@ -464,10 +492,18 @@ static void mtk_iommu_probe_finalize(struct device *dev)
+ static void mtk_iommu_release_device(struct device *dev)
+ {
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
++ struct mtk_iommu_data *data;
++ struct device *larbdev;
++ unsigned int larbid;
+
+ if (!fwspec || fwspec->ops != &mtk_iommu_ops)
+ return;
+
++ data = dev_iommu_priv_get(dev);
++ larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
++ larbdev = data->larb_imu[larbid].dev;
++ device_link_remove(dev, larbdev);
++
+ iommu_fwspec_free(dev);
+ }
+
+@@ -595,7 +631,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
+ plarbdev = of_find_device_by_node(larbnode);
+ if (!plarbdev) {
+ of_node_put(larbnode);
+- return -EPROBE_DEFER;
++ return -ENODEV;
+ }
+ data->larb_imu[i].dev = &plarbdev->dev;
+
+diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
+index 91749654fd490..be60f6f3a265d 100644
+--- a/drivers/iommu/omap-iommu.c
++++ b/drivers/iommu/omap-iommu.c
+@@ -1661,7 +1661,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev)
+ num_iommus = of_property_count_elems_of_size(dev->of_node, "iommus",
+ sizeof(phandle));
+ if (num_iommus < 0)
+- return 0;
++ return ERR_PTR(-ENODEV);
+
+ arch_data = kcalloc(num_iommus + 1, sizeof(*arch_data), GFP_KERNEL);
+ if (!arch_data)
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5cb260820eda6..7f23ad61c094f 100644
--- a/drivers/iommu/rockchip-iommu.c
@@ -59863,7 +91045,7 @@ index e3483789f4df3..1bd0621c4ce2a 100644
spurious_interrupt();
}
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
-index eb0882d153666..0cb584d9815b9 100644
+index eb0882d153666..fc1bfffc468f3 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -742,7 +742,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its,
@@ -59875,10 +91057,89 @@ index eb0882d153666..0cb584d9815b9 100644
}
static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
+@@ -3007,18 +3007,12 @@ static int __init allocate_lpi_tables(void)
+ return 0;
+ }
+
+-static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
++static u64 read_vpend_dirty_clear(void __iomem *vlpi_base)
+ {
+ u32 count = 1000000; /* 1s! */
+ bool clean;
+ u64 val;
+
+- val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+- val &= ~GICR_VPENDBASER_Valid;
+- val &= ~clr;
+- val |= set;
+- gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+-
+ do {
+ val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+ clean = !(val & GICR_VPENDBASER_Dirty);
+@@ -3029,10 +3023,26 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
+ }
+ } while (!clean && count);
+
+- if (unlikely(val & GICR_VPENDBASER_Dirty)) {
++ if (unlikely(!clean))
+ pr_err_ratelimited("ITS virtual pending table not cleaning\n");
++
++ return val;
++}
++
++static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
++{
++ u64 val;
++
++ /* Make sure we wait until the RD is done with the initial scan */
++ val = read_vpend_dirty_clear(vlpi_base);
++ val &= ~GICR_VPENDBASER_Valid;
++ val &= ~clr;
++ val |= set;
++ gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
++
++ val = read_vpend_dirty_clear(vlpi_base);
++ if (unlikely(val & GICR_VPENDBASER_Dirty))
+ val |= GICR_VPENDBASER_PendingLast;
+- }
+
+ return val;
+ }
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
-index fd4e9a37fea67..7bbccb13b896b 100644
+index fd4e9a37fea67..1269284461dae 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
+@@ -206,11 +206,11 @@ static inline void __iomem *gic_dist_base(struct irq_data *d)
+ }
+ }
+
+-static void gic_do_wait_for_rwp(void __iomem *base)
++static void gic_do_wait_for_rwp(void __iomem *base, u32 bit)
+ {
+ u32 count = 1000000; /* 1s! */
+
+- while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
++ while (readl_relaxed(base + GICD_CTLR) & bit) {
+ count--;
+ if (!count) {
+ pr_err_ratelimited("RWP timeout, gone fishing\n");
+@@ -224,13 +224,13 @@ static void gic_do_wait_for_rwp(void __iomem *base)
+ /* Wait for completion of a distributor change */
+ static void gic_dist_wait_for_rwp(void)
+ {
+- gic_do_wait_for_rwp(gic_data.dist_base);
++ gic_do_wait_for_rwp(gic_data.dist_base, GICD_CTLR_RWP);
+ }
+
+ /* Wait for completion of a redistributor change */
+ static void gic_redist_wait_for_rwp(void)
+ {
+- gic_do_wait_for_rwp(gic_data_rdist_rd_base());
++ gic_do_wait_for_rwp(gic_data_rdist_rd_base(), GICR_CTLR_RWP);
+ }
+
+ #ifdef CONFIG_ARM64
@@ -920,6 +920,22 @@ static int __gic_update_rdist_properties(struct redist_region *region,
{
u64 typer = gic_read_typer(ptr + GICR_TYPER);
@@ -59902,8 +91163,38 @@ index fd4e9a37fea67..7bbccb13b896b 100644
gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
+@@ -1450,6 +1466,12 @@ static int gic_irq_domain_translate(struct irq_domain *d,
+ if(fwspec->param_count != 2)
+ return -EINVAL;
+
++ if (fwspec->param[0] < 16) {
++ pr_err(FW_BUG "Illegal GSI%d translation request\n",
++ fwspec->param[0]);
++ return -EINVAL;
++ }
++
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1];
+
+diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
+index 5f22c9d65e578..99077f30f6999 100644
+--- a/drivers/irqchip/irq-gic.c
++++ b/drivers/irqchip/irq-gic.c
+@@ -1085,6 +1085,12 @@ static int gic_irq_domain_translate(struct irq_domain *d,
+ if(fwspec->param_count != 2)
+ return -EINVAL;
+
++ if (fwspec->param[0] < 16) {
++ pr_err(FW_BUG "Illegal GSI%d translation request\n",
++ fwspec->param[0]);
++ return -EINVAL;
++ }
++
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1];
+
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
-index b31c4cff4d3a5..599bb6fc5f0a2 100644
+index b31c4cff4d3a5..47b3b165479e8 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -26,7 +26,7 @@
@@ -59915,6 +91206,22 @@ index b31c4cff4d3a5..599bb6fc5f0a2 100644
#define NVIC_MAX_BANKS 16
/*
+@@ -92,6 +92,7 @@ static int __init nvic_of_init(struct device_node *node,
+
+ if (!nvic_irq_domain) {
+ pr_warn("Failed to allocate irq domain\n");
++ iounmap(nvic_base);
+ return -ENOMEM;
+ }
+
+@@ -101,6 +102,7 @@ static int __init nvic_of_init(struct device_node *node,
+ if (ret) {
+ pr_warn("Failed to allocate irq chips\n");
+ irq_domain_remove(nvic_irq_domain);
++ iounmap(nvic_base);
+ return ret;
+ }
+
diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index fd9f275592d29..50a56820c99bc 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
@@ -60004,6 +91311,48 @@ index cf74cfa820453..09cc98266d30f 100644
IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
+IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */
+diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
+index 173e6520e06ec..c0b457f26ec41 100644
+--- a/drivers/irqchip/qcom-pdc.c
++++ b/drivers/irqchip/qcom-pdc.c
+@@ -56,17 +56,18 @@ static u32 pdc_reg_read(int reg, u32 i)
+ static void pdc_enable_intr(struct irq_data *d, bool on)
+ {
+ int pin_out = d->hwirq;
++ unsigned long flags;
+ u32 index, mask;
+ u32 enable;
+
+ index = pin_out / 32;
+ mask = pin_out % 32;
+
+- raw_spin_lock(&pdc_lock);
++ raw_spin_lock_irqsave(&pdc_lock, flags);
+ enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
+ enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask);
+ pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
+- raw_spin_unlock(&pdc_lock);
++ raw_spin_unlock_irqrestore(&pdc_lock, flags);
+ }
+
+ static void qcom_pdc_gic_disable(struct irq_data *d)
+diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
+index bd087cca1c1d2..af17459c1a5c0 100644
+--- a/drivers/isdn/hardware/mISDN/hfcpci.c
++++ b/drivers/isdn/hardware/mISDN/hfcpci.c
+@@ -2005,7 +2005,11 @@ setup_hw(struct hfc_pci *hc)
+ }
+ /* Allocate memory for FIFOS */
+ /* the memory needs to be on a 32k boundary within the first 4G */
+- dma_set_mask(&hc->pdev->dev, 0xFFFF8000);
++ if (dma_set_mask(&hc->pdev->dev, 0xFFFF8000)) {
++ printk(KERN_WARNING
++ "HFC-PCI: No usable DMA configuration!\n");
++ return -EIO;
++ }
+ buffer = dma_alloc_coherent(&hc->pdev->dev, 0x8000, &hc->hw.dmahandle,
+ GFP_KERNEL);
+ /* We silently assume the address is okay if nonzero */
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index 55891e4204460..a41b4b2645941 100644
--- a/drivers/isdn/mISDN/core.c
@@ -60050,6 +91399,32 @@ index 23b44d3033279..42599f49c189d 100644
extern int Isdnl2_Init(u_int *);
extern void Isdnl2_cleanup(void);
+diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
+index e11ca6bbc7f41..c3b2c99b5cd5c 100644
+--- a/drivers/isdn/mISDN/dsp_pipeline.c
++++ b/drivers/isdn/mISDN/dsp_pipeline.c
+@@ -192,7 +192,7 @@ void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
+ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
+ {
+ int found = 0;
+- char *dup, *tok, *name, *args;
++ char *dup, *next, *tok, *name, *args;
+ struct dsp_element_entry *entry, *n;
+ struct dsp_pipeline_entry *pipeline_entry;
+ struct mISDN_dsp_element *elem;
+@@ -203,10 +203,10 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
+ if (!list_empty(&pipeline->list))
+ _dsp_pipeline_destroy(pipeline);
+
+- dup = kstrdup(cfg, GFP_ATOMIC);
++ dup = next = kstrdup(cfg, GFP_ATOMIC);
+ if (!dup)
+ return 0;
+- while ((tok = strsep(&dup, "|"))) {
++ while ((tok = strsep(&next, "|"))) {
+ if (!strlen(tok))
+ continue;
+ name = strsep(&tok, "(");
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index 98a3bc6c17009..7b31c25a550e3 100644
--- a/drivers/isdn/mISDN/layer1.c
@@ -60094,6 +91469,60 @@ index d1657c46ee2f8..9fdfc1b9a1a0c 100644
if (IS_ERR(pdata->enable_gpiod))
return ERR_CAST(pdata->enable_gpiod);
+diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
+index 0ce75c6b36b65..850d4004c50e0 100644
+--- a/drivers/mailbox/imx-mailbox.c
++++ b/drivers/mailbox/imx-mailbox.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/suspend.h>
+ #include <linux/slab.h>
+
+ #define IMX_MU_CHANS 16
+@@ -67,6 +68,7 @@ struct imx_mu_priv {
+ const struct imx_mu_dcfg *dcfg;
+ struct clk *clk;
+ int irq;
++ bool suspend;
+
+ u32 xcr[4];
+
+@@ -307,6 +309,9 @@ static irqreturn_t imx_mu_isr(int irq, void *p)
+ return IRQ_NONE;
+ }
+
++ if (priv->suspend)
++ pm_system_wakeup();
++
+ return IRQ_HANDLED;
+ }
+
+@@ -652,6 +657,8 @@ static int __maybe_unused imx_mu_suspend_noirq(struct device *dev)
+ priv->xcr[i] = imx_mu_read(priv, priv->dcfg->xCR[i]);
+ }
+
++ priv->suspend = true;
++
+ return 0;
+ }
+
+@@ -668,11 +675,13 @@ static int __maybe_unused imx_mu_resume_noirq(struct device *dev)
+ * send failed, may lead to system freeze. This issue
+ * is observed by testing freeze mode suspend.
+ */
+- if (!imx_mu_read(priv, priv->dcfg->xCR[0]) && !priv->clk) {
++ if (!priv->clk && !imx_mu_read(priv, priv->dcfg->xCR[0])) {
+ for (i = 0; i < IMX_MU_xCR_MAX; i++)
+ imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]);
+ }
+
++ priv->suspend = false;
++
+ return 0;
+ }
+
diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c
index 0d6e2231a2c75..4e34854d12389 100644
--- a/drivers/mailbox/mailbox-mpfs.c
@@ -60153,8 +91582,24 @@ index 64175a893312e..3583c2aad0edc 100644
};
static const struct gce_plat gce_plat_v6 = {
+diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
+index acd0675da681e..78f7265039c66 100644
+--- a/drivers/mailbox/tegra-hsp.c
++++ b/drivers/mailbox/tegra-hsp.c
+@@ -412,6 +412,11 @@ static int tegra_hsp_mailbox_flush(struct mbox_chan *chan,
+ value = tegra_hsp_channel_readl(ch, HSP_SM_SHRD_MBOX);
+ if ((value & HSP_SM_SHRD_MBOX_FULL) == 0) {
+ mbox_chan_txdone(chan, 0);
++
++ /* Wait until channel is empty */
++ if (chan->active_req != NULL)
++ continue;
++
+ return 0;
+ }
+
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
-index 0595559de174a..183a58c893774 100644
+index 0595559de174a..8eecc9df319b5 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b)
@@ -60166,6 +91611,20 @@ index 0595559de174a..183a58c893774 100644
addr += PAGE_SIZE;
}
+@@ -2060,9 +2060,11 @@ int bch_btree_check(struct cache_set *c)
+ }
+ }
+
++ /*
++ * Must wait for all threads to stop.
++ */
+ wait_event_interruptible(check_state->wait,
+- atomic_read(&check_state->started) == 0 ||
+- test_bit(CACHE_SET_IO_DISABLE, &c->flags));
++ atomic_read(&check_state->started) == 0);
+
+ for (i = 0; i < check_state->total_threads; i++) {
+ if (check_state->infos[i].result) {
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index f2874c77ff797..3f72c0f40613d 100644
--- a/drivers/md/bcache/super.c
@@ -60181,29 +91640,397 @@ index f2874c77ff797..3f72c0f40613d 100644
}
bioset_exit(&d->bio_split);
+diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
+index 8120da278161e..1c03a3b72f8aa 100644
+--- a/drivers/md/bcache/writeback.c
++++ b/drivers/md/bcache/writeback.c
+@@ -998,9 +998,11 @@ void bch_sectors_dirty_init(struct bcache_device *d)
+ }
+ }
+
++ /*
++ * Must wait for all threads to stop.
++ */
+ wait_event_interruptible(state->wait,
+- atomic_read(&state->started) == 0 ||
+- test_bit(CACHE_SET_IO_DISABLE, &c->flags));
++ atomic_read(&state->started) == 0);
+
+ out:
+ kfree(state);
+diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
+index 55dccdfbcb22e..5a7d270b32c01 100644
+--- a/drivers/md/dm-core.h
++++ b/drivers/md/dm-core.h
+@@ -65,6 +65,8 @@ struct mapped_device {
+ struct gendisk *disk;
+ struct dax_device *dax_dev;
+
++ unsigned long __percpu *pending_io;
++
+ /*
+ * A list of ios that arrived while we were suspended.
+ */
+diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
+index 916b7da16de25..154139bf7d22b 100644
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -2579,7 +2579,7 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
+
+ static int get_key_size(char **key_string)
+ {
+- return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
++ return (*key_string[0] == ':') ? -EINVAL : (int)(strlen(*key_string) >> 1);
+ }
+
+ #endif /* CONFIG_KEYS */
+diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
+index dc03b70f6e65c..e2a51c184a254 100644
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -2459,9 +2459,11 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
+ dm_integrity_io_error(ic, "invalid sector in journal", -EIO);
+ sec &= ~(sector_t)(ic->sectors_per_block - 1);
+ }
++ if (unlikely(sec >= ic->provided_data_sectors)) {
++ journal_entry_set_unused(je);
++ continue;
++ }
+ }
+- if (unlikely(sec >= ic->provided_data_sectors))
+- continue;
+ get_area_and_offset(ic, sec, &area, &offset);
+ restore_last_bytes(ic, access_journal_data(ic, i, j), je);
+ for (k = j + 1; k < ic->journal_section_entries; k++) {
+@@ -4381,6 +4383,7 @@ try_smaller_buffer:
+ }
+
+ if (ic->internal_hash) {
++ size_t recalc_tags_size;
+ ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1);
+ if (!ic->recalc_wq ) {
+ ti->error = "Cannot allocate workqueue";
+@@ -4394,8 +4397,10 @@ try_smaller_buffer:
+ r = -ENOMEM;
+ goto bad;
+ }
+- ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block,
+- ic->tag_size, GFP_KERNEL);
++ recalc_tags_size = (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size;
++ if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size)
++ recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size;
++ ic->recalc_tags = kvmalloc(recalc_tags_size, GFP_KERNEL);
+ if (!ic->recalc_tags) {
+ ti->error = "Cannot allocate tags for recalculating";
+ r = -ENOMEM;
+diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
+index 21fe8652b095b..901abd6dea419 100644
+--- a/drivers/md/dm-ioctl.c
++++ b/drivers/md/dm-ioctl.c
+@@ -18,6 +18,7 @@
+ #include <linux/dm-ioctl.h>
+ #include <linux/hdreg.h>
+ #include <linux/compat.h>
++#include <linux/nospec.h>
+
+ #include <linux/uaccess.h>
+ #include <linux/ima.h>
+@@ -1788,6 +1789,7 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
+ if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
+ return NULL;
+
++ cmd = array_index_nospec(cmd, ARRAY_SIZE(_ioctls));
+ *ioctl_flags = _ioctls[cmd].flags;
+ return _ioctls[cmd].fn;
+ }
+diff --git a/drivers/md/dm-ps-historical-service-time.c b/drivers/md/dm-ps-historical-service-time.c
+index 1856a1b125cc1..82f2a06153dc0 100644
+--- a/drivers/md/dm-ps-historical-service-time.c
++++ b/drivers/md/dm-ps-historical-service-time.c
+@@ -432,7 +432,7 @@ static struct dm_path *hst_select_path(struct path_selector *ps,
+ {
+ struct selector *s = ps->context;
+ struct path_info *pi = NULL, *best = NULL;
+- u64 time_now = sched_clock();
++ u64 time_now = ktime_get_ns();
+ struct dm_path *ret = NULL;
+ unsigned long flags;
+
+@@ -473,7 +473,7 @@ static int hst_start_io(struct path_selector *ps, struct dm_path *path,
+
+ static u64 path_service_time(struct path_info *pi, u64 start_time)
+ {
+- u64 sched_now = ktime_get_ns();
++ u64 now = ktime_get_ns();
+
+ /* if a previous disk request has finished after this IO was
+ * sent to the hardware, pretend the submission happened
+@@ -482,11 +482,11 @@ static u64 path_service_time(struct path_info *pi, u64 start_time)
+ if (time_after64(pi->last_finish, start_time))
+ start_time = pi->last_finish;
+
+- pi->last_finish = sched_now;
+- if (time_before64(sched_now, start_time))
++ pi->last_finish = now;
++ if (time_before64(now, start_time))
+ return 0;
+
+- return sched_now - start_time;
++ return now - start_time;
+ }
+
+ static int hst_end_io(struct path_selector *ps, struct dm_path *path,
+diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
+index a896dea9750e4..53a9b16c7b2e6 100644
+--- a/drivers/md/dm-rq.c
++++ b/drivers/md/dm-rq.c
+@@ -500,8 +500,13 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
+
+ if (unlikely(!ti)) {
+ int srcu_idx;
+- struct dm_table *map = dm_get_live_table(md, &srcu_idx);
++ struct dm_table *map;
+
++ map = dm_get_live_table(md, &srcu_idx);
++ if (unlikely(!map)) {
++ dm_put_live_table(md, srcu_idx);
++ return BLK_STS_RESOURCE;
++ }
+ ti = dm_table_find_target(map, 0);
+ dm_put_live_table(md, srcu_idx);
+ }
+diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
+index 35d368c418d03..0e039a8c0bf2e 100644
+--- a/drivers/md/dm-stats.c
++++ b/drivers/md/dm-stats.c
+@@ -195,6 +195,7 @@ void dm_stats_init(struct dm_stats *stats)
+
+ mutex_init(&stats->mutex);
+ INIT_LIST_HEAD(&stats->list);
++ stats->precise_timestamps = false;
+ stats->last = alloc_percpu(struct dm_stats_last_position);
+ for_each_possible_cpu(cpu) {
+ last = per_cpu_ptr(stats->last, cpu);
+@@ -231,6 +232,22 @@ void dm_stats_cleanup(struct dm_stats *stats)
+ mutex_destroy(&stats->mutex);
+ }
+
++static void dm_stats_recalc_precise_timestamps(struct dm_stats *stats)
++{
++ struct list_head *l;
++ struct dm_stat *tmp_s;
++ bool precise_timestamps = false;
++
++ list_for_each(l, &stats->list) {
++ tmp_s = container_of(l, struct dm_stat, list_entry);
++ if (tmp_s->stat_flags & STAT_PRECISE_TIMESTAMPS) {
++ precise_timestamps = true;
++ break;
++ }
++ }
++ stats->precise_timestamps = precise_timestamps;
++}
++
+ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
+ sector_t step, unsigned stat_flags,
+ unsigned n_histogram_entries,
+@@ -376,6 +393,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
+ }
+ ret_id = s->id;
+ list_add_tail_rcu(&s->list_entry, l);
++
++ dm_stats_recalc_precise_timestamps(stats);
++
+ mutex_unlock(&stats->mutex);
+
+ resume_callback(md);
+@@ -418,6 +438,9 @@ static int dm_stats_delete(struct dm_stats *stats, int id)
+ }
+
+ list_del_rcu(&s->list_entry);
++
++ dm_stats_recalc_precise_timestamps(stats);
++
+ mutex_unlock(&stats->mutex);
+
+ /*
+@@ -621,13 +644,14 @@ static void __dm_stat_bio(struct dm_stat *s, int bi_rw,
+
+ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
+ sector_t bi_sector, unsigned bi_sectors, bool end,
+- unsigned long duration_jiffies,
++ unsigned long start_time,
+ struct dm_stats_aux *stats_aux)
+ {
+ struct dm_stat *s;
+ sector_t end_sector;
+ struct dm_stats_last_position *last;
+ bool got_precise_time;
++ unsigned long duration_jiffies = 0;
+
+ if (unlikely(!bi_sectors))
+ return;
+@@ -647,16 +671,16 @@ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
+ ));
+ WRITE_ONCE(last->last_sector, end_sector);
+ WRITE_ONCE(last->last_rw, bi_rw);
+- }
++ } else
++ duration_jiffies = jiffies - start_time;
+
+ rcu_read_lock();
+
+ got_precise_time = false;
+ list_for_each_entry_rcu(s, &stats->list, list_entry) {
+ if (s->stat_flags & STAT_PRECISE_TIMESTAMPS && !got_precise_time) {
+- if (!end)
+- stats_aux->duration_ns = ktime_to_ns(ktime_get());
+- else
++ /* start (!end) duration_ns is set by DM core's alloc_io() */
++ if (end)
+ stats_aux->duration_ns = ktime_to_ns(ktime_get()) - stats_aux->duration_ns;
+ got_precise_time = true;
+ }
+diff --git a/drivers/md/dm-stats.h b/drivers/md/dm-stats.h
+index 2ddfae678f320..09c81a1ec057d 100644
+--- a/drivers/md/dm-stats.h
++++ b/drivers/md/dm-stats.h
+@@ -13,8 +13,7 @@ struct dm_stats {
+ struct mutex mutex;
+ struct list_head list; /* list of struct dm_stat */
+ struct dm_stats_last_position __percpu *last;
+- sector_t last_sector;
+- unsigned last_rw;
++ bool precise_timestamps;
+ };
+
+ struct dm_stats_aux {
+@@ -32,7 +31,7 @@ int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
+
+ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
+ sector_t bi_sector, unsigned bi_sectors, bool end,
+- unsigned long duration_jiffies,
++ unsigned long start_time,
+ struct dm_stats_aux *aux);
+
+ static inline bool dm_stats_used(struct dm_stats *st)
+@@ -40,4 +39,10 @@ static inline bool dm_stats_used(struct dm_stats *st)
+ return !list_empty(&st->list);
+ }
+
++static inline void dm_stats_record_start(struct dm_stats *stats, struct dm_stats_aux *aux)
++{
++ if (unlikely(stats->precise_timestamps))
++ aux->duration_ns = ktime_to_ns(ktime_get());
++}
++
+ #endif
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
-index 76d9da49fda75..5f33700d12473 100644
+index 76d9da49fda75..36449422e7e07 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
-@@ -489,7 +489,7 @@ static void start_io_acct(struct dm_io *io)
- struct mapped_device *md = io->md;
- struct bio *bio = io->orig_bio;
+@@ -484,33 +484,48 @@ u64 dm_start_time_ns_from_clone(struct bio *bio)
+ }
+ EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone);
+-static void start_io_acct(struct dm_io *io)
++static bool bio_is_flush_with_data(struct bio *bio)
+ {
+- struct mapped_device *md = io->md;
+- struct bio *bio = io->orig_bio;
+-
- io->start_time = bio_start_io_acct(bio);
-+ bio_start_io_acct_time(bio, io->start_time);
+- if (unlikely(dm_stats_used(&md->stats)))
+- dm_stats_account_io(&md->stats, bio_data_dir(bio),
+- bio->bi_iter.bi_sector, bio_sectors(bio),
+- false, 0, &io->stats_aux);
++ return ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size);
+ }
+
+-static void end_io_acct(struct mapped_device *md, struct bio *bio,
+- unsigned long start_time, struct dm_stats_aux *stats_aux)
++static void dm_io_acct(bool end, struct mapped_device *md, struct bio *bio,
++ unsigned long start_time, struct dm_stats_aux *stats_aux)
+ {
+- unsigned long duration = jiffies - start_time;
++ bool is_flush_with_data;
++ unsigned int bi_size;
+
+- bio_end_io_acct(bio, start_time);
++ /* If REQ_PREFLUSH set save any payload but do not account it */
++ is_flush_with_data = bio_is_flush_with_data(bio);
++ if (is_flush_with_data) {
++ bi_size = bio->bi_iter.bi_size;
++ bio->bi_iter.bi_size = 0;
++ }
++
++ if (!end)
++ bio_start_io_acct_time(bio, start_time);
++ else
++ bio_end_io_acct(bio, start_time);
+
if (unlikely(dm_stats_used(&md->stats)))
dm_stats_account_io(&md->stats, bio_data_dir(bio),
bio->bi_iter.bi_sector, bio_sectors(bio),
-@@ -535,7 +535,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
+- true, duration, stats_aux);
++ end, start_time, stats_aux);
++
++ /* Restore bio's payload so it does get accounted upon requeue */
++ if (is_flush_with_data)
++ bio->bi_iter.bi_size = bi_size;
++}
+
+- /* nudge anyone waiting on suspend queue */
+- if (unlikely(wq_has_sleeper(&md->wait)))
+- wake_up(&md->wait);
++static void start_io_acct(struct dm_io *io)
++{
++ dm_io_acct(false, io->md, io->orig_bio, io->start_time, &io->stats_aux);
++}
++
++static void end_io_acct(struct mapped_device *md, struct bio *bio,
++ unsigned long start_time, struct dm_stats_aux *stats_aux)
++{
++ dm_io_acct(true, md, bio, start_time, stats_aux);
+ }
+
+ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
+@@ -531,11 +546,14 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
+ io->magic = DM_IO_MAGIC;
+ io->status = 0;
+ atomic_set(&io->io_count, 1);
++ this_cpu_inc(*md->pending_io);
+ io->orig_bio = bio;
io->md = md;
spin_lock_init(&io->endio_lock);
- start_io_acct(io);
+ io->start_time = jiffies;
++
++ dm_stats_record_start(&md->stats, &io->stats_aux);
return io;
}
-@@ -1514,9 +1514,6 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
+@@ -826,11 +844,17 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error)
+ stats_aux = io->stats_aux;
+ free_io(md, io);
+ end_io_acct(md, bio, start_time, &stats_aux);
++ smp_wmb();
++ this_cpu_dec(*md->pending_io);
++
++ /* nudge anyone waiting on suspend queue */
++ if (unlikely(wq_has_sleeper(&md->wait)))
++ wake_up(&md->wait);
+
+ if (io_error == BLK_STS_DM_REQUEUE)
+ return;
+
+- if ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size) {
++ if (bio_is_flush_with_data(bio)) {
+ /*
+ * Preflush done for flush with data, reissue
+ * without REQ_PREFLUSH.
+@@ -1514,9 +1538,6 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
ci->sector = bio->bi_iter.bi_sector;
}
@@ -60213,7 +92040,7 @@ index 76d9da49fda75..5f33700d12473 100644
/*
* Entry point to split a bio into clones and submit them to the targets.
*/
-@@ -1553,23 +1550,12 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
+@@ -1553,23 +1574,12 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
GFP_NOIO, &md->queue->bio_split);
ci.io->orig_bio = b;
@@ -60238,7 +92065,54 @@ index 76d9da49fda75..5f33700d12473 100644
/* drop the extra reference count */
dm_io_dec_pending(ci.io, errno_to_blk_status(error));
-@@ -1794,8 +1780,10 @@ static struct mapped_device *alloc_dev(int minor)
+@@ -1584,15 +1594,10 @@ static blk_qc_t dm_submit_bio(struct bio *bio)
+ struct dm_table *map;
+
+ map = dm_get_live_table(md, &srcu_idx);
+- if (unlikely(!map)) {
+- DMERR_LIMIT("%s: mapping table unavailable, erroring io",
+- dm_device_name(md));
+- bio_io_error(bio);
+- goto out;
+- }
+
+- /* If suspended, queue this IO for later */
+- if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
++ /* If suspended, or map not yet available, queue this IO for later */
++ if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) ||
++ unlikely(!map)) {
+ if (bio->bi_opf & REQ_NOWAIT)
+ bio_wouldblock_error(bio);
+ else if (bio->bi_opf & REQ_RAHEAD)
+@@ -1696,6 +1701,7 @@ static void cleanup_mapped_device(struct mapped_device *md)
+ md->dax_dev = NULL;
+ }
+
++ dm_cleanup_zoned_dev(md);
+ if (md->disk) {
+ spin_lock(&_minor_lock);
+ md->disk->private_data = NULL;
+@@ -1708,6 +1714,11 @@ static void cleanup_mapped_device(struct mapped_device *md)
+ blk_cleanup_disk(md->disk);
+ }
+
++ if (md->pending_io) {
++ free_percpu(md->pending_io);
++ md->pending_io = NULL;
++ }
++
+ cleanup_srcu_struct(&md->io_barrier);
+
+ mutex_destroy(&md->suspend_lock);
+@@ -1716,7 +1727,6 @@ static void cleanup_mapped_device(struct mapped_device *md)
+ mutex_destroy(&md->swap_bios_lock);
+
+ dm_mq_cleanup_mapped_device(md);
+- dm_cleanup_zoned_dev(md);
+ }
+
+ /*
+@@ -1794,8 +1804,10 @@ static struct mapped_device *alloc_dev(int minor)
if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
md->dax_dev = alloc_dax(md, md->disk->disk_name,
&dm_dax_ops, 0);
@@ -60250,7 +92124,18 @@ index 76d9da49fda75..5f33700d12473 100644
}
format_dev_t(md->name, MKDEV(_major, minor));
-@@ -2168,7 +2156,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
+@@ -1804,6 +1816,10 @@ static struct mapped_device *alloc_dev(int minor)
+ if (!md->wq)
+ goto bad;
+
++ md->pending_io = alloc_percpu(unsigned long);
++ if (!md->pending_io)
++ goto bad;
++
+ dm_stats_init(&md->stats);
+
+ /* Populate the mapping, nobody knows we exist yet */
+@@ -2168,7 +2184,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
set_bit(DMF_FREEING, &md->flags);
spin_unlock(&_minor_lock);
@@ -60259,11 +92144,58 @@ index 76d9da49fda75..5f33700d12473 100644
/*
* Take suspend_lock so that presuspend and postsuspend methods
+@@ -2219,16 +2235,13 @@ void dm_put(struct mapped_device *md)
+ }
+ EXPORT_SYMBOL_GPL(dm_put);
+
+-static bool md_in_flight_bios(struct mapped_device *md)
++static bool dm_in_flight_bios(struct mapped_device *md)
+ {
+ int cpu;
+- struct block_device *part = dm_disk(md)->part0;
+- long sum = 0;
++ unsigned long sum = 0;
+
+- for_each_possible_cpu(cpu) {
+- sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
+- sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
+- }
++ for_each_possible_cpu(cpu)
++ sum += *per_cpu_ptr(md->pending_io, cpu);
+
+ return sum != 0;
+ }
+@@ -2241,7 +2254,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int ta
+ while (true) {
+ prepare_to_wait(&md->wait, &wait, task_state);
+
+- if (!md_in_flight_bios(md))
++ if (!dm_in_flight_bios(md))
+ break;
+
+ if (signal_pending_state(task_state, current)) {
+@@ -2253,6 +2266,8 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int ta
+ }
+ finish_wait(&md->wait, &wait);
+
++ smp_rmb();
++
+ return r;
+ }
+
diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 6c0c3d0d905aa..2d31a079be33f 100644
+index 6c0c3d0d905aa..5ce2648cbe5b5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
-@@ -2193,6 +2193,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
+@@ -51,6 +51,7 @@
+ #include <linux/hdreg.h>
+ #include <linux/proc_fs.h>
+ #include <linux/random.h>
++#include <linux/major.h>
+ #include <linux/module.h>
+ #include <linux/reboot.h>
+ #include <linux/file.h>
+@@ -2193,6 +2194,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
if (!num_sectors || num_sectors > max_sectors)
num_sectors = max_sectors;
@@ -60271,7 +92203,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
}
sb = page_address(rdev->sb_page);
sb->data_size = cpu_to_le64(num_sectors);
-@@ -2976,7 +2977,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
+@@ -2976,7 +2978,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
* -write_error - clears WriteErrorSeen
* {,-}failfast - set/clear FailFast
*/
@@ -60283,7 +92215,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
md_error(rdev->mddev, rdev);
if (test_bit(Faulty, &rdev->flags))
-@@ -2991,7 +2996,6 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
+@@ -2991,7 +2997,6 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
if (rdev->raid_disk >= 0)
err = -EBUSY;
else {
@@ -60291,7 +92223,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
err = 0;
if (mddev_is_clustered(mddev))
err = md_cluster_ops->remove_disk(mddev, rdev);
-@@ -3008,10 +3012,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
+@@ -3008,10 +3013,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
} else if (cmd_match(buf, "writemostly")) {
set_bit(WriteMostly, &rdev->flags);
mddev_create_serial_pool(rdev->mddev, rdev, false);
@@ -60304,7 +92236,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
err = 0;
} else if (cmd_match(buf, "blocked")) {
set_bit(Blocked, &rdev->flags);
-@@ -3037,9 +3043,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
+@@ -3037,9 +3044,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
err = 0;
} else if (cmd_match(buf, "failfast")) {
set_bit(FailFast, &rdev->flags);
@@ -60316,7 +92248,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
err = 0;
} else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0 &&
!test_bit(Journal, &rdev->flags)) {
-@@ -3118,6 +3126,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
+@@ -3118,6 +3127,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
clear_bit(ExternalBbl, &rdev->flags);
err = 0;
}
@@ -60325,7 +92257,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
if (!err)
sysfs_notify_dirent_safe(rdev->sysfs_state);
return err ? err : len;
-@@ -5862,13 +5872,6 @@ int md_run(struct mddev *mddev)
+@@ -5862,13 +5873,6 @@ int md_run(struct mddev *mddev)
if (err)
goto exit_bio_set;
}
@@ -60339,7 +92271,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
spin_lock(&pers_lock);
pers = find_pers(mddev->level, mddev->clevel);
-@@ -6045,9 +6048,6 @@ bitmap_abort:
+@@ -6045,9 +6049,6 @@ bitmap_abort:
module_put(pers->owner);
md_bitmap_destroy(mddev);
abort:
@@ -60349,7 +92281,7 @@ index 6c0c3d0d905aa..2d31a079be33f 100644
bioset_exit(&mddev->sync_set);
exit_bio_set:
bioset_exit(&mddev->bio_set);
-@@ -8580,6 +8580,23 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
+@@ -8580,6 +8581,23 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
}
EXPORT_SYMBOL_GPL(md_submit_discard_bio);
@@ -61584,6 +93516,45 @@ index 08feb3e8c1bf6..6157e73eef24e 100644
help
Support for the Texas Instruments THS8200 video encoder.
+diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c
+index 41f4e749a859c..2217004264e4b 100644
+--- a/drivers/media/i2c/adv7511-v4l2.c
++++ b/drivers/media/i2c/adv7511-v4l2.c
+@@ -544,7 +544,7 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_
+ buffer[3] = 0;
+ buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
+
+- if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) {
++ if (hdmi_infoframe_unpack(&frame, buffer, len + 4) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
+ return;
+ }
+diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
+index 122e1fdccd962..d688ffff7a074 100644
+--- a/drivers/media/i2c/adv7604.c
++++ b/drivers/media/i2c/adv7604.c
+@@ -2484,7 +2484,7 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
+ buffer[i + 3] = infoframe_read(sd,
+ adv76xx_cri[index].payload_addr + i);
+
+- if (hdmi_infoframe_unpack(frame, buffer, sizeof(buffer)) < 0) {
++ if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
+ adv76xx_cri[index].desc);
+ return -ENOENT;
+diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
+index 7f8acbdf0db4a..8ab4c63839b49 100644
+--- a/drivers/media/i2c/adv7842.c
++++ b/drivers/media/i2c/adv7842.c
+@@ -2593,7 +2593,7 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7842_cfg_read_
+ for (i = 0; i < len; i++)
+ buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
+
+- if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) {
++ if (hdmi_infoframe_unpack(&frame, buffer, len + 3) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
+ return;
+ }
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 81cdf37216ca7..c249507aa2dbc 100644
--- a/drivers/media/i2c/imx258.c
@@ -61704,6 +93675,280 @@ index 6eb88ef997836..3ae1b28c8351b 100644
return mt9p031_pll_enable(mt9p031);
}
+diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
+index ddbd71394db33..db5a19babe67d 100644
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -2293,7 +2293,6 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ struct ov5640_dev *sensor = to_ov5640_dev(sd);
+ const struct ov5640_mode_info *new_mode;
+ struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
+- struct v4l2_mbus_framefmt *fmt;
+ int ret;
+
+ if (format->pad != 0)
+@@ -2311,12 +2310,10 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ if (ret)
+ goto out;
+
+- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+- fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+- else
+- fmt = &sensor->fmt;
+-
+- *fmt = *mbus_fmt;
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
++ *v4l2_subdev_get_try_format(sd, sd_state, 0) = *mbus_fmt;
++ goto out;
++ }
+
+ if (new_mode != sensor->current_mode) {
+ sensor->current_mode = new_mode;
+@@ -2325,6 +2322,9 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ if (mbus_fmt->code != sensor->fmt.code)
+ sensor->pending_fmt_change = true;
+
++ /* update format even if code is unchanged, resolution might change */
++ sensor->fmt = *mbus_fmt;
++
+ __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
+ ov5640_calc_pixel_rate(sensor));
+ out:
+diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c
+index 947d437ed0efe..ef8b52dc9401d 100644
+--- a/drivers/media/i2c/ov5648.c
++++ b/drivers/media/i2c/ov5648.c
+@@ -639,7 +639,7 @@ struct ov5648_ctrls {
+ struct v4l2_ctrl *pixel_rate;
+
+ struct v4l2_ctrl_handler handler;
+-} __packed;
++};
+
+ struct ov5648_sensor {
+ struct device *dev;
+@@ -1778,8 +1778,14 @@ static int ov5648_state_configure(struct ov5648_sensor *sensor,
+
+ static int ov5648_state_init(struct ov5648_sensor *sensor)
+ {
+- return ov5648_state_configure(sensor, &ov5648_modes[0],
+- ov5648_mbus_codes[0]);
++ int ret;
++
++ mutex_lock(&sensor->mutex);
++ ret = ov5648_state_configure(sensor, &ov5648_modes[0],
++ ov5648_mbus_codes[0]);
++ mutex_unlock(&sensor->mutex);
++
++ return ret;
+ }
+
+ /* Sensor Base */
+diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
+index f67412150b16b..eb59dc8bb5929 100644
+--- a/drivers/media/i2c/ov6650.c
++++ b/drivers/media/i2c/ov6650.c
+@@ -472,9 +472,16 @@ static int ov6650_get_selection(struct v4l2_subdev *sd,
+ {
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov6650 *priv = to_ov6650(client);
++ struct v4l2_rect *rect;
+
+- if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+- return -EINVAL;
++ if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
++ /* pre-select try crop rectangle */
++ rect = &sd_state->pads->try_crop;
++
++ } else {
++ /* pre-select active crop rectangle */
++ rect = &priv->rect;
++ }
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+@@ -483,14 +490,33 @@ static int ov6650_get_selection(struct v4l2_subdev *sd,
+ sel->r.width = W_CIF;
+ sel->r.height = H_CIF;
+ return 0;
++
+ case V4L2_SEL_TGT_CROP:
+- sel->r = priv->rect;
++ /* use selected crop rectangle */
++ sel->r = *rect;
+ return 0;
++
+ default:
+ return -EINVAL;
+ }
+ }
+
++static bool is_unscaled_ok(int width, int height, struct v4l2_rect *rect)
++{
++ return width > rect->width >> 1 || height > rect->height >> 1;
++}
++
++static void ov6650_bind_align_crop_rectangle(struct v4l2_rect *rect)
++{
++ v4l_bound_align_image(&rect->width, 2, W_CIF, 1,
++ &rect->height, 2, H_CIF, 1, 0);
++ v4l_bound_align_image(&rect->left, DEF_HSTRT << 1,
++ (DEF_HSTRT << 1) + W_CIF - (__s32)rect->width, 1,
++ &rect->top, DEF_VSTRT << 1,
++ (DEF_VSTRT << 1) + H_CIF - (__s32)rect->height,
++ 1, 0);
++}
++
+ static int ov6650_set_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+@@ -499,18 +525,30 @@ static int ov6650_set_selection(struct v4l2_subdev *sd,
+ struct ov6650 *priv = to_ov6650(client);
+ int ret;
+
+- if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+- sel->target != V4L2_SEL_TGT_CROP)
++ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+- v4l_bound_align_image(&sel->r.width, 2, W_CIF, 1,
+- &sel->r.height, 2, H_CIF, 1, 0);
+- v4l_bound_align_image(&sel->r.left, DEF_HSTRT << 1,
+- (DEF_HSTRT << 1) + W_CIF - (__s32)sel->r.width, 1,
+- &sel->r.top, DEF_VSTRT << 1,
+- (DEF_VSTRT << 1) + H_CIF - (__s32)sel->r.height,
+- 1, 0);
++ ov6650_bind_align_crop_rectangle(&sel->r);
++
++ if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
++ struct v4l2_rect *crop = &sd_state->pads->try_crop;
++ struct v4l2_mbus_framefmt *mf = &sd_state->pads->try_fmt;
++ /* detect current pad config scaling factor */
++ bool half_scale = !is_unscaled_ok(mf->width, mf->height, crop);
++
++ /* store new crop rectangle */
++ *crop = sel->r;
+
++ /* adjust frame size */
++ mf->width = crop->width >> half_scale;
++ mf->height = crop->height >> half_scale;
++
++ return 0;
++ }
++
++ /* V4L2_SUBDEV_FORMAT_ACTIVE */
++
++ /* apply new crop rectangle */
+ ret = ov6650_reg_write(client, REG_HSTRT, sel->r.left >> 1);
+ if (!ret) {
+ priv->rect.width += priv->rect.left - sel->r.left;
+@@ -562,30 +600,13 @@ static int ov6650_get_fmt(struct v4l2_subdev *sd,
+ return 0;
+ }
+
+-static bool is_unscaled_ok(int width, int height, struct v4l2_rect *rect)
+-{
+- return width > rect->width >> 1 || height > rect->height >> 1;
+-}
+-
+ #define to_clkrc(div) ((div) - 1)
+
+ /* set the format we will capture in */
+-static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
++static int ov6650_s_fmt(struct v4l2_subdev *sd, u32 code, bool half_scale)
+ {
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov6650 *priv = to_ov6650(client);
+- bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
+- struct v4l2_subdev_selection sel = {
+- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+- .target = V4L2_SEL_TGT_CROP,
+- .r.left = priv->rect.left + (priv->rect.width >> 1) -
+- (mf->width >> (1 - half_scale)),
+- .r.top = priv->rect.top + (priv->rect.height >> 1) -
+- (mf->height >> (1 - half_scale)),
+- .r.width = mf->width << half_scale,
+- .r.height = mf->height << half_scale,
+- };
+- u32 code = mf->code;
+ u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask;
+ int ret;
+
+@@ -653,9 +674,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+ coma_mask |= COMA_QCIF;
+ }
+
+- ret = ov6650_set_selection(sd, NULL, &sel);
+- if (!ret)
+- ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
++ ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
+ if (!ret) {
+ priv->half_scale = half_scale;
+
+@@ -674,14 +693,12 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov6650 *priv = to_ov6650(client);
++ struct v4l2_rect *crop;
++ bool half_scale;
+
+ if (format->pad)
+ return -EINVAL;
+
+- if (is_unscaled_ok(mf->width, mf->height, &priv->rect))
+- v4l_bound_align_image(&mf->width, 2, W_CIF, 1,
+- &mf->height, 2, H_CIF, 1, 0);
+-
+ switch (mf->code) {
+ case MEDIA_BUS_FMT_Y10_1X10:
+ mf->code = MEDIA_BUS_FMT_Y8_1X8;
+@@ -699,10 +716,17 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
+ break;
+ }
+
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
++ crop = &sd_state->pads->try_crop;
++ else
++ crop = &priv->rect;
++
++ half_scale = !is_unscaled_ok(mf->width, mf->height, crop);
++
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+- /* store media bus format code and frame size in pad config */
+- sd_state->pads->try_fmt.width = mf->width;
+- sd_state->pads->try_fmt.height = mf->height;
++ /* store new mbus frame format code and size in pad config */
++ sd_state->pads->try_fmt.width = crop->width >> half_scale;
++ sd_state->pads->try_fmt.height = crop->height >> half_scale;
+ sd_state->pads->try_fmt.code = mf->code;
+
+ /* return default mbus frame format updated with pad config */
+@@ -712,9 +736,11 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
+ mf->code = sd_state->pads->try_fmt.code;
+
+ } else {
+- /* apply new media bus format code and frame size */
+- int ret = ov6650_s_fmt(sd, mf);
++ int ret = 0;
+
++ /* apply new media bus frame format and scaling if changed */
++ if (mf->code != priv->code || half_scale != priv->half_scale)
++ ret = ov6650_s_fmt(sd, mf->code, half_scale);
+ if (ret)
+ return ret;
+
+@@ -890,9 +916,8 @@ static int ov6650_video_probe(struct v4l2_subdev *sd)
+ if (!ret)
+ ret = ov6650_prog_dflt(client, xclk->clkrc);
+ if (!ret) {
+- struct v4l2_mbus_framefmt mf = ov6650_def_fmt;
+-
+- ret = ov6650_s_fmt(sd, &mf);
++ /* driver default frame format, no scaling */
++ ret = ov6650_s_fmt(sd, ov6650_def_fmt.code, false);
+ }
+ if (!ret)
+ ret = v4l2_ctrl_handler_setup(&priv->hdl);
diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index ce50f3ea87b8e..92f6c3a940cfb 100644
--- a/drivers/media/i2c/ov8865.c
@@ -61833,6 +94078,28 @@ index 6a4c7cb0ad0f9..486c8ec0fa60d 100644
spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
return ret;
}
+diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
+index 0e9df8b35ac66..661ebfa7bf3f5 100644
+--- a/drivers/media/pci/bt8xx/bttv-driver.c
++++ b/drivers/media/pci/bt8xx/bttv-driver.c
+@@ -3890,7 +3890,7 @@ static int bttv_register_video(struct bttv *btv)
+
+ /* video */
+ vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
+- btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
++ btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+ if (btv->tuner_type != TUNER_ABSENT)
+ btv->video_dev.device_caps |= V4L2_CAP_TUNER;
+@@ -3911,7 +3911,7 @@ static int bttv_register_video(struct bttv *btv)
+ /* vbi */
+ vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi");
+ btv->vbi_dev.device_caps = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE |
+- V4L2_CAP_STREAMING | V4L2_CAP_TUNER;
++ V4L2_CAP_STREAMING;
+ if (btv->tuner_type != TUNER_ABSENT)
+ btv->vbi_dev.device_caps |= V4L2_CAP_TUNER;
+
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
index ab14d35214aa8..25dc8d4dc5b73 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -61854,6 +94121,110 @@ index ab14d35214aa8..25dc8d4dc5b73 100644
pr_err("%s(): Failed to register analog audio adapter\n",
__func__);
+diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
+index 680e1e3fe89b7..2c1d5137ac470 100644
+--- a/drivers/media/pci/cx88/cx88-mpeg.c
++++ b/drivers/media/pci/cx88/cx88-mpeg.c
+@@ -162,6 +162,9 @@ int cx8802_start_dma(struct cx8802_dev *dev,
+ cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
+ q->count = 0;
+
++ /* clear interrupt status register */
++ cx_write(MO_TS_INTSTAT, 0x1f1111);
++
+ /* enable irqs */
+ dprintk(1, "setting the interrupt mask\n");
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
+diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h
+index 4cf92dee65271..ce3a7ca51736e 100644
+--- a/drivers/media/pci/ivtv/ivtv-driver.h
++++ b/drivers/media/pci/ivtv/ivtv-driver.h
+@@ -330,7 +330,6 @@ struct ivtv_stream {
+ struct ivtv *itv; /* for ease of use */
+ const char *name; /* name of the stream */
+ int type; /* stream type */
+- u32 caps; /* V4L2 capabilities */
+
+ struct v4l2_fh *fh; /* pointer to the streaming filehandle */
+ spinlock_t qlock; /* locks access to the queues */
+diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
+index da19b2e95e6cf..6d2d3348e3215 100644
+--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
++++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
+@@ -438,7 +438,7 @@ static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f
+ struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
+ struct v4l2_window *winfmt = &fmt->fmt.win;
+
+- if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
++ if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -EINVAL;
+ if (!itv->osd_video_pbase)
+ return -EINVAL;
+@@ -549,7 +549,7 @@ static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2
+ u32 chromakey = fmt->fmt.win.chromakey;
+ u8 global_alpha = fmt->fmt.win.global_alpha;
+
+- if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
++ if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -EINVAL;
+ if (!itv->osd_video_pbase)
+ return -EINVAL;
+@@ -1383,7 +1383,7 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+ 0,
+ };
+
+- if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
++ if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -ENOTTY;
+ if (!itv->osd_video_pbase)
+ return -ENOTTY;
+@@ -1450,7 +1450,7 @@ static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffe
+ struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
+ struct yuv_playback_info *yi = &itv->yuv_info;
+
+- if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
++ if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -ENOTTY;
+ if (!itv->osd_video_pbase)
+ return -ENOTTY;
+@@ -1470,7 +1470,7 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
+ struct ivtv *itv = id->itv;
+ struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
+
+- if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
++ if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -ENOTTY;
+ if (!itv->osd_video_pbase)
+ return -ENOTTY;
+diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
+index f04ee84bab5fd..f9de5d1605fe3 100644
+--- a/drivers/media/pci/ivtv/ivtv-streams.c
++++ b/drivers/media/pci/ivtv/ivtv-streams.c
+@@ -176,7 +176,7 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
+ s->itv = itv;
+ s->type = type;
+ s->name = ivtv_stream_info[type].name;
+- s->caps = ivtv_stream_info[type].v4l2_caps;
++ s->vdev.device_caps = ivtv_stream_info[type].v4l2_caps;
+
+ if (ivtv_stream_info[type].pio)
+ s->dma = PCI_DMA_NONE;
+@@ -299,12 +299,9 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
+ if (s_mpg->vdev.v4l2_dev)
+ num = s_mpg->vdev.num + ivtv_stream_info[type].num_offset;
+ }
+- s->vdev.device_caps = s->caps;
+- if (itv->osd_video_pbase) {
+- itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps |=
+- V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+- itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps |=
+- V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
++ if (itv->osd_video_pbase && (type == IVTV_DEC_STREAM_TYPE_YUV ||
++ type == IVTV_DEC_STREAM_TYPE_MPG)) {
++ s->vdev.device_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+ itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+ }
+ video_set_drvdata(&s->vdev, s);
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index e2d56dca5be40..5ad03b2a50bdb 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
@@ -61916,6 +94287,28 @@ index 6f3125c2d0976..77bae14685513 100644
dev_err(&pci_dev->dev,
"%s(): unknown interrupt 0x%x\n",
__func__, reg_isr);
+diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
+index fb24d2ed3621b..d3cde05a6ebab 100644
+--- a/drivers/media/pci/saa7134/saa7134-alsa.c
++++ b/drivers/media/pci/saa7134/saa7134-alsa.c
+@@ -1214,7 +1214,7 @@ static int alsa_device_exit(struct saa7134_dev *dev)
+
+ static int saa7134_alsa_init(void)
+ {
+- struct saa7134_dev *dev = NULL;
++ struct saa7134_dev *dev;
+
+ saa7134_dmasound_init = alsa_device_init;
+ saa7134_dmasound_exit = alsa_device_exit;
+@@ -1229,7 +1229,7 @@ static int saa7134_alsa_init(void)
+ alsa_device_init(dev);
+ }
+
+- if (dev == NULL)
++ if (list_empty(&saa7134_devlist))
+ pr_info("saa7134 ALSA: no saa7134 cards found\n");
+
+ return 0;
diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c
index 2214c74bbbf15..3947701cd6c7e 100644
--- a/drivers/media/pci/saa7146/hexium_gemini.c
@@ -61999,10 +94392,28 @@ index 887b492e4ad1c..14a119b43bca0 100644
return IRQ_HANDLED;
diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
-index 7bb6babdcade0..debc7509c173c 100644
+index 7bb6babdcade0..757a58829a512 100644
--- a/drivers/media/platform/aspeed-video.c
+++ b/drivers/media/platform/aspeed-video.c
-@@ -500,6 +500,10 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video)
+@@ -151,7 +151,7 @@
+ #define VE_SRC_TB_EDGE_DET_BOT GENMASK(28, VE_SRC_TB_EDGE_DET_BOT_SHF)
+
+ #define VE_MODE_DETECT_STATUS 0x098
+-#define VE_MODE_DETECT_H_PIXELS GENMASK(11, 0)
++#define VE_MODE_DETECT_H_PERIOD GENMASK(11, 0)
+ #define VE_MODE_DETECT_V_LINES_SHF 16
+ #define VE_MODE_DETECT_V_LINES GENMASK(27, VE_MODE_DETECT_V_LINES_SHF)
+ #define VE_MODE_DETECT_STATUS_VSYNC BIT(28)
+@@ -162,6 +162,8 @@
+ #define VE_SYNC_STATUS_VSYNC_SHF 16
+ #define VE_SYNC_STATUS_VSYNC GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
+
++#define VE_H_TOTAL_PIXELS 0x0A0
++
+ #define VE_INTERRUPT_CTRL 0x304
+ #define VE_INTERRUPT_STATUS 0x308
+ #define VE_INTERRUPT_MODE_DETECT_WD BIT(0)
+@@ -500,6 +502,10 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video)
aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
VE_INTERRUPT_MODE_DETECT);
@@ -62013,7 +94424,7 @@ index 7bb6babdcade0..debc7509c173c 100644
/* Trigger mode detect */
aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET);
}
-@@ -552,6 +556,8 @@ static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay)
+@@ -552,6 +558,8 @@ static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay)
set_bit(VIDEO_RES_CHANGE, &video->flags);
clear_bit(VIDEO_FRAME_INPRG, &video->flags);
@@ -62022,7 +94433,15 @@ index 7bb6babdcade0..debc7509c173c 100644
aspeed_video_off(video);
aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
-@@ -786,10 +792,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+@@ -759,6 +767,7 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+ u32 src_lr_edge;
+ u32 src_tb_edge;
+ u32 sync;
++ u32 htotal;
+ struct v4l2_bt_timings *det = &video->detected_timings;
+
+ det->width = MIN_WIDTH;
+@@ -786,10 +795,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
return;
}
@@ -62033,7 +94452,25 @@ index 7bb6babdcade0..debc7509c173c 100644
aspeed_video_check_and_set_polarity(video);
aspeed_video_enable_mode_detect(video);
-@@ -1337,7 +1339,6 @@ static void aspeed_video_resolution_work(struct work_struct *work)
+@@ -807,6 +812,7 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+ src_tb_edge = aspeed_video_read(video, VE_SRC_TB_EDGE_DET);
+ mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
+ sync = aspeed_video_read(video, VE_SYNC_STATUS);
++ htotal = aspeed_video_read(video, VE_H_TOTAL_PIXELS);
+
+ video->frame_bottom = (src_tb_edge & VE_SRC_TB_EDGE_DET_BOT) >>
+ VE_SRC_TB_EDGE_DET_BOT_SHF;
+@@ -823,8 +829,7 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+ VE_SRC_LR_EDGE_DET_RT_SHF;
+ video->frame_left = src_lr_edge & VE_SRC_LR_EDGE_DET_LEFT;
+ det->hfrontporch = video->frame_left;
+- det->hbackporch = (mds & VE_MODE_DETECT_H_PIXELS) -
+- video->frame_right;
++ det->hbackporch = htotal - video->frame_right;
+ det->hsync = sync & VE_SYNC_STATUS_HSYNC;
+ if (video->frame_left > video->frame_right)
+ continue;
+@@ -1337,7 +1342,6 @@ static void aspeed_video_resolution_work(struct work_struct *work)
struct delayed_work *dwork = to_delayed_work(work);
struct aspeed_video *video = container_of(dwork, struct aspeed_video,
res_work);
@@ -62041,7 +94478,7 @@ index 7bb6babdcade0..debc7509c173c 100644
aspeed_video_on(video);
-@@ -1350,8 +1351,7 @@ static void aspeed_video_resolution_work(struct work_struct *work)
+@@ -1350,8 +1354,7 @@ static void aspeed_video_resolution_work(struct work_struct *work)
aspeed_video_get_resolution(video);
if (video->detected_timings.width != video->active_timings.width ||
@@ -62052,7 +94489,7 @@ index 7bb6babdcade0..debc7509c173c 100644
.type = V4L2_EVENT_SOURCE_CHANGE,
.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c
-index 136ab7cf36edc..ebf264b980f91 100644
+index 136ab7cf36edc..f768be3c40595 100644
--- a/drivers/media/platform/atmel/atmel-isc-base.c
+++ b/drivers/media/platform/atmel/atmel-isc-base.c
@@ -123,11 +123,9 @@ static int isc_clk_prepare(struct clk_hw *hw)
@@ -62111,6 +94548,46 @@ index 136ab7cf36edc..ebf264b980f91 100644
num_parents = of_clk_get_parent_count(np);
if (num_parents < 1 || num_parents > 3)
return -EINVAL;
+@@ -1372,14 +1369,12 @@ static int isc_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+ {
+ struct isc_device *isc = video_drvdata(file);
+- struct v4l2_subdev_frame_size_enum fse = {
+- .code = isc->config.sd_format->mbus_code,
+- .index = fsize->index,
+- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+- };
+ int ret = -EINVAL;
+ int i;
+
++ if (fsize->index)
++ return -EINVAL;
++
+ for (i = 0; i < isc->num_user_formats; i++)
+ if (isc->user_formats[i]->fourcc == fsize->pixel_format)
+ ret = 0;
+@@ -1391,14 +1386,14 @@ static int isc_enum_framesizes(struct file *file, void *fh,
+ if (ret)
+ return ret;
+
+- ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size,
+- NULL, &fse);
+- if (ret)
+- return ret;
++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+
+- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+- fsize->discrete.width = fse.max_width;
+- fsize->discrete.height = fse.max_height;
++ fsize->stepwise.min_width = 16;
++ fsize->stepwise.max_width = isc->max_width;
++ fsize->stepwise.min_height = 16;
++ fsize->stepwise.max_height = isc->max_height;
++ fsize->stepwise.step_width = 1;
++ fsize->stepwise.step_height = 1;
+
+ return 0;
+ }
diff --git a/drivers/media/platform/atmel/atmel-isc.h b/drivers/media/platform/atmel/atmel-isc.h
index 19cc60dfcbe0f..2bfcb135ef13b 100644
--- a/drivers/media/platform/atmel/atmel-isc.h
@@ -62207,7 +94684,7 @@ index b66f1d174e9d7..e29a9193bac81 100644
clk_disable_unprepare(isc->hclock);
diff --git a/drivers/media/platform/atmel/atmel-sama7g5-isc.c b/drivers/media/platform/atmel/atmel-sama7g5-isc.c
-index f2785131ff569..9c05acafd0724 100644
+index f2785131ff569..6a5d3f7ce75e5 100644
--- a/drivers/media/platform/atmel/atmel-sama7g5-isc.c
+++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c
@@ -447,6 +447,9 @@ static int microchip_xisc_probe(struct platform_device *pdev)
@@ -62256,11 +94733,46 @@ index f2785131ff569..9c05acafd0724 100644
unprepare_hclk:
clk_disable_unprepare(isc->hclock);
+@@ -569,7 +555,6 @@ static int microchip_xisc_remove(struct platform_device *pdev)
+
+ v4l2_device_unregister(&isc->v4l2_dev);
+
+- clk_disable_unprepare(isc->ispck);
+ clk_disable_unprepare(isc->hclock);
+
+ isc_clk_cleanup(isc);
+@@ -581,7 +566,6 @@ static int __maybe_unused xisc_runtime_suspend(struct device *dev)
+ {
+ struct isc_device *isc = dev_get_drvdata(dev);
+
+- clk_disable_unprepare(isc->ispck);
+ clk_disable_unprepare(isc->hclock);
+
+ return 0;
+@@ -596,10 +580,6 @@ static int __maybe_unused xisc_runtime_resume(struct device *dev)
+ if (ret)
+ return ret;
+
+- ret = clk_prepare_enable(isc->ispck);
+- if (ret)
+- clk_disable_unprepare(isc->hclock);
+-
+ return ret;
+ }
+
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
-index 0e312b0842d7f..9a2640a9c75c6 100644
+index 0e312b0842d7f..4a553f42ff0a3 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
-@@ -1537,11 +1537,13 @@ static void coda_pic_run_work(struct work_struct *work)
+@@ -408,6 +408,7 @@ static struct vdoa_data *coda_get_vdoa_data(void)
+ if (!vdoa_data)
+ vdoa_data = ERR_PTR(-EPROBE_DEFER);
+
++ put_device(&vdoa_pdev->dev);
+ out:
+ of_node_put(vdoa_node);
+
+@@ -1537,11 +1538,13 @@ static void coda_pic_run_work(struct work_struct *work)
if (!wait_for_completion_timeout(&ctx->completion,
msecs_to_jiffies(1000))) {
@@ -62340,8 +94852,49 @@ index 8bc0d83718193..dd6e2e320264e 100644
vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
if (!vdoa)
+diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
+index f1ce10828b8e5..5658c7f148d79 100644
+--- a/drivers/media/platform/davinci/vpif.c
++++ b/drivers/media/platform/davinci/vpif.c
+@@ -428,6 +428,7 @@ static int vpif_probe(struct platform_device *pdev)
+ static struct resource *res, *res_irq;
+ struct platform_device *pdev_capture, *pdev_display;
+ struct device_node *endpoint = NULL;
++ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ vpif_base = devm_ioremap_resource(&pdev->dev, res);
+@@ -457,8 +458,8 @@ static int vpif_probe(struct platform_device *pdev)
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq) {
+ dev_warn(&pdev->dev, "Missing IRQ resource.\n");
+- pm_runtime_put(&pdev->dev);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_rpm;
+ }
+
+ pdev_capture = devm_kzalloc(&pdev->dev, sizeof(*pdev_capture),
+@@ -492,10 +493,17 @@ static int vpif_probe(struct platform_device *pdev)
+ }
+
+ return 0;
++
++err_put_rpm:
++ pm_runtime_put(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
++ return ret;
+ }
+
+ static int vpif_remove(struct platform_device *pdev)
+ {
++ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+ }
diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c
-index 755138063ee61..fc905ea78b175 100644
+index 755138063ee61..37905547466bd 100644
--- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c
@@ -575,6 +575,10 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
@@ -62355,7 +94908,22 @@ index 755138063ee61..fc905ea78b175 100644
jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {
-@@ -2088,6 +2092,8 @@ err_m2m:
+@@ -921,8 +925,13 @@ static void mxc_jpeg_device_run(void *priv)
+ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
+
+ jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
++ if (q_data_cap->fmt->colplanes != dst_buf->vb2_buf.num_planes) {
++ dev_err(dev, "Capture format %s has %d planes, but capture buffer has %d planes\n",
++ q_data_cap->fmt->name, q_data_cap->fmt->colplanes,
++ dst_buf->vb2_buf.num_planes);
++ jpeg_src_buf->jpeg_parse_error = true;
++ }
+ if (jpeg_src_buf->jpeg_parse_error) {
+- jpeg->slot_data[ctx->slot].used = false;
+ 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);
+@@ -2088,6 +2097,8 @@ err_m2m:
v4l2_device_unregister(&jpeg->v4l2_dev);
err_register:
@@ -62387,9 +94955,57 @@ index 4321edc0c23d9..8e9c6fee75a48 100644
if (ret)
goto err_clk;
diff --git a/drivers/media/platform/meson/ge2d/ge2d.c b/drivers/media/platform/meson/ge2d/ge2d.c
-index a1393fefa8aea..9b1e973e78da3 100644
+index a1393fefa8aea..a373dea9866bb 100644
--- a/drivers/media/platform/meson/ge2d/ge2d.c
+++ b/drivers/media/platform/meson/ge2d/ge2d.c
+@@ -215,35 +215,35 @@ static void ge2d_hw_start(struct meson_ge2d *ge2d)
+
+ regmap_write(ge2d->map, GE2D_SRC1_CLIPY_START_END,
+ FIELD_PREP(GE2D_START, ctx->in.crop.top) |
+- FIELD_PREP(GE2D_END, ctx->in.crop.top + ctx->in.crop.height));
++ FIELD_PREP(GE2D_END, ctx->in.crop.top + ctx->in.crop.height - 1));
+ regmap_write(ge2d->map, GE2D_SRC1_CLIPX_START_END,
+ FIELD_PREP(GE2D_START, ctx->in.crop.left) |
+- FIELD_PREP(GE2D_END, ctx->in.crop.left + ctx->in.crop.width));
++ FIELD_PREP(GE2D_END, ctx->in.crop.left + ctx->in.crop.width - 1));
+ regmap_write(ge2d->map, GE2D_SRC2_CLIPY_START_END,
+ FIELD_PREP(GE2D_START, ctx->out.crop.top) |
+- FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height));
++ FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height - 1));
+ regmap_write(ge2d->map, GE2D_SRC2_CLIPX_START_END,
+ FIELD_PREP(GE2D_START, ctx->out.crop.left) |
+- FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width));
++ FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width - 1));
+ regmap_write(ge2d->map, GE2D_DST_CLIPY_START_END,
+ FIELD_PREP(GE2D_START, ctx->out.crop.top) |
+- FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height));
++ FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height - 1));
+ regmap_write(ge2d->map, GE2D_DST_CLIPX_START_END,
+ FIELD_PREP(GE2D_START, ctx->out.crop.left) |
+- FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width));
++ FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width - 1));
+
+ regmap_write(ge2d->map, GE2D_SRC1_Y_START_END,
+- FIELD_PREP(GE2D_END, ctx->in.pix_fmt.height));
++ FIELD_PREP(GE2D_END, ctx->in.pix_fmt.height - 1));
+ regmap_write(ge2d->map, GE2D_SRC1_X_START_END,
+- FIELD_PREP(GE2D_END, ctx->in.pix_fmt.width));
++ FIELD_PREP(GE2D_END, ctx->in.pix_fmt.width - 1));
+ regmap_write(ge2d->map, GE2D_SRC2_Y_START_END,
+- FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height));
++ FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height - 1));
+ regmap_write(ge2d->map, GE2D_SRC2_X_START_END,
+- FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width));
++ FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width - 1));
+ regmap_write(ge2d->map, GE2D_DST_Y_START_END,
+- FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height));
++ FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height - 1));
+ regmap_write(ge2d->map, GE2D_DST_X_START_END,
+- FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width));
++ FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width - 1));
+
+ /* Color, no blend, use source color */
+ reg = GE2D_ALU_DO_COLOR_OPERATION_LOGIC(LOGIC_OPERATION_COPY,
@@ -779,11 +779,7 @@ static int ge2d_s_ctrl(struct v4l2_ctrl *ctrl)
* If the rotation parameter changes the OUTPUT frames
* parameters, take them in account
@@ -62446,6 +95062,19 @@ index 45d1870c83dd7..4ced20ca647b1 100644
list_del_init(&ctx->list);
kfree(ctx);
+diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
+index cd27f637dbe7c..cfc7ebed8fb7a 100644
+--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
++++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
+@@ -102,6 +102,8 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
+ vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
+
+ fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
++ if (!fw)
++ return ERR_PTR(-ENOMEM);
+ fw->type = VPU;
+ fw->ops = &mtk_vcodec_vpu_msg;
+ fw->pdev = fw_pdev;
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
index ec290dde59cfd..7f1647da0ade0 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -62469,6 +95098,81 @@ index ec290dde59cfd..7f1647da0ade0 100644
return ret;
}
+diff --git a/drivers/media/platform/qcom/camss/camss-csid-170.c b/drivers/media/platform/qcom/camss/camss-csid-170.c
+index ac22ff29d2a9f..82f59933ad7b3 100644
+--- a/drivers/media/platform/qcom/camss/camss-csid-170.c
++++ b/drivers/media/platform/qcom/camss/camss-csid-170.c
+@@ -105,7 +105,8 @@
+ #define CSID_RDI_CTRL(rdi) ((IS_LITE ? 0x208 : 0x308)\
+ + 0x100 * (rdi))
+ #define RDI_CTRL_HALT_CMD 0
+-#define ALT_CMD_RESUME_AT_FRAME_BOUNDARY 1
++#define HALT_CMD_HALT_AT_FRAME_BOUNDARY 0
++#define HALT_CMD_RESUME_AT_FRAME_BOUNDARY 1
+ #define RDI_CTRL_HALT_MODE 2
+
+ #define CSID_RDI_FRM_DROP_PATTERN(rdi) ((IS_LITE ? 0x20C : 0x30C)\
+@@ -366,7 +367,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
+ val |= input_format->width & 0x1fff << TPG_DT_n_CFG_0_FRAME_WIDTH;
+ writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
+
+- val = DATA_TYPE_RAW_10BIT << TPG_DT_n_CFG_1_DATA_TYPE;
++ val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
+ writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
+
+ val = tg->mode << TPG_DT_n_CFG_2_PAYLOAD_MODE;
+@@ -382,8 +383,9 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
+ val = 1 << RDI_CFG0_BYTE_CNTR_EN;
+ val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
+ val |= 1 << RDI_CFG0_TIMESTAMP_EN;
++ /* note: for non-RDI path, this should be format->decode_format */
+ val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
+- val |= DATA_TYPE_RAW_10BIT << RDI_CFG0_DATA_TYPE;
++ val |= format->data_type << RDI_CFG0_DATA_TYPE;
+ val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
+ val |= dt_id << RDI_CFG0_DT_ID;
+ writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
+@@ -443,13 +445,10 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
+ val |= 1 << CSI2_RX_CFG1_MISR_EN;
+ writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); // csi2_vc_mode_shift_val ?
+
+- /* error irqs start at BIT(11) */
+- writel_relaxed(~0u, csid->base + CSID_CSI2_RX_IRQ_MASK);
+-
+- /* RDI irq */
+- writel_relaxed(~0u, csid->base + CSID_TOP_IRQ_MASK);
+-
+- val = 1 << RDI_CTRL_HALT_CMD;
++ if (enable)
++ val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
++ else
++ val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
+ writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
+ }
+
+diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-170.c
+index 8594d275b41d1..02cb8005504a2 100644
+--- a/drivers/media/platform/qcom/camss/camss-vfe-170.c
++++ b/drivers/media/platform/qcom/camss/camss-vfe-170.c
+@@ -399,17 +399,7 @@ static irqreturn_t vfe_isr(int irq, void *dev)
+ */
+ static int vfe_halt(struct vfe_device *vfe)
+ {
+- unsigned long time;
+-
+- reinit_completion(&vfe->halt_complete);
+-
+- time = wait_for_completion_timeout(&vfe->halt_complete,
+- msecs_to_jiffies(VFE_HALT_TIMEOUT_MS));
+- if (!time) {
+- dev_err(vfe->camss->dev, "VFE halt timeout\n");
+- return -EIO;
+- }
+-
++ /* rely on vfe_disable_output() to stop the VFE */
+ return 0;
+ }
+
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 91b15842c5558..1f0181b6353c9 100644
--- a/drivers/media/platform/qcom/venus/core.c
@@ -62508,6 +95212,19 @@ index 91b15842c5558..1f0181b6353c9 100644
return ret;
}
+diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c
+index 60f4b8e4b8d02..1bf5db7673ebf 100644
+--- a/drivers/media/platform/qcom/venus/hfi_cmds.c
++++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
+@@ -1054,6 +1054,8 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
+ pkt->shdr.hdr.size += sizeof(u32) + sizeof(*info);
+ break;
+ }
++ case HFI_PROPERTY_PARAM_VENC_HDR10_PQ_SEI:
++ return -ENOTSUPP;
+
+ /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
+ case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index 3e2345eb47f7c..a591dd315ebcc 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -62653,6 +95370,45 @@ index 3e2345eb47f7c..a591dd315ebcc 100644
}
static const struct venus_pm_ops pm_ops_v4 = {
+diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
+index bc1c42dd53c04..c4e0fe14c058d 100644
+--- a/drivers/media/platform/qcom/venus/venc.c
++++ b/drivers/media/platform/qcom/venus/venc.c
+@@ -604,8 +604,8 @@ static int venc_set_properties(struct venus_inst *inst)
+
+ ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
+ h264_transform.enable_type = 0;
+- if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
+- ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
++ if (ctr->profile.h264 == V4L2_MPEG_VIDEO_H264_PROFILE_HIGH ||
++ ctr->profile.h264 == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH)
+ h264_transform.enable_type = ctr->h264_8x8_transform;
+
+ ret = hfi_session_set_property(inst, ptype, &h264_transform);
+diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
+index 1ada42df314dc..ea5805e71c143 100644
+--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
++++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
+@@ -320,8 +320,8 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+ ctr->intra_refresh_period = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+- if (ctr->profile.h264 != HFI_H264_PROFILE_HIGH &&
+- ctr->profile.h264 != HFI_H264_PROFILE_CONSTRAINED_HIGH)
++ if (ctr->profile.h264 != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH &&
++ ctr->profile.h264 != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH)
+ return -EINVAL;
+
+ /*
+@@ -457,7 +457,7 @@ int venc_ctrl_init(struct venus_inst *inst)
+ V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, 1, 51, 1, 1);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+- V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 0);
++ V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 1);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, 1, 51, 1, 1);
diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index e28eff0396888..0c5e2f7e04beb 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -62760,6 +95516,19 @@ index 0d141155f0e3e..eb8c79bac540f 100644
pix->bytesperline = rvin_format_bytesperline(vin, pix);
pix->sizeimage = rvin_format_sizeimage(pix);
+diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
+index 6759091b15e09..d99ea8973b678 100644
+--- a/drivers/media/platform/rockchip/rga/rga.c
++++ b/drivers/media/platform/rockchip/rga/rga.c
+@@ -895,7 +895,7 @@ static int rga_probe(struct platform_device *pdev)
+ }
+ rga->dst_mmu_pages =
+ (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+- if (rga->dst_mmu_pages) {
++ if (!rga->dst_mmu_pages) {
+ ret = -ENOMEM;
+ goto free_src_pages;
+ }
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index 7474150b94ed3..560f928c37520 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -62870,6 +95639,20 @@ index 07b2161392d21..5ba3e29f794fd 100644
ret = sun6i_csi_set_power(video->csi, true);
if (ret < 0)
+diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
+index 7799da1cc261b..3e936a2ca36c6 100644
+--- a/drivers/media/platform/ti-vpe/cal-video.c
++++ b/drivers/media/platform/ti-vpe/cal-video.c
+@@ -823,6 +823,9 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
+ /* Enumerate sub device formats and enable all matching local formats */
+ ctx->active_fmt = devm_kcalloc(ctx->cal->dev, cal_num_formats,
+ sizeof(*ctx->active_fmt), GFP_KERNEL);
++ if (!ctx->active_fmt)
++ return -ENOMEM;
++
+ ctx->num_active_fmt = 0;
+
+ for (j = 0, i = 0; ; ++j) {
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 1123768731676..484046471c03f 100644
--- a/drivers/media/radio/radio-wl1273.c
@@ -62926,6 +95709,63 @@ index fedff68d8c496..3f8634a465730 100644
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
#define DRIVER_VERSION "1.0.10"
+diff --git a/drivers/media/rc/gpio-ir-tx.c b/drivers/media/rc/gpio-ir-tx.c
+index c6cd2e6d8e654..a50701cfbbd7b 100644
+--- a/drivers/media/rc/gpio-ir-tx.c
++++ b/drivers/media/rc/gpio-ir-tx.c
+@@ -48,11 +48,29 @@ static int gpio_ir_tx_set_carrier(struct rc_dev *dev, u32 carrier)
+ return 0;
+ }
+
++static void delay_until(ktime_t until)
++{
++ /*
++ * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on
++ * m68k ndelay(s64) does not compile; so use s32 rather than s64.
++ */
++ s32 delta;
++
++ while (true) {
++ delta = ktime_us_delta(until, ktime_get());
++ if (delta <= 0)
++ return;
++
++ /* udelay more than 1ms may not work */
++ delta = min(delta, 1000);
++ udelay(delta);
++ }
++}
++
+ static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf,
+ uint count)
+ {
+ ktime_t edge;
+- s32 delta;
+ int i;
+
+ local_irq_disable();
+@@ -63,9 +81,7 @@ static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf,
+ gpiod_set_value(gpio_ir->gpio, !(i % 2));
+
+ edge = ktime_add_us(edge, txbuf[i]);
+- delta = ktime_us_delta(edge, ktime_get());
+- if (delta > 0)
+- udelay(delta);
++ delay_until(edge);
+ }
+
+ gpiod_set_value(gpio_ir->gpio, 0);
+@@ -97,9 +113,7 @@ static void gpio_ir_tx_modulated(struct gpio_ir *gpio_ir, uint *txbuf,
+ if (i % 2) {
+ // space
+ edge = ktime_add_us(edge, txbuf[i]);
+- delta = ktime_us_delta(edge, ktime_get());
+- if (delta > 0)
+- udelay(delta);
++ delay_until(edge);
+ } else {
+ // pulse
+ ktime_t last = ktime_add_us(edge, txbuf[i]);
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
index effaa5751d6c9..3e9988ee785f0 100644
--- a/drivers/media/rc/igorplugusb.c
@@ -62944,7 +95784,7 @@ index effaa5751d6c9..3e9988ee785f0 100644
do {
rawir.duration = ir->buf_in[i] * 85;
diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c
-index 48d52baec1a1c..1aa7989e756cc 100644
+index 48d52baec1a1c..7f394277478b3 100644
--- a/drivers/media/rc/ir_toy.c
+++ b/drivers/media/rc/ir_toy.c
@@ -310,7 +310,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count)
@@ -62956,6 +95796,15 @@ index 48d52baec1a1c..1aa7989e756cc 100644
irtoy->tx_buf = buf;
irtoy->tx_len = size;
+@@ -429,7 +429,7 @@ static int irtoy_probe(struct usb_interface *intf,
+ err = usb_submit_urb(irtoy->urb_in, GFP_KERNEL);
+ if (err != 0) {
+ dev_err(irtoy->dev, "fail to submit in urb: %d\n", err);
+- return err;
++ goto free_rcdev;
+ }
+
+ err = irtoy_setup(irtoy);
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 5bc23e8c6d91d..4f77d4ebacdc5 100644
--- a/drivers/media/rc/ite-cir.c
@@ -63137,6 +95986,48 @@ index 75617709c8ce2..82620613d56b8 100644
}
static struct platform_device vidtv_bridge_dev = {
+diff --git a/drivers/media/test-drivers/vidtv/vidtv_s302m.c b/drivers/media/test-drivers/vidtv/vidtv_s302m.c
+index d79b65854627c..4676083cee3b8 100644
+--- a/drivers/media/test-drivers/vidtv/vidtv_s302m.c
++++ b/drivers/media/test-drivers/vidtv/vidtv_s302m.c
+@@ -455,6 +455,9 @@ struct vidtv_encoder
+ e->name = kstrdup(args.name, GFP_KERNEL);
+
+ e->encoder_buf = vzalloc(VIDTV_S302M_BUF_SZ);
++ if (!e->encoder_buf)
++ goto out_kfree_e;
++
+ e->encoder_buf_sz = VIDTV_S302M_BUF_SZ;
+ e->encoder_buf_offset = 0;
+
+@@ -467,10 +470,8 @@ struct vidtv_encoder
+ e->is_video_encoder = false;
+
+ ctx = kzalloc(priv_sz, GFP_KERNEL);
+- if (!ctx) {
+- kfree(e);
+- return NULL;
+- }
++ if (!ctx)
++ goto out_kfree_buf;
+
+ e->ctx = ctx;
+ ctx->last_duration = 0;
+@@ -498,6 +499,14 @@ struct vidtv_encoder
+ e->next = NULL;
+
+ return e;
++
++out_kfree_buf:
++ kfree(e->encoder_buf);
++
++out_kfree_e:
++ kfree(e->name);
++ kfree(e);
++ return NULL;
+ }
+
+ void vidtv_s302m_encoder_destroy(struct vidtv_encoder *e)
diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c
index 78e6fd600d8ef..44247049a3190 100644
--- a/drivers/media/tuners/msi001.c
@@ -63783,7 +96674,7 @@ index 4bb5b82599a79..691e05833db19 100644
for (j = 0; j < msg[i].len; j++) {
/* Last byte of transaction? Then send STOP. */
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
-index c1e0dccb74088..ebc430b05f21c 100644
+index c1e0dccb74088..92d867fc519c4 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -3625,8 +3625,10 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
@@ -63832,19 +96723,37 @@ index c1e0dccb74088..ebc430b05f21c 100644
}
static int em28xx_duplicate_dev(struct em28xx *dev)
-@@ -4139,8 +4145,11 @@ static void em28xx_usb_disconnect(struct usb_interface *intf)
+@@ -3925,6 +3931,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
+ goto err_free;
+ }
- em28xx_close_extension(dev);
++ kref_init(&dev->ref);
++
+ dev->devno = nr;
+ dev->model = id->driver_info;
+ dev->alt = -1;
+@@ -4025,6 +4033,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
+ }
-- if (dev->dev_next)
-+ if (dev->dev_next) {
-+ em28xx_close_extension(dev->dev_next);
- em28xx_release_resources(dev->dev_next);
-+ }
+ if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) {
++ kref_init(&dev->dev_next->ref);
+
- em28xx_release_resources(dev);
+ dev->dev_next->ts = SECONDARY_TS;
+ dev->dev_next->alt = -1;
+ dev->dev_next->is_audio_only = has_vendor_audio &&
+@@ -4079,12 +4089,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
+ em28xx_write_reg(dev, 0x0b, 0x82);
+ mdelay(100);
+ }
+-
+- kref_init(&dev->dev_next->ref);
+ }
- if (dev->dev_next) {
+- kref_init(&dev->ref);
+-
+ request_modules(dev);
+
+ /*
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 584fa400cd7d8..c837cc528a335 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
@@ -63879,6 +96788,63 @@ index 584fa400cd7d8..c837cc528a335 100644
if (dev->dev_next)
ops->suspend(dev->dev_next);
}
+diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c
+index c742cc88fac5c..1fa6f10ee157b 100644
+--- a/drivers/media/usb/go7007/s2250-board.c
++++ b/drivers/media/usb/go7007/s2250-board.c
+@@ -504,6 +504,7 @@ static int s2250_probe(struct i2c_client *client,
+ u8 *data;
+ struct go7007 *go = i2c_get_adapdata(adapter);
+ struct go7007_usb *usb = go->hpi_context;
++ int err = -EIO;
+
+ audio = i2c_new_dummy_device(adapter, TLV320_ADDRESS >> 1);
+ if (IS_ERR(audio))
+@@ -532,11 +533,8 @@ static int s2250_probe(struct i2c_client *client,
+ V4L2_CID_HUE, -512, 511, 1, 0);
+ sd->ctrl_handler = &state->hdl;
+ if (state->hdl.error) {
+- int err = state->hdl.error;
+-
+- v4l2_ctrl_handler_free(&state->hdl);
+- kfree(state);
+- return err;
++ err = state->hdl.error;
++ goto fail;
+ }
+
+ state->std = V4L2_STD_NTSC;
+@@ -600,7 +598,7 @@ fail:
+ i2c_unregister_device(audio);
+ v4l2_ctrl_handler_free(&state->hdl);
+ kfree(state);
+- return -EIO;
++ return err;
+ }
+
+ static int s2250_remove(struct i2c_client *client)
+diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
+index 563128d117317..60e57e0f19272 100644
+--- a/drivers/media/usb/hdpvr/hdpvr-video.c
++++ b/drivers/media/usb/hdpvr/hdpvr-video.c
+@@ -308,7 +308,6 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev)
+
+ dev->status = STATUS_STREAMING;
+
+- INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
+ schedule_work(&dev->worker);
+
+ v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+@@ -1165,6 +1164,9 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+ bool ac3 = dev->flags & HDPVR_FLAG_AC3_CAP;
+ int res;
+
++ // initialize dev->worker
++ INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
++
+ dev->cur_std = V4L2_STD_525_60;
+ dev->width = 720;
+ dev->height = 480;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index d38dee1792e41..3915d551d59e7 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -63942,7 +96908,7 @@ index 3b0e4ed75d99c..acf18e2251a52 100644
kfree(buf);
return r;
diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c
-index b4f8bc5db1389..4e1698f788187 100644
+index b4f8bc5db1389..ce717502ea4c3 100644
--- a/drivers/media/usb/stk1160/stk1160-core.c
+++ b/drivers/media/usb/stk1160/stk1160-core.c
@@ -65,7 +65,7 @@ int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value)
@@ -63963,6 +96929,77 @@ index b4f8bc5db1389..4e1698f788187 100644
if (ret < 0) {
stk1160_err("write failed on reg 0x%x (%d)\n",
reg, ret);
+@@ -403,7 +403,7 @@ static void stk1160_disconnect(struct usb_interface *interface)
+ /* Here is the only place where isoc get released */
+ stk1160_uninit_isoc(dev);
+
+- stk1160_clear_queue(dev);
++ stk1160_clear_queue(dev, VB2_BUF_STATE_ERROR);
+
+ video_unregister_device(&dev->vdev);
+ v4l2_device_disconnect(&dev->v4l2_dev);
+diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
+index 6a4eb616d5160..1aa953469402f 100644
+--- a/drivers/media/usb/stk1160/stk1160-v4l.c
++++ b/drivers/media/usb/stk1160/stk1160-v4l.c
+@@ -258,7 +258,7 @@ out_uninit:
+ stk1160_uninit_isoc(dev);
+ out_stop_hw:
+ usb_set_interface(dev->udev, 0, 0);
+- stk1160_clear_queue(dev);
++ stk1160_clear_queue(dev, VB2_BUF_STATE_QUEUED);
+
+ mutex_unlock(&dev->v4l_lock);
+
+@@ -306,7 +306,7 @@ static int stk1160_stop_streaming(struct stk1160 *dev)
+
+ stk1160_stop_hw(dev);
+
+- stk1160_clear_queue(dev);
++ stk1160_clear_queue(dev, VB2_BUF_STATE_ERROR);
+
+ stk1160_dbg("streaming stopped\n");
+
+@@ -745,7 +745,7 @@ static const struct video_device v4l_template = {
+ /********************************************************************/
+
+ /* Must be called with both v4l_lock and vb_queue_lock hold */
+-void stk1160_clear_queue(struct stk1160 *dev)
++void stk1160_clear_queue(struct stk1160 *dev, enum vb2_buffer_state vb2_state)
+ {
+ struct stk1160_buffer *buf;
+ unsigned long flags;
+@@ -756,7 +756,7 @@ void stk1160_clear_queue(struct stk1160 *dev)
+ buf = list_first_entry(&dev->avail_bufs,
+ struct stk1160_buffer, list);
+ list_del(&buf->list);
+- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
++ vb2_buffer_done(&buf->vb.vb2_buf, vb2_state);
+ stk1160_dbg("buffer [%p/%d] aborted\n",
+ buf, buf->vb.vb2_buf.index);
+ }
+@@ -766,7 +766,7 @@ void stk1160_clear_queue(struct stk1160 *dev)
+ buf = dev->isoc_ctl.buf;
+ dev->isoc_ctl.buf = NULL;
+
+- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
++ vb2_buffer_done(&buf->vb.vb2_buf, vb2_state);
+ stk1160_dbg("buffer [%p/%d] aborted\n",
+ buf, buf->vb.vb2_buf.index);
+ }
+diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
+index a31ea1c80f255..a70963ce87533 100644
+--- a/drivers/media/usb/stk1160/stk1160.h
++++ b/drivers/media/usb/stk1160/stk1160.h
+@@ -166,7 +166,7 @@ struct regval {
+ int stk1160_vb2_setup(struct stk1160 *dev);
+ int stk1160_video_register(struct stk1160 *dev);
+ void stk1160_video_unregister(struct stk1160 *dev);
+-void stk1160_clear_queue(struct stk1160 *dev);
++void stk1160_clear_queue(struct stk1160 *dev, enum vb2_buffer_state vb2_state);
+
+ /* Provided by stk1160-video.c */
+ int stk1160_alloc_isoc(struct stk1160 *dev);
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 3f650ede0c3dc..e293f6f3d1bc9 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
@@ -64182,11 +97219,79 @@ index 47aff3b197426..80aaf07b16f28 100644
#endif
}
return 0;
+diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
+index c4b5082849b66..45a76f40deeb3 100644
+--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
++++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
+@@ -113,6 +113,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
+ struct v4l2_ctrl_mpeg2_quantisation *p_mpeg2_quant;
+ struct v4l2_ctrl_vp8_frame *p_vp8_frame;
+ struct v4l2_ctrl_fwht_params *p_fwht_params;
++ struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
+ void *p = ptr.p + idx * ctrl->elem_size;
+
+ if (ctrl->p_def.p_const)
+@@ -160,6 +161,15 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
+ p_fwht_params->flags = V4L2_FWHT_FL_PIXENC_YUV |
+ (2 << V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET);
+ break;
++ case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
++ p_h264_scaling_matrix = p;
++ /*
++ * The default (flat) H.264 scaling matrix when none are
++ * specified in the bitstream, this is according to formulas
++ * (7-8) and (7-9) of the specification.
++ */
++ memset(p_h264_scaling_matrix, 16, sizeof(*p_h264_scaling_matrix));
++ break;
+ }
+ }
+
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
-index 05d5db3d85e58..c7308a2a80a0f 100644
+index 05d5db3d85e58..7c596a85f34f5 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
-@@ -869,7 +869,7 @@ static void v4l_print_default(const void *arg, bool write_only)
+@@ -279,8 +279,8 @@ static void v4l_print_format(const void *arg, bool write_only)
+ const struct v4l2_vbi_format *vbi;
+ const struct v4l2_sliced_vbi_format *sliced;
+ const struct v4l2_window *win;
+- const struct v4l2_sdr_format *sdr;
+ const struct v4l2_meta_format *meta;
++ u32 pixelformat;
+ u32 planes;
+ unsigned i;
+
+@@ -299,8 +299,9 @@ static void v4l_print_format(const void *arg, bool write_only)
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ mp = &p->fmt.pix_mp;
++ pixelformat = mp->pixelformat;
+ pr_cont(", width=%u, height=%u, format=%p4cc, field=%s, colorspace=%d, num_planes=%u, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
+- mp->width, mp->height, &mp->pixelformat,
++ mp->width, mp->height, &pixelformat,
+ prt_names(mp->field, v4l2_field_names),
+ mp->colorspace, mp->num_planes, mp->flags,
+ mp->ycbcr_enc, mp->quantization, mp->xfer_func);
+@@ -343,14 +344,15 @@ static void v4l_print_format(const void *arg, bool write_only)
+ break;
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+- sdr = &p->fmt.sdr;
+- pr_cont(", pixelformat=%p4cc\n", &sdr->pixelformat);
++ pixelformat = p->fmt.sdr.pixelformat;
++ pr_cont(", pixelformat=%p4cc\n", &pixelformat);
+ break;
+ case V4L2_BUF_TYPE_META_CAPTURE:
+ case V4L2_BUF_TYPE_META_OUTPUT:
+ meta = &p->fmt.meta;
++ pixelformat = meta->dataformat;
+ pr_cont(", dataformat=%p4cc, buffersize=%u\n",
+- &meta->dataformat, meta->buffersize);
++ &pixelformat, meta->buffersize);
+ break;
+ }
+ }
+@@ -869,7 +871,7 @@ static void v4l_print_default(const void *arg, bool write_only)
pr_cont("driver-specific ioctl\n");
}
@@ -64195,7 +97300,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
{
__u32 i;
-@@ -878,23 +878,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
+@@ -878,23 +880,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
@@ -64249,7 +97354,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
}
static int check_fmt(struct file *file, enum v4l2_buf_type type)
-@@ -2070,6 +2088,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
+@@ -2070,6 +2090,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
@@ -64257,7 +97362,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
struct v4l2_streamparm *p = arg;
v4l2_std_id std;
int ret = check_fmt(file, p->type);
-@@ -2081,7 +2100,8 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
+@@ -2081,7 +2102,8 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
return -EINVAL;
@@ -64267,7 +97372,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
ret = ops->vidioc_g_std(file, fh, &std);
if (ret == 0)
v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe);
-@@ -2187,7 +2207,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,
+@@ -2187,7 +2209,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,
ctrls.controls = &ctrl;
ctrl.id = p->id;
ctrl.value = p->value;
@@ -64276,7 +97381,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
if (ret == 0)
-@@ -2206,6 +2226,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
+@@ -2206,6 +2228,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
@@ -64284,7 +97389,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
if (vfh && vfh->ctrl_handler)
return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
-@@ -2221,9 +2242,11 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
+@@ -2221,9 +2244,11 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
ctrls.controls = &ctrl;
ctrl.id = p->id;
ctrl.value = p->value;
@@ -64299,7 +97404,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
}
static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
-@@ -2243,8 +2266,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
+@@ -2243,8 +2268,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
vfd, vfd->v4l2_dev->mdev, p);
if (ops->vidioc_g_ext_ctrls == NULL)
return -ENOTTY;
@@ -64310,7 +97415,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
}
static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
-@@ -2264,8 +2287,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
+@@ -2264,8 +2289,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
vfd, vfd->v4l2_dev->mdev, p);
if (ops->vidioc_s_ext_ctrls == NULL)
return -ENOTTY;
@@ -64321,7 +97426,7 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
}
static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
-@@ -2285,8 +2308,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
+@@ -2285,8 +2310,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
vfd, vfd->v4l2_dev->mdev, p);
if (ops->vidioc_try_ext_ctrls == NULL)
return -ENOTTY;
@@ -64332,6 +97437,189 @@ index 05d5db3d85e58..c7308a2a80a0f 100644
}
/*
+diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
+index e7f4bf5bc8dd7..3de683b5e06d0 100644
+--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
+@@ -585,19 +585,14 @@ int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ }
+ EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
+
+-int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+- struct v4l2_buffer *buf)
++static void v4l2_m2m_adjust_mem_offset(struct vb2_queue *vq,
++ struct v4l2_buffer *buf)
+ {
+- struct vb2_queue *vq;
+- int ret = 0;
+- unsigned int i;
+-
+- vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+- ret = vb2_querybuf(vq, buf);
+-
+ /* Adjust MMAP memory offsets for the CAPTURE queue */
+ if (buf->memory == V4L2_MEMORY_MMAP && V4L2_TYPE_IS_CAPTURE(vq->type)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
++ unsigned int i;
++
+ for (i = 0; i < buf->length; ++i)
+ buf->m.planes[i].m.mem_offset
+ += DST_QUEUE_OFF_BASE;
+@@ -605,8 +600,23 @@ int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ buf->m.offset += DST_QUEUE_OFF_BASE;
+ }
+ }
++}
+
+- return ret;
++int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
++ struct v4l2_buffer *buf)
++{
++ struct vb2_queue *vq;
++ int ret;
++
++ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
++ ret = vb2_querybuf(vq, buf);
++ if (ret)
++ return ret;
++
++ /* Adjust MMAP memory offsets for the CAPTURE queue */
++ v4l2_m2m_adjust_mem_offset(vq, buf);
++
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf);
+
+@@ -763,6 +773,9 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ if (ret)
+ return ret;
+
++ /* Adjust MMAP memory offsets for the CAPTURE queue */
++ v4l2_m2m_adjust_mem_offset(vq, buf);
++
+ /*
+ * If the capture queue is streaming, but streaming hasn't started
+ * on the device, but was asked to stop, mark the previously queued
+@@ -784,9 +797,17 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_buffer *buf)
+ {
+ struct vb2_queue *vq;
++ int ret;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+- return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
++ ret = vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
++ if (ret)
++ return ret;
++
++ /* Adjust MMAP memory offsets for the CAPTURE queue */
++ v4l2_m2m_adjust_mem_offset(vq, buf);
++
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
+
+@@ -795,9 +816,17 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct vb2_queue *vq;
++ int ret;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+- return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
++ ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
++ if (ret)
++ return ret;
++
++ /* Adjust MMAP memory offsets for the CAPTURE queue */
++ v4l2_m2m_adjust_mem_offset(vq, buf);
++
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
+
+diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
+index c267283b01fda..e749dcb3ddea9 100644
+--- a/drivers/memory/atmel-ebi.c
++++ b/drivers/memory/atmel-ebi.c
+@@ -544,20 +544,27 @@ static int atmel_ebi_probe(struct platform_device *pdev)
+ smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
+
+ ebi->smc.regmap = syscon_node_to_regmap(smc_np);
+- if (IS_ERR(ebi->smc.regmap))
+- return PTR_ERR(ebi->smc.regmap);
++ if (IS_ERR(ebi->smc.regmap)) {
++ ret = PTR_ERR(ebi->smc.regmap);
++ goto put_node;
++ }
+
+ ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np);
+- if (IS_ERR(ebi->smc.layout))
+- return PTR_ERR(ebi->smc.layout);
++ if (IS_ERR(ebi->smc.layout)) {
++ ret = PTR_ERR(ebi->smc.layout);
++ goto put_node;
++ }
+
+ ebi->smc.clk = of_clk_get(smc_np, 0);
+ if (IS_ERR(ebi->smc.clk)) {
+- if (PTR_ERR(ebi->smc.clk) != -ENOENT)
+- return PTR_ERR(ebi->smc.clk);
++ if (PTR_ERR(ebi->smc.clk) != -ENOENT) {
++ ret = PTR_ERR(ebi->smc.clk);
++ goto put_node;
++ }
+
+ ebi->smc.clk = NULL;
+ }
++ of_node_put(smc_np);
+ ret = clk_prepare_enable(ebi->smc.clk);
+ if (ret)
+ return ret;
+@@ -608,6 +615,10 @@ static int atmel_ebi_probe(struct platform_device *pdev)
+ }
+
+ return of_platform_populate(np, NULL, NULL, dev);
++
++put_node:
++ of_node_put(smc_np);
++ return ret;
+ }
+
+ static __maybe_unused int atmel_ebi_resume(struct device *dev)
+diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
+index 762d0c0f0716f..ecc78d6f89ed2 100644
+--- a/drivers/memory/emif.c
++++ b/drivers/memory/emif.c
+@@ -1025,7 +1025,7 @@ static struct emif_data *__init_or_module get_device_details(
+ temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
+
+- if (!emif || !pd || !dev_info) {
++ if (!emif || !temp || !dev_info) {
+ dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
+ goto error;
+ }
+@@ -1117,7 +1117,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
+ {
+ struct emif_data *emif;
+ struct resource *res;
+- int irq;
++ int irq, ret;
+
+ if (pdev->dev.of_node)
+ emif = of_get_memory_device_details(pdev->dev.of_node, &pdev->dev);
+@@ -1147,7 +1147,9 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
+ emif_onetime_settings(emif);
+ emif_debugfs_init(emif);
+ disable_and_clear_all_interrupts(emif);
+- setup_interrupts(emif, irq);
++ ret = setup_interrupts(emif, irq);
++ if (ret)
++ goto error;
+
+ /* One-time actions taken on probing the first device */
+ if (!emif1) {
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
index d062c2f8250f4..75a8c38df9394 100644
--- a/drivers/memory/fsl_ifc.c
@@ -64377,34 +97665,48 @@ index d062c2f8250f4..75a8c38df9394 100644
err:
iounmap(fsl_ifc_ctrl_dev->gregs);
diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
-index 45eed659b0c6d..8618702233002 100644
+index 45eed659b0c6d..3a416705f61cb 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
-@@ -160,10 +160,62 @@ static const struct regmap_access_table rpcif_volatile_table = {
+@@ -160,10 +160,92 @@ static const struct regmap_access_table rpcif_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges),
};
+
+/*
-+ * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed
-+ * with proper width. Requires SMENR_SPIDE to be correctly set before!
++ * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
++ * proper width. Requires rpcif.xfer_size to be correctly set before!
+ */
+static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct rpcif *rpc = context;
+
-+ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) {
-+ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF);
-+
-+ if (spide == 0x8) {
++ switch (reg) {
++ case RPCIF_SMRDR0:
++ case RPCIF_SMWDR0:
++ switch (rpc->xfer_size) {
++ case 1:
+ *val = readb(rpc->base + reg);
+ return 0;
-+ } else if (spide == 0xC) {
++
++ case 2:
+ *val = readw(rpc->base + reg);
+ return 0;
-+ } else if (spide != 0xF) {
++
++ case 4:
++ case 8:
++ *val = readl(rpc->base + reg);
++ return 0;
++
++ default:
+ return -EILSEQ;
+ }
++
++ case RPCIF_SMRDR1:
++ case RPCIF_SMWDR1:
++ if (rpc->xfer_size != 8)
++ return -EILSEQ;
++ break;
+ }
+
+ *val = readl(rpc->base + reg);
@@ -64416,18 +97718,34 @@ index 45eed659b0c6d..8618702233002 100644
+{
+ struct rpcif *rpc = context;
+
-+ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) {
-+ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF);
-+
-+ if (spide == 0x8) {
++ switch (reg) {
++ case RPCIF_SMWDR0:
++ switch (rpc->xfer_size) {
++ case 1:
+ writeb(val, rpc->base + reg);
+ return 0;
-+ } else if (spide == 0xC) {
++
++ case 2:
+ writew(val, rpc->base + reg);
+ return 0;
-+ } else if (spide != 0xF) {
++
++ case 4:
++ case 8:
++ writel(val, rpc->base + reg);
++ return 0;
++
++ default:
+ return -EILSEQ;
+ }
++
++ case RPCIF_SMWDR1:
++ if (rpc->xfer_size != 8)
++ return -EILSEQ;
++ break;
++
++ case RPCIF_SMRDR0:
++ case RPCIF_SMRDR1:
++ return -EPERM;
+ }
+
+ writel(val, rpc->base + reg);
@@ -64443,7 +97761,7 @@ index 45eed659b0c6d..8618702233002 100644
.fast_io = true,
.max_register = RPCIF_PHYINT,
.volatile_table = &rpcif_volatile_table,
-@@ -173,17 +225,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
+@@ -173,17 +255,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
@@ -64465,7 +97783,7 @@ index 45eed659b0c6d..8618702233002 100644
if (IS_ERR(rpc->regmap)) {
dev_err(&pdev->dev,
"failed to init regmap for rpcif, error %ld\n",
-@@ -194,7 +244,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
+@@ -194,7 +274,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
rpc->dirmap = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rpc->dirmap))
@@ -64474,7 +97792,7 @@ index 45eed659b0c6d..8618702233002 100644
rpc->size = resource_size(res);
rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
-@@ -354,20 +404,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
+@@ -354,20 +434,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
nbytes = op->data.nbytes;
rpc->xferlen = nbytes;
@@ -64497,7 +97815,7 @@ index 45eed659b0c6d..8618702233002 100644
pm_runtime_get_sync(rpc->dev);
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
-@@ -378,37 +424,36 @@ int rpcif_manual_xfer(struct rpcif *rpc)
+@@ -378,37 +454,37 @@ int rpcif_manual_xfer(struct rpcif *rpc)
regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option);
regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy);
regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr);
@@ -64524,6 +97842,7 @@ index 45eed659b0c6d..8618702233002 100644
+
+ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes));
+ regmap_write(rpc->regmap, RPCIF_SMENR, smenr);
++ rpc->xfer_size = nbytes;
memcpy(data, rpc->buffer + pos, nbytes);
- if (nbytes > 4) {
@@ -64547,7 +97866,7 @@ index 45eed659b0c6d..8618702233002 100644
regmap_write(rpc->regmap, RPCIF_SMCR, smcr);
ret = wait_msg_xfer_end(rpc);
if (ret)
-@@ -448,14 +493,16 @@ int rpcif_manual_xfer(struct rpcif *rpc)
+@@ -448,33 +524,32 @@ int rpcif_manual_xfer(struct rpcif *rpc)
break;
}
while (pos < rpc->xferlen) {
@@ -64568,7 +97887,8 @@ index 45eed659b0c6d..8618702233002 100644
regmap_write(rpc->regmap, RPCIF_SMENR, smenr);
regmap_write(rpc->regmap, RPCIF_SMCR,
rpc->smcr | RPCIF_SMCR_SPIE);
-@@ -463,18 +510,14 @@ int rpcif_manual_xfer(struct rpcif *rpc)
++ rpc->xfer_size = nbytes;
+ ret = wait_msg_xfer_end(rpc);
if (ret)
goto err_out;
@@ -64579,16 +97899,40 @@ index 45eed659b0c6d..8618702233002 100644
regmap_read(rpc->regmap, RPCIF_SMRDR0,
&data[1]);
- } else if (nbytes > 2) {
-- regmap_read(rpc->regmap, RPCIF_SMRDR0,
-- &data[0]);
-- } else {
+ } else {
regmap_read(rpc->regmap, RPCIF_SMRDR0,
&data[0]);
+- } else {
+- regmap_read(rpc->regmap, RPCIF_SMRDR0,
+- &data[0]);
- data[0] >>= 16;
}
memcpy(rpc->buffer + pos, data, nbytes);
+@@ -536,6 +611,7 @@ static int rpcif_probe(struct platform_device *pdev)
+ struct platform_device *vdev;
+ struct device_node *flash;
+ const char *name;
++ int ret;
+
+ flash = of_get_next_child(pdev->dev.of_node, NULL);
+ if (!flash) {
+@@ -559,7 +635,14 @@ static int rpcif_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ vdev->dev.parent = &pdev->dev;
+ platform_set_drvdata(pdev, vdev);
+- return platform_device_add(vdev);
++
++ ret = platform_device_add(vdev);
++ if (ret) {
++ platform_device_put(vdev);
++ return ret;
++ }
++
++ return 0;
+ }
+
+ static int rpcif_remove(struct platform_device *pdev)
diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index c3462dbc8c22b..6fc90f2160e93 100644
--- a/drivers/memory/tegra/tegra20-emc.c
@@ -64674,6 +98018,41 @@ index 20cb294c75122..5d3715a28b28e 100644
regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config);
}
+diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
+index 8d58c8df46cfb..56338f9dbd0ba 100644
+--- a/drivers/mfd/asic3.c
++++ b/drivers/mfd/asic3.c
+@@ -906,14 +906,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
+ ret = mfd_add_devices(&pdev->dev, pdev->id,
+ &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
+ if (ret < 0)
+- goto out;
++ goto out_unmap;
+ }
+
+ if (mem_sdio && (irq >= 0)) {
+ ret = mfd_add_devices(&pdev->dev, pdev->id,
+ &asic3_cell_mmc, 1, mem_sdio, irq, NULL);
+ if (ret < 0)
+- goto out;
++ goto out_unmap;
+ }
+
+ ret = 0;
+@@ -927,8 +927,12 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
+ ret = mfd_add_devices(&pdev->dev, 0,
+ asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
+ }
++ return ret;
+
+- out:
++out_unmap:
++ if (asic->tmio_cnf)
++ iounmap(asic->tmio_cnf);
++out:
+ return ret;
+ }
+
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
index d2f5c073fdf31..559eb4d352b68 100644
--- a/drivers/mfd/atmel-flexcom.c
@@ -64787,6 +98166,22 @@ index 3f1d976eb67cb..f2ea6540a01e1 100644
}
static int intel_lpss_acpi_remove(struct platform_device *pdev)
+diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
+index 1abe7432aad82..e281a9202f110 100644
+--- a/drivers/mfd/mc13xxx-core.c
++++ b/drivers/mfd/mc13xxx-core.c
+@@ -323,8 +323,10 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
+ adc1 |= MC13783_ADC1_ATOX;
+
+ dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
+- mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
++ ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
+ mc13xxx_handler_adcdone, __func__, &adcdone_data);
++ if (ret)
++ goto out;
+
+ mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
+ mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 79f5c6a18815a..684a011a63968 100644
--- a/drivers/mfd/mfd-core.c
@@ -64898,6 +98293,47 @@ index 6e105cca27d47..67e2707af4bce 100644
tps65910_i2c_client = i2c;
pm_power_off = tps65910_power_off;
}
+diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c
+index de6d44a158bba..3f514d77a843f 100644
+--- a/drivers/misc/cardreader/alcor_pci.c
++++ b/drivers/misc/cardreader/alcor_pci.c
+@@ -266,7 +266,7 @@ static int alcor_pci_probe(struct pci_dev *pdev,
+ if (!priv)
+ return -ENOMEM;
+
+- ret = ida_simple_get(&alcor_pci_idr, 0, 0, GFP_KERNEL);
++ ret = ida_alloc(&alcor_pci_idr, GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+ priv->id = ret;
+@@ -280,7 +280,8 @@ static int alcor_pci_probe(struct pci_dev *pdev,
+ ret = pci_request_regions(pdev, DRV_NAME_ALCOR_PCI);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request region\n");
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto error_free_ida;
+ }
+
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
+@@ -324,6 +325,8 @@ static int alcor_pci_probe(struct pci_dev *pdev,
+
+ error_release_regions:
+ pci_release_regions(pdev);
++error_free_ida:
++ ida_free(&alcor_pci_idr, priv->id);
+ return ret;
+ }
+
+@@ -337,7 +340,7 @@ static void alcor_pci_remove(struct pci_dev *pdev)
+
+ mfd_remove_devices(&pdev->dev);
+
+- ida_simple_remove(&alcor_pci_idr, priv->id);
++ ida_free(&alcor_pci_idr, priv->id);
+
+ pci_release_regions(pdev);
+ pci_set_drvdata(pdev, NULL);
diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
index baf83594a01d3..5121edb0d9eff 100644
--- a/drivers/misc/cardreader/rtsx_pcr.c
@@ -64921,7 +98357,7 @@ index baf83594a01d3..5121edb0d9eff 100644
if (pcr->ops->fetch_vendor_settings)
pcr->ops->fetch_vendor_settings(pcr);
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
-index 632325474233a..9193b812bc07e 100644
+index 632325474233a..403243859dce9 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -17,8 +17,6 @@
@@ -64933,7 +98369,94 @@ index 632325474233a..9193b812bc07e 100644
#include <linux/math.h>
/*
-@@ -376,28 +374,31 @@ MODULE_DEVICE_TABLE(spi, at25_spi_ids);
+@@ -32,6 +30,8 @@
+ */
+
+ #define FM25_SN_LEN 8 /* serial number length */
++#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
++
+ struct at25_data {
+ struct spi_device *spi;
+ struct mutex lock;
+@@ -40,6 +40,7 @@ struct at25_data {
+ struct nvmem_config nvmem_config;
+ struct nvmem_device *nvmem;
+ u8 sernum[FM25_SN_LEN];
++ u8 command[EE_MAXADDRLEN + 1];
+ };
+
+ #define AT25_WREN 0x06 /* latch the write enable */
+@@ -62,8 +63,6 @@ struct at25_data {
+
+ #define FM25_ID_LEN 9 /* ID length */
+
+-#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
+-
+ /* Specs often allow 5 msec for a page write, sometimes 20 msec;
+ * it's important to recover from write timeouts.
+ */
+@@ -78,7 +77,6 @@ static int at25_ee_read(void *priv, unsigned int offset,
+ {
+ struct at25_data *at25 = priv;
+ char *buf = val;
+- u8 command[EE_MAXADDRLEN + 1];
+ u8 *cp;
+ ssize_t status;
+ struct spi_transfer t[2];
+@@ -92,12 +90,15 @@ static int at25_ee_read(void *priv, unsigned int offset,
+ if (unlikely(!count))
+ return -EINVAL;
+
+- cp = command;
++ cp = at25->command;
+
+ instr = AT25_READ;
+ if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
+ if (offset >= (1U << (at25->addrlen * 8)))
+ instr |= AT25_INSTR_BIT3;
++
++ mutex_lock(&at25->lock);
++
+ *cp++ = instr;
+
+ /* 8/16/24-bit address is written MSB first */
+@@ -116,7 +117,7 @@ static int at25_ee_read(void *priv, unsigned int offset,
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+- t[0].tx_buf = command;
++ t[0].tx_buf = at25->command;
+ t[0].len = at25->addrlen + 1;
+ spi_message_add_tail(&t[0], &m);
+
+@@ -124,8 +125,6 @@ static int at25_ee_read(void *priv, unsigned int offset,
+ t[1].len = count;
+ spi_message_add_tail(&t[1], &m);
+
+- mutex_lock(&at25->lock);
+-
+ /* Read it all at once.
+ *
+ * REVISIT that's potentially a problem with large chips, if
+@@ -153,7 +152,7 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+- t[0].tx_buf = &command;
++ t[0].tx_buf = at25->command;
+ t[0].len = 1;
+ spi_message_add_tail(&t[0], &m);
+
+@@ -163,6 +162,8 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,
+
+ mutex_lock(&at25->lock);
+
++ at25->command[0] = command;
++
+ status = spi_sync(at25->spi, &m);
+ dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status);
+
+@@ -376,28 +377,31 @@ MODULE_DEVICE_TABLE(spi, at25_spi_ids);
static int at25_probe(struct spi_device *spi)
{
struct at25_data *at25 = NULL;
@@ -64979,7 +98502,7 @@ index 632325474233a..9193b812bc07e 100644
/* Ping the chip ... the status register is pretty portable,
* unlike probing manufacturer IDs. We do expect that system
-@@ -409,12 +410,7 @@ static int at25_probe(struct spi_device *spi)
+@@ -409,12 +413,7 @@ static int at25_probe(struct spi_device *spi)
return -ENXIO;
}
@@ -64992,7 +98515,7 @@ index 632325474233a..9193b812bc07e 100644
at25->spi = spi;
spi_set_drvdata(spi, at25);
-@@ -431,7 +427,7 @@ static int at25_probe(struct spi_device *spi)
+@@ -431,7 +430,7 @@ static int at25_probe(struct spi_device *spi)
dev_err(&spi->dev, "Error: unsupported size (id %02x)\n", id[7]);
return -ENODEV;
}
@@ -65001,7 +98524,7 @@ index 632325474233a..9193b812bc07e 100644
if (at25->chip.byte_len > 64 * 1024)
at25->chip.flags |= EE_ADDR3;
-@@ -464,7 +460,7 @@ static int at25_probe(struct spi_device *spi)
+@@ -464,7 +463,7 @@ static int at25_probe(struct spi_device *spi)
at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM;
at25->nvmem_config.name = dev_name(&spi->dev);
at25->nvmem_config.dev = &spi->dev;
@@ -65010,7 +98533,7 @@ index 632325474233a..9193b812bc07e 100644
at25->nvmem_config.root_only = true;
at25->nvmem_config.owner = THIS_MODULE;
at25->nvmem_config.compat = true;
-@@ -474,17 +470,18 @@ static int at25_probe(struct spi_device *spi)
+@@ -474,17 +473,18 @@ static int at25_probe(struct spi_device *spi)
at25->nvmem_config.priv = at25;
at25->nvmem_config.stride = 1;
at25->nvmem_config.word_size = 1;
@@ -65090,6 +98613,19 @@ index ad6ced4546556..86d8fb8c0148b 100644
return -EFAULT;
}
+diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/misc/habanalabs/common/debugfs.c
+index 985f1f3dbd20f..0b46fd22c411b 100644
+--- a/drivers/misc/habanalabs/common/debugfs.c
++++ b/drivers/misc/habanalabs/common/debugfs.c
+@@ -856,6 +856,8 @@ static ssize_t hl_set_power_state(struct file *f, const char __user *buf,
+ pci_set_power_state(hdev->pdev, PCI_D0);
+ pci_restore_state(hdev->pdev);
+ rc = pci_enable_device(hdev->pdev);
++ if (rc < 0)
++ return rc;
+ } else if (value == 2) {
+ pci_save_state(hdev->pdev);
+ pci_disable_device(hdev->pdev);
diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c
index 8d2568c63f19e..a8e683964ab03 100644
--- a/drivers/misc/habanalabs/common/firmware_if.c
@@ -65159,6 +98695,36 @@ index bebebcb163ee8..dfcd87b98ca08 100644
};
/**
+diff --git a/drivers/misc/habanalabs/common/mmu/mmu_v1.c b/drivers/misc/habanalabs/common/mmu/mmu_v1.c
+index 0f536f79dd9c9..e68e9f71c546a 100644
+--- a/drivers/misc/habanalabs/common/mmu/mmu_v1.c
++++ b/drivers/misc/habanalabs/common/mmu/mmu_v1.c
+@@ -467,7 +467,7 @@ static void hl_mmu_v1_fini(struct hl_device *hdev)
+ {
+ /* MMU H/W fini was already done in device hw_fini() */
+
+- if (!ZERO_OR_NULL_PTR(hdev->mmu_priv.hr.mmu_shadow_hop0)) {
++ if (!ZERO_OR_NULL_PTR(hdev->mmu_priv.dr.mmu_shadow_hop0)) {
+ kvfree(hdev->mmu_priv.dr.mmu_shadow_hop0);
+ gen_pool_destroy(hdev->mmu_priv.dr.mmu_pgt_pool);
+
+diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
+index 67c5b452dd356..88b91ad8e5413 100644
+--- a/drivers/misc/kgdbts.c
++++ b/drivers/misc/kgdbts.c
+@@ -1070,10 +1070,10 @@ static int kgdbts_option_setup(char *opt)
+ {
+ if (strlen(opt) >= MAX_CONFIG_LEN) {
+ printk(KERN_ERR "kgdbts: config string too long\n");
+- return -ENOSPC;
++ return 1;
+ }
+ strcpy(config, opt);
+- return 0;
++ return 1;
+ }
+
+ __setup("kgdbts=", kgdbts_option_setup);
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c
index 0f54730c7ed56..98828030b5a4d 100644
--- a/drivers/misc/lattice-ecp3-config.c
@@ -65267,8 +98833,163 @@ index be41843df75bc..cebcca6d6d3ef 100644
wake_up(&cl->wait);
}
+diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
+index 67bb6a25fd0a0..64ce3f830262b 100644
+--- a/drivers/misc/mei/hw-me-regs.h
++++ b/drivers/misc/mei/hw-me-regs.h
+@@ -107,6 +107,7 @@
+ #define MEI_DEV_ID_ADP_S 0x7AE8 /* Alder Lake Point S */
+ #define MEI_DEV_ID_ADP_LP 0x7A60 /* Alder Lake Point LP */
+ #define MEI_DEV_ID_ADP_P 0x51E0 /* Alder Lake Point P */
++#define MEI_DEV_ID_ADP_N 0x54E0 /* Alder Lake Point N */
+
+ /*
+ * MEI HW Section
+@@ -120,6 +121,7 @@
+ #define PCI_CFG_HFS_2 0x48
+ #define PCI_CFG_HFS_3 0x60
+ # define PCI_CFG_HFS_3_FW_SKU_MSK 0x00000070
++# define PCI_CFG_HFS_3_FW_SKU_IGN 0x00000000
+ # define PCI_CFG_HFS_3_FW_SKU_SPS 0x00000060
+ #define PCI_CFG_HFS_4 0x64
+ #define PCI_CFG_HFS_5 0x68
+diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
+index d3a6c07286451..fbc4c95818645 100644
+--- a/drivers/misc/mei/hw-me.c
++++ b/drivers/misc/mei/hw-me.c
+@@ -1405,16 +1405,16 @@ static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev)
+ .quirk_probe = mei_me_fw_type_sps_4
+
+ /**
+- * mei_me_fw_type_sps() - check for sps sku
++ * mei_me_fw_type_sps_ign() - check for sps or ign sku
+ *
+- * Read ME FW Status register to check for SPS Firmware.
+- * The SPS FW is only signaled in pci function 0
++ * Read ME FW Status register to check for SPS or IGN Firmware.
++ * The SPS/IGN FW is only signaled in pci function 0
+ *
+ * @pdev: pci device
+ *
+- * Return: true in case of SPS firmware
++ * Return: true in case of SPS/IGN firmware
+ */
+-static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
++static bool mei_me_fw_type_sps_ign(const struct pci_dev *pdev)
+ {
+ u32 reg;
+ u32 fw_type;
+@@ -1427,14 +1427,15 @@ static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
+
+ dev_dbg(&pdev->dev, "fw type is %d\n", fw_type);
+
+- return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
++ return fw_type == PCI_CFG_HFS_3_FW_SKU_IGN ||
++ fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
+ }
+
+ #define MEI_CFG_KIND_ITOUCH \
+ .kind = "itouch"
+
+-#define MEI_CFG_FW_SPS \
+- .quirk_probe = mei_me_fw_type_sps
++#define MEI_CFG_FW_SPS_IGN \
++ .quirk_probe = mei_me_fw_type_sps_ign
+
+ #define MEI_CFG_FW_VER_SUPP \
+ .fw_ver_supported = 1
+@@ -1535,7 +1536,7 @@ static const struct mei_cfg mei_me_pch12_sps_cfg = {
+ MEI_CFG_PCH8_HFS,
+ MEI_CFG_FW_VER_SUPP,
+ MEI_CFG_DMA_128,
+- MEI_CFG_FW_SPS,
++ MEI_CFG_FW_SPS_IGN,
+ };
+
+ /* Cannon Lake itouch with quirk for SPS 5.0 and newer Firmware exclusion
+@@ -1545,7 +1546,7 @@ static const struct mei_cfg mei_me_pch12_itouch_sps_cfg = {
+ MEI_CFG_KIND_ITOUCH,
+ MEI_CFG_PCH8_HFS,
+ MEI_CFG_FW_VER_SUPP,
+- MEI_CFG_FW_SPS,
++ MEI_CFG_FW_SPS_IGN,
+ };
+
+ /* Tiger Lake and newer devices */
+@@ -1562,7 +1563,7 @@ static const struct mei_cfg mei_me_pch15_sps_cfg = {
+ MEI_CFG_FW_VER_SUPP,
+ MEI_CFG_DMA_128,
+ MEI_CFG_TRC,
+- MEI_CFG_FW_SPS,
++ MEI_CFG_FW_SPS_IGN,
+ };
+
+ /*
+diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
+index a67f4f2d33a93..0706322154cbe 100644
+--- a/drivers/misc/mei/interrupt.c
++++ b/drivers/misc/mei/interrupt.c
+@@ -424,31 +424,26 @@ int mei_irq_read_handler(struct mei_device *dev,
+ list_for_each_entry(cl, &dev->file_list, link) {
+ if (mei_cl_hbm_equal(cl, mei_hdr)) {
+ cl_dbg(dev, cl, "got a message\n");
+- break;
++ ret = mei_cl_irq_read_msg(cl, mei_hdr, meta_hdr, cmpl_list);
++ goto reset_slots;
+ }
+ }
+
+ /* if no recipient cl was found we assume corrupted header */
+- if (&cl->link == &dev->file_list) {
+- /* A message for not connected fixed address clients
+- * should be silently discarded
+- * On power down client may be force cleaned,
+- * silently discard such messages
+- */
+- if (hdr_is_fixed(mei_hdr) ||
+- dev->dev_state == MEI_DEV_POWER_DOWN) {
+- mei_irq_discard_msg(dev, mei_hdr, mei_hdr->length);
+- ret = 0;
+- goto reset_slots;
+- }
+- dev_err(dev->dev, "no destination client found 0x%08X\n",
+- dev->rd_msg_hdr[0]);
+- ret = -EBADMSG;
+- goto end;
++ /* A message for not connected fixed address clients
++ * should be silently discarded
++ * On power down client may be force cleaned,
++ * silently discard such messages
++ */
++ if (hdr_is_fixed(mei_hdr) ||
++ dev->dev_state == MEI_DEV_POWER_DOWN) {
++ mei_irq_discard_msg(dev, mei_hdr, mei_hdr->length);
++ ret = 0;
++ goto reset_slots;
+ }
+-
+- ret = mei_cl_irq_read_msg(cl, mei_hdr, meta_hdr, cmpl_list);
+-
++ dev_err(dev->dev, "no destination client found 0x%08X\n", dev->rd_msg_hdr[0]);
++ ret = -EBADMSG;
++ goto end;
+
+ reset_slots:
+ /* reset the number of slots and header */
+diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
+index 3a45aaf002ac8..a738253dbd056 100644
+--- a/drivers/misc/mei/pci-me.c
++++ b/drivers/misc/mei/pci-me.c
+@@ -113,6 +113,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_S, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_LP, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
++ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)},
+
+ /* required last entry */
+ {0, }
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
-index 431af5e8be2f8..b575d0bfd0d68 100644
+index 431af5e8be2f8..c4fcb1ad6d4d4 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1682,31 +1682,31 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req)
@@ -65317,6 +99038,86 @@ index 431af5e8be2f8..b575d0bfd0d68 100644
if (mrq->cmd->error ||
mrq->data->error ||
+@@ -1880,6 +1880,31 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
+ brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
+ }
+
++static int mmc_spi_err_check(struct mmc_card *card)
++{
++ u32 status = 0;
++ int err;
++
++ /*
++ * SPI does not have a TRAN state we have to wait on, instead the
++ * card is ready again when it no longer holds the line LOW.
++ * We still have to ensure two things here before we know the write
++ * was successful:
++ * 1. The card has not disconnected during busy and we actually read our
++ * own pull-up, thinking it was still connected, so ensure it
++ * still responds.
++ * 2. Check for any error bits, in particular R1_SPI_IDLE to catch a
++ * just reconnected card after being disconnected during busy.
++ */
++ err = __mmc_send_status(card, &status, 0);
++ if (err)
++ return err;
++ /* All R1 and R2 bits of SPI are errors in our case */
++ if (status)
++ return -EIO;
++ return 0;
++}
++
+ static int mmc_blk_busy_cb(void *cb_data, bool *busy)
+ {
+ struct mmc_blk_busy_data *data = cb_data;
+@@ -1903,9 +1928,16 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
+ struct mmc_blk_busy_data cb_data;
+ int err;
+
+- if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
++ if (rq_data_dir(req) == READ)
+ return 0;
+
++ if (mmc_host_is_spi(card->host)) {
++ err = mmc_spi_err_check(card);
++ if (err)
++ mqrq->brq.data.bytes_xfered = 0;
++ return err;
++ }
++
+ cb_data.card = card;
+ cb_data.status = 0;
+ err = __mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, &mmc_blk_busy_cb,
+@@ -2344,6 +2376,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ struct mmc_blk_data *md;
+ int devidx, ret;
+ char cap_str[10];
++ bool cache_enabled = false;
++ bool fua_enabled = false;
+
+ devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);
+ if (devidx < 0) {
+@@ -2425,13 +2459,17 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ md->flags |= MMC_BLK_CMD23;
+ }
+
+- if (mmc_card_mmc(card) &&
+- md->flags & MMC_BLK_CMD23 &&
++ if (md->flags & MMC_BLK_CMD23 &&
+ ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
+ card->ext_csd.rel_sectors)) {
+ md->flags |= MMC_BLK_REL_WR;
+- blk_queue_write_cache(md->queue.queue, true, true);
++ fua_enabled = true;
++ cache_enabled = true;
+ }
++ if (mmc_cache_enabled(card->host))
++ cache_enabled = true;
++
++ blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
+
+ string_get_size((u64)size, 512, STRING_UNITS_2,
+ cap_str, sizeof(cap_str));
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 240c5af793dce..368f10405e132 100644
--- a/drivers/mmc/core/core.c
@@ -65355,7 +99156,7 @@ index 7931a4f0137d2..f5f3f623ea492 100644
void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
-index d4683b1d263fd..cf140f4ec8643 100644
+index d4683b1d263fd..d739e2b631fe8 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -80,9 +80,18 @@ static void mmc_host_classdev_release(struct device *dev)
@@ -65377,6 +99178,98 @@ index d4683b1d263fd..cf140f4ec8643 100644
.pm = MMC_HOST_CLASS_DEV_PM_OPS,
};
+@@ -579,6 +588,16 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+
+ EXPORT_SYMBOL(mmc_alloc_host);
+
++static int mmc_validate_host_caps(struct mmc_host *host)
++{
++ if (host->caps & MMC_CAP_SDIO_IRQ && !host->ops->enable_sdio_irq) {
++ dev_warn(host->parent, "missing ->enable_sdio_irq() ops\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ /**
+ * mmc_add_host - initialise host hardware
+ * @host: mmc host
+@@ -591,8 +610,9 @@ int mmc_add_host(struct mmc_host *host)
+ {
+ int err;
+
+- WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
+- !host->ops->enable_sdio_irq);
++ err = mmc_validate_host_caps(host);
++ if (err)
++ return err;
+
+ err = device_add(&host->class_dev);
+ if (err)
+diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
+index 29e58ffae3797..d805f84507198 100644
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -1381,13 +1381,17 @@ static int mmc_select_hs400es(struct mmc_card *card)
+ goto out_err;
+ }
+
++ /*
++ * Bump to HS timing and frequency. Some cards don't handle
++ * SEND_STATUS reliably at the initial frequency.
++ */
+ mmc_set_timing(host, MMC_TIMING_MMC_HS);
++ mmc_set_bus_speed(card);
++
+ err = mmc_switch_status(card, true);
+ if (err)
+ goto out_err;
+
+- mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+-
+ /* Switch card to DDR with strobe bit */
+ val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+@@ -1445,7 +1449,7 @@ out_err:
+ static int mmc_select_hs200(struct mmc_card *card)
+ {
+ struct mmc_host *host = card->host;
+- unsigned int old_timing, old_signal_voltage;
++ unsigned int old_timing, old_signal_voltage, old_clock;
+ int err = -EINVAL;
+ u8 val;
+
+@@ -1476,8 +1480,17 @@ static int mmc_select_hs200(struct mmc_card *card)
+ false, true, MMC_CMD_RETRIES);
+ if (err)
+ goto err;
++
++ /*
++ * Bump to HS timing and frequency. Some cards don't handle
++ * SEND_STATUS reliably at the initial frequency.
++ * NB: We can't move to full (HS200) speeds until after we've
++ * successfully switched over.
++ */
+ old_timing = host->ios.timing;
++ old_clock = host->ios.clock;
+ mmc_set_timing(host, MMC_TIMING_MMC_HS200);
++ mmc_set_clock(card->host, card->ext_csd.hs_max_dtr);
+
+ /*
+ * For HS200, CRC errors are not a reliable way to know the
+@@ -1490,8 +1503,10 @@ static int mmc_select_hs200(struct mmc_card *card)
+ * mmc_select_timing() assumes timing has not changed if
+ * it is a switch error.
+ */
+- if (err == -EBADMSG)
++ if (err == -EBADMSG) {
++ mmc_set_clock(host, old_clock);
+ mmc_set_timing(host, old_timing);
++ }
+ }
+ err:
+ if (err) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 4646b7a03db6b..44e134fa04afb 100644
--- a/drivers/mmc/core/sd.c
@@ -65425,6 +99318,24 @@ index 68edf7a615be5..5447c47157aa5 100644
mmc_fixup_device(card, sdio_fixup_methods);
if (card->type == MMC_TYPE_SD_COMBO) {
+diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
+index 2a757c88f9d21..80de660027d89 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -1375,8 +1375,12 @@ static int davinci_mmcsd_suspend(struct device *dev)
+ static int davinci_mmcsd_resume(struct device *dev)
+ {
+ struct mmc_davinci_host *host = dev_get_drvdata(dev);
++ int ret;
++
++ ret = clk_enable(host->clk);
++ if (ret)
++ return ret;
+
+- clk_enable(host->clk);
+ mmc_davinci_reset_ctrl(host, 0);
+
+ return 0;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 380f9aa56eb26..1e8f1bb3cad7c 100644
--- a/drivers/mmc/host/dw_mmc.c
@@ -65439,6 +99350,63 @@ index 380f9aa56eb26..1e8f1bb3cad7c 100644
state = STATE_SENDING_DATA;
continue;
}
+diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
+index 8f36536cb1b6d..58ab9d90bc8b9 100644
+--- a/drivers/mmc/host/meson-gx-mmc.c
++++ b/drivers/mmc/host/meson-gx-mmc.c
+@@ -173,6 +173,8 @@ struct meson_host {
+ int irq;
+
+ bool vqmmc_enabled;
++ bool needs_pre_post_req;
++
+ };
+
+ #define CMD_CFG_LENGTH_MASK GENMASK(8, 0)
+@@ -663,6 +665,8 @@ static void meson_mmc_request_done(struct mmc_host *mmc,
+ struct meson_host *host = mmc_priv(mmc);
+
+ host->cmd = NULL;
++ if (host->needs_pre_post_req)
++ meson_mmc_post_req(mmc, mrq, 0);
+ mmc_request_done(host->mmc, mrq);
+ }
+
+@@ -880,7 +884,7 @@ static int meson_mmc_validate_dram_access(struct mmc_host *mmc, struct mmc_data
+ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ {
+ struct meson_host *host = mmc_priv(mmc);
+- bool needs_pre_post_req = mrq->data &&
++ host->needs_pre_post_req = mrq->data &&
+ !(mrq->data->host_cookie & SD_EMMC_PRE_REQ_DONE);
+
+ /*
+@@ -896,22 +900,19 @@ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ }
+ }
+
+- if (needs_pre_post_req) {
++ if (host->needs_pre_post_req) {
+ meson_mmc_get_transfer_mode(mmc, mrq);
+ if (!meson_mmc_desc_chain_mode(mrq->data))
+- needs_pre_post_req = false;
++ host->needs_pre_post_req = false;
+ }
+
+- if (needs_pre_post_req)
++ if (host->needs_pre_post_req)
+ meson_mmc_pre_req(mmc, mrq);
+
+ /* Stop execution */
+ writel(0, host->regs + SD_EMMC_START);
+
+ meson_mmc_start_cmd(mmc, mrq->sbc ?: mrq->cmd);
+-
+- if (needs_pre_post_req)
+- meson_mmc_post_req(mmc, mrq, 0);
+ }
+
+ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
index 7cd9c0ec2fcfe..28aa78aa08f3f 100644
--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c
@@ -65533,9 +99501,29 @@ index f4c8e1a61f537..b431cdd27353b 100644
.remove = mmc_spi_remove,
};
diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
-index fdaa11f92fe6f..a75d3dd34d18c 100644
+index fdaa11f92fe6f..4cceb9bab0361 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
+@@ -62,8 +62,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
+ * excepted the last element which has no constraint on idmasize
+ */
+ for_each_sg(data->sg, sg, data->sg_len - 1, i) {
+- if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) ||
+- !IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) {
++ if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
++ !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
+ dev_err(mmc_dev(host->mmc),
+ "unaligned scatterlist: ofst:%x length:%d\n",
+ data->sg->offset, data->sg->length);
+@@ -71,7 +71,7 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
+ }
+ }
+
+- if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) {
++ if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
+ dev_err(mmc_dev(host->mmc),
+ "unaligned last scatterlist: ofst:%x length:%d\n",
+ data->sg->offset, data->sg->length);
@@ -441,6 +441,8 @@ static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
return -EINVAL;
}
@@ -65849,9 +99837,22 @@ index 947581de78601..8c3655d3be961 100644
ssp->clk = devm_clk_get(&pdev->dev, NULL);
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
-index a4407f391f66a..f5b2684ad8058 100644
+index a4407f391f66a..ae689bf54686f 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
+@@ -382,10 +382,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
+ SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
+
+- /* Set the sampling clock selection range of HS400 mode */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
+- 0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
++ sd_scc_read32(host, priv,
++ SH_MOBILE_SDHI_SCC_DTCNTL));
+
+ /* Avoid bad TAP */
+ if (bad_taps & BIT(priv->tap_set)) {
@@ -673,7 +673,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)
/* Issue CMD19 twice for each tap */
@@ -65861,6 +99862,145 @@ index a4407f391f66a..f5b2684ad8058 100644
/* Set sampling clock position */
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num);
+diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
+index 58cfaffa3c2d8..e1580f78c6b2d 100644
+--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
+@@ -38,10 +38,7 @@ struct realtek_pci_sdmmc {
+ bool double_clk;
+ bool eject;
+ bool initial_mode;
+- int power_state;
+-#define SDMMC_POWER_ON 1
+-#define SDMMC_POWER_OFF 0
+-
++ int prev_power_state;
+ int sg_count;
+ s32 cookie;
+ int cookie_sg_count;
+@@ -905,7 +902,7 @@ static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
+ return err;
+ }
+
+-static int sd_power_on(struct realtek_pci_sdmmc *host)
++static int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode)
+ {
+ struct rtsx_pcr *pcr = host->pcr;
+ struct mmc_host *mmc = host->mmc;
+@@ -913,9 +910,14 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
+ u32 val;
+ u8 test_mode;
+
+- if (host->power_state == SDMMC_POWER_ON)
++ if (host->prev_power_state == MMC_POWER_ON)
+ return 0;
+
++ if (host->prev_power_state == MMC_POWER_UP) {
++ rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0);
++ goto finish;
++ }
++
+ msleep(100);
+
+ rtsx_pci_init_cmd(pcr);
+@@ -936,10 +938,15 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
+ if (err < 0)
+ return err;
+
++ mdelay(1);
++
+ err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+ if (err < 0)
+ return err;
+
++ /* send at least 74 clocks */
++ rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
++
+ if (PCI_PID(pcr) == PID_5261) {
+ /*
+ * If test mode is set switch to SD Express mandatorily,
+@@ -964,7 +971,8 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
+ }
+ }
+
+- host->power_state = SDMMC_POWER_ON;
++finish:
++ host->prev_power_state = power_mode;
+ return 0;
+ }
+
+@@ -973,7 +981,7 @@ static int sd_power_off(struct realtek_pci_sdmmc *host)
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+- host->power_state = SDMMC_POWER_OFF;
++ host->prev_power_state = MMC_POWER_OFF;
+
+ rtsx_pci_init_cmd(pcr);
+
+@@ -999,7 +1007,7 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
+ if (power_mode == MMC_POWER_OFF)
+ err = sd_power_off(host);
+ else
+- err = sd_power_on(host);
++ err = sd_power_on(host, power_mode);
+
+ return err;
+ }
+@@ -1482,10 +1490,11 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
+
+ host = mmc_priv(mmc);
+ host->pcr = pcr;
++ mmc->ios.power_delay_ms = 5;
+ host->mmc = mmc;
+ host->pdev = pdev;
+ host->cookie = -1;
+- host->power_state = SDMMC_POWER_OFF;
++ host->prev_power_state = MMC_POWER_OFF;
+ INIT_WORK(&host->work, sd_request);
+ platform_set_drvdata(pdev, host);
+ pcr->slots[RTSX_SD_CARD].p_dev = pdev;
+@@ -1495,12 +1504,12 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
+
+ realtek_init_host(host);
+
+- if (pcr->rtd3_en) {
+- pm_runtime_set_autosuspend_delay(&pdev->dev, 5000);
+- pm_runtime_use_autosuspend(&pdev->dev);
+- pm_runtime_enable(&pdev->dev);
+- }
+-
++ pm_runtime_no_callbacks(&pdev->dev);
++ pm_runtime_set_active(&pdev->dev);
++ pm_runtime_enable(&pdev->dev);
++ pm_runtime_set_autosuspend_delay(&pdev->dev, 200);
++ pm_runtime_mark_last_busy(&pdev->dev);
++ pm_runtime_use_autosuspend(&pdev->dev);
+
+ mmc_add_host(mmc);
+
+@@ -1521,11 +1530,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
+ pcr->slots[RTSX_SD_CARD].card_event = NULL;
+ mmc = host->mmc;
+
+- if (pcr->rtd3_en) {
+- pm_runtime_dont_use_autosuspend(&pdev->dev);
+- pm_runtime_disable(&pdev->dev);
+- }
+-
+ cancel_work_sync(&host->work);
+
+ mutex_lock(&host->host_mutex);
+@@ -1548,6 +1552,9 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
+
+ flush_work(&host->work);
+
++ pm_runtime_dont_use_autosuspend(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
+ mmc_free_host(mmc);
+
+ dev_dbg(&(pdev->dev),
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index e658f01742420..60f19369de845 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -65881,6 +100021,73 @@ index e658f01742420..60f19369de845 100644
| ESDHC_FLAG_STATE_LOST_IN_LPMODE,
};
+diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
+index 50c71e0ba5e4e..ff9f5b63c337e 100644
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -17,6 +17,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/interconnect.h>
+ #include <linux/pinctrl/consumer.h>
++#include <linux/reset.h>
+
+ #include "sdhci-pltfm.h"
+ #include "cqhci.h"
+@@ -2482,6 +2483,43 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
+ of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config);
+ }
+
++static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
++{
++ struct reset_control *reset;
++ int ret = 0;
++
++ reset = reset_control_get_optional_exclusive(dev, NULL);
++ if (IS_ERR(reset))
++ return dev_err_probe(dev, PTR_ERR(reset),
++ "unable to acquire core_reset\n");
++
++ if (!reset)
++ return ret;
++
++ ret = reset_control_assert(reset);
++ if (ret) {
++ reset_control_put(reset);
++ return dev_err_probe(dev, ret, "core_reset assert failed\n");
++ }
++
++ /*
++ * The hardware requirement for delay between assert/deassert
++ * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to
++ * ~125us (4/32768). To be on the safe side add 200us delay.
++ */
++ usleep_range(200, 210);
++
++ ret = reset_control_deassert(reset);
++ if (ret) {
++ reset_control_put(reset);
++ return dev_err_probe(dev, ret, "core_reset deassert failed\n");
++ }
++
++ usleep_range(200, 210);
++ reset_control_put(reset);
++
++ return ret;
++}
+
+ static int sdhci_msm_probe(struct platform_device *pdev)
+ {
+@@ -2529,6 +2567,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
+
+ msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+
++ ret = sdhci_msm_gcc_reset(&pdev->dev, host);
++ if (ret)
++ goto pltfm_free;
++
+ /* Setup SDCC bus voter clock. */
+ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
+ if (!IS_ERR(msm_host->bus_clk)) {
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index a593b1fbd69e5..0f3658b36513c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
@@ -66082,6 +100289,27 @@ index a5001875876b9..9762ffab2e236 100644
static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
+index 666cee4c7f7c6..08e838400b526 100644
+--- a/drivers/mmc/host/sdhci-xenon.c
++++ b/drivers/mmc/host/sdhci-xenon.c
+@@ -241,16 +241,6 @@ static void xenon_voltage_switch(struct sdhci_host *host)
+ {
+ /* Wait for 5ms after set 1.8V signal enable bit */
+ usleep_range(5000, 5500);
+-
+- /*
+- * For some reason the controller's Host Control2 register reports
+- * the bit representing 1.8V signaling as 0 when read after it was
+- * written as 1. Subsequent read reports 1.
+- *
+- * Since this may cause some issues, do an empty read of the Host
+- * Control2 register here to circumvent this.
+- */
+- sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ }
+
+ static unsigned int xenon_get_max_clock(struct sdhci_host *host)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2d80a04e11d87..7728f26adb19f 100644
--- a/drivers/mmc/host/sdhci.c
@@ -66152,6 +100380,67 @@ index e8d04e42a5afd..6c689be3e48f6 100644
void *adma_table; /* ADMA descriptor table */
void *align_buffer; /* Bounce buffer */
+diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
+index f654afbe8e83c..b4891bb266485 100644
+--- a/drivers/mmc/host/sdhci_am654.c
++++ b/drivers/mmc/host/sdhci_am654.c
+@@ -514,26 +514,6 @@ static const struct sdhci_am654_driver_data sdhci_j721e_4bit_drvdata = {
+ .flags = IOMUX_PRESENT,
+ };
+
+-static const struct sdhci_pltfm_data sdhci_am64_8bit_pdata = {
+- .ops = &sdhci_j721e_8bit_ops,
+- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+-};
+-
+-static const struct sdhci_am654_driver_data sdhci_am64_8bit_drvdata = {
+- .pdata = &sdhci_am64_8bit_pdata,
+- .flags = DLL_PRESENT | DLL_CALIB,
+-};
+-
+-static const struct sdhci_pltfm_data sdhci_am64_4bit_pdata = {
+- .ops = &sdhci_j721e_4bit_ops,
+- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+-};
+-
+-static const struct sdhci_am654_driver_data sdhci_am64_4bit_drvdata = {
+- .pdata = &sdhci_am64_4bit_pdata,
+- .flags = IOMUX_PRESENT,
+-};
+-
+ static const struct soc_device_attribute sdhci_am654_devices[] = {
+ { .family = "AM65X",
+ .revision = "SR1.0",
+@@ -759,11 +739,11 @@ static const struct of_device_id sdhci_am654_of_match[] = {
+ },
+ {
+ .compatible = "ti,am64-sdhci-8bit",
+- .data = &sdhci_am64_8bit_drvdata,
++ .data = &sdhci_j721e_8bit_drvdata,
+ },
+ {
+ .compatible = "ti,am64-sdhci-4bit",
+- .data = &sdhci_am64_4bit_drvdata,
++ .data = &sdhci_j721e_4bit_drvdata,
+ },
+ { /* sentinel */ }
+ };
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index 2702736a1c57d..ce6cb8be654ef 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -377,8 +377,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
+ pdes[i].buf_addr_ptr1 =
+ cpu_to_le32(sg_dma_address(&data->sg[i]) >>
+ host->cfg->idma_des_shift);
+- pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >>
+- host->cfg->idma_des_shift);
++ pdes[i].buf_addr_ptr2 =
++ cpu_to_le32(next_desc >>
++ host->cfg->idma_des_shift);
+ }
+
+ pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD);
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index e2affa52ef469..a5850d83908be 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
@@ -66234,6 +100523,66 @@ index aef14990e5f7c..19726ebd973d0 100644
bool "LITTLE_ENDIAN_BYTE"
endchoice
+diff --git a/drivers/mtd/devices/mchp23k256.c b/drivers/mtd/devices/mchp23k256.c
+index 77c872fd3d839..7d188cdff6a26 100644
+--- a/drivers/mtd/devices/mchp23k256.c
++++ b/drivers/mtd/devices/mchp23k256.c
+@@ -229,6 +229,19 @@ static const struct of_device_id mchp23k256_of_table[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mchp23k256_of_table);
+
++static const struct spi_device_id mchp23k256_spi_ids[] = {
++ {
++ .name = "mchp23k256",
++ .driver_data = (kernel_ulong_t)&mchp23k256_caps,
++ },
++ {
++ .name = "mchp23lcv1024",
++ .driver_data = (kernel_ulong_t)&mchp23lcv1024_caps,
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(spi, mchp23k256_spi_ids);
++
+ static struct spi_driver mchp23k256_driver = {
+ .driver = {
+ .name = "mchp23k256",
+@@ -236,6 +249,7 @@ static struct spi_driver mchp23k256_driver = {
+ },
+ .probe = mchp23k256_probe,
+ .remove = mchp23k256_remove,
++ .id_table = mchp23k256_spi_ids,
+ };
+
+ module_spi_driver(mchp23k256_driver);
+diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c
+index 99400d0fb8c1e..fbd6b6bf908e5 100644
+--- a/drivers/mtd/devices/mchp48l640.c
++++ b/drivers/mtd/devices/mchp48l640.c
+@@ -357,6 +357,15 @@ static const struct of_device_id mchp48l640_of_table[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mchp48l640_of_table);
+
++static const struct spi_device_id mchp48l640_spi_ids[] = {
++ {
++ .name = "48l640",
++ .driver_data = (kernel_ulong_t)&mchp48l640_caps,
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(spi, mchp48l640_spi_ids);
++
+ static struct spi_driver mchp48l640_driver = {
+ .driver = {
+ .name = "mchp48l640",
+@@ -364,6 +373,7 @@ static struct spi_driver mchp48l640_driver = {
+ },
+ .probe = mchp48l640_probe,
+ .remove = mchp48l640_remove,
++ .id_table = mchp48l640_spi_ids,
+ };
+
+ module_spi_driver(mchp48l640_driver);
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 9802e265fca80..2b317ed6c103f 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
@@ -66395,6 +100744,24 @@ index 04af12b66110c..357661b62c94d 100644
free_partition(mtd);
return 0;
+diff --git a/drivers/mtd/nand/onenand/generic.c b/drivers/mtd/nand/onenand/generic.c
+index 8b6f4da5d7201..a4b8b65fe15f5 100644
+--- a/drivers/mtd/nand/onenand/generic.c
++++ b/drivers/mtd/nand/onenand/generic.c
+@@ -53,7 +53,12 @@ static int generic_onenand_probe(struct platform_device *pdev)
+ }
+
+ info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
+- info->onenand.irq = platform_get_irq(pdev, 0);
++
++ err = platform_get_irq(pdev, 0);
++ if (err < 0)
++ goto out_iounmap;
++
++ info->onenand.irq = err;
+
+ info->mtd.dev.parent = &pdev->dev;
+ info->mtd.priv = &info->onenand;
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index ff1697f899ba6..13de39aa3288f 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
@@ -66451,6 +100818,46 @@ index 9cbcc698c64d8..53bd10738418b 100644
} else {
sdr = nand_get_sdr_timings(conf);
if (IS_ERR(sdr))
+diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
+index f3276ee9e4fe7..ddd93bc38ea6c 100644
+--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
++++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
+@@ -2060,13 +2060,15 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
+ nc->mck = of_clk_get(dev->parent->of_node, 0);
+ if (IS_ERR(nc->mck)) {
+ dev_err(dev, "Failed to retrieve MCK clk\n");
+- return PTR_ERR(nc->mck);
++ ret = PTR_ERR(nc->mck);
++ goto out_release_dma;
+ }
+
+ np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
+ if (!np) {
+ dev_err(dev, "Missing or invalid atmel,smc property\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto out_release_dma;
+ }
+
+ nc->smc = syscon_node_to_regmap(np);
+@@ -2074,10 +2076,16 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
+ if (IS_ERR(nc->smc)) {
+ ret = PTR_ERR(nc->smc);
+ dev_err(dev, "Could not get SMC regmap (err = %d)\n", ret);
+- return ret;
++ goto out_release_dma;
+ }
+
+ return 0;
++
++out_release_dma:
++ if (nc->dmac)
++ dma_release_channel(nc->dmac);
++
++ return ret;
+ }
+
+ static int
diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
index 99116896cfd6c..5aa3a06d740c7 100644
--- a/drivers/mtd/nand/raw/au1550nd.c
@@ -66710,10 +101117,27 @@ index fb7a086de35e5..fdf073d2e1b6c 100644
if (ret)
goto err_wp;
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
-index 4d08e4ab5c1b6..668d69fe4cf27 100644
+index 4d08e4ab5c1b6..b72b387c08ef7 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
-@@ -713,14 +713,32 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+@@ -648,6 +648,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+ const struct nand_sdr_timings *sdr)
+ {
+ struct gpmi_nfc_hardware_timing *hw = &this->hw;
++ struct resources *r = &this->resources;
+ unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
+ unsigned int period_ps, reference_period_ps;
+ unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
+@@ -671,6 +672,8 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+ wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+ }
+
++ hw->clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
++
+ /* SDR core timings are given in picoseconds */
+ period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
+
+@@ -713,14 +716,32 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
(use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
}
@@ -66725,15 +101149,15 @@ index 4d08e4ab5c1b6..668d69fe4cf27 100644
void __iomem *gpmi_regs = r->gpmi_regs;
unsigned int dll_wait_time_us;
+ int ret;
-
-- clk_set_rate(r->clock[0], hw->clk_rate);
++
+ /* Clock dividers do NOT guarantee a clean clock signal on its output
+ * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8,
+ * all clock dividers provide these guarantee.
+ */
+ if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this))
+ clk_disable_unprepare(r->clock[0]);
-+
+
+- clk_set_rate(r->clock[0], hw->clk_rate);
+ ret = clk_set_rate(r->clock[0], hw->clk_rate);
+ if (ret) {
+ dev_err(this->dev, "cannot set clock rate to %lu Hz: %d\n", hw->clk_rate, ret);
@@ -66748,7 +101172,7 @@ index 4d08e4ab5c1b6..668d69fe4cf27 100644
writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
-@@ -739,6 +757,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
+@@ -739,6 +760,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
/* Wait for the DLL to settle. */
udelay(dll_wait_time_us);
@@ -66757,7 +101181,7 @@ index 4d08e4ab5c1b6..668d69fe4cf27 100644
}
static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
-@@ -1034,15 +1054,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
+@@ -1034,15 +1057,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
r->clock[i] = clk;
}
@@ -66773,7 +101197,7 @@ index 4d08e4ab5c1b6..668d69fe4cf27 100644
return 0;
err_clock:
-@@ -2280,7 +2291,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
+@@ -2280,7 +2294,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
*/
if (this->hw.must_apply_timings) {
this->hw.must_apply_timings = false;
@@ -66784,7 +101208,7 @@ index 4d08e4ab5c1b6..668d69fe4cf27 100644
}
dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
-@@ -2409,6 +2422,7 @@ unmap:
+@@ -2409,6 +2425,7 @@ unmap:
this->bch = false;
@@ -66896,11 +101320,109 @@ index bcd4a556c959c..5b9271b9c3265 100644
/* Detect NAND chips */
retval = nand_scan(chip, be32_to_cpup(chips_no));
if (retval) {
+diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
+index c437d97debb8a..ec9d1fb07006f 100644
+--- a/drivers/mtd/nand/raw/mtk_ecc.c
++++ b/drivers/mtd/nand/raw/mtk_ecc.c
+@@ -43,6 +43,7 @@
+
+ struct mtk_ecc_caps {
+ u32 err_mask;
++ u32 err_shift;
+ const u8 *ecc_strength;
+ const u32 *ecc_regs;
+ u8 num_ecc_strength;
+@@ -76,7 +77,7 @@ static const u8 ecc_strength_mt2712[] = {
+ };
+
+ static const u8 ecc_strength_mt7622[] = {
+- 4, 6, 8, 10, 12, 14, 16
++ 4, 6, 8, 10, 12
+ };
+
+ enum mtk_ecc_regs {
+@@ -221,7 +222,7 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
+ for (i = 0; i < sectors; i++) {
+ offset = (i >> 2) << 2;
+ err = readl(ecc->regs + ECC_DECENUM0 + offset);
+- err = err >> ((i % 4) * 8);
++ err = err >> ((i % 4) * ecc->caps->err_shift);
+ err &= ecc->caps->err_mask;
+ if (err == ecc->caps->err_mask) {
+ /* uncorrectable errors */
+@@ -449,6 +450,7 @@ EXPORT_SYMBOL(mtk_ecc_get_parity_bits);
+
+ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
+ .err_mask = 0x3f,
++ .err_shift = 8,
+ .ecc_strength = ecc_strength_mt2701,
+ .ecc_regs = mt2701_ecc_regs,
+ .num_ecc_strength = 20,
+@@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
+
+ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
+ .err_mask = 0x7f,
++ .err_shift = 8,
+ .ecc_strength = ecc_strength_mt2712,
+ .ecc_regs = mt2712_ecc_regs,
+ .num_ecc_strength = 23,
+@@ -468,10 +471,11 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
+ };
+
+ static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = {
+- .err_mask = 0x3f,
++ .err_mask = 0x1f,
++ .err_shift = 5,
+ .ecc_strength = ecc_strength_mt7622,
+ .ecc_regs = mt7622_ecc_regs,
+- .num_ecc_strength = 7,
++ .num_ecc_strength = 5,
+ .ecc_mode_shift = 4,
+ .parity_bits = 13,
+ .pg_irq_sel = 0,
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
-index 3d6c6e8805207..d5a2110eb38ed 100644
+index 3d6c6e8805207..881e768f636f8 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
-@@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
+@@ -335,16 +335,19 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
+ *
+ * Return: -EBUSY if the chip has been suspended, 0 otherwise
+ */
+-static int nand_get_device(struct nand_chip *chip)
++static void nand_get_device(struct nand_chip *chip)
+ {
+- mutex_lock(&chip->lock);
+- if (chip->suspended) {
++ /* Wait until the device is resumed. */
++ while (1) {
++ mutex_lock(&chip->lock);
++ if (!chip->suspended) {
++ mutex_lock(&chip->controller->lock);
++ return;
++ }
+ mutex_unlock(&chip->lock);
+- return -EBUSY;
+- }
+- mutex_lock(&chip->controller->lock);
+
+- return 0;
++ wait_event(chip->resume_wq, !chip->suspended);
++ }
+ }
+
+ /**
+@@ -573,9 +576,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
+ nand_erase_nand(chip, &einfo, 0);
+
+ /* Write bad block marker to OOB */
+- ret = nand_get_device(chip);
+- if (ret)
+- return ret;
++ nand_get_device(chip);
+
+ ret = nand_markbad_bbm(chip, ofs);
+ nand_release_device(chip);
+@@ -926,7 +927,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
struct nand_sdr_timings *spec_timings)
{
const struct nand_controller_ops *ops = chip->controller->ops;
@@ -66909,7 +101431,7 @@ index 3d6c6e8805207..d5a2110eb38ed 100644
iface->type = NAND_SDR_IFACE;
-@@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip,
+@@ -977,7 +978,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip,
struct nand_nvddr_timings *spec_timings)
{
const struct nand_controller_ops *ops = chip->controller->ops;
@@ -66918,7 +101440,7 @@ index 3d6c6e8805207..d5a2110eb38ed 100644
iface->type = NAND_NVDDR_IFACE;
-@@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
+@@ -1837,7 +1838,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
NAND_OP_CMD(NAND_CMD_ERASE1, 0),
NAND_OP_ADDR(2, addrs, 0),
NAND_OP_CMD(NAND_CMD_ERASE2,
@@ -66927,7 +101449,7 @@ index 3d6c6e8805207..d5a2110eb38ed 100644
NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max),
0),
};
-@@ -3160,6 +3160,73 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
+@@ -3160,6 +3161,73 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
return max_bitflips;
}
@@ -67001,6 +101523,81 @@ index 3d6c6e8805207..d5a2110eb38ed 100644
/**
* nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
* @chip: nand chip info structure
+@@ -3756,9 +3824,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
+ ops->mode != MTD_OPS_RAW)
+ return -ENOTSUPP;
+
+- ret = nand_get_device(chip);
+- if (ret)
+- return ret;
++ nand_get_device(chip);
+
+ if (!ops->datbuf)
+ ret = nand_do_read_oob(chip, from, ops);
+@@ -4345,13 +4411,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+ {
+ struct nand_chip *chip = mtd_to_nand(mtd);
+- int ret;
++ int ret = 0;
+
+ ops->retlen = 0;
+
+- ret = nand_get_device(chip);
+- if (ret)
+- return ret;
++ nand_get_device(chip);
+
+ switch (ops->mode) {
+ case MTD_OPS_PLACE_OOB:
+@@ -4411,9 +4475,7 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
+ return -EIO;
+
+ /* Grab the lock and see if the device is available */
+- ret = nand_get_device(chip);
+- if (ret)
+- return ret;
++ nand_get_device(chip);
+
+ /* Shift to get first page */
+ page = (int)(instr->addr >> chip->page_shift);
+@@ -4500,7 +4562,7 @@ static void nand_sync(struct mtd_info *mtd)
+ pr_debug("%s: called\n", __func__);
+
+ /* Grab the lock and see if the device is available */
+- WARN_ON(nand_get_device(chip));
++ nand_get_device(chip);
+ /* Release it and go back */
+ nand_release_device(chip);
+ }
+@@ -4517,9 +4579,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
+ int ret;
+
+ /* Select the NAND device */
+- ret = nand_get_device(chip);
+- if (ret)
+- return ret;
++ nand_get_device(chip);
+
+ nand_select_target(chip, chipnr);
+
+@@ -4590,6 +4650,8 @@ static void nand_resume(struct mtd_info *mtd)
+ __func__);
+ }
+ mutex_unlock(&chip->lock);
++
++ wake_up_all(&chip->resume_wq);
+ }
+
+ /**
+@@ -5367,6 +5429,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
+ chip->cur_cs = -1;
+
+ mutex_init(&chip->lock);
++ init_waitqueue_head(&chip->resume_wq);
+
+ /* Enforce the right timings for reset/detection */
+ chip->current_interface_config = nand_get_reset_interface_config();
diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
index 66211c9311d2f..2c87c7d892058 100644
--- a/drivers/mtd/nand/raw/orion_nand.c
@@ -67061,6 +101658,19 @@ index 789f33312c15f..c176036453ed9 100644
/* Scan to find existence of the device */
err = nand_scan(chip, 1);
if (err)
+diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c
+index 8a91e069ee2e9..3c6f6aff649f8 100644
+--- a/drivers/mtd/nand/raw/pl35x-nand-controller.c
++++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c
+@@ -1062,7 +1062,7 @@ static int pl35x_nand_chip_init(struct pl35x_nandc *nfc,
+ chip->controller = &nfc->controller;
+ mtd = nand_to_mtd(chip);
+ mtd->dev.parent = nfc->dev;
+- nand_set_flash_node(chip, nfc->dev->of_node);
++ nand_set_flash_node(chip, np);
+ if (!mtd->name) {
+ mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
+ "%s", PL35X_NANDC_DRIVER_NAME);
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index 7711e1020c21c..0ee08c42cc35b 100644
--- a/drivers/mtd/nand/raw/plat_nand.c
@@ -67092,7 +101702,7 @@ index 7711e1020c21c..0ee08c42cc35b 100644
err = nand_scan(&data->chip, pdata->chip.nr_chips);
if (err)
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
-index 04e6f7b267064..0f41a9a421575 100644
+index 04e6f7b267064..e972bee60e7c8 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2,7 +2,6 @@
@@ -67103,7 +101713,49 @@ index 04e6f7b267064..0f41a9a421575 100644
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/bitops.h>
-@@ -3063,10 +3062,6 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+@@ -2642,10 +2641,23 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
+ ecc->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
+
+ mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
++ /* Free the initially allocated BAM transaction for reading the ONFI params */
++ if (nandc->props->is_bam)
++ free_bam_transaction(nandc);
+
+ nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
+ cwperpage);
+
++ /* Now allocate the BAM transaction based on updated max_cwperpage */
++ if (nandc->props->is_bam) {
++ nandc->bam_txn = alloc_bam_transaction(nandc);
++ if (!nandc->bam_txn) {
++ dev_err(nandc->dev,
++ "failed to allocate bam transaction\n");
++ return -ENOMEM;
++ }
++ }
++
+ /*
+ * DATA_UD_BYTES varies based on whether the read/write command protects
+ * spare data with ECC too. We protect spare data by default, so we set
+@@ -2946,17 +2958,6 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
+ if (ret)
+ return ret;
+
+- if (nandc->props->is_bam) {
+- free_bam_transaction(nandc);
+- nandc->bam_txn = alloc_bam_transaction(nandc);
+- if (!nandc->bam_txn) {
+- dev_err(nandc->dev,
+- "failed to allocate bam transaction\n");
+- nand_cleanup(chip);
+- return -ENOMEM;
+- }
+- }
+-
+ ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
+ if (ret)
+ nand_cleanup(chip);
+@@ -3063,10 +3064,6 @@ static int qcom_nandc_probe(struct platform_device *pdev)
if (dma_mapping_error(dev, nandc->base_dma))
return -ENXIO;
@@ -67114,7 +101766,7 @@ index 04e6f7b267064..0f41a9a421575 100644
ret = clk_prepare_enable(nandc->core_clk);
if (ret)
goto err_core_clk;
-@@ -3075,6 +3070,10 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+@@ -3075,6 +3072,10 @@ static int qcom_nandc_probe(struct platform_device *pdev)
if (ret)
goto err_aon_clk;
@@ -67125,7 +101777,7 @@ index 04e6f7b267064..0f41a9a421575 100644
ret = qcom_nandc_setup(nandc);
if (ret)
goto err_setup;
-@@ -3086,15 +3085,14 @@ static int qcom_nandc_probe(struct platform_device *pdev)
+@@ -3086,15 +3087,14 @@ static int qcom_nandc_probe(struct platform_device *pdev)
return 0;
err_setup:
@@ -67143,6 +101795,64 @@ index 04e6f7b267064..0f41a9a421575 100644
return ret;
}
+diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
+index 13df4bdf792af..8f89e2d3d817f 100644
+--- a/drivers/mtd/nand/raw/sh_flctl.c
++++ b/drivers/mtd/nand/raw/sh_flctl.c
+@@ -384,7 +384,8 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
+ dma_addr_t dma_addr;
+ dma_cookie_t cookie;
+ uint32_t reg;
+- int ret;
++ int ret = 0;
++ unsigned long time_left;
+
+ if (dir == DMA_FROM_DEVICE) {
+ chan = flctl->chan_fifo0_rx;
+@@ -425,13 +426,14 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
+ goto out;
+ }
+
+- ret =
++ time_left =
+ wait_for_completion_timeout(&flctl->dma_complete,
+ msecs_to_jiffies(3000));
+
+- if (ret <= 0) {
++ if (time_left == 0) {
+ dmaengine_terminate_all(chan);
+ dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
++ ret = -ETIMEDOUT;
+ }
+
+ out:
+@@ -441,7 +443,7 @@ out:
+
+ dma_unmap_single(chan->device->dev, dma_addr, len, dir);
+
+- /* ret > 0 is success */
++ /* ret == 0 is success */
+ return ret;
+ }
+
+@@ -465,7 +467,7 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+
+ /* initiate DMA transfer */
+ if (flctl->chan_fifo0_rx && rlen >= 32 &&
+- flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0)
++ !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE))
+ goto convert; /* DMA success */
+
+ /* do polling transfer */
+@@ -524,7 +526,7 @@ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen,
+
+ /* initiate DMA transfer */
+ if (flctl->chan_fifo0_tx && rlen >= 32 &&
+- flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0)
++ !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE))
+ return; /* DMA success */
+
+ /* do polling transfer */
diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
index 70f8305c9b6e1..fb39cc7ebce03 100644
--- a/drivers/mtd/nand/raw/socrates_nand.c
@@ -67319,11 +102029,164 @@ index 1138bdbf41998..75dd13a390404 100644
nor->mtd.erasesize = 8 * nor->page_size;
} else {
/* Flash in Default addressing mode */
+diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
+index a7e3eb9befb62..a32050fecabf3 100644
+--- a/drivers/mtd/ubi/build.c
++++ b/drivers/mtd/ubi/build.c
+@@ -351,9 +351,6 @@ static ssize_t dev_attribute_show(struct device *dev,
+ * we still can use 'ubi->ubi_num'.
+ */
+ ubi = container_of(dev, struct ubi_device, dev);
+- ubi = ubi_get_device(ubi->ubi_num);
+- if (!ubi)
+- return -ENODEV;
+
+ if (attr == &dev_eraseblock_size)
+ ret = sprintf(buf, "%d\n", ubi->leb_size);
+@@ -382,7 +379,6 @@ static ssize_t dev_attribute_show(struct device *dev,
+ else
+ ret = -EINVAL;
+
+- ubi_put_device(ubi);
+ return ret;
+ }
+
+@@ -979,9 +975,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
+ goto out_detach;
+ }
+
+- /* Make device "available" before it becomes accessible via sysfs */
+- ubi_devices[ubi_num] = ubi;
+-
+ err = uif_init(ubi);
+ if (err)
+ goto out_detach;
+@@ -1026,6 +1019,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
+ wake_up_process(ubi->bgt_thread);
+ spin_unlock(&ubi->wl_lock);
+
++ ubi_devices[ubi_num] = ubi;
+ ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
+ return ubi_num;
+
+@@ -1034,7 +1028,6 @@ out_debugfs:
+ out_uif:
+ uif_close(ubi);
+ out_detach:
+- ubi_devices[ubi_num] = NULL;
+ ubi_wl_close(ubi);
+ ubi_free_all_volumes(ubi);
+ vfree(ubi->vtbl);
+diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
+index 022af59906aa9..6b5f1ffd961b9 100644
+--- a/drivers/mtd/ubi/fastmap.c
++++ b/drivers/mtd/ubi/fastmap.c
+@@ -468,7 +468,9 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
+ if (err == UBI_IO_FF_BITFLIPS)
+ scrub = 1;
+
+- add_aeb(ai, free, pnum, ec, scrub);
++ ret = add_aeb(ai, free, pnum, ec, scrub);
++ if (ret)
++ goto out;
+ continue;
+ } else if (err == 0 || err == UBI_IO_BITFLIPS) {
+ dbg_bld("Found non empty PEB:%i in pool", pnum);
+@@ -638,8 +640,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+- add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
+- be32_to_cpu(fmec->ec), 0);
++ ret = add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
++ be32_to_cpu(fmec->ec), 0);
++ if (ret)
++ goto fail;
+ }
+
+ /* read EC values from used list */
+@@ -649,8 +653,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+- add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+- be32_to_cpu(fmec->ec), 0);
++ ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
++ be32_to_cpu(fmec->ec), 0);
++ if (ret)
++ goto fail;
+ }
+
+ /* read EC values from scrub list */
+@@ -660,8 +666,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+- add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+- be32_to_cpu(fmec->ec), 1);
++ ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
++ be32_to_cpu(fmec->ec), 1);
++ if (ret)
++ goto fail;
+ }
+
+ /* read EC values from erase list */
+@@ -671,8 +679,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+- add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
+- be32_to_cpu(fmec->ec), 1);
++ ret = add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
++ be32_to_cpu(fmec->ec), 1);
++ if (ret)
++ goto fail;
+ }
+
+ ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
+diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
+index 139ee132bfbcf..1bc7b3a056046 100644
+--- a/drivers/mtd/ubi/vmt.c
++++ b/drivers/mtd/ubi/vmt.c
+@@ -56,16 +56,11 @@ static ssize_t vol_attribute_show(struct device *dev,
+ {
+ int ret;
+ struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
+- struct ubi_device *ubi;
+-
+- ubi = ubi_get_device(vol->ubi->ubi_num);
+- if (!ubi)
+- return -ENODEV;
++ struct ubi_device *ubi = vol->ubi;
+
+ spin_lock(&ubi->volumes_lock);
+ if (!ubi->volumes[vol->vol_id]) {
+ spin_unlock(&ubi->volumes_lock);
+- ubi_put_device(ubi);
+ return -ENODEV;
+ }
+ /* Take a reference to prevent volume removal */
+@@ -103,7 +98,6 @@ static ssize_t vol_attribute_show(struct device *dev,
+ vol->ref_count -= 1;
+ ubi_assert(vol->ref_count >= 0);
+ spin_unlock(&ubi->volumes_lock);
+- ubi_put_device(ubi);
+ return ret;
+ }
+
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index f37b1c56f7c43..dd335ae1122b0 100644
+index f37b1c56f7c43..44a7d36446c52 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
-@@ -150,7 +150,7 @@ config NET_FC
+@@ -81,7 +81,6 @@ config WIREGUARD
+ select CRYPTO
+ select CRYPTO_LIB_CURVE25519
+ select CRYPTO_LIB_CHACHA20POLY1305
+- select CRYPTO_LIB_BLAKE2S
+ select CRYPTO_CHACHA20_X86_64 if X86 && 64BIT
+ select CRYPTO_POLY1305_X86_64 if X86 && 64BIT
+ select CRYPTO_BLAKE2S_X86 if X86 && 64BIT
+@@ -150,7 +149,7 @@ config NET_FC
config IFB
tristate "Intermediate Functional Block support"
@@ -67346,6 +102209,63 @@ index 3c8f665c15580..28dccbc0e8d8f 100644
priv->ci = ci;
mm = &ci->misc_map;
+diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
+index 54e321a695ce9..98c915943f323 100644
+--- a/drivers/net/bareudp.c
++++ b/drivers/net/bareudp.c
+@@ -141,14 +141,14 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+ skb_reset_network_header(skb);
+ skb_reset_mac_header(skb);
+
+- if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET)
++ if (!ipv6_mod_enabled() || family == AF_INET)
+ err = IP_ECN_decapsulate(oiph, skb);
+ else
+ err = IP6_ECN_decapsulate(oiph, skb);
+
+ if (unlikely(err)) {
+ if (log_ecn_error) {
+- if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET)
++ if (!ipv6_mod_enabled() || family == AF_INET)
+ net_info_ratelimited("non-ECT from %pI4 "
+ "with TOS=%#x\n",
+ &((struct iphdr *)oiph)->saddr,
+@@ -214,11 +214,12 @@ static struct socket *bareudp_create_sock(struct net *net, __be16 port)
+ int err;
+
+ memset(&udp_conf, 0, sizeof(udp_conf));
+-#if IS_ENABLED(CONFIG_IPV6)
+- udp_conf.family = AF_INET6;
+-#else
+- udp_conf.family = AF_INET;
+-#endif
++
++ if (ipv6_mod_enabled())
++ udp_conf.family = AF_INET6;
++ else
++ udp_conf.family = AF_INET;
++
+ udp_conf.local_udp_port = port;
+ /* Open UDP socket */
+ err = udp_sock_create(net, &udp_conf, &sock);
+@@ -441,7 +442,7 @@ static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ rcu_read_lock();
+- if (IS_ENABLED(CONFIG_IPV6) && info->mode & IP_TUNNEL_INFO_IPV6)
++ if (ipv6_mod_enabled() && info->mode & IP_TUNNEL_INFO_IPV6)
+ err = bareudp6_xmit_skb(skb, dev, bareudp, info);
+ else
+ err = bareudp_xmit_skb(skb, dev, bareudp, info);
+@@ -471,7 +472,7 @@ static int bareudp_fill_metadata_dst(struct net_device *dev,
+
+ use_cache = ip_tunnel_dst_cache_usable(skb, info);
+
+- if (!IS_ENABLED(CONFIG_IPV6) || ip_tunnel_info_af(info) == AF_INET) {
++ if (!ipv6_mod_enabled() || ip_tunnel_info_af(info) == AF_INET) {
+ struct rtable *rt;
+ __be32 saddr;
+
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6006c2e8fa2bc..a86b1f71762ea 100644
--- a/drivers/net/bonding/bond_3ad.c
@@ -67486,7 +102406,7 @@ index 7d3752cbf761d..bca36be884b8d 100644
bond->alb_info.rlb_rebalance = 1;
/* If the updelay module parameter is smaller than the
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
-index 77dc79a7f5748..46c3301a5e07d 100644
+index 77dc79a7f5748..2e75b7e8f70b3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1096,9 +1096,6 @@ static bool bond_should_notify_peers(struct bonding *bond)
@@ -67522,7 +102442,38 @@ index 77dc79a7f5748..46c3301a5e07d 100644
unblock_netpoll_tx();
synchronize_rcu();
-@@ -3872,8 +3871,8 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
+@@ -3818,14 +3817,19 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb, const v
+ return true;
+ }
+
+-static u32 bond_ip_hash(u32 hash, struct flow_keys *flow)
++static u32 bond_ip_hash(u32 hash, struct flow_keys *flow, int xmit_policy)
+ {
+ hash ^= (__force u32)flow_get_u32_dst(flow) ^
+ (__force u32)flow_get_u32_src(flow);
+ hash ^= (hash >> 16);
+ hash ^= (hash >> 8);
++
+ /* discard lowest hash bit to deal with the common even ports pattern */
+- return hash >> 1;
++ if (xmit_policy == BOND_XMIT_POLICY_LAYER34 ||
++ xmit_policy == BOND_XMIT_POLICY_ENCAP34)
++ return hash >> 1;
++
++ return hash;
+ }
+
+ /* Generate hash based on xmit policy. If @skb is given it is used to linearize
+@@ -3855,7 +3859,7 @@ static u32 __bond_xmit_hash(struct bonding *bond, struct sk_buff *skb, const voi
+ memcpy(&hash, &flow.ports.ports, sizeof(hash));
+ }
+
+- return bond_ip_hash(hash, &flow);
++ return bond_ip_hash(hash, &flow, bond->params.xmit_policy);
+ }
+
+ /**
+@@ -3872,8 +3876,8 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
skb->l4_hash)
return skb->hash;
@@ -67533,7 +102484,7 @@ index 77dc79a7f5748..46c3301a5e07d 100644
skb_headlen(skb));
}
-@@ -4843,25 +4842,39 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb,
+@@ -4843,25 +4847,39 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb,
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave = NULL;
struct list_head *iter;
@@ -67581,6 +102532,15 @@ index 77dc79a7f5748..46c3301a5e07d 100644
}
/*------------------------- Device initialization ---------------------------*/
+@@ -4999,7 +5017,7 @@ static u32 bond_sk_hash_l34(struct sock *sk)
+ /* L4 */
+ memcpy(&hash, &flow.ports.ports, sizeof(hash));
+ /* L3 */
+- return bond_ip_hash(hash, &flow);
++ return bond_ip_hash(hash, &flow, BOND_XMIT_POLICY_LAYER34);
+ }
+
+ static struct net_device *__bond_sk_get_lower_dev(struct bonding *bond,
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index a8fde3bc458f6..b93337b5a7211 100644
--- a/drivers/net/bonding/bond_options.c
@@ -68075,6 +103035,151 @@ index 7734229aa0788..18d7bb99ec1bd 100644
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_FD_NON_ISO;
priv->can.bittiming_const = &flexcan_fd_bittiming_const;
+diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
+index 78e27940b2aff..daee3652ac8b3 100644
+--- a/drivers/net/can/grcan.c
++++ b/drivers/net/can/grcan.c
+@@ -241,13 +241,14 @@ struct grcan_device_config {
+ .rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \
+ }
+
+-#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100
++#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 4100
+ #define GRLIB_VERSION_MASK 0xffff
+
+ /* GRCAN private data structure */
+ struct grcan_priv {
+ struct can_priv can; /* must be the first member */
+ struct net_device *dev;
++ struct device *ofdev_dev;
+ struct napi_struct napi;
+
+ struct grcan_registers __iomem *regs; /* ioremap'ed registers */
+@@ -924,7 +925,7 @@ static void grcan_free_dma_buffers(struct net_device *dev)
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_dma *dma = &priv->dma;
+
+- dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
++ dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf,
+ dma->base_handle);
+ memset(dma, 0, sizeof(*dma));
+ }
+@@ -949,7 +950,7 @@ static int grcan_allocate_dma_buffers(struct net_device *dev,
+
+ /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
+ dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
+- dma->base_buf = dma_alloc_coherent(&dev->dev,
++ dma->base_buf = dma_alloc_coherent(priv->ofdev_dev,
+ dma->base_size,
+ &dma->base_handle,
+ GFP_KERNEL);
+@@ -1113,8 +1114,10 @@ static int grcan_close(struct net_device *dev)
+
+ priv->closing = true;
+ if (priv->need_txbug_workaround) {
++ spin_unlock_irqrestore(&priv->lock, flags);
+ del_timer_sync(&priv->hang_timer);
+ del_timer_sync(&priv->rr_timer);
++ spin_lock_irqsave(&priv->lock, flags);
+ }
+ netif_stop_queue(dev);
+ grcan_stop_hardware(dev);
+@@ -1134,7 +1137,7 @@ static int grcan_close(struct net_device *dev)
+ return 0;
+ }
+
+-static int grcan_transmit_catch_up(struct net_device *dev, int budget)
++static void grcan_transmit_catch_up(struct net_device *dev)
+ {
+ struct grcan_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+@@ -1142,7 +1145,7 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- work_done = catch_up_echo_skb(dev, budget, true);
++ work_done = catch_up_echo_skb(dev, -1, true);
+ if (work_done) {
+ if (!priv->resetting && !priv->closing &&
+ !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+@@ -1156,8 +1159,6 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+-
+- return work_done;
+ }
+
+ static int grcan_receive(struct net_device *dev, int budget)
+@@ -1239,19 +1240,13 @@ static int grcan_poll(struct napi_struct *napi, int budget)
+ struct net_device *dev = priv->dev;
+ struct grcan_registers __iomem *regs = priv->regs;
+ unsigned long flags;
+- int tx_work_done, rx_work_done;
+- int rx_budget = budget / 2;
+- int tx_budget = budget - rx_budget;
++ int work_done;
+
+- /* Half of the budget for receiving messages */
+- rx_work_done = grcan_receive(dev, rx_budget);
++ work_done = grcan_receive(dev, budget);
+
+- /* Half of the budget for transmitting messages as that can trigger echo
+- * frames being received
+- */
+- tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
++ grcan_transmit_catch_up(dev);
+
+- if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
++ if (work_done < budget) {
+ napi_complete(napi);
+
+ /* Guarantee no interference with a running reset that otherwise
+@@ -1268,7 +1263,7 @@ static int grcan_poll(struct napi_struct *napi, int budget)
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+- return rx_work_done + tx_work_done;
++ return work_done;
+ }
+
+ /* Work tx bug by waiting while for the risky situation to clear. If that fails,
+@@ -1600,6 +1595,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev,
+ memcpy(&priv->config, &grcan_module_config,
+ sizeof(struct grcan_device_config));
+ priv->dev = dev;
++ priv->ofdev_dev = &ofdev->dev;
+ priv->regs = base;
+ priv->can.bittiming_const = &grcan_bittiming_const;
+ priv->can.do_set_bittiming = grcan_set_bittiming;
+@@ -1652,6 +1648,7 @@ exit_free_candev:
+ static int grcan_probe(struct platform_device *ofdev)
+ {
+ struct device_node *np = ofdev->dev.of_node;
++ struct device_node *sysid_parent;
+ u32 sysid, ambafreq;
+ int irq, err;
+ void __iomem *base;
+@@ -1660,10 +1657,15 @@ static int grcan_probe(struct platform_device *ofdev)
+ /* Compare GRLIB version number with the first that does not
+ * have the tx bug (see start_xmit)
+ */
+- err = of_property_read_u32(np, "systemid", &sysid);
+- if (!err && ((sysid & GRLIB_VERSION_MASK)
+- >= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
+- txbug = false;
++ sysid_parent = of_find_node_by_path("/ambapp0");
++ if (sysid_parent) {
++ of_node_get(sysid_parent);
++ err = of_property_read_u32(sysid_parent, "systemid", &sysid);
++ if (!err && ((sysid & GRLIB_VERSION_MASK) >=
++ GRCAN_TXBUG_SAFE_GRLIB_VERSION))
++ txbug = false;
++ of_node_put(sysid_parent);
++ }
+
+ err = of_property_read_u32(np, "freq", &ambafreq);
+ if (err) {
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index 74d9899fc904c..eb74cdf26b88c 100644
--- a/drivers/net/can/kvaser_pciefd.c
@@ -68102,7 +103207,7 @@ index 74d9899fc904c..eb74cdf26b88c 100644
can->bec.txerr = bec.txerr;
can->bec.rxerr = bec.rxerr;
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
-index 2470c47b2e315..25713d6232151 100644
+index 2470c47b2e315..bff33a619acde 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -204,16 +204,16 @@ enum m_can_reg {
@@ -68214,6 +103319,25 @@ index 2470c47b2e315..25713d6232151 100644
cdev->can.ctrlmode_supported |=
(m_can_niso_supported(cdev) ?
+@@ -1622,8 +1640,6 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
+ if (err)
+ goto out_fail;
+
+- can_put_echo_skb(skb, dev, 0, 0);
+-
+ if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) {
+ cccr = m_can_read(cdev, M_CAN_CCCR);
+ cccr &= ~CCCR_CMR_MASK;
+@@ -1640,6 +1656,9 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
+ m_can_write(cdev, M_CAN_CCCR, cccr);
+ }
+ m_can_write(cdev, M_CAN_TXBTIE, 0x1);
++
++ can_put_echo_skb(skb, dev, 0, 0);
++
+ m_can_write(cdev, M_CAN_TXBAR, 0x1);
+ /* End of xmit function for version 3.0.x */
+ } else {
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index d18b515e6ccc7..2c5d409971686 100644
--- a/drivers/net/can/m_can/m_can.h
@@ -68229,26 +103353,19 @@ index d18b515e6ccc7..2c5d409971686 100644
int version;
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
-index 89cc3d41e952b..b56a54d6c5a9c 100644
+index 89cc3d41e952b..8f184a852a0a7 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
-@@ -18,9 +18,14 @@
+@@ -18,7 +18,7 @@
#define M_CAN_PCI_MMIO_BAR 0
-#define M_CAN_CLOCK_FREQ_EHL 100000000
++#define M_CAN_CLOCK_FREQ_EHL 200000000
#define CTL_CSR_INT_CTL_OFFSET 0x508
-+struct m_can_pci_config {
-+ const struct can_bittiming_const *bit_timing;
-+ const struct can_bittiming_const *data_timing;
-+ unsigned int clock_freq;
-+};
-+
struct m_can_pci_priv {
- struct m_can_classdev cdev;
-
-@@ -42,8 +47,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
+@@ -42,8 +42,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
{
struct m_can_pci_priv *priv = cdev_to_priv(cdev);
@@ -68263,7 +103380,7 @@ index 89cc3d41e952b..b56a54d6c5a9c 100644
return 0;
}
-@@ -61,8 +71,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
+@@ -61,8 +66,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
const void *val, size_t val_count)
{
struct m_can_pci_priv *priv = cdev_to_priv(cdev);
@@ -68278,78 +103395,6 @@ index 89cc3d41e952b..b56a54d6c5a9c 100644
return 0;
}
-@@ -74,9 +89,40 @@ static struct m_can_ops m_can_pci_ops = {
- .read_fifo = iomap_read_fifo,
- };
-
-+static const struct can_bittiming_const m_can_bittiming_const_ehl = {
-+ .name = KBUILD_MODNAME,
-+ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
-+ .tseg1_max = 64,
-+ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */
-+ .tseg2_max = 128,
-+ .sjw_max = 128,
-+ .brp_min = 1,
-+ .brp_max = 512,
-+ .brp_inc = 1,
-+};
-+
-+static const struct can_bittiming_const m_can_data_bittiming_const_ehl = {
-+ .name = KBUILD_MODNAME,
-+ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
-+ .tseg1_max = 16,
-+ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */
-+ .tseg2_max = 8,
-+ .sjw_max = 4,
-+ .brp_min = 1,
-+ .brp_max = 32,
-+ .brp_inc = 1,
-+};
-+
-+static const struct m_can_pci_config m_can_pci_ehl = {
-+ .bit_timing = &m_can_bittiming_const_ehl,
-+ .data_timing = &m_can_data_bittiming_const_ehl,
-+ .clock_freq = 200000000,
-+};
-+
- static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
- {
- struct device *dev = &pci->dev;
-+ const struct m_can_pci_config *cfg;
- struct m_can_classdev *mcan_class;
- struct m_can_pci_priv *priv;
- void __iomem *base;
-@@ -104,6 +150,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
- if (!mcan_class)
- return -ENOMEM;
-
-+ cfg = (const struct m_can_pci_config *)id->driver_data;
-+
- priv = cdev_to_priv(mcan_class);
-
- priv->base = base;
-@@ -115,7 +163,9 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
- mcan_class->dev = &pci->dev;
- mcan_class->net->irq = pci_irq_vector(pci, 0);
- mcan_class->pm_clock_support = 1;
-- mcan_class->can.clock.freq = id->driver_data;
-+ mcan_class->bit_timing = cfg->bit_timing;
-+ mcan_class->data_timing = cfg->data_timing;
-+ mcan_class->can.clock.freq = cfg->clock_freq;
- mcan_class->ops = &m_can_pci_ops;
-
- pci_set_drvdata(pci, mcan_class);
-@@ -168,8 +218,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
- m_can_pci_suspend, m_can_pci_resume);
-
- static const struct pci_device_id m_can_pci_id_table[] = {
-- { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, },
-- { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, },
-+ { PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, },
-+ { PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, },
- { } /* Terminating Entry */
- };
- MODULE_DEVICE_TABLE(pci, m_can_pci_id_table);
diff --git a/drivers/net/can/m_can/tcan4x5x-regmap.c b/drivers/net/can/m_can/tcan4x5x-regmap.c
index ca80dbaf7a3f5..26e212b8ca7a6 100644
--- a/drivers/net/can/m_can/tcan4x5x-regmap.c
@@ -68381,7 +103426,7 @@ index 92a54a5fd4c50..964c8a09226a9 100644
pch_fifo_thresh(priv, obj_num);
obj_num++;
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
-index ff9d0f5ae0dd2..388521e70837f 100644
+index ff9d0f5ae0dd2..2f44c567ebd73 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1640,8 +1640,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
@@ -68394,7 +103439,24 @@ index ff9d0f5ae0dd2..388521e70837f 100644
}
priv = netdev_priv(ndev);
-@@ -1735,8 +1734,8 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
+@@ -1721,22 +1720,22 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
+
+ netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
+ RCANFD_NAPI_WEIGHT);
++ spin_lock_init(&priv->tx_lock);
++ devm_can_led_init(ndev);
++ gpriv->ch[priv->channel] = priv;
+ err = register_candev(ndev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "register_candev() failed, error %d\n", err);
+ goto fail_candev;
+ }
+- spin_lock_init(&priv->tx_lock);
+- devm_can_led_init(ndev);
+- gpriv->ch[priv->channel] = priv;
+ dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel);
+ return 0;
fail_candev:
netif_napi_del(&priv->napi);
@@ -68465,7 +103527,7 @@ index 7e15368779931..32286f861a195 100644
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
-index 673861ab665a4..9a4791d88683c 100644
+index 673861ab665a4..3a0f022b15625 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1092,7 +1092,7 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
@@ -68516,6 +103578,27 @@ index 673861ab665a4..9a4791d88683c 100644
devm_gpiod_put(&priv->spi->dev, priv->rx_int);
priv->rx_int = NULL;
+@@ -2704,7 +2706,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv,
+ out_kfree_buf_rx:
+ kfree(buf_rx);
+
+- return 0;
++ return err;
+ }
+
+ #define MCP251XFD_QUIRK_ACTIVE(quirk) \
+diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
+index 2b5302e724353..c9552846fe257 100644
+--- a/drivers/net/can/usb/ems_usb.c
++++ b/drivers/net/can/usb/ems_usb.c
+@@ -823,7 +823,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
+
+ usb_unanchor_urb(urb);
+ usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
+- dev_kfree_skb(skb);
+
+ atomic_dec(&dev->active_tx_urbs);
+
diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index 96a13c770e4a1..cd4e7f356e488 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -68629,6 +103712,24 @@ index 826a15871573a..e5033cb5e6959 100644
u16 rx_cmd_buf_len;
union es58x_urb_cmd rx_cmd_buf;
+diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c
+index af042aa55f59e..26bf4775e884c 100644
+--- a/drivers/net/can/usb/etas_es58x/es58x_fd.c
++++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c
+@@ -171,12 +171,11 @@ static int es58x_fd_rx_event_msg(struct net_device *netdev,
+ const struct es58x_fd_rx_event_msg *rx_event_msg;
+ int ret;
+
++ rx_event_msg = &es58x_fd_urb_cmd->rx_event_msg;
+ ret = es58x_check_msg_len(es58x_dev->dev, *rx_event_msg, msg_len);
+ if (ret)
+ return ret;
+
+- rx_event_msg = &es58x_fd_urb_cmd->rx_event_msg;
+-
+ return es58x_rx_err_msg(netdev, rx_event_msg->error_code,
+ rx_event_msg->event_code,
+ get_unaligned_le64(&rx_event_msg->timestamp));
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 5e892bef46b00..d68d698f2606b 100644
--- a/drivers/net/can/usb/gs_usb.c
@@ -68866,6 +103967,93 @@ index 59ba7c7beec00..f7af1bf5ab46d 100644
- .timestamp_freq = 1,
- .bittiming_const = &kvaser_usb_leaf_bittiming_const,
-};
+diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
+index a1a154c08b7f7..023bd34d48e3c 100644
+--- a/drivers/net/can/usb/mcba_usb.c
++++ b/drivers/net/can/usb/mcba_usb.c
+@@ -33,10 +33,6 @@
+ #define MCBA_USB_RX_BUFF_SIZE 64
+ #define MCBA_USB_TX_BUFF_SIZE (sizeof(struct mcba_usb_msg))
+
+-/* MCBA endpoint numbers */
+-#define MCBA_USB_EP_IN 1
+-#define MCBA_USB_EP_OUT 1
+-
+ /* Microchip command id */
+ #define MBCA_CMD_RECEIVE_MESSAGE 0xE3
+ #define MBCA_CMD_I_AM_ALIVE_FROM_CAN 0xF5
+@@ -84,6 +80,8 @@ struct mcba_priv {
+ atomic_t free_ctx_cnt;
+ void *rxbuf[MCBA_MAX_RX_URBS];
+ dma_addr_t rxbuf_dma[MCBA_MAX_RX_URBS];
++ int rx_pipe;
++ int tx_pipe;
+ };
+
+ /* CAN frame */
+@@ -272,10 +270,8 @@ static netdev_tx_t mcba_usb_xmit(struct mcba_priv *priv,
+
+ memcpy(buf, usb_msg, MCBA_USB_TX_BUFF_SIZE);
+
+- usb_fill_bulk_urb(urb, priv->udev,
+- usb_sndbulkpipe(priv->udev, MCBA_USB_EP_OUT), buf,
+- MCBA_USB_TX_BUFF_SIZE, mcba_usb_write_bulk_callback,
+- ctx);
++ usb_fill_bulk_urb(urb, priv->udev, priv->tx_pipe, buf, MCBA_USB_TX_BUFF_SIZE,
++ mcba_usb_write_bulk_callback, ctx);
+
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &priv->tx_submitted);
+@@ -368,7 +364,6 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
+ xmit_failed:
+ can_free_echo_skb(priv->netdev, ctx->ndx, NULL);
+ mcba_usb_free_ctx(ctx);
+- dev_kfree_skb(skb);
+ stats->tx_dropped++;
+
+ return NETDEV_TX_OK;
+@@ -611,7 +606,7 @@ static void mcba_usb_read_bulk_callback(struct urb *urb)
+ resubmit_urb:
+
+ usb_fill_bulk_urb(urb, priv->udev,
+- usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_OUT),
++ priv->rx_pipe,
+ urb->transfer_buffer, MCBA_USB_RX_BUFF_SIZE,
+ mcba_usb_read_bulk_callback, priv);
+
+@@ -656,7 +651,7 @@ static int mcba_usb_start(struct mcba_priv *priv)
+ urb->transfer_dma = buf_dma;
+
+ usb_fill_bulk_urb(urb, priv->udev,
+- usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_IN),
++ priv->rx_pipe,
+ buf, MCBA_USB_RX_BUFF_SIZE,
+ mcba_usb_read_bulk_callback, priv);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+@@ -810,6 +805,13 @@ static int mcba_usb_probe(struct usb_interface *intf,
+ struct mcba_priv *priv;
+ int err;
+ struct usb_device *usbdev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *in, *out;
++
++ err = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL, NULL);
++ if (err) {
++ dev_err(&intf->dev, "Can't find endpoints\n");
++ return err;
++ }
+
+ netdev = alloc_candev(sizeof(struct mcba_priv), MCBA_MAX_TX_URBS);
+ if (!netdev) {
+@@ -855,6 +857,9 @@ static int mcba_usb_probe(struct usb_interface *intf,
+ goto cleanup_free_candev;
+ }
+
++ priv->rx_pipe = usb_rcvbulkpipe(priv->udev, in->bEndpointAddress);
++ priv->tx_pipe = usb_sndbulkpipe(priv->udev, out->bEndpointAddress);
++
+ devm_can_led_init(netdev);
+
+ /* Start USB dev only if we have successfully registered CAN device */
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index 837b3fecd71e9..af8d3dadbbb8b 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -68901,6 +104089,67 @@ index 837b3fecd71e9..af8d3dadbbb8b 100644
CAN_CTRLMODE_CC_LEN8_DLC,
.clock = {
.freq = PCAN_USB_CRYSTAL_HZ / 2,
+diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
+index d1b83bd1b3cb9..d4c8f934a1ce0 100644
+--- a/drivers/net/can/usb/usb_8dev.c
++++ b/drivers/net/can/usb/usb_8dev.c
+@@ -670,9 +670,20 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
+ atomic_inc(&priv->active_tx_urbs);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (unlikely(err))
+- goto failed;
+- else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
++ if (unlikely(err)) {
++ can_free_echo_skb(netdev, context->echo_index, NULL);
++
++ usb_unanchor_urb(urb);
++ usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
++
++ atomic_dec(&priv->active_tx_urbs);
++
++ if (err == -ENODEV)
++ netif_device_detach(netdev);
++ else
++ netdev_warn(netdev, "failed tx_urb %d\n", err);
++ stats->tx_dropped++;
++ } else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+ /* Slow down tx path */
+ netif_stop_queue(netdev);
+
+@@ -691,19 +702,6 @@ nofreecontext:
+
+ return NETDEV_TX_BUSY;
+
+-failed:
+- can_free_echo_skb(netdev, context->echo_index, NULL);
+-
+- usb_unanchor_urb(urb);
+- usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
+-
+- atomic_dec(&priv->active_tx_urbs);
+-
+- if (err == -ENODEV)
+- netif_device_detach(netdev);
+- else
+- netdev_warn(netdev, "failed tx_urb %d\n", err);
+-
+ nomembuf:
+ usb_free_urb(urb);
+
+diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
+index 8861a7d875e7e..be5566168d0f3 100644
+--- a/drivers/net/can/vxcan.c
++++ b/drivers/net/can/vxcan.c
+@@ -148,7 +148,7 @@ static void vxcan_setup(struct net_device *dev)
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->tx_queue_len = 0;
+- dev->flags = (IFF_NOARP|IFF_ECHO);
++ dev->flags = IFF_NOARP;
+ dev->netdev_ops = &vxcan_netdev_ops;
+ dev->needs_free_netdev = true;
+
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 3b883e607d8ba..a579b9b791ede 100644
--- a/drivers/net/can/xilinx_can.c
@@ -68972,7 +104221,7 @@ index 01e37b75471e1..2b88f03e52521 100644
module_spi_driver(b53_spi_driver);
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
-index 7578a5c38df59..2e314e3021d8b 100644
+index 7578a5c38df59..b3a43a3d90e49 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -584,7 +584,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
@@ -69004,6 +104253,38 @@ index 7578a5c38df59..2e314e3021d8b 100644
of_node_put(priv->master_mii_dn);
}
+@@ -793,6 +796,9 @@ static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
+ struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ u32 reg, offset;
+
++ if (priv->wol_ports_mask & BIT(port))
++ return;
++
+ if (port != core_readl(priv, CORE_IMP0_PRT_ID)) {
+ if (priv->type == BCM4908_DEVICE_ID ||
+ priv->type == BCM7445_DEVICE_ID)
+diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
+index a7e2fcf2df2c9..edbe5e7f1cb6b 100644
+--- a/drivers/net/dsa/bcm_sf2_cfp.c
++++ b/drivers/net/dsa/bcm_sf2_cfp.c
+@@ -567,14 +567,14 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
+ static struct cfp_rule *bcm_sf2_cfp_rule_find(struct bcm_sf2_priv *priv,
+ int port, u32 location)
+ {
+- struct cfp_rule *rule = NULL;
++ struct cfp_rule *rule;
+
+ list_for_each_entry(rule, &priv->cfp.rules_list, next) {
+ if (rule->port == port && rule->fs.location == location)
+- break;
++ return rule;
+ }
+
+- return rule;
++ return NULL;
+ }
+
+ static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port,
diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
index 354655f9ed003..950a54ec4b59b 100644
--- a/drivers/net/dsa/hirschmann/hellcreek.c
@@ -69189,7 +104470,7 @@ index 89f920289ae21..0b6f29ee87b56 100644
return PTR_ERR(chip->reset_gpio);
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
-index dbd4486a173ff..9e006a25b636c 100644
+index dbd4486a173ff..8a8f392813d82 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -497,8 +497,9 @@ static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg)
@@ -69216,7 +104497,17 @@ index dbd4486a173ff..9e006a25b636c 100644
}
static int gswip_pce_table_entry_read(struct gswip_priv *priv,
-@@ -2170,8 +2175,10 @@ disable_switch:
+@@ -1658,9 +1663,6 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ miicfg |= GSWIP_MII_CFG_MODE_RMIIM;
+-
+- /* Configure the RMII clock as output: */
+- miicfg |= GSWIP_MII_CFG_RMII_CLK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+@@ -2170,8 +2172,10 @@ disable_switch:
gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
dsa_unregister_switch(priv->ds);
mdio_bus:
@@ -69228,7 +104519,7 @@ index dbd4486a173ff..9e006a25b636c 100644
put_mdio_node:
of_node_put(mdio_np);
for (i = 0; i < priv->num_gphy_fw; i++)
-@@ -2195,6 +2202,7 @@ static int gswip_remove(struct platform_device *pdev)
+@@ -2195,6 +2199,7 @@ static int gswip_remove(struct platform_device *pdev)
if (priv->ds->slave_mii_bus) {
mdiobus_unregister(priv->ds->slave_mii_bus);
of_node_put(priv->ds->slave_mii_bus->dev.of_node);
@@ -69236,8 +104527,65 @@ index dbd4486a173ff..9e006a25b636c 100644
}
for (i = 0; i < priv->num_gphy_fw; i++)
+diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
+index 866767b70d65b..b0a7dee27ffc9 100644
+--- a/drivers/net/dsa/microchip/ksz8795_spi.c
++++ b/drivers/net/dsa/microchip/ksz8795_spi.c
+@@ -124,12 +124,23 @@ static const struct of_device_id ksz8795_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
+
++static const struct spi_device_id ksz8795_spi_ids[] = {
++ { "ksz8765" },
++ { "ksz8794" },
++ { "ksz8795" },
++ { "ksz8863" },
++ { "ksz8873" },
++ { },
++};
++MODULE_DEVICE_TABLE(spi, ksz8795_spi_ids);
++
+ static struct spi_driver ksz8795_spi_driver = {
+ .driver = {
+ .name = "ksz8795-switch",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ksz8795_dt_ids),
+ },
++ .id_table = ksz8795_spi_ids,
+ .probe = ksz8795_spi_probe,
+ .remove = ksz8795_spi_remove,
+ .shutdown = ksz8795_spi_shutdown,
+diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
+index e3cb0e6c9f6f2..43addeabfc259 100644
+--- a/drivers/net/dsa/microchip/ksz9477_spi.c
++++ b/drivers/net/dsa/microchip/ksz9477_spi.c
+@@ -98,12 +98,24 @@ static const struct of_device_id ksz9477_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
+
++static const struct spi_device_id ksz9477_spi_ids[] = {
++ { "ksz9477" },
++ { "ksz9897" },
++ { "ksz9893" },
++ { "ksz9563" },
++ { "ksz8563" },
++ { "ksz9567" },
++ { },
++};
++MODULE_DEVICE_TABLE(spi, ksz9477_spi_ids);
++
+ static struct spi_driver ksz9477_spi_driver = {
+ .driver = {
+ .name = "ksz9477-switch",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ksz9477_dt_ids),
+ },
++ .id_table = ksz9477_spi_ids,
+ .probe = ksz9477_spi_probe,
+ .remove = ksz9477_spi_remove,
+ .shutdown = ksz9477_spi_shutdown,
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
-index 9890672a206d0..fb59efc7f9266 100644
+index 9890672a206d0..ca9e171cb2bb0 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2066,7 +2066,7 @@ mt7530_setup_mdio(struct mt7530_priv *priv)
@@ -69249,8 +104597,25 @@ index 9890672a206d0..fb59efc7f9266 100644
if (ret) {
dev_err(dev, "failed to register MDIO bus: %d\n", ret);
if (priv->irq)
+@@ -2216,6 +2216,7 @@ mt7530_setup(struct dsa_switch *ds)
+ ret = of_get_phy_mode(mac_np, &interface);
+ if (ret && ret != -ENODEV) {
+ of_node_put(mac_np);
++ of_node_put(phy_node);
+ return ret;
+ }
+ id = of_mdio_parse_addr(ds->dev, phy_node);
+@@ -2928,7 +2929,7 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port,
+
+ phylink_set_port_modes(mask);
+
+- if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
++ if (state->interface != PHY_INTERFACE_MODE_TRGMII &&
+ !phy_interface_mode_is_8023z(state->interface)) {
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
-index 8dadcae93c9b5..263da7e2d6be7 100644
+index 8dadcae93c9b5..0830d7bb7a001 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -471,6 +471,12 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
@@ -69394,21 +104759,7 @@ index 8dadcae93c9b5..263da7e2d6be7 100644
mode == MLO_AN_FIXED) {
/* FIXME: for an automedia port, should we force the link
* down here - what if the link comes up due to "other" media
-@@ -2275,6 +2291,13 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
- if (!mv88e6xxx_max_vid(chip))
- return -EOPNOTSUPP;
-
-+ /* The ATU removal procedure needs the FID to be mapped in the VTU,
-+ * but FDB deletion runs concurrently with VLAN deletion. Flush the DSA
-+ * switchdev workqueue to ensure that all FDB entries are deleted
-+ * before we remove the VLAN.
-+ */
-+ dsa_flush_workqueue();
-+
- mv88e6xxx_reg_lock(chip);
-
- err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
-@@ -3400,7 +3423,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
+@@ -3400,7 +3416,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
return err;
}
@@ -69417,7 +104768,7 @@ index 8dadcae93c9b5..263da7e2d6be7 100644
if (!bus)
return -ENOMEM;
-@@ -3425,14 +3448,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
+@@ -3425,14 +3441,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
if (!external) {
err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
if (err)
@@ -69434,7 +104785,7 @@ index 8dadcae93c9b5..263da7e2d6be7 100644
}
if (external)
-@@ -3441,21 +3464,26 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
+@@ -3441,21 +3457,26 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
list_add(&mdio_bus->list, &chip->mdios);
return 0;
@@ -69463,6 +104814,14 @@ index 8dadcae93c9b5..263da7e2d6be7 100644
}
}
+@@ -3628,6 +3649,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
+ .port_sync_link = mv88e6185_port_sync_link,
+ .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
+ .port_tag_remap = mv88e6095_port_tag_remap,
++ .port_set_policy = mv88e6352_port_set_policy,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
+ .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index d9817b20ea641..ab41619a809b3 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
@@ -69485,6 +104844,22 @@ index d9817b20ea641..ab41619a809b3 100644
dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
else
dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
+diff --git a/drivers/net/dsa/mv88e6xxx/port_hidden.c b/drivers/net/dsa/mv88e6xxx/port_hidden.c
+index b49d05f0e1179..7a9f9ff6dedf3 100644
+--- a/drivers/net/dsa/mv88e6xxx/port_hidden.c
++++ b/drivers/net/dsa/mv88e6xxx/port_hidden.c
+@@ -40,8 +40,9 @@ int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip)
+ {
+ int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY);
+
+- return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+- MV88E6XXX_PORT_RESERVED_1A, bit, 0);
++ return mv88e6xxx_port_wait_bit(chip,
++ MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
++ MV88E6XXX_PORT_RESERVED_1A, bit, 0);
+ }
+
+ int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 6ea0036787986..2b05ead515cdc 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -69921,7 +105296,7 @@ index 341236dcbdb47..1513dfb523de7 100644
if ((tstamp & 0xffffffff) < tstamp_lo)
tstamp_hi--;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
-index 11b42fd812e4a..e53ad283e2596 100644
+index 11b42fd812e4a..a9c7ada890d88 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1066,7 +1066,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
@@ -69949,6 +105324,15 @@ index 11b42fd812e4a..e53ad283e2596 100644
}
static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
+@@ -1453,7 +1455,7 @@ static int felix_pci_probe(struct pci_dev *pdev,
+
+ err = dsa_register_switch(ds);
+ if (err) {
+- dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
++ dev_err_probe(&pdev->dev, err, "Failed to register DSA switch\n");
+ goto err_register_ds;
+ }
+
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index de1d34a1f1e47..05e4e75c01076 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -70027,6 +105411,122 @@ index a89093bc6c6ad..9e3b572ed999e 100644
if (smi->vlan4k_enabled)
max = RTL8366RB_NUM_VIDS - 1;
+diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
+index 4ad8031ab6695..065fdbe66c425 100644
+--- a/drivers/net/ethernet/8390/mcf8390.c
++++ b/drivers/net/ethernet/8390/mcf8390.c
+@@ -406,12 +406,12 @@ static int mcf8390_init(struct net_device *dev)
+ static int mcf8390_probe(struct platform_device *pdev)
+ {
+ struct net_device *dev;
+- struct resource *mem, *irq;
++ struct resource *mem;
+ resource_size_t msize;
+- int ret;
++ int ret, irq;
+
+- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+- if (irq == NULL) {
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
+ dev_err(&pdev->dev, "no IRQ specified?\n");
+ return -ENXIO;
+ }
+@@ -434,7 +434,7 @@ static int mcf8390_probe(struct platform_device *pdev)
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ platform_set_drvdata(pdev, dev);
+
+- dev->irq = irq->start;
++ dev->irq = irq;
+ dev->base_addr = mem->start;
+
+ ret = mcf8390_init(dev);
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index 412ae3e43ffb7..35ac6fe7529c5 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -34,15 +34,6 @@ source "drivers/net/ethernet/apple/Kconfig"
+ source "drivers/net/ethernet/aquantia/Kconfig"
+ source "drivers/net/ethernet/arc/Kconfig"
+ source "drivers/net/ethernet/atheros/Kconfig"
+-source "drivers/net/ethernet/broadcom/Kconfig"
+-source "drivers/net/ethernet/brocade/Kconfig"
+-source "drivers/net/ethernet/cadence/Kconfig"
+-source "drivers/net/ethernet/calxeda/Kconfig"
+-source "drivers/net/ethernet/cavium/Kconfig"
+-source "drivers/net/ethernet/chelsio/Kconfig"
+-source "drivers/net/ethernet/cirrus/Kconfig"
+-source "drivers/net/ethernet/cisco/Kconfig"
+-source "drivers/net/ethernet/cortina/Kconfig"
+
+ config CX_ECAT
+ tristate "Beckhoff CX5020 EtherCAT master support"
+@@ -56,6 +47,14 @@ config CX_ECAT
+ To compile this driver as a module, choose M here. The module
+ will be called ec_bhf.
+
++source "drivers/net/ethernet/broadcom/Kconfig"
++source "drivers/net/ethernet/cadence/Kconfig"
++source "drivers/net/ethernet/calxeda/Kconfig"
++source "drivers/net/ethernet/cavium/Kconfig"
++source "drivers/net/ethernet/chelsio/Kconfig"
++source "drivers/net/ethernet/cirrus/Kconfig"
++source "drivers/net/ethernet/cisco/Kconfig"
++source "drivers/net/ethernet/cortina/Kconfig"
+ source "drivers/net/ethernet/davicom/Kconfig"
+
+ config DNET
+@@ -82,7 +81,6 @@ source "drivers/net/ethernet/huawei/Kconfig"
+ source "drivers/net/ethernet/i825xx/Kconfig"
+ source "drivers/net/ethernet/ibm/Kconfig"
+ source "drivers/net/ethernet/intel/Kconfig"
+-source "drivers/net/ethernet/microsoft/Kconfig"
+ source "drivers/net/ethernet/xscale/Kconfig"
+
+ config JME
+@@ -125,8 +123,9 @@ source "drivers/net/ethernet/mediatek/Kconfig"
+ source "drivers/net/ethernet/mellanox/Kconfig"
+ source "drivers/net/ethernet/micrel/Kconfig"
+ source "drivers/net/ethernet/microchip/Kconfig"
+-source "drivers/net/ethernet/moxa/Kconfig"
+ source "drivers/net/ethernet/mscc/Kconfig"
++source "drivers/net/ethernet/microsoft/Kconfig"
++source "drivers/net/ethernet/moxa/Kconfig"
+ source "drivers/net/ethernet/myricom/Kconfig"
+
+ config FEALNX
+@@ -138,10 +137,10 @@ config FEALNX
+ Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
+ cards. <http://www.myson.com.tw/>
+
++source "drivers/net/ethernet/ni/Kconfig"
+ source "drivers/net/ethernet/natsemi/Kconfig"
+ source "drivers/net/ethernet/neterion/Kconfig"
+ source "drivers/net/ethernet/netronome/Kconfig"
+-source "drivers/net/ethernet/ni/Kconfig"
+ source "drivers/net/ethernet/8390/Kconfig"
+ source "drivers/net/ethernet/nvidia/Kconfig"
+ source "drivers/net/ethernet/nxp/Kconfig"
+@@ -161,6 +160,7 @@ source "drivers/net/ethernet/packetengines/Kconfig"
+ source "drivers/net/ethernet/pasemi/Kconfig"
+ source "drivers/net/ethernet/pensando/Kconfig"
+ source "drivers/net/ethernet/qlogic/Kconfig"
++source "drivers/net/ethernet/brocade/Kconfig"
+ source "drivers/net/ethernet/qualcomm/Kconfig"
+ source "drivers/net/ethernet/rdc/Kconfig"
+ source "drivers/net/ethernet/realtek/Kconfig"
+@@ -168,10 +168,10 @@ source "drivers/net/ethernet/renesas/Kconfig"
+ source "drivers/net/ethernet/rocker/Kconfig"
+ source "drivers/net/ethernet/samsung/Kconfig"
+ source "drivers/net/ethernet/seeq/Kconfig"
+-source "drivers/net/ethernet/sfc/Kconfig"
+ source "drivers/net/ethernet/sgi/Kconfig"
+ source "drivers/net/ethernet/silan/Kconfig"
+ source "drivers/net/ethernet/sis/Kconfig"
++source "drivers/net/ethernet/sfc/Kconfig"
+ source "drivers/net/ethernet/smsc/Kconfig"
+ source "drivers/net/ethernet/socionext/Kconfig"
+ source "drivers/net/ethernet/stmicro/Kconfig"
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 1c00d719e5d76..804b37c76b1e6 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
@@ -70306,6 +105806,37 @@ index 18e48b3bc402b..213769054391c 100644
}
static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 5f1fc6582d74a..78c7cbc372b05 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -696,6 +696,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
+ buf_pool->rx_skb[skb_index] = NULL;
+
+ datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
++
++ /* strip off CRC as HW isn't doing this */
++ nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
++ if (!nv)
++ datalen -= 4;
++
+ skb_put(skb, datalen);
+ prefetch(skb->data - NET_IP_ALIGN);
+ skb->protocol = eth_type_trans(skb, ndev);
+@@ -717,12 +723,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
+ }
+ }
+
+- nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
+- if (!nv) {
+- /* strip off CRC as HW isn't doing this */
+- datalen -= 4;
++ if (!nv)
+ goto skip_jumbo;
+- }
+
+ slots = page_pool->slots - 1;
+ head = page_pool->head;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
index 23b2d390fcdda..ace691d7cd759 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h
@@ -70370,9 +105901,31 @@ index bed481816ea31..7442850ca95f0 100644
u64 mprc;
u64 bprc;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
-index 6c049864dac08..9de0065f89b90 100644
+index 6c049864dac08..fbb1e05d58783 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+@@ -480,8 +480,8 @@ int aq_nic_start(struct aq_nic_s *self)
+ if (err < 0)
+ goto err_exit;
+
+- for (i = 0U, aq_vec = self->aq_vec[0];
+- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
++ for (i = 0U; self->aq_vecs > i; ++i) {
++ aq_vec = self->aq_vec[i];
+ err = aq_vec_start(aq_vec);
+ if (err < 0)
+ goto err_exit;
+@@ -511,8 +511,8 @@ int aq_nic_start(struct aq_nic_s *self)
+ mod_timer(&self->polling_timer, jiffies +
+ AQ_CFG_POLLING_TIMER_INTERVAL);
+ } else {
+- for (i = 0U, aq_vec = self->aq_vec[0];
+- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
++ for (i = 0U; self->aq_vecs > i; ++i) {
++ aq_vec = self->aq_vec[i];
+ err = aq_pci_func_alloc_irq(self, i, self->ndev->name,
+ aq_vec_isr, aq_vec,
+ aq_vec_get_affinity_mask(aq_vec));
@@ -903,8 +903,14 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
data[++i] = stats->mbtc;
data[++i] = stats->bbrc;
@@ -70391,7 +105944,7 @@ index 6c049864dac08..9de0065f89b90 100644
data[++i] = stats->dma_pkt_tc;
data[++i] = stats->dma_oct_rc;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
-index d4b1976ee69b9..797a95142d1f4 100644
+index d4b1976ee69b9..831833911a525 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -49,6 +49,8 @@ static const struct pci_device_id aq_pci_tbl[] = {
@@ -70415,22 +105968,76 @@ index d4b1976ee69b9..797a95142d1f4 100644
};
MODULE_DEVICE_TABLE(pci, aq_pci_tbl);
+@@ -439,7 +444,7 @@ err_exit:
+
+ static int aq_pm_freeze(struct device *dev)
+ {
+- return aq_suspend_common(dev, false);
++ return aq_suspend_common(dev, true);
+ }
+
+ static int aq_pm_suspend_poweroff(struct device *dev)
+@@ -449,7 +454,7 @@ static int aq_pm_suspend_poweroff(struct device *dev)
+
+ static int aq_pm_thaw(struct device *dev)
+ {
+- return atl_resume_common(dev, false);
++ return atl_resume_common(dev, true);
+ }
+
+ static int aq_pm_resume_restore(struct device *dev)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
-index 24122ccda614c..72f8751784c31 100644
+index 24122ccda614c..e9c6f1fa0b1a7 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
-@@ -365,6 +365,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+@@ -345,7 +345,6 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+ int budget)
+ {
+ struct net_device *ndev = aq_nic_get_ndev(self->aq_nic);
+- bool is_rsc_completed = true;
+ int err = 0;
+
+ for (; (self->sw_head != self->hw_head) && budget;
+@@ -363,8 +362,17 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+ continue;
+
if (!buff->is_eop) {
++ unsigned int frag_cnt = 0U;
buff_ = buff;
do {
++ bool is_rsc_completed = true;
++
+ if (buff_->next >= self->size) {
+ err = -EIO;
+ goto err_exit;
+ }
++
++ frag_cnt++;
next_ = buff_->next,
buff_ = &self->buff_ring[next_];
is_rsc_completed =
-@@ -388,6 +392,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+@@ -372,22 +380,25 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+ next_,
+ self->hw_head);
+
+- if (unlikely(!is_rsc_completed))
+- break;
++ if (unlikely(!is_rsc_completed) ||
++ frag_cnt > MAX_SKB_FRAGS) {
++ err = 0;
++ goto err_exit;
++ }
+
+ buff->is_error |= buff_->is_error;
+ buff->is_cso_err |= buff_->is_cso_err;
+
+ } while (!buff_->is_eop);
+
+- if (!is_rsc_completed) {
+- err = 0;
+- goto err_exit;
+- }
+ if (buff->is_error ||
(buff->is_lro && buff->is_cso_err)) {
buff_ = buff;
do {
@@ -70441,10 +106048,93 @@ index 24122ccda614c..72f8751784c31 100644
next_ = buff_->next,
buff_ = &self->buff_ring[next_];
+@@ -437,7 +448,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+ ALIGN(hdr_len, sizeof(long)));
+
+ if (buff->len - hdr_len > 0) {
+- skb_add_rx_frag(skb, 0, buff->rxdata.page,
++ skb_add_rx_frag(skb, i++, buff->rxdata.page,
+ buff->rxdata.pg_off + hdr_len,
+ buff->len - hdr_len,
+ AQ_CFG_RX_FRAME_MAX);
+@@ -446,7 +457,6 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
+
+ if (!buff->is_eop) {
+ buff_ = buff;
+- i = 1U;
+ do {
+ next_ = buff_->next;
+ buff_ = &self->buff_ring[next_];
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
-index d281322d7dd29..f4774cf051c97 100644
+index d281322d7dd29..6ab1f3212d246 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+@@ -43,8 +43,8 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
+ if (!self) {
+ err = -EINVAL;
+ } else {
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp);
+ ring[AQ_VEC_RX_ID].stats.rx.polls++;
+ u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp);
+@@ -182,8 +182,8 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops,
+ self->aq_hw_ops = aq_hw_ops;
+ self->aq_hw = aq_hw;
+
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX);
+ if (err < 0)
+ goto err_exit;
+@@ -224,8 +224,8 @@ int aq_vec_start(struct aq_vec_s *self)
+ unsigned int i = 0U;
+ int err = 0;
+
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ err = self->aq_hw_ops->hw_ring_tx_start(self->aq_hw,
+ &ring[AQ_VEC_TX_ID]);
+ if (err < 0)
+@@ -248,8 +248,8 @@ void aq_vec_stop(struct aq_vec_s *self)
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ self->aq_hw_ops->hw_ring_tx_stop(self->aq_hw,
+ &ring[AQ_VEC_TX_ID]);
+
+@@ -268,8 +268,8 @@ void aq_vec_deinit(struct aq_vec_s *self)
+ if (!self)
+ goto err_exit;
+
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
+ aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]);
+ }
+@@ -297,8 +297,8 @@ void aq_vec_ring_free(struct aq_vec_s *self)
+ if (!self)
+ goto err_exit;
+
+- for (i = 0U, ring = self->ring[0];
+- self->tx_rings > i; ++i, ring = self->ring[i]) {
++ for (i = 0U; self->tx_rings > i; ++i) {
++ ring = self->ring[i];
+ aq_ring_free(&ring[AQ_VEC_TX_ID]);
+ if (i < self->rx_rings)
+ aq_ring_free(&ring[AQ_VEC_RX_ID]);
@@ -362,9 +362,6 @@ unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u
{
unsigned int count;
@@ -70455,6 +106145,24 @@ index d281322d7dd29..f4774cf051c97 100644
if (!aq_vec_is_valid_tc(self, tc))
return 0;
+diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+index 9f1b15077e7d6..45c17c585d743 100644
+--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+@@ -889,6 +889,13 @@ int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self,
+ err = -ENXIO;
+ goto err_exit;
+ }
++
++ /* Validate that the new hw_head_ is reasonable. */
++ if (hw_head_ >= ring->size) {
++ err = -ENXIO;
++ goto err_exit;
++ }
++
+ ring->hw_head = hw_head_;
+ err = aq_hw_err_from_flags(self);
+
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 404cbf60d3f2f..65b9e5846be45 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -70915,6 +106623,23 @@ index 02ae98aabf91c..416a5c99db5a2 100644
return err;
}
+diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
+index 4ea157efca868..98a8698a32017 100644
+--- a/drivers/net/ethernet/atheros/alx/main.c
++++ b/drivers/net/ethernet/atheros/alx/main.c
+@@ -1181,8 +1181,11 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
+ alx->hw.mtu = mtu;
+ alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
+ netdev_update_features(netdev);
+- if (netif_running(netdev))
++ if (netif_running(netdev)) {
++ mutex_lock(&alx->mtx);
+ alx_reinit(alx);
++ mutex_unlock(&alx->mtx);
++ }
+ return 0;
+ }
+
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 3b51b172b3172..5cbd815c737e7 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -70944,7 +106669,7 @@ index 02a569500234c..376f81796a293 100644
err = bcm4908_enet_dma_alloc(enet);
if (err)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
-index 7fa1b695400d7..0877b3d7f88c5 100644
+index 7fa1b695400d7..ae541a9d1eeed 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -1309,11 +1309,11 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
@@ -70979,6 +106704,19 @@ index 7fa1b695400d7..0877b3d7f88c5 100644
for (i = 0; i < dev->num_tx_queues; i++) {
ret = bcm_sysport_init_tx_ring(priv, i);
if (ret) {
+@@ -2582,8 +2585,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
+ device_set_wakeup_capable(&pdev->dev, 1);
+
+ priv->wol_clk = devm_clk_get_optional(&pdev->dev, "sw_sysportwol");
+- if (IS_ERR(priv->wol_clk))
+- return PTR_ERR(priv->wol_clk);
++ if (IS_ERR(priv->wol_clk)) {
++ ret = PTR_ERR(priv->wol_clk);
++ goto err_deregister_fixed_link;
++ }
+
+ /* Set the needed headroom once and for all */
+ BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8);
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 984f76e74b43e..16b73bb9acc78 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -71034,8 +106772,21 @@ index df8ff839cc621..94eb3a42158e9 100644
bgmac->read = platform_bgmac_read;
bgmac->write = platform_bgmac_write;
+diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
+index 8c83973adca57..9d70d908c0646 100644
+--- a/drivers/net/ethernet/broadcom/bnx2.c
++++ b/drivers/net/ethernet/broadcom/bnx2.c
+@@ -8212,7 +8212,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+ rc = dma_set_coherent_mask(&pdev->dev, persist_dma_mask);
+ if (rc) {
+ dev_err(&pdev->dev,
+- "pci_set_consistent_dma_mask failed, aborting\n");
++ "dma_set_coherent_mask failed, aborting\n");
+ goto err_out_unmap;
+ }
+ } else if ((rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) != 0) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
-index e789430f407c3..72bdbebf25cec 100644
+index e789430f407c3..9e79bcfb365fa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1850,6 +1850,14 @@ struct bnx2x {
@@ -71053,31 +106804,60 @@ index e789430f407c3..72bdbebf25cec 100644
};
/* Tx queues may be less or equal to Rx queues */
-@@ -2525,5 +2533,6 @@ void bnx2x_register_phc(struct bnx2x *bp);
+@@ -2525,5 +2533,4 @@ void bnx2x_register_phc(struct bnx2x *bp);
* Meant for implicit re-load flows.
*/
int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp);
-
-+int bnx2x_init_firmware(struct bnx2x *bp);
-+void bnx2x_release_firmware(struct bnx2x *bp);
#endif /* bnx2x.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
-index b5d954cb409ae..41ebbb2c7d3ac 100644
+index b5d954cb409ae..198e041d84109 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
-@@ -2364,10 +2364,8 @@ int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err)
+@@ -2363,26 +2363,30 @@ int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err)
+ /* is another pf loaded on this engine? */
if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
- /* build my FW version dword */
+- /* build my FW version dword */
- u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
- (BCM_5710_FW_MINOR_VERSION << 8) +
- (BCM_5710_FW_REVISION_VERSION << 16) +
- (BCM_5710_FW_ENGINEERING_VERSION << 24);
-+ u32 my_fw = (bp->fw_major) + (bp->fw_minor << 8) +
-+ (bp->fw_rev << 16) + (bp->fw_eng << 24);
++ u8 loaded_fw_major, loaded_fw_minor, loaded_fw_rev, loaded_fw_eng;
++ u32 loaded_fw;
/* read loaded FW from chip */
- u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
+- u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
++ loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
+
+- DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x\n",
+- loaded_fw, my_fw);
++ loaded_fw_major = loaded_fw & 0xff;
++ loaded_fw_minor = (loaded_fw >> 8) & 0xff;
++ loaded_fw_rev = (loaded_fw >> 16) & 0xff;
++ loaded_fw_eng = (loaded_fw >> 24) & 0xff;
++
++ DP(BNX2X_MSG_SP, "loaded fw 0x%x major 0x%x minor 0x%x rev 0x%x eng 0x%x\n",
++ loaded_fw, loaded_fw_major, loaded_fw_minor, loaded_fw_rev, loaded_fw_eng);
+
+ /* abort nic load if version mismatch */
+- if (my_fw != loaded_fw) {
++ if (loaded_fw_major != BCM_5710_FW_MAJOR_VERSION ||
++ loaded_fw_minor != BCM_5710_FW_MINOR_VERSION ||
++ loaded_fw_eng != BCM_5710_FW_ENGINEERING_VERSION ||
++ loaded_fw_rev < BCM_5710_FW_REVISION_VERSION_V15) {
+ if (print_err)
+- BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n",
+- loaded_fw, my_fw);
++ BNX2X_ERR("loaded FW incompatible. Aborting\n");
+ else
+- BNX2X_DEV_INFO("bnx2x with FW %x was already loaded which mismatches my %x FW, possibly due to MF UNDI\n",
+- loaded_fw, my_fw);
++ BNX2X_DEV_INFO("loaded FW incompatible, possibly due to MF UNDI\n");
++
+ return -EBUSY;
+ }
+ }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 3f8435208bf49..a84d015da5dfa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -71125,7 +106905,7 @@ index 1835d2e451c01..fc7fce642666c 100644
return 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
-index ae87296ae1ffa..dc70f6f96d024 100644
+index ae87296ae1ffa..553f3de939574 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -74,9 +74,19 @@
@@ -71169,31 +106949,7 @@ index ae87296ae1ffa..dc70f6f96d024 100644
return rc;
}
-@@ -12302,6 +12313,15 @@ static int bnx2x_init_bp(struct bnx2x *bp)
-
- bnx2x_read_fwinfo(bp);
-
-+ if (IS_PF(bp)) {
-+ rc = bnx2x_init_firmware(bp);
-+
-+ if (rc) {
-+ bnx2x_free_mem_bp(bp);
-+ return rc;
-+ }
-+ }
-+
- func = BP_FUNC(bp);
-
- /* need to reset chip if undi was active */
-@@ -12314,6 +12334,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
-
- rc = bnx2x_prev_unload(bp);
- if (rc) {
-+ bnx2x_release_firmware(bp);
- bnx2x_free_mem_bp(bp);
- return rc;
- }
-@@ -13311,16 +13332,11 @@ static int bnx2x_check_firmware(struct bnx2x *bp)
+@@ -13311,16 +13322,11 @@ static int bnx2x_check_firmware(struct bnx2x *bp)
/* Check FW version */
offset = be32_to_cpu(fw_hdr->fw_version.offset);
fw_ver = firmware->data + offset;
@@ -71214,12 +106970,9 @@ index ae87296ae1ffa..dc70f6f96d024 100644
return -EINVAL;
}
-@@ -13398,34 +13414,51 @@ do { \
- (u8 *)bp->arr, len); \
- } while (0)
+@@ -13400,32 +13406,49 @@ do { \
--static int bnx2x_init_firmware(struct bnx2x *bp)
-+int bnx2x_init_firmware(struct bnx2x *bp)
+ static int bnx2x_init_firmware(struct bnx2x *bp)
{
- const char *fw_file_name;
+ const char *fw_file_name, *fw_file_name_v15;
@@ -71275,23 +107028,29 @@ index ae87296ae1ffa..dc70f6f96d024 100644
rc = bnx2x_check_firmware(bp);
if (rc) {
BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
-@@ -13481,7 +13514,7 @@ request_firmware_exit:
- return rc;
- }
+@@ -14135,10 +14158,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
--static void bnx2x_release_firmware(struct bnx2x *bp)
-+void bnx2x_release_firmware(struct bnx2x *bp)
- {
- kfree(bp->init_ops_offsets);
- kfree(bp->init_ops);
-@@ -13998,6 +14031,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
- return 0;
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
+- /* Delete all NAPI objects */
+- bnx2x_del_all_napi(bp);
+- if (CNIC_LOADED(bp))
+- bnx2x_del_all_napi_cnic(bp);
+ netdev_reset_tc(bp->dev);
- init_one_freemem:
-+ bnx2x_release_firmware(bp);
- bnx2x_free_mem_bp(bp);
+ del_timer_sync(&bp->timer);
+@@ -14243,6 +14262,11 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
+ bnx2x_drain_tx_queues(bp);
+ bnx2x_send_unload_req(bp, UNLOAD_RECOVERY);
+ bnx2x_netif_stop(bp, 1);
++ bnx2x_del_all_napi(bp);
++
++ if (CNIC_LOADED(bp))
++ bnx2x_del_all_napi_cnic(bp);
++
+ bnx2x_free_irq(bp);
- init_one_exit:
+ /* Report UNLOAD_DONE to MCP */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 6fbf735fca31c..5613957314501 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -71330,10 +107089,29 @@ index c6ef7ec2c1151..2bc2b707d6eee 100644
bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
-index 62f84cc91e4d1..ce36ee5a250fb 100644
+index 62f84cc91e4d1..cb53149455890 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
-@@ -4757,8 +4757,10 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id)
+@@ -2699,6 +2699,10 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
+ u32 idx = le32_to_cpu(nqcmp->cq_handle_low);
+ struct bnxt_cp_ring_info *cpr2;
+
++ /* No more budget for RX work */
++ if (budget && work_done >= budget && idx == BNXT_RX_HDL)
++ break;
++
+ cpr2 = cpr->cp_ring_arr[idx];
+ work_done += __bnxt_poll_work(bp, cpr2,
+ budget - work_done);
+@@ -3234,6 +3238,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
+ }
+ qidx = bp->tc_to_qidx[j];
+ ring->queue_id = bp->q_info[qidx].queue_id;
++ spin_lock_init(&txr->xdp_tx_lock);
+ if (i < bp->tx_nr_rings_xdp)
+ continue;
+ if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
+@@ -4757,8 +4762,10 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id)
return rc;
req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);
@@ -71346,7 +107124,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
req->mask = cpu_to_le32(vnic->rx_mask);
return hwrm_req_send_silent(bp, req);
}
-@@ -8004,6 +8006,12 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
+@@ -8004,6 +8011,12 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
bp->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
if (!bp->hwrm_cmd_timeout)
bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
@@ -71359,7 +107137,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
if (resp->hwrm_intf_maj_8b >= 1) {
bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
-@@ -8609,6 +8617,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+@@ -8609,6 +8622,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
vnic->uc_filter_count = 1;
vnic->rx_mask = 0;
@@ -71369,7 +107147,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
if (bp->dev->flags & IFF_BROADCAST)
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
-@@ -8618,7 +8629,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+@@ -8618,7 +8634,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
if (bp->dev->flags & IFF_ALLMULTI) {
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0;
@@ -71378,7 +107156,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
u32 mask = 0;
bnxt_mc_list_updated(bp, &mask);
-@@ -8629,6 +8640,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+@@ -8629,6 +8645,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
if (rc)
goto err_out;
@@ -71386,7 +107164,20 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
rc = bnxt_hwrm_set_coal(bp);
if (rc)
netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
-@@ -10289,13 +10301,15 @@ int bnxt_half_open_nic(struct bnxt *bp)
+@@ -10234,6 +10251,12 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+ if (irq_re_init)
+ udp_tunnel_nic_reset_ntf(bp->dev);
+
++ if (bp->tx_nr_rings_xdp < num_possible_cpus()) {
++ if (!static_key_enabled(&bnxt_xdp_locking_key))
++ static_branch_enable(&bnxt_xdp_locking_key);
++ } else if (static_key_enabled(&bnxt_xdp_locking_key)) {
++ static_branch_disable(&bnxt_xdp_locking_key);
++ }
+ set_bit(BNXT_STATE_OPEN, &bp->state);
+ bnxt_enable_int(bp);
+ /* Enable TX queues */
+@@ -10289,13 +10312,15 @@ int bnxt_half_open_nic(struct bnxt *bp)
goto half_open_err;
}
@@ -71404,7 +107195,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
goto half_open_err;
}
-@@ -10303,7 +10317,7 @@ int bnxt_half_open_nic(struct bnxt *bp)
+@@ -10303,7 +10328,7 @@ int bnxt_half_open_nic(struct bnxt *bp)
half_open_err:
bnxt_free_skbs(bp);
@@ -71413,7 +107204,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
dev_close(bp->dev);
return rc;
}
-@@ -10313,9 +10327,10 @@ half_open_err:
+@@ -10313,9 +10338,10 @@ half_open_err:
*/
void bnxt_half_close_nic(struct bnxt *bp)
{
@@ -71426,7 +107217,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
}
static void bnxt_reenable_sriov(struct bnxt *bp)
-@@ -10731,7 +10746,7 @@ static void bnxt_set_rx_mode(struct net_device *dev)
+@@ -10731,7 +10757,7 @@ static void bnxt_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) {
mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0;
@@ -71435,7 +107226,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
mc_update = bnxt_mc_list_updated(bp, &mask);
}
-@@ -10799,9 +10814,10 @@ skip_uc:
+@@ -10799,9 +10825,10 @@ skip_uc:
!bnxt_promisc_ok(bp))
vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
@@ -71447,7 +107238,30 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0;
rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
-@@ -13370,7 +13386,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -10858,7 +10885,7 @@ static bool bnxt_rfs_capable(struct bnxt *bp)
+
+ if (bp->flags & BNXT_FLAG_CHIP_P5)
+ return bnxt_rfs_supported(bp);
+- if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp))
++ if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp) || !bp->rx_nr_rings)
+ return false;
+
+ vnics = 1 + bp->rx_nr_rings;
+@@ -13064,10 +13091,9 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp)
+ goto init_dflt_ring_err;
+
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+- if (bnxt_rfs_supported(bp) && bnxt_rfs_capable(bp)) {
+- bp->flags |= BNXT_FLAG_RFS;
+- bp->dev->features |= NETIF_F_NTUPLE;
+- }
++
++ bnxt_set_dflt_rfs(bp);
++
+ init_dflt_ring_err:
+ bnxt_ulp_irq_restart(bp, rc);
+ return rc;
+@@ -13370,7 +13396,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
bnxt_inv_fw_health_reg(bp);
@@ -71458,7 +107272,7 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
rc = register_netdev(dev);
if (rc)
-@@ -13390,6 +13408,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -13390,6 +13418,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
init_err_cleanup:
bnxt_dl_unregister(bp);
@@ -71467,10 +107281,29 @@ index 62f84cc91e4d1..ce36ee5a250fb 100644
bnxt_clear_int_mode(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
-index 19fe6478e9b4b..ca6fdf03e5865 100644
+index 19fe6478e9b4b..e5874c829226e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
-@@ -1840,6 +1840,7 @@ struct bnxt {
+@@ -584,7 +584,8 @@ struct nqe_cn {
+ #define BNXT_MAX_MTU 9500
+ #define BNXT_MAX_PAGE_MODE_MTU \
+ ((unsigned int)PAGE_SIZE - VLAN_ETH_HLEN - NET_IP_ALIGN - \
+- XDP_PACKET_HEADROOM)
++ XDP_PACKET_HEADROOM - \
++ SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info)))
+
+ #define BNXT_MIN_PKT_SIZE 52
+
+@@ -791,6 +792,8 @@ struct bnxt_tx_ring_info {
+ u32 dev_state;
+
+ struct bnxt_ring_struct tx_ring_struct;
++ /* Synchronize simultaneous xdp_xmit on same ring */
++ spinlock_t xdp_tx_lock;
+ };
+
+ #define BNXT_LEGACY_COAL_CMPL_PARAMS \
+@@ -1840,6 +1843,7 @@ struct bnxt {
#define BNXT_STATE_DRV_REGISTERED 7
#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN 8
#define BNXT_STATE_NAPI_DISABLED 9
@@ -71478,7 +107311,7 @@ index 19fe6478e9b4b..ca6fdf03e5865 100644
#define BNXT_NO_FW_ACCESS(bp) \
(test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \
-@@ -1901,7 +1902,8 @@ struct bnxt {
+@@ -1901,7 +1905,8 @@ struct bnxt {
u16 hwrm_max_req_len;
u16 hwrm_max_ext_req_len;
@@ -72017,7 +107850,7 @@ index d889f240da2b2..406dc655a5fc9 100644
#define NVM_OFF_MSIX_VEC_PER_PF_MIN 114
#define NVM_OFF_IGNORE_ARI 164
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
-index 7260910e75fb2..af7de9ee66cf2 100644
+index 7260910e75fb2..0f276ce2d1eb7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -25,15 +25,13 @@
@@ -72047,7 +107880,18 @@ index 7260910e75fb2..af7de9ee66cf2 100644
}
return 0;
}
-@@ -2167,7 +2168,7 @@ static int bnxt_flash_nvram(struct net_device *dev, u16 dir_type,
+@@ -2073,9 +2074,7 @@ static int bnxt_set_pauseparam(struct net_device *dev,
+ }
+
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+- if (bp->hwrm_spec_code >= 0x10201)
+- link_info->req_flow_ctrl =
+- PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE;
++ link_info->req_flow_ctrl = 0;
+ } else {
+ /* when transition from auto pause to force pause,
+ * force a link change
+@@ -2167,7 +2166,7 @@ static int bnxt_flash_nvram(struct net_device *dev, u16 dir_type,
req->host_src_addr = cpu_to_le64(dma_handle);
}
@@ -72056,7 +107900,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
req->dir_type = cpu_to_le16(dir_type);
req->dir_ordinal = cpu_to_le16(dir_ordinal);
req->dir_ext = cpu_to_le16(dir_ext);
-@@ -2508,8 +2509,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
+@@ -2508,8 +2507,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
return rc;
}
@@ -72067,7 +107911,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
hwrm_req_hold(bp, modify);
modify->host_src_addr = cpu_to_le64(dma_handle);
-@@ -3408,7 +3409,7 @@ static int bnxt_run_loopback(struct bnxt *bp)
+@@ -3408,7 +3407,7 @@ static int bnxt_run_loopback(struct bnxt *bp)
if (!skb)
return -ENOMEM;
data = skb_put(skb, pkt_size);
@@ -72076,7 +107920,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
i += ETH_ALEN;
ether_addr_copy(&data[i], bp->dev->dev_addr);
i += ETH_ALEN;
-@@ -3502,9 +3503,12 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
+@@ -3502,9 +3501,12 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
if (!offline) {
bnxt_run_fw_tests(bp, test_mask, &test_results);
} else {
@@ -72091,7 +107935,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
bnxt_run_fw_tests(bp, test_mask, &test_results);
buf[BNXT_MACLPBK_TEST_IDX] = 1;
-@@ -3514,6 +3518,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
+@@ -3514,6 +3516,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
if (rc) {
bnxt_hwrm_mac_loopback(bp, false);
etest->flags |= ETH_TEST_FL_FAILED;
@@ -72099,7 +107943,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
return;
}
if (bnxt_run_loopback(bp))
-@@ -3539,7 +3544,8 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
+@@ -3539,7 +3542,8 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
}
bnxt_hwrm_phy_loopback(bp, false, false);
bnxt_half_close_nic(bp);
@@ -72109,7 +107953,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
}
if (rc || bnxt_test_irq(bp)) {
buf[BNXT_IRQ_TEST_IDX] = 1;
-@@ -3609,337 +3615,6 @@ static int bnxt_reset(struct net_device *dev, u32 *flags)
+@@ -3609,337 +3613,6 @@ static int bnxt_reset(struct net_device *dev, u32 *flags)
return 0;
}
@@ -72447,7 +108291,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
static int bnxt_set_dump(struct net_device *dev, struct ethtool_dump *dump)
{
struct bnxt *bp = netdev_priv(dev);
-@@ -3971,10 +3646,7 @@ static int bnxt_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
+@@ -3971,10 +3644,7 @@ static int bnxt_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
bp->ver_resp.hwrm_fw_rsvd_8b;
dump->flag = bp->dump_flag;
@@ -72459,7 +108303,7 @@ index 7260910e75fb2..af7de9ee66cf2 100644
return 0;
}
-@@ -3989,15 +3661,7 @@ static int bnxt_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
+@@ -3989,15 +3659,7 @@ static int bnxt_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
memset(buf, 0, dump->len);
dump->flag = bp->dump_flag;
@@ -72597,6 +108441,50 @@ index 4d17f0d5363bb..380ef69afb51b 100644
static inline bool bnxt_cfa_hwrm_message(u16 req_type)
{
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index f0aa480799ca4..62a931de5b1a7 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -331,7 +331,7 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+ struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
+ ptp_info);
+ struct bnxt *bp = ptp->bp;
+- u8 pin_id;
++ int pin_id;
+ int rc;
+
+ switch (rq->type) {
+@@ -339,6 +339,8 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+ /* Configure an External PPS IN */
+ pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
+ rq->extts.index);
++ if (!TSIO_PIN_VALID(pin_id))
++ return -EOPNOTSUPP;
+ if (!on)
+ break;
+ rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+@@ -352,6 +354,8 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+ /* Configure a Periodic PPS OUT */
+ pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_PEROUT,
+ rq->perout.index);
++ if (!TSIO_PIN_VALID(pin_id))
++ return -EOPNOTSUPP;
+ if (!on)
+ break;
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
+index fa5f05708e6df..c3cd51e672e7b 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
+@@ -28,7 +28,7 @@ struct pps_pin {
+ u8 state;
+ };
+
+-#define TSIO_PIN_VALID(pin) ((pin) < (BNXT_MAX_TSIO_PINS))
++#define TSIO_PIN_VALID(pin) ((pin) >= 0 && (pin) < (BNXT_MAX_TSIO_PINS))
+
+ #define EVENT_DATA2_PPS_EVENT_TYPE(data2) \
+ ((data2) & ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index e6a4a768b10b2..1471b6130a2b9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -72610,11 +108498,111 @@ index e6a4a768b10b2..1471b6130a2b9 100644
return -EOPNOTSUPP;
switch (type) {
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+index c8083df5e0ab8..148b58f3468b3 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+@@ -20,6 +20,8 @@
+ #include "bnxt.h"
+ #include "bnxt_xdp.h"
+
++DEFINE_STATIC_KEY_FALSE(bnxt_xdp_locking_key);
++
+ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
+ struct bnxt_tx_ring_info *txr,
+ dma_addr_t mapping, u32 len)
+@@ -227,11 +229,16 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
+ ring = smp_processor_id() % bp->tx_nr_rings_xdp;
+ txr = &bp->tx_ring[ring];
+
++ if (READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING)
++ return -EINVAL;
++
++ if (static_branch_unlikely(&bnxt_xdp_locking_key))
++ spin_lock(&txr->xdp_tx_lock);
++
+ for (i = 0; i < num_frames; i++) {
+ struct xdp_frame *xdp = frames[i];
+
+- if (!txr || !bnxt_tx_avail(bp, txr) ||
+- !(bp->bnapi[ring]->flags & BNXT_NAPI_FLAG_XDP))
++ if (!bnxt_tx_avail(bp, txr))
+ break;
+
+ mapping = dma_map_single(&pdev->dev, xdp->data, xdp->len,
+@@ -250,6 +257,9 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
+ bnxt_db_write(bp, &txr->tx_db, txr->tx_prod);
+ }
+
++ if (static_branch_unlikely(&bnxt_xdp_locking_key))
++ spin_unlock(&txr->xdp_tx_lock);
++
+ return nxmit;
+ }
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+index 0df40c3beb050..067bb5e821f54 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+@@ -10,6 +10,8 @@
+ #ifndef BNXT_XDP_H
+ #define BNXT_XDP_H
+
++DECLARE_STATIC_KEY_FALSE(bnxt_xdp_locking_key);
++
+ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
+ struct bnxt_tx_ring_info *txr,
+ dma_addr_t mapping, u32 len);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-index 23c7595d2a1d3..9a67e24f46b27 100644
+index 23c7595d2a1d3..ea13917537526 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-@@ -3966,10 +3966,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
+@@ -1991,6 +1991,11 @@ static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,
+ return skb;
+ }
+
++static void bcmgenet_hide_tsb(struct sk_buff *skb)
++{
++ __skb_pull(skb, sizeof(struct status_64));
++}
++
+ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+@@ -2097,6 +2102,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ GENET_CB(skb)->last_cb = tx_cb_ptr;
++
++ bcmgenet_hide_tsb(skb);
+ skb_tx_timestamp(skb);
+
+ /* Decrement total BD count and advance our write pointer */
+@@ -2243,8 +2250,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
+ dma_length_status = status->length_status;
+ if (dev->features & NETIF_F_RXCSUM) {
+ rx_csum = (__force __be16)(status->rx_csum & 0xffff);
+- skb->csum = (__force __wsum)ntohs(rx_csum);
+- skb->ip_summed = CHECKSUM_COMPLETE;
++ if (rx_csum) {
++ skb->csum = (__force __wsum)ntohs(rx_csum);
++ skb->ip_summed = CHECKSUM_COMPLETE;
++ }
+ }
+
+ /* DMA flags and length are still valid no matter how
+@@ -3941,6 +3950,10 @@ static int bcmgenet_probe(struct platform_device *pdev)
+ goto err;
+ }
+ priv->wol_irq = platform_get_irq_optional(pdev, 2);
++ if (priv->wol_irq == -EPROBE_DEFER) {
++ err = priv->wol_irq;
++ goto err;
++ }
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base)) {
+@@ -3966,10 +3979,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
/* Request the WOL interrupt and advertise suspend if available */
priv->wol_irq_disabled = true;
@@ -72631,11 +108619,106 @@ index 23c7595d2a1d3..9a67e24f46b27 100644
/* Set the needed headroom to account for any possible
* features enabling/disabling at runtime
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+index e31a5a397f114..f55d9d9c01a85 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+@@ -40,6 +40,13 @@
+ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+ {
+ struct bcmgenet_priv *priv = netdev_priv(dev);
++ struct device *kdev = &priv->pdev->dev;
++
++ if (!device_can_wakeup(kdev)) {
++ wol->supported = 0;
++ wol->wolopts = 0;
++ return;
++ }
+
+ wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
+ wol->wolopts = priv->wolopts;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
-index d13fb1d318215..d71c11a6282ec 100644
+index d13fb1d318215..2fd3dd4b8b815 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
-@@ -4739,7 +4739,7 @@ static int macb_probe(struct platform_device *pdev)
+@@ -1250,7 +1250,6 @@ static void gem_rx_refill(struct macb_queue *queue)
+ /* Make hw descriptor updates visible to CPU */
+ rmb();
+
+- queue->rx_prepared_head++;
+ desc = macb_rx_desc(queue, entry);
+
+ if (!queue->rx_skbuff[entry]) {
+@@ -1289,6 +1288,7 @@ static void gem_rx_refill(struct macb_queue *queue)
+ dma_wmb();
+ desc->addr &= ~MACB_BIT(RX_USED);
+ }
++ queue->rx_prepared_head++;
+ }
+
+ /* Make descriptor updates visible to hardware */
+@@ -1606,7 +1606,14 @@ static int macb_poll(struct napi_struct *napi, int budget)
+ if (work_done < budget) {
+ napi_complete_done(napi, work_done);
+
+- /* Packets received while interrupts were disabled */
++ /* RSR bits only seem to propagate to raise interrupts when
++ * interrupts are enabled at the time, so if bits are already
++ * set due to packets received while interrupts were disabled,
++ * they will not cause another interrupt to be generated when
++ * interrupts are re-enabled.
++ * Check for this case here. This has been seen to happen
++ * around 30% of the time under heavy network load.
++ */
+ status = macb_readl(bp, RSR);
+ if (status) {
+ if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+@@ -1614,6 +1621,22 @@ static int macb_poll(struct napi_struct *napi, int budget)
+ napi_reschedule(napi);
+ } else {
+ queue_writel(queue, IER, bp->rx_intr_mask);
++
++ /* In rare cases, packets could have been received in
++ * the window between the check above and re-enabling
++ * interrupts. Therefore, a double-check is required
++ * to avoid losing a wakeup. This can potentially race
++ * with the interrupt handler doing the same actions
++ * if an interrupt is raised just after enabling them,
++ * but this should be harmless.
++ */
++ status = macb_readl(bp, RSR);
++ if (unlikely(status)) {
++ queue_writel(queue, IDR, bp->rx_intr_mask);
++ if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
++ queue_writel(queue, ISR, MACB_BIT(RCOMP));
++ napi_schedule(napi);
++ }
+ }
+ }
+
+@@ -1666,6 +1689,7 @@ static void macb_tx_restart(struct macb_queue *queue)
+ unsigned int head = queue->tx_head;
+ unsigned int tail = queue->tx_tail;
+ struct macb *bp = queue->bp;
++ unsigned int head_idx, tbqp;
+
+ if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+ queue_writel(queue, ISR, MACB_BIT(TXUBR));
+@@ -1673,6 +1697,13 @@ static void macb_tx_restart(struct macb_queue *queue)
+ if (head == tail)
+ return;
+
++ tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);
++ tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));
++ head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head));
++
++ if (tbqp == head_idx)
++ return;
++
+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
+ }
+
+@@ -4739,7 +4770,7 @@ static int macb_probe(struct platform_device *pdev)
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
@@ -72679,6 +108762,30 @@ index 5903bdb78916f..129352bbe1143 100644
}
break;
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 64144b6171d72..b1c9f65ab10f6 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -2793,14 +2793,14 @@ int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p)
+ goto out;
+ na = ret;
+
+- memcpy(p->id, vpd + id, min_t(int, id_len, ID_LEN));
++ memcpy(p->id, vpd + id, min_t(unsigned int, id_len, ID_LEN));
+ strim(p->id);
+- memcpy(p->sn, vpd + sn, min_t(int, sn_len, SERNUM_LEN));
++ memcpy(p->sn, vpd + sn, min_t(unsigned int, sn_len, SERNUM_LEN));
+ strim(p->sn);
+- memcpy(p->pn, vpd + pn, min_t(int, pn_len, PN_LEN));
++ memcpy(p->pn, vpd + pn, min_t(unsigned int, pn_len, PN_LEN));
+ strim(p->pn);
+- memcpy(p->na, vpd + na, min_t(int, na_len, MACADDR_LEN));
+- strim((char *)p->na);
++ memcpy(p->na, vpd + na, min_t(unsigned int, na_len, MACADDR_LEN));
++ strim(p->na);
+
+ out:
+ vfree(vpd);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 002fc62ea7262..63bc956d20376 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -72830,6 +108937,30 @@ index 36ab4cbf2ad08..b9d967e419387 100644
}
}
purgatory:
+diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
+index fcedd733bacbf..834a3f8c80da0 100644
+--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
++++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
+@@ -1398,8 +1398,10 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ /* alloc_etherdev ensures aligned and zeroed private structures */
+ dev = alloc_etherdev (sizeof (*tp));
+- if (!dev)
++ if (!dev) {
++ pci_disable_device(pdev);
+ return -ENOMEM;
++ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
+@@ -1778,6 +1780,7 @@ err_out_free_res:
+
+ err_out_free_netdev:
+ free_netdev (dev);
++ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 85b99099c6b94..5babcf05bc2f1 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -72856,6 +108987,34 @@ index 38aa824efb25d..9241b9b1c7a36 100644
depends on HAS_IOMEM
help
Simple LAN device for debug or management purposes.
+diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
+index ff76e401a014b..e1df2dc810a28 100644
+--- a/drivers/net/ethernet/faraday/ftgmac100.c
++++ b/drivers/net/ethernet/faraday/ftgmac100.c
+@@ -1817,11 +1817,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
+ priv->rxdes0_edorr_mask = BIT(30);
+ priv->txdes0_edotr_mask = BIT(30);
+ priv->is_aspeed = true;
+- /* Disable ast2600 problematic HW arbitration */
+- if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
+- iowrite32(FTGMAC100_TM_DEFAULT,
+- priv->base + FTGMAC100_OFFSET_TM);
+- }
+ } else {
+ priv->rxdes0_edorr_mask = BIT(15);
+ priv->txdes0_edotr_mask = BIT(15);
+@@ -1893,6 +1888,11 @@ static int ftgmac100_probe(struct platform_device *pdev)
+ err = ftgmac100_setup_clk(priv);
+ if (err)
+ goto err_phy_connect;
++
++ /* Disable ast2600 problematic HW arbitration */
++ if (of_device_is_compatible(np, "aspeed,ast2600-mac"))
++ iowrite32(FTGMAC100_TM_DEFAULT,
++ priv->base + FTGMAC100_OFFSET_TM);
+ }
+
+ /* Default ring sizes */
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index 25c91b3c5fd30..819266d463b07 100644
--- a/drivers/net/ethernet/fealnx.c
@@ -72869,6 +109028,28 @@ index 25c91b3c5fd30..819266d463b07 100644
if (boot_cpu_data.x86 <= 4)
np->crvalue = 0xa00;
else
+diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+index 763d2c7b5fb1a..5750f9a56393a 100644
+--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+@@ -489,11 +489,15 @@ static int dpaa_get_ts_info(struct net_device *net_dev,
+ info->phc_index = -1;
+
+ fman_node = of_get_parent(mac_node);
+- if (fman_node)
++ if (fman_node) {
+ ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
++ of_node_put(fman_node);
++ }
+
+- if (ptp_node)
++ if (ptp_node) {
+ ptp_dev = of_find_device_by_node(ptp_node);
++ of_node_put(ptp_node);
++ }
+
+ if (ptp_dev)
+ ptp = platform_get_drvdata(ptp_dev);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 7065c71ed7b86..8b7a29e1e221b 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -72911,6 +109092,28 @@ index 7065c71ed7b86..8b7a29e1e221b 100644
return 0;
}
+diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
+index 32b5faa87bb8d..208a3459f2e29 100644
+--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
+@@ -168,7 +168,7 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
+ base = of_iomap(node, 0);
+ if (!base) {
+ err = -ENOMEM;
+- goto err_close;
++ goto err_put;
+ }
+
+ err = fsl_mc_allocate_irqs(mc_dev);
+@@ -212,6 +212,8 @@ err_free_mc_irq:
+ fsl_mc_free_irqs(mc_dev);
+ err_unmap:
+ iounmap(base);
++err_put:
++ of_node_put(node);
+ err_close:
+ dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+ err_free_mcp:
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
index d6eefbbf163fa..cacd454ac696c 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
@@ -72935,30 +109138,139 @@ index d6eefbbf163fa..cacd454ac696c 100644
}
static int
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+index 910b9f722504a..d62c188c87480 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+@@ -672,7 +672,10 @@ static int enetc_get_ts_info(struct net_device *ndev,
+ #ifdef CONFIG_FSL_ENETC_PTP_CLOCK
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+- SOF_TIMESTAMPING_RAW_HARDWARE;
++ SOF_TIMESTAMPING_RAW_HARDWARE |
++ SOF_TIMESTAMPING_TX_SOFTWARE |
++ SOF_TIMESTAMPING_RX_SOFTWARE |
++ SOF_TIMESTAMPING_SOFTWARE;
+
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON) |
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
-index 4577226d3c6ad..0536d2c76fbc4 100644
+index 4577226d3c6ad..d779dde522c86 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
-@@ -486,14 +486,16 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+@@ -45,6 +45,7 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed)
+ | pspeed);
+ }
+
++#define ENETC_QOS_ALIGN 64
+ static int enetc_setup_taprio(struct net_device *ndev,
+ struct tc_taprio_qopt_offload *admin_conf)
+ {
+@@ -52,10 +53,11 @@ static int enetc_setup_taprio(struct net_device *ndev,
+ struct enetc_cbd cbd = {.cmd = 0};
+ struct tgs_gcl_conf *gcl_config;
+ struct tgs_gcl_data *gcl_data;
++ dma_addr_t dma, dma_align;
+ struct gce *gce;
+- dma_addr_t dma;
+ u16 data_size;
+ u16 gcl_len;
++ void *tmp;
+ u32 tge;
+ int err;
+ int i;
+@@ -82,9 +84,16 @@ static int enetc_setup_taprio(struct net_device *ndev,
+ gcl_config = &cbd.gcl_conf;
+
+ data_size = struct_size(gcl_data, entry, gcl_len);
+- gcl_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
+- if (!gcl_data)
++ tmp = dma_alloc_coherent(&priv->si->pdev->dev,
++ data_size + ENETC_QOS_ALIGN,
++ &dma, GFP_KERNEL);
++ if (!tmp) {
++ dev_err(&priv->si->pdev->dev,
++ "DMA mapping of taprio gate list failed!\n");
+ return -ENOMEM;
++ }
++ dma_align = ALIGN(dma, ENETC_QOS_ALIGN);
++ gcl_data = (struct tgs_gcl_data *)PTR_ALIGN(tmp, ENETC_QOS_ALIGN);
- data_size = sizeof(struct streamid_data);
- si_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
-+ if (!si_data)
-+ return -ENOMEM;
+ gce = (struct gce *)(gcl_data + 1);
+
+@@ -110,16 +119,8 @@ static int enetc_setup_taprio(struct net_device *ndev,
cbd.length = cpu_to_le16(data_size);
+ cbd.status_flags = 0;
- dma = dma_map_single(&priv->si->pdev->dev, si_data,
- data_size, DMA_FROM_DEVICE);
- if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
- netdev_err(priv->si->ndev, "DMA mapping failed!\n");
-- kfree(si_data);
+- dma = dma_map_single(&priv->si->pdev->dev, gcl_data,
+- data_size, DMA_TO_DEVICE);
+- if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
+- netdev_err(priv->si->ndev, "DMA mapping failed!\n");
+- kfree(gcl_data);
- return -ENOMEM;
-+ err = -ENOMEM;
-+ goto out;
+- }
+-
+- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
+- cbd.addr[1] = cpu_to_le32(upper_32_bits(dma));
++ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
++ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+ cbd.cls = BDCR_CMD_PORT_GCL;
+ cbd.status_flags = 0;
+
+@@ -132,8 +133,8 @@ static int enetc_setup_taprio(struct net_device *ndev,
+ ENETC_QBV_PTGCR_OFFSET,
+ tge & (~ENETC_QBV_TGE));
+
+- dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_TO_DEVICE);
+- kfree(gcl_data);
++ dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN,
++ tmp, dma);
+
+ return err;
+ }
+@@ -463,8 +464,9 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+ struct enetc_cbd cbd = {.cmd = 0};
+ struct streamid_data *si_data;
+ struct streamid_conf *si_conf;
++ dma_addr_t dma, dma_align;
+ u16 data_size;
+- dma_addr_t dma;
++ void *tmp;
+ int port;
+ int err;
+
+@@ -485,19 +487,20 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+ cbd.status_flags = 0;
+
+ data_size = sizeof(struct streamid_data);
+- si_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
+- cbd.length = cpu_to_le16(data_size);
+-
+- dma = dma_map_single(&priv->si->pdev->dev, si_data,
+- data_size, DMA_FROM_DEVICE);
+- if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
+- netdev_err(priv->si->ndev, "DMA mapping failed!\n");
+- kfree(si_data);
++ tmp = dma_alloc_coherent(&priv->si->pdev->dev,
++ data_size + ENETC_QOS_ALIGN,
++ &dma, GFP_KERNEL);
++ if (!tmp) {
++ dev_err(&priv->si->pdev->dev,
++ "DMA mapping of stream identify failed!\n");
+ return -ENOMEM;
}
++ dma_align = ALIGN(dma, ENETC_QOS_ALIGN);
++ si_data = (struct streamid_data *)PTR_ALIGN(tmp, ENETC_QOS_ALIGN);
- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
-@@ -512,12 +514,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
+- cbd.addr[1] = cpu_to_le32(upper_32_bits(dma));
++ cbd.length = cpu_to_le16(data_size);
++ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
++ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+ eth_broadcast_addr(si_data->dmac);
+ si_data->vid_vidm_tg = (ENETC_CBDR_SID_VID_MASK
+ + ((0x3 << 14) | ENETC_CBDR_SID_VIDM));
+@@ -512,12 +515,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
err = enetc_send_cmd(priv->si, &cbd);
if (err)
@@ -72974,17 +109286,139 @@ index 4577226d3c6ad..0536d2c76fbc4 100644
/* Enable the entry overwrite again incase space flushed by hardware */
memset(&cbd, 0, sizeof(cbd));
-@@ -560,6 +560,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+@@ -539,8 +540,8 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
+
+ cbd.length = cpu_to_le16(data_size);
+
+- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
+- cbd.addr[1] = cpu_to_le32(upper_32_bits(dma));
++ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
++ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+
+ /* VIDM default to be 1.
+ * VID Match. If set (b1) then the VID must match, otherwise
+@@ -560,7 +561,9 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv,
}
err = enetc_send_cmd(priv->si, &cbd);
+- kfree(si_data);
+out:
-+ if (!dma_mapping_error(&priv->si->pdev->dev, dma))
-+ dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_FROM_DEVICE);
++ dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN,
++ tmp, dma);
+
+ return err;
+ }
+@@ -629,8 +632,9 @@ static int enetc_streamcounter_hw_get(struct enetc_ndev_priv *priv,
+ {
+ struct enetc_cbd cbd = { .cmd = 2 };
+ struct sfi_counter_data *data_buf;
+- dma_addr_t dma;
++ dma_addr_t dma, dma_align;
+ u16 data_size;
++ void *tmp;
+ int err;
+
+ cbd.index = cpu_to_le16((u16)index);
+@@ -639,19 +643,19 @@ static int enetc_streamcounter_hw_get(struct enetc_ndev_priv *priv,
+ cbd.status_flags = 0;
+
+ data_size = sizeof(struct sfi_counter_data);
+- data_buf = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
+- if (!data_buf)
++ tmp = dma_alloc_coherent(&priv->si->pdev->dev,
++ data_size + ENETC_QOS_ALIGN,
++ &dma, GFP_KERNEL);
++ if (!tmp) {
++ dev_err(&priv->si->pdev->dev,
++ "DMA mapping of stream counter failed!\n");
+ return -ENOMEM;
+-
+- dma = dma_map_single(&priv->si->pdev->dev, data_buf,
+- data_size, DMA_FROM_DEVICE);
+- if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
+- netdev_err(priv->si->ndev, "DMA mapping failed!\n");
+- err = -ENOMEM;
+- goto exit;
+ }
+- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
+- cbd.addr[1] = cpu_to_le32(upper_32_bits(dma));
++ dma_align = ALIGN(dma, ENETC_QOS_ALIGN);
++ data_buf = (struct sfi_counter_data *)PTR_ALIGN(tmp, ENETC_QOS_ALIGN);
+
- kfree(si_data);
++ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
++ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+
+ cbd.length = cpu_to_le16(data_size);
+@@ -680,7 +684,9 @@ static int enetc_streamcounter_hw_get(struct enetc_ndev_priv *priv,
+ data_buf->flow_meter_dropl;
+
+ exit:
+- kfree(data_buf);
++ dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN,
++ tmp, dma);
++
return err;
+ }
+
+@@ -719,9 +725,10 @@ static int enetc_streamgate_hw_set(struct enetc_ndev_priv *priv,
+ struct sgcl_conf *sgcl_config;
+ struct sgcl_data *sgcl_data;
+ struct sgce *sgce;
+- dma_addr_t dma;
++ dma_addr_t dma, dma_align;
+ u16 data_size;
+ int err, i;
++ void *tmp;
+ u64 now;
+
+ cbd.index = cpu_to_le16(sgi->index);
+@@ -768,24 +775,20 @@ static int enetc_streamgate_hw_set(struct enetc_ndev_priv *priv,
+ sgcl_config->acl_len = (sgi->num_entries - 1) & 0x3;
+
+ data_size = struct_size(sgcl_data, sgcl, sgi->num_entries);
+-
+- sgcl_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
+- if (!sgcl_data)
+- return -ENOMEM;
+-
+- cbd.length = cpu_to_le16(data_size);
+-
+- dma = dma_map_single(&priv->si->pdev->dev,
+- sgcl_data, data_size,
+- DMA_FROM_DEVICE);
+- if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
+- netdev_err(priv->si->ndev, "DMA mapping failed!\n");
+- kfree(sgcl_data);
++ tmp = dma_alloc_coherent(&priv->si->pdev->dev,
++ data_size + ENETC_QOS_ALIGN,
++ &dma, GFP_KERNEL);
++ if (!tmp) {
++ dev_err(&priv->si->pdev->dev,
++ "DMA mapping of stream counter failed!\n");
+ return -ENOMEM;
+ }
++ dma_align = ALIGN(dma, ENETC_QOS_ALIGN);
++ sgcl_data = (struct sgcl_data *)PTR_ALIGN(tmp, ENETC_QOS_ALIGN);
+
+- cbd.addr[0] = cpu_to_le32(lower_32_bits(dma));
+- cbd.addr[1] = cpu_to_le32(upper_32_bits(dma));
++ cbd.length = cpu_to_le16(data_size);
++ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
++ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+
+ sgce = &sgcl_data->sgcl[0];
+
+@@ -840,7 +843,8 @@ static int enetc_streamgate_hw_set(struct enetc_ndev_priv *priv,
+ err = enetc_send_cmd(priv->si, &cbd);
+
+ exit:
+- kfree(sgcl_data);
++ dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN,
++ tmp, dma);
+
+ return err;
+ }
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 7b4961daa2540..ed7301b691694 100644
--- a/drivers/net/ethernet/freescale/fec.h
@@ -73000,7 +109434,7 @@ index 7b4961daa2540..ed7301b691694 100644
#define FEC_ENET_TS_TIMER ((uint)0x00008000)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
-index ec87b370bba1f..a3e87e10ee6bd 100644
+index ec87b370bba1f..67eb9b671244b 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1480,7 +1480,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
@@ -73012,6 +109446,15 @@ index ec87b370bba1f..a3e87e10ee6bd 100644
/* Check for errors. */
status ^= BD_ENET_RX_LAST;
+@@ -3726,7 +3726,7 @@ static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
+ ARRAY_SIZE(out_val));
+ if (ret) {
+ dev_dbg(&fep->pdev->dev, "no stop mode property\n");
+- return ret;
++ goto out;
+ }
+
+ fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np);
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index d9baac0dbc7d0..4c9d05c45c033 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -73136,6 +109579,18 @@ index d9fc5c456bf3e..39ae965cd4f64 100644
if (priv->max_speed == SPEED_10000)
params.phy_if = PHY_INTERFACE_MODE_XGMII;
+diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
+index 7b32ed29bf4cb..8c17fe5d66ed4 100644
+--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
++++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
+@@ -1460,6 +1460,7 @@ static int gfar_get_ts_info(struct net_device *dev,
+ ptp_node = of_find_compatible_node(NULL, NULL, "fsl,etsec-ptp");
+ if (ptp_node) {
+ ptp_dev = of_find_device_by_node(ptp_node);
++ of_node_put(ptp_node);
+ if (ptp_dev)
+ ptp = platform_get_drvdata(ptp_dev);
+ }
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index 0b68852379da5..27d07468765f0 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -73708,30 +110163,71 @@ index 23d9cbf262c32..740850b64aff5 100644
port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off;
/* there is difference between V1 and V2 in register.*/
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
-index d701451596c82..47bba4c62f040 100644
+index d701451596c82..9204f5ecd4151 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
-@@ -830,6 +830,8 @@ struct hnae3_handle {
+@@ -527,6 +527,8 @@ struct hnae3_ae_dev {
+ * Get 1588 rx hwstamp
+ * get_ts_info
+ * Get phc info
++ * clean_vf_config
++ * Clean residual vf info after disable sriov
+ */
+ struct hnae3_ae_ops {
+ int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
+@@ -720,6 +722,7 @@ struct hnae3_ae_ops {
+ struct ethtool_ts_info *info);
+ int (*get_link_diagnosis_info)(struct hnae3_handle *handle,
+ u32 *status_code);
++ void (*clean_vf_config)(struct hnae3_ae_dev *ae_dev, int num_vfs);
+ };
+
+ struct hnae3_dcb_ops {
+@@ -830,6 +833,9 @@ struct hnae3_handle {
u8 netdev_flags;
struct dentry *hnae3_dbgfs;
+ /* protects concurrent contention between debugfs commands */
+ struct mutex dbgfs_lock;
++ char **dbgfs_buf;
/* Network interface message level enabled bits */
u32 msg_enable;
+@@ -850,6 +856,20 @@ struct hnae3_handle {
+ #define hnae3_get_bit(origin, shift) \
+ hnae3_get_field(origin, 0x1 << (shift), shift)
+
++#define HNAE3_FORMAT_MAC_ADDR_LEN 18
++#define HNAE3_FORMAT_MAC_ADDR_OFFSET_0 0
++#define HNAE3_FORMAT_MAC_ADDR_OFFSET_4 4
++#define HNAE3_FORMAT_MAC_ADDR_OFFSET_5 5
++
++static inline void hnae3_format_mac_addr(char *format_mac_addr,
++ const u8 *mac_addr)
++{
++ snprintf(format_mac_addr, HNAE3_FORMAT_MAC_ADDR_LEN, "%02x:**:**:**:%02x:%02x",
++ mac_addr[HNAE3_FORMAT_MAC_ADDR_OFFSET_0],
++ mac_addr[HNAE3_FORMAT_MAC_ADDR_OFFSET_4],
++ mac_addr[HNAE3_FORMAT_MAC_ADDR_OFFSET_5]);
++}
++
+ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
+ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
+
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
-index e54f96251fea9..3205849bdb95b 100644
+index e54f96251fea9..15ce1a33649ee 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
-@@ -1021,6 +1021,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
+@@ -1021,7 +1021,8 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
if (ret)
return ret;
+- save_buf = &hns3_dbg_cmd[index].buf;
+ mutex_lock(&handle->dbgfs_lock);
- save_buf = &hns3_dbg_cmd[index].buf;
++ save_buf = &handle->dbgfs_buf[index];
if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
+ test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) {
@@ -1033,15 +1034,15 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
read_buf = *save_buf;
} else {
@@ -73773,7 +110269,21 @@ index e54f96251fea9..3205849bdb95b 100644
return ret;
}
-@@ -1132,6 +1136,8 @@ int hns3_dbg_init(struct hnae3_handle *handle)
+@@ -1123,6 +1127,13 @@ int hns3_dbg_init(struct hnae3_handle *handle)
+ int ret;
+ u32 i;
+
++ handle->dbgfs_buf = devm_kcalloc(&handle->pdev->dev,
++ ARRAY_SIZE(hns3_dbg_cmd),
++ sizeof(*handle->dbgfs_buf),
++ GFP_KERNEL);
++ if (!handle->dbgfs_buf)
++ return -ENOMEM;
++
+ hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry =
+ debugfs_create_dir(name, hns3_dbgfs_root);
+ handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry;
+@@ -1132,6 +1143,8 @@ int hns3_dbg_init(struct hnae3_handle *handle)
debugfs_create_dir(hns3_dbg_dentry[i].name,
handle->hnae3_dbgfs);
@@ -73782,7 +110292,7 @@ index e54f96251fea9..3205849bdb95b 100644
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) {
if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES &&
ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) ||
-@@ -1158,6 +1164,7 @@ int hns3_dbg_init(struct hnae3_handle *handle)
+@@ -1158,6 +1171,7 @@ int hns3_dbg_init(struct hnae3_handle *handle)
return 0;
out:
@@ -73790,14 +110300,180 @@ index e54f96251fea9..3205849bdb95b 100644
debugfs_remove_recursive(handle->hnae3_dbgfs);
handle->hnae3_dbgfs = NULL;
return ret;
-@@ -1173,6 +1180,7 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
- hns3_dbg_cmd[i].buf = NULL;
+@@ -1168,11 +1182,12 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++)
+- if (hns3_dbg_cmd[i].buf) {
+- kvfree(hns3_dbg_cmd[i].buf);
+- hns3_dbg_cmd[i].buf = NULL;
++ if (handle->dbgfs_buf[i]) {
++ kvfree(handle->dbgfs_buf[i]);
++ handle->dbgfs_buf[i] = NULL;
}
+ mutex_destroy(&handle->dbgfs_lock);
debugfs_remove_recursive(handle->hnae3_dbgfs);
handle->hnae3_dbgfs = NULL;
}
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
+index bd8801065e024..814f7491ca08d 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
+@@ -47,7 +47,6 @@ struct hns3_dbg_cmd_info {
+ enum hnae3_dbg_cmd cmd;
+ enum hns3_dbg_dentry_type dentry;
+ u32 buf_len;
+- char *buf;
+ int (*init)(struct hnae3_handle *handle, unsigned int cmd);
+ };
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+index 4b886a13e0797..818a028703c65 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+@@ -2255,6 +2255,8 @@ out_err_tx_ok:
+
+ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
+ {
++ char format_mac_addr_perm[HNAE3_FORMAT_MAC_ADDR_LEN];
++ char format_mac_addr_sa[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+ struct sockaddr *mac_addr = p;
+ int ret;
+@@ -2263,8 +2265,9 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
+ return -EADDRNOTAVAIL;
+
+ if (ether_addr_equal(netdev->dev_addr, mac_addr->sa_data)) {
+- netdev_info(netdev, "already using mac address %pM\n",
+- mac_addr->sa_data);
++ hnae3_format_mac_addr(format_mac_addr_sa, mac_addr->sa_data);
++ netdev_info(netdev, "already using mac address %s\n",
++ format_mac_addr_sa);
+ return 0;
+ }
+
+@@ -2273,8 +2276,10 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
+ */
+ if (!hns3_is_phys_func(h->pdev) &&
+ !is_zero_ether_addr(netdev->perm_addr)) {
+- netdev_err(netdev, "has permanent MAC %pM, user MAC %pM not allow\n",
+- netdev->perm_addr, mac_addr->sa_data);
++ hnae3_format_mac_addr(format_mac_addr_perm, netdev->perm_addr);
++ hnae3_format_mac_addr(format_mac_addr_sa, mac_addr->sa_data);
++ netdev_err(netdev, "has permanent MAC %s, user MAC %s not allow\n",
++ format_mac_addr_perm, format_mac_addr_sa);
+ return -EPERM;
+ }
+
+@@ -2836,14 +2841,16 @@ static int hns3_nic_set_vf_rate(struct net_device *ndev, int vf,
+ static int hns3_nic_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
+ {
+ struct hnae3_handle *h = hns3_get_handle(netdev);
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+
+ if (!h->ae_algo->ops->set_vf_mac)
+ return -EOPNOTSUPP;
+
+ if (is_multicast_ether_addr(mac)) {
++ hnae3_format_mac_addr(format_mac_addr, mac);
+ netdev_err(netdev,
+- "Invalid MAC:%pM specified. Could not set MAC\n",
+- mac);
++ "Invalid MAC:%s specified. Could not set MAC\n",
++ format_mac_addr);
+ return -EINVAL;
+ }
+
+@@ -2947,6 +2954,21 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ return ret;
+ }
+
++/**
++ * hns3_clean_vf_config
++ * @pdev: pointer to a pci_dev structure
++ * @num_vfs: number of VFs allocated
++ *
++ * Clean residual vf config after disable sriov
++ **/
++static void hns3_clean_vf_config(struct pci_dev *pdev, int num_vfs)
++{
++ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
++
++ if (ae_dev->ops->clean_vf_config)
++ ae_dev->ops->clean_vf_config(ae_dev, num_vfs);
++}
++
+ /* hns3_remove - Device removal routine
+ * @pdev: PCI device information struct
+ */
+@@ -2985,7 +3007,10 @@ static int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
+ else
+ return num_vfs;
+ } else if (!pci_vfs_assigned(pdev)) {
++ int num_vfs_pre = pci_num_vf(pdev);
++
+ pci_disable_sriov(pdev);
++ hns3_clean_vf_config(pdev, num_vfs_pre);
+ } else {
+ dev_warn(&pdev->dev,
+ "Unable to free VFs because some are assigned to VMs.\n");
+@@ -4927,6 +4952,7 @@ static void hns3_uninit_all_ring(struct hns3_nic_priv *priv)
+ static int hns3_init_mac_addr(struct net_device *netdev)
+ {
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hnae3_handle *h = priv->ae_handle;
+ u8 mac_addr_temp[ETH_ALEN];
+ int ret = 0;
+@@ -4937,8 +4963,9 @@ static int hns3_init_mac_addr(struct net_device *netdev)
+ /* Check if the MAC address is valid, if not get a random one */
+ if (!is_valid_ether_addr(mac_addr_temp)) {
+ eth_hw_addr_random(netdev);
+- dev_warn(priv->dev, "using random MAC address %pM\n",
+- netdev->dev_addr);
++ hnae3_format_mac_addr(format_mac_addr, netdev->dev_addr);
++ dev_warn(priv->dev, "using random MAC address %s\n",
++ format_mac_addr);
+ } else if (!ether_addr_equal(netdev->dev_addr, mac_addr_temp)) {
+ ether_addr_copy(netdev->dev_addr, mac_addr_temp);
+ ether_addr_copy(netdev->perm_addr, mac_addr_temp);
+@@ -4990,8 +5017,10 @@ static void hns3_client_stop(struct hnae3_handle *handle)
+ static void hns3_info_show(struct hns3_nic_priv *priv)
+ {
+ struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+
+- dev_info(priv->dev, "MAC address: %pM\n", priv->netdev->dev_addr);
++ hnae3_format_mac_addr(format_mac_addr, priv->netdev->dev_addr);
++ dev_info(priv->dev, "MAC address: %s\n", format_mac_addr);
+ dev_info(priv->dev, "Task queue pairs numbers: %u\n", kinfo->num_tqps);
+ dev_info(priv->dev, "RSS size: %u\n", kinfo->rss_size);
+ dev_info(priv->dev, "Allocated RSS size: %u\n", kinfo->req_rss_size);
+@@ -5063,6 +5092,13 @@ static void hns3_state_init(struct hnae3_handle *handle)
+ set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state);
+ }
+
++static void hns3_state_uninit(struct hnae3_handle *handle)
++{
++ struct hns3_nic_priv *priv = handle->priv;
++
++ clear_bit(HNS3_NIC_STATE_INITED, &priv->state);
++}
++
+ static int hns3_client_init(struct hnae3_handle *handle)
+ {
+ struct pci_dev *pdev = handle->pdev;
+@@ -5180,7 +5216,9 @@ static int hns3_client_init(struct hnae3_handle *handle)
+ return ret;
+
+ out_reg_netdev_fail:
++ hns3_state_uninit(handle);
+ hns3_dbg_uninit(handle);
++ hns3_client_stop(handle);
+ out_client_start:
+ hns3_free_rx_cpu_rmap(netdev);
+ hns3_nic_uninit_irq(priv);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 5ebd96f6833d6..526fb56c84f24 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -73877,7 +110553,7 @@ index 91cb578f56b80..375ebf105a9aa 100644
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
-index d891390d492f6..66c407d0d507e 100644
+index d891390d492f6..892f2f12c54c6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -26,8 +26,6 @@
@@ -73898,7 +110574,15 @@ index d891390d492f6..66c407d0d507e 100644
{
u32 desc_num;
int ret;
-@@ -2498,7 +2496,7 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport)
+@@ -1865,6 +1863,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
+ vport->vf_info.link_state = IFLA_VF_LINK_STATE_AUTO;
+ vport->mps = HCLGE_MAC_DEFAULT_FRAME;
+ vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE;
++ vport->port_base_vlan_cfg.tbl_sta = true;
+ vport->rxvlan_cfg.rx_vlan_offload_en = true;
+ vport->req_vlan_fltr_en = true;
+ INIT_LIST_HEAD(&vport->vlan_list);
+@@ -2498,7 +2497,7 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport)
if (hdev->num_msi < hdev->num_nic_msi + hdev->num_roce_msi)
return -EINVAL;
@@ -73907,7 +110591,7 @@ index d891390d492f6..66c407d0d507e 100644
roce->rinfo.netdev = nic->kinfo.netdev;
roce->rinfo.roce_io_base = hdev->hw.io_base;
-@@ -2534,10 +2532,6 @@ static int hclge_init_msi(struct hclge_dev *hdev)
+@@ -2534,10 +2533,6 @@ static int hclge_init_msi(struct hclge_dev *hdev)
hdev->num_msi = vectors;
hdev->num_msi_left = vectors;
@@ -73918,8 +110602,529 @@ index d891390d492f6..66c407d0d507e 100644
hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
sizeof(u16), GFP_KERNEL);
if (!hdev->vector_status) {
+@@ -8575,6 +8570,7 @@ int hclge_update_mac_list(struct hclge_vport *vport,
+ enum HCLGE_MAC_ADDR_TYPE mac_type,
+ const unsigned char *addr)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ struct hclge_mac_node *mac_node;
+ struct list_head *list;
+@@ -8599,9 +8595,10 @@ int hclge_update_mac_list(struct hclge_vport *vport,
+ /* if this address is never added, unnecessary to delete */
+ if (state == HCLGE_MAC_TO_DEL) {
+ spin_unlock_bh(&vport->mac_list_lock);
++ hnae3_format_mac_addr(format_mac_addr, addr);
+ dev_err(&hdev->pdev->dev,
+- "failed to delete address %pM from mac list\n",
+- addr);
++ "failed to delete address %s from mac list\n",
++ format_mac_addr);
+ return -ENOENT;
+ }
+
+@@ -8634,6 +8631,7 @@ static int hclge_add_uc_addr(struct hnae3_handle *handle,
+ int hclge_add_uc_addr_common(struct hclge_vport *vport,
+ const unsigned char *addr)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
+ struct hclge_desc desc;
+@@ -8644,9 +8642,10 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport,
+ if (is_zero_ether_addr(addr) ||
+ is_broadcast_ether_addr(addr) ||
+ is_multicast_ether_addr(addr)) {
++ hnae3_format_mac_addr(format_mac_addr, addr);
+ dev_err(&hdev->pdev->dev,
+- "Set_uc mac err! invalid mac:%pM. is_zero:%d,is_br=%d,is_mul=%d\n",
+- addr, is_zero_ether_addr(addr),
++ "Set_uc mac err! invalid mac:%s. is_zero:%d,is_br=%d,is_mul=%d\n",
++ format_mac_addr, is_zero_ether_addr(addr),
+ is_broadcast_ether_addr(addr),
+ is_multicast_ether_addr(addr));
+ return -EINVAL;
+@@ -8703,6 +8702,7 @@ static int hclge_rm_uc_addr(struct hnae3_handle *handle,
+ int hclge_rm_uc_addr_common(struct hclge_vport *vport,
+ const unsigned char *addr)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
+ int ret;
+@@ -8711,8 +8711,9 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport,
+ if (is_zero_ether_addr(addr) ||
+ is_broadcast_ether_addr(addr) ||
+ is_multicast_ether_addr(addr)) {
+- dev_dbg(&hdev->pdev->dev, "Remove mac err! invalid mac:%pM.\n",
+- addr);
++ hnae3_format_mac_addr(format_mac_addr, addr);
++ dev_dbg(&hdev->pdev->dev, "Remove mac err! invalid mac:%s.\n",
++ format_mac_addr);
+ return -EINVAL;
+ }
+
+@@ -8720,12 +8721,11 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport,
+ hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
+ hclge_prepare_mac_addr(&req, addr, false);
+ ret = hclge_remove_mac_vlan_tbl(vport, &req);
+- if (!ret) {
++ if (!ret || ret == -ENOENT) {
+ mutex_lock(&hdev->vport_lock);
+ hclge_update_umv_space(vport, true);
+ mutex_unlock(&hdev->vport_lock);
+- } else if (ret == -ENOENT) {
+- ret = 0;
++ return 0;
+ }
+
+ return ret;
+@@ -8743,6 +8743,7 @@ static int hclge_add_mc_addr(struct hnae3_handle *handle,
+ int hclge_add_mc_addr_common(struct hclge_vport *vport,
+ const unsigned char *addr)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
+ struct hclge_desc desc[3];
+@@ -8750,9 +8751,10 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport,
+
+ /* mac addr check */
+ if (!is_multicast_ether_addr(addr)) {
++ hnae3_format_mac_addr(format_mac_addr, addr);
+ dev_err(&hdev->pdev->dev,
+- "Add mc mac err! invalid mac:%pM.\n",
+- addr);
++ "Add mc mac err! invalid mac:%s.\n",
++ format_mac_addr);
+ return -EINVAL;
+ }
+ memset(&req, 0, sizeof(req));
+@@ -8788,6 +8790,7 @@ static int hclge_rm_mc_addr(struct hnae3_handle *handle,
+ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
+ const unsigned char *addr)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
+ enum hclge_cmd_status status;
+@@ -8795,9 +8798,10 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
+
+ /* mac addr check */
+ if (!is_multicast_ether_addr(addr)) {
++ hnae3_format_mac_addr(format_mac_addr, addr);
+ dev_dbg(&hdev->pdev->dev,
+- "Remove mc mac err! invalid mac:%pM.\n",
+- addr);
++ "Remove mc mac err! invalid mac:%s.\n",
++ format_mac_addr);
+ return -EINVAL;
+ }
+
+@@ -9263,16 +9267,18 @@ static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf,
+ u8 *mac_addr)
+ {
+ struct hclge_vport *vport = hclge_get_vport(handle);
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+
+ vport = hclge_get_vf_vport(hdev, vf);
+ if (!vport)
+ return -EINVAL;
+
++ hnae3_format_mac_addr(format_mac_addr, mac_addr);
+ if (ether_addr_equal(mac_addr, vport->vf_info.mac)) {
+ dev_info(&hdev->pdev->dev,
+- "Specified MAC(=%pM) is same as before, no change committed!\n",
+- mac_addr);
++ "Specified MAC(=%s) is same as before, no change committed!\n",
++ format_mac_addr);
+ return 0;
+ }
+
+@@ -9284,15 +9290,20 @@ static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf,
+
+ ether_addr_copy(vport->vf_info.mac, mac_addr);
+
++ /* there is a timewindow for PF to know VF unalive, it may
++ * cause send mailbox fail, but it doesn't matter, VF will
++ * query it when reinit.
++ */
+ if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
+ dev_info(&hdev->pdev->dev,
+- "MAC of VF %d has been set to %pM, and it will be reinitialized!\n",
+- vf, mac_addr);
+- return hclge_inform_reset_assert_to_vf(vport);
++ "MAC of VF %d has been set to %s, and it will be reinitialized!\n",
++ vf, format_mac_addr);
++ (void)hclge_inform_reset_assert_to_vf(vport);
++ return 0;
+ }
+
+- dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %pM\n",
+- vf, mac_addr);
++ dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %s\n",
++ vf, format_mac_addr);
+ return 0;
+ }
+
+@@ -9396,6 +9407,7 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
+ {
+ const unsigned char *new_addr = (const unsigned char *)p;
+ struct hclge_vport *vport = hclge_get_vport(handle);
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclge_dev *hdev = vport->back;
+ unsigned char *old_addr = NULL;
+ int ret;
+@@ -9404,9 +9416,10 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
+ if (is_zero_ether_addr(new_addr) ||
+ is_broadcast_ether_addr(new_addr) ||
+ is_multicast_ether_addr(new_addr)) {
++ hnae3_format_mac_addr(format_mac_addr, new_addr);
+ dev_err(&hdev->pdev->dev,
+- "change uc mac err! invalid mac: %pM.\n",
+- new_addr);
++ "change uc mac err! invalid mac: %s.\n",
++ format_mac_addr);
+ return -EINVAL;
+ }
+
+@@ -9424,9 +9437,10 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
+ spin_lock_bh(&vport->mac_list_lock);
+ ret = hclge_update_mac_node_for_dev_addr(vport, old_addr, new_addr);
+ if (ret) {
++ hnae3_format_mac_addr(format_mac_addr, new_addr);
+ dev_err(&hdev->pdev->dev,
+- "failed to change the mac addr:%pM, ret = %d\n",
+- new_addr, ret);
++ "failed to change the mac addr:%s, ret = %d\n",
++ format_mac_addr, ret);
+ spin_unlock_bh(&vport->mac_list_lock);
+
+ if (!is_first)
+@@ -10084,19 +10098,28 @@ static void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+ bool writen_to_tbl)
+ {
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
++ struct hclge_dev *hdev = vport->back;
+
+- list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node)
+- if (vlan->vlan_id == vlan_id)
++ mutex_lock(&hdev->vport_lock);
++
++ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
++ if (vlan->vlan_id == vlan_id) {
++ mutex_unlock(&hdev->vport_lock);
+ return;
++ }
++ }
+
+ vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
+- if (!vlan)
++ if (!vlan) {
++ mutex_unlock(&hdev->vport_lock);
+ return;
++ }
+
+ vlan->hd_tbl_status = writen_to_tbl;
+ vlan->vlan_id = vlan_id;
+
+ list_add_tail(&vlan->node, &vport->vlan_list);
++ mutex_unlock(&hdev->vport_lock);
+ }
+
+ static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport)
+@@ -10105,6 +10128,8 @@ static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport)
+ struct hclge_dev *hdev = vport->back;
+ int ret;
+
++ mutex_lock(&hdev->vport_lock);
++
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ if (!vlan->hd_tbl_status) {
+ ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
+@@ -10114,12 +10139,16 @@ static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport)
+ dev_err(&hdev->pdev->dev,
+ "restore vport vlan list failed, ret=%d\n",
+ ret);
++
++ mutex_unlock(&hdev->vport_lock);
+ return ret;
+ }
+ }
+ vlan->hd_tbl_status = true;
+ }
+
++ mutex_unlock(&hdev->vport_lock);
++
+ return 0;
+ }
+
+@@ -10129,6 +10158,8 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
+ struct hclge_dev *hdev = vport->back;
+
++ mutex_lock(&hdev->vport_lock);
++
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ if (vlan->vlan_id == vlan_id) {
+ if (is_write_tbl && vlan->hd_tbl_status)
+@@ -10143,6 +10174,8 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+ break;
+ }
+ }
++
++ mutex_unlock(&hdev->vport_lock);
+ }
+
+ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
+@@ -10150,6 +10183,8 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
+ struct hclge_dev *hdev = vport->back;
+
++ mutex_lock(&hdev->vport_lock);
++
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ if (vlan->hd_tbl_status)
+ hclge_set_vlan_filter_hw(hdev,
+@@ -10165,6 +10200,7 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
+ }
+ }
+ clear_bit(vport->vport_id, hdev->vf_vlan_full);
++ mutex_unlock(&hdev->vport_lock);
+ }
+
+ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
+@@ -10173,6 +10209,8 @@ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
+ struct hclge_vport *vport;
+ int i;
+
++ mutex_lock(&hdev->vport_lock);
++
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ vport = &hdev->vport[i];
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+@@ -10180,37 +10218,61 @@ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
+ kfree(vlan);
+ }
+ }
++
++ mutex_unlock(&hdev->vport_lock);
+ }
+
+-void hclge_restore_vport_vlan_table(struct hclge_vport *vport)
++void hclge_restore_vport_port_base_vlan_config(struct hclge_dev *hdev)
+ {
+- struct hclge_vport_vlan_cfg *vlan, *tmp;
+- struct hclge_dev *hdev = vport->back;
++ struct hclge_vlan_info *vlan_info;
++ struct hclge_vport *vport;
+ u16 vlan_proto;
+ u16 vlan_id;
+ u16 state;
++ int vf_id;
+ int ret;
+
+- vlan_proto = vport->port_base_vlan_cfg.vlan_info.vlan_proto;
+- vlan_id = vport->port_base_vlan_cfg.vlan_info.vlan_tag;
+- state = vport->port_base_vlan_cfg.state;
++ /* PF should restore all vfs port base vlan */
++ for (vf_id = 0; vf_id < hdev->num_alloc_vfs; vf_id++) {
++ vport = &hdev->vport[vf_id + HCLGE_VF_VPORT_START_NUM];
++ vlan_info = vport->port_base_vlan_cfg.tbl_sta ?
++ &vport->port_base_vlan_cfg.vlan_info :
++ &vport->port_base_vlan_cfg.old_vlan_info;
+
+- if (state != HNAE3_PORT_BASE_VLAN_DISABLE) {
+- clear_bit(vport->vport_id, hdev->vlan_table[vlan_id]);
+- hclge_set_vlan_filter_hw(hdev, htons(vlan_proto),
+- vport->vport_id, vlan_id,
+- false);
+- return;
++ vlan_id = vlan_info->vlan_tag;
++ vlan_proto = vlan_info->vlan_proto;
++ state = vport->port_base_vlan_cfg.state;
++
++ if (state != HNAE3_PORT_BASE_VLAN_DISABLE) {
++ clear_bit(vport->vport_id, hdev->vlan_table[vlan_id]);
++ ret = hclge_set_vlan_filter_hw(hdev, htons(vlan_proto),
++ vport->vport_id,
++ vlan_id, false);
++ vport->port_base_vlan_cfg.tbl_sta = ret == 0;
++ }
+ }
++}
+
+- list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+- ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
+- vport->vport_id,
+- vlan->vlan_id, false);
+- if (ret)
+- break;
+- vlan->hd_tbl_status = true;
++void hclge_restore_vport_vlan_table(struct hclge_vport *vport)
++{
++ struct hclge_vport_vlan_cfg *vlan, *tmp;
++ struct hclge_dev *hdev = vport->back;
++ int ret;
++
++ mutex_lock(&hdev->vport_lock);
++
++ if (vport->port_base_vlan_cfg.state == HNAE3_PORT_BASE_VLAN_DISABLE) {
++ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
++ ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
++ vport->vport_id,
++ vlan->vlan_id, false);
++ if (ret)
++ break;
++ vlan->hd_tbl_status = true;
++ }
+ }
++
++ mutex_unlock(&hdev->vport_lock);
+ }
+
+ /* For global reset and imp reset, hardware will clear the mac table,
+@@ -10250,6 +10312,7 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev)
+ struct hnae3_handle *handle = &vport->nic;
+
+ hclge_restore_mac_table_common(vport);
++ hclge_restore_vport_port_base_vlan_config(hdev);
+ hclge_restore_vport_vlan_table(vport);
+ set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state);
+ hclge_restore_fd_entries(handle);
+@@ -10306,6 +10369,8 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
+ false);
+ }
+
++ vport->port_base_vlan_cfg.tbl_sta = false;
++
+ /* force add VLAN 0 */
+ ret = hclge_set_vf_vlan_common(hdev, vport->vport_id, false, 0);
+ if (ret)
+@@ -10392,7 +10457,9 @@ out:
+ else
+ nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
+
++ vport->port_base_vlan_cfg.old_vlan_info = *old_vlan_info;
+ vport->port_base_vlan_cfg.vlan_info = *vlan_info;
++ vport->port_base_vlan_cfg.tbl_sta = true;
+ hclge_set_vport_vlan_fltr_change(vport);
+
+ return 0;
+@@ -10460,14 +10527,17 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
+ return ret;
+ }
+
+- /* for DEVICE_VERSION_V3, vf doesn't need to know about the port based
++ /* there is a timewindow for PF to know VF unalive, it may
++ * cause send mailbox fail, but it doesn't matter, VF will
++ * query it when reinit.
++ * for DEVICE_VERSION_V3, vf doesn't need to know about the port based
+ * VLAN state.
+ */
+ if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 &&
+ test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
+- hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
+- vport->vport_id, state,
+- &vlan_info);
++ (void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
++ vport->vport_id,
++ state, &vlan_info);
+
+ return 0;
+ }
+@@ -10525,11 +10595,11 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
+ }
+
+ if (!ret) {
+- if (is_kill)
+- hclge_rm_vport_vlan_table(vport, vlan_id, false);
+- else
++ if (!is_kill)
+ hclge_add_vport_vlan_table(vport, vlan_id,
+ writen_to_tbl);
++ else if (is_kill && vlan_id != 0)
++ hclge_rm_vport_vlan_table(vport, vlan_id, false);
+ } else if (is_kill) {
+ /* when remove hw vlan filter failed, record the vlan id,
+ * and try to remove it from hw later, to be consistence
+@@ -12103,8 +12173,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
+ hclge_misc_irq_uninit(hdev);
+ hclge_devlink_uninit(hdev);
+ hclge_pci_uninit(hdev);
+- mutex_destroy(&hdev->vport_lock);
+ hclge_uninit_vport_vlan_table(hdev);
++ mutex_destroy(&hdev->vport_lock);
+ ae_dev->priv = NULL;
+ }
+
+@@ -12917,6 +12987,55 @@ static int hclge_get_link_diagnosis_info(struct hnae3_handle *handle,
+ return 0;
+ }
+
++/* After disable sriov, VF still has some config and info need clean,
++ * which configed by PF.
++ */
++static void hclge_clear_vport_vf_info(struct hclge_vport *vport, int vfid)
++{
++ struct hclge_dev *hdev = vport->back;
++ struct hclge_vlan_info vlan_info;
++ int ret;
++
++ /* after disable sriov, clean VF rate configured by PF */
++ ret = hclge_tm_qs_shaper_cfg(vport, 0);
++ if (ret)
++ dev_err(&hdev->pdev->dev,
++ "failed to clean vf%d rate config, ret = %d\n",
++ vfid, ret);
++
++ vlan_info.vlan_tag = 0;
++ vlan_info.qos = 0;
++ vlan_info.vlan_proto = ETH_P_8021Q;
++ ret = hclge_update_port_base_vlan_cfg(vport,
++ HNAE3_PORT_BASE_VLAN_DISABLE,
++ &vlan_info);
++ if (ret)
++ dev_err(&hdev->pdev->dev,
++ "failed to clean vf%d port base vlan, ret = %d\n",
++ vfid, ret);
++
++ ret = hclge_set_vf_spoofchk_hw(hdev, vport->vport_id, false);
++ if (ret)
++ dev_err(&hdev->pdev->dev,
++ "failed to clean vf%d spoof config, ret = %d\n",
++ vfid, ret);
++
++ memset(&vport->vf_info, 0, sizeof(vport->vf_info));
++}
++
++static void hclge_clean_vport_config(struct hnae3_ae_dev *ae_dev, int num_vfs)
++{
++ struct hclge_dev *hdev = ae_dev->priv;
++ struct hclge_vport *vport;
++ int i;
++
++ for (i = 0; i < num_vfs; i++) {
++ vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM];
++
++ hclge_clear_vport_vf_info(vport, i);
++ }
++}
++
+ static const struct hnae3_ae_ops hclge_ops = {
+ .init_ae_dev = hclge_init_ae_dev,
+ .uninit_ae_dev = hclge_uninit_ae_dev,
+@@ -13018,6 +13137,7 @@ static const struct hnae3_ae_ops hclge_ops = {
+ .get_rx_hwts = hclge_ptp_get_rx_hwts,
+ .get_ts_info = hclge_ptp_get_ts_info,
+ .get_link_diagnosis_info = hclge_get_link_diagnosis_info,
++ .clean_vf_config = hclge_clean_vport_config,
+ };
+
+ static struct hnae3_ae_algo ae_algo = {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
-index 69cd8f87b4c86..2fa6e14c96e5b 100644
+index 69cd8f87b4c86..4d6dbfe0be7a2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -824,6 +824,9 @@ struct hclge_vf_vlan_cfg {
@@ -73945,12 +111150,130 @@ index 69cd8f87b4c86..2fa6e14c96e5b 100644
unsigned long service_timer_period;
unsigned long service_timer_previous;
-@@ -1138,4 +1139,5 @@ void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
+@@ -999,7 +1000,9 @@ struct hclge_vlan_info {
+
+ struct hclge_port_base_vlan_config {
+ u16 state;
++ bool tbl_sta;
+ struct hclge_vlan_info vlan_info;
++ struct hclge_vlan_info old_vlan_info;
+ };
+
+ struct hclge_vf_info {
+@@ -1054,6 +1057,7 @@ struct hclge_vport {
+ spinlock_t mac_list_lock; /* protect mac address need to add/detele */
+ struct list_head uc_mac_list; /* Store VF unicast table */
+ struct list_head mc_mac_list; /* Store VF multicast table */
++
+ struct list_head vlan_list; /* Store VF vlan table */
+ };
+
+@@ -1123,6 +1127,7 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
+ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
+ void hclge_restore_mac_table_common(struct hclge_vport *vport);
++void hclge_restore_vport_port_base_vlan_config(struct hclge_dev *hdev);
+ void hclge_restore_vport_vlan_table(struct hclge_vport *vport);
+ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
+ struct hclge_vlan_info *vlan_info);
+@@ -1138,4 +1143,5 @@ void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len);
int hclge_push_vf_link_status(struct hclge_vport *vport);
int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en);
+int hclge_mac_update_stats(struct hclge_dev *hdev);
#endif
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+index 65d78ee4d65a0..4a5b11b6fed3f 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+@@ -93,6 +93,13 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
+ enum hclge_cmd_status status;
+ struct hclge_desc desc;
+
++ if (msg_len > HCLGE_MBX_MAX_MSG_SIZE) {
++ dev_err(&hdev->pdev->dev,
++ "msg data length(=%u) exceeds maximum(=%u)\n",
++ msg_len, HCLGE_MBX_MAX_MSG_SIZE);
++ return -EMSGSIZE;
++ }
++
+ resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false);
+@@ -175,7 +182,7 @@ static int hclge_get_ring_chain_from_mbx(
+ ring_num = req->msg.ring_num;
+
+ if (ring_num > HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM)
+- return -ENOMEM;
++ return -EINVAL;
+
+ for (i = 0; i < ring_num; i++) {
+ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) {
+@@ -586,9 +593,9 @@ static int hclge_set_vf_mtu(struct hclge_vport *vport,
+ return hclge_set_vport_mtu(vport, mtu);
+ }
+
+-static void hclge_get_queue_id_in_pf(struct hclge_vport *vport,
+- struct hclge_mbx_vf_to_pf_cmd *mbx_req,
+- struct hclge_respond_to_vf_msg *resp_msg)
++static int hclge_get_queue_id_in_pf(struct hclge_vport *vport,
++ struct hclge_mbx_vf_to_pf_cmd *mbx_req,
++ struct hclge_respond_to_vf_msg *resp_msg)
+ {
+ struct hnae3_handle *handle = &vport->nic;
+ struct hclge_dev *hdev = vport->back;
+@@ -598,17 +605,18 @@ static void hclge_get_queue_id_in_pf(struct hclge_vport *vport,
+ if (queue_id >= handle->kinfo.num_tqps) {
+ dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n",
+ queue_id, mbx_req->mbx_src_vfid);
+- return;
++ return -EINVAL;
+ }
+
+ qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id);
+ memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf));
+ resp_msg->len = sizeof(qid_in_pf);
++ return 0;
+ }
+
+-static void hclge_get_rss_key(struct hclge_vport *vport,
+- struct hclge_mbx_vf_to_pf_cmd *mbx_req,
+- struct hclge_respond_to_vf_msg *resp_msg)
++static int hclge_get_rss_key(struct hclge_vport *vport,
++ struct hclge_mbx_vf_to_pf_cmd *mbx_req,
++ struct hclge_respond_to_vf_msg *resp_msg)
+ {
+ #define HCLGE_RSS_MBX_RESP_LEN 8
+ struct hclge_dev *hdev = vport->back;
+@@ -624,13 +632,14 @@ static void hclge_get_rss_key(struct hclge_vport *vport,
+ dev_warn(&hdev->pdev->dev,
+ "failed to get the rss hash key, the index(%u) invalid !\n",
+ index);
+- return;
++ return -EINVAL;
+ }
+
+ memcpy(resp_msg->data,
+ &hdev->vport[0].rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN],
+ HCLGE_RSS_MBX_RESP_LEN);
+ resp_msg->len = HCLGE_RSS_MBX_RESP_LEN;
++ return 0;
+ }
+
+ static void hclge_link_fail_parse(struct hclge_dev *hdev, u8 link_fail_code)
+@@ -805,10 +814,10 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
+ "VF fail(%d) to set mtu\n", ret);
+ break;
+ case HCLGE_MBX_GET_QID_IN_PF:
+- hclge_get_queue_id_in_pf(vport, req, &resp_msg);
++ ret = hclge_get_queue_id_in_pf(vport, req, &resp_msg);
+ break;
+ case HCLGE_MBX_GET_RSS_KEY:
+- hclge_get_rss_key(vport, req, &resp_msg);
++ ret = hclge_get_rss_key(vport, req, &resp_msg);
+ break;
+ case HCLGE_MBX_GET_LINK_MODE:
+ hclge_get_link_mode(vport, req);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 95074e91a8466..429652a8cde16 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -74079,7 +111402,7 @@ index 2ee9b795f71dc..1db7f40b45255 100644
int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num);
int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
-index cf00ad7bb881f..417a08d600b83 100644
+index cf00ad7bb881f..21678c12afa26 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -703,9 +703,9 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size)
@@ -74094,7 +111417,28 @@ index cf00ad7bb881f..417a08d600b83 100644
}
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false);
-@@ -2496,8 +2496,7 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
+@@ -1514,15 +1514,18 @@ static void hclgevf_config_mac_list(struct hclgevf_dev *hdev,
+ struct list_head *list,
+ enum HCLGEVF_MAC_ADDR_TYPE mac_type)
+ {
++ char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
+ struct hclgevf_mac_addr_node *mac_node, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(mac_node, tmp, list, node) {
+ ret = hclgevf_add_del_mac_addr(hdev, mac_node, mac_type);
+ if (ret) {
++ hnae3_format_mac_addr(format_mac_addr,
++ mac_node->mac_addr);
+ dev_err(&hdev->pdev->dev,
+- "failed to configure mac %pM, state = %d, ret = %d\n",
+- mac_node->mac_addr, mac_node->state, ret);
++ "failed to configure mac %s, state = %d, ret = %d\n",
++ format_mac_addr, mac_node->state, ret);
+ return;
+ }
+ if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
+@@ -2496,8 +2499,7 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
break;
}
@@ -74104,7 +111448,7 @@ index cf00ad7bb881f..417a08d600b83 100644
return IRQ_HANDLED;
}
-@@ -2557,7 +2556,7 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
+@@ -2557,7 +2559,7 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
hdev->num_msi_left == 0)
return -EINVAL;
@@ -74113,7 +111457,7 @@ index cf00ad7bb881f..417a08d600b83 100644
roce->rinfo.netdev = nic->kinfo.netdev;
roce->rinfo.roce_io_base = hdev->hw.io_base;
-@@ -2823,9 +2822,6 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev)
+@@ -2823,9 +2825,6 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev)
hdev->num_msi = vectors;
hdev->num_msi_left = vectors;
@@ -74123,7 +111467,7 @@ index cf00ad7bb881f..417a08d600b83 100644
hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
sizeof(u16), GFP_KERNEL);
if (!hdev->vector_status) {
-@@ -3013,7 +3009,10 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client,
+@@ -3013,7 +3012,10 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client,
/* un-init roce, if it exists */
if (hdev->roce_client) {
@@ -74134,7 +111478,7 @@ index cf00ad7bb881f..417a08d600b83 100644
hdev->roce_client->ops->uninit_instance(&hdev->roce, 0);
hdev->roce_client = NULL;
hdev->roce.client = NULL;
-@@ -3022,6 +3021,8 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client,
+@@ -3022,6 +3024,8 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client,
/* un-init nic/unic, if this was not called by roce client */
if (client->ops->uninit_instance && hdev->nic_client &&
client->type != HNAE3_CLIENT_ROCE) {
@@ -74143,6 +111487,18 @@ index cf00ad7bb881f..417a08d600b83 100644
clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
client->ops->uninit_instance(&hdev->nic, 0);
+@@ -3340,6 +3344,11 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
+ return ret;
+ }
+
++ /* get current port based vlan state from PF */
++ ret = hclgevf_get_port_base_vlan_filter_state(hdev);
++ if (ret)
++ return ret;
++
+ set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
+
+ hclgevf_init_rxd_adv_layout(hdev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
index 28288d7e33032..f6f736c0091c0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -74179,6 +111535,31 @@ index fdc66fae09601..c5ac6ecf36e10 100644
/* synchronous send */
if (need_resp) {
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
+index 7f0f1aa3cedd9..0c1b0a91b1aed 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
+@@ -772,7 +772,7 @@ struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size,
+ /* If we only have one page, still need to get shadown wqe when
+ * wqe rolling-over page
+ */
+- if (curr_pg != end_pg || MASKED_WQE_IDX(wq, end_prod_idx) < *prod_idx) {
++ if (curr_pg != end_pg || end_prod_idx < *prod_idx) {
+ void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size];
+
+ copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *prod_idx);
+@@ -842,7 +842,10 @@ struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size,
+
+ *cons_idx = curr_cons_idx;
+
+- if (curr_pg != end_pg) {
++ /* If we only have one page, still need to get shadown wqe when
++ * wqe rolling-over page
++ */
++ if (curr_pg != end_pg || end_cons_idx < curr_cons_idx) {
+ void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size];
+
+ copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *cons_idx);
diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
index 27937c5d79567..daec9ce04531b 100644
--- a/drivers/net/ethernet/i825xx/sni_82596.c
@@ -74196,7 +111577,7 @@ index 27937c5d79567..daec9ce04531b 100644
}
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
-index 6aa6ff89a7651..404921418f422 100644
+index 6aa6ff89a7651..b262aa84b6a24 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -108,6 +108,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter);
@@ -74207,7 +111588,7 @@ index 6aa6ff89a7651..404921418f422 100644
struct ibmvnic_stat {
char name[ETH_GSTRING_LEN];
-@@ -1245,7 +1246,7 @@ static int __ibmvnic_open(struct net_device *netdev)
+@@ -1245,10 +1246,19 @@ static int __ibmvnic_open(struct net_device *netdev)
rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
if (rc) {
ibmvnic_napi_disable(adapter);
@@ -74216,7 +111597,19 @@ index 6aa6ff89a7651..404921418f422 100644
return rc;
}
-@@ -1295,7 +1296,6 @@ static int ibmvnic_open(struct net_device *netdev)
++ adapter->tx_queues_active = true;
++
++ /* Since queues were stopped until now, there shouldn't be any
++ * one in ibmvnic_complete_tx() or ibmvnic_xmit() so maybe we
++ * don't need the synchronize_rcu()? Leaving it for consistency
++ * with setting ->tx_queues_active = false.
++ */
++ synchronize_rcu();
++
+ netif_tx_start_all_queues(netdev);
+
+ if (prev_state == VNIC_CLOSED) {
+@@ -1295,7 +1305,6 @@ static int ibmvnic_open(struct net_device *netdev)
rc = init_resources(adapter);
if (rc) {
netdev_err(netdev, "failed to initialize resources\n");
@@ -74224,7 +111617,7 @@ index 6aa6ff89a7651..404921418f422 100644
goto out;
}
}
-@@ -1312,6 +1312,11 @@ out:
+@@ -1312,6 +1321,11 @@ out:
adapter->state = VNIC_OPEN;
rc = 0;
}
@@ -74236,16 +111629,96 @@ index 6aa6ff89a7651..404921418f422 100644
return rc;
}
-@@ -1724,8 +1729,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
- ind_bufp = &tx_scrq->ind_buf;
+@@ -1417,6 +1431,14 @@ static void ibmvnic_cleanup(struct net_device *netdev)
+ struct ibmvnic_adapter *adapter = netdev_priv(netdev);
- if (test_bit(0, &adapter->resetting)) {
+ /* ensure that transmissions are stopped if called by do_reset */
++
++ adapter->tx_queues_active = false;
++
++ /* Ensure complete_tx() and ibmvnic_xmit() see ->tx_queues_active
++ * update so they don't restart a queue after we stop it below.
++ */
++ synchronize_rcu();
++
+ if (test_bit(0, &adapter->resetting))
+ netif_tx_disable(netdev);
+ else
+@@ -1657,14 +1679,21 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
+ tx_buff->skb = NULL;
+ adapter->netdev->stats.tx_dropped++;
+ }
++
+ ind_bufp->index = 0;
++
+ if (atomic_sub_return(entries, &tx_scrq->used) <=
+ (adapter->req_tx_entries_per_subcrq / 2) &&
+- __netif_subqueue_stopped(adapter->netdev, queue_num) &&
+- !test_bit(0, &adapter->resetting)) {
+- netif_wake_subqueue(adapter->netdev, queue_num);
+- netdev_dbg(adapter->netdev, "Started queue %d\n",
+- queue_num);
++ __netif_subqueue_stopped(adapter->netdev, queue_num)) {
++ rcu_read_lock();
++
++ if (adapter->tx_queues_active) {
++ netif_wake_subqueue(adapter->netdev, queue_num);
++ netdev_dbg(adapter->netdev, "Started queue %d\n",
++ queue_num);
++ }
++
++ rcu_read_unlock();
+ }
+ }
+
+@@ -1719,13 +1748,12 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ int index = 0;
+ u8 proto = 0;
+
+- tx_scrq = adapter->tx_scrq[queue_num];
+- txq = netdev_get_tx_queue(netdev, queue_num);
+- ind_bufp = &tx_scrq->ind_buf;
+-
+- if (test_bit(0, &adapter->resetting)) {
- if (!netif_subqueue_stopped(netdev, skb))
- netif_stop_subqueue(netdev, queue_num);
++ /* If a reset is in progress, drop the packet since
++ * the scrqs may get torn down. Otherwise use the
++ * rcu to ensure reset waits for us to complete.
++ */
++ rcu_read_lock();
++ if (!adapter->tx_queues_active) {
dev_kfree_skb_any(skb);
tx_send_failed++;
-@@ -2426,6 +2429,7 @@ static void __ibmvnic_reset(struct work_struct *work)
+@@ -1734,6 +1762,10 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ goto out;
+ }
+
++ tx_scrq = adapter->tx_scrq[queue_num];
++ txq = netdev_get_tx_queue(netdev, queue_num);
++ ind_bufp = &tx_scrq->ind_buf;
++
+ if (ibmvnic_xmit_workarounds(skb, netdev)) {
+ tx_dropped++;
+ tx_send_failed++;
+@@ -1741,6 +1773,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
+ ibmvnic_tx_scrq_flush(adapter, tx_scrq);
+ goto out;
+ }
++
+ if (skb_is_gso(skb))
+ tx_pool = &adapter->tso_pool[queue_num];
+ else
+@@ -1895,6 +1928,7 @@ tx_err:
+ netif_carrier_off(netdev);
+ }
+ out:
++ rcu_read_unlock();
+ netdev->stats.tx_dropped += tx_dropped;
+ netdev->stats.tx_bytes += tx_bytes;
+ netdev->stats.tx_packets += tx_packets;
+@@ -2426,6 +2460,7 @@ static void __ibmvnic_reset(struct work_struct *work)
struct ibmvnic_rwi *rwi;
unsigned long flags;
u32 reset_state;
@@ -74253,7 +111726,7 @@ index 6aa6ff89a7651..404921418f422 100644
int rc = 0;
adapter = container_of(work, struct ibmvnic_adapter, ibmvnic_reset);
-@@ -2479,11 +2483,23 @@ static void __ibmvnic_reset(struct work_struct *work)
+@@ -2479,11 +2514,23 @@ static void __ibmvnic_reset(struct work_struct *work)
rc = do_hard_reset(adapter, rwi, reset_state);
rtnl_unlock();
}
@@ -74281,7 +111754,7 @@ index 6aa6ff89a7651..404921418f422 100644
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(60 * HZ);
}
-@@ -2541,12 +2557,23 @@ static void __ibmvnic_delayed_reset(struct work_struct *work)
+@@ -2541,12 +2588,23 @@ static void __ibmvnic_delayed_reset(struct work_struct *work)
__ibmvnic_reset(&adapter->ibmvnic_reset);
}
@@ -74307,7 +111780,7 @@ index 6aa6ff89a7651..404921418f422 100644
unsigned long flags;
int ret;
-@@ -2567,7 +2594,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
+@@ -2567,7 +2625,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
if (adapter->state == VNIC_PROBING) {
netdev_warn(netdev, "Adapter reset during probe\n");
@@ -74316,7 +111789,7 @@ index 6aa6ff89a7651..404921418f422 100644
ret = EAGAIN;
goto err;
}
-@@ -2589,10 +2616,9 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
+@@ -2589,10 +2647,9 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
/* if we just received a transport event,
* flush reset queue and process this reset
*/
@@ -74330,7 +111803,226 @@ index 6aa6ff89a7651..404921418f422 100644
rwi->reset_reason = reason;
list_add_tail(&rwi->list, &adapter->rwi_list);
netdev_dbg(adapter->netdev, "Scheduling reset (reason %s)\n",
-@@ -3664,11 +3690,25 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
+@@ -2904,13 +2961,8 @@ static void ibmvnic_get_ringparam(struct net_device *netdev,
+ {
+ struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+
+- if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) {
+- ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq;
+- ring->tx_max_pending = adapter->max_tx_entries_per_subcrq;
+- } else {
+- ring->rx_max_pending = IBMVNIC_MAX_QUEUE_SZ;
+- ring->tx_max_pending = IBMVNIC_MAX_QUEUE_SZ;
+- }
++ ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq;
++ ring->tx_max_pending = adapter->max_tx_entries_per_subcrq;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = adapter->req_rx_add_entries_per_subcrq;
+@@ -2923,23 +2975,21 @@ static int ibmvnic_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+ {
+ struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+- int ret;
+
+- ret = 0;
++ if (ring->rx_pending > adapter->max_rx_add_entries_per_subcrq ||
++ ring->tx_pending > adapter->max_tx_entries_per_subcrq) {
++ netdev_err(netdev, "Invalid request.\n");
++ netdev_err(netdev, "Max tx buffers = %llu\n",
++ adapter->max_rx_add_entries_per_subcrq);
++ netdev_err(netdev, "Max rx buffers = %llu\n",
++ adapter->max_tx_entries_per_subcrq);
++ return -EINVAL;
++ }
++
+ adapter->desired.rx_entries = ring->rx_pending;
+ adapter->desired.tx_entries = ring->tx_pending;
+
+- ret = wait_for_reset(adapter);
+-
+- if (!ret &&
+- (adapter->req_rx_add_entries_per_subcrq != ring->rx_pending ||
+- adapter->req_tx_entries_per_subcrq != ring->tx_pending))
+- netdev_info(netdev,
+- "Could not match full ringsize request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n",
+- ring->rx_pending, ring->tx_pending,
+- adapter->req_rx_add_entries_per_subcrq,
+- adapter->req_tx_entries_per_subcrq);
+- return ret;
++ return wait_for_reset(adapter);
+ }
+
+ static void ibmvnic_get_channels(struct net_device *netdev,
+@@ -2947,14 +2997,8 @@ static void ibmvnic_get_channels(struct net_device *netdev,
+ {
+ struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+
+- if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) {
+- channels->max_rx = adapter->max_rx_queues;
+- channels->max_tx = adapter->max_tx_queues;
+- } else {
+- channels->max_rx = IBMVNIC_MAX_QUEUES;
+- channels->max_tx = IBMVNIC_MAX_QUEUES;
+- }
+-
++ channels->max_rx = adapter->max_rx_queues;
++ channels->max_tx = adapter->max_tx_queues;
+ channels->max_other = 0;
+ channels->max_combined = 0;
+ channels->rx_count = adapter->req_rx_queues;
+@@ -2967,22 +3011,11 @@ static int ibmvnic_set_channels(struct net_device *netdev,
+ struct ethtool_channels *channels)
+ {
+ struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+- int ret;
+
+- ret = 0;
+ adapter->desired.rx_queues = channels->rx_count;
+ adapter->desired.tx_queues = channels->tx_count;
+
+- ret = wait_for_reset(adapter);
+-
+- if (!ret &&
+- (adapter->req_rx_queues != channels->rx_count ||
+- adapter->req_tx_queues != channels->tx_count))
+- netdev_info(netdev,
+- "Could not match full channels request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n",
+- channels->rx_count, channels->tx_count,
+- adapter->req_rx_queues, adapter->req_tx_queues);
+- return ret;
++ return wait_for_reset(adapter);
+ }
+
+ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+@@ -2990,43 +3023,32 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+ struct ibmvnic_adapter *adapter = netdev_priv(dev);
+ int i;
+
+- switch (stringset) {
+- case ETH_SS_STATS:
+- for (i = 0; i < ARRAY_SIZE(ibmvnic_stats);
+- i++, data += ETH_GSTRING_LEN)
+- memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN);
++ if (stringset != ETH_SS_STATS)
++ return;
+
+- for (i = 0; i < adapter->req_tx_queues; i++) {
+- snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i);
+- data += ETH_GSTRING_LEN;
++ for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN)
++ memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN);
+
+- snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i);
+- data += ETH_GSTRING_LEN;
++ for (i = 0; i < adapter->req_tx_queues; i++) {
++ snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i);
++ data += ETH_GSTRING_LEN;
+
+- snprintf(data, ETH_GSTRING_LEN,
+- "tx%d_dropped_packets", i);
+- data += ETH_GSTRING_LEN;
+- }
++ snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i);
++ data += ETH_GSTRING_LEN;
+
+- for (i = 0; i < adapter->req_rx_queues; i++) {
+- snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i);
+- data += ETH_GSTRING_LEN;
++ snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i);
++ data += ETH_GSTRING_LEN;
++ }
+
+- snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i);
+- data += ETH_GSTRING_LEN;
++ for (i = 0; i < adapter->req_rx_queues; i++) {
++ snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i);
++ data += ETH_GSTRING_LEN;
+
+- snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i);
+- data += ETH_GSTRING_LEN;
+- }
+- break;
++ snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i);
++ data += ETH_GSTRING_LEN;
+
+- case ETH_SS_PRIV_FLAGS:
+- for (i = 0; i < ARRAY_SIZE(ibmvnic_priv_flags); i++)
+- strcpy(data + i * ETH_GSTRING_LEN,
+- ibmvnic_priv_flags[i]);
+- break;
+- default:
+- return;
++ snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i);
++ data += ETH_GSTRING_LEN;
+ }
+ }
+
+@@ -3039,8 +3061,6 @@ static int ibmvnic_get_sset_count(struct net_device *dev, int sset)
+ return ARRAY_SIZE(ibmvnic_stats) +
+ adapter->req_tx_queues * NUM_TX_STATS +
+ adapter->req_rx_queues * NUM_RX_STATS;
+- case ETH_SS_PRIV_FLAGS:
+- return ARRAY_SIZE(ibmvnic_priv_flags);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -3093,26 +3113,6 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
+ }
+ }
+
+-static u32 ibmvnic_get_priv_flags(struct net_device *netdev)
+-{
+- struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+-
+- return adapter->priv_flags;
+-}
+-
+-static int ibmvnic_set_priv_flags(struct net_device *netdev, u32 flags)
+-{
+- struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+- bool which_maxes = !!(flags & IBMVNIC_USE_SERVER_MAXES);
+-
+- if (which_maxes)
+- adapter->priv_flags |= IBMVNIC_USE_SERVER_MAXES;
+- else
+- adapter->priv_flags &= ~IBMVNIC_USE_SERVER_MAXES;
+-
+- return 0;
+-}
+-
+ static const struct ethtool_ops ibmvnic_ethtool_ops = {
+ .get_drvinfo = ibmvnic_get_drvinfo,
+ .get_msglevel = ibmvnic_get_msglevel,
+@@ -3126,8 +3126,6 @@ static const struct ethtool_ops ibmvnic_ethtool_ops = {
+ .get_sset_count = ibmvnic_get_sset_count,
+ .get_ethtool_stats = ibmvnic_get_ethtool_stats,
+ .get_link_ksettings = ibmvnic_get_link_ksettings,
+- .get_priv_flags = ibmvnic_get_priv_flags,
+- .set_priv_flags = ibmvnic_set_priv_flags,
+ };
+
+ /* Routines for managing CRQs/sCRQs */
+@@ -3456,9 +3454,15 @@ restart_loop:
+ (adapter->req_tx_entries_per_subcrq / 2) &&
+ __netif_subqueue_stopped(adapter->netdev,
+ scrq->pool_index)) {
+- netif_wake_subqueue(adapter->netdev, scrq->pool_index);
+- netdev_dbg(adapter->netdev, "Started queue %d\n",
+- scrq->pool_index);
++ rcu_read_lock();
++ if (adapter->tx_queues_active) {
++ netif_wake_subqueue(adapter->netdev,
++ scrq->pool_index);
++ netdev_dbg(adapter->netdev,
++ "Started queue %d\n",
++ scrq->pool_index);
++ }
++ rcu_read_unlock();
+ }
+ }
+
+@@ -3664,11 +3668,25 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
struct device *dev = &adapter->vdev->dev;
union ibmvnic_crq crq;
int max_entries;
@@ -74356,7 +112048,7 @@ index 6aa6ff89a7651..404921418f422 100644
if (adapter->min_tx_entries_per_subcrq > entries_page ||
adapter->min_rx_add_entries_per_subcrq > entries_page) {
dev_err(dev, "Fatal, invalid entries per sub-crq\n");
-@@ -3729,44 +3769,45 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
+@@ -3729,44 +3747,45 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
adapter->opt_rx_comp_queues;
adapter->req_rx_add_queues = adapter->max_rx_add_queues;
@@ -74409,7 +112101,7 @@ index 6aa6ff89a7651..404921418f422 100644
ibmvnic_send_crq(adapter, &crq);
if (adapter->netdev->flags & IFF_PROMISC) {
-@@ -3774,16 +3815,21 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
+@@ -3774,16 +3793,21 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
crq.request_capability.capability =
cpu_to_be16(PROMISC_REQUESTED);
crq.request_capability.number = cpu_to_be64(1);
@@ -74433,7 +112125,7 @@ index 6aa6ff89a7651..404921418f422 100644
}
static int pending_scrq(struct ibmvnic_adapter *adapter,
-@@ -4177,118 +4223,132 @@ static void send_query_map(struct ibmvnic_adapter *adapter)
+@@ -4177,118 +4201,132 @@ static void send_query_map(struct ibmvnic_adapter *adapter)
static void send_query_cap(struct ibmvnic_adapter *adapter)
{
union ibmvnic_crq crq;
@@ -74592,7 +112284,7 @@ index 6aa6ff89a7651..404921418f422 100644
}
static void send_query_ip_offload(struct ibmvnic_adapter *adapter)
-@@ -4593,6 +4653,8 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
+@@ -4593,6 +4631,8 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
char *name;
atomic_dec(&adapter->running_cap_crqs);
@@ -74601,7 +112293,7 @@ index 6aa6ff89a7651..404921418f422 100644
switch (be16_to_cpu(crq->request_capability_rsp.capability)) {
case REQ_TX_QUEUES:
req_value = &adapter->req_tx_queues;
-@@ -5069,11 +5131,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+@@ -5069,11 +5109,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
*/
adapter->login_pending = false;
@@ -74613,7 +112305,7 @@ index 6aa6ff89a7651..404921418f422 100644
if (adapter->state == VNIC_DOWN)
rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT);
else
-@@ -5094,6 +5151,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+@@ -5094,6 +5129,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
rc);
adapter->failover_pending = false;
}
@@ -74627,7 +112319,7 @@ index 6aa6ff89a7651..404921418f422 100644
break;
case IBMVNIC_CRQ_INIT_COMPLETE:
dev_info(dev, "Partner initialization complete\n");
-@@ -5114,6 +5178,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+@@ -5114,6 +5156,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
adapter->fw_done_rc = -EIO;
complete(&adapter->fw_done);
}
@@ -74641,7 +112333,7 @@ index 6aa6ff89a7651..404921418f422 100644
if (!completion_done(&adapter->stats_done))
complete(&adapter->stats_done);
if (test_bit(0, &adapter->resetting))
-@@ -5268,12 +5339,6 @@ static void ibmvnic_tasklet(struct tasklet_struct *t)
+@@ -5268,12 +5317,6 @@ static void ibmvnic_tasklet(struct tasklet_struct *t)
ibmvnic_handle_crq(crq, adapter);
crq->generic.first = 0;
}
@@ -74654,7 +112346,7 @@ index 6aa6ff89a7651..404921418f422 100644
}
/* if capabilities CRQ's were sent in this tasklet, the following
* tasklet must wait until all responses are received
-@@ -5414,6 +5479,9 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter)
+@@ -5414,6 +5457,9 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter)
crq->cur = 0;
spin_lock_init(&crq->lock);
@@ -74664,7 +112356,7 @@ index 6aa6ff89a7651..404921418f422 100644
return retrc;
req_irq_failed:
-@@ -5558,7 +5626,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+@@ -5558,7 +5604,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
}
rc = ibmvnic_reset_init(adapter, false);
@@ -74673,7 +112365,7 @@ index 6aa6ff89a7651..404921418f422 100644
/* We are ignoring the error from ibmvnic_reset_init() assuming that the
* partner is not ready. CRQ is not active. When the partner becomes
-@@ -5581,12 +5649,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+@@ -5581,12 +5627,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
goto ibmvnic_dev_file_err;
netif_carrier_off(netdev);
@@ -74686,7 +112378,7 @@ index 6aa6ff89a7651..404921418f422 100644
if (init_success) {
adapter->state = VNIC_PROBED;
-@@ -5599,6 +5661,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+@@ -5599,6 +5639,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
adapter->wait_for_reset = false;
adapter->last_reset_time = jiffies;
@@ -74701,7 +112393,7 @@ index 6aa6ff89a7651..404921418f422 100644
return 0;
ibmvnic_register_fail:
-@@ -5687,10 +5757,14 @@ static ssize_t failover_store(struct device *dev, struct device_attribute *attr,
+@@ -5687,10 +5735,14 @@ static ssize_t failover_store(struct device *dev, struct device_attribute *attr,
be64_to_cpu(session_token));
rc = plpar_hcall_norets(H_VIOCTL, adapter->vdev->unit_address,
H_SESSION_ERR_DETECTED, session_token, 0, 0);
@@ -74717,6 +112409,47 @@ index 6aa6ff89a7651..404921418f422 100644
last_resort:
netdev_dbg(netdev, "Trying to send CRQ_CMD, the last resort\n");
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
+index 22df602323bc0..1a9ed9202654f 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.h
++++ b/drivers/net/ethernet/ibm/ibmvnic.h
+@@ -43,11 +43,6 @@
+
+ #define IBMVNIC_RESET_DELAY 100
+
+-static const char ibmvnic_priv_flags[][ETH_GSTRING_LEN] = {
+-#define IBMVNIC_USE_SERVER_MAXES 0x1
+- "use-server-maxes"
+-};
+-
+ struct ibmvnic_login_buffer {
+ __be32 len;
+ __be32 version;
+@@ -885,7 +880,6 @@ struct ibmvnic_adapter {
+ struct ibmvnic_control_ip_offload_buffer ip_offload_ctrl;
+ dma_addr_t ip_offload_ctrl_tok;
+ u32 msg_enable;
+- u32 priv_flags;
+
+ /* Vital Product Data (VPD) */
+ struct ibmvnic_vpd *vpd;
+@@ -1002,11 +996,14 @@ struct ibmvnic_adapter {
+ struct work_struct ibmvnic_reset;
+ struct delayed_work ibmvnic_delayed_reset;
+ unsigned long resetting;
+- bool napi_enabled, from_passive_init;
+- bool login_pending;
+ /* last device reset time */
+ unsigned long last_reset_time;
+
++ bool napi_enabled;
++ bool from_passive_init;
++ bool login_pending;
++ /* protected by rcu */
++ bool tx_queues_active;
+ bool failover_pending;
+ bool force_reset_recovery;
+
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 09ae1939e6db4..36d52246bdc66 100644
--- a/drivers/net/ethernet/intel/e100.c
@@ -74814,9 +112547,20 @@ index bcf680e838113..13382df2f2eff 100644
bool autoneg_wait_to_complete;
};
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
-index 5e4fc9b4e2adb..d60e2016d03c6 100644
+index 5e4fc9b4e2adb..e6c8e6d5234f8 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -1009,8 +1009,8 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
+ {
+ u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
+ link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
+- u16 max_ltr_enc_d = 0; /* maximum LTR decoded by platform */
+- u16 lat_enc_d = 0; /* latency decoded */
++ u32 max_ltr_enc_d = 0; /* maximum LTR decoded by platform */
++ u32 lat_enc_d = 0; /* latency decoded */
+ u16 lat_enc = 0; /* latency encoded */
+
+ if (link) {
@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
bool blocked = false;
int i = 0;
@@ -75050,7 +112794,7 @@ index 39fb3d57c0574..56a3a6d1dbe41 100644
i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf);
i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
-index 291e61ac3e448..1e57cc8c47d7b 100644
+index 291e61ac3e448..9db5001297c7e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -240,7 +240,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
@@ -75077,8 +112821,21 @@ index 291e61ac3e448..1e57cc8c47d7b 100644
if (type == RING_TYPE_XDP && !i40e_enabled_xdp_vsi(vsi)) {
dev_info(&pf->pdev->dev, "XDP not enabled on VSI %d\n", vsi_seid);
return;
+@@ -734,10 +742,8 @@ static void i40e_dbg_dump_vf(struct i40e_pf *pf, int vf_id)
+ vsi = pf->vsi[vf->lan_vsi_idx];
+ dev_info(&pf->pdev->dev, "vf %2d: VSI id=%d, seid=%d, qps=%d\n",
+ vf_id, vf->lan_vsi_id, vsi->seid, vf->num_queue_pairs);
+- dev_info(&pf->pdev->dev, " num MDD=%lld, invalid msg=%lld, valid msg=%lld\n",
+- vf->num_mdd_events,
+- vf->num_invalid_msgs,
+- vf->num_valid_msgs);
++ dev_info(&pf->pdev->dev, " num MDD=%lld\n",
++ vf->num_mdd_events);
+ } else {
+ dev_info(&pf->pdev->dev, "invalid VF id %d\n", vf_id);
+ }
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
-index e04b540cedc85..ad73dd2540e71 100644
+index e04b540cedc85..29387f0814e9b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -99,6 +99,24 @@ MODULE_LICENSE("GPL v2");
@@ -75399,7 +113156,64 @@ index e04b540cedc85..ad73dd2540e71 100644
}
/* now onwards for main VSI, number of queues will be value
* of TC0's queue count
-@@ -7912,12 +7983,20 @@ config_tc:
+@@ -7464,42 +7535,43 @@ static void i40e_free_macvlan_channels(struct i40e_vsi *vsi)
+ static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
+ struct i40e_fwd_adapter *fwd)
+ {
++ struct i40e_channel *ch = NULL, *ch_tmp, *iter;
+ int ret = 0, num_tc = 1, i, aq_err;
+- struct i40e_channel *ch, *ch_tmp;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+
+- if (list_empty(&vsi->macvlan_list))
+- return -EINVAL;
+-
+ /* Go through the list and find an available channel */
+- list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {
+- if (!i40e_is_channel_macvlan(ch)) {
+- ch->fwd = fwd;
++ list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
++ if (!i40e_is_channel_macvlan(iter)) {
++ iter->fwd = fwd;
+ /* record configuration for macvlan interface in vdev */
+ for (i = 0; i < num_tc; i++)
+ netdev_bind_sb_channel_queue(vsi->netdev, vdev,
+ i,
+- ch->num_queue_pairs,
+- ch->base_queue);
+- for (i = 0; i < ch->num_queue_pairs; i++) {
++ iter->num_queue_pairs,
++ iter->base_queue);
++ for (i = 0; i < iter->num_queue_pairs; i++) {
+ struct i40e_ring *tx_ring, *rx_ring;
+ u16 pf_q;
+
+- pf_q = ch->base_queue + i;
++ pf_q = iter->base_queue + i;
+
+ /* Get to TX ring ptr */
+ tx_ring = vsi->tx_rings[pf_q];
+- tx_ring->ch = ch;
++ tx_ring->ch = iter;
+
+ /* Get the RX ring ptr */
+ rx_ring = vsi->rx_rings[pf_q];
+- rx_ring->ch = ch;
++ rx_ring->ch = iter;
+ }
++ ch = iter;
+ break;
+ }
+ }
+
++ if (!ch)
++ return -EINVAL;
++
+ /* Guarantee all rings are updated before we update the
+ * MAC address filter.
+ */
+@@ -7912,12 +7984,20 @@ config_tc:
vsi->seid);
need_reset = true;
goto exit;
@@ -75424,7 +113238,7 @@ index e04b540cedc85..ad73dd2540e71 100644
if (pf->flags & I40E_FLAG_TC_MQPRIO) {
if (vsi->mqprio_qopt.max_rate[0]) {
u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
-@@ -8482,9 +8561,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
+@@ -8482,9 +8562,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
err = i40e_add_del_cloud_filter(vsi, filter, true);
if (err) {
@@ -75436,7 +113250,7 @@ index e04b540cedc85..ad73dd2540e71 100644
goto err;
}
-@@ -8668,6 +8746,27 @@ int i40e_open(struct net_device *netdev)
+@@ -8668,6 +8747,27 @@ int i40e_open(struct net_device *netdev)
return 0;
}
@@ -75464,7 +113278,7 @@ index e04b540cedc85..ad73dd2540e71 100644
/**
* i40e_vsi_open -
* @vsi: the VSI to open
-@@ -8704,13 +8803,7 @@ int i40e_vsi_open(struct i40e_vsi *vsi)
+@@ -8704,13 +8804,7 @@ int i40e_vsi_open(struct i40e_vsi *vsi)
goto err_setup_rx;
/* Notify the stack of the actual queue counts. */
@@ -75479,7 +113293,7 @@ index e04b540cedc85..ad73dd2540e71 100644
if (err)
goto err_set_queues;
-@@ -10487,15 +10580,9 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
+@@ -10487,15 +10581,9 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
}
i40e_get_oem_version(&pf->hw);
@@ -75498,7 +113312,7 @@ index e04b540cedc85..ad73dd2540e71 100644
}
/* re-verify the eeprom if we just had an EMP reset */
-@@ -10766,6 +10853,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
+@@ -10766,6 +10854,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
bool lock_acquired)
{
int ret;
@@ -75508,7 +113322,7 @@ index e04b540cedc85..ad73dd2540e71 100644
/* Now we wait for GRST to settle out.
* We don't have to delete the VEBs or VSIs from the hw switch
* because the reset will make them disappear.
-@@ -11705,7 +11795,6 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf)
+@@ -11705,7 +11796,6 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf)
return -ENOMEM;
pf->irq_pile->num_entries = vectors;
@@ -75516,7 +113330,7 @@ index e04b540cedc85..ad73dd2540e71 100644
/* track first vector for misc interrupts, ignore return */
(void)i40e_get_lump(pf, pf->irq_pile, 1, I40E_PILE_VALID_BIT - 1);
-@@ -12126,6 +12215,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
+@@ -12126,6 +12216,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
vsi->req_queue_pairs = queue_count;
i40e_prep_for_reset(pf);
@@ -75525,7 +113339,7 @@ index e04b540cedc85..ad73dd2540e71 100644
pf->alloc_rss_size = new_rss_size;
-@@ -12508,7 +12599,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
+@@ -12508,7 +12600,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
goto sw_init_done;
}
pf->qp_pile->num_entries = pf->hw.func_caps.num_tx_qp;
@@ -75533,7 +113347,7 @@ index e04b540cedc85..ad73dd2540e71 100644
pf->tx_timeout_recovery_level = 1;
-@@ -12953,6 +13043,10 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
+@@ -12953,6 +13044,10 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
if (need_reset)
i40e_prep_for_reset(pf);
@@ -75544,7 +113358,7 @@ index e04b540cedc85..ad73dd2540e71 100644
old_prog = xchg(&vsi->xdp_prog, prog);
if (need_reset) {
-@@ -13771,7 +13865,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
+@@ -13771,7 +13866,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
return -ENODEV;
}
@@ -75553,7 +113367,7 @@ index e04b540cedc85..ad73dd2540e71 100644
uplink_seid = vsi->uplink_seid;
if (vsi->type != I40E_VSI_SRIOV) {
if (vsi->netdev_registered) {
-@@ -14101,6 +14195,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
+@@ -14101,6 +14196,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
case I40E_VSI_MAIN:
case I40E_VSI_VMDQ2:
ret = i40e_config_netdev(vsi);
@@ -75563,7 +113377,7 @@ index e04b540cedc85..ad73dd2540e71 100644
if (ret)
goto err_netdev;
ret = register_netdev(vsi->netdev);
-@@ -15403,8 +15500,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -15403,8 +15501,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw))
@@ -75574,7 +113388,7 @@ index e04b540cedc85..ad73dd2540e71 100644
hw->aq.api_maj_ver,
hw->aq.api_min_ver,
I40E_FW_API_VERSION_MAJOR,
-@@ -15840,8 +15937,13 @@ static void i40e_remove(struct pci_dev *pdev)
+@@ -15840,8 +15938,13 @@ static void i40e_remove(struct pci_dev *pdev)
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
@@ -75589,7 +113403,7 @@ index e04b540cedc85..ad73dd2540e71 100644
if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
set_bit(__I40E_VF_RESETS_DISABLED, pf->state);
-@@ -16040,6 +16142,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev)
+@@ -16040,6 +16143,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
@@ -75614,7 +113428,7 @@ index 8d0588a27a053..1908eed4fa5ee 100644
#define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
#define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
-index 472f56b360b8c..c6f643e54c4f7 100644
+index 472f56b360b8c..babf8b7fa7678 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -183,17 +183,18 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
@@ -75754,63 +113568,33 @@ index 472f56b360b8c..c6f643e54c4f7 100644
reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
reg |= I40E_VPGEN_VFRTRIG_VFSWR_MASK;
wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
-@@ -1868,17 +1917,19 @@ sriov_configure_out:
- /***********************virtual channel routines******************/
-
- /**
-- * i40e_vc_send_msg_to_vf
-+ * i40e_vc_send_msg_to_vf_ex
- * @vf: pointer to the VF info
- * @v_opcode: virtual channel opcode
- * @v_retval: virtual channel return value
- * @msg: pointer to the msg buffer
- * @msglen: msg length
-+ * @is_quiet: true for not printing unsuccessful return values, false otherwise
- *
- * send msg to VF
- **/
--static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
-- u32 v_retval, u8 *msg, u16 msglen)
-+static int i40e_vc_send_msg_to_vf_ex(struct i40e_vf *vf, u32 v_opcode,
-+ u32 v_retval, u8 *msg, u16 msglen,
-+ bool is_quiet)
- {
- struct i40e_pf *pf;
- struct i40e_hw *hw;
-@@ -1894,7 +1945,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
+@@ -1893,25 +1942,6 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
+ hw = &pf->hw;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
- /* single place to detect unsuccessful return values */
+- /* single place to detect unsuccessful return values */
- if (v_retval) {
-+ if (v_retval && !is_quiet) {
- vf->num_invalid_msgs++;
- dev_info(&pf->pdev->dev, "VF %d failed opcode %d, retval: %d\n",
- vf->vf_id, v_opcode, v_retval);
-@@ -1924,6 +1975,23 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
- return 0;
- }
-
-+/**
-+ * i40e_vc_send_msg_to_vf
-+ * @vf: pointer to the VF info
-+ * @v_opcode: virtual channel opcode
-+ * @v_retval: virtual channel return value
-+ * @msg: pointer to the msg buffer
-+ * @msglen: msg length
-+ *
-+ * send msg to VF
-+ **/
-+static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
-+ u32 v_retval, u8 *msg, u16 msglen)
-+{
-+ return i40e_vc_send_msg_to_vf_ex(vf, v_opcode, v_retval,
-+ msg, msglen, false);
-+}
-+
- /**
- * i40e_vc_send_resp_to_vf
- * @vf: pointer to the VF info
-@@ -1939,6 +2007,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf,
+- vf->num_invalid_msgs++;
+- dev_info(&pf->pdev->dev, "VF %d failed opcode %d, retval: %d\n",
+- vf->vf_id, v_opcode, v_retval);
+- if (vf->num_invalid_msgs >
+- I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED) {
+- dev_err(&pf->pdev->dev,
+- "Number of invalid messages exceeded for VF %d\n",
+- vf->vf_id);
+- dev_err(&pf->pdev->dev, "Use PF Control I/F to enable the VF\n");
+- set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
+- }
+- } else {
+- vf->num_valid_msgs++;
+- /* reset the invalid counter, if a valid message is received. */
+- vf->num_invalid_msgs = 0;
+- }
+-
+ aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
+ msg, msglen, NULL);
+ if (aq_ret) {
+@@ -1939,6 +1969,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf,
return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0);
}
@@ -75843,7 +113627,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
/**
* i40e_vc_get_version_msg
* @vf: pointer to the VF info
-@@ -1999,7 +2093,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
+@@ -1999,7 +2055,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
size_t len = 0;
int ret;
@@ -75852,7 +113636,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -2105,20 +2199,6 @@ err:
+@@ -2105,20 +2161,6 @@ err:
return ret;
}
@@ -75873,7 +113657,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
/**
* i40e_vc_config_promiscuous_mode_msg
* @vf: pointer to the VF info
-@@ -2136,7 +2216,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2136,7 +2178,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg)
bool allmulti = false;
bool alluni = false;
@@ -75882,7 +113666,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err_out;
}
-@@ -2217,13 +2297,14 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2217,13 +2259,14 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
struct virtchnl_vsi_queue_config_info *qci =
(struct virtchnl_vsi_queue_config_info *)msg;
struct virtchnl_queue_pair_info *qpi;
@@ -75900,7 +113684,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto error_param;
}
-@@ -2310,9 +2391,15 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2310,9 +2353,15 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
pf->vsi[vf->lan_vsi_idx]->num_queue_pairs =
qci->num_queue_pairs;
} else {
@@ -75919,7 +113703,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
}
error_param:
-@@ -2366,7 +2453,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2366,7 +2415,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
int i;
@@ -75928,7 +113712,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto error_param;
}
-@@ -2538,7 +2625,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2538,7 +2587,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg)
struct i40e_pf *pf = vf->pf;
i40e_status aq_ret = 0;
@@ -75937,7 +113721,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto error_param;
}
-@@ -2570,6 +2657,59 @@ error_param:
+@@ -2570,6 +2619,59 @@ error_param:
aq_ret);
}
@@ -75997,7 +113781,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
/**
* i40e_vc_request_queues_msg
* @vf: pointer to the VF info
-@@ -2588,7 +2728,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2588,7 +2690,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
u8 cur_pairs = vf->num_queue_pairs;
struct i40e_pf *pf = vf->pf;
@@ -76006,7 +113790,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
return -EINVAL;
if (req_pairs > I40E_MAX_VF_QUEUES) {
-@@ -2604,11 +2744,16 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2604,11 +2706,16 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
req_pairs - cur_pairs,
pf->queues_left);
vfres->num_queue_pairs = pf->queues_left + cur_pairs;
@@ -76025,7 +113809,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
return 0;
}
-@@ -2634,7 +2779,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2634,7 +2741,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg)
memset(&stats, 0, sizeof(struct i40e_eth_stats));
@@ -76034,44 +113818,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto error_param;
}
-@@ -2668,6 +2813,7 @@ error_param:
- * i40e_check_vf_permission
- * @vf: pointer to the VF info
- * @al: MAC address list from virtchnl
-+ * @is_quiet: set true for printing msg without opcode info, false otherwise
- *
- * Check that the given list of MAC addresses is allowed. Will return -EPERM
- * if any address in the list is not valid. Checks the following conditions:
-@@ -2682,13 +2828,15 @@ error_param:
- * addresses might not be accurate.
- **/
- static inline int i40e_check_vf_permission(struct i40e_vf *vf,
-- struct virtchnl_ether_addr_list *al)
-+ struct virtchnl_ether_addr_list *al,
-+ bool *is_quiet)
- {
- struct i40e_pf *pf = vf->pf;
- struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
- int mac2add_cnt = 0;
- int i;
-
-+ *is_quiet = false;
- for (i = 0; i < al->num_elements; i++) {
- struct i40e_mac_filter *f;
- u8 *addr = al->list[i].addr;
-@@ -2712,6 +2860,7 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
- !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
- dev_err(&pf->pdev->dev,
- "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
-+ *is_quiet = true;
- return -EPERM;
- }
-
-@@ -2748,10 +2897,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
- (struct virtchnl_ether_addr_list *)msg;
- struct i40e_pf *pf = vf->pf;
- struct i40e_vsi *vsi = NULL;
-+ bool is_quiet = false;
+@@ -2751,7 +2858,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
i40e_status ret = 0;
int i;
@@ -76080,27 +113827,18 @@ index 472f56b360b8c..c6f643e54c4f7 100644
!i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) {
ret = I40E_ERR_PARAM;
goto error_param;
-@@ -2764,7 +2914,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
- */
- spin_lock_bh(&vsi->mac_filter_hash_lock);
-
-- ret = i40e_check_vf_permission(vf, al);
-+ ret = i40e_check_vf_permission(vf, al, &is_quiet);
- if (ret) {
- spin_unlock_bh(&vsi->mac_filter_hash_lock);
- goto error_param;
-@@ -2802,8 +2952,8 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2802,8 +2909,8 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
error_param:
/* send the response to the VF */
- return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
- ret);
-+ return i40e_vc_send_msg_to_vf_ex(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
-+ ret, NULL, 0, is_quiet);
++ return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
++ ret, NULL, 0);
}
/**
-@@ -2823,7 +2973,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2823,7 +2930,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
i40e_status ret = 0;
int i;
@@ -76109,7 +113847,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
!i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) {
ret = I40E_ERR_PARAM;
goto error_param;
-@@ -2967,7 +3117,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg)
+@@ -2967,7 +3074,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
int i;
@@ -76118,7 +113856,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
!i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) {
aq_ret = I40E_ERR_PARAM;
goto error_param;
-@@ -3087,9 +3237,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg)
+@@ -3087,9 +3194,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg)
struct i40e_vsi *vsi = NULL;
i40e_status aq_ret = 0;
@@ -76130,7 +113868,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3118,9 +3268,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg)
+@@ -3118,9 +3225,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
u16 i;
@@ -76142,7 +113880,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3153,7 +3303,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg)
+@@ -3153,7 +3260,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
int len = 0;
@@ -76151,7 +113889,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3189,7 +3339,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg)
+@@ -3189,7 +3296,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg)
struct i40e_hw *hw = &pf->hw;
i40e_status aq_ret = 0;
@@ -76160,7 +113898,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3214,7 +3364,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg)
+@@ -3214,7 +3321,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
struct i40e_vsi *vsi;
@@ -76169,7 +113907,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3240,7 +3390,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg)
+@@ -3240,7 +3347,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
struct i40e_vsi *vsi;
@@ -76178,7 +113916,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3467,7 +3617,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg)
+@@ -3467,7 +3574,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
int i, ret;
@@ -76187,7 +113925,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3598,7 +3748,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
+@@ -3598,7 +3705,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
int i, ret;
@@ -76196,7 +113934,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err_out;
}
-@@ -3707,7 +3857,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
+@@ -3707,7 +3814,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
i40e_status aq_ret = 0;
u64 speed = 0;
@@ -76205,7 +113943,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3796,15 +3946,9 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
+@@ -3796,15 +3903,9 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
/* set this flag only after making sure all inputs are sane */
vf->adq_enabled = true;
@@ -76222,7 +113960,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
return I40E_SUCCESS;
-@@ -3824,7 +3968,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg)
+@@ -3824,7 +3925,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg)
struct i40e_pf *pf = vf->pf;
i40e_status aq_ret = 0;
@@ -76231,7 +113969,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
aq_ret = I40E_ERR_PARAM;
goto err;
}
-@@ -3844,8 +3988,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg)
+@@ -3844,8 +3945,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg)
}
/* reset the VF in order to allocate resources */
@@ -76241,7 +113979,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
return I40E_SUCCESS;
-@@ -3907,7 +4050,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
+@@ -3907,7 +4007,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
i40e_vc_notify_vf_link_state(vf);
break;
case VIRTCHNL_OP_RESET_VF:
@@ -76250,7 +113988,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
ret = 0;
break;
case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
-@@ -4161,7 +4304,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
+@@ -4161,7 +4261,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
/* Force the VF interface down so it has to bring up with new MAC
* address
*/
@@ -76259,7 +113997,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n");
error_param:
-@@ -4169,34 +4312,6 @@ error_param:
+@@ -4169,34 +4269,6 @@ error_param:
return ret;
}
@@ -76294,7 +114032,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
/**
* i40e_ndo_set_vf_port_vlan
* @netdev: network interface device structure
-@@ -4253,19 +4368,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
+@@ -4253,19 +4325,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
/* duplicate request, so just return success */
goto error_pvid;
@@ -76317,7 +114055,7 @@ index 472f56b360b8c..c6f643e54c4f7 100644
/* Locked once because multiple functions below iterate list */
spin_lock_bh(&vsi->mac_filter_hash_lock);
-@@ -4641,7 +4746,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
+@@ -4641,7 +4703,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
goto out;
vf->trusted = setting;
@@ -76327,10 +114065,18 @@ index 472f56b360b8c..c6f643e54c4f7 100644
vf_id, setting ? "" : "un");
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
-index 091e32c1bb46f..03c42fd0fea19 100644
+index 091e32c1bb46f..a554d0a0b09bd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
-@@ -18,6 +18,9 @@
+@@ -10,14 +10,15 @@
+
+ #define I40E_VIRTCHNL_SUPPORTED_QTYPES 2
+
+-#define I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED 10
+-
+ #define I40E_VLAN_PRIORITY_SHIFT 13
+ #define I40E_VLAN_MASK 0xFFF
+ #define I40E_PRIORITY_MASK 0xE000
#define I40E_MAX_VF_PROMISC_FLAGS 3
@@ -76340,6 +114086,52 @@ index 091e32c1bb46f..03c42fd0fea19 100644
/* Various queue ctrls */
enum i40e_queue_ctrl {
I40E_QUEUE_CTRL_UNKNOWN = 0,
+@@ -89,9 +90,6 @@ struct i40e_vf {
+ u8 num_queue_pairs; /* num of qps assigned to VF vsis */
+ u8 num_req_queues; /* num of requested qps */
+ u64 num_mdd_events; /* num of mdd events detected */
+- /* num of continuous malformed or invalid msgs detected */
+- u64 num_invalid_msgs;
+- u64 num_valid_msgs; /* num of valid msgs detected */
+
+ unsigned long vf_caps; /* vf's adv. capabilities */
+ unsigned long vf_states; /* vf's runtime states */
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+index e7e778ca074c0..3f27a8ebe2ec2 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+@@ -243,21 +243,25 @@ no_buffers:
+ static struct sk_buff *i40e_construct_skb_zc(struct i40e_ring *rx_ring,
+ struct xdp_buff *xdp)
+ {
++ unsigned int totalsize = xdp->data_end - xdp->data_meta;
+ unsigned int metasize = xdp->data - xdp->data_meta;
+- unsigned int datasize = xdp->data_end - xdp->data;
+ struct sk_buff *skb;
+
++ net_prefetch(xdp->data_meta);
++
+ /* allocate a skb to store the frags */
+- skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
+- xdp->data_end - xdp->data_hard_start,
++ skb = __napi_alloc_skb(&rx_ring->q_vector->napi, totalsize,
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ goto out;
+
+- skb_reserve(skb, xdp->data - xdp->data_hard_start);
+- memcpy(__skb_put(skb, datasize), xdp->data, datasize);
+- if (metasize)
++ memcpy(__skb_put(skb, totalsize), xdp->data_meta,
++ ALIGN(totalsize, sizeof(long)));
++
++ if (metasize) {
+ skb_metadata_set(skb, metasize);
++ __skb_pull(skb, metasize);
++ }
+
+ out:
+ xsk_buff_free(xdp);
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 68c80f04113c8..9a122aea69793 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
@@ -76659,7 +114451,7 @@ index 5a359a0a20ecc..461f5237a2f88 100644
return 0;
}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
-index cada4e0e40b48..711e8c7f62de7 100644
+index cada4e0e40b48..ca74824d40b85 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -14,7 +14,7 @@
@@ -77059,7 +114851,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!reg_val) {
adapter->flags |= IAVF_FLAG_RESET_PENDING;
-@@ -2007,22 +2115,22 @@ static void iavf_watchdog_task(struct work_struct *work)
+@@ -2007,24 +2115,31 @@ static void iavf_watchdog_task(struct work_struct *work)
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
queue_work(iavf_wq, &adapter->reset_task);
@@ -77087,8 +114879,17 @@ index cada4e0e40b48..711e8c7f62de7 100644
- queue_work(iavf_wq, &adapter->adminq_task);
}
++/**
++ * iavf_disable_vf - disable VF
++ * @adapter: board private structure
++ *
++ * Set communication failed flag and free all resources.
++ * NOTE: This function is expected to be called with crit_lock being held.
++ **/
static void iavf_disable_vf(struct iavf_adapter *adapter)
-@@ -2074,14 +2182,14 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
+ {
+ struct iavf_mac_filter *f, *ftmp;
+@@ -2074,14 +2189,13 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
iavf_free_misc_irq(adapter);
iavf_reset_interrupt_capability(adapter);
@@ -77098,14 +114899,14 @@ index cada4e0e40b48..711e8c7f62de7 100644
memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);
iavf_shutdown_adminq(&adapter->hw);
adapter->netdev->flags &= ~IFF_UP;
- mutex_unlock(&adapter->crit_lock);
+- mutex_unlock(&adapter->crit_lock);
adapter->flags &= ~IAVF_FLAG_RESET_PENDING;
- adapter->state = __IAVF_DOWN;
+ iavf_change_state(adapter, __IAVF_DOWN);
wake_up(&adapter->down_waitqueue);
dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
}
-@@ -2103,7 +2211,6 @@ static void iavf_reset_task(struct work_struct *work)
+@@ -2103,7 +2217,6 @@ static void iavf_reset_task(struct work_struct *work)
struct net_device *netdev = adapter->netdev;
struct iavf_hw *hw = &adapter->hw;
struct iavf_mac_filter *f, *ftmp;
@@ -77113,7 +114914,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
struct iavf_cloud_filter *cf;
u32 reg_val;
int i = 0, err;
-@@ -2112,13 +2219,13 @@ static void iavf_reset_task(struct work_struct *work)
+@@ -2112,13 +2225,13 @@ static void iavf_reset_task(struct work_struct *work)
/* When device is being removed it doesn't make sense to run the reset
* task, just return in such a case.
*/
@@ -77131,7 +114932,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
while (!mutex_trylock(&adapter->client_lock))
usleep_range(500, 1000);
if (CLIENT_ENABLED(adapter)) {
-@@ -2166,12 +2273,14 @@ static void iavf_reset_task(struct work_struct *work)
+@@ -2166,12 +2279,14 @@ static void iavf_reset_task(struct work_struct *work)
}
pci_set_master(adapter->pdev);
@@ -77146,7 +114947,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
return; /* Do not attempt to reinit. It's dead, Jim. */
}
-@@ -2180,8 +2289,7 @@ continue_reset:
+@@ -2180,8 +2295,7 @@ continue_reset:
* ndo_open() returning, so we can't assume it means all our open
* tasks have finished, since we're not holding the rtnl_lock here.
*/
@@ -77156,7 +114957,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
if (running) {
netif_carrier_off(netdev);
-@@ -2191,7 +2299,7 @@ continue_reset:
+@@ -2191,7 +2305,7 @@ continue_reset:
}
iavf_irq_disable(adapter);
@@ -77165,7 +114966,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
adapter->flags &= ~IAVF_FLAG_RESET_PENDING;
/* free the Tx/Rx rings and descriptors, might be better to just
-@@ -2243,11 +2351,6 @@ continue_reset:
+@@ -2243,11 +2357,6 @@ continue_reset:
list_for_each_entry(f, &adapter->mac_filter_list, list) {
f->add = true;
}
@@ -77177,7 +114978,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
spin_unlock_bh(&adapter->mac_vlan_list_lock);
/* check if TCs are running and re-add all cloud filters */
-@@ -2261,7 +2364,6 @@ continue_reset:
+@@ -2261,7 +2370,6 @@ continue_reset:
spin_unlock_bh(&adapter->cloud_filter_list_lock);
adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
@@ -77185,7 +114986,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER;
iavf_misc_irq_enable(adapter);
-@@ -2291,11 +2393,14 @@ continue_reset:
+@@ -2291,11 +2399,14 @@ continue_reset:
iavf_configure(adapter);
@@ -77201,7 +115002,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
wake_up(&adapter->down_waitqueue);
}
mutex_unlock(&adapter->client_lock);
-@@ -2305,6 +2410,8 @@ continue_reset:
+@@ -2305,6 +2416,8 @@ continue_reset:
reset_err:
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
@@ -77210,7 +115011,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
iavf_close(netdev);
}
-@@ -2327,13 +2434,19 @@ static void iavf_adminq_task(struct work_struct *work)
+@@ -2327,13 +2440,19 @@ static void iavf_adminq_task(struct work_struct *work)
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
goto out;
@@ -77232,7 +115033,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
do {
ret = iavf_clean_arq_element(hw, &event, &pending);
v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
-@@ -2349,6 +2462,18 @@ static void iavf_adminq_task(struct work_struct *work)
+@@ -2349,6 +2468,18 @@ static void iavf_adminq_task(struct work_struct *work)
} while (pending);
mutex_unlock(&adapter->crit_lock);
@@ -77251,7 +115052,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
if ((adapter->flags &
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
adapter->state == __IAVF_RESETTING)
-@@ -2356,7 +2481,7 @@ static void iavf_adminq_task(struct work_struct *work)
+@@ -2356,7 +2487,7 @@ static void iavf_adminq_task(struct work_struct *work)
/* check for error indications */
val = rd32(hw, hw->aq.arq.len);
@@ -77260,7 +115061,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
goto freedom;
oldval = val;
if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) {
-@@ -2624,8 +2749,11 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter,
+@@ -2624,8 +2755,11 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter,
total_max_rate += tx_rate;
num_qps += mqprio_qopt->qopt.count[i];
}
@@ -77273,7 +115074,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
ret = iavf_validate_tx_bandwidth(adapter, total_max_rate);
return ret;
-@@ -3041,8 +3169,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
+@@ -3041,8 +3175,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
return -ENOMEM;
while (!mutex_trylock(&adapter->crit_lock)) {
@@ -77286,7 +115087,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
udelay(1);
}
-@@ -3053,11 +3183,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
+@@ -3053,11 +3189,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
/* start out with flow type and eth type IPv4 to begin with */
filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
err = iavf_parse_cls_flower(adapter, cls_flower, filter);
@@ -77300,7 +115101,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
goto err;
/* add filter to the list */
-@@ -3226,6 +3356,13 @@ static int iavf_open(struct net_device *netdev)
+@@ -3226,6 +3362,13 @@ static int iavf_open(struct net_device *netdev)
goto err_unlock;
}
@@ -77314,7 +115115,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
/* allocate transmit descriptors */
err = iavf_setup_all_tx_resources(adapter);
if (err)
-@@ -3247,6 +3384,9 @@ static int iavf_open(struct net_device *netdev)
+@@ -3247,6 +3390,9 @@ static int iavf_open(struct net_device *netdev)
spin_unlock_bh(&adapter->mac_vlan_list_lock);
@@ -77324,7 +115125,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
iavf_configure(adapter);
iavf_up_complete(adapter);
-@@ -3286,18 +3426,19 @@ static int iavf_close(struct net_device *netdev)
+@@ -3286,18 +3432,19 @@ static int iavf_close(struct net_device *netdev)
struct iavf_adapter *adapter = netdev_priv(netdev);
int status;
@@ -77349,7 +115150,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
iavf_free_traffic_irqs(adapter);
mutex_unlock(&adapter->crit_lock);
-@@ -3337,8 +3478,11 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
+@@ -3337,8 +3484,11 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
iavf_notify_client_l2_params(&adapter->vsi);
adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
}
@@ -77363,7 +115164,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
return 0;
}
-@@ -3354,11 +3498,16 @@ static int iavf_set_features(struct net_device *netdev,
+@@ -3354,11 +3504,16 @@ static int iavf_set_features(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
@@ -77383,7 +115184,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
return -EINVAL;
} else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) {
if (features & NETIF_F_HW_VLAN_CTAG_RX)
-@@ -3442,7 +3591,8 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
+@@ -3442,7 +3597,8 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
@@ -77393,7 +115194,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER);
-@@ -3630,72 +3780,14 @@ int iavf_process_config(struct iavf_adapter *adapter)
+@@ -3630,72 +3786,14 @@ int iavf_process_config(struct iavf_adapter *adapter)
return 0;
}
@@ -77468,7 +115269,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
netif_device_detach(netdev);
-@@ -3705,7 +3797,7 @@ static void iavf_shutdown(struct pci_dev *pdev)
+@@ -3705,7 +3803,7 @@ static void iavf_shutdown(struct pci_dev *pdev)
if (iavf_lock_timeout(&adapter->crit_lock, 5000))
dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
/* Prevent the watchdog from running. */
@@ -77477,7 +115278,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
adapter->aq_required = 0;
mutex_unlock(&adapter->crit_lock);
-@@ -3778,7 +3870,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -3778,7 +3876,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->back = adapter;
adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
@@ -77486,7 +115287,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
/* Call save state here because it relies on the adapter struct. */
pci_save_state(pdev);
-@@ -3803,7 +3895,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -3803,7 +3901,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
mutex_init(&adapter->crit_lock);
mutex_init(&adapter->client_lock);
@@ -77494,7 +115295,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
mutex_init(&hw->aq.asq_mutex);
mutex_init(&hw->aq.arq_mutex);
-@@ -3822,8 +3913,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -3822,8 +3919,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
@@ -77504,7 +115305,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
/* Setup the wait queue for indicating transition to down status */
-@@ -3880,10 +3970,11 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
+@@ -3880,10 +3976,11 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
static int __maybe_unused iavf_resume(struct device *dev_d)
{
struct pci_dev *pdev = to_pci_dev(dev_d);
@@ -77518,7 +115319,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
pci_set_master(pdev);
rtnl_lock();
-@@ -3902,7 +3993,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
+@@ -3902,7 +3999,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
queue_work(iavf_wq, &adapter->reset_task);
@@ -77527,7 +115328,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
return err;
}
-@@ -3918,8 +4009,8 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
+@@ -3918,8 +4015,8 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
**/
static void iavf_remove(struct pci_dev *pdev)
{
@@ -77538,7 +115339,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
struct iavf_fdir_fltr *fdir, *fdirtmp;
struct iavf_vlan_filter *vlf, *vlftmp;
struct iavf_adv_rss *rss, *rsstmp;
-@@ -3927,14 +4018,30 @@ static void iavf_remove(struct pci_dev *pdev)
+@@ -3927,14 +4024,37 @@ static void iavf_remove(struct pci_dev *pdev)
struct iavf_cloud_filter *cf, *cftmp;
struct iavf_hw *hw = &adapter->hw;
int err;
@@ -77548,6 +115349,13 @@ index cada4e0e40b48..711e8c7f62de7 100644
- cancel_work_sync(&adapter->reset_task);
- cancel_delayed_work_sync(&adapter->client_task);
+
++ /* When reboot/shutdown is in progress no need to do anything
++ * as the adapter is already REMOVE state that was set during
++ * iavf_shutdown() callback.
++ */
++ if (adapter->state == __IAVF_REMOVE)
++ return;
++
+ set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section);
+ /* Wait until port initialization is complete.
+ * There are flows where register/unregister netdev may race.
@@ -77575,7 +115383,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
}
if (CLIENT_ALLOWED(adapter)) {
err = iavf_lan_del_device(adapter);
-@@ -3943,6 +4050,10 @@ static void iavf_remove(struct pci_dev *pdev)
+@@ -3943,6 +4063,10 @@ static void iavf_remove(struct pci_dev *pdev)
err);
}
@@ -77586,7 +115394,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
iavf_request_reset(adapter);
msleep(50);
/* If the FW isn't responding, kick it once, but only once. */
-@@ -3950,24 +4061,24 @@ static void iavf_remove(struct pci_dev *pdev)
+@@ -3950,24 +4074,24 @@ static void iavf_remove(struct pci_dev *pdev)
iavf_request_reset(adapter);
msleep(50);
}
@@ -77619,7 +115427,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
iavf_free_rss(adapter);
if (hw->aq.asq.count)
-@@ -3979,8 +4090,6 @@ static void iavf_remove(struct pci_dev *pdev)
+@@ -3979,8 +4103,6 @@ static void iavf_remove(struct pci_dev *pdev)
mutex_destroy(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
mutex_destroy(&adapter->crit_lock);
@@ -77629,7 +115437,7 @@ index cada4e0e40b48..711e8c7f62de7 100644
iounmap(hw->hw_addr);
pci_release_regions(pdev);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
-index 3c735968e1b85..8a1c293b8c7ab 100644
+index 3c735968e1b85..7013769fc0389 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -607,7 +607,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
@@ -77672,7 +115480,49 @@ index 3c735968e1b85..8a1c293b8c7ab 100644
adapter->current_op = VIRTCHNL_OP_GET_STATS;
vqs.vsi_id = adapter->vsi_res->vsi_id;
/* queue maps are ignored for this message - only the vsi is used */
-@@ -1722,8 +1734,25 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+@@ -1448,6 +1460,22 @@ void iavf_request_reset(struct iavf_adapter *adapter)
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ }
+
++/**
++ * iavf_netdev_features_vlan_strip_set - update vlan strip status
++ * @netdev: ptr to netdev being adjusted
++ * @enable: enable or disable vlan strip
++ *
++ * Helper function to change vlan strip status in netdev->features.
++ */
++static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
++ const bool enable)
++{
++ if (enable)
++ netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
++ else
++ netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
++}
++
+ /**
+ * iavf_virtchnl_completion
+ * @adapter: adapter structure
+@@ -1671,8 +1699,18 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+ }
+ break;
+ case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
++ dev_warn(&adapter->pdev->dev, "Changing VLAN Stripping is not allowed when Port VLAN is configured\n");
++ /* Vlan stripping could not be enabled by ethtool.
++ * Disable it in netdev->features.
++ */
++ iavf_netdev_features_vlan_strip_set(netdev, false);
++ break;
+ case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
+ dev_warn(&adapter->pdev->dev, "Changing VLAN Stripping is not allowed when Port VLAN is configured\n");
++ /* Vlan stripping could not be disabled by ethtool.
++ * Enable it in netdev->features.
++ */
++ iavf_netdev_features_vlan_strip_set(netdev, true);
+ break;
+ default:
+ dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
+@@ -1722,8 +1760,25 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
}
spin_lock_bh(&adapter->mac_vlan_list_lock);
iavf_add_filter(adapter, adapter->hw.mac.addr);
@@ -77698,7 +115548,7 @@ index 3c735968e1b85..8a1c293b8c7ab 100644
}
break;
case VIRTCHNL_OP_ENABLE_QUEUES:
-@@ -1735,7 +1764,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+@@ -1735,7 +1790,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
iavf_free_all_tx_resources(adapter);
iavf_free_all_rx_resources(adapter);
if (adapter->state == __IAVF_DOWN_PENDING) {
@@ -77707,8 +115557,29 @@ index 3c735968e1b85..8a1c293b8c7ab 100644
wake_up(&adapter->down_waitqueue);
}
break;
+@@ -1889,6 +1944,20 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+ spin_unlock_bh(&adapter->adv_rss_lock);
+ }
+ break;
++ case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
++ /* PF enabled vlan strip on this VF.
++ * Update netdev->features if needed to be in sync with ethtool.
++ */
++ if (!v_retval)
++ iavf_netdev_features_vlan_strip_set(netdev, true);
++ break;
++ case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
++ /* PF disabled vlan strip on this VF.
++ * Update netdev->features if needed to be in sync with ethtool.
++ */
++ if (!v_retval)
++ iavf_netdev_features_vlan_strip_set(netdev, false);
++ break;
+ default:
+ if (adapter->current_op && (v_opcode != adapter->current_op))
+ dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
-index 3c4f08d20414e..387322615e080 100644
+index 3c4f08d20414e..89bca2ed895a0 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -139,13 +139,10 @@
@@ -77734,7 +115605,15 @@ index 3c4f08d20414e..387322615e080 100644
ICE_CFG_BUSY,
ICE_SERVICE_SCHED,
ICE_SERVICE_DIS,
-@@ -306,10 +302,6 @@ struct ice_vsi {
+@@ -245,6 +241,7 @@ enum ice_pf_state {
+ ICE_LINK_DEFAULT_OVERRIDE_PENDING,
+ ICE_PHY_INIT_COMPLETE,
+ ICE_FD_VF_FLUSH_CTX, /* set at FD Rx IRQ or timeout */
++ ICE_AUX_ERR_PENDING,
+ ICE_STATE_NBITS /* must be last */
+ };
+
+@@ -306,10 +303,6 @@ struct ice_vsi {
spinlock_t arfs_lock; /* protects aRFS hash table and filter state */
atomic_t *arfs_last_fltr_id;
@@ -77745,15 +115624,16 @@ index 3c4f08d20414e..387322615e080 100644
u16 max_frame;
u16 rx_buf_len;
-@@ -405,6 +397,7 @@ enum ice_pf_flags {
+@@ -405,6 +398,8 @@ enum ice_pf_flags {
ICE_FLAG_VF_TRUE_PROMISC_ENA,
ICE_FLAG_MDD_AUTO_RESET_VF,
ICE_FLAG_LINK_LENIENT_MODE_ENA,
+ ICE_FLAG_PLUG_AUX_DEV,
++ ICE_FLAG_MTU_CHANGED,
ICE_PF_FLAGS_NBITS /* must be last */
};
-@@ -421,6 +414,9 @@ struct ice_pf {
+@@ -421,6 +416,9 @@ struct ice_pf {
struct devlink_region *nvm_region;
struct devlink_region *devcaps_region;
@@ -77763,7 +115643,32 @@ index 3c4f08d20414e..387322615e080 100644
/* OS reserved IRQ details */
struct msix_entry *msix_entries;
struct ice_res_tracker *irq_tracker;
-@@ -696,7 +692,7 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
+@@ -454,6 +452,7 @@ struct ice_pf {
+ struct mutex avail_q_mutex; /* protects access to avail_[rx|tx]qs */
+ struct mutex sw_mutex; /* lock for protecting VSI alloc flow */
+ struct mutex tc_mutex; /* lock to protect TC changes */
++ struct mutex adev_mutex; /* lock to protect aux device access */
+ u32 msg_enable;
+ struct ice_ptp ptp;
+ u16 num_rdma_msix; /* Total MSIX vectors for RDMA driver */
+@@ -467,6 +466,7 @@ struct ice_pf {
+ wait_queue_head_t reset_wait_queue;
+
+ u32 hw_csum_rx_error;
++ u32 oicr_err_reg;
+ u16 oicr_idx; /* Other interrupt cause MSIX vector index */
+ u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
+ u16 max_pf_txqs; /* Total Tx queues PF wide */
+@@ -553,7 +553,7 @@ static inline struct ice_pf *ice_netdev_to_pf(struct net_device *netdev)
+
+ static inline bool ice_is_xdp_ena_vsi(struct ice_vsi *vsi)
+ {
+- return !!vsi->xdp_prog;
++ return !!READ_ONCE(vsi->xdp_prog);
+ }
+
+ static inline void ice_set_ring_xdp(struct ice_ring *ring)
+@@ -696,7 +696,7 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) {
set_bit(ICE_FLAG_RDMA_ENA, pf->flags);
set_bit(ICE_FLAG_AUX_ENA, pf->flags);
@@ -77772,11 +115677,38 @@ index 3c4f08d20414e..387322615e080 100644
}
}
+@@ -706,7 +706,16 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
+ */
+ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
+ {
+- ice_unplug_aux_dev(pf);
++ /* We can directly unplug aux device here only if the flag bit
++ * ICE_FLAG_PLUG_AUX_DEV is not set because ice_unplug_aux_dev()
++ * could race with ice_plug_aux_dev() called from
++ * ice_service_task(). In this case we only clear that bit now and
++ * aux device will be unplugged later once ice_plug_aux_device()
++ * called from ice_service_task() finishes (see ice_service_task()).
++ */
++ if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
++ ice_unplug_aux_dev(pf);
++
+ clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+ clear_bit(ICE_FLAG_AUX_ENA, pf->flags);
+ }
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
-index c36057efc7ae3..f74610442bda7 100644
+index c36057efc7ae3..533a953f15acb 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
-@@ -909,7 +909,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
+@@ -115,6 +115,8 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
+ q_vector->rx.itr_setting = ICE_DFLT_RX_ITR;
+ q_vector->tx.itr_mode = ITR_DYNAMIC;
+ q_vector->rx.itr_mode = ITR_DYNAMIC;
++ q_vector->tx.type = ICE_TX_CONTAINER;
++ q_vector->rx.type = ICE_RX_CONTAINER;
+
+ if (vsi->type == ICE_VSI_VF)
+ goto out;
+@@ -909,7 +911,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
} else if (status == ICE_ERR_DOES_NOT_EXIST) {
dev_dbg(ice_pf_to_dev(vsi->back), "LAN Tx queues do not exist, nothing to disable\n");
} else if (status) {
@@ -77966,6 +115898,228 @@ index e07e74426bde8..e30284ccbed4c 100644
void ice_devlink_init_regions(struct ice_pf *pf);
void ice_devlink_destroy_regions(struct ice_pf *pf);
+diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
+index c451cf401e635..19f115402969e 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
+@@ -2275,7 +2275,7 @@ ice_set_link_ksettings(struct net_device *netdev,
+ goto done;
+ }
+
+- curr_link_speed = pi->phy.link_info.link_speed;
++ curr_link_speed = pi->phy.curr_user_speed_req;
+ adv_link_speed = ice_ksettings_find_adv_link_speed(ks);
+
+ /* If speed didn't get set, set it to what it currently is.
+@@ -3466,15 +3466,9 @@ static int ice_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+ return 0;
+ }
+
+-enum ice_container_type {
+- ICE_RX_CONTAINER,
+- ICE_TX_CONTAINER,
+-};
+-
+ /**
+ * ice_get_rc_coalesce - get ITR values for specific ring container
+ * @ec: ethtool structure to fill with driver's coalesce settings
+- * @c_type: container type, Rx or Tx
+ * @rc: ring container that the ITR values will come from
+ *
+ * Query the device for ice_ring_container specific ITR values. This is
+@@ -3484,13 +3478,12 @@ enum ice_container_type {
+ * Returns 0 on success, negative otherwise.
+ */
+ static int
+-ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type,
+- struct ice_ring_container *rc)
++ice_get_rc_coalesce(struct ethtool_coalesce *ec, struct ice_ring_container *rc)
+ {
+ if (!rc->ring)
+ return -EINVAL;
+
+- switch (c_type) {
++ switch (rc->type) {
+ case ICE_RX_CONTAINER:
+ ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc);
+ ec->rx_coalesce_usecs = rc->itr_setting;
+@@ -3501,7 +3494,7 @@ ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type,
+ ec->tx_coalesce_usecs = rc->itr_setting;
+ break;
+ default:
+- dev_dbg(ice_pf_to_dev(rc->ring->vsi->back), "Invalid c_type %d\n", c_type);
++ dev_dbg(ice_pf_to_dev(rc->ring->vsi->back), "Invalid c_type %d\n", rc->type);
+ return -EINVAL;
+ }
+
+@@ -3522,18 +3515,18 @@ static int
+ ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num)
+ {
+ if (q_num < vsi->num_rxq && q_num < vsi->num_txq) {
+- if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER,
++ if (ice_get_rc_coalesce(ec,
+ &vsi->rx_rings[q_num]->q_vector->rx))
+ return -EINVAL;
+- if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER,
++ if (ice_get_rc_coalesce(ec,
+ &vsi->tx_rings[q_num]->q_vector->tx))
+ return -EINVAL;
+ } else if (q_num < vsi->num_rxq) {
+- if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER,
++ if (ice_get_rc_coalesce(ec,
+ &vsi->rx_rings[q_num]->q_vector->rx))
+ return -EINVAL;
+ } else if (q_num < vsi->num_txq) {
+- if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER,
++ if (ice_get_rc_coalesce(ec,
+ &vsi->tx_rings[q_num]->q_vector->tx))
+ return -EINVAL;
+ } else {
+@@ -3585,7 +3578,6 @@ ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num,
+
+ /**
+ * ice_set_rc_coalesce - set ITR values for specific ring container
+- * @c_type: container type, Rx or Tx
+ * @ec: ethtool structure from user to update ITR settings
+ * @rc: ring container that the ITR values will come from
+ * @vsi: VSI associated to the ring container
+@@ -3597,10 +3589,10 @@ ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num,
+ * Returns 0 on success, negative otherwise.
+ */
+ static int
+-ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
++ice_set_rc_coalesce(struct ethtool_coalesce *ec,
+ struct ice_ring_container *rc, struct ice_vsi *vsi)
+ {
+- const char *c_type_str = (c_type == ICE_RX_CONTAINER) ? "rx" : "tx";
++ const char *c_type_str = (rc->type == ICE_RX_CONTAINER) ? "rx" : "tx";
+ u32 use_adaptive_coalesce, coalesce_usecs;
+ struct ice_pf *pf = vsi->back;
+ u16 itr_setting;
+@@ -3608,7 +3600,7 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
+ if (!rc->ring)
+ return -EINVAL;
+
+- switch (c_type) {
++ switch (rc->type) {
+ case ICE_RX_CONTAINER:
+ if (ec->rx_coalesce_usecs_high > ICE_MAX_INTRL ||
+ (ec->rx_coalesce_usecs_high &&
+@@ -3641,7 +3633,7 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
+ break;
+ default:
+ dev_dbg(ice_pf_to_dev(pf), "Invalid container type %d\n",
+- c_type);
++ rc->type);
+ return -EINVAL;
+ }
+
+@@ -3690,22 +3682,22 @@ static int
+ ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num)
+ {
+ if (q_num < vsi->num_rxq && q_num < vsi->num_txq) {
+- if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec,
++ if (ice_set_rc_coalesce(ec,
+ &vsi->rx_rings[q_num]->q_vector->rx,
+ vsi))
+ return -EINVAL;
+
+- if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec,
++ if (ice_set_rc_coalesce(ec,
+ &vsi->tx_rings[q_num]->q_vector->tx,
+ vsi))
+ return -EINVAL;
+ } else if (q_num < vsi->num_rxq) {
+- if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec,
++ if (ice_set_rc_coalesce(ec,
+ &vsi->rx_rings[q_num]->q_vector->rx,
+ vsi))
+ return -EINVAL;
+ } else if (q_num < vsi->num_txq) {
+- if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec,
++ if (ice_set_rc_coalesce(ec,
+ &vsi->tx_rings[q_num]->q_vector->tx,
+ vsi))
+ return -EINVAL;
+diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
+index adcc9a251595a..1dd3622991c65 100644
+--- a/drivers/net/ethernet/intel/ice/ice_idc.c
++++ b/drivers/net/ethernet/intel/ice/ice_idc.c
+@@ -34,14 +34,20 @@ void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event)
+ {
+ struct iidc_auxiliary_drv *iadrv;
+
+- if (!pf->adev)
++ if (WARN_ON_ONCE(!in_task()))
+ return;
+
++ mutex_lock(&pf->adev_mutex);
++ if (!pf->adev)
++ goto finish;
++
+ device_lock(&pf->adev->dev);
+ iadrv = ice_get_auxiliary_drv(pf);
+ if (iadrv && iadrv->event_handler)
+ iadrv->event_handler(pf, event);
+ device_unlock(&pf->adev->dev);
++finish:
++ mutex_unlock(&pf->adev_mutex);
+ }
+
+ /**
+@@ -282,7 +288,6 @@ int ice_plug_aux_dev(struct ice_pf *pf)
+ return -ENOMEM;
+
+ adev = &iadev->adev;
+- pf->adev = adev;
+ iadev->pf = pf;
+
+ adev->id = pf->aux_idx;
+@@ -292,18 +297,20 @@ int ice_plug_aux_dev(struct ice_pf *pf)
+
+ ret = auxiliary_device_init(adev);
+ if (ret) {
+- pf->adev = NULL;
+ kfree(iadev);
+ return ret;
+ }
+
+ ret = auxiliary_device_add(adev);
+ if (ret) {
+- pf->adev = NULL;
+ auxiliary_device_uninit(adev);
+ return ret;
+ }
+
++ mutex_lock(&pf->adev_mutex);
++ pf->adev = adev;
++ mutex_unlock(&pf->adev_mutex);
++
+ return 0;
+ }
+
+@@ -312,12 +319,17 @@ int ice_plug_aux_dev(struct ice_pf *pf)
+ */
+ void ice_unplug_aux_dev(struct ice_pf *pf)
+ {
+- if (!pf->adev)
+- return;
++ struct auxiliary_device *adev;
+
+- auxiliary_device_delete(pf->adev);
+- auxiliary_device_uninit(pf->adev);
++ mutex_lock(&pf->adev_mutex);
++ adev = pf->adev;
+ pf->adev = NULL;
++ mutex_unlock(&pf->adev_mutex);
++
++ if (adev) {
++ auxiliary_device_delete(adev);
++ auxiliary_device_uninit(adev);
++ }
+ }
+
+ /**
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index e375ac849aecd..4f954db01b929 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -78037,7 +116191,7 @@ index 80736e0ec0dca..3f635fdbfaff9 100644
enum ice_tx_ctx_desc_cmd_bits {
ICE_TX_CTX_DESC_TSO = 0x01,
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
-index b718e196af2a4..8c08997dcef64 100644
+index b718e196af2a4..4417238b0e64f 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -83,8 +83,13 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
@@ -78056,7 +116210,15 @@ index b718e196af2a4..8c08997dcef64 100644
sizeof(*vsi->txq_map), GFP_KERNEL);
if (!vsi->txq_map)
-@@ -1516,6 +1521,12 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
+@@ -1301,6 +1306,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
+ ring->tx_tstamps = &pf->ptp.port.tx;
+ ring->dev = dev;
+ ring->count = vsi->num_tx_desc;
++ ring->txq_teid = ICE_INVAL_TEID;
+ WRITE_ONCE(vsi->tx_rings[i], ring);
+ }
+
+@@ -1516,6 +1522,12 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
if (status)
dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %s\n",
vsi_num, ice_stat_str(status));
@@ -78069,7 +116231,7 @@ index b718e196af2a4..8c08997dcef64 100644
}
/**
-@@ -2860,7 +2871,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
+@@ -2860,7 +2872,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
}
@@ -78079,8 +116241,69 @@ index b718e196af2a4..8c08997dcef64 100644
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
ice_rss_clean(vsi);
+@@ -2911,6 +2924,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
+ }
+ }
+
++ if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
++ ice_clear_dflt_vsi(pf->first_sw);
+ ice_fltr_remove_all(vsi);
+ ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
+ err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
+@@ -2965,8 +2980,8 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
+ ice_for_each_q_vector(vsi, i) {
+ struct ice_q_vector *q_vector = vsi->q_vectors[i];
+
+- coalesce[i].itr_tx = q_vector->tx.itr_setting;
+- coalesce[i].itr_rx = q_vector->rx.itr_setting;
++ coalesce[i].itr_tx = q_vector->tx.itr_settings;
++ coalesce[i].itr_rx = q_vector->rx.itr_settings;
+ coalesce[i].intrl = q_vector->intrl;
+
+ if (i < vsi->num_txq)
+@@ -3022,21 +3037,21 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
+ */
+ if (i < vsi->alloc_rxq && coalesce[i].rx_valid) {
+ rc = &vsi->q_vectors[i]->rx;
+- rc->itr_setting = coalesce[i].itr_rx;
++ rc->itr_settings = coalesce[i].itr_rx;
+ ice_write_itr(rc, rc->itr_setting);
+ } else if (i < vsi->alloc_rxq) {
+ rc = &vsi->q_vectors[i]->rx;
+- rc->itr_setting = coalesce[0].itr_rx;
++ rc->itr_settings = coalesce[0].itr_rx;
+ ice_write_itr(rc, rc->itr_setting);
+ }
+
+ if (i < vsi->alloc_txq && coalesce[i].tx_valid) {
+ rc = &vsi->q_vectors[i]->tx;
+- rc->itr_setting = coalesce[i].itr_tx;
++ rc->itr_settings = coalesce[i].itr_tx;
+ ice_write_itr(rc, rc->itr_setting);
+ } else if (i < vsi->alloc_txq) {
+ rc = &vsi->q_vectors[i]->tx;
+- rc->itr_setting = coalesce[0].itr_tx;
++ rc->itr_settings = coalesce[0].itr_tx;
+ ice_write_itr(rc, rc->itr_setting);
+ }
+
+@@ -3050,12 +3065,12 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
+ for (; i < vsi->num_q_vectors; i++) {
+ /* transmit */
+ rc = &vsi->q_vectors[i]->tx;
+- rc->itr_setting = coalesce[0].itr_tx;
++ rc->itr_settings = coalesce[0].itr_tx;
+ ice_write_itr(rc, rc->itr_setting);
+
+ /* receive */
+ rc = &vsi->q_vectors[i]->rx;
+- rc->itr_setting = coalesce[0].itr_rx;
++ rc->itr_settings = coalesce[0].itr_rx;
+ ice_write_itr(rc, rc->itr_setting);
+
+ vsi->q_vectors[i]->intrl = coalesce[0].intrl;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
-index 06fa93e597fbc..8a0c928853e6a 100644
+index 06fa93e597fbc..188abf36a5b23 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -1679,7 +1679,9 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
@@ -78093,17 +116316,51 @@ index 06fa93e597fbc..8a0c928853e6a 100644
}
}
}
-@@ -2141,6 +2143,9 @@ static void ice_service_task(struct work_struct *work)
+@@ -2141,6 +2143,43 @@ static void ice_service_task(struct work_struct *work)
return;
}
-+ if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
++ if (test_and_clear_bit(ICE_AUX_ERR_PENDING, pf->state)) {
++ struct iidc_event *event;
++
++ event = kzalloc(sizeof(*event), GFP_KERNEL);
++ if (event) {
++ set_bit(IIDC_EVENT_CRIT_ERR, event->type);
++ /* report the entire OICR value to AUX driver */
++ swap(event->reg, pf->oicr_err_reg);
++ ice_send_event_to_aux(pf, event);
++ kfree(event);
++ }
++ }
++
++ if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) {
++ /* Plug aux device per request */
+ ice_plug_aux_dev(pf);
+
++ /* Mark plugging as done but check whether unplug was
++ * requested during ice_plug_aux_dev() call
++ * (e.g. from ice_clear_rdma_cap()) and if so then
++ * plug aux device.
++ */
++ if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
++ ice_unplug_aux_dev(pf);
++ }
++
++ if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) {
++ struct iidc_event *event;
++
++ event = kzalloc(sizeof(*event), GFP_KERNEL);
++ if (event) {
++ set_bit(IIDC_EVENT_AFTER_MTU_CHANGE, event->type);
++ ice_send_event_to_aux(pf, event);
++ kfree(event);
++ }
++ }
++
ice_clean_adminq_subtask(pf);
ice_check_media_subtask(pf);
ice_check_for_hang_subtask(pf);
-@@ -2497,7 +2502,18 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)
+@@ -2497,7 +2536,18 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)
ice_stat_str(status));
goto clear_xdp_rings;
}
@@ -78123,7 +116380,19 @@ index 06fa93e597fbc..8a0c928853e6a 100644
return 0;
clear_xdp_rings:
-@@ -2643,6 +2659,11 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
+@@ -2562,8 +2612,10 @@ free_qmap:
+
+ for (i = 0; i < vsi->num_xdp_txq; i++)
+ if (vsi->xdp_rings[i]) {
+- if (vsi->xdp_rings[i]->desc)
++ if (vsi->xdp_rings[i]->desc) {
++ synchronize_rcu();
+ ice_free_tx_ring(vsi->xdp_rings[i]);
++ }
+ kfree_rcu(vsi->xdp_rings[i], rcu);
+ vsi->xdp_rings[i] = NULL;
+ }
+@@ -2643,6 +2695,11 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed");
} else {
@@ -78135,7 +116404,43 @@ index 06fa93e597fbc..8a0c928853e6a 100644
ice_vsi_assign_bpf_prog(vsi, prog);
}
-@@ -4170,11 +4191,11 @@ static int ice_register_netdev(struct ice_pf *pf)
+@@ -2839,17 +2896,9 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
+
+ #define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
+ if (oicr & ICE_AUX_CRIT_ERR) {
+- struct iidc_event *event;
+-
++ pf->oicr_err_reg |= oicr;
++ set_bit(ICE_AUX_ERR_PENDING, pf->state);
+ ena_mask &= ~ICE_AUX_CRIT_ERR;
+- event = kzalloc(sizeof(*event), GFP_KERNEL);
+- if (event) {
+- set_bit(IIDC_EVENT_CRIT_ERR, event->type);
+- /* report the entire OICR value to AUX driver */
+- event->reg = oicr;
+- ice_send_event_to_aux(pf, event);
+- kfree(event);
+- }
+ }
+
+ /* Report any remaining unexpected interrupts */
+@@ -3398,6 +3447,7 @@ u16 ice_get_avail_rxq_count(struct ice_pf *pf)
+ static void ice_deinit_pf(struct ice_pf *pf)
+ {
+ ice_service_task_stop(pf);
++ mutex_destroy(&pf->adev_mutex);
+ mutex_destroy(&pf->sw_mutex);
+ mutex_destroy(&pf->tc_mutex);
+ mutex_destroy(&pf->avail_q_mutex);
+@@ -3478,6 +3528,7 @@ static int ice_init_pf(struct ice_pf *pf)
+
+ mutex_init(&pf->sw_mutex);
+ mutex_init(&pf->tc_mutex);
++ mutex_init(&pf->adev_mutex);
+
+ INIT_HLIST_HEAD(&pf->aq_wait_list);
+ spin_lock_init(&pf->aq_wait_lock);
+@@ -4170,11 +4221,11 @@ static int ice_register_netdev(struct ice_pf *pf)
set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
netif_carrier_off(vsi->netdev);
netif_tx_stop_all_queues(vsi->netdev);
@@ -78149,7 +116454,7 @@ index 06fa93e597fbc..8a0c928853e6a 100644
return 0;
err_devlink_create:
-@@ -4600,9 +4621,6 @@ static void ice_remove(struct pci_dev *pdev)
+@@ -4600,9 +4651,6 @@ static void ice_remove(struct pci_dev *pdev)
struct ice_pf *pf = pci_get_drvdata(pdev);
int i;
@@ -78159,17 +116464,66 @@ index 06fa93e597fbc..8a0c928853e6a 100644
for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
if (!ice_is_reset_in_progress(pf->state))
break;
-@@ -5608,6 +5626,9 @@ static int ice_up_complete(struct ice_vsi *vsi)
+@@ -5608,6 +5656,10 @@ static int ice_up_complete(struct ice_vsi *vsi)
netif_carrier_on(vsi->netdev);
}
-+ /* clear this now, and the first stats read will be used as baseline */
-+ vsi->stat_offsets_loaded = false;
-+
++ /* Perform an initial read of the statistics registers now to
++ * set the baseline so counters are ready when interface is up
++ */
++ ice_update_eth_stats(vsi);
ice_service_task_schedule(pf);
return 0;
-@@ -7190,6 +7211,7 @@ ice_features_check(struct sk_buff *skb,
+@@ -6511,7 +6563,6 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+- struct iidc_event *event;
+ u8 count = 0;
+ int err = 0;
+
+@@ -6546,14 +6597,6 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
+ return -EBUSY;
+ }
+
+- event = kzalloc(sizeof(*event), GFP_KERNEL);
+- if (!event)
+- return -ENOMEM;
+-
+- set_bit(IIDC_EVENT_BEFORE_MTU_CHANGE, event->type);
+- ice_send_event_to_aux(pf, event);
+- clear_bit(IIDC_EVENT_BEFORE_MTU_CHANGE, event->type);
+-
+ netdev->mtu = (unsigned int)new_mtu;
+
+ /* if VSI is up, bring it down and then back up */
+@@ -6561,21 +6604,18 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
+ err = ice_down(vsi);
+ if (err) {
+ netdev_err(netdev, "change MTU if_down err %d\n", err);
+- goto event_after;
++ return err;
+ }
+
+ err = ice_up(vsi);
+ if (err) {
+ netdev_err(netdev, "change MTU if_up err %d\n", err);
+- goto event_after;
++ return err;
+ }
+ }
+
+ netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);
+-event_after:
+- set_bit(IIDC_EVENT_AFTER_MTU_CHANGE, event->type);
+- ice_send_event_to_aux(pf, event);
+- kfree(event);
++ set_bit(ICE_FLAG_MTU_CHANGED, pf->flags);
+
+ return err;
+ }
+@@ -7190,6 +7230,7 @@ ice_features_check(struct sk_buff *skb,
struct net_device __always_unused *netdev,
netdev_features_t features)
{
@@ -78177,7 +116531,7 @@ index 06fa93e597fbc..8a0c928853e6a 100644
size_t len;
/* No point in doing any of this if neither checksum nor GSO are
-@@ -7202,24 +7224,32 @@ ice_features_check(struct sk_buff *skb,
+@@ -7202,24 +7243,32 @@ ice_features_check(struct sk_buff *skb,
/* We cannot support GSO if the MSS is going to be less than
* 64 bytes. If it is then we need to drop support for GSO.
*/
@@ -78219,10 +116573,41 @@ index 06fa93e597fbc..8a0c928853e6a 100644
goto out_rm_features;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
-index d1ef3d48a4b03..eb91936825795 100644
+index d1ef3d48a4b03..9b50e9e6042a5 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
-@@ -459,7 +459,7 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
+@@ -254,12 +254,19 @@ ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
+ * This function must be called periodically to ensure that the cached value
+ * is never more than 2 seconds old. It must also be called whenever the PHC
+ * time has been changed.
++ *
++ * Return:
++ * * 0 - OK, successfully updated
++ * * -EAGAIN - PF was busy, need to reschedule the update
+ */
+-static void ice_ptp_update_cached_phctime(struct ice_pf *pf)
++static int ice_ptp_update_cached_phctime(struct ice_pf *pf)
+ {
+ u64 systime;
+ int i;
+
++ if (test_and_set_bit(ICE_CFG_BUSY, pf->state))
++ return -EAGAIN;
++
+ /* Read the current PHC time */
+ systime = ice_ptp_read_src_clk_reg(pf, NULL);
+
+@@ -282,6 +289,9 @@ static void ice_ptp_update_cached_phctime(struct ice_pf *pf)
+ WRITE_ONCE(vsi->rx_rings[j]->cached_phctime, systime);
+ }
+ }
++ clear_bit(ICE_CFG_BUSY, pf->state);
++
++ return 0;
+ }
+
+ /**
+@@ -459,7 +469,7 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
scaled_ppm = -scaled_ppm;
}
@@ -78231,7 +116616,7 @@ index d1ef3d48a4b03..eb91936825795 100644
/* handle overflow by scaling down the scaled_ppm and
* the divisor, losing some precision
*/
-@@ -846,9 +846,12 @@ exit:
+@@ -846,9 +856,12 @@ exit:
static int ice_ptp_adjtime_nonatomic(struct ptp_clock_info *info, s64 delta)
{
struct timespec64 now, then;
@@ -78245,7 +116630,7 @@ index d1ef3d48a4b03..eb91936825795 100644
now = timespec64_add(now, then);
return ice_ptp_settime64(info, (const struct timespec64 *)&now);
-@@ -1182,19 +1185,16 @@ static void ice_ptp_tx_tstamp_work(struct kthread_work *work)
+@@ -1182,19 +1195,16 @@ static void ice_ptp_tx_tstamp_work(struct kthread_work *work)
if (err)
continue;
@@ -78269,6 +116654,63 @@ index d1ef3d48a4b03..eb91936825795 100644
clear_bit(idx, tx->in_use);
skb = tx->tstamps[idx].skb;
tx->tstamps[idx].skb = NULL;
+@@ -1375,6 +1385,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
+
+ /**
+ * ice_ptp_tx_tstamp_cleanup - Cleanup old timestamp requests that got dropped
++ * @hw: pointer to the hw struct
+ * @tx: PTP Tx tracker to clean up
+ *
+ * Loop through the Tx timestamp requests and see if any of them have been
+@@ -1383,7 +1394,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
+ * timestamp will never be captured. This might happen if the packet gets
+ * discarded before it reaches the PHY timestamping block.
+ */
+-static void ice_ptp_tx_tstamp_cleanup(struct ice_ptp_tx *tx)
++static void ice_ptp_tx_tstamp_cleanup(struct ice_hw *hw, struct ice_ptp_tx *tx)
+ {
+ u8 idx;
+
+@@ -1392,11 +1403,16 @@ static void ice_ptp_tx_tstamp_cleanup(struct ice_ptp_tx *tx)
+
+ for_each_set_bit(idx, tx->in_use, tx->len) {
+ struct sk_buff *skb;
++ u64 raw_tstamp;
+
+ /* Check if this SKB has been waiting for too long */
+ if (time_is_after_jiffies(tx->tstamps[idx].start + 2 * HZ))
+ continue;
+
++ /* Read tstamp to be able to use this register again */
++ ice_read_phy_tstamp(hw, tx->quad, idx + tx->quad_offset,
++ &raw_tstamp);
++
+ spin_lock(&tx->lock);
+ skb = tx->tstamps[idx].skb;
+ tx->tstamps[idx].skb = NULL;
+@@ -1412,17 +1428,18 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
+ {
+ struct ice_ptp *ptp = container_of(work, struct ice_ptp, work.work);
+ struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp);
++ int err;
+
+ if (!test_bit(ICE_FLAG_PTP, pf->flags))
+ return;
+
+- ice_ptp_update_cached_phctime(pf);
++ err = ice_ptp_update_cached_phctime(pf);
+
+- ice_ptp_tx_tstamp_cleanup(&pf->ptp.port.tx);
++ ice_ptp_tx_tstamp_cleanup(&pf->hw, &pf->ptp.port.tx);
+
+- /* Run twice a second */
++ /* Run twice a second or reschedule if phc update failed */
+ kthread_queue_delayed_work(ptp->kworker, &ptp->work,
+- msecs_to_jiffies(500));
++ msecs_to_jiffies(err ? 10 : 500));
+ }
+
+ /**
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index e1c787bd5b967..8cdd6f7046b73 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -78296,7 +116738,7 @@ index e1c787bd5b967..8cdd6f7046b73 100644
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
-index 1e46e80f3d6f8..7c2328529ff8e 100644
+index 1e46e80f3d6f8..4adc3dff04ba7 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -164,17 +164,10 @@ struct ice_tx_offload_params {
@@ -78329,8 +116771,39 @@ index 1e46e80f3d6f8..7c2328529ff8e 100644
};
/* CL2 - 2nd cacheline starts here */
u16 q_index; /* Queue number of ring */
+@@ -338,6 +332,11 @@ static inline bool ice_ring_is_xdp(struct ice_ring *ring)
+ return !!(ring->flags & ICE_TX_FLAGS_RING_XDP);
+ }
+
++enum ice_container_type {
++ ICE_RX_CONTAINER,
++ ICE_TX_CONTAINER,
++};
++
+ struct ice_ring_container {
+ /* head of linked-list of rings */
+ struct ice_ring *ring;
+@@ -346,9 +345,15 @@ struct ice_ring_container {
+ /* this matches the maximum number of ITR bits, but in usec
+ * values, so it is shifted left one bit (bit zero is ignored)
+ */
+- u16 itr_setting:13;
+- u16 itr_reserved:2;
+- u16 itr_mode:1;
++ union {
++ struct {
++ u16 itr_setting:13;
++ u16 itr_reserved:2;
++ u16 itr_mode:1;
++ };
++ u16 itr_settings;
++ };
++ enum ice_container_type type;
+ };
+
+ struct ice_coalesce_stored {
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
-index e93430ab37f1e..4054adb5279c3 100644
+index e93430ab37f1e..9d4d58757e040 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -251,7 +251,7 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list_comms[] = {
@@ -78478,7 +116951,32 @@ index e93430ab37f1e..4054adb5279c3 100644
}
/**
-@@ -2954,6 +2970,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
+@@ -2218,24 +2234,6 @@ ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
+
+ dev = ice_pf_to_dev(pf);
+
+- /* single place to detect unsuccessful return values */
+- if (v_retval) {
+- vf->num_inval_msgs++;
+- dev_info(dev, "VF %d failed opcode %d, retval: %d\n", vf->vf_id,
+- v_opcode, v_retval);
+- if (vf->num_inval_msgs > ICE_DFLT_NUM_INVAL_MSGS_ALLOWED) {
+- dev_err(dev, "Number of invalid messages exceeded for VF %d\n",
+- vf->vf_id);
+- dev_err(dev, "Use PF Control I/F to enable the VF\n");
+- set_bit(ICE_VF_STATE_DIS, vf->vf_states);
+- return -EIO;
+- }
+- } else {
+- vf->num_valid_msgs++;
+- /* reset the invalid counter, if a valid message is received. */
+- vf->num_inval_msgs = 0;
+- }
+-
+ aq_ret = ice_aq_send_msg_to_vf(&pf->hw, vf->vf_id, v_opcode, v_retval,
+ msg, msglen, NULL);
+ if (aq_ret && pf->hw.mailboxq.sq_last_status != ICE_AQ_RC_ENOSYS) {
+@@ -2954,6 +2952,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
{
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
@@ -78486,7 +116984,7 @@ index e93430ab37f1e..4054adb5279c3 100644
bool rm_promisc, alluni = false, allmulti = false;
struct virtchnl_promisc_info *info =
(struct virtchnl_promisc_info *)msg;
-@@ -3043,52 +3060,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
+@@ -3043,52 +3042,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
goto error_param;
}
} else {
@@ -78577,7 +117075,19 @@ index e93430ab37f1e..4054adb5279c3 100644
error_param:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
-@@ -3762,6 +3778,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
+@@ -3337,9 +3335,9 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
+ goto error_param;
+ }
+
+- /* Skip queue if not enabled */
+ if (!test_bit(vf_q_id, vf->txq_ena))
+- continue;
++ dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n",
++ vf_q_id, vsi->vsi_num);
+
+ ice_fill_txq_meta(vsi, ring, &txq_meta);
+
+@@ -3762,6 +3760,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
struct device *dev = ice_pf_to_dev(vf->pf);
u8 *mac_addr = vc_ether_addr->addr;
enum ice_status status;
@@ -78585,7 +117095,7 @@ index e93430ab37f1e..4054adb5279c3 100644
/* device MAC already added */
if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr))
-@@ -3774,20 +3791,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
+@@ -3774,20 +3773,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
status = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
if (status == ICE_ERR_ALREADY_EXISTS) {
@@ -78614,7 +117124,7 @@ index e93430ab37f1e..4054adb5279c3 100644
}
/**
-@@ -4078,6 +4098,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
+@@ -4078,6 +4080,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
return 0;
}
@@ -78623,7 +117133,7 @@ index e93430ab37f1e..4054adb5279c3 100644
vf->port_vlan_info = vlanprio;
if (vf->port_vlan_info)
-@@ -4087,6 +4109,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
+@@ -4087,6 +4091,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
dev_info(dev, "Clearing port VLAN on VF %d\n", vf_id);
ice_vc_reset_vf(vf);
@@ -78631,7 +117141,7 @@ index e93430ab37f1e..4054adb5279c3 100644
return 0;
}
-@@ -4418,10 +4441,6 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
+@@ -4418,10 +4423,6 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
struct device *dev;
int err = 0;
@@ -78642,7 +117152,7 @@ index e93430ab37f1e..4054adb5279c3 100644
dev = ice_pf_to_dev(pf);
if (ice_validate_vf_id(pf, vf_id)) {
err = -EINVAL;
-@@ -4461,6 +4480,15 @@ error_handler:
+@@ -4461,6 +4462,15 @@ error_handler:
return;
}
@@ -78658,7 +117168,7 @@ index e93430ab37f1e..4054adb5279c3 100644
switch (v_opcode) {
case VIRTCHNL_OP_VERSION:
err = ice_vc_get_ver_msg(vf, msg);
-@@ -4549,6 +4577,8 @@ error_handler:
+@@ -4549,6 +4559,8 @@ error_handler:
dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n",
vf_id, v_opcode, err);
}
@@ -78667,7 +117177,7 @@ index e93430ab37f1e..4054adb5279c3 100644
}
/**
-@@ -4664,6 +4694,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
+@@ -4664,6 +4676,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
return -EINVAL;
}
@@ -78676,7 +117186,7 @@ index e93430ab37f1e..4054adb5279c3 100644
/* VF is notified of its new MAC via the PF's response to the
* VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
*/
-@@ -4682,6 +4714,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
+@@ -4682,6 +4696,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
ice_vc_reset_vf(vf);
@@ -78684,7 +117194,7 @@ index e93430ab37f1e..4054adb5279c3 100644
return 0;
}
-@@ -4711,11 +4744,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
+@@ -4711,11 +4726,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
if (trusted == vf->trusted)
return 0;
@@ -78701,10 +117211,18 @@ index e93430ab37f1e..4054adb5279c3 100644
}
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
-index 842cb077df861..a750e9a9d7125 100644
+index 842cb077df861..532f57f014673 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
-@@ -74,6 +74,11 @@ struct ice_mdd_vf_events {
+@@ -14,7 +14,6 @@
+ #define ICE_MAX_MACADDR_PER_VF 18
+
+ /* Malicious Driver Detection */
+-#define ICE_DFLT_NUM_INVAL_MSGS_ALLOWED 10
+ #define ICE_MDD_EVENTS_THRESHOLD 30
+
+ /* Static VF transaction/status register def */
+@@ -74,6 +73,11 @@ struct ice_mdd_vf_events {
struct ice_vf {
struct ice_pf *pf;
@@ -78716,7 +117234,16 @@ index 842cb077df861..a750e9a9d7125 100644
u16 vf_id; /* VF ID in the PF space */
u16 lan_vsi_idx; /* index into PF struct */
u16 ctrl_vsi_idx;
-@@ -111,9 +116,13 @@ struct ice_vf {
+@@ -102,8 +106,6 @@ struct ice_vf {
+ unsigned int tx_rate; /* Tx bandwidth limit in Mbps */
+ DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */
+
+- u64 num_inval_msgs; /* number of continuous invalid msgs */
+- u64 num_valid_msgs; /* number of valid msgs detected */
+ unsigned long vf_caps; /* VF's adv. capabilities */
+ u8 num_req_qs; /* num of queue pairs requested by VF */
+ u16 num_mac;
+@@ -111,9 +113,13 @@ struct ice_vf {
struct ice_mdd_vf_events mdd_rx_events;
struct ice_mdd_vf_events mdd_tx_events;
DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX);
@@ -78730,7 +117257,7 @@ index 842cb077df861..a750e9a9d7125 100644
void ice_process_vflr_event(struct ice_pf *pf);
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
-@@ -171,6 +180,11 @@ static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { }
+@@ -171,6 +177,11 @@ static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { }
static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { }
static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { }
@@ -78743,10 +117270,22 @@ index 842cb077df861..a750e9a9d7125 100644
ice_is_malicious_vf(struct ice_pf __always_unused *pf,
struct ice_rq_event_info __always_unused *event,
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
-index 5a9f61deeb38d..37c7dc6b44a9f 100644
+index 5a9f61deeb38d..5581747947e57 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
-@@ -364,7 +364,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)
+@@ -36,8 +36,10 @@ static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx)
+ static void ice_qp_clean_rings(struct ice_vsi *vsi, u16 q_idx)
+ {
+ ice_clean_tx_ring(vsi->tx_rings[q_idx]);
+- if (ice_is_xdp_ena_vsi(vsi))
++ if (ice_is_xdp_ena_vsi(vsi)) {
++ synchronize_rcu();
+ ice_clean_tx_ring(vsi->xdp_rings[q_idx]);
++ }
+ ice_clean_rx_ring(vsi->rx_rings[q_idx]);
+ }
+
+@@ -364,7 +366,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)
{
union ice_32b_rx_flex_desc *rx_desc;
u16 ntu = rx_ring->next_to_use;
@@ -78755,7 +117294,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
bool ok = true;
dma_addr_t dma;
-@@ -372,26 +372,26 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)
+@@ -372,26 +374,26 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)
return true;
rx_desc = ICE_RX_DESC(rx_ring, ntu);
@@ -78766,7 +117305,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
- rx_buf->xdp = xsk_buff_alloc(rx_ring->xsk_pool);
- if (!rx_buf->xdp) {
+ *xdp = xsk_buff_alloc(rx_ring->xsk_pool);
-+ if (!xdp) {
++ if (!*xdp) {
ok = false;
break;
}
@@ -78788,7 +117327,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
ntu = 0;
}
} while (--count);
-@@ -421,19 +421,19 @@ static void ice_bump_ntc(struct ice_ring *rx_ring)
+@@ -421,19 +423,19 @@ static void ice_bump_ntc(struct ice_ring *rx_ring)
/**
* ice_construct_skb_zc - Create an sk_buff from zero-copy buffer
* @rx_ring: Rx ring
@@ -78814,7 +117353,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
struct sk_buff *skb;
skb = __napi_alloc_skb(&rx_ring->q_vector->napi, datasize_hard,
-@@ -441,13 +441,13 @@ ice_construct_skb_zc(struct ice_ring *rx_ring, struct ice_rx_buf *rx_buf)
+@@ -441,13 +443,13 @@ ice_construct_skb_zc(struct ice_ring *rx_ring, struct ice_rx_buf *rx_buf)
if (unlikely(!skb))
return NULL;
@@ -78832,7 +117371,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
return skb;
}
-@@ -521,7 +521,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
+@@ -521,7 +523,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
while (likely(total_rx_packets < (unsigned int)budget)) {
union ice_32b_rx_flex_desc *rx_desc;
unsigned int size, xdp_res = 0;
@@ -78841,7 +117380,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
struct sk_buff *skb;
u16 stat_err_bits;
u16 vlan_tag = 0;
-@@ -544,18 +544,18 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
+@@ -544,18 +546,18 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
if (!size)
break;
@@ -78866,7 +117405,7 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
total_rx_bytes += size;
total_rx_packets++;
cleaned_count++;
-@@ -565,7 +565,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
+@@ -565,7 +567,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)
}
/* XDP_PASS path */
@@ -78875,7 +117414,16 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
if (!skb) {
rx_ring->rx_stats.alloc_buf_failed++;
break;
-@@ -810,15 +810,15 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi)
+@@ -759,7 +761,7 @@ ice_xsk_wakeup(struct net_device *netdev, u32 queue_id,
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_ring *ring;
+
+- if (test_bit(ICE_DOWN, vsi->state))
++ if (test_bit(ICE_VSI_DOWN, vsi->state))
+ return -ENETDOWN;
+
+ if (!ice_is_xdp_ena_vsi(vsi))
+@@ -810,15 +812,15 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi)
*/
void ice_xsk_clean_rx_ring(struct ice_ring *rx_ring)
{
@@ -78898,11 +117446,72 @@ index 5a9f61deeb38d..37c7dc6b44a9f 100644
}
}
+diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+index fb1029352c3e7..3cbb5a89b336f 100644
+--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
++++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+@@ -961,10 +961,6 @@ static int igb_set_ringparam(struct net_device *netdev,
+ memcpy(&temp_ring[i], adapter->rx_ring[i],
+ sizeof(struct igb_ring));
+
+- /* Clear copied XDP RX-queue info */
+- memset(&temp_ring[i].xdp_rxq, 0,
+- sizeof(temp_ring[i].xdp_rxq));
+-
+ temp_ring[i].count = new_rx_count;
+ err = igb_setup_rx_resources(&temp_ring[i]);
+ if (err) {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
-index 751de06019a0e..82a712f77cb34 100644
+index 751de06019a0e..b883033514843 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
-@@ -7641,6 +7641,20 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
+@@ -4345,7 +4345,18 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
+ {
+ struct igb_adapter *adapter = netdev_priv(rx_ring->netdev);
+ struct device *dev = rx_ring->dev;
+- int size;
++ int size, res;
++
++ /* XDP RX-queue info */
++ if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
++ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
++ res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
++ rx_ring->queue_index, 0);
++ if (res < 0) {
++ dev_err(dev, "Failed to register xdp_rxq index %u\n",
++ rx_ring->queue_index);
++ return res;
++ }
+
+ size = sizeof(struct igb_rx_buffer) * rx_ring->count;
+
+@@ -4368,14 +4379,10 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
+
+ rx_ring->xdp_prog = adapter->xdp_prog;
+
+- /* XDP RX-queue info */
+- if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
+- rx_ring->queue_index, 0) < 0)
+- goto err;
+-
+ return 0;
+
+ err:
++ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+ vfree(rx_ring->rx_buffer_info);
+ rx_ring->rx_buffer_info = NULL;
+ dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n");
+@@ -5498,7 +5505,8 @@ static void igb_watchdog_task(struct work_struct *work)
+ break;
+ }
+
+- if (adapter->link_speed != SPEED_1000)
++ if (adapter->link_speed != SPEED_1000 ||
++ !hw->phy.ops.read_reg)
+ goto no_wait;
+
+ /* wait for Remote receiver status OK */
+@@ -7641,6 +7649,20 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
struct vf_mac_filter *entry = NULL;
int ret = 0;
@@ -78923,7 +117532,7 @@ index 751de06019a0e..82a712f77cb34 100644
switch (info) {
case E1000_VF_MAC_FILTER_CLR:
/* remove all unicast MAC filters related to the current VF */
-@@ -7654,20 +7668,6 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
+@@ -7654,20 +7676,6 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
}
break;
case E1000_VF_MAC_FILTER_ADD:
@@ -78944,7 +117553,7 @@ index 751de06019a0e..82a712f77cb34 100644
/* try to find empty slot in the list */
list_for_each(pos, &adapter->vf_macs.l) {
entry = list_entry(pos, struct vf_mac_filter, l);
-@@ -8019,7 +8019,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
+@@ -8019,7 +8027,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
if (likely(napi_complete_done(napi, work_done)))
igb_ring_irq_enable(q_vector);
@@ -78953,7 +117562,7 @@ index 751de06019a0e..82a712f77cb34 100644
}
/**
-@@ -9247,7 +9247,7 @@ static int __maybe_unused igb_suspend(struct device *dev)
+@@ -9247,7 +9255,7 @@ static int __maybe_unused igb_suspend(struct device *dev)
return __igb_shutdown(to_pci_dev(dev), NULL, 0);
}
@@ -78962,7 +117571,7 @@ index 751de06019a0e..82a712f77cb34 100644
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
-@@ -9290,17 +9290,24 @@ static int __maybe_unused igb_resume(struct device *dev)
+@@ -9290,17 +9298,24 @@ static int __maybe_unused igb_resume(struct device *dev)
wr32(E1000_WUS, ~0);
@@ -78989,7 +117598,7 @@ index 751de06019a0e..82a712f77cb34 100644
static int __maybe_unused igb_runtime_idle(struct device *dev)
{
struct net_device *netdev = dev_get_drvdata(dev);
-@@ -9319,7 +9326,7 @@ static int __maybe_unused igb_runtime_suspend(struct device *dev)
+@@ -9319,7 +9334,7 @@ static int __maybe_unused igb_runtime_suspend(struct device *dev)
static int __maybe_unused igb_runtime_resume(struct device *dev)
{
@@ -78998,7 +117607,7 @@ index 751de06019a0e..82a712f77cb34 100644
}
static void igb_shutdown(struct pci_dev *pdev)
-@@ -9435,7 +9442,7 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
+@@ -9435,7 +9450,7 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot. Implementation
@@ -79007,7 +117616,7 @@ index 751de06019a0e..82a712f77cb34 100644
**/
static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
{
-@@ -9475,7 +9482,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
+@@ -9475,7 +9490,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
*
* This callback is called when the error recovery driver tells us that
* its OK to resume normal operation. Implementation resembles the
@@ -79029,10 +117638,28 @@ index d32e72d953c8d..d051918dfdff9 100644
kfree(adapter->rx_ring);
err_sw_init:
diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c
-index b2ef9fde97b38..b6807e16eea93 100644
+index b2ef9fde97b38..a0e2a404d5355 100644
--- a/drivers/net/ethernet/intel/igc/igc_i225.c
+++ b/drivers/net/ethernet/intel/igc/igc_i225.c
-@@ -636,7 +636,7 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link)
+@@ -156,8 +156,15 @@ void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask)
+ {
+ u32 swfw_sync;
+
+- while (igc_get_hw_semaphore_i225(hw))
+- ; /* Empty */
++ /* Releasing the resource requires first getting the HW semaphore.
++ * If we fail to get the semaphore, there is nothing we can do,
++ * except log an error and quit. We are not allowed to hang here
++ * indefinitely, as it may cause denial of service or system crash.
++ */
++ if (igc_get_hw_semaphore_i225(hw)) {
++ hw_dbg("Failed to release SW_FW_SYNC.\n");
++ return;
++ }
+
+ swfw_sync = rd32(IGC_SW_FW_SYNC);
+ swfw_sync &= ~mask;
+@@ -636,7 +643,7 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link)
ltrv = rd32(IGC_LTRMAXV);
if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) {
ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max |
@@ -79042,14 +117669,44 @@ index b2ef9fde97b38..b6807e16eea93 100644
}
}
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
-index 0e19b4d02e628..c7fa978cdf02e 100644
+index 0e19b4d02e628..f99819fc559d9 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
-@@ -2447,8 +2447,10 @@ static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring,
+@@ -504,6 +504,9 @@ int igc_setup_rx_resources(struct igc_ring *rx_ring)
+ u8 index = rx_ring->queue_index;
+ int size, desc_len, res;
+
++ /* XDP RX-queue info */
++ if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
++ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+ res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, ndev, index,
+ rx_ring->q_vector->napi.napi_id);
+ if (res < 0) {
+@@ -2434,21 +2437,24 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
+ static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring,
+ struct xdp_buff *xdp)
+ {
++ unsigned int totalsize = xdp->data_end - xdp->data_meta;
+ unsigned int metasize = xdp->data - xdp->data_meta;
+- unsigned int datasize = xdp->data_end - xdp->data;
+- unsigned int totalsize = metasize + datasize;
+ struct sk_buff *skb;
- skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
- memcpy(__skb_put(skb, totalsize), xdp->data_meta, totalsize);
+- skb = __napi_alloc_skb(&ring->q_vector->napi,
+- xdp->data_end - xdp->data_hard_start,
++ net_prefetch(xdp->data_meta);
++
++ skb = __napi_alloc_skb(&ring->q_vector->napi, totalsize,
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ return NULL;
+
+- skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
+- memcpy(__skb_put(skb, totalsize), xdp->data_meta, totalsize);
- if (metasize)
++ memcpy(__skb_put(skb, totalsize), xdp->data_meta,
++ ALIGN(totalsize, sizeof(long)));
++
+ if (metasize) {
skb_metadata_set(skb, metasize);
+ __skb_pull(skb, metasize);
@@ -79057,7 +117714,7 @@ index 0e19b4d02e628..c7fa978cdf02e 100644
return skb;
}
-@@ -5466,6 +5468,9 @@ static irqreturn_t igc_intr_msi(int irq, void *data)
+@@ -5466,6 +5472,9 @@ static irqreturn_t igc_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
@@ -79067,7 +117724,7 @@ index 0e19b4d02e628..c7fa978cdf02e 100644
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
-@@ -5509,6 +5514,9 @@ static irqreturn_t igc_intr(int irq, void *data)
+@@ -5509,6 +5518,9 @@ static irqreturn_t igc_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
@@ -79078,9 +117735,27 @@ index 0e19b4d02e628..c7fa978cdf02e 100644
return IRQ_HANDLED;
diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c
-index 5cad31c3c7b09..40dbf4b432345 100644
+index 5cad31c3c7b09..6961f65d36b9a 100644
--- a/drivers/net/ethernet/intel/igc/igc_phy.c
+++ b/drivers/net/ethernet/intel/igc/igc_phy.c
+@@ -581,7 +581,7 @@ static s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data)
+ * the lower time out
+ */
+ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
+- usleep_range(500, 1000);
++ udelay(50);
+ mdic = rd32(IGC_MDIC);
+ if (mdic & IGC_MDIC_READY)
+ break;
+@@ -638,7 +638,7 @@ static s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data)
+ * the lower time out
+ */
+ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
+- usleep_range(500, 1000);
++ udelay(50);
+ mdic = rd32(IGC_MDIC);
+ if (mdic & IGC_MDIC_READY)
+ break;
@@ -746,8 +746,6 @@ s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data)
if (ret_val)
return ret_val;
@@ -79100,7 +117775,7 @@ index 5cad31c3c7b09..40dbf4b432345 100644
} else {
ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr,
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
-index 0f021909b430a..4f9245aa79a18 100644
+index 0f021909b430a..8e521f99b80ae 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -768,12 +768,25 @@ int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
@@ -79131,6 +117806,50 @@ index 0f021909b430a..4f9245aa79a18 100644
return convert_art_ns_to_tsc(tstamp);
#else
return (struct system_counterval_t) { };
+@@ -983,6 +996,17 @@ static void igc_ptp_time_restore(struct igc_adapter *adapter)
+ igc_ptp_write_i225(adapter, &ts);
+ }
+
++static void igc_ptm_stop(struct igc_adapter *adapter)
++{
++ struct igc_hw *hw = &adapter->hw;
++ u32 ctrl;
++
++ ctrl = rd32(IGC_PTM_CTRL);
++ ctrl &= ~IGC_PTM_CTRL_EN;
++
++ wr32(IGC_PTM_CTRL, ctrl);
++}
++
+ /**
+ * igc_ptp_suspend - Disable PTP work items and prepare for suspend
+ * @adapter: Board private structure
+@@ -1000,8 +1024,10 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
+ adapter->ptp_tx_skb = NULL;
+ clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+
+- if (pci_device_is_present(adapter->pdev))
++ if (pci_device_is_present(adapter->pdev)) {
+ igc_ptp_time_save(adapter);
++ igc_ptm_stop(adapter);
++ }
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+index e596e1a9fc757..69d11ff7677d6 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+@@ -903,7 +903,8 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+ /* Tx IPsec offload doesn't seem to work on this
+ * device, so block these requests for now.
+ */
+- if (!(sam->flags & XFRM_OFFLOAD_INBOUND)) {
++ sam->flags = sam->flags & ~XFRM_OFFLOAD_IPV6;
++ if (sam->flags != XFRM_OFFLOAD_INBOUND) {
+ err = -EOPNOTSUPP;
+ goto err_out;
+ }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 13c4782b920a7..750b02bb2fdc2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -79161,10 +117880,66 @@ index 9724ffb165189..e4b50c7781ffa 100644
status = hw->phy.ops.init(hw);
if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
-index b1d22e4d5ec9c..e3bf024717ed3 100644
+index b1d22e4d5ec9c..b399b9c147172 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
-@@ -388,12 +388,14 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
+@@ -201,26 +201,28 @@ bool ixgbe_alloc_rx_buffers_zc(struct ixgbe_ring *rx_ring, u16 count)
+ }
+
+ static struct sk_buff *ixgbe_construct_skb_zc(struct ixgbe_ring *rx_ring,
+- struct ixgbe_rx_buffer *bi)
++ const struct xdp_buff *xdp)
+ {
+- unsigned int metasize = bi->xdp->data - bi->xdp->data_meta;
+- unsigned int datasize = bi->xdp->data_end - bi->xdp->data;
++ unsigned int totalsize = xdp->data_end - xdp->data_meta;
++ unsigned int metasize = xdp->data - xdp->data_meta;
+ struct sk_buff *skb;
+
++ net_prefetch(xdp->data_meta);
++
+ /* allocate a skb to store the frags */
+- skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
+- bi->xdp->data_end - bi->xdp->data_hard_start,
++ skb = __napi_alloc_skb(&rx_ring->q_vector->napi, totalsize,
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ return NULL;
+
+- skb_reserve(skb, bi->xdp->data - bi->xdp->data_hard_start);
+- memcpy(__skb_put(skb, datasize), bi->xdp->data, datasize);
+- if (metasize)
++ memcpy(__skb_put(skb, totalsize), xdp->data_meta,
++ ALIGN(totalsize, sizeof(long)));
++
++ if (metasize) {
+ skb_metadata_set(skb, metasize);
++ __skb_pull(skb, metasize);
++ }
+
+- xsk_buff_free(bi->xdp);
+- bi->xdp = NULL;
+ return skb;
+ }
+
+@@ -311,12 +313,15 @@ int ixgbe_clean_rx_irq_zc(struct ixgbe_q_vector *q_vector,
+ }
+
+ /* XDP_PASS path */
+- skb = ixgbe_construct_skb_zc(rx_ring, bi);
++ skb = ixgbe_construct_skb_zc(rx_ring, bi->xdp);
+ if (!skb) {
+ rx_ring->rx_stats.alloc_rx_buff_failed++;
+ break;
+ }
+
++ xsk_buff_free(bi->xdp);
++ bi->xdp = NULL;
++
+ cleaned_count++;
+ ixgbe_inc_ntc(rx_ring);
+
+@@ -388,12 +393,14 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
u32 cmd_type;
while (budget-- > 0) {
@@ -79246,7 +118021,7 @@ index a9bdbf0dcfe1e..5bb1cc8a2ce13 100644
return 0;
}
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
-index 28d5ad296646a..1b61fe2e9b4d5 100644
+index 28d5ad296646a..90fd5588e20dd 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2700,6 +2700,16 @@ MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids);
@@ -79272,7 +118047,7 @@ index 28d5ad296646a..1b61fe2e9b4d5 100644
- of_get_mac_address(pnp, ppd.mac_addr);
+ ret = of_get_mac_address(pnp, ppd.mac_addr);
-+ if (ret)
++ if (ret == -EPROBE_DEFER)
+ return ret;
mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size);
@@ -81208,7 +119983,7 @@ index 6970540dc4709..603361c94786a 100644
nix_free_all_bandprof(rvu, pcifunc);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
-index 5efb4174e82df..fbb573c40c1ac 100644
+index 5efb4174e82df..c4a46b295d401 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -402,6 +402,7 @@ static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam,
@@ -81243,7 +120018,76 @@ index 5efb4174e82df..fbb573c40c1ac 100644
/* Set 'action' */
rvu_write64(rvu, blkaddr,
-@@ -916,7 +923,8 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
+@@ -598,7 +605,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+ struct npc_install_flow_req req = { 0 };
+ struct npc_install_flow_rsp rsp = { 0 };
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+- struct nix_rx_action action;
++ struct nix_rx_action action = { 0 };
+ int blkaddr, index;
+
+ /* AF's and SDP VFs work in promiscuous mode */
+@@ -619,7 +626,6 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+ *(u64 *)&action = npc_get_mcam_action(rvu, mcam,
+ blkaddr, index);
+ } else {
+- *(u64 *)&action = 0x00;
+ action.op = NIX_RX_ACTIONOP_UCAST;
+ action.pf_func = pcifunc;
+ }
+@@ -650,7 +656,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ struct rvu_hwinfo *hw = rvu->hw;
+ int blkaddr, ucast_idx, index;
+- struct nix_rx_action action;
++ struct nix_rx_action action = { 0 };
+ u64 relaxed_mask;
+
+ if (!hw->cap.nix_rx_multicast && is_cgx_vf(rvu, pcifunc))
+@@ -678,14 +684,14 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+ blkaddr, ucast_idx);
+
+ if (action.op != NIX_RX_ACTIONOP_RSS) {
+- *(u64 *)&action = 0x00;
++ *(u64 *)&action = 0;
+ action.op = NIX_RX_ACTIONOP_UCAST;
+ }
+
+ /* RX_ACTION set to MCAST for CGX PF's */
+ if (hw->cap.nix_rx_multicast && pfvf->use_mce_list &&
+ is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) {
+- *(u64 *)&action = 0x00;
++ *(u64 *)&action = 0;
+ action.op = NIX_RX_ACTIONOP_MCAST;
+ pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
+ action.index = pfvf->promisc_mce_idx;
+@@ -825,7 +831,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+ struct rvu_hwinfo *hw = rvu->hw;
+ int blkaddr, ucast_idx, index;
+ u8 mac_addr[ETH_ALEN] = { 0 };
+- struct nix_rx_action action;
++ struct nix_rx_action action = { 0 };
+ struct rvu_pfvf *pfvf;
+ u16 vf_func;
+
+@@ -854,14 +860,14 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+ blkaddr, ucast_idx);
+
+ if (action.op != NIX_RX_ACTIONOP_RSS) {
+- *(u64 *)&action = 0x00;
++ *(u64 *)&action = 0;
+ action.op = NIX_RX_ACTIONOP_UCAST;
+ action.pf_func = pcifunc;
+ }
+
+ /* RX_ACTION set to MCAST for CGX PF's */
+ if (hw->cap.nix_rx_multicast && pfvf->use_mce_list) {
+- *(u64 *)&action = 0x00;
++ *(u64 *)&action = 0;
+ action.op = NIX_RX_ACTIONOP_MCAST;
+ action.index = pfvf->mcast_mce_idx;
+ }
+@@ -916,7 +922,8 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 pcifunc, u64 rx_action)
{
int actindex, index, bank, entry;
@@ -81253,7 +120097,7 @@ index 5efb4174e82df..fbb573c40c1ac 100644
if (!(pcifunc & RVU_PFVF_FUNC_MASK))
return;
-@@ -924,6 +932,14 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
+@@ -924,6 +931,14 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
mutex_lock(&mcam->lock);
for (index = 0; index < mcam->bmap_entries; index++) {
if (mcam->entry2target_pffunc[index] == pcifunc) {
@@ -81268,7 +120112,7 @@ index 5efb4174e82df..fbb573c40c1ac 100644
bank = npc_get_bank(mcam, index);
actindex = index;
entry = index & (mcam->banksize - 1);
-@@ -3167,6 +3183,102 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
+@@ -3167,6 +3182,102 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
return 0;
}
@@ -81549,7 +120393,7 @@ index 53df7fff92c40..b1894d4045b8d 100644
return 0;
}
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
-index 44c670807fb3c..aa543b29799ed 100644
+index 44c670807fb3c..656c68cfd7ec6 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -54,12 +54,14 @@ int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
@@ -81588,7 +120432,15 @@ index 44c670807fb3c..aa543b29799ed 100644
}
read_unlock(&sw->port_list_lock);
-@@ -703,23 +707,27 @@ static int prestera_netdev_port_event(struct net_device *lower,
+@@ -488,6 +492,7 @@ static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)
+ dev_info(prestera_dev(sw), "using random base mac address\n");
+ }
+ of_node_put(base_mac_np);
++ of_node_put(np);
+
+ return prestera_hw_switch_mac_set(sw, sw->base_mac);
+ }
+@@ -703,23 +708,27 @@ static int prestera_netdev_port_event(struct net_device *lower,
struct net_device *dev,
unsigned long event, void *ptr)
{
@@ -81620,7 +120472,7 @@ index 44c670807fb3c..aa543b29799ed 100644
break;
if (netdev_has_any_upper_dev(upper)) {
-@@ -728,7 +736,7 @@ static int prestera_netdev_port_event(struct net_device *lower,
+@@ -728,7 +737,7 @@ static int prestera_netdev_port_event(struct net_device *lower,
}
if (netif_is_lag_master(upper) &&
@@ -81629,7 +120481,7 @@ index 44c670807fb3c..aa543b29799ed 100644
return -EOPNOTSUPP;
if (netif_is_lag_master(upper) && vlan_uses_dev(dev)) {
NL_SET_ERR_MSG_MOD(extack,
-@@ -744,14 +752,15 @@ static int prestera_netdev_port_event(struct net_device *lower,
+@@ -744,14 +753,15 @@ static int prestera_netdev_port_event(struct net_device *lower,
break;
case NETDEV_CHANGEUPPER:
@@ -81797,6 +120649,31 @@ index 5ef70dd8b49c6..f2d90639d7ed1 100644
#define PHY_IAC_TIMEOUT HZ
#define MTK_MAC_MISC 0x1000c
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+index 3ad10c793308e..66298e2235c91 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -395,7 +395,7 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe)
+ static const u8 skip[] = { 12, 25, 38, 51, 76, 89, 102 };
+ int i, k;
+
+- memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(ppe->foe_table));
++ memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(*ppe->foe_table));
+
+ if (!IS_ENABLED(CONFIG_SOC_MT7621))
+ return;
+diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+index 32d83421226a2..5897940a418b6 100644
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -26,6 +26,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+ break;
+
+ ss->regmap[i] = syscon_node_to_regmap(np);
++ of_node_put(np);
+ if (IS_ERR(ss->regmap[i]))
+ return PTR_ERR(ss->regmap[i]);
+ }
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index ef518b1040f72..fde521b1eecad 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -81844,25 +120721,48 @@ index 8af7f28273225..3bd3603873e32 100644
if (mlx4_en_alloc_resources(tmp)) {
en_warn(priv,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
-index db5dfff585c99..00f63fbfe9b48 100644
+index db5dfff585c99..e06a6104e91fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
-@@ -147,8 +147,12 @@ static void cmd_ent_put(struct mlx5_cmd_work_ent *ent)
+@@ -130,11 +130,8 @@ static int cmd_alloc_index(struct mlx5_cmd *cmd)
+
+ static void cmd_free_index(struct mlx5_cmd *cmd, int idx)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cmd->alloc_lock, flags);
++ lockdep_assert_held(&cmd->alloc_lock);
+ set_bit(idx, &cmd->bitmask);
+- spin_unlock_irqrestore(&cmd->alloc_lock, flags);
+ }
+
+ static void cmd_ent_get(struct mlx5_cmd_work_ent *ent)
+@@ -144,13 +141,21 @@ static void cmd_ent_get(struct mlx5_cmd_work_ent *ent)
+
+ static void cmd_ent_put(struct mlx5_cmd_work_ent *ent)
+ {
++ struct mlx5_cmd *cmd = ent->cmd;
++ unsigned long flags;
++
++ spin_lock_irqsave(&cmd->alloc_lock, flags);
if (!refcount_dec_and_test(&ent->refcnt))
- return;
+- return;
++ goto out;
- if (ent->idx >= 0)
- cmd_free_index(ent->cmd, ent->idx);
+ if (ent->idx >= 0) {
-+ struct mlx5_cmd *cmd = ent->cmd;
-+
+ cmd_free_index(cmd, ent->idx);
+ up(ent->page_queue ? &cmd->pages_sem : &cmd->sem);
+ }
cmd_free_ent(ent);
++out:
++ spin_unlock_irqrestore(&cmd->alloc_lock, flags);
}
-@@ -334,6 +338,9 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
+
+ static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx)
+@@ -334,6 +339,9 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
case MLX5_CMD_OP_PAGE_FAULT_RESUME:
case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
case MLX5_CMD_OP_DEALLOC_SF:
@@ -81872,7 +120772,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
return MLX5_CMD_STAT_OK;
case MLX5_CMD_OP_QUERY_HCA_CAP:
-@@ -439,7 +446,6 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
+@@ -439,7 +447,6 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
case MLX5_CMD_OP_MODIFY_TIS:
case MLX5_CMD_OP_QUERY_TIS:
case MLX5_CMD_OP_CREATE_RQT:
@@ -81880,7 +120780,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
case MLX5_CMD_OP_QUERY_RQT:
case MLX5_CMD_OP_CREATE_FLOW_TABLE:
-@@ -459,9 +465,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
+@@ -459,9 +466,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
case MLX5_CMD_OP_CREATE_UCTX:
@@ -81890,7 +120790,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
case MLX5_CMD_OP_ALLOC_MEMIC:
case MLX5_CMD_OP_MODIFY_XRQ:
case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
-@@ -895,25 +899,6 @@ static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode)
+@@ -895,25 +900,6 @@ static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode)
return cmd->allowed_opcode == opcode;
}
@@ -81916,7 +120816,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
bool mlx5_cmd_is_down(struct mlx5_core_dev *dev)
{
return pci_channel_offline(dev->pdev) ||
-@@ -938,7 +923,7 @@ static void cmd_work_handler(struct work_struct *work)
+@@ -938,7 +924,7 @@ static void cmd_work_handler(struct work_struct *work)
sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
down(sem);
if (!ent->page_queue) {
@@ -81925,7 +120825,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
if (alloc_ret < 0) {
mlx5_core_err_rl(dev, "failed to allocate command entry\n");
if (ent->callback) {
-@@ -1594,8 +1579,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+@@ -1594,8 +1580,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
vector = vec & 0xffffffff;
for (i = 0; i < (1 << cmd->log_sz); i++) {
if (test_bit(i, &vector)) {
@@ -81934,7 +120834,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
ent = cmd->ent_arr[i];
/* if we already completed the command, ignore it */
-@@ -1618,10 +1601,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+@@ -1618,10 +1602,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
cmd_ent_put(ent);
@@ -81945,7 +120845,7 @@ index db5dfff585c99..00f63fbfe9b48 100644
ent->ts2 = ktime_get_ns();
memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
dump_command(dev, ent, 0);
-@@ -1675,7 +1654,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+@@ -1675,7 +1655,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
*/
complete(&ent->done);
}
@@ -81989,7 +120889,7 @@ index 07c8d9811bc81..10d195042ab55 100644
+ }
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
-index dcf9f27ba2efd..d7576b6fa43b7 100644
+index dcf9f27ba2efd..7d56a927081d0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -625,7 +625,6 @@ static int mlx5_devlink_eth_param_register(struct devlink *devlink)
@@ -82040,43 +120940,113 @@ index dcf9f27ba2efd..d7576b6fa43b7 100644
devlink_param_unregister(devlink, &enable_vnet_param);
}
-@@ -799,16 +793,12 @@ int mlx5_devlink_register(struct devlink *devlink)
- {
- int err;
-
-- err = devlink_register(devlink);
-- if (err)
-- return err;
--
- err = devlink_params_register(devlink, mlx5_devlink_params,
- ARRAY_SIZE(mlx5_devlink_params));
+@@ -808,7 +802,6 @@ int mlx5_devlink_register(struct devlink *devlink)
if (err)
-- goto params_reg_err;
-+ return err;
-+
+ goto params_reg_err;
mlx5_devlink_set_params_init_values(devlink);
- devlink_params_publish(devlink);
err = mlx5_devlink_auxdev_params_register(devlink);
if (err)
-@@ -825,8 +815,6 @@ traps_reg_err:
- auxdev_reg_err:
- devlink_params_unregister(devlink, mlx5_devlink_params,
- ARRAY_SIZE(mlx5_devlink_params));
--params_reg_err:
-- devlink_unregister(devlink);
- return err;
- }
+@@ -818,6 +811,7 @@ int mlx5_devlink_register(struct devlink *devlink)
+ if (err)
+ goto traps_reg_err;
+
++ devlink_params_publish(devlink);
+ return 0;
-@@ -834,8 +822,6 @@ void mlx5_devlink_unregister(struct devlink *devlink)
+ traps_reg_err:
+@@ -832,9 +826,9 @@ params_reg_err:
+
+ void mlx5_devlink_unregister(struct devlink *devlink)
{
++ devlink_params_unpublish(devlink);
mlx5_devlink_traps_unregister(devlink);
mlx5_devlink_auxdev_params_unregister(devlink);
- devlink_params_unpublish(devlink);
devlink_params_unregister(devlink, mlx5_devlink_params,
ARRAY_SIZE(mlx5_devlink_params));
-- devlink_unregister(devlink);
+ devlink_unregister(devlink);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c
+index ed4fb79b4db76..75b6060f7a9ae 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c
+@@ -31,6 +31,7 @@ static const char *const mlx5_rsc_sgmt_name[] = {
+ struct mlx5_rsc_dump {
+ u32 pdn;
+ struct mlx5_core_mkey mkey;
++ u32 number_of_menu_items;
+ u16 fw_segment_type[MLX5_SGMT_TYPE_NUM];
+ };
+
+@@ -50,21 +51,37 @@ static int mlx5_rsc_dump_sgmt_get_by_name(char *name)
+ return -EINVAL;
+ }
+
+-static void mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page)
++#define MLX5_RSC_DUMP_MENU_HEADER_SIZE (MLX5_ST_SZ_BYTES(resource_dump_info_segment) + \
++ MLX5_ST_SZ_BYTES(resource_dump_command_segment) + \
++ MLX5_ST_SZ_BYTES(resource_dump_menu_segment))
++
++static int mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page,
++ int read_size, int start_idx)
+ {
+ void *data = page_address(page);
+ enum mlx5_sgmt_type sgmt_idx;
+ int num_of_items;
+ char *sgmt_name;
+ void *member;
++ int size = 0;
+ void *menu;
+ int i;
+
+- menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu);
+- num_of_items = MLX5_GET(resource_dump_menu_segment, menu, num_of_records);
++ if (!start_idx) {
++ menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu);
++ rsc_dump->number_of_menu_items = MLX5_GET(resource_dump_menu_segment, menu,
++ num_of_records);
++ size = MLX5_RSC_DUMP_MENU_HEADER_SIZE;
++ data += size;
++ }
++ num_of_items = rsc_dump->number_of_menu_items;
++
++ for (i = 0; start_idx + i < num_of_items; i++) {
++ size += MLX5_ST_SZ_BYTES(resource_dump_menu_record);
++ if (size >= read_size)
++ return start_idx + i;
+
+- for (i = 0; i < num_of_items; i++) {
+- member = MLX5_ADDR_OF(resource_dump_menu_segment, menu, record[i]);
++ member = data + MLX5_ST_SZ_BYTES(resource_dump_menu_record) * i;
+ sgmt_name = MLX5_ADDR_OF(resource_dump_menu_record, member, segment_name);
+ sgmt_idx = mlx5_rsc_dump_sgmt_get_by_name(sgmt_name);
+ if (sgmt_idx == -EINVAL)
+@@ -72,6 +89,7 @@ static void mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct
+ rsc_dump->fw_segment_type[sgmt_idx] = MLX5_GET(resource_dump_menu_record,
+ member, segment_type);
+ }
++ return 0;
}
+
+ static int mlx5_rsc_dump_trigger(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
+@@ -168,6 +186,7 @@ static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev)
+ struct mlx5_rsc_dump_cmd *cmd = NULL;
+ struct mlx5_rsc_key key = {};
+ struct page *page;
++ int start_idx = 0;
+ int size;
+ int err;
+
+@@ -189,7 +208,7 @@ static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev)
+ if (err < 0)
+ goto destroy_cmd;
+
+- mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page);
++ start_idx = mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page, size, start_idx);
+
+ } while (err > 0);
+
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 03a7a4ce5cd5e..7204bc86e4741 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -82219,6 +121189,21 @@ index 879ad46d754e1..e9593f5f06610 100644
/* Build queue parameters */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
+index 673f1c82d3815..c9d5d8d93994d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
+@@ -309,8 +309,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
+ if (err)
+ return err;
+
+- err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, port_buff_cell_sz,
+- xoff, &port_buffer, &update_buffer);
++ err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, xoff,
++ port_buff_cell_sz, &port_buffer, &update_buffer);
+ if (err)
+ return err;
+ }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
index e8a8d78e3e4d5..965838893432d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
@@ -82850,7 +121835,7 @@ index db0146df9b303..9ef8a49d78014 100644
+#endif /* CONFIG_MLX5_TC_SAMPLE */
#endif /* __MLX5_EN_TC_SAMPLE_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
-index 6c949abcd2e14..bc65151321ec2 100644
+index 6c949abcd2e14..d4b7b4d73b08e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -1356,9 +1356,13 @@ mlx5_tc_ct_match_add(struct mlx5_tc_ct_priv *priv,
@@ -82885,7 +121870,25 @@ index 6c949abcd2e14..bc65151321ec2 100644
return 0;
}
-@@ -1898,23 +1913,16 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
+@@ -1684,6 +1699,8 @@ mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg)
+ static void
+ mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft)
+ {
++ struct mlx5e_priv *priv;
++
+ if (!refcount_dec_and_test(&ft->refcount))
+ return;
+
+@@ -1693,6 +1710,8 @@ mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft)
+ rhashtable_free_and_destroy(&ft->ct_entries_ht,
+ mlx5_tc_ct_flush_ft_entry,
+ ct_priv);
++ priv = netdev_priv(ct_priv->netdev);
++ flush_workqueue(priv->wq);
+ mlx5_tc_ct_free_pre_ct_tables(ft);
+ mapping_remove(ct_priv->zone_mapping, ft->zone_restore_id);
+ kfree(ft);
+@@ -1898,23 +1917,16 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
memcpy(pre_ct_attr, attr, attr_sz);
@@ -82910,7 +121913,7 @@ index 6c949abcd2e14..bc65151321ec2 100644
rule = mlx5_tc_rule_insert(priv, orig_spec, pre_ct_attr);
if (IS_ERR(rule)) {
-@@ -1930,7 +1938,7 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
+@@ -1930,7 +1942,7 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
err_insert:
mlx5_modify_header_dealloc(priv->mdev, mod_hdr);
@@ -83374,6 +122377,27 @@ index 62abce008c7b8..15711814d2d28 100644
db_cseg = cseg;
}
if (db_cseg)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+index a4c8d8d00d5a4..72e08559e0d05 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+@@ -1198,6 +1198,16 @@ static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
+ if (err)
+ return err;
+
++ if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) {
++ /*
++ * Align the driver state with the register state.
++ * Temporary state change is required to enable the app list reset.
++ */
++ priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP;
++ mlx5e_dcbnl_delete_app(priv);
++ priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP;
++ }
++
+ mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params,
+ priv->dcbx_dp.trust_state);
+
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 9d451b8ee467c..2d3cd237355a6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -83423,7 +122447,7 @@ index 03693fa74a704..d32b70c62c949 100644
return err;
eth_rule->rss = rss;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
-index 41ef6eb70a585..f075bb8ccd00d 100644
+index 41ef6eb70a585..7efb898e9f96f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -911,8 +911,6 @@ void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
@@ -83618,7 +122642,21 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
-@@ -3606,7 +3628,7 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
+@@ -3520,6 +3542,13 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
+ }
+ }
+
++ if (params->xdp_prog) {
++ if (features & NETIF_F_LRO) {
++ netdev_warn(netdev, "LRO is incompatible with XDP\n");
++ features &= ~NETIF_F_LRO;
++ }
++ }
++
+ if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
+ features &= ~NETIF_F_RXHASH;
+ if (netdev->features & NETIF_F_RXHASH)
+@@ -3606,7 +3635,7 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
goto out;
}
@@ -83627,7 +122665,7 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
reset = false;
if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
-@@ -4063,8 +4085,8 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
+@@ -4063,8 +4092,8 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
struct net_device *netdev = priv->netdev;
struct mlx5e_params new_params;
@@ -83638,7 +122676,7 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
return -EINVAL;
}
-@@ -4321,9 +4343,10 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
+@@ -4321,9 +4350,10 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
/* No XSK params: checking the availability of striding RQ in general. */
if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL))
@@ -83651,7 +122689,7 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
/* CQ moderation params */
rx_cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
-@@ -4462,15 +4485,22 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+@@ -4462,15 +4492,22 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
}
if (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev)) {
@@ -83680,7 +122718,7 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
}
if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_IPIP)) {
-@@ -4608,7 +4638,6 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
+@@ -4608,7 +4645,6 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
{
struct mlx5_core_dev *mdev = priv->mdev;
enum mlx5e_rx_res_features features;
@@ -83688,7 +122726,7 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
int err;
priv->rx_res = mlx5e_rx_res_alloc();
-@@ -4626,9 +4655,9 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
+@@ -4626,9 +4662,9 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
features = MLX5E_RX_RES_FEATURE_XSK | MLX5E_RX_RES_FEATURE_PTP;
if (priv->channels.params.tunneled_offload_en)
features |= MLX5E_RX_RES_FEATURE_INNER_FT;
@@ -83700,6 +122738,14 @@ index 41ef6eb70a585..f075bb8ccd00d 100644
priv->channels.params.num_channels);
if (err)
goto err_close_drop_rq;
+@@ -4885,6 +4921,7 @@ mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *prof
+ }
+
+ netif_carrier_off(netdev);
++ netif_tx_disable(netdev);
+ dev_net_set(netdev, mlx5_core_net(mdev));
+
+ return netdev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 0684ac6699b2d..161b60e1139b3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -83795,7 +122841,7 @@ index 29a6586ef28dc..d2de1e6c514c1 100644
/* CQE csum doesn't cover padding octets in short ethernet
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
-index 129ff7e0d65cc..8b041deb25e5f 100644
+index 129ff7e0d65cc..60a4ac0ca76da 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -248,7 +248,6 @@ get_ct_priv(struct mlx5e_priv *priv)
@@ -83995,7 +123041,25 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
}
err = mlx5e_flower_parse_meta(filter_dev, f);
-@@ -2351,10 +2451,12 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -2191,6 +2291,17 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+ match.key->vlan_priority);
+
+ *match_level = MLX5_MATCH_L2;
++
++ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN) &&
++ match.mask->vlan_eth_type &&
++ MLX5_CAP_FLOWTABLE_TYPE(priv->mdev,
++ ft_field_support.outer_second_vid,
++ fs_type)) {
++ MLX5_SET(fte_match_set_misc, misc_c,
++ outer_second_cvlan_tag, 1);
++ spec->match_criteria_enable |=
++ MLX5_MATCH_MISC_PARAMETERS;
++ }
+ }
+ } else if (*match_level != MLX5_MATCH_NONE) {
+ /* cvlan_tag enabled in match criteria and
+@@ -2351,10 +2462,12 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct flow_match_ip match;
flow_rule_match_ip(rule, &match);
@@ -84012,7 +123076,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
match.mask->tos >> 2);
-@@ -3457,7 +3559,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
+@@ -3457,7 +3570,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
attr->dest_chain = act->chain_index;
break;
case FLOW_ACTION_CT:
@@ -84023,7 +123087,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
if (err)
return err;
-@@ -4008,7 +4112,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
+@@ -4008,7 +4123,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
return -EOPNOTSUPP;
}
@@ -84034,7 +123098,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
if (err)
return err;
-@@ -4222,6 +4328,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
+@@ -4222,6 +4339,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
INIT_LIST_HEAD(&flow->l3_to_l2_reformat);
refcount_set(&flow->refcnt, 1);
init_completion(&flow->init_done);
@@ -84042,7 +123106,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
*__flow = flow;
*__parse_attr = parse_attr;
-@@ -5008,9 +5115,7 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
+@@ -5008,9 +5126,7 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
MLX5_FLOW_NAMESPACE_FDB,
uplink_priv->post_act);
@@ -84052,7 +123116,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
mapping_id = mlx5_query_nic_system_image_guid(esw->dev);
-@@ -5054,9 +5159,7 @@ err_ht_init:
+@@ -5054,9 +5170,7 @@ err_ht_init:
err_enc_opts_mapping:
mapping_destroy(uplink_priv->tunnel_mapping);
err_tun_mapping:
@@ -84062,7 +123126,7 @@ index 129ff7e0d65cc..8b041deb25e5f 100644
mlx5_tc_ct_clean(uplink_priv->ct_priv);
netdev_warn(priv->netdev,
"Failed to initialize tc (eswitch), err: %d", err);
-@@ -5076,9 +5179,7 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
+@@ -5076,9 +5190,7 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
mapping_destroy(uplink_priv->tunnel_enc_opts_mapping);
mapping_destroy(uplink_priv->tunnel_mapping);
@@ -84318,18 +123382,131 @@ index fe501ba88bea9..00834c914dc64 100644
kfree(handle);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
-index 106b50e42b464..a45c6f25add16 100644
+index 106b50e42b464..8c2b249949b97 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
-@@ -131,7 +131,7 @@ static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
+@@ -111,6 +111,28 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
+ }
+ }
+
++static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
++{
++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
++
++ del_timer_sync(&fw_reset->timer);
++}
++
++static int mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health)
++{
++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
++
++ if (!test_and_clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) {
++ mlx5_core_warn(dev, "Reset request was already cleared\n");
++ return -EALREADY;
++ }
++
++ mlx5_stop_sync_reset_poll(dev);
++ if (poll_health)
++ mlx5_start_health_poll(dev);
++ return 0;
++}
++
+ static void mlx5_sync_reset_reload_work(struct work_struct *work)
{
- struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+ struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
+@@ -118,6 +140,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work)
+ struct mlx5_core_dev *dev = fw_reset->dev;
+ int err;
++ mlx5_sync_reset_clear_reset_requested(dev, false);
+ mlx5_enter_error_state(dev, true);
+ mlx5_unload_one(dev);
+ err = mlx5_health_wait_pci_up(dev);
+@@ -127,23 +150,6 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work)
+ mlx5_fw_reset_complete_reload(dev);
+ }
+
+-static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
+-{
+- struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+-
- del_timer(&fw_reset->timer);
-+ del_timer_sync(&fw_reset->timer);
+-}
+-
+-static void mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health)
+-{
+- struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+-
+- mlx5_stop_sync_reset_poll(dev);
+- clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags);
+- if (poll_health)
+- mlx5_start_health_poll(dev);
+-}
+-
+ #define MLX5_RESET_POLL_INTERVAL (HZ / 10)
+ static void poll_sync_reset(struct timer_list *t)
+ {
+@@ -158,7 +164,6 @@ static void poll_sync_reset(struct timer_list *t)
+
+ if (fatal_error) {
+ mlx5_core_warn(dev, "Got Device Reset\n");
+- mlx5_sync_reset_clear_reset_requested(dev, false);
+ queue_work(fw_reset->wq, &fw_reset->reset_reload_work);
+ return;
+ }
+@@ -185,13 +190,17 @@ static int mlx5_fw_reset_set_reset_sync_nack(struct mlx5_core_dev *dev)
+ return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL3, 0, 2, false);
+ }
+
+-static void mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev)
++static int mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev)
+ {
+ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+
++ if (test_and_set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) {
++ mlx5_core_warn(dev, "Reset request was already set\n");
++ return -EALREADY;
++ }
+ mlx5_stop_health_poll(dev, true);
+- set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags);
+ mlx5_start_sync_reset_poll(dev);
++ return 0;
+ }
+
+ static void mlx5_fw_live_patch_event(struct work_struct *work)
+@@ -220,7 +229,9 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
+ err ? "Failed" : "Sent");
+ return;
+ }
+- mlx5_sync_reset_set_reset_requested(dev);
++ if (mlx5_sync_reset_set_reset_requested(dev))
++ return;
++
+ err = mlx5_fw_reset_set_reset_sync_ack(dev);
+ if (err)
+ mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err);
+@@ -320,7 +331,8 @@ static void mlx5_sync_reset_now_event(struct work_struct *work)
+ struct mlx5_core_dev *dev = fw_reset->dev;
+ int err;
+
+- mlx5_sync_reset_clear_reset_requested(dev, false);
++ if (mlx5_sync_reset_clear_reset_requested(dev, false))
++ return;
+
+ mlx5_core_warn(dev, "Sync Reset now. Device is going to reset.\n");
+
+@@ -349,10 +361,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work)
+ reset_abort_work);
+ struct mlx5_core_dev *dev = fw_reset->dev;
+
+- if (!test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags))
++ if (mlx5_sync_reset_clear_reset_requested(dev, true))
+ return;
+-
+- mlx5_sync_reset_clear_reset_requested(dev, true);
+ mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
}
- static void mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index 269ebb53eda67..cfde0a45b8b8a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -84426,10 +123603,112 @@ index d2105c1635c34..c19d9327095b2 100644
switch (event) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
-index 21fdaf708f1fe..30282d86e6b96 100644
+index 21fdaf708f1fe..81786a9a424c8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
-@@ -268,10 +268,8 @@ static int mlx5_lag_fib_event(struct notifier_block *nb,
+@@ -100,6 +100,14 @@ static void mlx5_lag_fib_event_flush(struct notifier_block *nb)
+ flush_workqueue(mp->wq);
+ }
+
++static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi, u32 dst, int dst_len)
++{
++ mp->fib.mfi = fi;
++ mp->fib.priority = fi->fib_priority;
++ mp->fib.dst = dst;
++ mp->fib.dst_len = dst_len;
++}
++
+ struct mlx5_fib_event_work {
+ struct work_struct work;
+ struct mlx5_lag *ldev;
+@@ -110,10 +118,10 @@ struct mlx5_fib_event_work {
+ };
+ };
+
+-static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+- unsigned long event,
+- struct fib_info *fi)
++static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
++ struct fib_entry_notifier_info *fen_info)
+ {
++ struct fib_info *fi = fen_info->fi;
+ struct lag_mp *mp = &ldev->lag_mp;
+ struct fib_nh *fib_nh0, *fib_nh1;
+ unsigned int nhs;
+@@ -121,11 +129,17 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+ /* Handle delete event */
+ if (event == FIB_EVENT_ENTRY_DEL) {
+ /* stop track */
+- if (mp->mfi == fi)
+- mp->mfi = NULL;
++ if (mp->fib.mfi == fi)
++ mp->fib.mfi = NULL;
+ return;
+ }
+
++ /* Handle multipath entry with lower priority value */
++ if (mp->fib.mfi && mp->fib.mfi != fi &&
++ (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) &&
++ fi->fib_priority >= mp->fib.priority)
++ return;
++
+ /* Handle add/replace event */
+ nhs = fib_info_num_path(fi);
+ if (nhs == 1) {
+@@ -135,12 +149,13 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+ int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev);
+
+ if (i < 0)
+- i = MLX5_LAG_NORMAL_AFFINITY;
+- else
+- ++i;
++ return;
+
++ i++;
+ mlx5_lag_set_port_affinity(ldev, i);
++ mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+ }
++
+ return;
+ }
+
+@@ -160,7 +175,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+ }
+
+ /* First time we see multipath route */
+- if (!mp->mfi && !__mlx5_lag_is_active(ldev)) {
++ if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) {
+ struct lag_tracker tracker;
+
+ tracker = ldev->tracker;
+@@ -168,7 +183,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+ }
+
+ mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY);
+- mp->mfi = fi;
++ mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+ }
+
+ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
+@@ -179,7 +194,7 @@ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
+ struct lag_mp *mp = &ldev->lag_mp;
+
+ /* Check the nh event is related to the route */
+- if (!mp->mfi || mp->mfi != fi)
++ if (!mp->fib.mfi || mp->fib.mfi != fi)
+ return;
+
+ /* nh added/removed */
+@@ -209,7 +224,7 @@ static void mlx5_lag_fib_update(struct work_struct *work)
+ case FIB_EVENT_ENTRY_REPLACE:
+ case FIB_EVENT_ENTRY_DEL:
+ mlx5_lag_fib_route_event(ldev, fib_work->event,
+- fib_work->fen_info.fi);
++ &fib_work->fen_info);
+ fib_info_put(fib_work->fen_info.fi);
+ break;
+ case FIB_EVENT_NH_ADD:
+@@ -268,10 +283,8 @@ static int mlx5_lag_fib_event(struct notifier_block *nb,
fen_info = container_of(info, struct fib_entry_notifier_info,
info);
fi = fen_info->fi;
@@ -84442,17 +123721,54 @@ index 21fdaf708f1fe..30282d86e6b96 100644
fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
if (fib_dev != ldev->pf[MLX5_LAG_P1].netdev &&
fib_dev != ldev->pf[MLX5_LAG_P2].netdev) {
+@@ -310,7 +323,7 @@ void mlx5_lag_mp_reset(struct mlx5_lag *ldev)
+ /* Clear mfi, as it might become stale when a route delete event
+ * has been missed, see mlx5_lag_fib_route_event().
+ */
+- ldev->lag_mp.mfi = NULL;
++ ldev->lag_mp.fib.mfi = NULL;
+ }
+
+ int mlx5_lag_mp_init(struct mlx5_lag *ldev)
+@@ -321,7 +334,7 @@ int mlx5_lag_mp_init(struct mlx5_lag *ldev)
+ /* always clear mfi, as it might become stale when a route delete event
+ * has been missed
+ */
+- mp->mfi = NULL;
++ mp->fib.mfi = NULL;
+
+ if (mp->fib_nb.notifier_call)
+ return 0;
+@@ -351,5 +364,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev)
+ unregister_fib_notifier(&init_net, &mp->fib_nb);
+ destroy_workqueue(mp->wq);
+ mp->fib_nb.notifier_call = NULL;
+- mp->mfi = NULL;
++ mp->fib.mfi = NULL;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h
+index dea199e79beda..b3a7f18b9e303 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h
+@@ -15,7 +15,12 @@ enum mlx5_lag_port_affinity {
+
+ struct lag_mp {
+ struct notifier_block fib_nb;
+- struct fib_info *mfi; /* used in tracking fib events */
++ struct {
++ const void *mfi; /* used in tracking fib events */
++ u32 priority;
++ u32 dst;
++ int dst_len;
++ } fib;
+ struct workqueue_struct *wq;
+ };
+
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
-index 97e5845b4cfdd..1e8ec4f236b28 100644
+index 97e5845b4cfdd..df58cba37930a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
-@@ -121,9 +121,16 @@ u32 mlx5_chains_get_nf_ft_chain(struct mlx5_fs_chains *chains)
-
- u32 mlx5_chains_get_prio_range(struct mlx5_fs_chains *chains)
- {
-+ if (!mlx5_chains_prios_supported(chains))
-+ return 1;
-+
+@@ -124,6 +124,10 @@ u32 mlx5_chains_get_prio_range(struct mlx5_fs_chains *chains)
if (mlx5_chains_ignore_flow_level_supported(chains))
return UINT_MAX;
@@ -84463,7 +123779,7 @@ index 97e5845b4cfdd..1e8ec4f236b28 100644
/* We should get here only for eswitch case */
return FDB_TC_MAX_PRIO;
}
-@@ -208,7 +215,7 @@ static int
+@@ -208,7 +212,7 @@ static int
create_chain_restore(struct fs_chain *chain)
{
struct mlx5_eswitch *esw = chain->chains->dev->priv.eswitch;
@@ -84473,7 +123789,7 @@ index 97e5845b4cfdd..1e8ec4f236b28 100644
enum mlx5e_tc_attr_to_reg chain_to_reg;
struct mlx5_modify_hdr *mod_hdr;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
-index 79482824c64ff..097ab6fe371ca 100644
+index 79482824c64ff..4ed7409942791 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -97,6 +97,8 @@ enum {
@@ -84505,23 +123821,7 @@ index 79482824c64ff..097ab6fe371ca 100644
mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n",
prof->log_max_qp,
MLX5_CAP_GEN_MAX(dev, log_max_qp));
-@@ -1537,6 +1541,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
- dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
-
- pci_save_state(pdev);
-+ devlink_register(devlink);
- if (!mlx5_core_is_mp_slave(dev))
- devlink_reload_enable(devlink);
- return 0;
-@@ -1559,6 +1564,7 @@ static void remove_one(struct pci_dev *pdev)
- struct devlink *devlink = priv_to_devlink(dev);
-
- devlink_reload_disable(devlink);
-+ devlink_unregister(devlink);
- mlx5_crdump_disable(dev);
- mlx5_drain_health_wq(dev);
- mlx5_uninit_one(dev);
-@@ -1756,10 +1762,12 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
+@@ -1756,10 +1760,12 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */
{ PCI_VDEVICE(MELLANOX, 0x101f) }, /* ConnectX-6 LX */
{ PCI_VDEVICE(MELLANOX, 0x1021) }, /* ConnectX-7 */
@@ -84534,7 +123834,7 @@ index 79482824c64ff..097ab6fe371ca 100644
{ 0, }
};
-@@ -1773,12 +1781,13 @@ void mlx5_disable_device(struct mlx5_core_dev *dev)
+@@ -1773,12 +1779,13 @@ void mlx5_disable_device(struct mlx5_core_dev *dev)
int mlx5_recover_device(struct mlx5_core_dev *dev)
{
@@ -84569,7 +123869,7 @@ index 763c83a023809..11f3649fdaab1 100644
return new_irq;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
-index 1ef2b6a848c10..7b16a1188aabb 100644
+index 1ef2b6a848c10..fd79860de723b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -406,23 +406,24 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
@@ -84601,6 +123901,42 @@ index 1ef2b6a848c10..7b16a1188aabb 100644
return mlx5_query_mcia(dev, &query, data);
}
+@@ -432,35 +433,12 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
+ struct mlx5_module_eeprom_query_params *params,
+ u8 *data)
+ {
+- u8 module_id;
+ int err;
+
+ err = mlx5_query_module_num(dev, &params->module_number);
+ if (err)
+ return err;
+
+- err = mlx5_query_module_id(dev, params->module_number, &module_id);
+- if (err)
+- return err;
+-
+- switch (module_id) {
+- case MLX5_MODULE_ID_SFP:
+- if (params->page > 0)
+- return -EINVAL;
+- break;
+- case MLX5_MODULE_ID_QSFP:
+- case MLX5_MODULE_ID_QSFP28:
+- case MLX5_MODULE_ID_QSFP_PLUS:
+- if (params->page > 3)
+- return -EINVAL;
+- break;
+- case MLX5_MODULE_ID_DSFP:
+- break;
+- default:
+- mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
+- return -EINVAL;
+- }
+-
+ if (params->i2c_address != MLX5_I2C_ADDR_HIGH &&
+ params->i2c_address != MLX5_I2C_ADDR_LOW) {
+ mlx5_core_err(dev, "I2C address not recognized: 0x%x\n", params->i2c_address);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
index 871c2fbe18d39..64bbc18332d56 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
@@ -84617,26 +123953,30 @@ index 871c2fbe18d39..64bbc18332d56 100644
}
static ssize_t sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
-diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
-index 052f48068dc16..3cf272fa21646 100644
---- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
-+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
-@@ -46,6 +46,7 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
- mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err);
- goto init_one_err;
- }
-+ devlink_register(devlink);
- devlink_reload_enable(devlink);
- return 0;
-
-@@ -65,6 +66,7 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
-
- devlink = priv_to_devlink(sf_dev->mdev);
- devlink_reload_disable(devlink);
-+ devlink_unregister(devlink);
- mlx5_uninit_one(sf_dev->mdev);
- iounmap(sf_dev->mdev->iseg);
- mlx5_mdev_uninit(sf_dev->mdev);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+index a5b9f65db23c6..897c7f8521238 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+@@ -846,7 +846,8 @@ struct mlx5dr_action *
+ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
+ struct mlx5dr_action_dest *dests,
+ u32 num_of_dests,
+- bool ignore_flow_level)
++ bool ignore_flow_level,
++ u32 flow_source)
+ {
+ struct mlx5dr_cmd_flow_destination_hw_info *hw_dests;
+ struct mlx5dr_action **ref_actions;
+@@ -914,7 +915,8 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
+ reformat_req,
+ &action->dest_tbl->fw_tbl.id,
+ &action->dest_tbl->fw_tbl.group_id,
+- ignore_flow_level);
++ ignore_flow_level,
++ flow_source);
+ if (ret)
+ goto free_action;
+
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
index 0fe159809ba15..ea1b8ca5bf3aa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
@@ -84661,6 +124001,28 @@ index 0fe159809ba15..ea1b8ca5bf3aa 100644
goto clean_pd;
}
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
+index 0d6f86eb248b9..c74083de1801b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
+@@ -104,7 +104,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
+ bool reformat_req,
+ u32 *tbl_id,
+ u32 *group_id,
+- bool ignore_flow_level)
++ bool ignore_flow_level,
++ u32 flow_source)
+ {
+ struct mlx5dr_cmd_create_flow_table_attr ft_attr = {};
+ struct mlx5dr_cmd_fte_info fte_info = {};
+@@ -139,6 +140,7 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
+ fte_info.val = val;
+ fte_info.dest_arr = dest;
+ fte_info.ignore_flow_level = ignore_flow_level;
++ fte_info.flow_context.flow_source = flow_source;
+
+ ret = mlx5dr_cmd_set_fte(dmn->mdev, 0, 0, &ft_info, *group_id, &fte_info);
+ if (ret) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c
index 66c24767e3b00..8ad8d73e17f06 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c
@@ -84960,7 +124322,7 @@ index 1cdfe4fccc7a9..01246a1ae7d13 100644
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
-index b20e8aabb861b..3d4e035698dd3 100644
+index b20e8aabb861b..bc206836af6ac 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
@@ -740,6 +740,16 @@ struct mlx5dr_match_param {
@@ -84980,11 +124342,50 @@ index b20e8aabb861b..3d4e035698dd3 100644
struct mlx5dr_esw_caps {
u64 drop_icm_address_rx;
u64 drop_icm_address_tx;
+@@ -1384,7 +1394,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
+ bool reformat_req,
+ u32 *tbl_id,
+ u32 *group_id,
+- bool ignore_flow_level);
++ bool ignore_flow_level,
++ u32 flow_source);
+ void mlx5dr_fw_destroy_md_tbl(struct mlx5dr_domain *dmn, u32 tbl_id,
+ u32 group_id);
+ #endif /* _DR_TYPES_H_ */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+index 7e58f4e594b74..ae4597118f8b6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+@@ -492,11 +492,13 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
+ } else if (num_term_actions > 1) {
+ bool ignore_flow_level =
+ !!(fte->action.flags & FLOW_ACT_IGNORE_FLOW_LEVEL);
++ u32 flow_source = fte->flow_context.flow_source;
+
+ tmp_action = mlx5dr_action_create_mult_dest_tbl(domain,
+ term_actions,
+ num_term_actions,
+- ignore_flow_level);
++ ignore_flow_level,
++ flow_source);
+ if (!tmp_action) {
+ err = -EOPNOTSUPP;
+ goto free_actions;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
-index c5a8b16019991..5ef1995434794 100644
+index c5a8b16019991..7806e5c05b677 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
-@@ -160,6 +160,11 @@ struct mlx5dr_icm_buddy_mem {
+@@ -96,7 +96,8 @@ struct mlx5dr_action *
+ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
+ struct mlx5dr_action_dest *dests,
+ u32 num_of_dests,
+- bool ignore_flow_level);
++ bool ignore_flow_level,
++ u32 flow_source);
+
+ struct mlx5dr_action *mlx5dr_action_create_drop(void);
+
+@@ -160,6 +161,11 @@ struct mlx5dr_icm_buddy_mem {
* sync_ste command sets them free.
*/
struct list_head hot_list;
@@ -85019,6 +124420,18 @@ index 392ce3cb27f72..51b260d54237e 100644
/* cmd_mbox_sw2hw_dq_sdq_tclass
* SDQ: CPU Egress TClass
* RDQ: Reserved
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+index 939b692ffc335..ce843ea914646 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+@@ -650,6 +650,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
+ return 0;
+
+ errout:
++ mutex_destroy(&mlxsw_i2c->cmd.lock);
+ i2c_set_clientdata(client, NULL);
+
+ return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index fcace73eae40f..d9f9cbba62465 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -85074,6 +124487,18 @@ index 250c5a24264dc..edfdd44de579c 100644
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port)
+diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
+index 93df3049cdc05..1b632cdd76309 100644
+--- a/drivers/net/ethernet/micrel/Kconfig
++++ b/drivers/net/ethernet/micrel/Kconfig
+@@ -39,6 +39,7 @@ config KS8851
+ config KS8851_MLL
+ tristate "Micrel KS8851 MLL"
+ depends on HAS_IOMEM
++ depends on PTP_1588_CLOCK_OPTIONAL
+ select MII
+ select CRC32
+ select EEPROM_93CX6
diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c
index 2e8fcce50f9d1..c6f517c07bb9a 100644
--- a/drivers/net/ethernet/micrel/ks8851_par.c
@@ -85130,6 +124555,19 @@ index 4d5a5d6595b3b..d64ce65a3c174 100644
}
}
+diff --git a/drivers/net/ethernet/microchip/sparx5/Kconfig b/drivers/net/ethernet/microchip/sparx5/Kconfig
+index 7bdbb2d09a148..cc5e48e1bb4c3 100644
+--- a/drivers/net/ethernet/microchip/sparx5/Kconfig
++++ b/drivers/net/ethernet/microchip/sparx5/Kconfig
+@@ -4,6 +4,8 @@ config SPARX5_SWITCH
+ depends on HAS_IOMEM
+ depends on OF
+ depends on ARCH_SPARX5 || COMPILE_TEST
++ depends on PTP_1588_CLOCK_OPTIONAL
++ depends on BRIDGE || BRIDGE=n
+ select PHYLINK
+ select PHY_SPARX5_SERDES
+ select RESET_CONTROLLER
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c
index 59783fc46a7b9..10b866e9f7266 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c
@@ -85143,6 +124581,19 @@ index 59783fc46a7b9..10b866e9f7266 100644
stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop
+ idx];
stats->tx_dropped = portstats[spx5_stats_tx_local_drop];
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
+index 7436f62fa1525..174ad95e746a3 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
+@@ -420,6 +420,8 @@ static int sparx5_fdma_tx_alloc(struct sparx5 *sparx5)
+ db_hw->dataptr = phys;
+ db_hw->status = 0;
+ db = devm_kzalloc(sparx5->dev, sizeof(*db), GFP_KERNEL);
++ if (!db)
++ return -ENOMEM;
+ db->cpu_addr = cpu_addr;
+ list_add_tail(&db->list, &tx->db_list);
+ }
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
index dc7e5ea6ec158..148d431fcde42 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
@@ -85210,7 +124661,7 @@ index b6a73d151dec1..8dd8c7f425d2c 100644
select GENERIC_PHY
help
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
-index a08e4f530c1c1..6aad0953e8fe5 100644
+index a08e4f530c1c1..a59300d9e0000 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -555,7 +555,10 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
@@ -85365,11 +124816,63 @@ index a08e4f530c1c1..6aad0953e8fe5 100644
ocelot_rmw_gix(ocelot,
ANA_PORT_PORT_CFG_PORTID_VAL(lag),
+@@ -1933,6 +1932,8 @@ static void ocelot_port_set_mcast_flood(struct ocelot *ocelot, int port,
+ val = BIT(port);
+
+ ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MC);
++ ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MCIPV4);
++ ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MCIPV6);
+ }
+
+ static void ocelot_port_set_bcast_flood(struct ocelot *ocelot, int port,
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
-index 8b843d3c9189a..afa062c5f82d3 100644
+index 8b843d3c9189a..a3a5ad5dbb0e0 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
-@@ -467,13 +467,6 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
+@@ -54,6 +54,12 @@ static int ocelot_chain_to_block(int chain, bool ingress)
+ */
+ static int ocelot_chain_to_lookup(int chain)
+ {
++ /* Backwards compatibility with older, single-chain tc-flower
++ * offload support in Ocelot
++ */
++ if (chain == 0)
++ return 0;
++
+ return (chain / VCAP_LOOKUP) % 10;
+ }
+
+@@ -62,7 +68,15 @@ static int ocelot_chain_to_lookup(int chain)
+ */
+ static int ocelot_chain_to_pag(int chain)
+ {
+- int lookup = ocelot_chain_to_lookup(chain);
++ int lookup;
++
++ /* Backwards compatibility with older, single-chain tc-flower
++ * offload support in Ocelot
++ */
++ if (chain == 0)
++ return 0;
++
++ lookup = ocelot_chain_to_lookup(chain);
+
+ /* calculate PAG value as chain index relative to the first PAG */
+ return chain - VCAP_IS2_CHAIN(lookup, 0);
+@@ -192,9 +206,10 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
+ filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
+ break;
+ case FLOW_ACTION_TRAP:
+- if (filter->block_id != VCAP_IS2) {
++ if (filter->block_id != VCAP_IS2 ||
++ filter->lookup != 0) {
+ NL_SET_ERR_MSG_MOD(extack,
+- "Trap action can only be offloaded to VCAP IS2");
++ "Trap action can only be offloaded to VCAP IS2 lookup 0");
+ return -EOPNOTSUPP;
+ }
+ if (filter->goto_target != -1) {
+@@ -467,13 +482,6 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
return -EOPNOTSUPP;
}
@@ -85383,7 +124886,7 @@ index 8b843d3c9189a..afa062c5f82d3 100644
/* The hw support mac matches only for MAC_ETYPE key,
* therefore if other matches(port, tcp flags, etc) are added
* then just bail out
-@@ -488,6 +481,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
+@@ -488,6 +496,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
return -EOPNOTSUPP;
flow_rule_match_eth_addrs(rule, &match);
@@ -85429,6 +124932,66 @@ index 2545727fd5b2f..c08c56e07b1d3 100644
&ocelot_switchdev_blocking_nb);
}
+diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
+index 99d7376a70a74..732a4ef22518d 100644
+--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
++++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
+@@ -373,7 +373,6 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
+ OCELOT_VCAP_BIT_0);
+ vcap_key_set(vcap, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0,
+ ~filter->ingress_port_mask);
+- vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_ANY);
+ vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_HOST_MATCH,
+ OCELOT_VCAP_BIT_ANY);
+ vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L2_MC, filter->dmac_mc);
+@@ -1153,6 +1152,8 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot,
+ struct ocelot_vcap_filter *tmp;
+
+ tmp = ocelot_vcap_block_find_filter_by_index(block, i);
++ /* Read back the filter's counters before moving it */
++ vcap_entry_get(ocelot, i - 1, tmp);
+ vcap_entry_set(ocelot, i, tmp);
+ }
+
+@@ -1192,7 +1193,11 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot,
+ struct ocelot_vcap_filter del_filter;
+ int i, index;
+
++ /* Need to inherit the block_id so that vcap_entry_set()
++ * does not get confused and knows where to install it.
++ */
+ memset(&del_filter, 0, sizeof(del_filter));
++ del_filter.block_id = filter->block_id;
+
+ /* Gets index of the filter */
+ index = ocelot_vcap_block_get_filter_index(block, filter);
+@@ -1207,6 +1212,8 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot,
+ struct ocelot_vcap_filter *tmp;
+
+ tmp = ocelot_vcap_block_find_filter_by_index(block, i);
++ /* Read back the filter's counters before moving it */
++ vcap_entry_get(ocelot, i + 1, tmp);
+ vcap_entry_set(ocelot, i, tmp);
+ }
+
+diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+index c1a75b08ced7e..052696ce50963 100644
+--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+@@ -2900,11 +2900,9 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+ status = myri10ge_xmit(curr, dev);
+ if (status != 0) {
+ dev_kfree_skb_any(curr);
+- if (segs != NULL) {
+- curr = segs;
+- segs = next;
++ skb_list_walk_safe(next, curr, next) {
+ curr->next = NULL;
+- dev_kfree_skb_any(segs);
++ dev_kfree_skb_any(curr);
+ }
+ goto drop;
+ }
diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index ca4686094701c..0a02d8bd0a3e5 100644
--- a/drivers/net/ethernet/natsemi/xtsonic.c
@@ -85600,6 +125163,126 @@ index d7ac0307797fd..34c0d2ddf9ef6 100644
cache->id = 0;
cache->addr = 0;
+diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
+index c910fa2f40a4b..919140522885d 100644
+--- a/drivers/net/ethernet/nxp/lpc_eth.c
++++ b/drivers/net/ethernet/nxp/lpc_eth.c
+@@ -1469,6 +1469,7 @@ static int lpc_eth_drv_resume(struct platform_device *pdev)
+ {
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct netdata_local *pldat;
++ int ret;
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(ndev->irq);
+@@ -1478,7 +1479,9 @@ static int lpc_eth_drv_resume(struct platform_device *pdev)
+ pldat = netdev_priv(ndev);
+
+ /* Enable interface clock */
+- clk_enable(pldat->clk);
++ ret = clk_enable(pldat->clk);
++ if (ret)
++ return ret;
+
+ /* Reset and initialize */
+ __lpc_eth_reset(pldat);
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+index 7e296fa71b368..d324c292318b3 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
++++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+@@ -255,7 +255,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ err = ionic_map_bars(ionic);
+ if (err)
+- goto err_out_pci_disable_device;
++ goto err_out_pci_release_regions;
+
+ /* Configure the device */
+ err = ionic_setup(ionic);
+@@ -331,6 +331,9 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ goto err_out_deregister_lifs;
+ }
+
++ mod_timer(&ionic->watchdog_timer,
++ round_jiffies(jiffies + ionic->watchdog_period));
++
+ return 0;
+
+ err_out_deregister_lifs:
+@@ -348,7 +351,6 @@ err_out_port_reset:
+ err_out_reset:
+ ionic_reset(ionic);
+ err_out_teardown:
+- del_timer_sync(&ionic->watchdog_timer);
+ pci_clear_master(pdev);
+ /* Don't fail the probe for these errors, keep
+ * the hw interface around for inspection
+@@ -357,6 +359,7 @@ err_out_teardown:
+
+ err_out_unmap_bars:
+ ionic_unmap_bars(ionic);
++err_out_pci_release_regions:
+ pci_release_regions(pdev);
+ err_out_pci_disable_device:
+ pci_disable_device(pdev);
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+index 0d6858ab511c6..b778d8264bca0 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
++++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+@@ -122,9 +122,6 @@ int ionic_dev_setup(struct ionic *ionic)
+ idev->fw_generation = IONIC_FW_STS_F_GENERATION &
+ ioread8(&idev->dev_info_regs->fw_status);
+
+- mod_timer(&ionic->watchdog_timer,
+- round_jiffies(jiffies + ionic->watchdog_period));
+-
+ idev->db_pages = bar->vaddr;
+ idev->phy_db_pages = bar->bus_addr;
+
+@@ -132,6 +129,16 @@ int ionic_dev_setup(struct ionic *ionic)
+ }
+
+ /* Devcmd Interface */
++bool ionic_is_fw_running(struct ionic_dev *idev)
++{
++ u8 fw_status = ioread8(&idev->dev_info_regs->fw_status);
++
++ /* firmware is useful only if the running bit is set and
++ * fw_status != 0xff (bad PCI read)
++ */
++ return (fw_status != 0xff) && (fw_status & IONIC_FW_STS_F_RUNNING);
++}
++
+ int ionic_heartbeat_check(struct ionic *ionic)
+ {
+ struct ionic_dev *idev = &ionic->idev;
+@@ -155,13 +162,10 @@ do_check_time:
+ goto do_check_time;
+ }
+
+- /* firmware is useful only if the running bit is set and
+- * fw_status != 0xff (bad PCI read)
+- * If fw_status is not ready don't bother with the generation.
+- */
+ fw_status = ioread8(&idev->dev_info_regs->fw_status);
+
+- if (fw_status == 0xff || !(fw_status & IONIC_FW_STS_F_RUNNING)) {
++ /* If fw_status is not ready don't bother with the generation */
++ if (!ionic_is_fw_running(idev)) {
+ fw_status_ready = false;
+ } else {
+ fw_generation = fw_status & IONIC_FW_STS_F_GENERATION;
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+index 8311086fb1f49..922bb6c9e01d5 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
++++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+@@ -357,5 +357,6 @@ void ionic_q_rewind(struct ionic_queue *q, struct ionic_desc_info *start);
+ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
+ unsigned int stop_index);
+ int ionic_heartbeat_check(struct ionic *ionic);
++bool ionic_is_fw_running(struct ionic_dev *idev);
+
+ #endif /* _IONIC_DEV_H_ */
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 7f3322ce044c7..6ac507ddf09af 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -85613,11 +125296,251 @@ index 7f3322ce044c7..6ac507ddf09af 100644
if (!lif->dbid_inuse) {
dev_err(dev, "Failed alloc doorbell id bitmap, aborting\n");
return -ENOMEM;
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c
+index 6f07bf509efed..480f85bc17f99 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
++++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
+@@ -328,10 +328,10 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
+
+ static void ionic_dev_cmd_clean(struct ionic *ionic)
+ {
+- union __iomem ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
++ struct ionic_dev *idev = &ionic->idev;
+
+- iowrite32(0, &regs->doorbell);
+- memset_io(&regs->cmd, 0, sizeof(regs->cmd));
++ iowrite32(0, &idev->dev_cmd_regs->doorbell);
++ memset_io(&idev->dev_cmd_regs->cmd, 0, sizeof(idev->dev_cmd_regs->cmd));
+ }
+
+ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
+@@ -488,6 +488,9 @@ int ionic_reset(struct ionic *ionic)
+ struct ionic_dev *idev = &ionic->idev;
+ int err;
+
++ if (!ionic_is_fw_running(idev))
++ return 0;
++
+ mutex_lock(&ionic->dev_cmd_lock);
+ ionic_dev_cmd_reset(idev);
+ err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+@@ -560,15 +563,17 @@ int ionic_port_init(struct ionic *ionic)
+ int ionic_port_reset(struct ionic *ionic)
+ {
+ struct ionic_dev *idev = &ionic->idev;
+- int err;
++ int err = 0;
+
+ if (!idev->port_info)
+ return 0;
+
+- mutex_lock(&ionic->dev_cmd_lock);
+- ionic_dev_cmd_port_reset(idev);
+- err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+- mutex_unlock(&ionic->dev_cmd_lock);
++ if (ionic_is_fw_running(idev)) {
++ mutex_lock(&ionic->dev_cmd_lock);
++ ionic_dev_cmd_port_reset(idev);
++ err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
++ mutex_unlock(&ionic->dev_cmd_lock);
++ }
+
+ dma_free_coherent(ionic->dev, idev->port_info_sz,
+ idev->port_info, idev->port_info_pa);
+@@ -576,9 +581,6 @@ int ionic_port_reset(struct ionic *ionic)
+ idev->port_info = NULL;
+ idev->port_info_pa = 0;
+
+- if (err)
+- dev_err(ionic->dev, "Failed to reset port\n");
+-
+ return err;
+ }
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+index ed2b6fe5a78d3..3eb05376e7c3e 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+@@ -2982,12 +2982,16 @@ static int qed_iov_pre_update_vport(struct qed_hwfn *hwfn,
+ u8 mask = QED_ACCEPT_UCAST_UNMATCHED | QED_ACCEPT_MCAST_UNMATCHED;
+ struct qed_filter_accept_flags *flags = &params->accept_flags;
+ struct qed_public_vf_info *vf_info;
++ u16 tlv_mask;
++
++ tlv_mask = BIT(QED_IOV_VP_UPDATE_ACCEPT_PARAM) |
++ BIT(QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN);
+
+ /* Untrusted VFs can't even be trusted to know that fact.
+ * Simply indicate everything is configured fine, and trace
+ * configuration 'behind their back'.
+ */
+- if (!(*tlvs & BIT(QED_IOV_VP_UPDATE_ACCEPT_PARAM)))
++ if (!(*tlvs & tlv_mask))
+ return 0;
+
+ vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true);
+@@ -3004,6 +3008,13 @@ static int qed_iov_pre_update_vport(struct qed_hwfn *hwfn,
+ flags->tx_accept_filter &= ~mask;
+ }
+
++ if (params->update_accept_any_vlan_flg) {
++ vf_info->accept_any_vlan = params->accept_any_vlan;
++
++ if (vf_info->forced_vlan && !vf_info->is_trusted_configured)
++ params->accept_any_vlan = false;
++ }
++
+ return 0;
+ }
+
+@@ -3778,11 +3789,11 @@ bool qed_iov_mark_vf_flr(struct qed_hwfn *p_hwfn, u32 *p_disabled_vfs)
+ return found;
+ }
+
+-static void qed_iov_get_link(struct qed_hwfn *p_hwfn,
+- u16 vfid,
+- struct qed_mcp_link_params *p_params,
+- struct qed_mcp_link_state *p_link,
+- struct qed_mcp_link_capabilities *p_caps)
++static int qed_iov_get_link(struct qed_hwfn *p_hwfn,
++ u16 vfid,
++ struct qed_mcp_link_params *p_params,
++ struct qed_mcp_link_state *p_link,
++ struct qed_mcp_link_capabilities *p_caps)
+ {
+ struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn,
+ vfid,
+@@ -3790,7 +3801,7 @@ static void qed_iov_get_link(struct qed_hwfn *p_hwfn,
+ struct qed_bulletin_content *p_bulletin;
+
+ if (!p_vf)
+- return;
++ return -EINVAL;
+
+ p_bulletin = p_vf->bulletin.p_virt;
+
+@@ -3800,6 +3811,7 @@ static void qed_iov_get_link(struct qed_hwfn *p_hwfn,
+ __qed_vf_get_link_state(p_hwfn, p_link, p_bulletin);
+ if (p_caps)
+ __qed_vf_get_link_caps(p_hwfn, p_caps, p_bulletin);
++ return 0;
+ }
+
+ static int
+@@ -4658,6 +4670,7 @@ static int qed_get_vf_config(struct qed_dev *cdev,
+ struct qed_public_vf_info *vf_info;
+ struct qed_mcp_link_state link;
+ u32 tx_rate;
++ int ret;
+
+ /* Sanitize request */
+ if (IS_VF(cdev))
+@@ -4671,7 +4684,9 @@ static int qed_get_vf_config(struct qed_dev *cdev,
+
+ vf_info = qed_iov_get_public_vf_info(hwfn, vf_id, true);
+
+- qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL);
++ ret = qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL);
++ if (ret)
++ return ret;
+
+ /* Fill information about VF */
+ ivi->vf = vf_id;
+@@ -4687,6 +4702,7 @@ static int qed_get_vf_config(struct qed_dev *cdev,
+ tx_rate = vf_info->tx_rate;
+ ivi->max_tx_rate = tx_rate ? tx_rate : link.speed;
+ ivi->min_tx_rate = qed_iov_get_vf_min_rate(hwfn, vf_id);
++ ivi->trusted = vf_info->is_trusted_request;
+
+ return 0;
+ }
+@@ -5117,6 +5133,12 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
+
+ params.update_ctl_frame_check = 1;
+ params.mac_chk_en = !vf_info->is_trusted_configured;
++ params.update_accept_any_vlan_flg = 0;
++
++ if (vf_info->accept_any_vlan && vf_info->forced_vlan) {
++ params.update_accept_any_vlan_flg = 1;
++ params.accept_any_vlan = vf_info->accept_any_vlan;
++ }
+
+ if (vf_info->rx_accept_mode & mask) {
+ flags->update_rx_mode_config = 1;
+@@ -5132,13 +5154,20 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
+ if (!vf_info->is_trusted_configured) {
+ flags->rx_accept_filter &= ~mask;
+ flags->tx_accept_filter &= ~mask;
++ params.accept_any_vlan = false;
+ }
+
+ if (flags->update_rx_mode_config ||
+ flags->update_tx_mode_config ||
+- params.update_ctl_frame_check)
++ params.update_ctl_frame_check ||
++ params.update_accept_any_vlan_flg) {
++ DP_VERBOSE(hwfn, QED_MSG_IOV,
++ "vport update config for %s VF[abs 0x%x rel 0x%x]\n",
++ vf_info->is_trusted_configured ? "trusted" : "untrusted",
++ vf->abs_vf_id, vf->relative_vf_id);
+ qed_sp_vport_update(hwfn, &params,
+ QED_SPQ_MODE_EBLOCK, NULL);
++ }
+ }
+ }
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+index eacd6457f195c..7ff23ef8ccc17 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h
++++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+@@ -62,6 +62,7 @@ struct qed_public_vf_info {
+ bool is_trusted_request;
+ u8 rx_accept_mode;
+ u8 tx_accept_mode;
++ bool accept_any_vlan;
+ };
+
+ struct qed_iov_vf_init_params {
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
+index 72a38d53d33f6..e2a5a6a373cbe 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
+@@ -513,6 +513,9 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
+ p_iov->bulletin.size,
+ &p_iov->bulletin.phys,
+ GFP_KERNEL);
++ if (!p_iov->bulletin.p_virt)
++ goto free_pf2vf_reply;
++
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "VF's bulletin Board [%p virt 0x%llx phys 0x%08x bytes]\n",
+ p_iov->bulletin.p_virt,
+@@ -552,6 +555,10 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
+
+ return rc;
+
++free_pf2vf_reply:
++ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
++ sizeof(union pfvf_tlvs),
++ p_iov->pf2vf_reply, p_iov->pf2vf_reply_phys);
+ free_vf2pf_request:
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(union vfpf_tlvs),
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
-index 065e9004598ee..999abcfe3310a 100644
+index 065e9004598ee..17f895250e041 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
-@@ -1643,6 +1643,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+@@ -747,6 +747,9 @@ qede_build_skb(struct qede_rx_queue *rxq,
+ buf = page_address(bd->data) + bd->page_offset;
+ skb = build_skb(buf, rxq->rx_buf_seg_size);
+
++ if (unlikely(!skb))
++ return NULL;
++
+ skb_reserve(skb, pad);
+ skb_put(skb, len);
+
+@@ -1643,6 +1646,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
data_split = true;
}
} else {
@@ -85661,7 +125584,7 @@ index 9837bdb89cd40..ee4c3bd28a934 100644
memset(&edev->stats, 0, sizeof(edev->stats));
memcpy(&edev->dev_info, &dev_info, sizeof(dev_info));
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
-index c00ad57575eab..4eb9ea280474f 100644
+index c00ad57575eab..40d14d80f6f1f 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3478,20 +3478,19 @@ static int ql_adapter_up(struct ql3_adapter *qdev)
@@ -85694,6 +125617,16 @@ index c00ad57575eab..4eb9ea280474f 100644
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
set_bit(QL_ADAPTER_UP, &qdev->flags);
+@@ -3613,7 +3612,8 @@ static void ql_reset_work(struct work_struct *work)
+ qdev->mem_map_registers;
+ unsigned long hw_flags;
+
+- if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START), &qdev->flags)) {
++ if (test_bit(QL_RESET_PER_SCSI, &qdev->flags) ||
++ test_bit(QL_RESET_START, &qdev->flags)) {
+ clear_bit(QL_LINK_MASTER, &qdev->flags);
+
+ /*
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index d51bac7ba5afa..bd06076803295 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -85715,6 +125648,55 @@ index d51bac7ba5afa..bd06076803295 100644
cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
/* set up status rings, mbx 2-81 */
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
+index 5d79ee4370bcd..7519773eaca6e 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
+@@ -51,7 +51,7 @@ static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
+ if (dcb && dcb->ops->get_hw_capability)
+ return dcb->ops->get_hw_capability(dcb);
+
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
+ static inline void qlcnic_dcb_free(struct qlcnic_dcb *dcb)
+@@ -65,7 +65,7 @@ static inline int qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
+ if (dcb && dcb->ops->attach)
+ return dcb->ops->attach(dcb);
+
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
+ static inline int
+@@ -74,7 +74,7 @@ qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
+ if (dcb && dcb->ops->query_hw_capability)
+ return dcb->ops->query_hw_capability(dcb, buf);
+
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
+ static inline void qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
+@@ -89,7 +89,7 @@ qlcnic_dcb_query_cee_param(struct qlcnic_dcb *dcb, char *buf, u8 type)
+ if (dcb && dcb->ops->query_cee_param)
+ return dcb->ops->query_cee_param(dcb, buf, type);
+
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
+ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
+@@ -97,7 +97,7 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
+ if (dcb && dcb->ops->get_cee_cfg)
+ return dcb->ops->get_cee_cfg(dcb);
+
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
+ static inline void qlcnic_dcb_aen_handler(struct qlcnic_dcb *dcb, void *msg)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
index 7160b42f51ddd..d0111cb3b40e1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -85852,6 +125834,22 @@ index 6781aa636d588..1b415fe6f9b9f 100644
}
__setup("sxgbeeth=", sxgbe_cmdline_opt);
+diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
+index e7e2223aebbf5..f5a4d8f4fd114 100644
+--- a/drivers/net/ethernet/sfc/ef10.c
++++ b/drivers/net/ethernet/sfc/ef10.c
+@@ -3579,6 +3579,11 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx)
+ n_parts++;
+ }
+
++ if (!n_parts) {
++ kfree(parts);
++ return 0;
++ }
++
+ rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
+ fail:
+ if (rc)
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 518268ce20644..d35cafd422b1c 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
@@ -85866,6 +125864,244 @@ index 518268ce20644..d35cafd422b1c 100644
efx_nic_copy_stats(efx, mc_stats);
efx_nic_update_stats(ef100_stat_desc, EF100_STAT_COUNT, mask,
stats, mc_stats, false);
+diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c
+index 3dbea028b325c..d5f2ccd3bca44 100644
+--- a/drivers/net/ethernet/sfc/efx_channels.c
++++ b/drivers/net/ethernet/sfc/efx_channels.c
+@@ -763,9 +763,90 @@ void efx_remove_channels(struct efx_nic *efx)
+ kfree(efx->xdp_tx_queues);
+ }
+
++static int efx_set_xdp_tx_queue(struct efx_nic *efx, int xdp_queue_number,
++ struct efx_tx_queue *tx_queue)
++{
++ if (xdp_queue_number >= efx->xdp_tx_queue_count)
++ return -EINVAL;
++
++ netif_dbg(efx, drv, efx->net_dev,
++ "Channel %u TXQ %u is XDP %u, HW %u\n",
++ tx_queue->channel->channel, tx_queue->label,
++ xdp_queue_number, tx_queue->queue);
++ efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
++ return 0;
++}
++
++static void efx_set_xdp_channels(struct efx_nic *efx)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_channel *channel;
++ unsigned int next_queue = 0;
++ int xdp_queue_number = 0;
++ int rc;
++
++ /* We need to mark which channels really have RX and TX
++ * queues, and adjust the TX queue numbers if we have separate
++ * RX-only and TX-only channels.
++ */
++ efx_for_each_channel(channel, efx) {
++ if (channel->channel < efx->tx_channel_offset)
++ continue;
++
++ if (efx_channel_is_xdp_tx(channel)) {
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ tx_queue->queue = next_queue++;
++ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number,
++ tx_queue);
++ if (rc == 0)
++ xdp_queue_number++;
++ }
++ } else {
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ tx_queue->queue = next_queue++;
++ netif_dbg(efx, drv, efx->net_dev,
++ "Channel %u TXQ %u is HW %u\n",
++ channel->channel, tx_queue->label,
++ tx_queue->queue);
++ }
++
++ /* If XDP is borrowing queues from net stack, it must
++ * use the queue with no csum offload, which is the
++ * first one of the channel
++ * (note: tx_queue_by_type is not initialized yet)
++ */
++ if (efx->xdp_txq_queues_mode ==
++ EFX_XDP_TX_QUEUES_BORROWED) {
++ tx_queue = &channel->tx_queue[0];
++ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number,
++ tx_queue);
++ if (rc == 0)
++ xdp_queue_number++;
++ }
++ }
++ }
++ WARN_ON(efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_DEDICATED &&
++ xdp_queue_number != efx->xdp_tx_queue_count);
++ WARN_ON(efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED &&
++ xdp_queue_number > efx->xdp_tx_queue_count);
++
++ /* If we have more CPUs than assigned XDP TX queues, assign the already
++ * existing queues to the exceeding CPUs
++ */
++ next_queue = 0;
++ while (xdp_queue_number < efx->xdp_tx_queue_count) {
++ tx_queue = efx->xdp_tx_queues[next_queue++];
++ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
++ if (rc == 0)
++ xdp_queue_number++;
++ }
++}
++
+ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+ {
+- struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
++ struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel,
++ *ptp_channel = efx_ptp_channel(efx);
++ struct efx_ptp_data *ptp_data = efx->ptp_data;
+ unsigned int i, next_buffer_table = 0;
+ u32 old_rxq_entries, old_txq_entries;
+ int rc, rc2;
+@@ -818,11 +899,8 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+ old_txq_entries = efx->txq_entries;
+ efx->rxq_entries = rxq_entries;
+ efx->txq_entries = txq_entries;
+- for (i = 0; i < efx->n_channels; i++) {
+- channel = efx->channel[i];
+- efx->channel[i] = other_channel[i];
+- other_channel[i] = channel;
+- }
++ for (i = 0; i < efx->n_channels; i++)
++ swap(efx->channel[i], other_channel[i]);
+
+ /* Restart buffer table allocation */
+ efx->next_buffer_table = next_buffer_table;
+@@ -837,7 +915,9 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+ efx_init_napi_channel(efx->channel[i]);
+ }
+
++ efx_set_xdp_channels(efx);
+ out:
++ efx->ptp_data = NULL;
+ /* Destroy unused channel structures */
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = other_channel[i];
+@@ -848,6 +928,7 @@ out:
+ }
+ }
+
++ efx->ptp_data = ptp_data;
+ rc2 = efx_soft_enable_interrupts(efx);
+ if (rc2) {
+ rc = rc ? rc : rc2;
+@@ -864,34 +945,15 @@ rollback:
+ /* Swap back */
+ efx->rxq_entries = old_rxq_entries;
+ efx->txq_entries = old_txq_entries;
+- for (i = 0; i < efx->n_channels; i++) {
+- channel = efx->channel[i];
+- efx->channel[i] = other_channel[i];
+- other_channel[i] = channel;
+- }
++ for (i = 0; i < efx->n_channels; i++)
++ swap(efx->channel[i], other_channel[i]);
++ efx_ptp_update_channel(efx, ptp_channel);
+ goto out;
+ }
+
+-static inline int
+-efx_set_xdp_tx_queue(struct efx_nic *efx, int xdp_queue_number,
+- struct efx_tx_queue *tx_queue)
+-{
+- if (xdp_queue_number >= efx->xdp_tx_queue_count)
+- return -EINVAL;
+-
+- netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
+- tx_queue->channel->channel, tx_queue->label,
+- xdp_queue_number, tx_queue->queue);
+- efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
+- return 0;
+-}
+-
+ int efx_set_channels(struct efx_nic *efx)
+ {
+- struct efx_tx_queue *tx_queue;
+ struct efx_channel *channel;
+- unsigned int next_queue = 0;
+- int xdp_queue_number;
+ int rc;
+
+ efx->tx_channel_offset =
+@@ -909,61 +971,14 @@ int efx_set_channels(struct efx_nic *efx)
+ return -ENOMEM;
+ }
+
+- /* We need to mark which channels really have RX and TX
+- * queues, and adjust the TX queue numbers if we have separate
+- * RX-only and TX-only channels.
+- */
+- xdp_queue_number = 0;
+ efx_for_each_channel(channel, efx) {
+ if (channel->channel < efx->n_rx_channels)
+ channel->rx_queue.core_index = channel->channel;
+ else
+ channel->rx_queue.core_index = -1;
+-
+- if (channel->channel >= efx->tx_channel_offset) {
+- if (efx_channel_is_xdp_tx(channel)) {
+- efx_for_each_channel_tx_queue(tx_queue, channel) {
+- tx_queue->queue = next_queue++;
+- rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+- if (rc == 0)
+- xdp_queue_number++;
+- }
+- } else {
+- efx_for_each_channel_tx_queue(tx_queue, channel) {
+- tx_queue->queue = next_queue++;
+- netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is HW %u\n",
+- channel->channel, tx_queue->label,
+- tx_queue->queue);
+- }
+-
+- /* If XDP is borrowing queues from net stack, it must use the queue
+- * with no csum offload, which is the first one of the channel
+- * (note: channel->tx_queue_by_type is not initialized yet)
+- */
+- if (efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_BORROWED) {
+- tx_queue = &channel->tx_queue[0];
+- rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+- if (rc == 0)
+- xdp_queue_number++;
+- }
+- }
+- }
+ }
+- WARN_ON(efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_DEDICATED &&
+- xdp_queue_number != efx->xdp_tx_queue_count);
+- WARN_ON(efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED &&
+- xdp_queue_number > efx->xdp_tx_queue_count);
+
+- /* If we have more CPUs than assigned XDP TX queues, assign the already
+- * existing queues to the exceeding CPUs
+- */
+- next_queue = 0;
+- while (xdp_queue_number < efx->xdp_tx_queue_count) {
+- tx_queue = efx->xdp_tx_queues[next_queue++];
+- rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+- if (rc == 0)
+- xdp_queue_number++;
+- }
++ efx_set_xdp_channels(efx);
+
+ rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
+ if (rc)
+@@ -1107,7 +1122,7 @@ void efx_start_channels(struct efx_nic *efx)
+ struct efx_rx_queue *rx_queue;
+ struct efx_channel *channel;
+
+- efx_for_each_channel(channel, efx) {
++ efx_for_each_channel_rev(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ efx_init_tx_queue(tx_queue);
+ atomic_inc(&efx->active_queues);
diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c
index bf1443539a1a4..bd552c7dffcb1 100644
--- a/drivers/net/ethernet/sfc/ethtool_common.c
@@ -85928,8 +126164,81 @@ index 966f13e7475dd..0c6cc21913693 100644
}
void ef4_init_rx_queue(struct ef4_rx_queue *rx_queue)
+diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
+index be6bfd6b7ec75..50baf62b2cbc6 100644
+--- a/drivers/net/ethernet/sfc/mcdi.c
++++ b/drivers/net/ethernet/sfc/mcdi.c
+@@ -163,9 +163,9 @@ static void efx_mcdi_send_request(struct efx_nic *efx, unsigned cmd,
+ /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
+ spin_lock_bh(&mcdi->iface_lock);
+ ++mcdi->seqno;
++ seqno = mcdi->seqno & SEQ_MASK;
+ spin_unlock_bh(&mcdi->iface_lock);
+
+- seqno = mcdi->seqno & SEQ_MASK;
+ xflags = 0;
+ if (mcdi->mode == MCDI_MODE_EVENTS)
+ xflags |= MCDI_HEADER_XFLAGS_EVREQ;
+diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
+index 797e51802ccbb..725b0f38813a9 100644
+--- a/drivers/net/ethernet/sfc/ptp.c
++++ b/drivers/net/ethernet/sfc/ptp.c
+@@ -45,6 +45,7 @@
+ #include "farch_regs.h"
+ #include "tx.h"
+ #include "nic.h" /* indirectly includes ptp.h */
++#include "efx_channels.h"
+
+ /* Maximum number of events expected to make up a PTP event */
+ #define MAX_EVENT_FRAGS 3
+@@ -541,6 +542,12 @@ struct efx_channel *efx_ptp_channel(struct efx_nic *efx)
+ return efx->ptp_data ? efx->ptp_data->channel : NULL;
+ }
+
++void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel)
++{
++ if (efx->ptp_data)
++ efx->ptp_data->channel = channel;
++}
++
+ static u32 last_sync_timestamp_major(struct efx_nic *efx)
+ {
+ struct efx_channel *channel = efx_ptp_channel(efx);
+@@ -1443,6 +1450,11 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
+ int rc = 0;
+ unsigned int pos;
+
++ if (efx->ptp_data) {
++ efx->ptp_data->channel = channel;
++ return 0;
++ }
++
+ ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL);
+ efx->ptp_data = ptp;
+ if (!efx->ptp_data)
+@@ -2179,7 +2191,7 @@ static const struct efx_channel_type efx_ptp_channel_type = {
+ .pre_probe = efx_ptp_probe_channel,
+ .post_remove = efx_ptp_remove_channel,
+ .get_name = efx_ptp_get_channel_name,
+- /* no copy operation; there is no need to reallocate this channel */
++ .copy = efx_copy_channel,
+ .receive_skb = efx_ptp_rx,
+ .want_txqs = efx_ptp_want_txqs,
+ .keep_eventq = false,
+diff --git a/drivers/net/ethernet/sfc/ptp.h b/drivers/net/ethernet/sfc/ptp.h
+index 9855e8c9e544d..7b1ef7002b3f0 100644
+--- a/drivers/net/ethernet/sfc/ptp.h
++++ b/drivers/net/ethernet/sfc/ptp.h
+@@ -16,6 +16,7 @@ struct ethtool_ts_info;
+ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel);
+ void efx_ptp_defer_probe_with_channel(struct efx_nic *efx);
+ struct efx_channel *efx_ptp_channel(struct efx_nic *efx);
++void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel);
+ void efx_ptp_remove(struct efx_nic *efx);
+ int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr);
+ int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr);
diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c
-index 68fc7d317693b..633ca77a26fd1 100644
+index 68fc7d317693b..b925de9b43028 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -45,6 +45,8 @@ static struct page *efx_reuse_page(struct efx_rx_queue *rx_queue)
@@ -85963,6 +126272,43 @@ index 68fc7d317693b..633ca77a26fd1 100644
}
static void efx_fini_rx_recycle_ring(struct efx_rx_queue *rx_queue)
+@@ -158,6 +166,9 @@ static void efx_fini_rx_recycle_ring(struct efx_rx_queue *rx_queue)
+ struct efx_nic *efx = rx_queue->efx;
+ int i;
+
++ if (unlikely(!rx_queue->page_ring))
++ return;
++
+ /* Unmap and release the pages in the recycle ring. Remove the ring. */
+ for (i = 0; i <= rx_queue->page_ptr_mask; i++) {
+ struct page *page = rx_queue->page_ring[i];
+diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
+index d16e031e95f44..6983799e1c05d 100644
+--- a/drivers/net/ethernet/sfc/tx.c
++++ b/drivers/net/ethernet/sfc/tx.c
+@@ -443,6 +443,9 @@ int efx_xdp_tx_buffers(struct efx_nic *efx, int n, struct xdp_frame **xdpfs,
+ if (unlikely(!tx_queue))
+ return -EINVAL;
+
++ if (!tx_queue->initialised)
++ return -EINVAL;
++
+ if (efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED)
+ HARD_TX_LOCK(efx->net_dev, tx_queue->core_txq, cpu);
+
+diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
+index d530cde2b8648..9bc8281b7f5bd 100644
+--- a/drivers/net/ethernet/sfc/tx_common.c
++++ b/drivers/net/ethernet/sfc/tx_common.c
+@@ -101,6 +101,8 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "shutting down TX queue %d\n", tx_queue->queue);
+
++ tx_queue->initialised = false;
++
+ if (!tx_queue->buffer)
+ return;
+
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index b008b4e8a2a5a..0641a1d392b86 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
@@ -85979,6 +126325,74 @@ index b008b4e8a2a5a..0641a1d392b86 100644
lp = netdev_priv(ndev);
lp->netdev = ndev;
#ifdef SMC_DYNAMIC_BUS_CONFIG
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index 199a973392806..592e191adbf7d 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -2429,7 +2429,7 @@ static int smsc911x_drv_probe(struct platform_device *pdev)
+ if (irq == -EPROBE_DEFER) {
+ retval = -EPROBE_DEFER;
+ goto out_0;
+- } else if (irq <= 0) {
++ } else if (irq < 0) {
+ pr_warn("Could not allocate irq resource\n");
+ retval = -ENODEV;
+ goto out_0;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+index cd478d2cd871a..00f6d347eaf75 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
++++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+@@ -57,10 +57,6 @@
+ #define TSE_PCS_USE_SGMII_ENA BIT(0)
+ #define TSE_PCS_IF_USE_SGMII 0x03
+
+-#define SGMII_ADAPTER_CTRL_REG 0x00
+-#define SGMII_ADAPTER_DISABLE 0x0001
+-#define SGMII_ADAPTER_ENABLE 0x0000
+-
+ #define AUTONEGO_LINK_TIMER 20
+
+ static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs)
+@@ -202,12 +198,8 @@ void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
+ unsigned int speed)
+ {
+ void __iomem *tse_pcs_base = pcs->tse_pcs_base;
+- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
+ u32 val;
+
+- writew(SGMII_ADAPTER_ENABLE,
+- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+-
+ pcs->autoneg = phy_dev->autoneg;
+
+ if (phy_dev->autoneg == AUTONEG_ENABLE) {
+diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+index 442812c0a4bdc..694ac25ef426b 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
++++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+@@ -10,6 +10,10 @@
+ #include <linux/phy.h>
+ #include <linux/timer.h>
+
++#define SGMII_ADAPTER_CTRL_REG 0x00
++#define SGMII_ADAPTER_ENABLE 0x0000
++#define SGMII_ADAPTER_DISABLE 0x0001
++
+ struct tse_pcs {
+ struct device *dev;
+ void __iomem *tse_pcs_base;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+index 8e8778cfbbadd..6f87e296a410f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+@@ -454,6 +454,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
+ plat->has_gmac4 = 1;
+ plat->force_sf_dma_mode = 0;
+ plat->tso_en = 1;
++ plat->sph_disable = 1;
+
+ /* Multiplying factor to the clk_eee_i clock time
+ * period to make it closer to 100 ns. This value
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 5c74b6279d690..6b1d9e8879f46 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -86042,10 +126456,49 @@ index 6924a6aacbd53..c469abc91fa1b 100644
while (ops->regs[i]) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
-index 85208128f135c..b7c2579c963b6 100644
+index 85208128f135c..6b447d8f0bd8a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
-@@ -485,8 +485,28 @@ static int socfpga_dwmac_resume(struct device *dev)
+@@ -18,9 +18,6 @@
+
+ #include "altr_tse_pcs.h"
+
+-#define SGMII_ADAPTER_CTRL_REG 0x00
+-#define SGMII_ADAPTER_DISABLE 0x0001
+-
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+@@ -62,14 +59,13 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
+ {
+ struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
+ void __iomem *splitter_base = dwmac->splitter_base;
+- void __iomem *tse_pcs_base = dwmac->pcs.tse_pcs_base;
+ void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
+ struct device *dev = dwmac->dev;
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct phy_device *phy_dev = ndev->phydev;
+ u32 val;
+
+- if ((tse_pcs_base) && (sgmii_adapter_base))
++ if (sgmii_adapter_base)
+ writew(SGMII_ADAPTER_DISABLE,
+ sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+
+@@ -93,8 +89,11 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
+ writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
+ }
+
+- if (tse_pcs_base && sgmii_adapter_base)
++ if (phy_dev && sgmii_adapter_base) {
++ writew(SGMII_ADAPTER_ENABLE,
++ sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+ tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
++ }
+ }
+
+ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
+@@ -485,8 +484,28 @@ static int socfpga_dwmac_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
@@ -86077,7 +126530,7 @@ index 85208128f135c..b7c2579c963b6 100644
static const struct socfpga_dwmac_ops socfpga_gen5_ops = {
.set_phy_mode = socfpga_gen5_set_phy_mode,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
-index 4422baeed3d89..13fbb68158c66 100644
+index 4422baeed3d89..06e2af9387d7c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -756,7 +756,7 @@ static int sun8i_dwmac_reset(struct stmmac_priv *priv)
@@ -86089,6 +126542,14 @@ index 4422baeed3d89..13fbb68158c66 100644
}
return 0;
}
+@@ -916,6 +916,7 @@ static int sun8i_dwmac_register_mdio_mux(struct stmmac_priv *priv)
+
+ ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn,
+ &gmac->mux_handle, priv, priv->mii);
++ of_node_put(mdio_mux);
+ return ret;
+ }
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
index d046e33b8a297..c27441c08dd6f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
@@ -86320,9 +126781,21 @@ index d89455803beda..8f563b446d5ca 100644
&reg_space[DMA_BUS_MODE / 4],
NUM_DWMAC1000_DMA_REGS * 4);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
-index 074e2cdfb0fa6..a7ec9f4d46ced 100644
+index 074e2cdfb0fa6..d68ef72dcdde0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+@@ -71,9 +71,9 @@ static int init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
+ writel(value, ioaddr + PTP_TCR);
+
+ /* wait for present system time initialize to complete */
+- return readl_poll_timeout(ioaddr + PTP_TCR, value,
++ return readl_poll_timeout_atomic(ioaddr + PTP_TCR, value,
+ !(value & PTP_TCR_TSINIT),
+- 10000, 100000);
++ 10, 100000);
+ }
+
+ static int config_addend(void __iomem *ioaddr, u32 addend)
@@ -145,15 +145,20 @@ static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
static void get_systime(void __iomem *ioaddr, u64 *systime)
@@ -86352,7 +126825,7 @@ index 074e2cdfb0fa6..a7ec9f4d46ced 100644
static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-index 3d67d1fa36906..9376c4e286268 100644
+index 3d67d1fa36906..9c1e19ea6fcd0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -50,6 +50,13 @@
@@ -86920,6 +127393,15 @@ index 3d67d1fa36906..9376c4e286268 100644
int stmmac_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags)
{
struct stmmac_priv *priv = netdev_priv(dev);
+@@ -6889,7 +7081,7 @@ int stmmac_dvr_probe(struct device *device,
+ dev_info(priv->device, "TSO feature enabled\n");
+ }
+
+- if (priv->dma_cap.sphen) {
++ if (priv->dma_cap.sphen && !priv->plat->sph_disable) {
+ ndev->hw_features |= NETIF_F_GRO;
+ priv->sph_cap = true;
+ priv->sph = priv->sph_cap;
@@ -7044,6 +7236,9 @@ int stmmac_dvr_probe(struct device *device,
stmmac_init_fs(ndev);
#endif
@@ -86981,11 +127463,43 @@ index 3d67d1fa36906..9376c4e286268 100644
}
__setup("stmmaceth=", stmmac_cmdline_opt);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index fcf17d8a0494b..644bb54f5f020 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -181,7 +181,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ return -ENOMEM;
+
+ /* Enable pci device */
+- ret = pci_enable_device(pdev);
++ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
+ __func__);
+@@ -241,8 +241,6 @@ static void stmmac_pci_remove(struct pci_dev *pdev)
+ pcim_iounmap_regions(pdev, BIT(i));
+ break;
+ }
+-
+- pci_disable_device(pdev);
+ }
+
+ static int __maybe_unused stmmac_pci_suspend(struct device *dev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-index 232ac98943cd0..5d29f336315b7 100644
+index 232ac98943cd0..11e1055e8260f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -816,7 +816,7 @@ static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev)
+@@ -431,8 +431,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
+ plat->phylink_node = np;
+
+ /* Get max speed of operation from device tree */
+- if (of_property_read_u32(np, "max-speed", &plat->max_speed))
+- plat->max_speed = -1;
++ of_property_read_u32(np, "max-speed", &plat->max_speed);
+
+ plat->bus_id = of_alias_get_id(np, "ethernet");
+ if (plat->bus_id < 0)
+@@ -816,7 +815,7 @@ static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev)
if (ret)
return ret;
@@ -87193,6 +127707,30 @@ index 2a616c6f7cd0e..9d4d8c3dad0a3 100644
return 0;
}
+diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
+index 62f81b0d14ed8..b05ee2e0e3051 100644
+--- a/drivers/net/ethernet/sun/sunhme.c
++++ b/drivers/net/ethernet/sun/sunhme.c
+@@ -3139,7 +3139,7 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
+ if (err) {
+ printk(KERN_ERR "happymeal(PCI): Cannot register net device, "
+ "aborting.\n");
+- goto err_out_iounmap;
++ goto err_out_free_coherent;
+ }
+
+ pci_set_drvdata(pdev, hp);
+@@ -3172,6 +3172,10 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
+
+ return 0;
+
++err_out_free_coherent:
++ dma_free_coherent(hp->dma_dev, PAGE_SIZE,
++ hp->happy_block, hp->hblock_dvma);
++
+ err_out_iounmap:
+ iounmap(hp->gregs);
+
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 66f7ddd9b1f99..e226ecd95a2cc 100644
--- a/drivers/net/ethernet/ti/cpsw.c
@@ -87241,8 +127779,26 @@ index 0c75e0576ee1f..1ef0aaef5c61c 100644
if (!ale->p0_untag_vid_mask)
return ERR_PTR(-ENOMEM);
+diff --git a/drivers/net/ethernet/ti/cpsw_ethtool.c b/drivers/net/ethernet/ti/cpsw_ethtool.c
+index 158c8d3793f43..b5bae6324970a 100644
+--- a/drivers/net/ethernet/ti/cpsw_ethtool.c
++++ b/drivers/net/ethernet/ti/cpsw_ethtool.c
+@@ -364,11 +364,9 @@ int cpsw_ethtool_op_begin(struct net_device *ndev)
+ struct cpsw_common *cpsw = priv->cpsw;
+ int ret;
+
+- ret = pm_runtime_get_sync(cpsw->dev);
+- if (ret < 0) {
++ ret = pm_runtime_resume_and_get(cpsw->dev);
++ if (ret < 0)
+ cpsw_err(priv, drv, "ethtool begin failed %d\n", ret);
+- pm_runtime_put_noidle(cpsw->dev);
+- }
+
+ return ret;
+ }
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
-index 7968f24d99c85..9e16afbdbdc1d 100644
+index 7968f24d99c85..277c91d135708 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -283,7 +283,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
@@ -87272,6 +127828,26 @@ index 7968f24d99c85..9e16afbdbdc1d 100644
ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma,
pkt_size, 0);
if (ret < 0) {
+@@ -1246,8 +1246,10 @@ static int cpsw_probe_dt(struct cpsw_common *cpsw)
+ data->slave_data = devm_kcalloc(dev, CPSW_SLAVE_PORTS_NUM,
+ sizeof(struct cpsw_slave_data),
+ GFP_KERNEL);
+- if (!data->slave_data)
++ if (!data->slave_data) {
++ of_node_put(tmp_node);
+ return -ENOMEM;
++ }
+
+ /* Populate all the child nodes here...
+ */
+@@ -1341,6 +1343,7 @@ static int cpsw_probe_dt(struct cpsw_common *cpsw)
+
+ err_node_put:
+ of_node_put(port_np);
++ of_node_put(tmp_node);
+ return ret;
+ }
+
diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c
index ecc2a6b7e28f2..f8e591d69d2cb 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.c
@@ -87294,6 +127870,21 @@ index ecc2a6b7e28f2..f8e591d69d2cb 100644
struct page_pool *pool;
pp_params.order = 0;
+diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
+index 43222a34cba06..f9514518700eb 100644
+--- a/drivers/net/ethernet/ti/cpts.c
++++ b/drivers/net/ethernet/ti/cpts.c
+@@ -568,7 +568,9 @@ int cpts_register(struct cpts *cpts)
+ for (i = 0; i < CPTS_MAX_EVENTS; i++)
+ list_add(&cpts->pool_data[i].list, &cpts->pool);
+
+- clk_enable(cpts->refclk);
++ err = clk_enable(cpts->refclk);
++ if (err)
++ return err;
+
+ cpts_write32(cpts, CPTS_EN, control);
+ cpts_write32(cpts, TS_PEND_EN, int_enable);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index e8291d8488391..d243ca5dfde00 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
@@ -87335,7 +127926,7 @@ index 463094ced104a..2ab29efa6b6e4 100644
}
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
-index 871b5ec3183d6..2169417210c2b 100644
+index 871b5ec3183d6..fbbbcfe0e891e 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -41,8 +41,9 @@
@@ -87533,16 +128124,111 @@ index 871b5ec3183d6..2169417210c2b 100644
return NETDEV_TX_OK;
}
-@@ -834,6 +859,8 @@ static void axienet_recv(struct net_device *ndev)
-
- tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
+@@ -832,44 +857,53 @@ static void axienet_recv(struct net_device *ndev)
+ while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
+ dma_addr_t phys;
+- tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
+-
+- phys = desc_get_phys_addr(lp, cur_p);
+- dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size,
+- DMA_FROM_DEVICE);
+ /* Ensure we see complete descriptor update */
+ dma_rmb();
- phys = desc_get_phys_addr(lp, cur_p);
- dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size,
- DMA_FROM_DEVICE);
-@@ -1346,7 +1373,8 @@ static int axienet_ethtools_set_ringparam(struct net_device *ndev,
+
+ skb = cur_p->skb;
+ cur_p->skb = NULL;
+- length = cur_p->app4 & 0x0000FFFF;
+-
+- skb_put(skb, length);
+- skb->protocol = eth_type_trans(skb, ndev);
+- /*skb_checksum_none_assert(skb);*/
+- skb->ip_summed = CHECKSUM_NONE;
+-
+- /* if we're doing Rx csum offload, set it up */
+- if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
+- csumstatus = (cur_p->app2 &
+- XAE_FULL_CSUM_STATUS_MASK) >> 3;
+- if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) ||
+- (csumstatus == XAE_IP_UDP_CSUM_VALIDATED)) {
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ /* skb could be NULL if a previous pass already received the
++ * packet for this slot in the ring, but failed to refill it
++ * with a newly allocated buffer. In this case, don't try to
++ * receive it again.
++ */
++ if (likely(skb)) {
++ length = cur_p->app4 & 0x0000FFFF;
++
++ phys = desc_get_phys_addr(lp, cur_p);
++ dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size,
++ DMA_FROM_DEVICE);
++
++ skb_put(skb, length);
++ skb->protocol = eth_type_trans(skb, ndev);
++ /*skb_checksum_none_assert(skb);*/
++ skb->ip_summed = CHECKSUM_NONE;
++
++ /* if we're doing Rx csum offload, set it up */
++ if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
++ csumstatus = (cur_p->app2 &
++ XAE_FULL_CSUM_STATUS_MASK) >> 3;
++ if (csumstatus == XAE_IP_TCP_CSUM_VALIDATED ||
++ csumstatus == XAE_IP_UDP_CSUM_VALIDATED) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++ } else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
++ skb->protocol == htons(ETH_P_IP) &&
++ skb->len > 64) {
++ skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
++ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+- } else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
+- skb->protocol == htons(ETH_P_IP) &&
+- skb->len > 64) {
+- skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
+- skb->ip_summed = CHECKSUM_COMPLETE;
+- }
+
+- netif_rx(skb);
++ netif_rx(skb);
+
+- size += length;
+- packets++;
++ size += length;
++ packets++;
++ }
+
+ new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
+ if (!new_skb)
+- return;
++ break;
+
+ phys = dma_map_single(ndev->dev.parent, new_skb->data,
+ lp->max_frm_size,
+@@ -878,7 +912,7 @@ static void axienet_recv(struct net_device *ndev)
+ if (net_ratelimit())
+ netdev_err(ndev, "RX DMA mapping error\n");
+ dev_kfree_skb(new_skb);
+- return;
++ break;
+ }
+ desc_set_phys_addr(lp, phys, cur_p);
+
+@@ -886,6 +920,11 @@ static void axienet_recv(struct net_device *ndev)
+ cur_p->status = 0;
+ cur_p->skb = new_skb;
+
++ /* Only update tail_p to mark this slot as usable after it has
++ * been successfully refilled.
++ */
++ tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
++
+ if (++lp->rx_bd_ci >= lp->rx_bd_num)
+ lp->rx_bd_ci = 0;
+ cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+@@ -1346,7 +1385,8 @@ static int axienet_ethtools_set_ringparam(struct net_device *ndev,
if (ering->rx_pending > RX_BD_NUM_MAX ||
ering->rx_mini_pending ||
ering->rx_jumbo_pending ||
@@ -87552,18 +128238,137 @@ index 871b5ec3183d6..2169417210c2b 100644
return -EINVAL;
if (netif_running(ndev))
-@@ -2082,6 +2110,11 @@ static int axienet_probe(struct platform_device *pdev)
+@@ -2082,15 +2122,19 @@ static int axienet_probe(struct platform_device *pdev)
lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
+- lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+- if (lp->phy_node) {
+- ret = axienet_mdio_setup(lp);
+- if (ret)
+- dev_warn(&pdev->dev,
+- "error registering MDIO bus: %d\n", ret);
+- }
+ /* Reset core now that clocks are enabled, prior to accessing MDIO */
+ ret = __axienet_device_reset(lp);
+ if (ret)
+ goto cleanup_clk;
+
- lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
++ ret = axienet_mdio_setup(lp);
++ if (ret)
++ dev_warn(&pdev->dev,
++ "error registering MDIO bus: %d\n", ret);
++
+ if (lp->phy_mode == PHY_INTERFACE_MODE_SGMII ||
+ lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) {
++ lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+ if (!lp->phy_node) {
+ dev_err(&pdev->dev, "phy-handle required for 1000BaseX/SGMII\n");
+ ret = -EINVAL;
+diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+index b780aad3550aa..97c1d1ecba34c 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+@@ -822,10 +822,10 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
+ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+ {
+ struct mii_bus *bus;
+- int rc;
+ struct resource res;
+ struct device_node *np = of_get_parent(lp->phy_node);
+ struct device_node *npp;
++ int rc, ret;
+
+ /* Don't register the MDIO bus if the phy_node or its parent node
+ * can't be found.
+@@ -835,8 +835,14 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+ return -ENODEV;
+ }
+ npp = of_get_parent(np);
+-
+- of_address_to_resource(npp, 0, &res);
++ ret = of_address_to_resource(npp, 0, &res);
++ of_node_put(npp);
++ if (ret) {
++ dev_err(dev, "%s resource error!\n",
++ dev->of_node->full_name);
++ of_node_put(np);
++ return ret;
++ }
+ if (lp->ndev->mem_start != res.start) {
+ struct phy_device *phydev;
+ phydev = of_phy_find_device(lp->phy_node);
+@@ -845,6 +851,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+ "MDIO of the phy is not registered yet\n");
+ else
+ put_device(&phydev->mdio.dev);
++ of_node_put(np);
+ return 0;
+ }
+
+@@ -857,6 +864,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+ bus = mdiobus_alloc();
+ if (!bus) {
+ dev_err(dev, "Failed to allocate mdiobus\n");
++ of_node_put(np);
+ return -ENOMEM;
+ }
+
+@@ -869,6 +877,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+ bus->parent = dev;
+
+ rc = of_mdiobus_register(bus, np);
++ of_node_put(np);
+ if (rc) {
+ dev_err(dev, "Failed to register mdio bus.\n");
+ goto err_register;
+@@ -925,8 +934,6 @@ static int xemaclite_open(struct net_device *dev)
+ xemaclite_disable_interrupts(lp);
+
if (lp->phy_node) {
- ret = axienet_mdio_setup(lp);
+- u32 bmcr;
+-
+ lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
+ xemaclite_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+@@ -937,19 +944,6 @@ static int xemaclite_open(struct net_device *dev)
+
+ /* EmacLite doesn't support giga-bit speeds */
+ phy_set_max_speed(lp->phy_dev, SPEED_100);
+-
+- /* Don't advertise 1000BASE-T Full/Half duplex speeds */
+- phy_write(lp->phy_dev, MII_CTRL1000, 0);
+-
+- /* Advertise only 10 and 100mbps full/half duplex speeds */
+- phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL |
+- ADVERTISE_CSMA);
+-
+- /* Restart auto negotiation */
+- bmcr = phy_read(lp->phy_dev, MII_BMCR);
+- bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+- phy_write(lp->phy_dev, MII_BMCR, bmcr);
+-
+ phy_start(lp->phy_dev);
+ }
+
+@@ -1185,7 +1179,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
+ if (rc) {
+ dev_err(dev,
+ "Cannot register network device, aborting\n");
+- goto error;
++ goto put_node;
+ }
+
+ dev_info(dev,
+@@ -1193,6 +1187,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
+ (unsigned long __force)ndev->mem_start, lp->base_addr, ndev->irq);
+ return 0;
+
++put_node:
++ of_node_put(lp->phy_node);
+ error:
+ free_netdev(ndev);
+ return rc;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 185c8a3986816..1d1808afd5295 100644
--- a/drivers/net/fjes/fjes_main.c
@@ -87580,6 +128385,37 @@ index 185c8a3986816..1d1808afd5295 100644
err = fjes_hw_init(&adapter->hw);
if (err)
goto err_free_control_wq;
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index 6192244b304ab..36a9fbb704029 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -306,7 +306,6 @@ static void sp_setup(struct net_device *dev)
+ {
+ /* Finish setting up the DEVICE info. */
+ dev->netdev_ops = &sp_netdev_ops;
+- dev->needs_free_netdev = true;
+ dev->mtu = SIXP_MTU;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
+ dev->header_ops = &ax25_header_ops;
+@@ -669,14 +668,16 @@ static void sixpack_close(struct tty_struct *tty)
+ */
+ netif_stop_queue(sp->dev);
+
++ unregister_netdev(sp->dev);
++
+ del_timer_sync(&sp->tx_t);
+ del_timer_sync(&sp->resync_t);
+
+- /* Free all 6pack frame buffers. */
++ /* Free all 6pack frame buffers after unreg. */
+ kfree(sp->rbuff);
+ kfree(sp->xbuff);
+
+- unregister_netdev(sp->dev);
++ free_netdev(sp->dev);
+ }
+
+ /* Perform I/O control on an active 6pack channel. */
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 8666110bec555..763d435a9564c 100644
--- a/drivers/net/hamradio/mkiss.c
@@ -87625,6 +128461,34 @@ index 6ddacbdb224ba..528d57a435394 100644
kfree(ym);
return -EINVAL;
}
+diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
+index 7661dbb31162b..50e4bea46d673 100644
+--- a/drivers/net/hippi/rrunner.c
++++ b/drivers/net/hippi/rrunner.c
+@@ -1353,7 +1353,9 @@ static int rr_close(struct net_device *dev)
+
+ rrpriv->fw_running = 0;
+
++ spin_unlock_irqrestore(&rrpriv->lock, flags);
+ del_timer_sync(&rrpriv->timer);
++ spin_lock_irqsave(&rrpriv->lock, flags);
+
+ writel(0, &regs->TxPi);
+ writel(0, &regs->IpRxPi);
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index 382bebc2420df..bdfcf75f08277 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -1586,6 +1586,9 @@ static void netvsc_get_ethtool_stats(struct net_device *dev,
+ pcpu_sum = kvmalloc_array(num_possible_cpus(),
+ sizeof(struct netvsc_ethtool_pcpu_stats),
+ GFP_KERNEL);
++ if (!pcpu_sum)
++ return;
++
+ netvsc_get_pcpu_stats(dev, pcpu_sum);
+ for_each_present_cpu(cpu) {
+ struct netvsc_ethtool_pcpu_stats *this_sum = &pcpu_sum[cpu];
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 7d67f41387f55..4f5ef8a9a9a87 100644
--- a/drivers/net/ieee802154/at86rf230.c
@@ -87756,17 +128620,52 @@ index e9258a9f3702c..31bc02421dd4e 100644
u64_stats_update_begin(&txp->tsync);
txp->tx_packets++;
diff --git a/drivers/net/ipa/Kconfig b/drivers/net/ipa/Kconfig
-index d037682fb7adb..3e0da1e764718 100644
+index d037682fb7adb..6782c2cbf542f 100644
--- a/drivers/net/ipa/Kconfig
+++ b/drivers/net/ipa/Kconfig
-@@ -2,6 +2,7 @@ config QCOM_IPA
+@@ -2,7 +2,9 @@ config QCOM_IPA
tristate "Qualcomm IPA support"
depends on NET && QCOM_SMEM
depends on ARCH_QCOM || COMPILE_TEST
+ depends on INTERCONNECT
depends on QCOM_RPROC_COMMON || (QCOM_RPROC_COMMON=n && COMPILE_TEST)
++ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
select QCOM_MDT_LOADER if ARCH_QCOM
select QCOM_SCM
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
+index a2fcdb1abdb96..a734e5576729e 100644
+--- a/drivers/net/ipa/gsi.c
++++ b/drivers/net/ipa/gsi.c
+@@ -1370,9 +1370,10 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
+ struct gsi_event *event_done;
+ struct gsi_event *event;
+ struct gsi_trans *trans;
++ u32 trans_count = 0;
+ u32 byte_count = 0;
+- u32 old_index;
+ u32 event_avail;
++ u32 old_index;
+
+ trans_info = &channel->trans_info;
+
+@@ -1393,6 +1394,7 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
+ do {
+ trans->len = __le16_to_cpu(event->len);
+ byte_count += trans->len;
++ trans_count++;
+
+ /* Move on to the next event and transaction */
+ if (--event_avail)
+@@ -1404,7 +1406,7 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
+
+ /* We record RX bytes when they are received */
+ channel->byte_count += byte_count;
+- channel->trans_count++;
++ channel->trans_count += trans_count;
+ }
+
+ /* Initialize a ring, including allocating DMA memory for its entries */
diff --git a/drivers/net/ipa/ipa_cmd.c b/drivers/net/ipa/ipa_cmd.c
index cff51731195aa..d57472ea077f2 100644
--- a/drivers/net/ipa/ipa_cmd.c
@@ -88012,6 +128911,128 @@ index ad116bcc0580e..d0ab4d70c303b 100644
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "error %d getting power to handle crash\n", ret);
+diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
+index b1c6c0fcb654f..f2989aac47a62 100644
+--- a/drivers/net/ipa/ipa_power.c
++++ b/drivers/net/ipa/ipa_power.c
+@@ -11,6 +11,8 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/bitops.h>
+
++#include "linux/soc/qcom/qcom_aoss.h"
++
+ #include "ipa.h"
+ #include "ipa_power.h"
+ #include "ipa_endpoint.h"
+@@ -64,6 +66,7 @@ enum ipa_power_flag {
+ * struct ipa_power - IPA power management information
+ * @dev: IPA device pointer
+ * @core: IPA core clock
++ * @qmp: QMP handle for AOSS communication
+ * @spinlock: Protects modem TX queue enable/disable
+ * @flags: Boolean state flags
+ * @interconnect_count: Number of elements in interconnect[]
+@@ -72,6 +75,7 @@ enum ipa_power_flag {
+ struct ipa_power {
+ struct device *dev;
+ struct clk *core;
++ struct qmp *qmp;
+ spinlock_t spinlock; /* used with STOPPED/STARTED power flags */
+ DECLARE_BITMAP(flags, IPA_POWER_FLAG_COUNT);
+ u32 interconnect_count;
+@@ -382,6 +386,47 @@ void ipa_power_modem_queue_active(struct ipa *ipa)
+ clear_bit(IPA_POWER_FLAG_STARTED, ipa->power->flags);
+ }
+
++static int ipa_power_retention_init(struct ipa_power *power)
++{
++ struct qmp *qmp = qmp_get(power->dev);
++
++ if (IS_ERR(qmp)) {
++ if (PTR_ERR(qmp) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
++ /* We assume any other error means it's not defined/needed */
++ qmp = NULL;
++ }
++ power->qmp = qmp;
++
++ return 0;
++}
++
++static void ipa_power_retention_exit(struct ipa_power *power)
++{
++ qmp_put(power->qmp);
++ power->qmp = NULL;
++}
++
++/* Control register retention on power collapse */
++void ipa_power_retention(struct ipa *ipa, bool enable)
++{
++ static const char fmt[] = "{ class: bcm, res: ipa_pc, val: %c }";
++ struct ipa_power *power = ipa->power;
++ char buf[36]; /* Exactly enough for fmt[]; size a multiple of 4 */
++ int ret;
++
++ if (!power->qmp)
++ return; /* Not needed on this platform */
++
++ (void)snprintf(buf, sizeof(buf), fmt, enable ? '1' : '0');
++
++ ret = qmp_send(power->qmp, buf, sizeof(buf));
++ if (ret)
++ dev_err(power->dev, "error %d sending QMP %sable request\n",
++ ret, enable ? "en" : "dis");
++}
++
+ int ipa_power_setup(struct ipa *ipa)
+ {
+ int ret;
+@@ -438,12 +483,18 @@ ipa_power_init(struct device *dev, const struct ipa_power_data *data)
+ if (ret)
+ goto err_kfree;
+
++ ret = ipa_power_retention_init(power);
++ if (ret)
++ goto err_interconnect_exit;
++
+ pm_runtime_set_autosuspend_delay(dev, IPA_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+
+ return power;
+
++err_interconnect_exit:
++ ipa_interconnect_exit(power);
+ err_kfree:
+ kfree(power);
+ err_clk_put:
+@@ -460,6 +511,7 @@ void ipa_power_exit(struct ipa_power *power)
+
+ pm_runtime_disable(dev);
+ pm_runtime_dont_use_autosuspend(dev);
++ ipa_power_retention_exit(power);
+ ipa_interconnect_exit(power);
+ kfree(power);
+ clk_put(clk);
+diff --git a/drivers/net/ipa/ipa_power.h b/drivers/net/ipa/ipa_power.h
+index 2151805d7fbb0..6f84f057a2095 100644
+--- a/drivers/net/ipa/ipa_power.h
++++ b/drivers/net/ipa/ipa_power.h
+@@ -40,6 +40,13 @@ void ipa_power_modem_queue_wake(struct ipa *ipa);
+ */
+ void ipa_power_modem_queue_active(struct ipa *ipa);
+
++/**
++ * ipa_power_retention() - Control register retention on power collapse
++ * @ipa: IPA pointer
++ * @enable: Whether retention should be enabled or disabled
++ */
++void ipa_power_retention(struct ipa *ipa, bool enable);
++
+ /**
+ * ipa_power_setup() - Set up IPA power management
+ * @ipa: IPA pointer
diff --git a/drivers/net/ipa/ipa_resource.c b/drivers/net/ipa/ipa_resource.c
index e3da95d694099..06cec71993823 100644
--- a/drivers/net/ipa/ipa_resource.c
@@ -88113,6 +129134,36 @@ index 99a9567896388..59cee31a73836 100644
/**
* ipa_smp2p_notify_reset() - Reset modem notification state
+diff --git a/drivers/net/ipa/ipa_uc.c b/drivers/net/ipa/ipa_uc.c
+index 856e55a080a7f..fe11910518d95 100644
+--- a/drivers/net/ipa/ipa_uc.c
++++ b/drivers/net/ipa/ipa_uc.c
+@@ -11,6 +11,7 @@
+
+ #include "ipa.h"
+ #include "ipa_uc.h"
++#include "ipa_power.h"
+
+ /**
+ * DOC: The IPA embedded microcontroller
+@@ -154,6 +155,7 @@ static void ipa_uc_response_hdlr(struct ipa *ipa, enum ipa_irq_id irq_id)
+ case IPA_UC_RESPONSE_INIT_COMPLETED:
+ if (ipa->uc_powered) {
+ ipa->uc_loaded = true;
++ ipa_power_retention(ipa, true);
+ pm_runtime_mark_last_busy(dev);
+ (void)pm_runtime_put_autosuspend(dev);
+ ipa->uc_powered = false;
+@@ -184,6 +186,9 @@ void ipa_uc_deconfig(struct ipa *ipa)
+
+ ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_1);
+ ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_0);
++ if (ipa->uc_loaded)
++ ipa_power_retention(ipa, false);
++
+ if (!ipa->uc_powered)
+ return;
+
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 93dc48b9b4f24..e53b40359fd10 100644
--- a/drivers/net/macsec.c
@@ -88171,6 +129222,72 @@ index 93dc48b9b4f24..e53b40359fd10 100644
if (data && data[IFLA_MACSEC_ICV_LEN])
icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);
mtu = real_dev->mtu - icv_len - macsec_extra_len(true);
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index 35f46ad040b0d..a9a515cf5a460 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -460,8 +460,10 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
+ return RX_HANDLER_CONSUMED;
+ *pskb = skb;
+ eth = eth_hdr(skb);
+- if (macvlan_forward_source(skb, port, eth->h_source))
++ if (macvlan_forward_source(skb, port, eth->h_source)) {
++ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
++ }
+ src = macvlan_hash_lookup(port, eth->h_source);
+ if (src && src->mode != MACVLAN_MODE_VEPA &&
+ src->mode != MACVLAN_MODE_BRIDGE) {
+@@ -480,8 +482,10 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
+ return RX_HANDLER_PASS;
+ }
+
+- if (macvlan_forward_source(skb, port, eth->h_source))
++ if (macvlan_forward_source(skb, port, eth->h_source)) {
++ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
++ }
+ if (macvlan_passthru(port))
+ vlan = list_first_or_null_rcu(&port->vlans,
+ struct macvlan_dev, list);
+diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
+index 694e2f5dbbe59..39801c31e5071 100644
+--- a/drivers/net/macvtap.c
++++ b/drivers/net/macvtap.c
+@@ -133,11 +133,17 @@ static void macvtap_setup(struct net_device *dev)
+ dev->tx_queue_len = TUN_READQ_SIZE;
+ }
+
++static struct net *macvtap_link_net(const struct net_device *dev)
++{
++ return dev_net(macvlan_dev_real_dev(dev));
++}
++
+ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
+ .kind = "macvtap",
+ .setup = macvtap_setup,
+ .newlink = macvtap_newlink,
+ .dellink = macvtap_dellink,
++ .get_link_net = macvtap_link_net,
+ .priv_size = sizeof(struct macvtap_dev),
+ };
+
+diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
+index 1becb1a731f67..1c1584fca6327 100644
+--- a/drivers/net/mdio/fwnode_mdio.c
++++ b/drivers/net/mdio/fwnode_mdio.c
+@@ -43,6 +43,11 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
+ int rc;
+
+ rc = fwnode_irq_get(child, 0);
++ /* Don't wait forever if the IRQ provider doesn't become available,
++ * just fall back to poll mode
++ */
++ if (rc == -EPROBE_DEFER)
++ rc = driver_deferred_probe_check_state(&phy->mdio.dev);
+ if (rc == -EPROBE_DEFER)
+ return rc;
+
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index cad820568f751..e2273588c75b6 100644
--- a/drivers/net/mdio/mdio-aspeed.c
@@ -88214,6 +129331,43 @@ index 5f4cd24a0241d..4eba5a91075c0 100644
}
static int ipq4019_mdio_probe(struct platform_device *pdev)
+diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
+index 17f98f609ec82..5070ca2f2637a 100644
+--- a/drivers/net/mdio/mdio-mscc-miim.c
++++ b/drivers/net/mdio/mdio-mscc-miim.c
+@@ -76,6 +76,9 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum)
+ u32 val;
+ int ret;
+
++ if (regnum & MII_ADDR_C45)
++ return -EOPNOTSUPP;
++
+ ret = mscc_miim_wait_pending(bus);
+ if (ret)
+ goto out;
+@@ -105,6 +108,9 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id,
+ struct mscc_miim_dev *miim = bus->priv;
+ int ret;
+
++ if (regnum & MII_ADDR_C45)
++ return -EOPNOTSUPP;
++
+ ret = mscc_miim_wait_pending(bus);
+ if (ret < 0)
+ goto out;
+diff --git a/drivers/net/mdio/mdio-mux-bcm6368.c b/drivers/net/mdio/mdio-mux-bcm6368.c
+index 6dcbf987d61b5..8b444a8eb6b55 100644
+--- a/drivers/net/mdio/mdio-mux-bcm6368.c
++++ b/drivers/net/mdio/mdio-mux-bcm6368.c
+@@ -115,7 +115,7 @@ static int bcm6368_mdiomux_probe(struct platform_device *pdev)
+ md->mii_bus = devm_mdiobus_alloc(&pdev->dev);
+ if (!md->mii_bus) {
+ dev_err(&pdev->dev, "mdiomux bus alloc failed\n");
+- return ENOMEM;
++ return -ENOMEM;
+ }
+
+ bus = md->mii_bus;
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 90aafb56f1409..a438202129323 100644
--- a/drivers/net/netdevsim/bpf.c
@@ -88263,11 +129417,112 @@ index 4300261e2f9e7..378ee779061c3 100644
nsim_fib6_rt_nh_del(fib6_rt, fib6_event->rt_arr[i]);
}
return err;
+diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
+index bdac087058b26..5ae39d236b307 100644
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -666,25 +666,7 @@ static int at803x_probe(struct phy_device *phydev)
+ return ret;
+ }
+
+- /* Some bootloaders leave the fiber page selected.
+- * Switch to the copper page, as otherwise we read
+- * the PHY capabilities from the fiber side.
+- */
+- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+- phy_lock_mdio_bus(phydev);
+- ret = at803x_write_page(phydev, AT803X_PAGE_COPPER);
+- phy_unlock_mdio_bus(phydev);
+- if (ret)
+- goto err;
+- }
+-
+ return 0;
+-
+-err:
+- if (priv->vddio)
+- regulator_disable(priv->vddio);
+-
+- return ret;
+ }
+
+ static void at803x_remove(struct phy_device *phydev)
+@@ -785,6 +767,22 @@ static int at803x_config_init(struct phy_device *phydev)
+ {
+ int ret;
+
++ if (phydev->drv->phy_id == ATH8031_PHY_ID) {
++ /* Some bootloaders leave the fiber page selected.
++ * Switch to the copper page, as otherwise we read
++ * the PHY capabilities from the fiber side.
++ */
++ phy_lock_mdio_bus(phydev);
++ ret = at803x_write_page(phydev, AT803X_PAGE_COPPER);
++ phy_unlock_mdio_bus(phydev);
++ if (ret)
++ return ret;
++
++ ret = at8031_pll_config(phydev);
++ if (ret < 0)
++ return ret;
++ }
++
+ /* The RX and TX delay default is:
+ * after HW reset: RX delay enabled and TX delay disabled
+ * after SW reset: RX delay enabled, while TX delay retains the
+@@ -814,12 +812,6 @@ static int at803x_config_init(struct phy_device *phydev)
+ if (ret < 0)
+ return ret;
+
+- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+- ret = at8031_pll_config(phydev);
+- if (ret < 0)
+- return ret;
+- }
+-
+ /* Ar803x extended next page bit is enabled by default. Cisco
+ * multigig switches read this bit and attempt to negotiate 10Gbps
+ * rates even if the next page bit is disabled. This is incorrect
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
-index 83aea5c5cd03c..db26ff8ce7dbb 100644
+index 83aea5c5cd03c..b330efb98209b 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
-@@ -768,6 +768,7 @@ static struct phy_driver broadcom_drivers[] = {
+@@ -11,6 +11,7 @@
+ */
+
+ #include "bcm-phy-lib.h"
++#include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/phy.h>
+ #include <linux/brcmphy.h>
+@@ -553,6 +554,26 @@ static int brcm_fet_config_init(struct phy_device *phydev)
+ if (err < 0)
+ return err;
+
++ /* The datasheet indicates the PHY needs up to 1us to complete a reset,
++ * build some slack here.
++ */
++ usleep_range(1000, 2000);
++
++ /* The PHY requires 65 MDC clock cycles to complete a write operation
++ * and turnaround the line properly.
++ *
++ * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)
++ * may flag the lack of turn-around as a read failure. This is
++ * particularly true with this combination since the MDIO controller
++ * only used 64 MDC cycles. This is not a critical failure in this
++ * specific case and it has no functional impact otherwise, so we let
++ * that one go through. If there is a genuine bus error, the next read
++ * of MII_BRCM_FET_INTREG will error out.
++ */
++ err = phy_read(phydev, MII_BMCR);
++ if (err < 0 && err != -EIO)
++ return err;
++
+ reg = phy_read(phydev, MII_BRCM_FET_INTREG);
+ if (reg < 0)
+ return reg;
+@@ -768,6 +789,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM54616S",
/* PHY_GBIT_FEATURES */
@@ -88275,8 +129530,21 @@ index 83aea5c5cd03c..db26ff8ce7dbb 100644
.config_init = bcm54xx_config_init,
.config_aneg = bcm54616s_config_aneg,
.config_intr = bcm_phy_config_intr,
+diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
+index 211b5476a6f51..ce17b2af3218f 100644
+--- a/drivers/net/phy/dp83822.c
++++ b/drivers/net/phy/dp83822.c
+@@ -274,7 +274,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
+ if (err < 0)
+ return err;
+
+- err = phy_write(phydev, MII_DP83822_MISR1, 0);
++ err = phy_write(phydev, MII_DP83822_MISR2, 0);
+ if (err < 0)
+ return err;
+
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
-index 4fcfca4e17021..cfda625dbea57 100644
+index 4fcfca4e17021..4d726ee03ce20 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -189,6 +189,8 @@
@@ -88349,6 +129617,28 @@ index 4fcfca4e17021..cfda625dbea57 100644
/* Adjust LED Control */
if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
err = phy_write(phydev, 0x10, 0x1100);
+@@ -1684,8 +1693,8 @@ static int marvell_suspend(struct phy_device *phydev)
+ int err;
+
+ /* Suspend the fiber mode first */
+- if (!linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
+- phydev->supported)) {
++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
++ phydev->supported)) {
+ err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
+ if (err < 0)
+ goto error;
+@@ -1719,8 +1728,8 @@ static int marvell_resume(struct phy_device *phydev)
+ int err;
+
+ /* Resume the fiber mode first */
+- if (!linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
+- phydev->supported)) {
++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
++ phydev->supported)) {
+ err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
+ if (err < 0)
+ goto error;
@@ -1932,6 +1941,58 @@ static void marvell_get_stats(struct phy_device *phydev,
data[i] = marvell_get_stat(phydev, i);
}
@@ -88417,6 +129707,19 @@ index 4fcfca4e17021..cfda625dbea57 100644
.get_tunable = m88e1011_get_tunable,
.set_tunable = m88e1011_set_tunable,
.cable_test_start = marvell_vct7_cable_test_start,
+diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
+index bd310e8d5e43d..df33637c5269a 100644
+--- a/drivers/net/phy/marvell10g.c
++++ b/drivers/net/phy/marvell10g.c
+@@ -789,7 +789,7 @@ static int mv3310_read_status_copper(struct phy_device *phydev)
+
+ cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1);
+ if (cssr1 < 0)
+- return val;
++ return cssr1;
+
+ /* If the link settings are not resolved, mark the link down */
+ if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) {
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 6865d9319197f..8dc6e6269c65e 100644
--- a/drivers/net/phy/mdio_bus.c
@@ -88444,8 +129747,77 @@ index b7a5ae20edd53..68ee434f9dea3 100644
mtk_gephy_config_init(phydev);
/* PHY link down power saving enable */
+diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
+index 7e7904fee1d97..73f7962a37d33 100644
+--- a/drivers/net/phy/meson-gxl.c
++++ b/drivers/net/phy/meson-gxl.c
+@@ -30,8 +30,12 @@
+ #define INTSRC_LINK_DOWN BIT(4)
+ #define INTSRC_REMOTE_FAULT BIT(5)
+ #define INTSRC_ANEG_COMPLETE BIT(6)
++#define INTSRC_ENERGY_DETECT BIT(7)
+ #define INTSRC_MASK 30
+
++#define INT_SOURCES (INTSRC_LINK_DOWN | INTSRC_ANEG_COMPLETE | \
++ INTSRC_ENERGY_DETECT)
++
+ #define BANK_ANALOG_DSP 0
+ #define BANK_WOL 1
+ #define BANK_BIST 3
+@@ -200,7 +204,6 @@ static int meson_gxl_ack_interrupt(struct phy_device *phydev)
+
+ static int meson_gxl_config_intr(struct phy_device *phydev)
+ {
+- u16 val;
+ int ret;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+@@ -209,16 +212,9 @@ static int meson_gxl_config_intr(struct phy_device *phydev)
+ if (ret)
+ return ret;
+
+- val = INTSRC_ANEG_PR
+- | INTSRC_PARALLEL_FAULT
+- | INTSRC_ANEG_LP_ACK
+- | INTSRC_LINK_DOWN
+- | INTSRC_REMOTE_FAULT
+- | INTSRC_ANEG_COMPLETE;
+- ret = phy_write(phydev, INTSRC_MASK, val);
++ ret = phy_write(phydev, INTSRC_MASK, INT_SOURCES);
+ } else {
+- val = 0;
+- ret = phy_write(phydev, INTSRC_MASK, val);
++ ret = phy_write(phydev, INTSRC_MASK, 0);
+
+ /* Ack any pending IRQ */
+ ret = meson_gxl_ack_interrupt(phydev);
+@@ -237,10 +233,23 @@ static irqreturn_t meson_gxl_handle_interrupt(struct phy_device *phydev)
+ return IRQ_NONE;
+ }
+
++ irq_status &= INT_SOURCES;
++
+ if (irq_status == 0)
+ return IRQ_NONE;
+
+- phy_trigger_machine(phydev);
++ /* Aneg-complete interrupt is used for link-up detection */
++ if (phydev->autoneg == AUTONEG_ENABLE &&
++ irq_status == INTSRC_ENERGY_DETECT)
++ return IRQ_HANDLED;
++
++ /* Give PHY some time before MAC starts sending data. This works
++ * around an issue where network doesn't come up properly.
++ */
++ if (!(irq_status & INTSRC_LINK_DOWN))
++ phy_queue_state_machine(phydev, msecs_to_jiffies(100));
++ else
++ phy_trigger_machine(phydev);
+
+ return IRQ_HANDLED;
+ }
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
-index 5c928f827173c..e2ac61f44c945 100644
+index 5c928f827173c..64d829ed98876 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -863,9 +863,9 @@ static int ksz9031_config_init(struct phy_device *phydev)
@@ -88460,7 +129832,11 @@ index 5c928f827173c..e2ac61f44c945 100644
/* Silicon Errata Sheet (DS80000691D or DS80000692D):
* When the device links in the 1000BASE-T slave mode only,
-@@ -1547,8 +1547,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1544,11 +1544,12 @@ static struct phy_driver ksphy_driver[] = {
+ .name = "Micrel KS8737",
+ /* PHY_BASIC_FEATURES */
+ .driver_data = &ks8737_type,
++ .probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt,
@@ -88471,7 +129847,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8021,
.phy_id_mask = 0x00ffffff,
-@@ -1562,8 +1562,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1562,8 +1563,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88482,7 +129858,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8031,
.phy_id_mask = 0x00ffffff,
-@@ -1577,8 +1577,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1577,8 +1578,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88493,7 +129869,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8041,
.phy_id_mask = MICREL_PHY_ID_MASK,
-@@ -1593,8 +1593,9 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1593,8 +1594,9 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88505,7 +129881,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8041RNLI,
.phy_id_mask = MICREL_PHY_ID_MASK,
-@@ -1608,8 +1609,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1608,8 +1610,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88516,7 +129892,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.name = "Micrel KSZ8051",
/* PHY_BASIC_FEATURES */
-@@ -1622,8 +1623,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1622,8 +1624,8 @@ static struct phy_driver ksphy_driver[] = {
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
.match_phy_device = ksz8051_match_phy_device,
@@ -88527,7 +129903,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8001,
.name = "Micrel KSZ8001 or KS8721",
-@@ -1637,8 +1638,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1637,8 +1639,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88538,18 +129914,7 @@ index 5c928f827173c..e2ac61f44c945 100644
}, {
.phy_id = PHY_ID_KSZ8081,
.name = "Micrel KSZ8081 or KSZ8091",
-@@ -1668,8 +1669,8 @@ static struct phy_driver ksphy_driver[] = {
- .config_init = ksz8061_config_init,
- .config_intr = kszphy_config_intr,
- .handle_interrupt = kszphy_handle_interrupt,
-- .suspend = genphy_suspend,
-- .resume = genphy_resume,
-+ .suspend = kszphy_suspend,
-+ .resume = kszphy_resume,
- }, {
- .phy_id = PHY_ID_KSZ9021,
- .phy_id_mask = 0x000ffffe,
-@@ -1684,8 +1685,8 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1684,8 +1686,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88560,7 +129925,7 @@ index 5c928f827173c..e2ac61f44c945 100644
.read_mmd = genphy_read_mmd_unsupported,
.write_mmd = genphy_write_mmd_unsupported,
}, {
-@@ -1703,7 +1704,7 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1703,7 +1705,7 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88569,7 +129934,7 @@ index 5c928f827173c..e2ac61f44c945 100644
.resume = kszphy_resume,
}, {
.phy_id = PHY_ID_LAN8814,
-@@ -1731,7 +1732,7 @@ static struct phy_driver ksphy_driver[] = {
+@@ -1731,7 +1733,7 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
@@ -88578,6 +129943,17 @@ index 5c928f827173c..e2ac61f44c945 100644
.resume = kszphy_resume,
}, {
.phy_id = PHY_ID_KSZ8873MLL,
+diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
+index 6e32da28e138f..f2e3a67198dd6 100644
+--- a/drivers/net/phy/mscc/mscc_main.c
++++ b/drivers/net/phy/mscc/mscc_main.c
+@@ -2685,3 +2685,6 @@ MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
+ MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
+ MODULE_AUTHOR("Nagaraju Lakkaraju");
+ MODULE_LICENSE("Dual MIT/GPL");
++
++MODULE_FIRMWARE(MSCC_VSC8584_REVB_INT8051_FW);
++MODULE_FIRMWARE(MSCC_VSC8574_REVB_INT8051_FW);
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 2870c33b8975d..271fc01f7f7fd 100644
--- a/drivers/net/phy/phy-core.c
@@ -88596,7 +129972,7 @@ index 2870c33b8975d..271fc01f7f7fd 100644
PHY_SETTING( 100, FULL, 100baseT_Full ),
PHY_SETTING( 100, FULL, 100baseT1_Full ),
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
-index a3bfb156c83d7..beb2b66da1324 100644
+index a3bfb156c83d7..f122026c46826 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -815,7 +815,12 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
@@ -88613,6 +129989,21 @@ index a3bfb156c83d7..beb2b66da1324 100644
mutex_unlock(&phydev->lock);
return 0;
+@@ -965,8 +970,13 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
+ {
+ struct phy_device *phydev = phy_dat;
+ struct phy_driver *drv = phydev->drv;
++ irqreturn_t ret;
+
+- return drv->handle_interrupt(phydev);
++ mutex_lock(&phydev->lock);
++ ret = drv->handle_interrupt(phydev);
++ mutex_unlock(&phydev->lock);
++
++ return ret;
+ }
+
+ /**
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 4f9990b47a377..28f4a383aba72 100644
--- a/drivers/net/phy/phy_device.c
@@ -88724,10 +130115,23 @@ index 0a0abe8e4be0b..fef1416dcee4c 100644
pause_state = 0;
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
-index 7362f8c3271c9..ef2c6a09eb0f3 100644
+index 7362f8c3271c9..4369d6249e7bb 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
-@@ -651,6 +651,11 @@ struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
+@@ -74,6 +74,12 @@ static const struct sfp_quirk sfp_quirks[] = {
+ .vendor = "HUAWEI",
+ .part = "MA5671A",
+ .modes = sfp_quirk_2500basex,
++ }, {
++ // Lantech 8330-262D-E can operate at 2500base-X, but
++ // incorrectly report 2500MBd NRZ in their EEPROM
++ .vendor = "Lantech",
++ .part = "8330-262D-E",
++ .modes = sfp_quirk_2500basex,
+ }, {
+ .vendor = "UBNT",
+ .part = "UF-INSTANT",
+@@ -651,6 +657,11 @@ struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
else if (ret < 0)
return ERR_PTR(ret);
@@ -88740,10 +130144,18 @@ index 7362f8c3271c9..ef2c6a09eb0f3 100644
fwnode_handle_put(ref.fwnode);
if (!bus)
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
-index ab77a9f439ef9..4720b24ca51b5 100644
+index ab77a9f439ef9..90dfefc1f5f8d 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
-@@ -1641,17 +1641,20 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
+@@ -250,6 +250,7 @@ struct sfp {
+ struct sfp_eeprom_id id;
+ unsigned int module_power_mW;
+ unsigned int module_t_start_up;
++ bool tx_fault_ignore;
+
+ #if IS_ENABLED(CONFIG_HWMON)
+ struct sfp_diag diag;
+@@ -1641,17 +1642,20 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
static int sfp_module_parse_power(struct sfp *sfp)
{
u32 power_mW = 1000;
@@ -88767,7 +130179,7 @@ index ab77a9f439ef9..4720b24ca51b5 100644
/* The module appears not to implement bus address
* 0xa2, so assume that the module powers up in the
* indicated mode.
-@@ -1668,11 +1671,25 @@ static int sfp_module_parse_power(struct sfp *sfp)
+@@ -1668,11 +1672,25 @@ static int sfp_module_parse_power(struct sfp *sfp)
}
}
@@ -88794,6 +130206,31 @@ index ab77a9f439ef9..4720b24ca51b5 100644
dev_warn(sfp->dev,
"Address Change Sequence not supported but module requires %u.%uW, module may not be functional\n",
power_mW / 1000, (power_mW / 100) % 10);
+@@ -1928,6 +1946,12 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
+ else
+ sfp->module_t_start_up = T_START_UP;
+
++ if (!memcmp(id.base.vendor_name, "HUAWEI ", 16) &&
++ !memcmp(id.base.vendor_pn, "MA5671A ", 16))
++ sfp->tx_fault_ignore = true;
++ else
++ sfp->tx_fault_ignore = false;
++
+ return 0;
+ }
+
+@@ -2380,7 +2404,10 @@ static void sfp_check_state(struct sfp *sfp)
+ mutex_lock(&sfp->st_mutex);
+ state = sfp_get_state(sfp);
+ changed = state ^ sfp->state;
+- changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT;
++ if (sfp->tx_fault_ignore)
++ changed &= SFP_F_PRESENT | SFP_F_LOS;
++ else
++ changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT;
+
+ for (i = 0; i < GPIO_MAX; i++)
+ if (changed & BIT(i))
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index fb52cd175b45d..829d6ada1704c 100644
--- a/drivers/net/ppp/ppp_generic.c
@@ -88826,6 +130263,31 @@ index fb52cd175b45d..829d6ada1704c 100644
switch (proto) {
case PPP_IP:
+diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
+index 3619520340b74..e172743948ed7 100644
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -988,6 +988,7 @@ static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx,
+ path->encap.proto = htons(ETH_P_PPP_SES);
+ path->encap.id = be16_to_cpu(po->num);
+ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN);
++ memcpy(ctx->daddr, po->pppoe_pa.remote, ETH_ALEN);
+ path->dev = ctx->dev;
+ ctx->dev = dev;
+
+diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
+index 5435b5689ce6b..2a3892528ec36 100644
+--- a/drivers/net/slip/slip.c
++++ b/drivers/net/slip/slip.c
+@@ -469,7 +469,7 @@ static void sl_tx_timeout(struct net_device *dev, unsigned int txqueue)
+ spin_lock(&sl->lock);
+
+ if (netif_queue_stopped(dev)) {
+- if (!netif_running(dev))
++ if (!netif_running(dev) || !sl->tty)
+ goto out;
+
+ /* May be we must check transmitter timeout here ?
diff --git a/drivers/net/slip/slip.h b/drivers/net/slip/slip.h
index c420e59485221..3d7f88b330c1e 100644
--- a/drivers/net/slip/slip.h
@@ -88839,8 +130301,22 @@ index c420e59485221..3d7f88b330c1e 100644
/* SLIP protocol characters. */
#define END 0300 /* indicates end of frame */
#define ESC 0333 /* indicates byte stuffing */
+diff --git a/drivers/net/tap.c b/drivers/net/tap.c
+index 8e3a28ba6b282..ba2ef5437e167 100644
+--- a/drivers/net/tap.c
++++ b/drivers/net/tap.c
+@@ -1198,7 +1198,8 @@ static int tap_sendmsg(struct socket *sock, struct msghdr *m,
+ struct xdp_buff *xdp;
+ int i;
+
+- if (ctl && (ctl->type == TUN_MSG_PTR)) {
++ if (m->msg_controllen == sizeof(struct tun_msg_ctl) &&
++ ctl && ctl->type == TUN_MSG_PTR) {
+ for (i = 0; i < ctl->num; i++) {
+ xdp = &((struct xdp_buff *)ctl->ptr)[i];
+ tap_get_user_xdp(q, xdp);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
-index fecc9a1d293ae..45a67e72a02c6 100644
+index fecc9a1d293ae..02de8d998bfa4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -209,6 +209,9 @@ struct tun_struct {
@@ -88969,7 +130445,17 @@ index fecc9a1d293ae..45a67e72a02c6 100644
tun_flow_uninit(tun);
security_tun_dev_free_security(tun->security);
__tun_set_ebpf(tun, &tun->steering_prog, NULL);
-@@ -2711,41 +2762,16 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
+@@ -2438,7 +2489,8 @@ static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
+ if (!tun)
+ return -EBADFD;
+
+- if (ctl && (ctl->type == TUN_MSG_PTR)) {
++ if (m->msg_controllen == sizeof(struct tun_msg_ctl) &&
++ ctl && ctl->type == TUN_MSG_PTR) {
+ struct tun_page tpage;
+ int n = ctl->num;
+ int flush = 0;
+@@ -2711,41 +2763,16 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->rx_batched = 0;
RCU_INIT_POINTER(tun->steering_prog, NULL);
@@ -89018,7 +130504,7 @@ index fecc9a1d293ae..45a67e72a02c6 100644
/* free_netdev() won't check refcnt, to avoid race
* with dev_put() we need publish tun after registration.
*/
-@@ -2762,24 +2788,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
+@@ -2762,24 +2789,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
strcpy(ifr->ifr_name, tun->dev->name);
return 0;
@@ -89043,20 +130529,75 @@ index fecc9a1d293ae..45a67e72a02c6 100644
}
static void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr)
+diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
+index 73b97f4cc1ec1..e8d49886d6953 100644
+--- a/drivers/net/usb/aqc111.c
++++ b/drivers/net/usb/aqc111.c
+@@ -1102,10 +1102,15 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ if (start_of_descs != desc_offset)
+ goto err;
+
+- /* self check desc_offset from header*/
+- if (desc_offset >= skb_len)
++ /* self check desc_offset from header and make sure that the
++ * bounds of the metadata array are inside the SKB
++ */
++ if (pkt_count * 2 + desc_offset >= skb_len)
+ goto err;
+
++ /* Packets must not overlap the metadata array */
++ skb_trim(skb, desc_offset);
++
+ if (pkt_count == 0)
+ goto err;
+
+diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
+index 2a1e31defe718..4334aafab59a4 100644
+--- a/drivers/net/usb/asix.h
++++ b/drivers/net/usb/asix.h
+@@ -192,8 +192,8 @@ extern const struct driver_info ax88172a_info;
+ /* ASIX specific flags */
+ #define FLAG_EEPROM_MAC (1UL << 0) /* init device MAC from eeprom */
+
+-int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+- u16 size, void *data, int in_pm);
++int __must_check asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
++ u16 size, void *data, int in_pm);
+
+ int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data, int in_pm);
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
-index 38cda590895cc..9aa92076500af 100644
+index 38cda590895cc..f39188b7717ae 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
-@@ -9,6 +9,8 @@
+@@ -9,8 +9,10 @@
#include "asix.h"
+-int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+- u16 size, void *data, int in_pm)
+#define AX_HOST_EN_RETRIES 30
+
- int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data, int in_pm)
++int __must_check asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
++ u16 size, void *data, int in_pm)
{
-@@ -68,7 +70,7 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm)
+ int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
+@@ -25,9 +27,12 @@ int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, data, size);
+
+- if (unlikely(ret < 0))
++ if (unlikely(ret < size)) {
++ ret = ret < 0 ? ret : -ENODATA;
++
+ netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n",
+ index, ret);
++ }
+
+ return ret;
+ }
+@@ -68,7 +73,7 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm)
int i, ret;
u8 smsr;
@@ -89065,14 +130606,7 @@ index 38cda590895cc..9aa92076500af 100644
ret = asix_set_sw_mii(dev, in_pm);
if (ret == -ENODEV || ret == -ETIMEDOUT)
break;
-@@ -77,13 +79,13 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm)
- 0, 0, 1, &smsr, in_pm);
- if (ret == -ENODEV)
- break;
-- else if (ret < 0)
-+ else if (ret < sizeof(smsr))
- continue;
- else if (smsr & AX_HOST_EN)
+@@ -83,7 +88,7 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm)
break;
}
@@ -89081,6 +130615,63 @@ index 38cda590895cc..9aa92076500af 100644
}
static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx)
+@@ -577,8 +582,12 @@ int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc)
+ return ret;
+ }
+
+- asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+- (__u16)loc, 2, &res, 1);
++ ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
++ (__u16)loc, 2, &res, 1);
++ if (ret < 0) {
++ mutex_unlock(&dev->phy_mutex);
++ return ret;
++ }
+ asix_set_hw_mii(dev, 1);
+ mutex_unlock(&dev->phy_mutex);
+
+diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
+index 30821f6a6d7ac..bd8f8619ad6f2 100644
+--- a/drivers/net/usb/asix_devices.c
++++ b/drivers/net/usb/asix_devices.c
+@@ -755,7 +755,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+ priv->phy_addr = ret;
+ priv->embd_phy = ((priv->phy_addr & 0x1f) == 0x10);
+
+- asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
++ ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
++ if (ret < 0) {
++ netdev_dbg(dev->net, "Failed to read STATMNGSTS_REG: %d\n", ret);
++ return ret;
++ }
++
+ chipcode &= AX_CHIPCODE_MASK;
+
+ ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+@@ -920,11 +925,21 @@ static int ax88178_reset(struct usbnet *dev)
+ int gpio0 = 0;
+ u32 phyid;
+
+- asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status, 0);
++ ret = asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status, 0);
++ if (ret < 0) {
++ netdev_dbg(dev->net, "Failed to read GPIOS: %d\n", ret);
++ return ret;
++ }
++
+ netdev_dbg(dev->net, "GPIO Status: 0x%04x\n", status);
+
+ asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL, 0);
+- asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom, 0);
++ ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom, 0);
++ if (ret < 0) {
++ netdev_dbg(dev->net, "Failed to read EEPROM: %d\n", ret);
++ return ret;
++ }
++
+ asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL, 0);
+
+ netdev_dbg(dev->net, "EEPROM index 0x17 is 0x%04x\n", eeprom);
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index f25448a088707..d5ce642200e8e 100644
--- a/drivers/net/usb/ax88179_178a.c
@@ -89553,10 +131144,94 @@ index 85a8b96e39a65..bedd36ab5cf01 100644
/* RNDIS is MSFT's un-official variant of CDC ACM */
USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
-index 26b1bd8e845b4..026e7487c45b5 100644
+index 26b1bd8e845b4..eb0d325e92b76 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
-@@ -1049,6 +1049,14 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
+@@ -84,9 +84,10 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
+- if (unlikely(ret < 0)) {
+- netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+- index, ret);
++ if (ret < 0) {
++ if (ret != -ENODEV)
++ netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
++ index, ret);
+ return ret;
+ }
+
+@@ -116,7 +117,7 @@ static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
+ ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
+- if (unlikely(ret < 0))
++ if (ret < 0 && ret != -ENODEV)
+ netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+ index, ret);
+
+@@ -159,6 +160,9 @@ static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
+ do {
+ ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
+ if (ret < 0) {
++ /* Ignore -ENODEV error during disconnect() */
++ if (ret == -ENODEV)
++ return 0;
+ netdev_warn(dev->net, "Error reading MII_ACCESS\n");
+ return ret;
+ }
+@@ -194,7 +198,8 @@ static int __smsc95xx_mdio_read(struct usbnet *dev, int phy_id, int idx,
+ addr = mii_address_cmd(phy_id, idx, MII_READ_ | MII_BUSY_);
+ ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+ if (ret < 0) {
+- netdev_warn(dev->net, "Error writing MII_ADDR\n");
++ if (ret != -ENODEV)
++ netdev_warn(dev->net, "Error writing MII_ADDR\n");
+ goto done;
+ }
+
+@@ -206,7 +211,8 @@ static int __smsc95xx_mdio_read(struct usbnet *dev, int phy_id, int idx,
+
+ ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
+ if (ret < 0) {
+- netdev_warn(dev->net, "Error reading MII_DATA\n");
++ if (ret != -ENODEV)
++ netdev_warn(dev->net, "Error reading MII_DATA\n");
+ goto done;
+ }
+
+@@ -214,6 +220,10 @@ static int __smsc95xx_mdio_read(struct usbnet *dev, int phy_id, int idx,
+
+ done:
+ mutex_unlock(&dev->phy_mutex);
++
++ /* Ignore -ENODEV error during disconnect() */
++ if (ret == -ENODEV)
++ return 0;
+ return ret;
+ }
+
+@@ -235,7 +245,8 @@ static void __smsc95xx_mdio_write(struct usbnet *dev, int phy_id,
+ val = regval;
+ ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
+ if (ret < 0) {
+- netdev_warn(dev->net, "Error writing MII_DATA\n");
++ if (ret != -ENODEV)
++ netdev_warn(dev->net, "Error writing MII_DATA\n");
+ goto done;
+ }
+
+@@ -243,7 +254,8 @@ static void __smsc95xx_mdio_write(struct usbnet *dev, int phy_id,
+ addr = mii_address_cmd(phy_id, idx, MII_WRITE_ | MII_BUSY_);
+ ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+ if (ret < 0) {
+- netdev_warn(dev->net, "Error writing MII_ADDR\n");
++ if (ret != -ENODEV)
++ netdev_warn(dev->net, "Error writing MII_ADDR\n");
+ goto done;
+ }
+
+@@ -1049,6 +1061,14 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
.ndo_set_features = smsc95xx_set_features,
};
@@ -89571,7 +131246,7 @@ index 26b1bd8e845b4..026e7487c45b5 100644
static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
{
struct smsc95xx_priv *pdata;
-@@ -1153,6 +1161,17 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+@@ -1153,6 +1173,17 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->min_mtu = ETH_MIN_MTU;
dev->net->max_mtu = ETH_DATA_LEN;
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
@@ -89589,7 +131264,7 @@ index 26b1bd8e845b4..026e7487c45b5 100644
return 0;
unregister_mdio:
-@@ -1170,47 +1189,25 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
+@@ -1170,47 +1201,25 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
{
struct smsc95xx_priv *pdata = dev->driver_priv;
@@ -89613,12 +131288,12 @@ index 26b1bd8e845b4..026e7487c45b5 100644
- struct smsc95xx_priv *pdata = dev->driver_priv;
- struct net_device *net = dev->net;
- int ret;
-+ phy_start(dev->net->phydev);
-
+-
- ret = smsc95xx_reset(dev);
- if (ret < 0)
- return ret;
--
++ phy_start(dev->net->phydev);
+
- ret = phy_connect_direct(net, pdata->phydev,
- &smsc95xx_handle_link_change,
- PHY_INTERFACE_MODE_MII);
@@ -89643,7 +131318,7 @@ index 26b1bd8e845b4..026e7487c45b5 100644
return 0;
}
-@@ -1964,8 +1961,9 @@ static const struct driver_info smsc95xx_info = {
+@@ -1964,8 +1973,9 @@ static const struct driver_info smsc95xx_info = {
.bind = smsc95xx_bind,
.unbind = smsc95xx_unbind,
.link_reset = smsc95xx_link_reset,
@@ -89699,7 +131374,7 @@ index 8e717a0b559b3..7984f2157d222 100644
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
-index 50eb43e5bf459..f478fe7e2b820 100644
+index 50eb43e5bf459..64fa8e9c0a22b 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -272,9 +272,10 @@ static void __veth_xdp_flush(struct veth_rq *rq)
@@ -89716,6 +131391,15 @@ index 50eb43e5bf459..f478fe7e2b820 100644
}
}
+@@ -326,7 +327,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ rcu_read_lock();
+ rcv = rcu_dereference(priv->peer);
+- if (unlikely(!rcv)) {
++ if (unlikely(!rcv) || !pskb_may_pull(skb, ETH_HLEN)) {
+ kfree_skb(skb);
+ goto drop;
+ }
@@ -342,7 +343,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
*/
use_napi = rcu_access_pointer(rq->napi) &&
@@ -89752,11 +131436,76 @@ index 50eb43e5bf459..f478fe7e2b820 100644
}
}
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 4ad25a8b0870c..73aba760e10c6 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -965,6 +965,24 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
+ * xdp.data_meta were adjusted
+ */
+ len = xdp.data_end - xdp.data + vi->hdr_len + metasize;
++
++ /* recalculate headroom if xdp.data or xdp_data_meta
++ * were adjusted, note that offset should always point
++ * to the start of the reserved bytes for virtio_net
++ * header which are followed by xdp.data, that means
++ * that offset is equal to the headroom (when buf is
++ * starting at the beginning of the page, otherwise
++ * there is a base offset inside the page) but it's used
++ * with a different starting point (buf start) than
++ * xdp.data (buf start + vnet hdr size). If xdp.data or
++ * data_meta were adjusted by the xdp prog then the
++ * headroom size has changed and so has the offset, we
++ * can use data_hard_start, which points at buf start +
++ * vnet hdr size, to calculate the new headroom and use
++ * it later to compute buf start in page_to_skb()
++ */
++ headroom = xdp.data - xdp.data_hard_start - metasize;
++
+ /* We can only create skb based on xdp_page. */
+ if (unlikely(xdp_page != page)) {
+ rcu_read_unlock();
+@@ -972,7 +990,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
+ head_skb = page_to_skb(vi, rq, xdp_page, offset,
+ len, PAGE_SIZE, false,
+ metasize,
+- VIRTIO_XDP_HEADROOM);
++ headroom);
+ return head_skb;
+ }
+ break;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
-index 8799854bacb29..5b0215b7c1761 100644
+index 8799854bacb29..bc3192cf48e3e 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
-@@ -3261,7 +3261,7 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
+@@ -589,6 +589,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
+ if (dma_mapping_error(&adapter->pdev->dev,
+ rbi->dma_addr)) {
+ dev_kfree_skb_any(rbi->skb);
++ rbi->skb = NULL;
+ rq->stats.rx_buf_alloc_failure++;
+ break;
+ }
+@@ -613,6 +614,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
+ if (dma_mapping_error(&adapter->pdev->dev,
+ rbi->dma_addr)) {
+ put_page(rbi->page);
++ rbi->page = NULL;
+ rq->stats.rx_buf_alloc_failure++;
+ break;
+ }
+@@ -1666,6 +1668,10 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
+ u32 i, ring_idx;
+ struct Vmxnet3_RxDesc *rxd;
+
++ /* ring has already been cleaned up */
++ if (!rq->rx_ring[0].base)
++ return;
++
+ for (ring_idx = 0; ring_idx < 2; ring_idx++) {
+ for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
+ #ifdef __BIG_ENDIAN_BITFIELD
+@@ -3261,7 +3267,7 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
#ifdef CONFIG_PCI_MSI
if (adapter->intr.type == VMXNET3_IT_MSIX) {
@@ -89765,7 +131514,7 @@ index 8799854bacb29..5b0215b7c1761 100644
nvec = adapter->share_intr == VMXNET3_INTR_TXSHARE ?
1 : adapter->num_tx_queues;
-@@ -3274,14 +3274,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
+@@ -3274,14 +3280,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
for (i = 0; i < nvec; i++)
adapter->intr.msix_entries[i].entry = i;
@@ -89784,7 +131533,7 @@ index 8799854bacb29..5b0215b7c1761 100644
if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE
|| adapter->num_rx_queues != 1) {
adapter->share_intr = VMXNET3_INTR_TXSHARE;
-@@ -3291,14 +3292,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
+@@ -3291,14 +3298,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
}
}
@@ -89802,7 +131551,7 @@ index 8799854bacb29..5b0215b7c1761 100644
adapter->intr.type = VMXNET3_IT_MSI;
}
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
-index 662e261173539..b2242a082431c 100644
+index 662e261173539..091dd7caf10cc 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -35,6 +35,7 @@
@@ -89911,6 +131660,82 @@ index 662e261173539..b2242a082431c 100644
if (qdisc_tx_is_default(vrf_dev) ||
IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
return vrf_ip_out_direct(vrf_dev, sk, skb);
+@@ -1243,6 +1265,7 @@ static int vrf_prepare_mac_header(struct sk_buff *skb,
+ eth = (struct ethhdr *)skb->data;
+
+ skb_reset_mac_header(skb);
++ skb_reset_mac_len(skb);
+
+ /* we set the ethernet destination and the source addresses to the
+ * address of the VRF device.
+@@ -1272,9 +1295,9 @@ static int vrf_prepare_mac_header(struct sk_buff *skb,
+ */
+ static int vrf_add_mac_header_if_unset(struct sk_buff *skb,
+ struct net_device *vrf_dev,
+- u16 proto)
++ u16 proto, struct net_device *orig_dev)
+ {
+- if (skb_mac_header_was_set(skb))
++ if (skb_mac_header_was_set(skb) && dev_has_header(orig_dev))
+ return 0;
+
+ return vrf_prepare_mac_header(skb, vrf_dev, proto);
+@@ -1380,6 +1403,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+
+ /* if packet is NDISC then keep the ingress interface */
+ if (!is_ndisc) {
++ struct net_device *orig_dev = skb->dev;
++
+ vrf_rx_stats(vrf_dev, skb->len);
+ skb->dev = vrf_dev;
+ skb->skb_iif = vrf_dev->ifindex;
+@@ -1388,7 +1413,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+ int err;
+
+ err = vrf_add_mac_header_if_unset(skb, vrf_dev,
+- ETH_P_IPV6);
++ ETH_P_IPV6,
++ orig_dev);
+ if (likely(!err)) {
+ skb_push(skb, skb->mac_len);
+ dev_queue_xmit_nit(skb, vrf_dev);
+@@ -1418,6 +1444,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
+ struct sk_buff *skb)
+ {
++ struct net_device *orig_dev = skb->dev;
++
+ skb->dev = vrf_dev;
+ skb->skb_iif = vrf_dev->ifindex;
+ IPCB(skb)->flags |= IPSKB_L3SLAVE;
+@@ -1438,7 +1466,8 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
+ if (!list_empty(&vrf_dev->ptype_all)) {
+ int err;
+
+- err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP);
++ err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP,
++ orig_dev);
+ if (likely(!err)) {
+ skb_push(skb, skb->mac_len);
+ dev_queue_xmit_nit(skb, vrf_dev);
+diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
+index 141635a35c28a..129e270e9a7cd 100644
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -711,11 +711,11 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
+
+ rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+ if (rd == NULL)
+- return -ENOBUFS;
++ return -ENOMEM;
+
+ if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) {
+ kfree(rd);
+- return -ENOBUFS;
++ return -ENOMEM;
+ }
+
+ rd->remote_ip = *ip;
diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index b7197e80f2264..9a4c8ff32d9dd 100644
--- a/drivers/net/wireguard/allowedips.c
@@ -89925,10 +131750,18 @@ index b7197e80f2264..9a4c8ff32d9dd 100644
node->parent_bit_packed = (unsigned long)parent | bit;
rcu_assign_pointer(*parent, node);
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
-index 551ddaaaf5400..a46067c38bf5d 100644
+index 551ddaaaf5400..5eaef79c06e16 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
-@@ -98,6 +98,7 @@ static int wg_stop(struct net_device *dev)
+@@ -19,6 +19,7 @@
+ #include <linux/if_arp.h>
+ #include <linux/icmp.h>
+ #include <linux/suspend.h>
++#include <net/dst_metadata.h>
+ #include <net/icmp.h>
+ #include <net/rtnetlink.h>
+ #include <net/ip_tunnels.h>
+@@ -98,6 +99,7 @@ static int wg_stop(struct net_device *dev)
{
struct wg_device *wg = netdev_priv(dev);
struct wg_peer *peer;
@@ -89936,7 +131769,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
mutex_lock(&wg->device_update_lock);
list_for_each_entry(peer, &wg->peer_list, peer_list) {
-@@ -108,7 +109,9 @@ static int wg_stop(struct net_device *dev)
+@@ -108,7 +110,9 @@ static int wg_stop(struct net_device *dev)
wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake);
}
mutex_unlock(&wg->device_update_lock);
@@ -89947,7 +131780,16 @@ index 551ddaaaf5400..a46067c38bf5d 100644
wg_socket_reinit(wg, NULL, NULL);
return 0;
}
-@@ -235,14 +238,13 @@ static void wg_destruct(struct net_device *dev)
+@@ -149,7 +153,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
+ goto err_peer;
+ }
+
+- mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
++ mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
+
+ __skb_queue_head_init(&packets);
+ if (!skb_is_gso(skb)) {
+@@ -235,14 +239,13 @@ static void wg_destruct(struct net_device *dev)
destroy_workqueue(wg->handshake_receive_wq);
destroy_workqueue(wg->handshake_send_wq);
destroy_workqueue(wg->packet_crypt_wq);
@@ -89965,7 +131807,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
kvfree(wg->index_hashtable);
kvfree(wg->peer_hashtable);
mutex_unlock(&wg->device_update_lock);
-@@ -298,7 +300,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
+@@ -298,7 +301,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
init_rwsem(&wg->static_identity.lock);
mutex_init(&wg->socket_update_lock);
mutex_init(&wg->device_update_lock);
@@ -89973,7 +131815,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
wg_allowedips_init(&wg->peer_allowedips);
wg_cookie_checker_init(&wg->cookie_checker, wg);
INIT_LIST_HEAD(&wg->peer_list);
-@@ -316,16 +317,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
+@@ -316,16 +318,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
if (!dev->tstats)
goto err_free_index_hashtable;
@@ -89991,7 +131833,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
wg->handshake_send_wq = alloc_workqueue("wg-kex-%s",
WQ_UNBOUND | WQ_FREEZABLE, 0, dev->name);
-@@ -347,10 +342,15 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
+@@ -347,10 +343,15 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
if (ret < 0)
goto err_free_encrypt_queue;
@@ -90008,7 +131850,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
ret = register_netdevice(dev);
if (ret < 0)
goto err_uninit_ratelimiter;
-@@ -367,18 +367,18 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
+@@ -367,18 +368,18 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
err_uninit_ratelimiter:
wg_ratelimiter_uninit();
@@ -90031,7 +131873,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
err_free_tstats:
free_percpu(dev->tstats);
err_free_index_hashtable:
-@@ -398,6 +398,7 @@ static struct rtnl_link_ops link_ops __read_mostly = {
+@@ -398,6 +399,7 @@ static struct rtnl_link_ops link_ops __read_mostly = {
static void wg_netns_pre_exit(struct net *net)
{
struct wg_device *wg;
@@ -90039,7 +131881,7 @@ index 551ddaaaf5400..a46067c38bf5d 100644
rtnl_lock();
list_for_each_entry(wg, &device_list, device_list) {
-@@ -407,6 +408,8 @@ static void wg_netns_pre_exit(struct net *net)
+@@ -407,6 +409,8 @@ static void wg_netns_pre_exit(struct net *net)
mutex_lock(&wg->device_update_lock);
rcu_assign_pointer(wg->creating_net, NULL);
wg_socket_reinit(wg, NULL, NULL);
@@ -90077,11 +131919,102 @@ index 854bc3d97150e..43c7cebbf50b0 100644
unsigned int num_peers, device_update_gen;
u32 fwmark;
u16 incoming_port;
+diff --git a/drivers/net/wireguard/noise.c b/drivers/net/wireguard/noise.c
+index c0cfd9b36c0b5..720952b92e784 100644
+--- a/drivers/net/wireguard/noise.c
++++ b/drivers/net/wireguard/noise.c
+@@ -302,6 +302,41 @@ void wg_noise_set_static_identity_private_key(
+ static_identity->static_public, private_key);
+ }
+
++static void hmac(u8 *out, const u8 *in, const u8 *key, const size_t inlen, const size_t keylen)
++{
++ struct blake2s_state state;
++ u8 x_key[BLAKE2S_BLOCK_SIZE] __aligned(__alignof__(u32)) = { 0 };
++ u8 i_hash[BLAKE2S_HASH_SIZE] __aligned(__alignof__(u32));
++ int i;
++
++ if (keylen > BLAKE2S_BLOCK_SIZE) {
++ blake2s_init(&state, BLAKE2S_HASH_SIZE);
++ blake2s_update(&state, key, keylen);
++ blake2s_final(&state, x_key);
++ } else
++ memcpy(x_key, key, keylen);
++
++ for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
++ x_key[i] ^= 0x36;
++
++ blake2s_init(&state, BLAKE2S_HASH_SIZE);
++ blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
++ blake2s_update(&state, in, inlen);
++ blake2s_final(&state, i_hash);
++
++ for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
++ x_key[i] ^= 0x5c ^ 0x36;
++
++ blake2s_init(&state, BLAKE2S_HASH_SIZE);
++ blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
++ blake2s_update(&state, i_hash, BLAKE2S_HASH_SIZE);
++ blake2s_final(&state, i_hash);
++
++ memcpy(out, i_hash, BLAKE2S_HASH_SIZE);
++ memzero_explicit(x_key, BLAKE2S_BLOCK_SIZE);
++ memzero_explicit(i_hash, BLAKE2S_HASH_SIZE);
++}
++
+ /* This is Hugo Krawczyk's HKDF:
+ * - https://eprint.iacr.org/2010/264.pdf
+ * - https://tools.ietf.org/html/rfc5869
+@@ -322,14 +357,14 @@ static void kdf(u8 *first_dst, u8 *second_dst, u8 *third_dst, const u8 *data,
+ ((third_len || third_dst) && (!second_len || !second_dst))));
+
+ /* Extract entropy from data into secret */
+- blake2s256_hmac(secret, data, chaining_key, data_len, NOISE_HASH_LEN);
++ hmac(secret, data, chaining_key, data_len, NOISE_HASH_LEN);
+
+ if (!first_dst || !first_len)
+ goto out;
+
+ /* Expand first key: key = secret, data = 0x1 */
+ output[0] = 1;
+- blake2s256_hmac(output, output, secret, 1, BLAKE2S_HASH_SIZE);
++ hmac(output, output, secret, 1, BLAKE2S_HASH_SIZE);
+ memcpy(first_dst, output, first_len);
+
+ if (!second_dst || !second_len)
+@@ -337,8 +372,7 @@ static void kdf(u8 *first_dst, u8 *second_dst, u8 *third_dst, const u8 *data,
+
+ /* Expand second key: key = secret, data = first-key || 0x2 */
+ output[BLAKE2S_HASH_SIZE] = 2;
+- blake2s256_hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1,
+- BLAKE2S_HASH_SIZE);
++ hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE);
+ memcpy(second_dst, output, second_len);
+
+ if (!third_dst || !third_len)
+@@ -346,8 +380,7 @@ static void kdf(u8 *first_dst, u8 *second_dst, u8 *third_dst, const u8 *data,
+
+ /* Expand third key: key = secret, data = second-key || 0x3 */
+ output[BLAKE2S_HASH_SIZE] = 3;
+- blake2s256_hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1,
+- BLAKE2S_HASH_SIZE);
++ hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE);
+ memcpy(third_dst, output, third_len);
+
+ out:
diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c
-index 48e7b982a3073..1de413b19e342 100644
+index 48e7b982a3073..8084e7408c0ae 100644
--- a/drivers/net/wireguard/queueing.c
+++ b/drivers/net/wireguard/queueing.c
-@@ -38,11 +38,11 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
+@@ -4,6 +4,7 @@
+ */
+
+ #include "queueing.h"
++#include <linux/skb_array.h>
+
+ struct multicore_worker __percpu *
+ wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr)
+@@ -38,11 +39,11 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
return 0;
}
@@ -90092,7 +132025,7 @@ index 48e7b982a3073..1de413b19e342 100644
- WARN_ON(!__ptr_ring_empty(&queue->ring));
- ptr_ring_cleanup(&queue->ring, NULL);
+ WARN_ON(!purge && !__ptr_ring_empty(&queue->ring));
-+ ptr_ring_cleanup(&queue->ring, purge ? (void(*)(void*))kfree_skb : NULL);
++ ptr_ring_cleanup(&queue->ring, purge ? __skb_array_destroy_skb : NULL);
}
#define NEXT(skb) ((skb)->prev)
@@ -90202,10 +132135,36 @@ index 7dc84bcca2613..7b8df406c7737 100644
}
case cpu_to_le32(MESSAGE_DATA):
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
-index 8c496b7471082..6f07b949cb81d 100644
+index 8c496b7471082..0414d7a6ce741 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
-@@ -308,7 +308,7 @@ void wg_socket_clear_peer_endpoint_src(struct wg_peer *peer)
+@@ -160,6 +160,7 @@ out:
+ rcu_read_unlock_bh();
+ return ret;
+ #else
++ kfree_skb(skb);
+ return -EAFNOSUPPORT;
+ #endif
+ }
+@@ -241,7 +242,7 @@ int wg_socket_endpoint_from_skb(struct endpoint *endpoint,
+ endpoint->addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
+ endpoint->src4.s_addr = ip_hdr(skb)->daddr;
+ endpoint->src_if4 = skb->skb_iif;
+- } else if (skb->protocol == htons(ETH_P_IPV6)) {
++ } else if (IS_ENABLED(CONFIG_IPV6) && skb->protocol == htons(ETH_P_IPV6)) {
+ endpoint->addr6.sin6_family = AF_INET6;
+ endpoint->addr6.sin6_port = udp_hdr(skb)->source;
+ endpoint->addr6.sin6_addr = ipv6_hdr(skb)->saddr;
+@@ -284,7 +285,7 @@ void wg_socket_set_peer_endpoint(struct wg_peer *peer,
+ peer->endpoint.addr4 = endpoint->addr4;
+ peer->endpoint.src4 = endpoint->src4;
+ peer->endpoint.src_if4 = endpoint->src_if4;
+- } else if (endpoint->addr.sa_family == AF_INET6) {
++ } else if (IS_ENABLED(CONFIG_IPV6) && endpoint->addr.sa_family == AF_INET6) {
+ peer->endpoint.addr6 = endpoint->addr6;
+ peer->endpoint.src6 = endpoint->src6;
+ } else {
+@@ -308,7 +309,7 @@ void wg_socket_clear_peer_endpoint_src(struct wg_peer *peer)
{
write_lock_bh(&peer->endpoint_lock);
memset(&peer->endpoint.src6, 0, sizeof(peer->endpoint.src6));
@@ -90605,7 +132564,7 @@ index b746052737e0b..eb705214f3f0a 100644
static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
-index ea00fbb156015..9513ab696fff1 100644
+index ea00fbb156015..f79dd9a716906 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -12,6 +12,7 @@
@@ -90691,6 +132650,19 @@ index ea00fbb156015..9513ab696fff1 100644
static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)
{
struct device *dev = ar->dev;
+@@ -1487,11 +1556,11 @@ static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (node) {
+ ret = of_address_to_resource(node, 0, &r);
++ of_node_put(node);
+ if (ret) {
+ dev_err(dev, "failed to resolve msa fixed region\n");
+ return ret;
+ }
+- of_node_put(node);
+
+ ar->msa.paddr = r.start;
+ ar->msa.mem_size = resource_size(&r);
@@ -1740,10 +1809,17 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_fw_deinit;
}
@@ -90822,8 +132794,31 @@ index 41c1a3d339c25..01bfd09a9d88c 100644
u32 max_antenna_gain;
u32 reg_class_id;
enum wmi_phy_mode mode;
+diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
+index 7d65c115669fe..20b9aa8ddf7d5 100644
+--- a/drivers/net/wireless/ath/ath10k/wow.c
++++ b/drivers/net/wireless/ath/ath10k/wow.c
+@@ -337,14 +337,15 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
+ if (patterns[i].mask[j / 8] & BIT(j % 8))
+ bitmask[j] = 0xff;
+ old_pattern.mask = bitmask;
+- new_pattern = old_pattern;
+
+ if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) {
+- if (patterns[i].pkt_offset < ETH_HLEN)
++ if (patterns[i].pkt_offset < ETH_HLEN) {
+ ath10k_wow_convert_8023_to_80211(&new_pattern,
+ &old_pattern);
+- else
++ } else {
++ new_pattern = old_pattern;
+ new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
++ }
+ }
+
+ if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
-index 8c9c781afc3e5..3fb0aa0008259 100644
+index 8c9c781afc3e5..24bd0520926bf 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -175,8 +175,11 @@ static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
@@ -90888,6 +132883,15 @@ index 8c9c781afc3e5..3fb0aa0008259 100644
ath11k_ahb_ext_grp_enable(irq_grp);
}
}
+@@ -385,6 +391,8 @@ static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
+
+ for (j = 0; j < irq_grp->num_irq; j++)
+ free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
++
++ netif_napi_del(&irq_grp->napi);
+ }
+ }
+
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 969bf1a590d99..7dcf6b13f7949 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
@@ -91199,7 +133203,7 @@ index d9596903b0a58..3e92cc7cfe4c9 100644
.rx_mon_status = {
0, 0, 0, 0,
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
-index e9b3689331ec2..3834be1587057 100644
+index e9b3689331ec2..07004564a3ec5 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1,6 +1,7 @@
@@ -91226,7 +133230,42 @@ index e9b3689331ec2..3834be1587057 100644
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
-@@ -2576,9 +2581,12 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
+@@ -2151,6 +2156,19 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
+ if (ret)
+ ath11k_warn(ar->ab, "failed to update bcn template: %d\n",
+ ret);
++ if (vif->bss_conf.he_support) {
++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
++ WMI_VDEV_PARAM_BA_MODE,
++ WMI_BA_MODE_BUFFER_SIZE_256);
++ if (ret)
++ ath11k_warn(ar->ab,
++ "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
++ arvif->vdev_id);
++ else
++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
++ "Set BA BUFFER SIZE 256 for VDEV: %d\n",
++ arvif->vdev_id);
++ }
+ }
+
+ if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
+@@ -2186,14 +2204,6 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
+
+ if (arvif->is_up && vif->bss_conf.he_support &&
+ vif->bss_conf.he_oper.params) {
+- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+- WMI_VDEV_PARAM_BA_MODE,
+- WMI_BA_MODE_BUFFER_SIZE_256);
+- if (ret)
+- ath11k_warn(ar->ab,
+- "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
+- arvif->vdev_id);
+-
+ param_id = WMI_VDEV_PARAM_HEOPS_0_31;
+ param_value = vif->bss_conf.he_oper.params;
+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+@@ -2576,9 +2586,12 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg.scan_id = ATH11K_SCAN_ID;
if (req->ie_len) {
@@ -91241,7 +133280,7 @@ index e9b3689331ec2..3834be1587057 100644
}
if (req->n_ssids) {
-@@ -2655,9 +2663,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
+@@ -2655,9 +2668,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
return 0;
if (cmd == DISABLE_KEY) {
@@ -91252,7 +133291,7 @@ index e9b3689331ec2..3834be1587057 100644
arg.key_data = NULL;
goto install;
}
-@@ -2789,7 +2795,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+@@ -2789,7 +2800,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* flush the fragments cache during key (re)install to
* ensure all frags in the new frag list belong to the same key.
*/
@@ -91261,7 +133300,7 @@ index e9b3689331ec2..3834be1587057 100644
ath11k_peer_frags_flush(ar, peer);
spin_unlock_bh(&ab->base_lock);
-@@ -4131,23 +4137,32 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
+@@ -4131,23 +4142,32 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
return 0;
}
@@ -91300,7 +133339,7 @@ index e9b3689331ec2..3834be1587057 100644
return 0;
}
-@@ -4156,17 +4171,10 @@ static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
+@@ -4156,17 +4176,10 @@ static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
{
struct ieee80211_vif *vif = ctx;
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
@@ -91320,7 +133359,7 @@ index e9b3689331ec2..3834be1587057 100644
return 0;
}
-@@ -4181,6 +4189,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
+@@ -4181,6 +4194,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
int buf_id;
int ret;
@@ -91329,7 +133368,7 @@ index e9b3689331ec2..3834be1587057 100644
spin_lock_bh(&ar->txmgmt_idr_lock);
buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
ATH11K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
-@@ -6590,7 +6600,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
+@@ -6590,7 +6605,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
/* Apply the regd received during initialization */
@@ -91339,9 +133378,18 @@ index e9b3689331ec2..3834be1587057 100644
ath11k_err(ar->ab, "ath11k regd update failed: %d\n", ret);
goto err_unregister_hw;
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
-index 26c7ae242db67..49c0b1ad40a02 100644
+index 26c7ae242db67..f2149241fb131 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
+@@ -519,7 +519,7 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
+ ret = 0;
+ break;
+ case ATH11K_MHI_POWER_ON:
+- ret = mhi_async_power_up(ab_pci->mhi_ctrl);
++ ret = mhi_sync_power_up(ab_pci->mhi_ctrl);
+ break;
+ case ATH11K_MHI_POWER_OFF:
+ mhi_power_down(ab_pci->mhi_ctrl, true);
@@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
break;
@@ -91356,7 +133404,7 @@ index 26c7ae242db67..49c0b1ad40a02 100644
case ATH11K_MHI_TRIGGER_RDDM:
ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
-index 5abb38cc3b55f..54ce08f1c6e0c 100644
+index 5abb38cc3b55f..353a2d669fcd5 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -632,8 +632,11 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
@@ -91409,6 +133457,30 @@ index 5abb38cc3b55f..54ce08f1c6e0c 100644
ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
&soc_hw_version_minor);
switch (soc_hw_version_major) {
+@@ -1366,6 +1382,11 @@ static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
+ struct ath11k_base *ab = dev_get_drvdata(dev);
+ int ret;
+
++ if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci suspend as qmi is not initialised\n");
++ return 0;
++ }
++
+ ret = ath11k_core_suspend(ab);
+ if (ret)
+ ath11k_warn(ab, "failed to suspend core: %d\n", ret);
+@@ -1378,6 +1399,11 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
+ struct ath11k_base *ab = dev_get_drvdata(dev);
+ int ret;
+
++ if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci resume as qmi is not initialised\n");
++ return 0;
++ }
++
+ ret = ath11k_core_resume(ab);
+ if (ret)
+ ath11k_warn(ab, "failed to resume core: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index b5e34d670715e..e4a65513a1bfd 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
@@ -91798,6 +133870,20 @@ index d35c47e0b19d4..0b7d337b36930 100644
} __packed;
#define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0
+diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
+index 1fbc2c19848f2..d444b3d70ba2e 100644
+--- a/drivers/net/wireless/ath/ath5k/eeprom.c
++++ b/drivers/net/wireless/ath/ath5k/eeprom.c
+@@ -746,6 +746,9 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
+ }
+ }
+
++ if (idx == AR5K_EEPROM_N_PD_CURVES)
++ goto err_out;
++
+ ee->ee_pd_gains[mode] = 1;
+
+ pd = &chinfo[pier].pd_curves[idx];
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 5372e948e761d..aba70f35e574b 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
@@ -91899,8 +133985,31 @@ index 8e69e8989f6d3..6a850a0bfa8ad 100644
return 0;
err:
+diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
+index 510e61e97dbcb..994ec48b2f669 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
++++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
+@@ -30,6 +30,7 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
+ hdr->endpoint_id = epid;
+ hdr->flags = flags;
+ hdr->payload_len = cpu_to_be16(len);
++ memset(hdr->control, 0, sizeof(hdr->control));
+
+ status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
+
+@@ -272,6 +273,10 @@ int htc_connect_service(struct htc_target *target,
+ conn_msg->dl_pipeid = endpoint->dl_pipeid;
+ conn_msg->ul_pipeid = endpoint->ul_pipeid;
+
++ /* To prevent infoleak */
++ conn_msg->svc_meta_len = 0;
++ conn_msg->pad = 0;
++
+ ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
+ if (ret)
+ goto err;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
-index 139831539da37..98090e40e1cf4 100644
+index 139831539da37..e2791d45f5f59 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -533,8 +533,10 @@ irqreturn_t ath_isr(int irq, void *dev)
@@ -91915,6 +134024,15 @@ index 139831539da37..98090e40e1cf4 100644
/*
* If there are no status bits set, then this interrupt was not
+@@ -837,7 +839,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+- fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
++ fi = (struct ath_frame_info *)&txinfo->status.status_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index fe29ad4b9023c..f315c54bd3ac0 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
@@ -91930,6 +134048,91 @@ index fe29ad4b9023c..f315c54bd3ac0 100644
spin_lock_bh(&priv->tx.tx_lock);
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
spin_unlock_bh(&priv->tx.tx_lock);
+diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
+index 5691bd6eb82c2..6555abf02f18b 100644
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -141,8 +141,8 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
+ {
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ BUILD_BUG_ON(sizeof(struct ath_frame_info) >
+- sizeof(tx_info->rate_driver_data));
+- return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
++ sizeof(tx_info->status.status_driver_data));
++ return (struct ath_frame_info *) &tx_info->status.status_driver_data[0];
+ }
+
+ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
+@@ -2501,6 +2501,16 @@ skip_tx_complete:
+ spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
+ }
+
++static void ath_clear_tx_status(struct ieee80211_tx_info *tx_info)
++{
++ void *ptr = &tx_info->status;
++
++ memset(ptr + sizeof(tx_info->status.rates), 0,
++ sizeof(tx_info->status) -
++ sizeof(tx_info->status.rates) -
++ sizeof(tx_info->status.status_driver_data));
++}
++
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_status *ts, int nframes, int nbad,
+ int txok)
+@@ -2512,6 +2522,8 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_hw *ah = sc->sc_ah;
+ u8 i, tx_rateindex;
+
++ ath_clear_tx_status(tx_info);
++
+ if (txok)
+ tx_info->status.ack_signal = ts->ts_rssi;
+
+@@ -2526,6 +2538,13 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+ tx_info->status.ampdu_len = nframes;
+ tx_info->status.ampdu_ack_len = nframes - nbad;
+
++ tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
++
++ for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
++ tx_info->status.rates[i].count = 0;
++ tx_info->status.rates[i].idx = -1;
++ }
++
+ if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+ (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
+ /*
+@@ -2547,16 +2566,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+ tx_info->status.rates[tx_rateindex].count =
+ hw->max_rate_tries;
+ }
+-
+- for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
+- tx_info->status.rates[i].count = 0;
+- tx_info->status.rates[i].idx = -1;
+- }
+-
+- tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
+-
+- /* we report airtime in ath_tx_count_airtime(), don't report twice */
+- tx_info->status.tx_time = 0;
+ }
+
+ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
+index cca3b086aa701..a87476383c540 100644
+--- a/drivers/net/wireless/ath/carl9170/main.c
++++ b/drivers/net/wireless/ath/carl9170/main.c
+@@ -1915,7 +1915,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
+ WARN_ON(!(tx_streams >= 1 && tx_streams <=
+ IEEE80211_HT_MCS_TX_MAX_STREAMS));
+
+- tx_params = (tx_streams - 1) <<
++ tx_params |= (tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+
+ carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 80390495ea250..75cb53a3ec15e 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -91951,6 +134154,30 @@ index 80390495ea250..75cb53a3ec15e 100644
}
kfree(cd->detectors);
kfree(cd);
+diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
+index b2400e2417a55..f15e7bd690b5b 100644
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -667,14 +667,14 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
+
+ /*
+ * Some users have reported their EEPROM programmed with
+- * 0x8000 or 0x0 set, this is not a supported regulatory
+- * domain but since we have more than one user with it we
+- * need a solution for them. We default to 0x64, which is
+- * the default Atheros world regulatory domain.
++ * 0x8000 set, this is not a supported regulatory domain
++ * but since we have more than one user with it we need
++ * a solution for them. We default to 0x64, which is the
++ * default Atheros world regulatory domain.
+ */
+ static void ath_regd_sanitize(struct ath_regulatory *reg)
+ {
+- if (reg->current_rd != COUNTRY_ERD_FLAG && reg->current_rd != 0)
++ if (reg->current_rd != COUNTRY_ERD_FLAG)
+ return;
+ printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n");
+ reg->current_rd = 0x64;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 8e1dbfda65386..e1a35c2eadb6c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -92219,7 +134446,7 @@ index 455143c4164ee..de3bca043c2b3 100644
HW_RATE_INDEX_1MBPS = 0x82,
HW_RATE_INDEX_2MBPS = 0x84,
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
-index ec913ec991f3f..cf9e1396bd046 100644
+index ec913ec991f3f..d51a783301359 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -135,7 +135,9 @@ static struct ieee80211_supported_band wcn_band_2ghz = {
@@ -92374,6 +134601,16 @@ index ec913ec991f3f..cf9e1396bd046 100644
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
+@@ -1449,6 +1474,9 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
+ if (iris_node) {
+ if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
+ wcn->rf_id = RF_IRIS_WCN3620;
++ if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
++ of_device_is_compatible(iris_node, "qcom,wcn3660b"))
++ wcn->rf_id = RF_IRIS_WCN3660;
+ if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
+ wcn->rf_id = RF_IRIS_WCN3680;
+ of_node_put(iris_node);
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c
index 2d0780fefd477..2936aaf532738 100644
--- a/drivers/net/wireless/ath/wcn36xx/pmc.c
@@ -92813,10 +135050,18 @@ index 032216e82b2be..b54311ffde9c5 100644
/* 0x48 */
u32 msdu_size:16;
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
-index add6e527e8330..428546a6047f0 100644
+index add6e527e8330..597f740f3c256 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
-@@ -128,7 +128,6 @@ struct wcn36xx_vif {
+@@ -97,6 +97,7 @@ enum wcn36xx_ampdu_state {
+
+ #define RF_UNKNOWN 0x0000
+ #define RF_IRIS_WCN3620 0x3620
++#define RF_IRIS_WCN3660 0x3660
+ #define RF_IRIS_WCN3680 0x3680
+
+ static inline void buff_to_be(u32 *buf, size_t len)
+@@ -128,7 +129,6 @@ struct wcn36xx_vif {
enum wcn36xx_hal_bss_type bss_type;
/* Power management */
@@ -92824,7 +135069,7 @@ index add6e527e8330..428546a6047f0 100644
enum wcn36xx_power_state pw_state;
u8 bss_index;
-@@ -247,6 +246,7 @@ struct wcn36xx {
+@@ -247,6 +247,7 @@ struct wcn36xx {
struct cfg80211_scan_request *scan_req;
bool sw_scan;
u8 sw_scan_opchannel;
@@ -92880,10 +135125,19 @@ index 6d5188b78f2de..0af452dca7664 100644
/* Match for the GPDwin which unfortunately uses somewhat
* generic dmi strings, which is why we test for 4 strings.
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-index 0eb13e5df5177..d99140960a820 100644
+index 0eb13e5df5177..dcbe55b56e437 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -693,7 +693,7 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
+@@ -207,6 +207,8 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
+ size = BRCMF_FW_MAX_NVRAM_SIZE;
+ else
+ size = data_len;
++ /* Add space for properties we may add */
++ size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;
+ /* Alloc for extra 0 byte + roundup by 4 + length field */
+ size += 1 + 3 + sizeof(u32);
+ nvp->nvram = kzalloc(size, GFP_KERNEL);
+@@ -693,7 +695,7 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
{
struct brcmf_fw_item *first = &req->items[0];
struct brcmf_fw *fwctx;
@@ -92892,7 +135146,7 @@ index 0eb13e5df5177..d99140960a820 100644
int ret;
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
-@@ -712,7 +712,9 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
+@@ -712,7 +714,9 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
fwctx->done = fw_cb;
/* First try alternative board-specific path if any */
@@ -92903,6 +135157,180 @@ index 0eb13e5df5177..d99140960a820 100644
if (alt_path) {
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+index 8b149996fc000..3ff4997e1c97a 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -12,6 +12,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/bcma/bcma.h>
+ #include <linux/sched.h>
++#include <linux/io.h>
+ #include <asm/unaligned.h>
+
+ #include <soc.h>
+@@ -59,6 +60,13 @@ BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
+ BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
+ BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
+
++/* firmware config files */
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
++
++/* per-board firmware binaries */
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
++
+ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
+ BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
+ BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
+@@ -447,47 +455,6 @@ brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ }
+
+
+-static void
+-brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+- void *srcaddr, u32 len)
+-{
+- void __iomem *address = devinfo->tcm + mem_offset;
+- __le32 *src32;
+- __le16 *src16;
+- u8 *src8;
+-
+- if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) {
+- if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) {
+- src8 = (u8 *)srcaddr;
+- while (len) {
+- iowrite8(*src8, address);
+- address++;
+- src8++;
+- len--;
+- }
+- } else {
+- len = len / 2;
+- src16 = (__le16 *)srcaddr;
+- while (len) {
+- iowrite16(le16_to_cpu(*src16), address);
+- address += 2;
+- src16++;
+- len--;
+- }
+- }
+- } else {
+- len = len / 4;
+- src32 = (__le32 *)srcaddr;
+- while (len) {
+- iowrite32(le32_to_cpu(*src32), address);
+- address += 4;
+- src32++;
+- len--;
+- }
+- }
+-}
+-
+-
+ static void
+ brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ void *dstaddr, u32 len)
+@@ -1348,6 +1315,18 @@ static void brcmf_pcie_down(struct device *dev)
+ {
+ }
+
++static int brcmf_pcie_preinit(struct device *dev)
++{
++ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
++
++ brcmf_dbg(PCIE, "Enter\n");
++
++ brcmf_pcie_intr_enable(buspub->devinfo);
++ brcmf_pcie_hostready(buspub->devinfo);
++
++ return 0;
++}
+
+ static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
+ {
+@@ -1456,6 +1435,7 @@ static int brcmf_pcie_reset(struct device *dev)
+ }
+
+ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
++ .preinit = brcmf_pcie_preinit,
+ .txdata = brcmf_pcie_tx,
+ .stop = brcmf_pcie_down,
+ .txctl = brcmf_pcie_tx_ctlpkt,
+@@ -1563,8 +1543,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ return err;
+
+ brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
+- brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase,
+- (void *)fw->data, fw->size);
++ memcpy_toio(devinfo->tcm + devinfo->ci->rambase,
++ (void *)fw->data, fw->size);
+
+ resetintr = get_unaligned_le32(fw->data);
+ release_firmware(fw);
+@@ -1578,7 +1558,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
+ address = devinfo->ci->rambase + devinfo->ci->ramsize -
+ nvram_len;
+- brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
++ memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
+ brcmf_fw_nvram_free(nvram);
+ } else {
+ brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
+@@ -1777,6 +1757,8 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
+ ret = brcmf_chip_get_raminfo(devinfo->ci);
+ if (ret) {
+ brcmf_err(bus, "Failed to get RAM info\n");
++ release_firmware(fw);
++ brcmf_fw_nvram_free(nvram);
+ goto fail;
+ }
+
+@@ -1826,9 +1808,6 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
+
+ init_waitqueue_head(&devinfo->mbdata_resp_wait);
+
+- brcmf_pcie_intr_enable(devinfo);
+- brcmf_pcie_hostready(devinfo);
+-
+ ret = brcmf_attach(&devinfo->pdev->dev);
+ if (ret)
+ goto fail;
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+index 8effeb7a7269b..f7961b22e0518 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -557,7 +557,7 @@ enum brcmf_sdio_frmtype {
+ BRCMF_SDIO_FT_SUB,
+ };
+
+-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
++#define SDIOD_DRVSTR_KEY(chip, pmu) (((unsigned int)(chip) << 16) | (pmu))
+
+ /* SDIO Pad drive strength to select value mappings */
+ struct sdiod_drive_str {
+@@ -629,7 +629,6 @@ BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-sdio");
+
+ /* firmware config files */
+ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt");
+-MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
+
+ /* per-board firmware binaries */
+ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin");
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+index 75e7665773c52..90fe4adca4926 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+@@ -304,7 +304,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
+
+ priv->is_open = 1;
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+- return 0;
++ return ret;
+ }
+
+ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 1efac0b2a94d7..9e00d1d7e1468 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -92932,6 +135360,19 @@ index 1efac0b2a94d7..9e00d1d7e1468 100644
}
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+index 6dcafd0a3d4b1..b00cf92c8965a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+@@ -1532,8 +1532,6 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
+ return -EBUSY;
+
+ range->range_data_size = reg->dev_addr.size;
+- iwl_write_prph_no_grab(fwrt->trans, DBGI_SRAM_TARGET_ACCESS_CFG,
+- DBGI_SRAM_TARGET_ACCESS_CFG_RESET_ADDRESS_MSK);
+ for (i = 0; i < (le32_to_cpu(reg->dev_addr.size) / 4); i++) {
+ prph_data = iwl_read_prph(fwrt->trans, (i % 2) ?
+ DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index dde22bdc87039..069fcbc46d2ba 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -93025,6 +135466,19 @@ index cf796403c45c0..c8dff76ac03c1 100644
#define CSR_HW_REV_TYPE_7265D (0x0000210)
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+index 125479b5c0d61..fc4197bf2478e 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+@@ -322,7 +322,7 @@ void iwl_dbg_tlv_del_timers(struct iwl_trans *trans)
+ struct iwl_dbg_tlv_timer_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, timer_list, list) {
+- del_timer(&node->timer);
++ del_timer_sync(&node->timer);
+ list_del(&node->list);
+ kfree(node);
+ }
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 77124b8b235ee..524b0ad873578 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -93142,8 +135596,35 @@ index 2517c4ae07ab3..5e76ab6c8ad0a 100644
}
IWL_EXPORT_SYMBOL(iwl_force_nmi);
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+index 475f951d4b1ef..fc40cca096c26 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+@@ -541,8 +541,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
+ .has_he = true,
+ .he_cap_elem = {
+ .mac_cap_info[0] =
+- IEEE80211_HE_MAC_CAP0_HTC_HE |
+- IEEE80211_HE_MAC_CAP0_TWT_REQ,
++ IEEE80211_HE_MAC_CAP0_HTC_HE,
+ .mac_cap_info[1] =
+ IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
+ IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+index d0a7d58336a9e..6c4f1c949541a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+@@ -350,8 +350,6 @@
+ #define WFPM_GP2 0xA030B4
+
+ /* DBGI SRAM Register details */
+-#define DBGI_SRAM_TARGET_ACCESS_CFG 0x00A2E14C
+-#define DBGI_SRAM_TARGET_ACCESS_CFG_RESET_ADDRESS_MSK 0x10000
+ #define DBGI_SRAM_TARGET_ACCESS_RDATA_LSB 0x00A2E154
+ #define DBGI_SRAM_TARGET_ACCESS_RDATA_MSB 0x00A2E158
+
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
-index 9f706fffb5922..d3013a51a5096 100644
+index 9f706fffb5922..00ca17f3b263c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -2336,7 +2336,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
@@ -93172,6 +135653,26 @@ index 9f706fffb5922..d3013a51a5096 100644
return 1;
}
+@@ -2496,7 +2499,9 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
+
+ /* start pseudo D3 */
+ rtnl_lock();
++ wiphy_lock(mvm->hw->wiphy);
+ err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
++ wiphy_unlock(mvm->hw->wiphy);
+ rtnl_unlock();
+ if (err > 0)
+ err = -EINVAL;
+@@ -2552,7 +2557,9 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
+ iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
+
+ rtnl_lock();
++ wiphy_lock(mvm->hw->wiphy);
+ __iwl_mvm_resume(mvm, true);
++ wiphy_unlock(mvm->hw->wiphy);
+ rtnl_unlock();
+
+ iwl_mvm_resume_tcm(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 5dc39fbb74d67..d398a06b26567 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -93229,10 +135730,22 @@ index 03e5bf5cb9094..bb5fff8174435 100644
IWL_DEBUG_INFO(mvm,
"%pM: prev rtt_avg=%lld, new rtt_avg=%lld, rtt=%lld\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
-index 74404c96063bc..bcc032c815dcb 100644
+index 74404c96063bc..6d439ae7b50b1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
-@@ -1572,7 +1572,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
+@@ -1489,8 +1489,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
+ while (!sband && i < NUM_NL80211_BANDS)
+ sband = mvm->hw->wiphy->bands[i++];
+
+- if (WARN_ON_ONCE(!sband))
++ if (WARN_ON_ONCE(!sband)) {
++ ret = -ENODEV;
+ goto error;
++ }
+
+ chan = &sband->channels[0];
+
+@@ -1572,7 +1574,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
ret = iwl_mvm_sar_init(mvm);
if (ret == 0)
ret = iwl_mvm_sar_geo_init(mvm);
@@ -93242,7 +135755,7 @@ index 74404c96063bc..bcc032c815dcb 100644
iwl_mvm_tas_init(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
-index 3a4585222d6d4..750217393f480 100644
+index 3a4585222d6d4..56c7a68a6491c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -16,6 +16,7 @@
@@ -93253,7 +135766,15 @@ index 3a4585222d6d4..750217393f480 100644
#include "iwl-op-mode.h"
#include "iwl-io.h"
#include "mvm.h"
-@@ -1116,9 +1117,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
+@@ -294,7 +295,6 @@ static const u8 he_if_types_ext_capa_sta[] = {
+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+- [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
+ };
+
+ static const struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
+@@ -1116,9 +1116,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -93285,7 +135806,7 @@ index 3a4585222d6d4..750217393f480 100644
mutex_unlock(&mvm->mutex);
return ret;
-@@ -1665,6 +1687,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
+@@ -1665,6 +1686,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
struct iwl_mvm_mc_iter_data iter_data = {
.mvm = mvm,
};
@@ -93293,7 +135814,7 @@ index 3a4585222d6d4..750217393f480 100644
lockdep_assert_held(&mvm->mutex);
-@@ -1674,6 +1697,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
+@@ -1674,6 +1696,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_mc_iface_iterator, &iter_data);
@@ -93338,10 +135859,20 @@ index f877d86b038e3..46af8dd2dc930 100644
/* Keep track of completed init configuration */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
-index 77ea2d0a30916..49c32a8132a0f 100644
+index 77ea2d0a30916..c77d98c888116 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
-@@ -687,6 +687,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
+@@ -238,7 +238,8 @@ static void iwl_mvm_rx_thermal_dual_chain_req(struct iwl_mvm *mvm,
+ */
+ mvm->fw_static_smps_request =
+ req->event == cpu_to_le32(THERMAL_DUAL_CHAIN_REQ_DISABLE);
+- ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
++ ieee80211_iterate_interfaces(mvm->hw,
++ IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER,
+ iwl_mvm_intf_dual_chain_req, NULL);
+ }
+
+@@ -687,6 +688,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
int ret;
rtnl_lock();
@@ -93349,7 +135880,7 @@ index 77ea2d0a30916..49c32a8132a0f 100644
mutex_lock(&mvm->mutex);
ret = iwl_run_init_mvm_ucode(mvm);
-@@ -702,6 +703,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
+@@ -702,6 +704,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
iwl_mvm_stop_device(mvm);
mutex_unlock(&mvm->mutex);
@@ -93357,7 +135888,7 @@ index 77ea2d0a30916..49c32a8132a0f 100644
rtnl_unlock();
if (ret < 0)
-@@ -1424,6 +1426,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
+@@ -1424,6 +1427,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
*/
if (!mvm->fw_restart && fw_error) {
iwl_fw_error_collect(&mvm->fwrt, false);
@@ -93367,6 +135898,58 @@ index 77ea2d0a30916..49c32a8132a0f 100644
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
struct iwl_mvm_reprobe *reprobe;
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+index 035336a9e755e..6d82725cb87d0 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
++ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2017 Intel Deutschland GmbH
+ */
+@@ -295,18 +295,31 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
+ * otherwise we might not be able to reuse this phy.
+ */
+ if (ctxt->ref == 0) {
+- struct ieee80211_channel *chan;
++ struct ieee80211_channel *chan = NULL;
+ struct cfg80211_chan_def chandef;
+- struct ieee80211_supported_band *sband = NULL;
+- enum nl80211_band band = NL80211_BAND_2GHZ;
++ struct ieee80211_supported_band *sband;
++ enum nl80211_band band;
++ int channel;
+
+- while (!sband && band < NUM_NL80211_BANDS)
+- sband = mvm->hw->wiphy->bands[band++];
++ for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
++ sband = mvm->hw->wiphy->bands[band];
+
+- if (WARN_ON(!sband))
+- return;
++ if (!sband)
++ continue;
++
++ for (channel = 0; channel < sband->n_channels; channel++)
++ if (!(sband->channels[channel].flags &
++ IEEE80211_CHAN_DISABLED)) {
++ chan = &sband->channels[channel];
++ break;
++ }
+
+- chan = &sband->channels[0];
++ if (chan)
++ break;
++ }
++
++ if (WARN_ON(!chan))
++ return;
+
+ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+ iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index c12f303cf652c..efccdd3f33773 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -93412,10 +135995,22 @@ index c12f303cf652c..efccdd3f33773 100644
* If not, only pull ieee80211_hdr (including crypto if present, and
* an additional 8 bytes for SNAP/ethertype, see below) so that
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
-index d78e436fa8b53..5461bf3999593 100644
+index d78e436fa8b53..65e382756de68 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
-@@ -1924,22 +1924,19 @@ static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm,
+@@ -1890,7 +1890,10 @@ static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
+
+ /* set fragmented ebs for fragmented scan on HB channels */
+- if (iwl_mvm_is_scan_fragmented(params->hb_type))
++ if ((!iwl_mvm_is_cdb_supported(mvm) &&
++ iwl_mvm_is_scan_fragmented(params->type)) ||
++ (iwl_mvm_is_cdb_supported(mvm) &&
++ iwl_mvm_is_scan_fragmented(params->hb_type)))
+ flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;
+
+ return flags;
+@@ -1924,22 +1927,19 @@ static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm,
}
/*
@@ -93447,7 +136042,7 @@ index d78e436fa8b53..5461bf3999593 100644
return;
}
-@@ -2490,7 +2487,7 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
+@@ -2490,7 +2490,7 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
return -EIO;
}
@@ -93553,10 +136148,10 @@ index e91f8e889df70..ab06dcda1462a 100644
te_data->vif = vif;
spin_unlock_bh(&mvm->time_event_lock);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
-index 0a13c2bda2eed..06fbd9ab37dfe 100644
+index 0a13c2bda2eed..b5368cb57ca8c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
-@@ -268,17 +268,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
+@@ -268,7 +268,6 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
int rate_idx = -1;
u8 rate_plcp;
u32 rate_flags = 0;
@@ -93564,16 +136159,13 @@ index 0a13c2bda2eed..06fbd9ab37dfe 100644
/* info->control is only relevant for non HW rate control */
if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
-+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-+
- /* HT rate doesn't make sense for a non data frame */
- WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_data(fc),
+@@ -278,7 +277,8 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
"Got a HT rate (flags:0x%x/mcs:%d/fc:0x%x/state:%d) for a non data frame\n",
info->control.rates[0].flags,
info->control.rates[0].idx,
- le16_to_cpu(fc), mvmsta->sta_state);
-+ le16_to_cpu(fc), sta ? mvmsta->sta_state : -1);
++ le16_to_cpu(fc),
++ sta ? iwl_mvm_sta_from_mac80211(sta)->sta_state : -1);
rate_idx = info->control.rates[0].idx;
}
@@ -93675,18 +136267,20 @@ index 451b060693501..0f3526b0c5b00 100644
if (txq->entries && cmd_queue)
for (i = 0; i < slots_num; i++)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
-index 0adae76eb8df1..0aeb1e1ec93ff 100644
+index 0adae76eb8df1..c3189e2c7c93a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
-@@ -2336,6 +2336,15 @@ static void hw_scan_work(struct work_struct *work)
+@@ -2336,9 +2336,21 @@ static void hw_scan_work(struct work_struct *work)
if (req->ie_len)
skb_put_data(probe, req->ie, req->ie_len);
++ rcu_read_lock();
+ if (!ieee80211_tx_prepare_skb(hwsim->hw,
+ hwsim->hw_scan_vif,
+ probe,
+ hwsim->tmp_chan->band,
+ NULL)) {
++ rcu_read_unlock();
+ kfree_skb(probe);
+ continue;
+ }
@@ -93694,7 +136288,11 @@ index 0adae76eb8df1..0aeb1e1ec93ff 100644
local_bh_disable();
mac80211_hwsim_tx_frame(hwsim->hw, probe,
hwsim->tmp_chan);
-@@ -3641,6 +3650,10 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
++ rcu_read_unlock();
+ local_bh_enable();
+ }
+ }
+@@ -3641,6 +3653,10 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
}
txi->flags |= IEEE80211_TX_STAT_ACK;
}
@@ -94019,10 +136617,31 @@ index fa48cc3a7a8f7..ad97308c78534 100644
}
-EXPORT_SYMBOL_GPL(mt76_register_debugfs);
+EXPORT_SYMBOL_GPL(mt76_register_debugfs_fops);
+diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
+index 5e1c1506a4c65..7aecde35cb9a3 100644
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -465,6 +465,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+
+ qbuf.addr = addr + offset;
+ qbuf.len = len - offset;
++ qbuf.skip_unmap = false;
+ mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, NULL);
+ frames++;
+ }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
-index 25c5ceef52577..4d01fd85283df 100644
+index 25c5ceef52577..6e4d697159279 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -19,7 +19,7 @@
+
+ #define MT_MCU_RING_SIZE 32
+ #define MT_RX_BUF_SIZE 2048
+-#define MT_SKB_HEAD_LEN 128
++#define MT_SKB_HEAD_LEN 256
+
+ #define MT_MAX_NON_AQL_PKT 16
+ #define MT_TXQ_FREE_THR 32
@@ -869,7 +869,13 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
int mt76_register_phy(struct mt76_phy *phy, bool vht,
struct ieee80211_rate *rates, int n_rates);
@@ -94053,6 +136672,20 @@ index 3972c56136a20..65f1f2bb80835 100644
if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
!(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {
status->flag |= RX_FLAG_DECRYPTED;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+index 8edea1e7a602f..7f52a4a11ceaa 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+@@ -620,6 +620,9 @@ mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
+ int i;
+
++ if (!sta_rates)
++ return;
++
+ spin_lock_bh(&dev->mt76.lock);
+ for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
+ msta->rates[i].idx = sta_rates->rate[i].idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
index cb4659771fd97..bda22ca0bd714 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
@@ -94122,7 +136755,7 @@ index 2f1ac644e018e..47f23ac905a3c 100644
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
-index ff3f85e4087c9..f2704149834a0 100644
+index ff3f85e4087c9..8f4a5d4929e09 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -286,9 +286,16 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
@@ -94219,7 +136852,31 @@ index ff3f85e4087c9..f2704149834a0 100644
static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
{
struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data;
-@@ -2026,16 +2045,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
+@@ -1713,7 +1732,7 @@ mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy,
+ struct mt7615_dev *dev = phy->dev;
+ int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck;
+ bool ext_phy = phy != &dev->phy;
+- u16 def_th = ofdm ? -98 : -110;
++ s16 def_th = ofdm ? -98 : -110;
+ bool update = false;
+ s8 *sensitivity;
+ int signal;
+@@ -1981,6 +2000,14 @@ void mt7615_pm_power_save_work(struct work_struct *work)
+ test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state))
+ goto out;
+
++ if (mutex_is_locked(&dev->mt76.mutex))
++ /* if mt76 mutex is held we should not put the device
++ * to sleep since we are currently accessing device
++ * register map. We need to wait for the next power_save
++ * trigger.
++ */
++ goto out;
++
+ if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
+ delta = dev->pm.last_activity + delta - jiffies;
+ goto out;
+@@ -2026,16 +2053,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
int id;
spin_lock_bh(&dev->mt76.token_lock);
@@ -94239,7 +136896,7 @@ index ff3f85e4087c9..f2704149834a0 100644
idr_destroy(&dev->mt76.token);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
-index dada43d6d879e..fc266da54fe7b 100644
+index dada43d6d879e..60a41d0829611 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -135,8 +135,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
@@ -94275,6 +136932,16 @@ index dada43d6d879e..fc266da54fe7b 100644
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
+@@ -684,6 +682,9 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,
+ struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
+ int i;
+
++ if (!sta_rates)
++ return;
++
+ spin_lock_bh(&dev->mt76.lock);
+ for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
+ msta->rates[i].idx = sta_rates->rate[i].idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index f8a09692d3e4c..4fed3afad67cc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -94364,9 +137031,18 @@ index a2465b49ecd0c..87b4aa52ee0f9 100644
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
-index 5c3a81e5f559d..d25b50e769328 100644
+index 5c3a81e5f559d..017bd59c4ea80 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+@@ -295,7 +295,7 @@ mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid,
+ }
+
+ if (sta_hdr)
+- sta_hdr->len = cpu_to_le16(sizeof(hdr));
++ le16_add_cpu(&sta_hdr->len, sizeof(hdr));
+
+ return skb_put_data(nskb, &hdr, sizeof(hdr));
+ }
@@ -689,7 +689,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (ht_cap->ht_supported)
mode |= PHY_TYPE_BIT_HT;
@@ -94527,6 +137203,19 @@ index c32e6dc687739..07b21b2085823 100644
txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf,
max_txpwr_adj);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+index adf288e50e212..5cd0379d86de8 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+@@ -80,7 +80,7 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9);
+
+ /* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */
+- mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf);
++ mt76_rmw_field(dev, 0x15a0c, 0xfU << 28, 0xf);
+
+ /* RG_SSUSB_CDR_BR_PE1D = 0x3 */
+ mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 4798d6344305d..b171027e0cfa8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -94557,7 +137246,7 @@ index 4798d6344305d..b171027e0cfa8 100644
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
-index 2462704094b0a..ff613d7056119 100644
+index 2462704094b0a..7691292526e05 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -349,9 +349,16 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -94578,7 +137267,15 @@ index 2462704094b0a..ff613d7056119 100644
status->wcid = mt7915_rx_get_wcid(dev, idx, unicast);
if (status->wcid) {
-@@ -1232,7 +1239,7 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
+@@ -892,6 +899,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
+ val = MT_TXD3_SN_VALID |
+ FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
+ txwi[3] |= cpu_to_le32(val);
++ txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
+ }
+
+ val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
+@@ -1232,7 +1240,7 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
goto out;
info = IEEE80211_SKB_CB(skb);
@@ -94602,7 +137299,7 @@ index eb1885f4bd8eb..fee7741b5d421 100644
#define MT_TXP_MAX_BUF_NUM 6
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
-index 43960770a9af2..7440f2b443eca 100644
+index 43960770a9af2..e9d854e3293e4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
@@ -94659,7 +137356,44 @@ index 43960770a9af2..7440f2b443eca 100644
return -EOPNOTSUPP;
sec_key = &sec->key[0];
-@@ -2790,7 +2790,7 @@ out:
+@@ -1396,8 +1396,11 @@ mt7915_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ generic = (struct wtbl_generic *)tlv;
+
+ if (sta) {
++ if (vif->type == NL80211_IFTYPE_STATION)
++ generic->partial_aid = cpu_to_le16(vif->bss_conf.aid);
++ else
++ generic->partial_aid = cpu_to_le16(sta->aid);
+ memcpy(generic->peer_addr, sta->addr, ETH_ALEN);
+- generic->partial_aid = cpu_to_le16(sta->aid);
+ generic->muar_idx = mvif->omac_idx;
+ generic->qos = sta->wme;
+ } else {
+@@ -1451,12 +1454,15 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_AP:
+ basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA);
++ basic->aid = cpu_to_le16(sta->aid);
+ break;
+ case NL80211_IFTYPE_STATION:
+ basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP);
++ basic->aid = cpu_to_le16(vif->bss_conf.aid);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);
++ basic->aid = cpu_to_le16(sta->aid);
+ break;
+ default:
+ WARN_ON(1);
+@@ -1464,7 +1470,6 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ }
+
+ memcpy(basic->peer_addr, sta->addr, ETH_ALEN);
+- basic->aid = cpu_to_le16(sta->aid);
+ basic->qos = sta->wme;
+ }
+
+@@ -2790,7 +2795,7 @@ out:
default:
ret = -EAGAIN;
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
@@ -94668,7 +137402,7 @@ index 43960770a9af2..7440f2b443eca 100644
}
release_firmware(fw);
-@@ -3391,20 +3391,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
+@@ -3391,20 +3396,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
{
@@ -94693,7 +137427,7 @@ index 43960770a9af2..7440f2b443eca 100644
eep_len = MT7915_EEPROM_SIZE % PER_PAGE_SIZE;
else
eep_len = PER_PAGE_SIZE;
-@@ -3414,7 +3414,7 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
+@@ -3414,7 +3419,7 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
if (!skb)
return -ENOMEM;
@@ -94702,7 +137436,7 @@ index 43960770a9af2..7440f2b443eca 100644
FIELD_PREP(PAGE_IDX_MASK, i) | EE_FORMAT_WHOLE;
req.len = cpu_to_le16(eep_len);
-@@ -3481,7 +3481,7 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
+@@ -3481,7 +3486,7 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
u8 idx;
u8 rsv[4];
__le32 len;
@@ -94712,7 +137446,7 @@ index 43960770a9af2..7440f2b443eca 100644
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
-index 77468bdae460b..30f3b3085c786 100644
+index 77468bdae460b..8d5e261cd10f6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -4,6 +4,32 @@
@@ -94766,17 +137500,35 @@ index 77468bdae460b..30f3b3085c786 100644
for (i = 0; i < ARRAY_SIZE(stat); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ",
i + 1, stat[i]);
-@@ -98,6 +128,8 @@ mt7921_queues_acq(struct seq_file *s, void *data)
+@@ -98,25 +128,28 @@ mt7921_queues_acq(struct seq_file *s, void *data)
struct mt7921_dev *dev = dev_get_drvdata(s->private);
int i;
+- for (i = 0; i < 16; i++) {
+- int j, acs = i / 4, index = i % 4;
+ mt7921_mutex_acquire(dev);
+
- for (i = 0; i < 16; i++) {
- int j, acs = i / 4, index = i % 4;
++ for (i = 0; i < 4; i++) {
u32 ctrl, val, qlen = 0;
-@@ -117,6 +149,8 @@ mt7921_queues_acq(struct seq_file *s, void *data)
- seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
++ int j;
+
+- val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
+- ctrl = BIT(31) | BIT(15) | (acs << 8);
++ val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
++ ctrl = BIT(31) | BIT(11) | (i << 24);
+
+ for (j = 0; j < 32; j++) {
+ if (val & BIT(j))
+ continue;
+
+- mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
+- ctrl | (j + (index << 5)));
++ mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
+ qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
+ GENMASK(11, 0));
+ }
+- seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
++ seq_printf(s, "AC%d: queued=%d\n", i, qlen);
}
+ mt7921_mutex_release(dev);
@@ -94784,7 +137536,7 @@ index 77468bdae460b..30f3b3085c786 100644
return 0;
}
-@@ -373,7 +407,7 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
+@@ -373,7 +406,7 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
{
struct dentry *dir;
@@ -94793,6 +137545,141 @@ index 77468bdae460b..30f3b3085c786 100644
if (!dir)
return -ENOMEM;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+index 7d7d43a5422f8..93d0cc1827d26 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+@@ -118,109 +118,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
+ mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
+ }
+
+-static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
+-{
+- static const struct {
+- u32 phys;
+- u32 mapped;
+- u32 size;
+- } fixed_map[] = {
+- { 0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */
+- { 0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */
+- { 0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */
+- { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
+- { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
+- { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
+- { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
+- { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
+- { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
+- { 0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */
+- { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
+- { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
+- { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
+- { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
+- { 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
+- { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
+- { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
+- { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
+- { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
+- { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
+- { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
+- { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
+- { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
+- { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
+- { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
+- { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
+- { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
+- { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
+- { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
+- { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
+- { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
+- { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
+- { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
+- { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
+- { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
+- { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
+- { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
+- { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
+- { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
+- { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
+- { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
+- { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
+- };
+- int i;
+-
+- if (addr < 0x100000)
+- return addr;
+-
+- for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
+- u32 ofs;
+-
+- if (addr < fixed_map[i].phys)
+- continue;
+-
+- ofs = addr - fixed_map[i].phys;
+- if (ofs > fixed_map[i].size)
+- continue;
+-
+- return fixed_map[i].mapped + ofs;
+- }
+-
+- if ((addr >= 0x18000000 && addr < 0x18c00000) ||
+- (addr >= 0x70000000 && addr < 0x78000000) ||
+- (addr >= 0x7c000000 && addr < 0x7c400000))
+- return mt7921_reg_map_l1(dev, addr);
+-
+- dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
+- addr);
+-
+- return 0;
+-}
+-
+-static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
+-{
+- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+- u32 addr = __mt7921_reg_addr(dev, offset);
+-
+- return dev->bus_ops->rr(mdev, addr);
+-}
+-
+-static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+-{
+- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+- u32 addr = __mt7921_reg_addr(dev, offset);
+-
+- dev->bus_ops->wr(mdev, addr, val);
+-}
+-
+-static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+-{
+- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+- u32 addr = __mt7921_reg_addr(dev, offset);
+-
+- return dev->bus_ops->rmw(mdev, addr, mask, val);
+-}
+-
+ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
+ {
+ if (force) {
+@@ -380,20 +277,8 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
+
+ int mt7921_dma_init(struct mt7921_dev *dev)
+ {
+- struct mt76_bus_ops *bus_ops;
+ int ret;
+
+- dev->bus_ops = dev->mt76.bus;
+- bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
+- GFP_KERNEL);
+- if (!bus_ops)
+- return -ENOMEM;
+-
+- bus_ops->rr = mt7921_rr;
+- bus_ops->wr = mt7921_wr;
+- bus_ops->rmw = mt7921_rmw;
+- dev->mt76.bus = bus_ops;
+-
+ mt76_dma_attach(&dev->mt76);
+
+ ret = mt7921_dma_disable(dev, true);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index a9ce10b988273..78a00028137bd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -94827,7 +137714,7 @@ index a9ce10b988273..78a00028137bd 100644
mt7921_mcu_exit(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
-index 7fe2e3a50428f..04a288029c98e 100644
+index 7fe2e3a50428f..c093920a597d1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -180,12 +180,56 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
@@ -94984,6 +137871,21 @@ index 7fe2e3a50428f..04a288029c98e 100644
if (!(frame_type & (IEEE80211_FTYPE_DATA >> 2)))
return;
+@@ -1493,6 +1550,14 @@ void mt7921_pm_power_save_work(struct work_struct *work)
+ test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
+ goto out;
+
++ if (mutex_is_locked(&dev->mt76.mutex))
++ /* if mt76 mutex is held we should not put the device
++ * to sleep since we are currently accessing device
++ * register map. We need to wait for the next power_save
++ * trigger.
++ */
++ goto out;
++
+ if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
+ delta = dev->pm.last_activity + delta - jiffies;
+ goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
index 3af67fac213df..f0194c8780372 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
@@ -95013,10 +137915,18 @@ index 3af67fac213df..f0194c8780372 100644
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-index 63ec140c9c372..9eb90e6f01031 100644
+index 63ec140c9c372..30252f408ddc4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-@@ -285,12 +285,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
+@@ -224,6 +224,7 @@ static void mt7921_stop(struct ieee80211_hw *hw)
+
+ cancel_delayed_work_sync(&dev->pm.ps_work);
+ cancel_work_sync(&dev->pm.wake_work);
++ cancel_work_sync(&dev->reset_work);
+ mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
+
+ mt7921_mutex_acquire(dev);
+@@ -285,12 +286,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
mtxq->wcid = &mvif->sta.wcid;
}
@@ -95030,7 +137940,7 @@ index 63ec140c9c372..9eb90e6f01031 100644
mt7921_mutex_release(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-index 9fbaacc67cfad..506a1909ce6d5 100644
+index 9fbaacc67cfad..4119f8efd896b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -157,6 +157,7 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
@@ -95114,6 +138024,49 @@ index 9fbaacc67cfad..506a1909ce6d5 100644
}
release_firmware(fw);
+@@ -1294,8 +1306,6 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
+
+ int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
+ {
+- struct mt76_phy *mphy = &dev->mt76.phy;
+- struct mt76_connac_pm *pm = &dev->pm;
+ int i, err = 0;
+
+ for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
+@@ -1308,16 +1318,8 @@ int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
+ if (i == MT7921_DRV_OWN_RETRY_COUNT) {
+ dev_err(dev->mt76.dev, "driver own failed\n");
+ err = -EIO;
+- goto out;
+ }
+
+- mt7921_wpdma_reinit_cond(dev);
+- clear_bit(MT76_STATE_PM, &mphy->state);
+-
+- pm->stats.last_wake_event = jiffies;
+- pm->stats.doze_time += pm->stats.last_wake_event -
+- pm->stats.last_doze_event;
+-out:
+ return err;
+ }
+
+@@ -1333,6 +1335,16 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
+ goto out;
+
+ err = __mt7921_mcu_drv_pmctrl(dev);
++ if (err < 0)
++ goto out;
++
++ mt7921_wpdma_reinit_cond(dev);
++ clear_bit(MT76_STATE_PM, &mphy->state);
++
++ pm->stats.last_wake_event = jiffies;
++ pm->stats.doze_time += pm->stats.last_wake_event -
++ pm->stats.last_doze_event;
++
+ out:
+ mutex_unlock(&pm->mutex);
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
index de3c091f67368..42e7271848956 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
@@ -95145,11 +138098,176 @@ index de3c091f67368..42e7271848956 100644
u8 txs[28];
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+index c3905bcab3604..7d9b23a002388 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+@@ -88,6 +88,110 @@ static void mt7921_irq_tasklet(unsigned long data)
+ napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
+ }
+
++static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
++{
++ static const struct {
++ u32 phys;
++ u32 mapped;
++ u32 size;
++ } fixed_map[] = {
++ { 0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */
++ { 0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */
++ { 0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */
++ { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
++ { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
++ { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
++ { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
++ { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
++ { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
++ { 0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */
++ { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
++ { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
++ { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
++ { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
++ { 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
++ { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
++ { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
++ { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
++ { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
++ { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
++ { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
++ { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
++ { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
++ { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
++ { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
++ { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
++ { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
++ { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
++ { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
++ { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
++ { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
++ { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
++ { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
++ { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
++ { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
++ { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
++ { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
++ { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
++ { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
++ { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
++ { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
++ { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
++ };
++ int i;
++
++ if (addr < 0x100000)
++ return addr;
++
++ for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
++ u32 ofs;
++
++ if (addr < fixed_map[i].phys)
++ continue;
++
++ ofs = addr - fixed_map[i].phys;
++ if (ofs > fixed_map[i].size)
++ continue;
++
++ return fixed_map[i].mapped + ofs;
++ }
++
++ if ((addr >= 0x18000000 && addr < 0x18c00000) ||
++ (addr >= 0x70000000 && addr < 0x78000000) ||
++ (addr >= 0x7c000000 && addr < 0x7c400000))
++ return mt7921_reg_map_l1(dev, addr);
++
++ dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
++ addr);
++
++ return 0;
++}
++
++static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
++{
++ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
++ u32 addr = __mt7921_reg_addr(dev, offset);
++
++ return dev->bus_ops->rr(mdev, addr);
++}
++
++static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
++{
++ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
++ u32 addr = __mt7921_reg_addr(dev, offset);
++
++ dev->bus_ops->wr(mdev, addr, val);
++}
++
++static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
++{
++ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
++ u32 addr = __mt7921_reg_addr(dev, offset);
++
++ return dev->bus_ops->rmw(mdev, addr, mask, val);
++}
++
++
+ static int mt7921_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+@@ -110,6 +214,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
+ .sta_remove = mt7921_mac_sta_remove,
+ .update_survey = mt7921_update_channel,
+ };
++ struct mt76_bus_ops *bus_ops;
+ struct mt7921_dev *dev;
+ struct mt76_dev *mdev;
+ int ret;
+@@ -145,6 +250,22 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
+
+ mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
+ tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
++
++ dev->bus_ops = dev->mt76.bus;
++ bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
++ GFP_KERNEL);
++ if (!bus_ops)
++ return -ENOMEM;
++
++ bus_ops->rr = mt7921_rr;
++ bus_ops->wr = mt7921_wr;
++ bus_ops->rmw = mt7921_rmw;
++ dev->mt76.bus = bus_ops;
++
++ ret = __mt7921_mcu_drv_pmctrl(dev);
++ if (ret)
++ return ret;
++
+ mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
+ (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
+ dev_err(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
-index b6944c867a573..26fb118237626 100644
+index b6944c867a573..41c2855e7a3d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
-@@ -96,6 +96,10 @@
+@@ -17,13 +17,12 @@
+ #define MT_PLE_BASE 0x8000
+ #define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
+
+-#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)
+-#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)
+-#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8)
+-#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc)
++#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0)
++#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4)
++#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8)
++#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec)
+
+-#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \
+- ((n) << 2))
++#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
+ #define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
+
+ #define MT_MDP_BASE 0xf000
+@@ -96,6 +95,10 @@
#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800)
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
@@ -95160,7 +138278,7 @@ index b6944c867a573..26fb118237626 100644
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698)
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16)
-@@ -108,9 +112,9 @@
+@@ -108,9 +111,9 @@
#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090)
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
@@ -95244,6 +138362,37 @@ index e4473a5512415..74c3d8cb31002 100644
if (status == -EPROTO || status == -ETIMEDOUT)
rt2x00dev->num_proto_errs++;
else
+diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
+index 0f5009c47cd0a..f8409e93fe33e 100644
+--- a/drivers/net/wireless/ray_cs.c
++++ b/drivers/net/wireless/ray_cs.c
+@@ -382,6 +382,8 @@ static int ray_config(struct pcmcia_device *link)
+ goto failed;
+ local->sram = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
++ if (!local->sram)
++ goto failed;
+
+ /*** Set up 16k window for shared memory (receive buffer) ***************/
+ link->resource[3]->flags |=
+@@ -396,6 +398,8 @@ static int ray_config(struct pcmcia_device *link)
+ goto failed;
+ local->rmem = ioremap(link->resource[3]->start,
+ resource_size(link->resource[3]));
++ if (!local->rmem)
++ goto failed;
+
+ /*** Set up window for attribute memory ***********************************/
+ link->resource[4]->flags |=
+@@ -410,6 +414,8 @@ static int ray_config(struct pcmcia_device *link)
+ goto failed;
+ local->amem = ioremap(link->resource[4]->start,
+ resource_size(link->resource[4]));
++ if (!local->amem)
++ goto failed;
+
+ dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
+ dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
index 585784258c665..4efab907a3ac6 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
@@ -96190,6 +139339,46 @@ index accc991d153f7..dbac4c03d21a1 100644
}
bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread)
+diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
+index d24b7a7993aa0..990360d75cb64 100644
+--- a/drivers/net/xen-netback/xenbus.c
++++ b/drivers/net/xen-netback/xenbus.c
+@@ -256,6 +256,7 @@ static void backend_disconnect(struct backend_info *be)
+ unsigned int queue_index;
+
+ xen_unregister_watchers(vif);
++ xenbus_rm(XBT_NIL, be->dev->nodename, "hotplug-status");
+ #ifdef CONFIG_DEBUG_FS
+ xenvif_debugfs_delif(vif);
+ #endif /* CONFIG_DEBUG_FS */
+@@ -675,7 +676,6 @@ static void hotplug_status_changed(struct xenbus_watch *watch,
+
+ /* Not interested in this watch anymore. */
+ unregister_hotplug_status_watch(be);
+- xenbus_rm(XBT_NIL, be->dev->nodename, "hotplug-status");
+ }
+ kfree(str);
+ }
+@@ -824,15 +824,11 @@ static void connect(struct backend_info *be)
+ xenvif_carrier_on(be->vif);
+
+ unregister_hotplug_status_watch(be);
+- if (xenbus_exists(XBT_NIL, dev->nodename, "hotplug-status")) {
+- err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
+- NULL, hotplug_status_changed,
+- "%s/%s", dev->nodename,
+- "hotplug-status");
+- if (err)
+- goto err;
++ err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
++ hotplug_status_changed,
++ "%s/%s", dev->nodename, "hotplug-status");
++ if (!err)
+ be->have_hotplug_status_watch = 1;
+- }
+
+ netif_tx_wake_all_queues(be->vif->dev);
+
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index fc41ba95f81d0..2492a27467b46 100644
--- a/drivers/net/xen-netfront.c
@@ -96637,6 +139826,26 @@ index fc41ba95f81d0..2492a27467b46 100644
static int xennet_create_page_pool(struct netfront_queue *queue)
+diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
+index 2fcf545012b16..1a5284de4341b 100644
+--- a/drivers/nfc/nfcmrvl/main.c
++++ b/drivers/nfc/nfcmrvl/main.c
+@@ -183,6 +183,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
+ {
+ struct nci_dev *ndev = priv->ndev;
+
++ nci_unregister_device(ndev);
+ if (priv->ndev->nfc_dev->fw_download_in_progress)
+ nfcmrvl_fw_dnld_abort(priv);
+
+@@ -191,7 +192,6 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
+ if (gpio_is_valid(priv->config.reset_n_io))
+ gpio_free(priv->config.reset_n_io);
+
+- nci_unregister_device(ndev);
+ nci_free_device(ndev);
+ kfree(priv);
+ }
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
index 2f3f3fe9a0baa..d32aec0c334fe 100644
--- a/drivers/nfc/pn533/pn533.c
@@ -96668,6 +139877,20 @@ index 2f3f3fe9a0baa..d32aec0c334fe 100644
goto error;
/* get the first skb */
+diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c
+index 16ceb763594fc..90e30e2f15125 100644
+--- a/drivers/nfc/port100.c
++++ b/drivers/nfc/port100.c
+@@ -1612,7 +1612,9 @@ free_nfc_dev:
+ nfc_digital_free_device(dev->nfc_digital_dev);
+
+ error:
++ usb_kill_urb(dev->in_urb);
+ usb_free_urb(dev->in_urb);
++ usb_kill_urb(dev->out_urb);
+ usb_free_urb(dev->out_urb);
+ usb_put_dev(dev->udev);
+
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 279d88128b2e4..d56bc24709b5c 100644
--- a/drivers/nfc/st21nfca/i2c.c
@@ -96731,6 +139954,34 @@ index 279d88128b2e4..d56bc24709b5c 100644
return 0;
}
+diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
+index c8bdf078d1115..0841e0e370a03 100644
+--- a/drivers/nfc/st21nfca/se.c
++++ b/drivers/nfc/st21nfca/se.c
+@@ -320,6 +320,11 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+ return -ENOMEM;
+
+ transaction->aid_len = skb->data[1];
++
++ /* Checking if the length of the AID is valid */
++ if (transaction->aid_len > sizeof(transaction->aid))
++ return -EINVAL;
++
+ memcpy(transaction->aid, &skb->data[2],
+ transaction->aid_len);
+
+@@ -329,6 +334,11 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+ return -EPROTO;
+
+ transaction->params_len = skb->data[transaction->aid_len + 3];
++
++ /* Total size is allocated (skb->len - 2) minus fixed array members */
++ if (transaction->params_len > ((skb->len - 2) - sizeof(struct nfc_evt_transaction)))
++ return -EINVAL;
++
+ memcpy(transaction->params, skb->data +
+ transaction->aid_len + 4, transaction->params_len);
+
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen4.c b/drivers/ntb/hw/intel/ntb_hw_gen4.c
index fede05151f698..4081fc538ff45 100644
--- a/drivers/ntb/hw/intel/ntb_hw_gen4.c
@@ -96918,8 +140169,22 @@ index 054154c22899a..2721dd2ead0a7 100644
}
static int nd_pmem_probe(struct device *dev)
+diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
+index 9ccf3d6087993..70ad891a76bae 100644
+--- a/drivers/nvdimm/region_devs.c
++++ b/drivers/nvdimm/region_devs.c
+@@ -1025,6 +1025,9 @@ static unsigned long default_align(struct nd_region *nd_region)
+ }
+ }
+
++ if (nd_region->ndr_size < MEMREMAP_COMPAT_ALIGN_MAX)
++ align = PAGE_SIZE;
++
+ mappings = max_t(u16, 1, nd_region->ndr_mappings);
+ div_u64_rem(align, mappings, &remainder);
+ if (remainder)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
-index f8dd664b2eda5..d5d5d035d6775 100644
+index f8dd664b2eda5..87877397d1add 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -131,7 +131,7 @@ static void nvme_set_queue_dying(struct nvme_ns *ns)
@@ -96931,7 +140196,91 @@ index f8dd664b2eda5..d5d5d035d6775 100644
blk_mq_unquiesce_queue(ns->queue);
set_capacity_and_notify(ns->disk, 0);
-@@ -1914,7 +1914,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
+@@ -1354,6 +1354,8 @@ static int nvme_process_ns_desc(struct nvme_ctrl *ctrl, struct nvme_ns_ids *ids,
+ warn_str, cur->nidl);
+ return -1;
+ }
++ if (ctrl->quirks & NVME_QUIRK_BOGUS_NID)
++ return NVME_NIDT_EUI64_LEN;
+ memcpy(ids->eui64, data + sizeof(*cur), NVME_NIDT_EUI64_LEN);
+ return NVME_NIDT_EUI64_LEN;
+ case NVME_NIDT_NGUID:
+@@ -1362,6 +1364,8 @@ static int nvme_process_ns_desc(struct nvme_ctrl *ctrl, struct nvme_ns_ids *ids,
+ warn_str, cur->nidl);
+ return -1;
+ }
++ if (ctrl->quirks & NVME_QUIRK_BOGUS_NID)
++ return NVME_NIDT_NGUID_LEN;
+ memcpy(ids->nguid, data + sizeof(*cur), NVME_NIDT_NGUID_LEN);
+ return NVME_NIDT_NGUID_LEN;
+ case NVME_NIDT_UUID:
+@@ -1370,6 +1374,8 @@ static int nvme_process_ns_desc(struct nvme_ctrl *ctrl, struct nvme_ns_ids *ids,
+ warn_str, cur->nidl);
+ return -1;
+ }
++ if (ctrl->quirks & NVME_QUIRK_BOGUS_NID)
++ return NVME_NIDT_UUID_LEN;
+ uuid_copy(&ids->uuid, data + sizeof(*cur));
+ return NVME_NIDT_UUID_LEN;
+ case NVME_NIDT_CSI:
+@@ -1466,12 +1472,18 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
+ if ((*id)->ncap == 0) /* namespace not allocated or attached */
+ goto out_free_id;
+
+- if (ctrl->vs >= NVME_VS(1, 1, 0) &&
+- !memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
+- memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64));
+- if (ctrl->vs >= NVME_VS(1, 2, 0) &&
+- !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
+- memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid));
++
++ if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) {
++ dev_info(ctrl->device,
++ "Ignoring bogus Namespace Identifiers\n");
++ } else {
++ if (ctrl->vs >= NVME_VS(1, 1, 0) &&
++ !memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
++ memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64));
++ if (ctrl->vs >= NVME_VS(1, 2, 0) &&
++ !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
++ memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid));
++ }
+
+ return 0;
+
+@@ -1674,13 +1686,6 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
+ blk_queue_max_write_zeroes_sectors(queue, UINT_MAX);
+ }
+
+-static bool nvme_ns_ids_valid(struct nvme_ns_ids *ids)
+-{
+- return !uuid_is_null(&ids->uuid) ||
+- memchr_inv(ids->nguid, 0, sizeof(ids->nguid)) ||
+- memchr_inv(ids->eui64, 0, sizeof(ids->eui64));
+-}
+-
+ static bool nvme_ns_ids_equal(struct nvme_ns_ids *a, struct nvme_ns_ids *b)
+ {
+ return uuid_equal(&a->uuid, &b->uuid) &&
+@@ -1845,9 +1850,6 @@ static void nvme_update_disk_info(struct gendisk *disk,
+ nvme_config_discard(disk, ns);
+ blk_queue_max_write_zeroes_sectors(disk->queue,
+ ns->ctrl->max_zeroes_sectors);
+-
+- set_disk_ro(disk, (id->nsattr & NVME_NS_ATTR_RO) ||
+- test_bit(NVME_NS_FORCE_RO, &ns->flags));
+ }
+
+ static inline bool nvme_first_scan(struct gendisk *disk)
+@@ -1908,18 +1910,23 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
+ goto out_unfreeze;
+ }
+
++ set_disk_ro(ns->disk, (id->nsattr & NVME_NS_ATTR_RO) ||
++ test_bit(NVME_NS_FORCE_RO, &ns->flags));
+ set_bit(NVME_NS_READY, &ns->flags);
+ blk_mq_unfreeze_queue(ns->disk->queue);
+
if (blk_queue_is_zoned(ns->queue)) {
ret = nvme_revalidate_zones(ns);
if (ret && !nvme_first_scan(ns->disk))
@@ -96940,7 +140289,15 @@ index f8dd664b2eda5..d5d5d035d6775 100644
}
if (nvme_ns_head_multipath(ns->head)) {
-@@ -1929,16 +1929,16 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
+ blk_mq_freeze_queue(ns->head->disk->queue);
+ nvme_update_disk_info(ns->head->disk, ns, id);
++ set_disk_ro(ns->head->disk,
++ (id->nsattr & NVME_NS_ATTR_RO) ||
++ test_bit(NVME_NS_FORCE_RO, &ns->flags));
+ nvme_mpath_revalidate_paths(ns);
+ blk_stack_limits(&ns->head->disk->queue->limits,
+ &ns->queue->limits, 0);
+@@ -1929,16 +1936,16 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
return 0;
out_unfreeze:
@@ -96959,7 +140316,79 @@ index f8dd664b2eda5..d5d5d035d6775 100644
return ret;
}
-@@ -4187,7 +4187,14 @@ static void nvme_async_event_work(struct work_struct *work)
+@@ -3517,15 +3524,20 @@ static const struct attribute_group *nvme_dev_attr_groups[] = {
+ NULL,
+ };
+
+-static struct nvme_ns_head *nvme_find_ns_head(struct nvme_subsystem *subsys,
++static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
+ unsigned nsid)
+ {
+ struct nvme_ns_head *h;
+
+- lockdep_assert_held(&subsys->lock);
++ lockdep_assert_held(&ctrl->subsys->lock);
+
+- list_for_each_entry(h, &subsys->nsheads, entry) {
+- if (h->ns_id != nsid)
++ list_for_each_entry(h, &ctrl->subsys->nsheads, entry) {
++ /*
++ * Private namespaces can share NSIDs under some conditions.
++ * In that case we can't use the same ns_head for namespaces
++ * with the same NSID.
++ */
++ if (h->ns_id != nsid || !nvme_is_unique_nsid(ctrl, h))
+ continue;
+ if (!list_empty(&h->list) && nvme_tryget_ns_head(h))
+ return h;
+@@ -3534,16 +3546,24 @@ static struct nvme_ns_head *nvme_find_ns_head(struct nvme_subsystem *subsys,
+ return NULL;
+ }
+
+-static int __nvme_check_ids(struct nvme_subsystem *subsys,
+- struct nvme_ns_head *new)
++static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys,
++ struct nvme_ns_ids *ids)
+ {
++ bool has_uuid = !uuid_is_null(&ids->uuid);
++ bool has_nguid = memchr_inv(ids->nguid, 0, sizeof(ids->nguid));
++ bool has_eui64 = memchr_inv(ids->eui64, 0, sizeof(ids->eui64));
+ struct nvme_ns_head *h;
+
+ lockdep_assert_held(&subsys->lock);
+
+ list_for_each_entry(h, &subsys->nsheads, entry) {
+- if (nvme_ns_ids_valid(&new->ids) &&
+- nvme_ns_ids_equal(&new->ids, &h->ids))
++ if (has_uuid && uuid_equal(&ids->uuid, &h->ids.uuid))
++ return -EINVAL;
++ if (has_nguid &&
++ memcmp(&ids->nguid, &h->ids.nguid, sizeof(ids->nguid)) == 0)
++ return -EINVAL;
++ if (has_eui64 &&
++ memcmp(&ids->eui64, &h->ids.eui64, sizeof(ids->eui64)) == 0)
+ return -EINVAL;
+ }
+
+@@ -3642,7 +3662,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
+ head->ids = *ids;
+ kref_init(&head->ref);
+
+- ret = __nvme_check_ids(ctrl->subsys, head);
++ ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, &head->ids);
+ if (ret) {
+ dev_err(ctrl->device,
+ "duplicate IDs for nsid %d\n", nsid);
+@@ -3685,7 +3705,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
+ int ret = 0;
+
+ mutex_lock(&ctrl->subsys->lock);
+- head = nvme_find_ns_head(ctrl->subsys, nsid);
++ head = nvme_find_ns_head(ctrl, nsid);
+ if (!head) {
+ head = nvme_alloc_ns_head(ctrl, nsid, ids);
+ if (IS_ERR(head)) {
+@@ -4187,7 +4207,14 @@ static void nvme_async_event_work(struct work_struct *work)
container_of(work, struct nvme_ctrl, async_event_work);
nvme_aen_uevent(ctrl);
@@ -96975,6 +140404,14 @@ index f8dd664b2eda5..d5d5d035d6775 100644
}
static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl)
+@@ -4331,6 +4358,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
+ if (ctrl->queue_count > 1) {
+ nvme_queue_scan(ctrl);
+ nvme_start_queues(ctrl);
++ nvme_mpath_update(ctrl);
+ }
+ }
+ EXPORT_SYMBOL_GPL(nvme_start_ctrl);
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index a146cb903869c..561c2abd3892b 100644
--- a/drivers/nvme/host/fabrics.h
@@ -96988,7 +140425,7 @@ index a146cb903869c..561c2abd3892b 100644
strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) ||
strcmp(opts->host->nqn, ctrl->opts->host->nqn) ||
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
-index fba06618c6c23..727520c397109 100644
+index fba06618c6c23..064acad505d38 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -138,13 +138,12 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
@@ -97009,7 +140446,61 @@ index fba06618c6c23..727520c397109 100644
}
void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
-@@ -793,7 +792,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
+@@ -463,10 +462,11 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
+
+ /*
+ * Add a multipath node if the subsystems supports multiple controllers.
+- * We also do this for private namespaces as the namespace sharing data could
+- * change after a rescan.
++ * We also do this for private namespaces as the namespace sharing flag
++ * could change after a rescan.
+ */
+- if (!(ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) || !multipath)
++ if (!(ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) ||
++ !nvme_is_unique_nsid(ctrl, head) || !multipath)
+ return 0;
+
+ head->disk = blk_alloc_disk(ctrl->numa_node);
+@@ -574,8 +574,17 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
+ ns->ana_grpid = le32_to_cpu(desc->grpid);
+ ns->ana_state = desc->state;
+ clear_bit(NVME_NS_ANA_PENDING, &ns->flags);
+-
+- if (nvme_state_is_live(ns->ana_state))
++ /*
++ * nvme_mpath_set_live() will trigger I/O to the multipath path device
++ * and in turn to this path device. However we cannot accept this I/O
++ * if the controller is not live. This may deadlock if called from
++ * nvme_mpath_init_identify() and the ctrl will never complete
++ * initialization, preventing I/O from completing. For this case we
++ * will reprocess the ANA log page in nvme_mpath_update() once the
++ * controller is ready.
++ */
++ if (nvme_state_is_live(ns->ana_state) &&
++ ns->ctrl->state == NVME_CTRL_LIVE)
+ nvme_mpath_set_live(ns);
+ }
+
+@@ -662,6 +671,18 @@ static void nvme_ana_work(struct work_struct *work)
+ nvme_read_ana_log(ctrl);
+ }
+
++void nvme_mpath_update(struct nvme_ctrl *ctrl)
++{
++ u32 nr_change_groups = 0;
++
++ if (!ctrl->ana_log_buf)
++ return;
++
++ mutex_lock(&ctrl->ana_lock);
++ nvme_parse_ana_log(ctrl, &nr_change_groups, nvme_update_ana_state);
++ mutex_unlock(&ctrl->ana_lock);
++}
++
+ static void nvme_anatt_timeout(struct timer_list *t)
+ {
+ struct nvme_ctrl *ctrl = from_timer(ctrl, t, anatt_timer);
+@@ -793,7 +814,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
{
if (!head->disk)
return;
@@ -97018,8 +140509,68 @@ index fba06618c6c23..727520c397109 100644
/* make sure all pending bios are cleaned up */
kblockd_schedule_work(&head->requeue_work);
flush_work(&head->requeue_work);
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index ed79a6c7e8043..72bcd7e5716e5 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -144,6 +144,11 @@ enum nvme_quirks {
+ * encoding the generation sequence number.
+ */
+ NVME_QUIRK_SKIP_CID_GEN = (1 << 17),
++
++ /*
++ * Reports garbage in the namespace identifiers (eui64, nguid, uuid).
++ */
++ NVME_QUIRK_BOGUS_NID = (1 << 18),
+ };
+
+ /*
+@@ -693,6 +698,25 @@ static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
+ return true;
+ return __nvme_check_ready(ctrl, rq, queue_live);
+ }
++
++/*
++ * NSID shall be unique for all shared namespaces, or if at least one of the
++ * following conditions is met:
++ * 1. Namespace Management is supported by the controller
++ * 2. ANA is supported by the controller
++ * 3. NVM Set are supported by the controller
++ *
++ * In other case, private namespace are not required to report a unique NSID.
++ */
++static inline bool nvme_is_unique_nsid(struct nvme_ctrl *ctrl,
++ struct nvme_ns_head *head)
++{
++ return head->shared ||
++ (ctrl->oacs & NVME_CTRL_OACS_NS_MNGT_SUPP) ||
++ (ctrl->subsys->cmic & NVME_CTRL_CMIC_ANA) ||
++ (ctrl->ctratt & NVME_CTRL_CTRATT_NVM_SETS);
++}
++
+ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
+ void *buf, unsigned bufflen);
+ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
+@@ -752,6 +776,7 @@ void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
+ void nvme_mpath_remove_disk(struct nvme_ns_head *head);
+ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
+ void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl);
++void nvme_mpath_update(struct nvme_ctrl *ctrl);
+ void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
+ void nvme_mpath_stop(struct nvme_ctrl *ctrl);
+ bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
+@@ -826,6 +851,9 @@ static inline int nvme_mpath_init_identify(struct nvme_ctrl *ctrl,
+ "Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");
+ return 0;
+ }
++static inline void nvme_mpath_update(struct nvme_ctrl *ctrl)
++{
++}
+ static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
+ {
+ }
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
-index 149ecf73df384..b925a5f4afc3a 100644
+index 149ecf73df384..e6f55cf6e494a 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3300,7 +3300,8 @@ static const struct pci_device_id nvme_id_table[] = {
@@ -97032,6 +140583,41 @@ index 149ecf73df384..b925a5f4afc3a 100644
{ PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
+@@ -3313,7 +3314,10 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */
+ .driver_data = NVME_QUIRK_IDENTIFY_CNS |
+- NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++ NVME_QUIRK_DISABLE_WRITE_ZEROES |
++ NVME_QUIRK_BOGUS_NID, },
++ { PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */
++ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x126f, 0x2263), /* Silicon Motion unidentified */
+ .driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
+ { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
+@@ -3351,6 +3355,10 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
+ { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
++ { PCI_DEVICE(0x1e4B, 0x1002), /* MAXIO MAP1002 */
++ .driver_data = NVME_QUIRK_BOGUS_NID, },
++ { PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */
++ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061),
+ .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
+@@ -3371,7 +3379,10 @@ static const struct pci_device_id nvme_id_table[] = {
+ NVME_QUIRK_128_BYTES_SQES |
+ NVME_QUIRK_SHARED_TAGS |
+ NVME_QUIRK_SKIP_CID_GEN },
+-
++ { PCI_DEVICE(0x144d, 0xa808), /* Samsung X5 */
++ .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY|
++ NVME_QUIRK_NO_DEEPEST_PS |
++ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { 0, }
+ };
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 042c594bc57e2..d51f52e296f50 100644
--- a/drivers/nvme/host/rdma.c
@@ -97059,10 +140645,55 @@ index 042c594bc57e2..d51f52e296f50 100644
nvme_start_queues(&ctrl->ctrl);
nvme_rdma_teardown_admin_queue(ctrl, false);
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
-index 4ae562d30d2b9..ef65d24639c44 100644
+index 4ae562d30d2b9..10882d3d554c2 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
-@@ -920,7 +920,15 @@ static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue)
+@@ -30,6 +30,44 @@ static int so_priority;
+ module_param(so_priority, int, 0644);
+ MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority");
+
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++/* lockdep can detect a circular dependency of the form
++ * sk_lock -> mmap_lock (page fault) -> fs locks -> sk_lock
++ * because dependencies are tracked for both nvme-tcp and user contexts. Using
++ * a separate class prevents lockdep from conflating nvme-tcp socket use with
++ * user-space socket API use.
++ */
++static struct lock_class_key nvme_tcp_sk_key[2];
++static struct lock_class_key nvme_tcp_slock_key[2];
++
++static void nvme_tcp_reclassify_socket(struct socket *sock)
++{
++ struct sock *sk = sock->sk;
++
++ if (WARN_ON_ONCE(!sock_allow_reclassification(sk)))
++ return;
++
++ switch (sk->sk_family) {
++ case AF_INET:
++ sock_lock_init_class_and_name(sk, "slock-AF_INET-NVME",
++ &nvme_tcp_slock_key[0],
++ "sk_lock-AF_INET-NVME",
++ &nvme_tcp_sk_key[0]);
++ break;
++ case AF_INET6:
++ sock_lock_init_class_and_name(sk, "slock-AF_INET6-NVME",
++ &nvme_tcp_slock_key[1],
++ "sk_lock-AF_INET6-NVME",
++ &nvme_tcp_sk_key[1]);
++ break;
++ default:
++ WARN_ON_ONCE(1);
++ }
++}
++#else
++static void nvme_tcp_reclassify_socket(struct socket *sock) { }
++#endif
++
+ enum nvme_tcp_send_state {
+ NVME_TCP_SEND_CMD_PDU = 0,
+ NVME_TCP_SEND_H2C_PDU,
+@@ -920,7 +958,15 @@ static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue)
static void nvme_tcp_fail_request(struct nvme_tcp_request *req)
{
@@ -97079,7 +140710,16 @@ index 4ae562d30d2b9..ef65d24639c44 100644
}
static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
-@@ -2097,6 +2105,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
+@@ -1428,6 +1474,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
+ goto err_destroy_mutex;
+ }
+
++ nvme_tcp_reclassify_socket(queue->sock);
++
+ /* Single syn retry */
+ tcp_sock_set_syncnt(queue->sock->sk, 1);
+
+@@ -2097,6 +2145,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl;
nvme_stop_keep_alive(ctrl);
@@ -97087,8 +140727,21 @@ index 4ae562d30d2b9..ef65d24639c44 100644
nvme_tcp_teardown_io_queues(ctrl, false);
/* unquiesce to fail fast pending requests */
nvme_start_queues(ctrl);
+diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
+index aa6d84d8848e7..52bb262d267ac 100644
+--- a/drivers/nvme/target/admin-cmd.c
++++ b/drivers/nvme/target/admin-cmd.c
+@@ -978,7 +978,7 @@ void nvmet_execute_async_event(struct nvmet_req *req)
+ ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req;
+ mutex_unlock(&ctrl->lock);
+
+- schedule_work(&ctrl->async_event_work);
++ queue_work(nvmet_wq, &ctrl->async_event_work);
+ }
+
+ void nvmet_execute_keep_alive(struct nvmet_req *req)
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
-index be5d82421e3a4..496d775c67707 100644
+index be5d82421e3a4..cea30e4f50533 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1553,6 +1553,8 @@ static void nvmet_port_release(struct config_item *item)
@@ -97096,12 +140749,214 @@ index be5d82421e3a4..496d775c67707 100644
struct nvmet_port *port = to_nvmet_port(item);
+ /* Let inflight controllers teardown complete */
-+ flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
list_del(&port->global_entry);
kfree(port->ana_state);
+diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
+index b8425fa34300f..a8dafe8670f20 100644
+--- a/drivers/nvme/target/core.c
++++ b/drivers/nvme/target/core.c
+@@ -20,6 +20,9 @@ struct workqueue_struct *zbd_wq;
+ static const struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX];
+ static DEFINE_IDA(cntlid_ida);
+
++struct workqueue_struct *nvmet_wq;
++EXPORT_SYMBOL_GPL(nvmet_wq);
++
+ /*
+ * This read/write semaphore is used to synchronize access to configuration
+ * information on a target system that will result in discovery log page
+@@ -205,7 +208,7 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
+ list_add_tail(&aen->entry, &ctrl->async_events);
+ mutex_unlock(&ctrl->lock);
+
+- schedule_work(&ctrl->async_event_work);
++ queue_work(nvmet_wq, &ctrl->async_event_work);
+ }
+
+ static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid)
+@@ -385,7 +388,7 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
+ if (reset_tbkas) {
+ pr_debug("ctrl %d reschedule traffic based keep-alive timer\n",
+ ctrl->cntlid);
+- schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
++ queue_delayed_work(nvmet_wq, &ctrl->ka_work, ctrl->kato * HZ);
+ return;
+ }
+
+@@ -403,7 +406,7 @@ void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
+ pr_debug("ctrl %d start keep-alive timer for %d secs\n",
+ ctrl->cntlid, ctrl->kato);
+
+- schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
++ queue_delayed_work(nvmet_wq, &ctrl->ka_work, ctrl->kato * HZ);
+ }
+
+ void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
+@@ -1477,7 +1480,7 @@ void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl)
+ mutex_lock(&ctrl->lock);
+ if (!(ctrl->csts & NVME_CSTS_CFS)) {
+ ctrl->csts |= NVME_CSTS_CFS;
+- schedule_work(&ctrl->fatal_err_work);
++ queue_work(nvmet_wq, &ctrl->fatal_err_work);
+ }
+ mutex_unlock(&ctrl->lock);
+ }
+@@ -1617,9 +1620,15 @@ static int __init nvmet_init(void)
+ goto out_free_zbd_work_queue;
+ }
+
++ nvmet_wq = alloc_workqueue("nvmet-wq", WQ_MEM_RECLAIM, 0);
++ if (!nvmet_wq) {
++ error = -ENOMEM;
++ goto out_free_buffered_work_queue;
++ }
++
+ error = nvmet_init_discovery();
+ if (error)
+- goto out_free_work_queue;
++ goto out_free_nvmet_work_queue;
+
+ error = nvmet_init_configfs();
+ if (error)
+@@ -1628,7 +1637,9 @@ static int __init nvmet_init(void)
+
+ out_exit_discovery:
+ nvmet_exit_discovery();
+-out_free_work_queue:
++out_free_nvmet_work_queue:
++ destroy_workqueue(nvmet_wq);
++out_free_buffered_work_queue:
+ destroy_workqueue(buffered_io_wq);
+ out_free_zbd_work_queue:
+ destroy_workqueue(zbd_wq);
+@@ -1640,6 +1651,7 @@ static void __exit nvmet_exit(void)
+ nvmet_exit_configfs();
+ nvmet_exit_discovery();
+ ida_destroy(&cntlid_ida);
++ destroy_workqueue(nvmet_wq);
+ destroy_workqueue(buffered_io_wq);
+ destroy_workqueue(zbd_wq);
+
+diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
+index 22b5108168a6a..c43bc5e1c7a28 100644
+--- a/drivers/nvme/target/fc.c
++++ b/drivers/nvme/target/fc.c
+@@ -1491,7 +1491,7 @@ __nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport)
+ list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) {
+ if (!nvmet_fc_tgt_a_get(assoc))
+ continue;
+- if (!schedule_work(&assoc->del_work))
++ if (!queue_work(nvmet_wq, &assoc->del_work))
+ /* already deleting - release local reference */
+ nvmet_fc_tgt_a_put(assoc);
+ }
+@@ -1546,7 +1546,7 @@ nvmet_fc_invalidate_host(struct nvmet_fc_target_port *target_port,
+ continue;
+ assoc->hostport->invalid = 1;
+ noassoc = false;
+- if (!schedule_work(&assoc->del_work))
++ if (!queue_work(nvmet_wq, &assoc->del_work))
+ /* already deleting - release local reference */
+ nvmet_fc_tgt_a_put(assoc);
+ }
+@@ -1592,7 +1592,7 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl)
+ nvmet_fc_tgtport_put(tgtport);
+
+ if (found_ctrl) {
+- if (!schedule_work(&assoc->del_work))
++ if (!queue_work(nvmet_wq, &assoc->del_work))
+ /* already deleting - release local reference */
+ nvmet_fc_tgt_a_put(assoc);
+ return;
+@@ -2060,7 +2060,7 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port,
+ iod->rqstdatalen = lsreqbuf_len;
+ iod->hosthandle = hosthandle;
+
+- schedule_work(&iod->work);
++ queue_work(nvmet_wq, &iod->work);
+
+ return 0;
+ }
+diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
+index 54606f1872b4a..5c16372f3b533 100644
+--- a/drivers/nvme/target/fcloop.c
++++ b/drivers/nvme/target/fcloop.c
+@@ -360,7 +360,7 @@ fcloop_h2t_ls_req(struct nvme_fc_local_port *localport,
+ spin_lock(&rport->lock);
+ list_add_tail(&rport->ls_list, &tls_req->ls_list);
+ spin_unlock(&rport->lock);
+- schedule_work(&rport->ls_work);
++ queue_work(nvmet_wq, &rport->ls_work);
+ return ret;
+ }
+
+@@ -393,7 +393,7 @@ fcloop_h2t_xmt_ls_rsp(struct nvmet_fc_target_port *targetport,
+ spin_lock(&rport->lock);
+ list_add_tail(&rport->ls_list, &tls_req->ls_list);
+ spin_unlock(&rport->lock);
+- schedule_work(&rport->ls_work);
++ queue_work(nvmet_wq, &rport->ls_work);
+ }
+
+ return 0;
+@@ -448,7 +448,7 @@ fcloop_t2h_ls_req(struct nvmet_fc_target_port *targetport, void *hosthandle,
+ spin_lock(&tport->lock);
+ list_add_tail(&tport->ls_list, &tls_req->ls_list);
+ spin_unlock(&tport->lock);
+- schedule_work(&tport->ls_work);
++ queue_work(nvmet_wq, &tport->ls_work);
+ return ret;
+ }
+
+@@ -480,7 +480,7 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
+ spin_lock(&tport->lock);
+ list_add_tail(&tport->ls_list, &tls_req->ls_list);
+ spin_unlock(&tport->lock);
+- schedule_work(&tport->ls_work);
++ queue_work(nvmet_wq, &tport->ls_work);
+ }
+
+ return 0;
+@@ -520,7 +520,7 @@ fcloop_tgt_discovery_evt(struct nvmet_fc_target_port *tgtport)
+ tgt_rscn->tport = tgtport->private;
+ INIT_WORK(&tgt_rscn->work, fcloop_tgt_rscn_work);
+
+- schedule_work(&tgt_rscn->work);
++ queue_work(nvmet_wq, &tgt_rscn->work);
+ }
+
+ static void
+@@ -739,7 +739,7 @@ fcloop_fcp_req(struct nvme_fc_local_port *localport,
+ INIT_WORK(&tfcp_req->tio_done_work, fcloop_tgt_fcprqst_done_work);
+ kref_init(&tfcp_req->ref);
+
+- schedule_work(&tfcp_req->fcp_rcv_work);
++ queue_work(nvmet_wq, &tfcp_req->fcp_rcv_work);
+
+ return 0;
+ }
+@@ -921,7 +921,7 @@ fcloop_fcp_req_release(struct nvmet_fc_target_port *tgtport,
+ {
+ struct fcloop_fcpreq *tfcp_req = tgt_fcp_req_to_fcpreq(tgt_fcpreq);
+
+- schedule_work(&tfcp_req->tio_done_work);
++ queue_work(nvmet_wq, &tfcp_req->tio_done_work);
+ }
+
+ static void
+@@ -976,7 +976,7 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
+
+ if (abortio)
+ /* leave the reference while the work item is scheduled */
+- WARN_ON(!schedule_work(&tfcp_req->abort_rcv_work));
++ WARN_ON(!queue_work(nvmet_wq, &tfcp_req->abort_rcv_work));
+ else {
+ /*
+ * as the io has already had the done callback made,
diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c
-index 1dd1a0fe2e819..df7e033dd2732 100644
+index 1dd1a0fe2e819..228871d48106b 100644
--- a/drivers/nvme/target/io-cmd-file.c
+++ b/drivers/nvme/target/io-cmd-file.c
@@ -8,6 +8,7 @@
@@ -97122,10 +140977,120 @@ index 1dd1a0fe2e819..df7e033dd2732 100644
return;
nvmet_file_submit_buffered_io(req);
} else
+@@ -290,7 +292,7 @@ static void nvmet_file_execute_flush(struct nvmet_req *req)
+ if (!nvmet_check_transfer_len(req, 0))
+ return;
+ INIT_WORK(&req->f.work, nvmet_file_flush_work);
+- schedule_work(&req->f.work);
++ queue_work(nvmet_wq, &req->f.work);
+ }
+
+ static void nvmet_file_execute_discard(struct nvmet_req *req)
+@@ -350,7 +352,7 @@ static void nvmet_file_execute_dsm(struct nvmet_req *req)
+ if (!nvmet_check_data_len_lte(req, nvmet_dsm_len(req)))
+ return;
+ INIT_WORK(&req->f.work, nvmet_file_dsm_work);
+- schedule_work(&req->f.work);
++ queue_work(nvmet_wq, &req->f.work);
+ }
+
+ static void nvmet_file_write_zeroes_work(struct work_struct *w)
+@@ -380,7 +382,7 @@ static void nvmet_file_execute_write_zeroes(struct nvmet_req *req)
+ if (!nvmet_check_transfer_len(req, 0))
+ return;
+ INIT_WORK(&req->f.work, nvmet_file_write_zeroes_work);
+- schedule_work(&req->f.work);
++ queue_work(nvmet_wq, &req->f.work);
+ }
+
+ u16 nvmet_file_parse_io_cmd(struct nvmet_req *req)
+diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
+index 0285ccc7541f6..2553f487c9f24 100644
+--- a/drivers/nvme/target/loop.c
++++ b/drivers/nvme/target/loop.c
+@@ -166,7 +166,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ iod->req.transfer_len = blk_rq_payload_bytes(req);
+ }
+
+- schedule_work(&iod->work);
++ queue_work(nvmet_wq, &iod->work);
+ return BLK_STS_OK;
+ }
+
+@@ -187,7 +187,7 @@ static void nvme_loop_submit_async_event(struct nvme_ctrl *arg)
+ return;
+ }
+
+- schedule_work(&iod->work);
++ queue_work(nvmet_wq, &iod->work);
+ }
+
+ static int nvme_loop_init_iod(struct nvme_loop_ctrl *ctrl,
+diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
+index 7143c7fa74641..dbeb0b8c11947 100644
+--- a/drivers/nvme/target/nvmet.h
++++ b/drivers/nvme/target/nvmet.h
+@@ -365,6 +365,7 @@ struct nvmet_req {
+
+ extern struct workqueue_struct *buffered_io_wq;
+ extern struct workqueue_struct *zbd_wq;
++extern struct workqueue_struct *nvmet_wq;
+
+ static inline void nvmet_set_result(struct nvmet_req *req, u32 result)
+ {
+diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
+index f0efb35379898..6220e1dd961ad 100644
+--- a/drivers/nvme/target/passthru.c
++++ b/drivers/nvme/target/passthru.c
+@@ -281,7 +281,7 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req)
+ if (req->p.use_workqueue || effects) {
+ INIT_WORK(&req->p.work, nvmet_passthru_execute_cmd_work);
+ req->p.rq = rq;
+- schedule_work(&req->p.work);
++ queue_work(nvmet_wq, &req->p.work);
+ } else {
+ rq->end_io_data = req;
+ blk_execute_rq_nowait(ns ? ns->disk : NULL, rq, 0,
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
-index 891174ccd44bb..f1eedbf493d5b 100644
+index 891174ccd44bb..18e082091c821 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
+@@ -1583,7 +1583,7 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
+
+ if (queue->host_qid == 0) {
+ /* Let inflight controller teardown complete */
+- flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
+ }
+
+ ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);
+@@ -1668,7 +1668,7 @@ static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue)
+
+ if (disconnect) {
+ rdma_disconnect(queue->cm_id);
+- schedule_work(&queue->release_work);
++ queue_work(nvmet_wq, &queue->release_work);
+ }
+ }
+
+@@ -1698,7 +1698,7 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,
+ mutex_unlock(&nvmet_rdma_queue_mutex);
+
+ pr_err("failed to connect queue %d\n", queue->idx);
+- schedule_work(&queue->release_work);
++ queue_work(nvmet_wq, &queue->release_work);
+ }
+
+ /**
+@@ -1772,7 +1772,7 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id,
+ if (!queue) {
+ struct nvmet_rdma_port *port = cm_id->context;
+
+- schedule_delayed_work(&port->repair_work, 0);
++ queue_delayed_work(nvmet_wq, &port->repair_work, 0);
+ break;
+ }
+ fallthrough;
@@ -1818,12 +1818,36 @@ restart:
mutex_unlock(&nvmet_rdma_queue_mutex);
}
@@ -97163,8 +141128,26 @@ index 891174ccd44bb..f1eedbf493d5b 100644
}
static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port)
+@@ -1878,7 +1902,7 @@ static void nvmet_rdma_repair_port_work(struct work_struct *w)
+ nvmet_rdma_disable_port(port);
+ ret = nvmet_rdma_enable_port(port);
+ if (ret)
+- schedule_delayed_work(&port->repair_work, 5 * HZ);
++ queue_delayed_work(nvmet_wq, &port->repair_work, 5 * HZ);
+ }
+
+ static int nvmet_rdma_add_port(struct nvmet_port *nport)
+@@ -2022,7 +2046,7 @@ static void nvmet_rdma_remove_one(struct ib_device *ib_device, void *client_data
+ }
+ mutex_unlock(&nvmet_rdma_queue_mutex);
+
+- flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
+ }
+
+ static struct ib_client nvmet_rdma_ib_client = {
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
-index 46c3b3be7e033..2b8bab28417b8 100644
+index 46c3b3be7e033..f592e5f7f5f3d 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -700,10 +700,11 @@ static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
@@ -97191,6 +141174,24 @@ index 46c3b3be7e033..2b8bab28417b8 100644
if (queue->nvme_sq.sqhd_disabled) {
cmd->queue->snd_cmd = NULL;
+@@ -1246,7 +1251,7 @@ static void nvmet_tcp_schedule_release_queue(struct nvmet_tcp_queue *queue)
+ spin_lock(&queue->state_lock);
+ if (queue->state != NVMET_TCP_Q_DISCONNECTING) {
+ queue->state = NVMET_TCP_Q_DISCONNECTING;
+- schedule_work(&queue->release_work);
++ queue_work(nvmet_wq, &queue->release_work);
+ }
+ spin_unlock(&queue->state_lock);
+ }
+@@ -1657,7 +1662,7 @@ static void nvmet_tcp_listen_data_ready(struct sock *sk)
+ goto out;
+
+ if (sk->sk_state == TCP_LISTEN)
+- schedule_work(&port->accept_work);
++ queue_work(nvmet_wq, &port->accept_work);
+ out:
+ read_unlock_bh(&sk->sk_callback_lock);
+ }
@@ -1740,6 +1745,17 @@ err_port:
return ret;
}
@@ -97221,6 +141222,30 @@ index 46c3b3be7e033..2b8bab28417b8 100644
sock_release(port->sock);
kfree(port);
+@@ -1772,7 +1793,7 @@ static u16 nvmet_tcp_install_queue(struct nvmet_sq *sq)
+
+ if (sq->qid == 0) {
+ /* Let inflight controller teardown complete */
+- flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
+ }
+
+ queue->nr_cmds = sq->size * 2;
+@@ -1833,12 +1854,12 @@ static void __exit nvmet_tcp_exit(void)
+
+ nvmet_unregister_transport(&nvmet_tcp_ops);
+
+- flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
+ mutex_lock(&nvmet_tcp_queue_mutex);
+ list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
+ kernel_sock_shutdown(queue->sock, SHUT_RDWR);
+ mutex_unlock(&nvmet_tcp_queue_mutex);
+- flush_scheduled_work();
++ flush_workqueue(nvmet_wq);
+
+ destroy_workqueue(nvmet_tcp_wq);
+ }
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 8976da38b375a..fb7840c73765a 100644
--- a/drivers/nvmem/core.c
@@ -97625,6 +141650,32 @@ index 8c056972a6ddc..2bee1d992408f 100644
unittest(chip_request_count + 1 == unittest_gpio_chip_request_count,
"unittest_gpio_chip_request() called %d times (expected 1 time)\n",
+diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
+index 596c185b5dda4..b5f2f9f393926 100644
+--- a/drivers/opp/debugfs.c
++++ b/drivers/opp/debugfs.c
+@@ -10,6 +10,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
++#include <linux/of.h>
+ #include <linux/init.h>
+ #include <linux/limits.h>
+ #include <linux/slab.h>
+@@ -131,9 +132,13 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
+ debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
+ debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
+ debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate);
++ debugfs_create_u32("level", S_IRUGO, d, &opp->level);
+ debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+ &opp->clock_latency_ns);
+
++ opp->of_name = of_node_full_name(opp->np);
++ debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);
++
+ opp_debug_create_supplies(opp, opp_table, d);
+ opp_debug_create_bw(opp, opp_table, d);
+
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 2a97c6535c4c6..c32ae7497392b 100644
--- a/drivers/opp/of.c
@@ -97638,6 +141689,18 @@ index 2a97c6535c4c6..c32ae7497392b 100644
}
/* Initializes OPP tables based on new bindings */
+diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
+index 407c3bfe51d96..45e3a55239a13 100644
+--- a/drivers/opp/opp.h
++++ b/drivers/opp/opp.h
+@@ -96,6 +96,7 @@ struct dev_pm_opp {
+
+ #ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
++ const char *of_name;
+ #endif
+ };
+
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 059566f544291..9be007c9420f9 100644
--- a/drivers/parisc/ccio-dma.c
@@ -97659,6 +141722,178 @@ index 059566f544291..9be007c9420f9 100644
}
DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
+diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
+index 952a92504df69..e33036281327d 100644
+--- a/drivers/parisc/dino.c
++++ b/drivers/parisc/dino.c
+@@ -142,9 +142,8 @@ struct dino_device
+ {
+ struct pci_hba_data hba; /* 'C' inheritance - must be first */
+ spinlock_t dinosaur_pen;
+- unsigned long txn_addr; /* EIR addr to generate interrupt */
+- u32 txn_data; /* EIR data assign to each dino */
+ u32 imr; /* IRQ's which are enabled */
++ struct gsc_irq gsc_irq;
+ int global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
+ #ifdef DINO_DEBUG
+ unsigned int dino_irr0; /* save most recent IRQ line stat */
+@@ -339,14 +338,43 @@ static void dino_unmask_irq(struct irq_data *d)
+ if (tmp & DINO_MASK_IRQ(local_irq)) {
+ DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n",
+ __func__, tmp);
+- gsc_writel(dino_dev->txn_data, dino_dev->txn_addr);
++ gsc_writel(dino_dev->gsc_irq.txn_data, dino_dev->gsc_irq.txn_addr);
+ }
+ }
+
++#ifdef CONFIG_SMP
++static int dino_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
++ bool force)
++{
++ struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
++ struct cpumask tmask;
++ int cpu_irq;
++ u32 eim;
++
++ if (!cpumask_and(&tmask, dest, cpu_online_mask))
++ return -EINVAL;
++
++ cpu_irq = cpu_check_affinity(d, &tmask);
++ if (cpu_irq < 0)
++ return cpu_irq;
++
++ dino_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq);
++ eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data;
++ __raw_writel(eim, dino_dev->hba.base_addr+DINO_IAR0);
++
++ irq_data_update_effective_affinity(d, &tmask);
++
++ return IRQ_SET_MASK_OK;
++}
++#endif
++
+ static struct irq_chip dino_interrupt_type = {
+ .name = "GSC-PCI",
+ .irq_unmask = dino_unmask_irq,
+ .irq_mask = dino_mask_irq,
++#ifdef CONFIG_SMP
++ .irq_set_affinity = dino_set_affinity_irq,
++#endif
+ };
+
+
+@@ -806,7 +834,6 @@ static int __init dino_common_init(struct parisc_device *dev,
+ {
+ int status;
+ u32 eim;
+- struct gsc_irq gsc_irq;
+ struct resource *res;
+
+ pcibios_register_hba(&dino_dev->hba);
+@@ -821,10 +848,8 @@ static int __init dino_common_init(struct parisc_device *dev,
+ ** still only has 11 IRQ input lines - just map some of them
+ ** to a different processor.
+ */
+- dev->irq = gsc_alloc_irq(&gsc_irq);
+- dino_dev->txn_addr = gsc_irq.txn_addr;
+- dino_dev->txn_data = gsc_irq.txn_data;
+- eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
++ dev->irq = gsc_alloc_irq(&dino_dev->gsc_irq);
++ eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data;
+
+ /*
+ ** Dino needs a PA "IRQ" to get a processor's attention.
+diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
+index ed9371acf37eb..ec175ae998733 100644
+--- a/drivers/parisc/gsc.c
++++ b/drivers/parisc/gsc.c
+@@ -135,10 +135,41 @@ static void gsc_asic_unmask_irq(struct irq_data *d)
+ */
+ }
+
++#ifdef CONFIG_SMP
++static int gsc_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
++ bool force)
++{
++ struct gsc_asic *gsc_dev = irq_data_get_irq_chip_data(d);
++ struct cpumask tmask;
++ int cpu_irq;
++
++ if (!cpumask_and(&tmask, dest, cpu_online_mask))
++ return -EINVAL;
++
++ cpu_irq = cpu_check_affinity(d, &tmask);
++ if (cpu_irq < 0)
++ return cpu_irq;
++
++ gsc_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq);
++ gsc_dev->eim = ((u32) gsc_dev->gsc_irq.txn_addr) | gsc_dev->gsc_irq.txn_data;
++
++ /* switch IRQ's for devices below LASI/WAX to other CPU */
++ gsc_writel(gsc_dev->eim, gsc_dev->hpa + OFFSET_IAR);
++
++ irq_data_update_effective_affinity(d, &tmask);
++
++ return IRQ_SET_MASK_OK;
++}
++#endif
++
++
+ static struct irq_chip gsc_asic_interrupt_type = {
+ .name = "GSC-ASIC",
+ .irq_unmask = gsc_asic_unmask_irq,
+ .irq_mask = gsc_asic_mask_irq,
++#ifdef CONFIG_SMP
++ .irq_set_affinity = gsc_set_affinity_irq,
++#endif
+ };
+
+ int gsc_assign_irq(struct irq_chip *type, void *data)
+diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h
+index 86abad3fa2150..73cbd0bb1975a 100644
+--- a/drivers/parisc/gsc.h
++++ b/drivers/parisc/gsc.h
+@@ -31,6 +31,7 @@ struct gsc_asic {
+ int version;
+ int type;
+ int eim;
++ struct gsc_irq gsc_irq;
+ int global_irq[32];
+ };
+
+diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
+index 4e4fd12c2112e..6ef621adb63a8 100644
+--- a/drivers/parisc/lasi.c
++++ b/drivers/parisc/lasi.c
+@@ -163,7 +163,6 @@ static int __init lasi_init_chip(struct parisc_device *dev)
+ {
+ extern void (*chassis_power_off)(void);
+ struct gsc_asic *lasi;
+- struct gsc_irq gsc_irq;
+ int ret;
+
+ lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);
+@@ -185,7 +184,7 @@ static int __init lasi_init_chip(struct parisc_device *dev)
+ lasi_init_irq(lasi);
+
+ /* the IRQ lasi should use */
+- dev->irq = gsc_alloc_irq(&gsc_irq);
++ dev->irq = gsc_alloc_irq(&lasi->gsc_irq);
+ if (dev->irq < 0) {
+ printk(KERN_ERR "%s(): cannot get GSC irq\n",
+ __func__);
+@@ -193,9 +192,9 @@ static int __init lasi_init_chip(struct parisc_device *dev)
+ return -EBUSY;
+ }
+
+- lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
++ lasi->eim = ((u32) lasi->gsc_irq.txn_addr) | lasi->gsc_irq.txn_data;
+
+- ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);
++ ret = request_irq(lasi->gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);
+ if (ret < 0) {
+ kfree(lasi);
+ return ret;
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index e090978518f1a..4760f82def6ec 100644
--- a/drivers/parisc/pdc_stable.c
@@ -97696,6 +141931,59 @@ index e60690d38d677..374b9199878d4 100644
}
DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
+diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
+index 5b6df15162354..73a2b01f8d9ca 100644
+--- a/drivers/parisc/wax.c
++++ b/drivers/parisc/wax.c
+@@ -68,7 +68,6 @@ static int __init wax_init_chip(struct parisc_device *dev)
+ {
+ struct gsc_asic *wax;
+ struct parisc_device *parent;
+- struct gsc_irq gsc_irq;
+ int ret;
+
+ wax = kzalloc(sizeof(*wax), GFP_KERNEL);
+@@ -85,7 +84,7 @@ static int __init wax_init_chip(struct parisc_device *dev)
+ wax_init_irq(wax);
+
+ /* the IRQ wax should use */
+- dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ);
++ dev->irq = gsc_claim_irq(&wax->gsc_irq, WAX_GSC_IRQ);
+ if (dev->irq < 0) {
+ printk(KERN_ERR "%s(): cannot get GSC irq\n",
+ __func__);
+@@ -93,9 +92,9 @@ static int __init wax_init_chip(struct parisc_device *dev)
+ return -EBUSY;
+ }
+
+- wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
++ wax->eim = ((u32) wax->gsc_irq.txn_addr) | wax->gsc_irq.txn_data;
+
+- ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "wax", wax);
++ ret = request_irq(wax->gsc_irq.irq, gsc_asic_intr, 0, "wax", wax);
+ if (ret < 0) {
+ kfree(wax);
+ return ret;
+diff --git a/drivers/pci/access.c b/drivers/pci/access.c
+index 46935695cfb90..8d0d1f61c650d 100644
+--- a/drivers/pci/access.c
++++ b/drivers/pci/access.c
+@@ -160,9 +160,12 @@ int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
+ * write happen to have any RW1C (write-one-to-clear) bits set, we
+ * just inadvertently cleared something we shouldn't have.
+ */
+- dev_warn_ratelimited(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
+- size, pci_domain_nr(bus), bus->number,
+- PCI_SLOT(devfn), PCI_FUNC(devfn), where);
++ if (!bus->unsafe_warn) {
++ dev_warn(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
++ size, pci_domain_nr(bus), bus->number,
++ PCI_SLOT(devfn), PCI_FUNC(devfn), where);
++ bus->unsafe_warn = 1;
++ }
+
+ mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
+ tmp = readl(addr) & mask;
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index ffb176d288cd9..918e11082e6a7 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
@@ -97722,6 +142010,34 @@ index 5fee0f89ab594..a224afadbcc00 100644
err_init:
err_get_sync:
pm_runtime_put_sync(dev);
+diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
+index 80fc98acf097f..2c05f2f7d1c0b 100644
+--- a/drivers/pci/controller/dwc/pci-imx6.c
++++ b/drivers/pci/controller/dwc/pci-imx6.c
+@@ -779,9 +779,7 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
+ /* Start LTSSM. */
+ imx6_pcie_ltssm_enable(dev);
+
+- ret = dw_pcie_wait_for_link(pci);
+- if (ret)
+- goto err_reset_phy;
++ dw_pcie_wait_for_link(pci);
+
+ if (pci->link_gen == 2) {
+ /* Allow Gen2 mode after the link is up. */
+@@ -817,11 +815,7 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
+ }
+
+ /* Make sure link training is finished as well! */
+- ret = dw_pcie_wait_for_link(pci);
+- if (ret) {
+- dev_err(dev, "Failed to bring link up!\n");
+- goto err_reset_phy;
+- }
++ dw_pcie_wait_for_link(pci);
+ } else {
+ dev_info(dev, "Link: Gen2 disabled\n");
+ }
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index a945f0c0e73dc..3254f60d1713f 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
@@ -97741,6 +142057,71 @@ index a945f0c0e73dc..3254f60d1713f 100644
pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
}
+diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
+index 00cde9a248b5a..78d002be4f821 100644
+--- a/drivers/pci/controller/dwc/pcie-fu740.c
++++ b/drivers/pci/controller/dwc/pcie-fu740.c
+@@ -181,10 +181,59 @@ static int fu740_pcie_start_link(struct dw_pcie *pci)
+ {
+ struct device *dev = pci->dev;
+ struct fu740_pcie *afp = dev_get_drvdata(dev);
++ u8 cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
++ int ret;
++ u32 orig, tmp;
++
++ /*
++ * Force 2.5GT/s when starting the link, due to some devices not
++ * probing at higher speeds. This happens with the PCIe switch
++ * on the Unmatched board when U-Boot has not initialised the PCIe.
++ * The fix in U-Boot is to force 2.5GT/s, which then gets cleared
++ * by the soft reset done by this driver.
++ */
++ dev_dbg(dev, "cap_exp at %x\n", cap_exp);
++ dw_pcie_dbi_ro_wr_en(pci);
++
++ tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
++ orig = tmp & PCI_EXP_LNKCAP_SLS;
++ tmp &= ~PCI_EXP_LNKCAP_SLS;
++ tmp |= PCI_EXP_LNKCAP_SLS_2_5GB;
++ dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
+
+ /* Enable LTSSM */
+ writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
+- return 0;
++
++ ret = dw_pcie_wait_for_link(pci);
++ if (ret) {
++ dev_err(dev, "error: link did not start\n");
++ goto err;
++ }
++
++ tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
++ if ((tmp & PCI_EXP_LNKCAP_SLS) != orig) {
++ dev_dbg(dev, "changing speed back to original\n");
++
++ tmp &= ~PCI_EXP_LNKCAP_SLS;
++ tmp |= orig;
++ dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
++
++ tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
++ tmp |= PORT_LOGIC_SPEED_CHANGE;
++ dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
++
++ ret = dw_pcie_wait_for_link(pci);
++ if (ret) {
++ dev_err(dev, "error: link did not start at new speed\n");
++ goto err;
++ }
++ }
++
++ ret = 0;
++err:
++ WARN_ON(ret); /* we assume that errors will be very rare */
++ dw_pcie_dbi_ro_wr_dis(pci);
++ return ret;
+ }
+
+ static int fu740_pcie_host_init(struct pcie_port *pp)
diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c
index d842fd0181299..d05be942956e2 100644
--- a/drivers/pci/controller/dwc/pcie-uniphier.c
@@ -97805,7 +142186,7 @@ index d842fd0181299..d05be942956e2 100644
.irq_unmask = uniphier_pcie_irq_unmask,
};
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
-index 596ebcfcc82dc..b2217e2b3efde 100644
+index 596ebcfcc82dc..7cc2c54daad03 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -31,9 +31,6 @@
@@ -97818,7 +142199,18 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
#define PCIE_CORE_DEV_REV_REG 0x8
#define PCIE_CORE_PCIEXP_CAP 0xc0
#define PCIE_CORE_ERR_CAPCTL_REG 0x118
-@@ -99,6 +96,7 @@
+@@ -41,10 +38,6 @@
+ #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6)
+ #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7)
+ #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8)
+-#define PCIE_CORE_INT_A_ASSERT_ENABLE 1
+-#define PCIE_CORE_INT_B_ASSERT_ENABLE 2
+-#define PCIE_CORE_INT_C_ASSERT_ENABLE 3
+-#define PCIE_CORE_INT_D_ASSERT_ENABLE 4
+ /* PIO registers base address and register offsets */
+ #define PIO_BASE_ADDR 0x4000
+ #define PIO_CTRL (PIO_BASE_ADDR + 0x0)
+@@ -99,25 +92,32 @@
#define PCIE_CORE_CTRL2_MSI_ENABLE BIT(10)
#define PCIE_CORE_REF_CLK_REG (CONTROL_BASE_ADDR + 0x14)
#define PCIE_CORE_REF_CLK_TX_ENABLE BIT(1)
@@ -97826,8 +142218,12 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
#define PCIE_MSG_LOG_REG (CONTROL_BASE_ADDR + 0x30)
#define PCIE_ISR0_REG (CONTROL_BASE_ADDR + 0x40)
#define PCIE_MSG_PM_PME_MASK BIT(7)
-@@ -106,18 +104,19 @@
+ #define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44)
#define PCIE_ISR0_MSI_INT_PENDING BIT(24)
++#define PCIE_ISR0_CORR_ERR BIT(11)
++#define PCIE_ISR0_NFAT_ERR BIT(12)
++#define PCIE_ISR0_FAT_ERR BIT(13)
++#define PCIE_ISR0_ERR_MASK GENMASK(13, 11)
#define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val))
#define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val))
-#define PCIE_ISR0_ALL_MASK GENMASK(26, 0)
@@ -97843,12 +142239,13 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
#define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C)
++#define PCIE_MSI_ALL_MASK GENMASK(31, 0)
#define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C)
+#define PCIE_MSI_DATA_MASK GENMASK(15, 0)
/* PCIe window configuration */
#define OB_WIN_BASE_ADDR 0x4c00
-@@ -164,8 +163,50 @@
+@@ -164,8 +164,50 @@
#define CFG_REG (LMI_BASE_ADDR + 0x0)
#define LTSSM_SHIFT 24
#define LTSSM_MASK 0x3f
@@ -97900,7 +142297,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
#define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44)
/* PCIe core controller registers */
-@@ -198,7 +239,7 @@
+@@ -198,7 +240,7 @@
#define PCIE_IRQ_MSI_INT2_DET BIT(21)
#define PCIE_IRQ_RC_DBELL_DET BIT(22)
#define PCIE_IRQ_EP_STATUS BIT(23)
@@ -97909,7 +142306,27 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
#define PCIE_IRQ_ENABLE_INTS_MASK PCIE_IRQ_CORE_INT
/* Transaction types */
-@@ -257,18 +298,49 @@ static inline u32 advk_readl(struct advk_pcie *pcie, u64 reg)
+@@ -230,17 +272,15 @@ struct advk_pcie {
+ u32 actions;
+ } wins[OB_WIN_COUNT];
+ u8 wins_count;
++ struct irq_domain *rp_irq_domain;
+ struct irq_domain *irq_domain;
+ struct irq_chip irq_chip;
+ raw_spinlock_t irq_lock;
+ struct irq_domain *msi_domain;
+ struct irq_domain *msi_inner_domain;
+- struct irq_chip msi_bottom_irq_chip;
+- struct irq_chip msi_irq_chip;
+- struct msi_domain_info msi_domain_info;
++ raw_spinlock_t msi_irq_lock;
+ DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
+ struct mutex msi_used_lock;
+- u16 msi_msg;
+ int link_gen;
+ struct pci_bridge_emul bridge;
+ struct gpio_desc *reset_gpio;
+@@ -257,18 +297,49 @@ static inline u32 advk_readl(struct advk_pcie *pcie, u64 reg)
return readl(pcie->base + reg);
}
@@ -97966,7 +142383,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
-@@ -291,7 +363,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
+@@ -291,7 +362,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
size_t retries;
for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) {
@@ -97975,7 +142392,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
break;
udelay(RETRAIN_WAIT_USLEEP_US);
}
-@@ -299,23 +371,9 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
+@@ -299,23 +370,9 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
static void advk_pcie_issue_perst(struct advk_pcie *pcie)
{
@@ -97999,7 +142416,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
/* 10ms delay is needed for some cards */
dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
-@@ -323,53 +381,46 @@ static void advk_pcie_issue_perst(struct advk_pcie *pcie)
+@@ -323,53 +380,46 @@ static void advk_pcie_issue_perst(struct advk_pcie *pcie)
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
}
@@ -98076,7 +142493,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
/*
* Reset PCIe card via PERST# signal. Some cards are not detected
* during link training when they are in some non-initial state.
-@@ -380,41 +431,18 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)
+@@ -380,41 +430,18 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)
* PERST# signal could have been asserted by pinctrl subsystem before
* probe() callback has been called or issued explicitly by reset gpio
* function advk_pcie_issue_perst(), making the endpoint going into
@@ -98129,7 +142546,11 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
/*
-@@ -451,9 +479,15 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+@@ -448,12 +475,19 @@ static void advk_pcie_disable_ob_win(struct advk_pcie *pcie, u8 win_num)
+
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
++ phys_addr_t msi_addr;
u32 reg;
int i;
@@ -98189,7 +142610,50 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
reg |= PCI_EXP_DEVCTL_READRQ_512B;
advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
-@@ -574,19 +634,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+@@ -504,25 +564,36 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ reg |= LANE_COUNT_1;
+ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+
++ /* Set MSI address */
++ msi_addr = virt_to_phys(pcie);
++ advk_writel(pcie, lower_32_bits(msi_addr), PCIE_MSI_ADDR_LOW_REG);
++ advk_writel(pcie, upper_32_bits(msi_addr), PCIE_MSI_ADDR_HIGH_REG);
++
+ /* Enable MSI */
+ reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
+ reg |= PCIE_CORE_CTRL2_MSI_ENABLE;
+ advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
+
+ /* Clear all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
+ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
+ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
+ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
+
+- /* Disable All ISR0/1 Sources */
+- reg = PCIE_ISR0_ALL_MASK;
++ /* Disable All ISR0/1 and MSI Sources */
++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
++
++ /* Unmask summary MSI interrupt */
++ reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+ reg &= ~PCIE_ISR0_MSI_INT_PENDING;
+ advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
+
+- advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
+-
+- /* Unmask all MSIs */
+- advk_writel(pcie, 0, PCIE_MSI_MASK_REG);
++ /* Unmask PME interrupt for processing of PME requester */
++ reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++ reg &= ~PCIE_MSG_PM_PME_MASK;
++ advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
+
+ /* Enable summary interrupt for GIC SPI source */
+ reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
+@@ -574,19 +645,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
advk_pcie_disable_ob_win(pcie, i);
advk_pcie_train_link(pcie);
@@ -98209,7 +142673,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val)
-@@ -595,6 +642,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
+@@ -595,6 +653,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
u32 reg;
unsigned int status;
char *strcomp_status, *str_posted;
@@ -98217,7 +142681,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
reg = advk_readl(pcie, PIO_STAT);
status = (reg & PIO_COMPLETION_STATUS_MASK) >>
-@@ -619,6 +667,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
+@@ -619,6 +678,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
case PIO_COMPLETION_STATUS_OK:
if (reg & PIO_ERR_STATUS) {
strcomp_status = "COMP_ERR";
@@ -98225,7 +142689,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
break;
}
/* Get the read result */
-@@ -626,9 +675,11 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
+@@ -626,9 +686,11 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
*val = advk_readl(pcie, PIO_RD_DATA);
/* No error */
strcomp_status = NULL;
@@ -98237,7 +142701,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
break;
case PIO_COMPLETION_STATUS_CRS:
if (allow_crs && val) {
-@@ -646,6 +697,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
+@@ -646,6 +708,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
*/
*val = CFG_RD_CRS_VAL;
strcomp_status = NULL;
@@ -98245,7 +142709,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
break;
}
/* PCIe r4.0, sec 2.3.2, says:
-@@ -661,31 +713,34 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
+@@ -661,31 +724,34 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3
* Request and taking appropriate action, e.g., complete the
* Request to the host as a failed transaction.
*
@@ -98285,7 +142749,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static int advk_pcie_wait_pio(struct advk_pcie *pcie)
-@@ -693,13 +748,13 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
+@@ -693,13 +759,13 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
struct device *dev = &pcie->pdev->dev;
int i;
@@ -98301,7 +142765,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
udelay(PIO_RETRY_DELAY);
}
-@@ -707,6 +762,64 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
+@@ -707,6 +773,81 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
return -ETIMEDOUT;
}
@@ -98319,11 +142783,15 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
+ case PCI_INTERRUPT_LINE: {
+ /*
+ * From the whole 32bit register we support reading from HW only
-+ * one bit: PCI_BRIDGE_CTL_BUS_RESET.
++ * two bits: PCI_BRIDGE_CTL_BUS_RESET and PCI_BRIDGE_CTL_SERR.
+ * Other bits are retrieved only from emulated config buffer.
+ */
+ __le32 *cfgspace = (__le32 *)&bridge->conf;
+ u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
++ if (advk_readl(pcie, PCIE_ISR0_MASK_REG) & PCIE_ISR0_ERR_MASK)
++ val &= ~(PCI_BRIDGE_CTL_SERR << 16);
++ else
++ val |= PCI_BRIDGE_CTL_SERR << 16;
+ if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN)
+ val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
+ else
@@ -98349,6 +142817,19 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
+ break;
+
+ case PCI_INTERRUPT_LINE:
++ /*
++ * According to Figure 6-3: Pseudo Logic Diagram for Error
++ * Message Controls in PCIe base specification, SERR# Enable bit
++ * in Bridge Control register enable receiving of ERR_* messages
++ */
++ if (mask & (PCI_BRIDGE_CTL_SERR << 16)) {
++ u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++ if (new & (PCI_BRIDGE_CTL_SERR << 16))
++ val &= ~PCIE_ISR0_ERR_MASK;
++ else
++ val |= PCIE_ISR0_ERR_MASK;
++ advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
++ }
+ if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
+ u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG);
+ if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
@@ -98366,18 +142847,26 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
static pci_bridge_emul_read_status_t
advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
-@@ -723,6 +836,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
- case PCI_EXP_RTCTL: {
- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
- *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
-+ *value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE;
- *value |= PCI_EXP_RTCAP_CRSVIS << 16;
- return PCI_BRIDGE_EMUL_HANDLED;
- }
-@@ -734,20 +848,32 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+@@ -720,17 +861,21 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+ *value = PCI_EXP_SLTSTA_PDS << 16;
return PCI_BRIDGE_EMUL_HANDLED;
- }
+- case PCI_EXP_RTCTL: {
+- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+- *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
+- *value |= PCI_EXP_RTCAP_CRSVIS << 16;
+- return PCI_BRIDGE_EMUL_HANDLED;
+- }
++ /*
++ * PCI_EXP_RTCTL and PCI_EXP_RTSTA are also supported, but do not need
++ * to be handled here, because their values are stored in emulated
++ * config space buffer, and we read them from there when needed.
++ */
+
+- case PCI_EXP_RTSTA: {
+- u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
+- u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
+- *value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16);
+ case PCI_EXP_LNKCAP: {
+ u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
+ /*
@@ -98387,10 +142876,10 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
+ */
+ val |= PCI_EXP_LNKCAP_DLLLARC;
+ *value = val;
-+ return PCI_BRIDGE_EMUL_HANDLED;
-+ }
-+
- case PCI_EXP_LNKCTL: {
+ return PCI_BRIDGE_EMUL_HANDLED;
+ }
+
+@@ -738,18 +883,23 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */
u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &
~(PCI_EXP_LNKSTA_LT << 16);
@@ -98407,10 +142896,61 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
case PCI_EXP_DEVCAP:
case PCI_EXP_DEVCTL:
- case PCI_EXP_LNKCAP:
++ case PCI_EXP_DEVCAP2:
++ case PCI_EXP_DEVCTL2:
++ case PCI_EXP_LNKCAP2:
++ case PCI_EXP_LNKCTL2:
*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
return PCI_BRIDGE_EMUL_HANDLED;
++
default:
-@@ -794,6 +920,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ return PCI_BRIDGE_EMUL_NOT_HANDLED;
+ }
+@@ -763,10 +913,6 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ struct advk_pcie *pcie = bridge->data;
+
+ switch (reg) {
+- case PCI_EXP_DEVCTL:
+- advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+- break;
+-
+ case PCI_EXP_LNKCTL:
+ advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+ if (new & PCI_EXP_LNKCTL_RL)
+@@ -774,18 +920,23 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ break;
+
+ case PCI_EXP_RTCTL: {
+- /* Only mask/unmask PME interrupt */
+- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) &
+- ~PCIE_MSG_PM_PME_MASK;
+- if ((new & PCI_EXP_RTCTL_PMEIE) == 0)
+- val |= PCIE_MSG_PM_PME_MASK;
+- advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
++ u16 rootctl = le16_to_cpu(bridge->pcie_conf.rootctl);
++ /* Only emulation of PMEIE and CRSSVE bits is provided */
++ rootctl &= PCI_EXP_RTCTL_PMEIE | PCI_EXP_RTCTL_CRSSVE;
++ bridge->pcie_conf.rootctl = cpu_to_le16(rootctl);
+ break;
+ }
+
+- case PCI_EXP_RTSTA:
+- new = (new & PCI_EXP_RTSTA_PME) >> 9;
+- advk_writel(pcie, new, PCIE_ISR0_REG);
++ /*
++ * PCI_EXP_RTSTA is also supported, but does not need to be handled
++ * here, because its value is stored in emulated config space buffer,
++ * and we write it there when needed.
++ */
++
++ case PCI_EXP_DEVCTL:
++ case PCI_EXP_DEVCTL2:
++ case PCI_EXP_LNKCTL2:
++ advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+ break;
+
+ default:
+@@ -794,6 +945,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
}
static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
@@ -98419,7 +142959,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
.read_pcie = advk_pci_bridge_emul_pcie_conf_read,
.write_pcie = advk_pci_bridge_emul_pcie_conf_write,
};
-@@ -805,7 +933,6 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
+@@ -805,7 +958,6 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
{
struct pci_bridge_emul *bridge = &pcie->bridge;
@@ -98427,9 +142967,12 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
bridge->conf.vendor =
cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
-@@ -825,19 +952,17 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
+@@ -823,21 +975,19 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
+ bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
+
/* Support interrupt A for MSI feature */
- bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
+- bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
++ bridge->conf.intpin = PCI_INTERRUPT_INTA;
- bridge->has_pcie = true;
- bridge->data = pcie;
@@ -98454,7 +142997,22 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
-@@ -889,6 +1014,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
+@@ -847,8 +997,12 @@ static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
+ return false;
+
+ /*
+- * If the link goes down after we check for link-up, nothing bad
+- * happens but the config access times out.
++ * If the link goes down after we check for link-up, we have a problem:
++ * if a PIO request is executed while link-down, the whole controller
++ * gets stuck in a non-functional state, and even after link comes up
++ * again, PIO requests won't work anymore, and a reset of the whole PCIe
++ * controller is needed. Therefore we need to prevent sending PIO
++ * requests while the link is down.
+ */
+ if (!pci_is_root_bus(bus) && !advk_pcie_link_up(pcie))
+ return false;
+@@ -889,6 +1043,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 *val)
{
struct advk_pcie *pcie = bus->sysdata;
@@ -98462,7 +143020,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
bool allow_crs;
u32 reg;
int ret;
-@@ -911,18 +1037,8 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
+@@ -911,18 +1066,8 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) &
PCI_EXP_RTCTL_CRSSVE);
@@ -98483,7 +143041,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
/* Program the control register */
reg = advk_readl(pcie, PIO_CTRL);
-@@ -941,30 +1057,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
+@@ -941,30 +1086,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
/* Program the data strobe */
advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
@@ -98530,7 +143088,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
-@@ -972,6 +1082,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
+@@ -972,6 +1111,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
*val = (*val >> (8 * (where & 3))) & 0xffff;
return PCIBIOS_SUCCESSFUL;
@@ -98551,7 +143109,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
-@@ -980,6 +1104,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+@@ -980,6 +1133,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
struct advk_pcie *pcie = bus->sysdata;
u32 reg;
u32 data_strobe = 0x0;
@@ -98559,7 +143117,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
int offset;
int ret;
-@@ -1021,19 +1146,22 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+@@ -1021,19 +1175,22 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
/* Program the data strobe */
advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB);
@@ -98592,7 +143150,99 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static struct pci_ops advk_pcie_ops = {
-@@ -1082,7 +1210,7 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+@@ -1045,11 +1202,11 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
+ struct msi_msg *msg)
+ {
+ struct advk_pcie *pcie = irq_data_get_irq_chip_data(data);
+- phys_addr_t msi_msg = virt_to_phys(&pcie->msi_msg);
++ phys_addr_t msi_addr = virt_to_phys(pcie);
+
+- msg->address_lo = lower_32_bits(msi_msg);
+- msg->address_hi = upper_32_bits(msi_msg);
+- msg->data = data->irq;
++ msg->address_lo = lower_32_bits(msi_addr);
++ msg->address_hi = upper_32_bits(msi_addr);
++ msg->data = data->hwirq;
+ }
+
+ static int advk_msi_set_affinity(struct irq_data *irq_data,
+@@ -1058,6 +1215,54 @@ static int advk_msi_set_affinity(struct irq_data *irq_data,
+ return -EINVAL;
+ }
+
++static void advk_msi_irq_mask(struct irq_data *d)
++{
++ struct advk_pcie *pcie = d->domain->host_data;
++ irq_hw_number_t hwirq = irqd_to_hwirq(d);
++ unsigned long flags;
++ u32 mask;
++
++ raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
++ mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
++ mask |= BIT(hwirq);
++ advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
++ raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
++}
++
++static void advk_msi_irq_unmask(struct irq_data *d)
++{
++ struct advk_pcie *pcie = d->domain->host_data;
++ irq_hw_number_t hwirq = irqd_to_hwirq(d);
++ unsigned long flags;
++ u32 mask;
++
++ raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
++ mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
++ mask &= ~BIT(hwirq);
++ advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
++ raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
++}
++
++static void advk_msi_top_irq_mask(struct irq_data *d)
++{
++ pci_msi_mask_irq(d);
++ irq_chip_mask_parent(d);
++}
++
++static void advk_msi_top_irq_unmask(struct irq_data *d)
++{
++ pci_msi_unmask_irq(d);
++ irq_chip_unmask_parent(d);
++}
++
++static struct irq_chip advk_msi_bottom_irq_chip = {
++ .name = "MSI",
++ .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg,
++ .irq_set_affinity = advk_msi_set_affinity,
++ .irq_mask = advk_msi_irq_mask,
++ .irq_unmask = advk_msi_irq_unmask,
++};
++
+ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs, void *args)
+@@ -1066,23 +1271,19 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+ int hwirq, i;
+
+ mutex_lock(&pcie->msi_used_lock);
+- hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
+- 0, nr_irqs, 0);
+- if (hwirq >= MSI_IRQ_NUM) {
+- mutex_unlock(&pcie->msi_used_lock);
+- return -ENOSPC;
+- }
+-
+- bitmap_set(pcie->msi_used, hwirq, nr_irqs);
++ hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
++ order_base_2(nr_irqs));
+ mutex_unlock(&pcie->msi_used_lock);
++ if (hwirq < 0)
++ return -ENOSPC;
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_info(domain, virq + i, hwirq + i,
+- &pcie->msi_bottom_irq_chip,
++ &advk_msi_bottom_irq_chip,
domain->host_data, handle_simple_irq,
NULL, NULL);
@@ -98601,21 +143251,185 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
}
static void advk_msi_irq_domain_free(struct irq_domain *domain,
-@@ -1263,8 +1391,12 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
- if (!(BIT(msi_idx) & msi_status))
- continue;
+@@ -1092,7 +1293,7 @@ static void advk_msi_irq_domain_free(struct irq_domain *domain,
+ struct advk_pcie *pcie = domain->host_data;
+
+ mutex_lock(&pcie->msi_used_lock);
+- bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
++ bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
+ mutex_unlock(&pcie->msi_used_lock);
+ }
+
+@@ -1134,7 +1335,6 @@ static int advk_pcie_irq_map(struct irq_domain *h,
+ {
+ struct advk_pcie *pcie = h->host_data;
+
+- advk_pcie_irq_mask(irq_get_irq_data(virq));
+ irq_set_status_flags(virq, IRQ_LEVEL);
+ irq_set_chip_and_handler(virq, &pcie->irq_chip,
+ handle_level_irq);
+@@ -1148,37 +1348,25 @@ static const struct irq_domain_ops advk_pcie_irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ };
++static struct irq_chip advk_msi_irq_chip = {
++ .name = "advk-MSI",
++ .irq_mask = advk_msi_top_irq_mask,
++ .irq_unmask = advk_msi_top_irq_unmask,
++};
++
++static struct msi_domain_info advk_msi_domain_info = {
++ .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
++ MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
++ .chip = &advk_msi_irq_chip,
++};
++
+ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ {
+ struct device *dev = &pcie->pdev->dev;
+- struct device_node *node = dev->of_node;
+- struct irq_chip *bottom_ic, *msi_ic;
+- struct msi_domain_info *msi_di;
+- phys_addr_t msi_msg_phys;
+
++ raw_spin_lock_init(&pcie->msi_irq_lock);
+ mutex_init(&pcie->msi_used_lock);
+
+- bottom_ic = &pcie->msi_bottom_irq_chip;
+-
+- bottom_ic->name = "MSI";
+- bottom_ic->irq_compose_msi_msg = advk_msi_irq_compose_msi_msg;
+- bottom_ic->irq_set_affinity = advk_msi_set_affinity;
+-
+- msi_ic = &pcie->msi_irq_chip;
+- msi_ic->name = "advk-MSI";
+-
+- msi_di = &pcie->msi_domain_info;
+- msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+- MSI_FLAG_MULTI_PCI_MSI;
+- msi_di->chip = msi_ic;
+-
+- msi_msg_phys = virt_to_phys(&pcie->msi_msg);
+-
+- advk_writel(pcie, lower_32_bits(msi_msg_phys),
+- PCIE_MSI_ADDR_LOW_REG);
+- advk_writel(pcie, upper_32_bits(msi_msg_phys),
+- PCIE_MSI_ADDR_HIGH_REG);
+-
+ pcie->msi_inner_domain =
+ irq_domain_add_linear(NULL, MSI_IRQ_NUM,
+ &advk_msi_domain_ops, pcie);
+@@ -1186,8 +1374,9 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ return -ENOMEM;
+
+ pcie->msi_domain =
+- pci_msi_create_irq_domain(of_node_to_fwnode(node),
+- msi_di, pcie->msi_inner_domain);
++ pci_msi_create_irq_domain(dev_fwnode(dev),
++ &advk_msi_domain_info,
++ pcie->msi_inner_domain);
+ if (!pcie->msi_domain) {
+ irq_domain_remove(pcie->msi_inner_domain);
+ return -ENOMEM;
+@@ -1228,7 +1417,6 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
+ }
+
+ irq_chip->irq_mask = advk_pcie_irq_mask;
+- irq_chip->irq_mask_ack = advk_pcie_irq_mask;
+ irq_chip->irq_unmask = advk_pcie_irq_unmask;
+
+ pcie->irq_domain =
+@@ -1250,22 +1438,85 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
+ irq_domain_remove(pcie->irq_domain);
+ }
+
++static struct irq_chip advk_rp_irq_chip = {
++ .name = "advk-RP",
++};
++
++static int advk_pcie_rp_irq_map(struct irq_domain *h,
++ unsigned int virq, irq_hw_number_t hwirq)
++{
++ struct advk_pcie *pcie = h->host_data;
++
++ irq_set_chip_and_handler(virq, &advk_rp_irq_chip, handle_simple_irq);
++ irq_set_chip_data(virq, pcie);
++
++ return 0;
++}
++
++static const struct irq_domain_ops advk_pcie_rp_irq_domain_ops = {
++ .map = advk_pcie_rp_irq_map,
++ .xlate = irq_domain_xlate_onecell,
++};
++
++static int advk_pcie_init_rp_irq_domain(struct advk_pcie *pcie)
++{
++ pcie->rp_irq_domain = irq_domain_add_linear(NULL, 1,
++ &advk_pcie_rp_irq_domain_ops,
++ pcie);
++ if (!pcie->rp_irq_domain) {
++ dev_err(&pcie->pdev->dev, "Failed to add Root Port IRQ domain\n");
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static void advk_pcie_remove_rp_irq_domain(struct advk_pcie *pcie)
++{
++ irq_domain_remove(pcie->rp_irq_domain);
++}
++
++static void advk_pcie_handle_pme(struct advk_pcie *pcie)
++{
++ u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16;
++
++ advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
++
++ /*
++ * PCIE_MSG_LOG_REG contains the last inbound message, so store
++ * the requester ID only when PME was not asserted yet.
++ * Also do not trigger PME interrupt when PME is still asserted.
++ */
++ if (!(le32_to_cpu(pcie->bridge.pcie_conf.rootsta) & PCI_EXP_RTSTA_PME)) {
++ pcie->bridge.pcie_conf.rootsta = cpu_to_le32(requester | PCI_EXP_RTSTA_PME);
++
+ /*
-+ * msi_idx contains bits [4:0] of the msi_data and msi_data
-+ * contains 16bit MSI interrupt number
++ * Trigger PME interrupt only if PMEIE bit in Root Control is set.
++ * Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, so use PCIe interrupt 0.
+ */
++ if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE))
++ return;
++
++ if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL)
++ dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
++ }
++}
++
+ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
+ {
+ u32 msi_val, msi_mask, msi_status, msi_idx;
+- u16 msi_data;
+
+ msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
+ msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG);
+- msi_status = msi_val & ~msi_mask;
++ msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK);
+
+ for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) {
+ if (!(BIT(msi_idx) & msi_status))
+ continue;
+
advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG);
- msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF;
-+ msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK;
- generic_handle_irq(msi_data);
+- generic_handle_irq(msi_data);
++ if (generic_handle_domain_irq(pcie->msi_inner_domain, msi_idx) == -EINVAL)
++ dev_err_ratelimited(&pcie->pdev->dev, "unexpected MSI 0x%02x\n", msi_idx);
}
-@@ -1286,12 +1418,6 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ advk_writel(pcie, PCIE_ISR0_MSI_INT_PENDING,
+@@ -1286,10 +1537,20 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
@@ -98623,12 +143437,59 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
- advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
- advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
- return;
-- }
--
++ /* Process PME interrupt as the first one to do not miss PME requester id */
++ if (isr0_status & PCIE_MSG_PM_PME_MASK)
++ advk_pcie_handle_pme(pcie);
++
++ /* Process ERR interrupt */
++ if (isr0_status & PCIE_ISR0_ERR_MASK) {
++ advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG);
++
++ /*
++ * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use
++ * PCIe interrupt 0
++ */
++ if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL)
++ dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n");
+ }
+
/* Process MSI interrupts */
- if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
- advk_pcie_handle_msi(pcie);
-@@ -1411,8 +1537,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
+@@ -1304,7 +1565,9 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
+ PCIE_ISR1_REG);
+
+- generic_handle_domain_irq(pcie->irq_domain, i);
++ if (generic_handle_domain_irq(pcie->irq_domain, i) == -EINVAL)
++ dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n",
++ (char)i + 'A');
+ }
+ }
+
+@@ -1325,7 +1588,22 @@ static irqreturn_t advk_pcie_irq_handler(int irq, void *arg)
+ return IRQ_HANDLED;
+ }
+
+-static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie)
++static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ struct advk_pcie *pcie = dev->bus->sysdata;
++
++ /*
++ * Emulated root bridge has its own emulated irq chip and irq domain.
++ * Argument pin is the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) and
++ * hwirq for irq_create_mapping() is indexed from zero.
++ */
++ if (pci_is_root_bus(dev->bus))
++ return irq_create_mapping(pcie->rp_irq_domain, pin - 1);
++ else
++ return of_irq_parse_and_map_pci(dev, slot, pin);
++}
++
++static void advk_pcie_disable_phy(struct advk_pcie *pcie)
+ {
+ phy_power_off(pcie->phy);
+ phy_exit(pcie->phy);
+@@ -1411,8 +1689,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
* only PIO for issuing configuration transfers which does
* not use PCIe window configuration.
*/
@@ -98638,7 +143499,7 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
continue;
/*
-@@ -1420,8 +1545,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
+@@ -1420,8 +1697,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
* configuration is set to transparent memory access so it
* does not need window configuration.
*/
@@ -98648,8 +143509,96 @@ index 596ebcfcc82dc..b2217e2b3efde 100644
continue;
/*
+@@ -1536,11 +1812,21 @@ static int advk_pcie_probe(struct platform_device *pdev)
+ return ret;
+ }
+
++ ret = advk_pcie_init_rp_irq_domain(pcie);
++ if (ret) {
++ dev_err(dev, "Failed to initialize irq\n");
++ advk_pcie_remove_msi_irq_domain(pcie);
++ advk_pcie_remove_irq_domain(pcie);
++ return ret;
++ }
++
+ bridge->sysdata = pcie;
+ bridge->ops = &advk_pcie_ops;
++ bridge->map_irq = advk_pcie_map_irq;
+
+ ret = pci_host_probe(bridge);
+ if (ret < 0) {
++ advk_pcie_remove_rp_irq_domain(pcie);
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
+ return ret;
+@@ -1553,20 +1839,65 @@ static int advk_pcie_remove(struct platform_device *pdev)
+ {
+ struct advk_pcie *pcie = platform_get_drvdata(pdev);
+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ u32 val;
+ int i;
+
++ /* Remove PCI bus with all devices */
+ pci_lock_rescan_remove();
+ pci_stop_root_bus(bridge->bus);
+ pci_remove_root_bus(bridge->bus);
+ pci_unlock_rescan_remove();
+
++ /* Disable Root Bridge I/O space, memory space and bus mastering */
++ val = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
++ val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++ advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG);
++
++ /* Disable MSI */
++ val = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
++ val &= ~PCIE_CORE_CTRL2_MSI_ENABLE;
++ advk_writel(pcie, val, PCIE_CORE_CTRL2_REG);
++
++ /* Clear MSI address */
++ advk_writel(pcie, 0, PCIE_MSI_ADDR_LOW_REG);
++ advk_writel(pcie, 0, PCIE_MSI_ADDR_HIGH_REG);
++
++ /* Mask all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_MASK_REG);
++
++ /* Clear all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
++
++ /* Remove IRQ domains */
++ advk_pcie_remove_rp_irq_domain(pcie);
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
+
++ /* Free config space for emulated root bridge */
++ pci_bridge_emul_cleanup(&pcie->bridge);
++
++ /* Assert PERST# signal which prepares PCIe card for power down */
++ if (pcie->reset_gpio)
++ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
++
++ /* Disable link training */
++ val = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++ val &= ~LINK_TRAINING_EN;
++ advk_writel(pcie, val, PCIE_CORE_CTRL0_REG);
++
+ /* Disable outbound address windows mapping */
+ for (i = 0; i < OB_WIN_COUNT; i++)
+ advk_pcie_disable_ob_win(pcie, i);
+
++ /* Disable phy */
++ advk_pcie_disable_phy(pcie);
++
+ return 0;
+ }
+
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
-index 67c46e52c0dc3..9dd4502d32a41 100644
+index 67c46e52c0dc3..5b156c563e3a4 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -1899,8 +1899,17 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
@@ -98672,6 +143621,22 @@ index 67c46e52c0dc3..9dd4502d32a41 100644
put_pcichild(hv_dev);
}
+@@ -3139,6 +3148,15 @@ static int hv_pci_probe(struct hv_device *hdev,
+ hbus->bridge->domain_nr = dom;
+ #ifdef CONFIG_X86
+ hbus->sysdata.domain = dom;
++#elif defined(CONFIG_ARM64)
++ /*
++ * Set the PCI bus parent to be the corresponding VMbus
++ * device. Then the VMbus device will be assigned as the
++ * ACPI companion in pcibios_root_bridge_prepare() and
++ * pci_dma_configure() will propagate device coherence
++ * information to devices created on the bus.
++ */
++ hbus->sysdata.parent = hdev->device.parent;
+ #endif
+
+ hbus->hdev = hdev;
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index ed13e81cd691d..2a3bf82aa4e26 100644
--- a/drivers/pci/controller/pci-mvebu.c
@@ -99067,18 +144032,74 @@ index ed13e81cd691d..2a3bf82aa4e26 100644
pcie->nports = i;
diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
-index e64536047b651..7d7d8970fdc25 100644
+index e64536047b651..4641e57487cfd 100644
--- a/drivers/pci/controller/pci-xgene.c
+++ b/drivers/pci/controller/pci-xgene.c
-@@ -466,7 +466,7 @@ static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size)
- return 1;
+@@ -480,28 +480,27 @@ static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size)
+ }
+
+ static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
+- struct resource_entry *entry,
+- u8 *ib_reg_mask)
++ struct of_pci_range *range, u8 *ib_reg_mask)
+ {
+ void __iomem *cfg_base = port->cfg_base;
+ struct device *dev = port->dev;
+ void __iomem *bar_addr;
+ u32 pim_reg;
+- u64 cpu_addr = entry->res->start;
+- u64 pci_addr = cpu_addr - entry->offset;
+- u64 size = resource_size(entry->res);
++ u64 cpu_addr = range->cpu_addr;
++ u64 pci_addr = range->pci_addr;
++ u64 size = range->size;
+ u64 mask = ~(size - 1) | EN_REG;
+ u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64;
+ u32 bar_low;
+ int region;
+
+- region = xgene_pcie_select_ib_reg(ib_reg_mask, size);
++ region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size);
+ if (region < 0) {
+ dev_warn(dev, "invalid pcie dma-range config\n");
+ return;
}
-- if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) {
-+ if ((size > SZ_1K) && (size < SZ_4G) && !(*ib_reg_mask & (1 << 0))) {
- *ib_reg_mask |= (1 << 0);
- return 0;
- }
+- if (entry->res->flags & IORESOURCE_PREFETCH)
++ if (range->flags & IORESOURCE_PREFETCH)
+ flags |= PCI_BASE_ADDRESS_MEM_PREFETCH;
+
+ bar_low = pcie_bar_low_val((u32)cpu_addr, flags);
+@@ -532,13 +531,25 @@ static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
+
+ static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port)
+ {
+- struct pci_host_bridge *bridge = pci_host_bridge_from_priv(port);
+- struct resource_entry *entry;
++ struct device_node *np = port->node;
++ struct of_pci_range range;
++ struct of_pci_range_parser parser;
++ struct device *dev = port->dev;
+ u8 ib_reg_mask = 0;
+
+- resource_list_for_each_entry(entry, &bridge->dma_ranges)
+- xgene_pcie_setup_ib_reg(port, entry, &ib_reg_mask);
++ if (of_pci_dma_range_parser_init(&parser, np)) {
++ dev_err(dev, "missing dma-ranges property\n");
++ return -EINVAL;
++ }
++
++ /* Get the dma-ranges from DT */
++ for_each_of_pci_range(&parser, &range) {
++ u64 end = range.cpu_addr + range.size - 1;
+
++ dev_dbg(dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
++ range.flags, range.cpu_addr, end, range.pci_addr);
++ xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask);
++ }
+ return 0;
+ }
+
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index 17c59b0d6978b..21207df680ccf 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -99141,6 +144162,38 @@ index 8f3131844e777..bfb13f358d073 100644
ret = 1;
goto unlock_exit;
}
+diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
+index 90d84d3bc868f..5b833f00e9800 100644
+--- a/drivers/pci/endpoint/functions/pci-epf-test.c
++++ b/drivers/pci/endpoint/functions/pci-epf-test.c
+@@ -285,7 +285,17 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
+ if (ret)
+ dev_err(dev, "Data transfer failed\n");
+ } else {
+- memcpy(dst_addr, src_addr, reg->size);
++ void *buf;
++
++ buf = kzalloc(reg->size, GFP_KERNEL);
++ if (!buf) {
++ ret = -ENOMEM;
++ goto err_map_addr;
++ }
++
++ memcpy_fromio(buf, src_addr, reg->size);
++ memcpy_toio(dst_addr, buf, reg->size);
++ kfree(buf);
+ }
+ ktime_get_ts64(&end);
+ pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma);
+@@ -441,7 +451,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
+ if (!epf_test->dma_supported) {
+ dev_err(dev, "Cannot transfer data using DMA\n");
+ ret = -EINVAL;
+- goto err_map_addr;
++ goto err_dma_map;
+ }
+
+ src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 69fd401691be6..10d7e7e1b5530 100644
--- a/drivers/pci/hotplug/pciehp.h
@@ -99176,10 +144229,19 @@ index ad3393930ecb4..e7fe4b42f0394 100644
occupied = pciehp_card_present_or_link_active(ctrl);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
-index 3024d7e85e6a7..b0692f33b03ae 100644
+index 3024d7e85e6a7..8bedbc77fe95f 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
-@@ -583,7 +583,7 @@ static void pciehp_ignore_dpc_link_change(struct controller *ctrl,
+@@ -98,6 +98,8 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout)
+ if (slot_status & PCI_EXP_SLTSTA_CC) {
+ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_CC);
++ ctrl->cmd_busy = 0;
++ smp_mb();
+ return 1;
+ }
+ msleep(10);
+@@ -583,7 +585,7 @@ static void pciehp_ignore_dpc_link_change(struct controller *ctrl,
* the corresponding link change may have been ignored above.
* Synthesize it to ensure that it is acted on.
*/
@@ -99188,7 +144250,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
if (!pciehp_check_link_active(ctrl))
pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC);
up_read(&ctrl->reset_lock);
-@@ -642,6 +642,8 @@ read_status:
+@@ -642,6 +644,8 @@ read_status:
*/
if (ctrl->power_fault_detected)
status &= ~PCI_EXP_SLTSTA_PFD;
@@ -99197,7 +144259,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
events |= status;
if (!events) {
-@@ -651,7 +653,7 @@ read_status:
+@@ -651,7 +655,7 @@ read_status:
}
if (status) {
@@ -99206,7 +144268,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
/*
* In MSI mode, all event bits must be zero before the port
-@@ -725,8 +727,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
+@@ -725,8 +729,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
}
/* Check Power Fault Detected */
@@ -99216,7 +144278,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
PCI_EXP_SLTCTL_ATTN_IND_ON);
-@@ -746,7 +747,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
+@@ -746,7 +749,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
* Disable requests have higher priority than Presence Detect Changed
* or Data Link Layer State Changed events.
*/
@@ -99225,7 +144287,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
if (events & DISABLE_SLOT)
pciehp_handle_disable_request(ctrl);
else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC))
-@@ -880,7 +881,7 @@ int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe)
+@@ -880,7 +883,7 @@ int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe)
if (probe)
return 0;
@@ -99234,7 +144296,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
if (!ATTN_BUTTN(ctrl)) {
ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
-@@ -936,6 +937,20 @@ static inline void dbg_ctrl(struct controller *ctrl)
+@@ -936,6 +939,20 @@ static inline void dbg_ctrl(struct controller *ctrl)
#define FLAG(x, y) (((x) & (y)) ? '+' : '-')
@@ -99255,7 +144317,7 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
struct controller *pcie_init(struct pcie_device *dev)
{
struct controller *ctrl;
-@@ -949,6 +964,7 @@ struct controller *pcie_init(struct pcie_device *dev)
+@@ -949,6 +966,7 @@ struct controller *pcie_init(struct pcie_device *dev)
return NULL;
ctrl->pcie = dev;
@@ -99263,6 +144325,15 @@ index 3024d7e85e6a7..b0692f33b03ae 100644
pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
if (pdev->hotplug_user_indicators)
+@@ -1042,6 +1060,8 @@ static void quirk_cmd_compl(struct pci_dev *pdev)
+ }
+ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+ PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
++DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0110,
++ PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
+ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0400,
+ PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
+ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0401,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 4b4792940e869..cc4c2b8a5efd7 100644
--- a/drivers/pci/msi.c
@@ -99472,7 +144543,7 @@ index 4b4792940e869..cc4c2b8a5efd7 100644
WARN_ON_ONCE(1);
return NULL;
diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
-index fdaf86a888b73..37504c2cce9b8 100644
+index fdaf86a888b73..c994ebec23603 100644
--- a/drivers/pci/pci-bridge-emul.c
+++ b/drivers/pci/pci-bridge-emul.c
@@ -139,8 +139,13 @@ struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = {
@@ -99557,7 +144628,70 @@ index fdaf86a888b73..37504c2cce9b8 100644
.ro = GENMASK(13, 0) << 16,
.w1c = GENMASK(15, 14) << 16,
},
-@@ -277,11 +296,9 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
+@@ -251,6 +270,49 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
+ .ro = GENMASK(15, 0) | PCI_EXP_RTSTA_PENDING,
+ .w1c = PCI_EXP_RTSTA_PME,
+ },
++
++ [PCI_EXP_DEVCAP2 / 4] = {
++ /*
++ * Device capabilities 2 register has reserved bits [30:27].
++ * Also bits [26:24] are reserved for non-upstream ports.
++ */
++ .ro = BIT(31) | GENMASK(23, 0),
++ },
++
++ [PCI_EXP_DEVCTL2 / 4] = {
++ /*
++ * Device control 2 register is RW. Bit 11 is reserved for
++ * non-upstream ports.
++ *
++ * Device status 2 register is reserved.
++ */
++ .rw = GENMASK(15, 12) | GENMASK(10, 0),
++ },
++
++ [PCI_EXP_LNKCAP2 / 4] = {
++ /* Link capabilities 2 register has reserved bits [30:25] and 0. */
++ .ro = BIT(31) | GENMASK(24, 1),
++ },
++
++ [PCI_EXP_LNKCTL2 / 4] = {
++ /*
++ * Link control 2 register is RW.
++ *
++ * Link status 2 register has bits 5, 15 W1C;
++ * bits 10, 11 reserved and others are RO.
++ */
++ .rw = GENMASK(15, 0),
++ .w1c = (BIT(15) | BIT(5)) << 16,
++ .ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16,
++ },
++
++ [PCI_EXP_SLTCAP2 / 4] = {
++ /* Slot capabilities 2 register is reserved. */
++ },
++
++ [PCI_EXP_SLTCTL2 / 4] = {
++ /* Both Slot control 2 and Slot status 2 registers are reserved. */
++ },
+ };
+
+ /*
+@@ -265,7 +327,11 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
+ {
+ BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END);
+
+- bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
++ /*
++ * class_revision: Class is high 24 bits and revision is low 8 bit of this member,
++ * while class for PCI Bridge Normal Decode has the 24-bit value: PCI_CLASS_BRIDGE_PCI << 8
++ */
++ bridge->conf.class_revision |= cpu_to_le32((PCI_CLASS_BRIDGE_PCI << 8) << 8);
+ bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
+ bridge->conf.cache_line_size = 0x10;
+ bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);
+@@ -277,11 +343,9 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
if (bridge->has_pcie) {
bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
@@ -99571,7 +144705,7 @@ index fdaf86a888b73..37504c2cce9b8 100644
bridge->pcie_cap_regs_behavior =
kmemdup(pcie_cap_regs_behavior,
sizeof(pcie_cap_regs_behavior),
-@@ -290,6 +307,27 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
+@@ -290,6 +354,27 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
kfree(bridge->pci_regs_behavior);
return -ENOMEM;
}
@@ -99599,7 +144733,7 @@ index fdaf86a888b73..37504c2cce9b8 100644
}
if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) {
-@@ -431,8 +469,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
+@@ -431,8 +516,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
/* Clear the W1C bits */
new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
@@ -99622,10 +144756,27 @@ index fdaf86a888b73..37504c2cce9b8 100644
write_op(bridge, reg, old, new, mask);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index ce2ab62b64cfa..a101faf3e88a9 100644
+index ce2ab62b64cfa..0380543d10fdc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
-@@ -3719,6 +3719,14 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
+@@ -2888,6 +2888,16 @@ static const struct dmi_system_id bridge_d3_blacklist[] = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "X299 DESIGNARE EX-CF"),
+ },
++ /*
++ * Downstream device is not accessible after putting a root port
++ * into D3cold and back into D0 on Elo i2.
++ */
++ .ident = "Elo i2",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"),
++ },
+ },
+ #endif
+ { }
+@@ -3719,6 +3729,14 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
struct pci_dev *bridge;
u32 cap, ctl2;
@@ -99641,10 +144792,29 @@ index ce2ab62b64cfa..a101faf3e88a9 100644
return -EINVAL;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
-index 4537d1ea14fdc..0663762ea69db 100644
+index 4537d1ea14fdc..4893b1e824031 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
-@@ -3612,6 +3612,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
+@@ -1811,6 +1811,18 @@ static void quirk_alder_ioapic(struct pci_dev *pdev)
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
+ #endif
+
++static void quirk_no_msi(struct pci_dev *dev)
++{
++ pci_info(dev, "avoiding MSI to work around a hardware defect\n");
++ dev->no_msi = 1;
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4386, quirk_no_msi);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4387, quirk_no_msi);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4388, quirk_no_msi);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4389, quirk_no_msi);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x438a, quirk_no_msi);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x438b, quirk_no_msi);
++
+ static void quirk_pcie_mch(struct pci_dev *pdev)
+ {
+ pdev->no_msi = 1;
+@@ -3612,6 +3624,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
@@ -99652,7 +144822,7 @@ index 4537d1ea14fdc..0663762ea69db 100644
/*
* Root port on some Cavium CN8xxx chips do not successfully complete a bus
-@@ -4102,6 +4103,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9120,
+@@ -4102,6 +4115,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9120,
quirk_dma_func1_alias);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9123,
quirk_dma_func1_alias);
@@ -99662,7 +144832,39 @@ index 4537d1ea14fdc..0663762ea69db 100644
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9128,
quirk_dma_func1_alias);
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */
-@@ -5795,3 +5799,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev)
+@@ -5340,11 +5356,6 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0422, quirk_no_ext_tags);
+ */
+ static void quirk_amd_harvest_no_ats(struct pci_dev *pdev)
+ {
+- if ((pdev->device == 0x7312 && pdev->revision != 0x00) ||
+- (pdev->device == 0x7340 && pdev->revision != 0xc5) ||
+- (pdev->device == 0x7341 && pdev->revision != 0x00))
+- return;
+-
+ if (pdev->device == 0x15d8) {
+ if (pdev->revision == 0xcf &&
+ pdev->subsystem_vendor == 0xea50 &&
+@@ -5366,10 +5377,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_amd_harvest_no_ats);
+ /* AMD Iceland dGPU */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_amd_harvest_no_ats);
+ /* AMD Navi10 dGPU */
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7310, quirk_amd_harvest_no_ats);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7312, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7318, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7319, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731a, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731b, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731e, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731f, quirk_amd_harvest_no_ats);
+ /* AMD Navi14 dGPU */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7340, quirk_amd_harvest_no_ats);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7341, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7347, quirk_amd_harvest_no_ats);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x734f, quirk_amd_harvest_no_ats);
+ /* AMD Raven platform iGPU */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x15d8, quirk_amd_harvest_no_ats);
+ #endif /* CONFIG_PCI_ATS */
+@@ -5795,3 +5815,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
@@ -99745,6 +144947,73 @@ index bc3cba5f8c5dc..400eb7f579dce 100644
return 0;
}
+diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
+index 295cc7952d0ed..57d20cf3da7a3 100644
+--- a/drivers/perf/arm_pmu.c
++++ b/drivers/perf/arm_pmu.c
+@@ -398,6 +398,9 @@ validate_group(struct perf_event *event)
+ if (!validate_event(event->pmu, &fake_pmu, leader))
+ return -EINVAL;
+
++ if (event == leader)
++ return 0;
++
+ for_each_sibling_event(sibling, leader) {
+ if (!validate_event(event->pmu, &fake_pmu, sibling))
+ return -EINVAL;
+@@ -487,12 +490,7 @@ __hw_perf_event_init(struct perf_event *event)
+ local64_set(&hwc->period_left, hwc->sample_period);
+ }
+
+- if (event->group_leader != event) {
+- if (validate_group(event) != 0)
+- return -EINVAL;
+- }
+-
+- return 0;
++ return validate_group(event);
+ }
+
+ static int armpmu_event_init(struct perf_event *event)
+diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
+index 94ebc1ecace7c..b1b2a55de77fc 100644
+--- a/drivers/perf/fsl_imx8_ddr_perf.c
++++ b/drivers/perf/fsl_imx8_ddr_perf.c
+@@ -29,7 +29,7 @@
+ #define CNTL_OVER_MASK 0xFFFFFFFE
+
+ #define CNTL_CSV_SHIFT 24
+-#define CNTL_CSV_MASK (0xFF << CNTL_CSV_SHIFT)
++#define CNTL_CSV_MASK (0xFFU << CNTL_CSV_SHIFT)
+
+ #define EVENT_CYCLES_ID 0
+ #define EVENT_CYCLES_COUNTER 0
+diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
+index 5b093badd0f65..f60e79fac2021 100644
+--- a/drivers/perf/qcom_l2_pmu.c
++++ b/drivers/perf/qcom_l2_pmu.c
+@@ -736,7 +736,7 @@ static struct cluster_pmu *l2_cache_associate_cpu_with_cluster(
+ {
+ u64 mpidr;
+ int cpu_cluster_id;
+- struct cluster_pmu *cluster = NULL;
++ struct cluster_pmu *cluster;
+
+ /*
+ * This assumes that the cluster_id is in MPIDR[aff1] for
+@@ -758,10 +758,10 @@ static struct cluster_pmu *l2_cache_associate_cpu_with_cluster(
+ cluster->cluster_id);
+ cpumask_set_cpu(cpu, &cluster->cluster_cpus);
+ *per_cpu_ptr(l2cache_pmu->pmu_cluster, cpu) = cluster;
+- break;
++ return cluster;
+ }
+
+- return cluster;
++ return NULL;
+ }
+
+ static int l2cache_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c
index cd2332bf0e31a..fdbd64c03e12b 100644
--- a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c
@@ -99766,6 +145035,123 @@ index cd2332bf0e31a..fdbd64c03e12b 100644
regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
DIV_ROUND_UP(priv->config.hs_exit, temp) |
+diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
+index 5b471ab80fe28..54d65a6f0fccf 100644
+--- a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
++++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
+@@ -414,19 +414,19 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
+
+ ret = clk_prepare_enable(priv->clk_ref);
+ if (ret)
+- goto err_disable_clk_ref;
++ return ret;
+
+ priv->reset = devm_reset_control_array_get_exclusive(dev);
+- if (IS_ERR(priv->reset))
+- return PTR_ERR(priv->reset);
++ if (IS_ERR(priv->reset)) {
++ ret = PTR_ERR(priv->reset);
++ goto err_disable_clk_ref;
++ }
+
+ priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops);
+ if (IS_ERR(priv->phy)) {
+ ret = PTR_ERR(priv->phy);
+- if (ret != -EPROBE_DEFER)
+- dev_err(dev, "failed to create PHY\n");
+-
+- return ret;
++ dev_err_probe(dev, ret, "failed to create PHY\n");
++ goto err_disable_clk_ref;
+ }
+
+ phy_set_drvdata(priv->phy, priv);
+@@ -434,8 +434,12 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
+
+ phy_provider = devm_of_phy_provider_register(dev,
+ phy_g12a_usb3_pcie_xlate);
++ if (IS_ERR(phy_provider)) {
++ ret = PTR_ERR(phy_provider);
++ goto err_disable_clk_ref;
++ }
+
+- return PTR_ERR_OR_ZERO(phy_provider);
++ return 0;
+
+ err_disable_clk_ref:
+ clk_disable_unprepare(priv->clk_ref);
+diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
+index 2b3c0d730f20f..db17c3448bfed 100644
+--- a/drivers/phy/amlogic/phy-meson-gxl-usb2.c
++++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
+@@ -114,8 +114,10 @@ static int phy_meson_gxl_usb2_init(struct phy *phy)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk);
+- if (ret)
++ if (ret) {
++ reset_control_rearm(priv->reset);
+ return ret;
++ }
+
+ return 0;
+ }
+@@ -125,6 +127,7 @@ static int phy_meson_gxl_usb2_exit(struct phy *phy)
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(priv->clk);
++ reset_control_rearm(priv->reset);
+
+ return 0;
+ }
+diff --git a/drivers/phy/amlogic/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c
+index cf10bed40528a..dd96763911b8b 100644
+--- a/drivers/phy/amlogic/phy-meson8b-usb2.c
++++ b/drivers/phy/amlogic/phy-meson8b-usb2.c
+@@ -154,6 +154,7 @@ static int phy_meson8b_usb2_power_on(struct phy *phy)
+ ret = clk_prepare_enable(priv->clk_usb_general);
+ if (ret) {
+ dev_err(&phy->dev, "Failed to enable USB general clock\n");
++ reset_control_rearm(priv->reset);
+ return ret;
+ }
+
+@@ -161,6 +162,7 @@ static int phy_meson8b_usb2_power_on(struct phy *phy)
+ if (ret) {
+ dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
+ clk_disable_unprepare(priv->clk_usb_general);
++ reset_control_rearm(priv->reset);
+ return ret;
+ }
+
+@@ -199,6 +201,7 @@ static int phy_meson8b_usb2_power_on(struct phy *phy)
+ dev_warn(&phy->dev, "USB ID detect failed!\n");
+ clk_disable_unprepare(priv->clk_usb);
+ clk_disable_unprepare(priv->clk_usb_general);
++ reset_control_rearm(priv->reset);
+ return -EINVAL;
+ }
+ }
+@@ -218,6 +221,7 @@ static int phy_meson8b_usb2_power_off(struct phy *phy)
+
+ clk_disable_unprepare(priv->clk_usb);
+ clk_disable_unprepare(priv->clk_usb_general);
++ reset_control_rearm(priv->reset);
+
+ /* power off the PHY by putting it into reset mode */
+ regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
+@@ -265,8 +269,9 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
+ return PTR_ERR(priv->clk_usb);
+
+ priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
+- if (PTR_ERR(priv->reset) == -EPROBE_DEFER)
+- return PTR_ERR(priv->reset);
++ if (IS_ERR(priv->reset))
++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset),
++ "Failed to get the reset line");
+
+ priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
+ if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig
index fd92b73b71095..1dcfa3bd1442d 100644
--- a/drivers/phy/broadcom/Kconfig
@@ -99780,8 +145166,95 @@ index fd92b73b71095..1dcfa3bd1442d 100644
help
Enable this to support the Broadcom STB USB PHY.
This driver is required by the USB XHCI, EHCI and OHCI
+diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
+index 9391ab42a12b3..dd0f66288fbdd 100644
+--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
++++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
+@@ -79,6 +79,7 @@
+
+ enum brcm_family_type {
+ BRCM_FAMILY_3390A0,
++ BRCM_FAMILY_4908,
+ BRCM_FAMILY_7250B0,
+ BRCM_FAMILY_7271A0,
+ BRCM_FAMILY_7364A0,
+@@ -96,6 +97,7 @@ enum brcm_family_type {
+
+ static const char *family_names[BRCM_FAMILY_COUNT] = {
+ USB_BRCM_FAMILY(3390A0),
++ USB_BRCM_FAMILY(4908),
+ USB_BRCM_FAMILY(7250B0),
+ USB_BRCM_FAMILY(7271A0),
+ USB_BRCM_FAMILY(7364A0),
+@@ -203,6 +205,27 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ },
++ /* 4908 */
++ [BRCM_FAMILY_4908] = {
++ 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
++ 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
++ 0, /* USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
++ 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
++ 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
++ 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
++ 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
++ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
++ USB_CTRL_USB_PM_USB_PWRDN_MASK,
++ 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
++ 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
++ 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
++ 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
++ 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
++ 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
++ 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
++ 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK */
++ 0, /* USB_CTRL_SETUP ENDIAN bits */
++ },
+ /* 7250b0 */
+ [BRCM_FAMILY_7250B0] = {
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+@@ -559,6 +582,7 @@ static void brcmusb_usb3_pll_54mhz(struct brcm_usb_init_params *params)
+ */
+ switch (params->selected_family) {
+ case BRCM_FAMILY_3390A0:
++ case BRCM_FAMILY_4908:
+ case BRCM_FAMILY_7250B0:
+ case BRCM_FAMILY_7366C0:
+ case BRCM_FAMILY_74371A0:
+@@ -1004,6 +1028,18 @@ static const struct brcm_usb_init_ops bcm7445_ops = {
+ .set_dual_select = usb_set_dual_select,
+ };
+
++void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params)
++{
++ int fam;
++
++ fam = BRCM_FAMILY_4908;
++ params->selected_family = fam;
++ params->usb_reg_bits_map =
++ &usb_reg_bits_map_table[fam][0];
++ params->family_name = family_names[fam];
++ params->ops = &bcm7445_ops;
++}
++
+ void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params)
+ {
+ int fam;
+diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.h b/drivers/phy/broadcom/phy-brcm-usb-init.h
+index a39f30fa2e991..1ccb5ddab865c 100644
+--- a/drivers/phy/broadcom/phy-brcm-usb-init.h
++++ b/drivers/phy/broadcom/phy-brcm-usb-init.h
+@@ -64,6 +64,7 @@ struct brcm_usb_init_params {
+ bool suspend_with_clocks;
+ };
+
++void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params);
+ void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params);
+ void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params);
+ void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params);
diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c
-index 116fb23aebd99..0f1deb6e0eabf 100644
+index 116fb23aebd99..2cb3779fcdf82 100644
--- a/drivers/phy/broadcom/phy-brcm-usb.c
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
@@ -18,6 +18,7 @@
@@ -99848,7 +145321,32 @@ index 116fb23aebd99..0f1deb6e0eabf 100644
dev_dbg(&gphy->dev, "EXIT\n");
if (phy->id == BRCM_USB_PHY_2_0)
brcm_usb_uninit_eohci(&priv->ini);
-@@ -488,6 +518,9 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
+@@ -253,6 +283,15 @@ static const struct attribute_group brcm_usb_phy_group = {
+ .attrs = brcm_usb_phy_attrs,
+ };
+
++static const struct match_chip_info chip_info_4908 = {
++ .init_func = &brcm_usb_dvr_init_4908,
++ .required_regs = {
++ BRCM_REGS_CTRL,
++ BRCM_REGS_XHCI_EC,
++ -1,
++ },
++};
++
+ static const struct match_chip_info chip_info_7216 = {
+ .init_func = &brcm_usb_dvr_init_7216,
+ .required_regs = {
+@@ -288,7 +327,7 @@ static const struct match_chip_info chip_info_7445 = {
+ static const struct of_device_id brcm_usb_dt_ids[] = {
+ {
+ .compatible = "brcm,bcm4908-usb-phy",
+- .data = &chip_info_7445,
++ .data = &chip_info_4908,
+ },
+ {
+ .compatible = "brcm,bcm7216-usb-phy",
+@@ -488,6 +527,9 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
if (err)
return err;
@@ -99858,7 +145356,7 @@ index 116fb23aebd99..0f1deb6e0eabf 100644
mutex_init(&priv->mutex);
/* make sure invert settings are correct */
-@@ -528,7 +561,10 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
+@@ -528,7 +570,10 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
static int brcm_usb_phy_remove(struct platform_device *pdev)
{
@@ -99869,7 +145367,7 @@ index 116fb23aebd99..0f1deb6e0eabf 100644
return 0;
}
-@@ -539,6 +575,7 @@ static int brcm_usb_phy_suspend(struct device *dev)
+@@ -539,6 +584,7 @@ static int brcm_usb_phy_suspend(struct device *dev)
struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
if (priv->init_count) {
@@ -99877,7 +145375,7 @@ index 116fb23aebd99..0f1deb6e0eabf 100644
priv->ini.wake_enabled = device_may_wakeup(dev);
if (priv->phys[BRCM_USB_PHY_3_0].inited)
brcm_usb_uninit_xhci(&priv->ini);
-@@ -578,6 +615,7 @@ static int brcm_usb_phy_resume(struct device *dev)
+@@ -578,6 +624,7 @@ static int brcm_usb_phy_resume(struct device *dev)
* Uninitialize anything that wasn't previously initialized.
*/
if (priv->init_count) {
@@ -100236,8 +145734,22 @@ index 4076580fc2cd9..ab1b0986aa671 100644
}
for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) {
struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx];
+diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c
+index 5172971f4c360..3cd4d51c247c3 100644
+--- a/drivers/phy/motorola/phy-mapphone-mdm6600.c
++++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c
+@@ -629,7 +629,8 @@ idle:
+ cleanup:
+ if (error < 0)
+ phy_mdm6600_device_power_off(ddata);
+-
++ pm_runtime_disable(ddata->dev);
++ pm_runtime_dont_use_autosuspend(ddata->dev);
+ return error;
+ }
+
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
-index 288c9c67aa748..ccb4045685cdd 100644
+index 288c9c67aa748..929e86d6558e0 100644
--- a/drivers/phy/phy-core-mipi-dphy.c
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -36,7 +36,7 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
@@ -100249,6 +145761,19 @@ index 288c9c67aa748..ccb4045685cdd 100644
cfg->clk_prepare = 38000;
cfg->clk_settle = 95000;
cfg->clk_term_en = 0;
+@@ -64,10 +64,10 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+ cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
+
+ cfg->init = 100;
+- cfg->lpx = 60000;
++ cfg->lpx = 50000;
+ cfg->ta_get = 5 * cfg->lpx;
+ cfg->ta_go = 4 * cfg->lpx;
+- cfg->ta_sure = 2 * cfg->lpx;
++ cfg->ta_sure = cfg->lpx;
+ cfg->wakeup = 1000;
+
+ cfg->hs_clk_rate = hs_clk_rate;
@@ -97,7 +97,7 @@ int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
if (cfg->clk_post < (60000 + 52 * ui))
return -EINVAL;
@@ -100348,6 +145873,65 @@ index 347dc79a18c18..630e01b5c19b9 100644
/*
* The value of counter for HS Tlpx Time
+diff --git a/drivers/phy/samsung/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c
+index 9ec234243f7c6..595adba5fb8f1 100644
+--- a/drivers/phy/samsung/phy-exynos5250-sata.c
++++ b/drivers/phy/samsung/phy-exynos5250-sata.c
+@@ -187,6 +187,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
+ return -EINVAL;
+
+ sata_phy->client = of_find_i2c_device_by_node(node);
++ of_node_put(node);
+ if (!sata_phy->client)
+ return -EPROBE_DEFER;
+
+@@ -195,20 +196,21 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
+ sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
+ if (IS_ERR(sata_phy->phyclk)) {
+ dev_err(dev, "failed to get clk for PHY\n");
+- return PTR_ERR(sata_phy->phyclk);
++ ret = PTR_ERR(sata_phy->phyclk);
++ goto put_dev;
+ }
+
+ ret = clk_prepare_enable(sata_phy->phyclk);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable source clk\n");
+- return ret;
++ goto put_dev;
+ }
+
+ sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
+ if (IS_ERR(sata_phy->phy)) {
+- clk_disable_unprepare(sata_phy->phyclk);
+ dev_err(dev, "failed to create PHY\n");
+- return PTR_ERR(sata_phy->phy);
++ ret = PTR_ERR(sata_phy->phy);
++ goto clk_disable;
+ }
+
+ phy_set_drvdata(sata_phy->phy, sata_phy);
+@@ -216,11 +218,18 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
+ phy_provider = devm_of_phy_provider_register(dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+- clk_disable_unprepare(sata_phy->phyclk);
+- return PTR_ERR(phy_provider);
++ ret = PTR_ERR(phy_provider);
++ goto clk_disable;
+ }
+
+ return 0;
++
++clk_disable:
++ clk_disable_unprepare(sata_phy->phyclk);
++put_dev:
++ put_device(&sata_phy->client->dev);
++
++ return ret;
+ }
+
+ static const struct of_device_id exynos_sata_phy_of_match[] = {
diff --git a/drivers/phy/socionext/phy-uniphier-usb3ss.c b/drivers/phy/socionext/phy-uniphier-usb3ss.c
index 6700645bcbe6b..3b5ffc16a6947 100644
--- a/drivers/phy/socionext/phy-uniphier-usb3ss.c
@@ -100396,6 +145980,19 @@ index 937a14fa7448a..da05642d3bd4a 100644
}
ret = stm32_usbphyc_regulators_enable(usbphyc);
+diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
+index 2ff56ce77b307..21c0088f5ca9e 100644
+--- a/drivers/phy/ti/phy-am654-serdes.c
++++ b/drivers/phy/ti/phy-am654-serdes.c
+@@ -838,7 +838,7 @@ static int serdes_am654_probe(struct platform_device *pdev)
+
+ clk_err:
+ of_clk_del_provider(node);
+-
++ pm_runtime_disable(dev);
+ return ret;
+ }
+
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 5fd2e8a08bfcf..d0ab69750c6b4 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
@@ -100421,6 +146018,19 @@ index 126f5b8735cc1..8963fbf7aa73b 100644
};
static const struct wiz_clk_div_sel clk_div_sel[] = {
+diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
+index ebceb1520ce88..ca8532a3f1931 100644
+--- a/drivers/phy/ti/phy-omap-usb2.c
++++ b/drivers/phy/ti/phy-omap-usb2.c
+@@ -215,7 +215,7 @@ static int omap_usb2_enable_clocks(struct omap_usb *phy)
+ return 0;
+
+ err1:
+- clk_disable(phy->wkupclk);
++ clk_disable_unprepare(phy->wkupclk);
+
+ err0:
+ return ret;
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index f478d8a17115b..9be9535ad7ab7 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
@@ -100452,6 +146062,50 @@ index f478d8a17115b..9be9535ad7ab7 100644
xpsgtr_bypass_scrambler_8b10b(gtr_phy);
}
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+index a3fa03bcd9a30..54064714d73fb 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+@@ -1236,18 +1236,12 @@ FUNC_GROUP_DECL(SALT8, AA12);
+ FUNC_GROUP_DECL(WDTRST4, AA12);
+
+ #define AE12 196
+-SIG_EXPR_LIST_DECL_SEMG(AE12, FWSPIDQ2, FWQSPID, FWSPID,
+- SIG_DESC_SET(SCU438, 4));
+ SIG_EXPR_LIST_DECL_SESG(AE12, GPIOY4, GPIOY4);
+-PIN_DECL_(AE12, SIG_EXPR_LIST_PTR(AE12, FWSPIDQ2),
+- SIG_EXPR_LIST_PTR(AE12, GPIOY4));
++PIN_DECL_(AE12, SIG_EXPR_LIST_PTR(AE12, GPIOY4));
+
+ #define AF12 197
+-SIG_EXPR_LIST_DECL_SEMG(AF12, FWSPIDQ3, FWQSPID, FWSPID,
+- SIG_DESC_SET(SCU438, 5));
+ SIG_EXPR_LIST_DECL_SESG(AF12, GPIOY5, GPIOY5);
+-PIN_DECL_(AF12, SIG_EXPR_LIST_PTR(AF12, FWSPIDQ3),
+- SIG_EXPR_LIST_PTR(AF12, GPIOY5));
++PIN_DECL_(AF12, SIG_EXPR_LIST_PTR(AF12, GPIOY5));
+
+ #define AC12 198
+ SSSF_PIN_DECL(AC12, GPIOY6, FWSPIABR, SIG_DESC_SET(SCU438, 6));
+@@ -1520,9 +1514,8 @@ SIG_EXPR_LIST_DECL_SEMG(Y4, EMMCDAT7, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 3));
+ PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, EMMCDAT7);
+
+ GROUP_DECL(FWSPID, Y1, Y2, Y3, Y4);
+-GROUP_DECL(FWQSPID, Y1, Y2, Y3, Y4, AE12, AF12);
+ GROUP_DECL(EMMCG8, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5, Y1, Y2, Y3, Y4);
+-FUNC_DECL_2(FWSPID, FWSPID, FWQSPID);
++FUNC_DECL_1(FWSPID, FWSPID);
+ FUNC_GROUP_DECL(VB, Y1, Y2, Y3, Y4);
+ FUNC_DECL_3(EMMC, EMMCG1, EMMCG4, EMMCG8);
+ /*
+@@ -1918,7 +1911,6 @@ static const struct aspeed_pin_group aspeed_g6_groups[] = {
+ ASPEED_PINCTRL_GROUP(FSI2),
+ ASPEED_PINCTRL_GROUP(FWSPIABR),
+ ASPEED_PINCTRL_GROUP(FWSPID),
+- ASPEED_PINCTRL_GROUP(FWQSPID),
+ ASPEED_PINCTRL_GROUP(FWSPIWP),
+ ASPEED_PINCTRL_GROUP(GPIT0),
+ ASPEED_PINCTRL_GROUP(GPIT1),
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index c9c5efc927311..5973a279e6b8c 100644
--- a/drivers/pinctrl/bcm/Kconfig
@@ -100675,6 +146329,43 @@ index 85750974d1825..826d494f3cc66 100644
static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value)
{
u32 curr, updated;
+diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c
+index 0bcd19597e4ad..3ddaeffc04150 100644
+--- a/drivers/pinctrl/intel/pinctrl-tigerlake.c
++++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c
+@@ -749,7 +749,6 @@ static const struct acpi_device_id tgl_pinctrl_acpi_match[] = {
+ { "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
+ { "INT34C6", (kernel_ulong_t)&tglh_soc_data },
+ { "INTC1055", (kernel_ulong_t)&tgllp_soc_data },
+- { "INTC1057", (kernel_ulong_t)&tgllp_soc_data },
+ { }
+ };
+ MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index 7040a7a7bd5d1..246b0e951e1ce 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -30,6 +30,7 @@ config PINCTRL_MTK_MOORE
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select OF_GPIO
++ select EINT_MTK
+ select PINCTRL_MTK_V2
+
+ config PINCTRL_MTK_PARIS
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8365.c b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
+index 79b1fee5a1eba..ddee0db72d264 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
+@@ -259,7 +259,7 @@ static const struct mtk_pin_ies_smt_set mt8365_ies_set[] = {
+ MTK_PIN_IES_SMT_SPEC(104, 104, 0x420, 13),
+ MTK_PIN_IES_SMT_SPEC(105, 109, 0x420, 14),
+ MTK_PIN_IES_SMT_SPEC(110, 113, 0x420, 15),
+- MTK_PIN_IES_SMT_SPEC(114, 112, 0x420, 16),
++ MTK_PIN_IES_SMT_SPEC(114, 116, 0x420, 16),
+ MTK_PIN_IES_SMT_SPEC(117, 119, 0x420, 17),
+ MTK_PIN_IES_SMT_SPEC(120, 122, 0x420, 18),
+ MTK_PIN_IES_SMT_SPEC(123, 125, 0x420, 19),
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 45ebdeba985ae..12163d3c4bcb0 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -100694,6 +146385,496 @@ index 45ebdeba985ae..12163d3c4bcb0 100644
*gpio_n = eint_n;
else
*gpio_n = mtk_xt_find_eint_num(hw, eint_n);
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 5f7c421ab6e76..334cb85855a93 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -1038,6 +1038,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
+ node = of_parse_phandle(np, "mediatek,pctl-regmap", 0);
+ if (node) {
+ pctl->regmap1 = syscon_node_to_regmap(node);
++ of_node_put(node);
+ if (IS_ERR(pctl->regmap1))
+ return PTR_ERR(pctl->regmap1);
+ } else if (regmap) {
+@@ -1051,6 +1052,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
+ node = of_parse_phandle(np, "mediatek,pctl-regmap", 1);
+ if (node) {
+ pctl->regmap2 = syscon_node_to_regmap(node);
++ of_node_put(node);
+ if (IS_ERR(pctl->regmap2))
+ return PTR_ERR(pctl->regmap2);
+ }
+diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
+index 85db2e4377f0c..02e2a259edd39 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
++++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
+@@ -96,20 +96,16 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
+ if (err)
+ goto out;
++ if (ret == MTK_PUPD_SET_R1R0_00)
++ ret = MTK_DISABLE;
+ if (param == PIN_CONFIG_BIAS_DISABLE) {
+- if (ret == MTK_PUPD_SET_R1R0_00)
+- ret = MTK_DISABLE;
++ if (ret != MTK_DISABLE)
++ err = -EINVAL;
+ } else if (param == PIN_CONFIG_BIAS_PULL_UP) {
+- /* When desire to get pull-up value, return
+- * error if current setting is pull-down
+- */
+- if (!pullup)
++ if (!pullup || ret == MTK_DISABLE)
+ err = -EINVAL;
+ } else if (param == PIN_CONFIG_BIAS_PULL_DOWN) {
+- /* When desire to get pull-down value, return
+- * error if current setting is pull-up
+- */
+- if (pullup)
++ if (pullup || ret == MTK_DISABLE)
+ err = -EINVAL;
+ }
+ } else {
+@@ -188,8 +184,7 @@ out:
+ }
+
+ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+- enum pin_config_param param,
+- enum pin_config_param arg)
++ enum pin_config_param param, u32 arg)
+ {
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ const struct mtk_pin_desc *desc;
+@@ -585,6 +580,9 @@ ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
+ if (gpio >= hw->soc->npins)
+ return -EINVAL;
+
++ if (mtk_is_virt_gpio(hw, gpio))
++ return -EINVAL;
++
+ desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
+ pinmux = mtk_pctrl_get_pinmux(hw, gpio);
+ if (pinmux >= hw->soc->nfuncs)
+@@ -719,10 +717,10 @@ static int mtk_pconf_group_get(struct pinctrl_dev *pctldev, unsigned group,
+ unsigned long *config)
+ {
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
++ struct mtk_pinctrl_group *grp = &hw->groups[group];
+
+- *config = hw->groups[group].config;
+-
+- return 0;
++ /* One pin per group only */
++ return mtk_pinconf_get(pctldev, grp->pin, config);
+ }
+
+ static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+@@ -738,8 +736,6 @@ static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+ pinconf_to_config_argument(configs[i]));
+ if (ret < 0)
+ return ret;
+-
+- grp->config = configs[i];
+ }
+
+ return 0;
+diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+index 39828e9c3120a..4757bf964d3cd 100644
+--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
++++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+@@ -1883,8 +1883,10 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
+ }
+
+ prcm_np = of_parse_phandle(np, "prcm", 0);
+- if (prcm_np)
++ if (prcm_np) {
+ npct->prcm_base = of_iomap(prcm_np, 0);
++ of_node_put(prcm_np);
++ }
+ if (!npct->prcm_base) {
+ if (version == PINCTRL_NMK_STN8815) {
+ dev_info(&pdev->dev,
+diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+index 4d81908d6725d..41136f63014a4 100644
+--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
++++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+@@ -78,7 +78,6 @@ struct npcm7xx_gpio {
+ struct gpio_chip gc;
+ int irqbase;
+ int irq;
+- void *priv;
+ struct irq_chip irq_chip;
+ u32 pinctrl_id;
+ int (*direction_input)(struct gpio_chip *chip, unsigned offset);
+@@ -226,7 +225,7 @@ static void npcmgpio_irq_handler(struct irq_desc *desc)
+ chained_irq_enter(chip, desc);
+ sts = ioread32(bank->base + NPCM7XX_GP_N_EVST);
+ en = ioread32(bank->base + NPCM7XX_GP_N_EVEN);
+- dev_dbg(chip->parent_device, "==> got irq sts %.8x %.8x\n", sts,
++ dev_dbg(bank->gc.parent, "==> got irq sts %.8x %.8x\n", sts,
+ en);
+
+ sts &= en;
+@@ -241,33 +240,33 @@ static int npcmgpio_set_irq_type(struct irq_data *d, unsigned int type)
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ unsigned int gpio = BIT(d->hwirq);
+
+- dev_dbg(d->chip->parent_device, "setirqtype: %u.%u = %u\n", gpio,
++ dev_dbg(bank->gc.parent, "setirqtype: %u.%u = %u\n", gpio,
+ d->irq, type);
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+- dev_dbg(d->chip->parent_device, "edge.rising\n");
++ dev_dbg(bank->gc.parent, "edge.rising\n");
+ npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
+ npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+- dev_dbg(d->chip->parent_device, "edge.falling\n");
++ dev_dbg(bank->gc.parent, "edge.falling\n");
+ npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
+ npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+- dev_dbg(d->chip->parent_device, "edge.both\n");
++ dev_dbg(bank->gc.parent, "edge.both\n");
+ npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+- dev_dbg(d->chip->parent_device, "level.low\n");
++ dev_dbg(bank->gc.parent, "level.low\n");
+ npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+- dev_dbg(d->chip->parent_device, "level.high\n");
++ dev_dbg(bank->gc.parent, "level.high\n");
+ npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
+ break;
+ default:
+- dev_dbg(d->chip->parent_device, "invalid irq type\n");
++ dev_dbg(bank->gc.parent, "invalid irq type\n");
+ return -EINVAL;
+ }
+
+@@ -289,7 +288,7 @@ static void npcmgpio_irq_ack(struct irq_data *d)
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ unsigned int gpio = d->hwirq;
+
+- dev_dbg(d->chip->parent_device, "irq_ack: %u.%u\n", gpio, d->irq);
++ dev_dbg(bank->gc.parent, "irq_ack: %u.%u\n", gpio, d->irq);
+ iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVST);
+ }
+
+@@ -301,7 +300,7 @@ static void npcmgpio_irq_mask(struct irq_data *d)
+ unsigned int gpio = d->hwirq;
+
+ /* Clear events */
+- dev_dbg(d->chip->parent_device, "irq_mask: %u.%u\n", gpio, d->irq);
++ dev_dbg(bank->gc.parent, "irq_mask: %u.%u\n", gpio, d->irq);
+ iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENC);
+ }
+
+@@ -313,7 +312,7 @@ static void npcmgpio_irq_unmask(struct irq_data *d)
+ unsigned int gpio = d->hwirq;
+
+ /* Enable events */
+- dev_dbg(d->chip->parent_device, "irq_unmask: %u.%u\n", gpio, d->irq);
++ dev_dbg(bank->gc.parent, "irq_unmask: %u.%u\n", gpio, d->irq);
+ iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENS);
+ }
+
+@@ -323,7 +322,7 @@ static unsigned int npcmgpio_irq_startup(struct irq_data *d)
+ unsigned int gpio = d->hwirq;
+
+ /* active-high, input, clear interrupt, enable interrupt */
+- dev_dbg(d->chip->parent_device, "startup: %u.%u\n", gpio, d->irq);
++ dev_dbg(gc->parent, "startup: %u.%u\n", gpio, d->irq);
+ npcmgpio_direction_input(gc, gpio);
+ npcmgpio_irq_ack(d);
+ npcmgpio_irq_unmask(d);
+@@ -905,7 +904,7 @@ static struct npcm7xx_func npcm7xx_funcs[] = {
+ #define DRIVE_STRENGTH_HI_SHIFT 12
+ #define DRIVE_STRENGTH_MASK 0x0000FF00
+
+-#define DS(lo, hi) (((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
++#define DSTR(lo, hi) (((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
+ ((hi) << DRIVE_STRENGTH_HI_SHIFT))
+ #define DSLO(x) (((x) >> DRIVE_STRENGTH_LO_SHIFT) & 0xF)
+ #define DSHI(x) (((x) >> DRIVE_STRENGTH_HI_SHIFT) & 0xF)
+@@ -925,31 +924,31 @@ struct npcm7xx_pincfg {
+ static const struct npcm7xx_pincfg pincfg[] = {
+ /* PIN FUNCTION 1 FUNCTION 2 FUNCTION 3 FLAGS */
+ NPCM7XX_PINCFG(0, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(1, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(2, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(1, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(2, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(3, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(4, iox2, MFSEL3, 14, smb1d, I2CSEGSEL, 7, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(5, iox2, MFSEL3, 14, smb1d, I2CSEGSEL, 7, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(6, iox2, MFSEL3, 14, smb2d, I2CSEGSEL, 10, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(7, iox2, MFSEL3, 14, smb2d, I2CSEGSEL, 10, none, NONE, 0, SLEW),
+- NPCM7XX_PINCFG(8, lkgpo1, FLOCKR1, 4, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(9, lkgpo2, FLOCKR1, 8, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(10, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(11, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(8, lkgpo1, FLOCKR1, 4, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(9, lkgpo2, FLOCKR1, 8, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(10, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(11, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(12, gspi, MFSEL1, 24, smb5b, I2CSEGSEL, 19, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(13, gspi, MFSEL1, 24, smb5b, I2CSEGSEL, 19, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(14, gspi, MFSEL1, 24, smb5c, I2CSEGSEL, 20, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(15, gspi, MFSEL1, 24, smb5c, I2CSEGSEL, 20, none, NONE, 0, SLEW),
+- NPCM7XX_PINCFG(16, lkgpo0, FLOCKR1, 0, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(17, pspi2, MFSEL3, 13, smb4den, I2CSEGSEL, 23, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(18, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(19, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(16, lkgpo0, FLOCKR1, 0, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(17, pspi2, MFSEL3, 13, smb4den, I2CSEGSEL, 23, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(18, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(19, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(20, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(21, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(22, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(23, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(24, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(25, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(24, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(25, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(26, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(27, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(28, smb4, MFSEL1, 1, none, NONE, 0, none, NONE, 0, 0),
+@@ -965,12 +964,12 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(39, smb3b, I2CSEGSEL, 11, none, NONE, 0, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(40, smb3b, I2CSEGSEL, 11, none, NONE, 0, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(41, bmcuart0a, MFSEL1, 9, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(42, bmcuart0a, MFSEL1, 9, none, NONE, 0, none, NONE, 0, DS(2, 4) | GPO),
++ NPCM7XX_PINCFG(42, bmcuart0a, MFSEL1, 9, none, NONE, 0, none, NONE, 0, DSTR(2, 4) | GPO),
+ NPCM7XX_PINCFG(43, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, bmcuart1, MFSEL3, 24, 0),
+ NPCM7XX_PINCFG(44, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, bmcuart1, MFSEL3, 24, 0),
+ NPCM7XX_PINCFG(45, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(46, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, none, NONE, 0, DS(2, 8)),
+- NPCM7XX_PINCFG(47, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, none, NONE, 0, DS(2, 8)),
++ NPCM7XX_PINCFG(46, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, none, NONE, 0, DSTR(2, 8)),
++ NPCM7XX_PINCFG(47, uart1, MFSEL1, 10, jtag2, MFSEL4, 0, none, NONE, 0, DSTR(2, 8)),
+ NPCM7XX_PINCFG(48, uart2, MFSEL1, 11, bmcuart0b, MFSEL4, 1, none, NONE, 0, GPO),
+ NPCM7XX_PINCFG(49, uart2, MFSEL1, 11, bmcuart0b, MFSEL4, 1, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(50, uart2, MFSEL1, 11, none, NONE, 0, none, NONE, 0, 0),
+@@ -980,8 +979,8 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(54, uart2, MFSEL1, 11, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(55, uart2, MFSEL1, 11, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(56, r1err, MFSEL1, 12, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(57, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
+- NPCM7XX_PINCFG(58, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
++ NPCM7XX_PINCFG(57, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DSTR(2, 4)),
++ NPCM7XX_PINCFG(58, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DSTR(2, 4)),
+ NPCM7XX_PINCFG(59, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(60, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(61, uart1, MFSEL1, 10, none, NONE, 0, none, NONE, 0, GPO),
+@@ -1004,19 +1003,19 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(77, fanin13, MFSEL2, 13, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(78, fanin14, MFSEL2, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(79, fanin15, MFSEL2, 15, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(80, pwm0, MFSEL2, 16, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(81, pwm1, MFSEL2, 17, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(82, pwm2, MFSEL2, 18, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(83, pwm3, MFSEL2, 19, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(84, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(85, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(86, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(80, pwm0, MFSEL2, 16, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(81, pwm1, MFSEL2, 17, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(82, pwm2, MFSEL2, 18, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(83, pwm3, MFSEL2, 19, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(84, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(85, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(86, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(87, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(88, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(89, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(90, r2err, MFSEL1, 15, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(91, r2md, MFSEL1, 16, none, NONE, 0, none, NONE, 0, DS(2, 4)),
+- NPCM7XX_PINCFG(92, r2md, MFSEL1, 16, none, NONE, 0, none, NONE, 0, DS(2, 4)),
++ NPCM7XX_PINCFG(91, r2md, MFSEL1, 16, none, NONE, 0, none, NONE, 0, DSTR(2, 4)),
++ NPCM7XX_PINCFG(92, r2md, MFSEL1, 16, none, NONE, 0, none, NONE, 0, DSTR(2, 4)),
+ NPCM7XX_PINCFG(93, ga20kbc, MFSEL1, 17, smb5d, I2CSEGSEL, 21, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(94, ga20kbc, MFSEL1, 17, smb5d, I2CSEGSEL, 21, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(95, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, 0),
+@@ -1062,34 +1061,34 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(133, smb10, MFSEL4, 13, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(134, smb11, MFSEL4, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(135, smb11, MFSEL4, 14, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(136, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(137, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(138, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(139, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(140, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(136, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(137, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(138, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(139, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(140, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(141, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(142, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(142, sd1, MFSEL3, 12, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(143, sd1, MFSEL3, 12, sd1pwr, MFSEL4, 5, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(144, pwm4, MFSEL2, 20, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(145, pwm5, MFSEL2, 21, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(146, pwm6, MFSEL2, 22, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(147, pwm7, MFSEL2, 23, none, NONE, 0, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(148, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(149, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(150, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(151, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(152, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(144, pwm4, MFSEL2, 20, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(145, pwm5, MFSEL2, 21, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(146, pwm6, MFSEL2, 22, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(147, pwm7, MFSEL2, 23, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(148, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(149, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(150, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(151, mmc8, MFSEL3, 11, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(152, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(153, mmcwp, FLOCKR1, 24, none, NONE, 0, none, NONE, 0, 0), /* Z1/A1 */
+- NPCM7XX_PINCFG(154, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(154, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(155, mmccd, MFSEL3, 25, mmcrst, MFSEL4, 6, none, NONE, 0, 0), /* Z1/A1 */
+- NPCM7XX_PINCFG(156, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(157, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(158, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(159, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+-
+- NPCM7XX_PINCFG(160, clkout, MFSEL1, 21, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(161, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, DS(8, 12)),
+- NPCM7XX_PINCFG(162, serirq, NONE, 0, gpio, MFSEL1, 31, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(156, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(157, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(158, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(159, mmc, MFSEL3, 10, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++
++ NPCM7XX_PINCFG(160, clkout, MFSEL1, 21, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(161, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, DSTR(8, 12)),
++ NPCM7XX_PINCFG(162, serirq, NONE, 0, gpio, MFSEL1, 31, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(163, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, 0),
+ NPCM7XX_PINCFG(164, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, SLEWLPC),
+ NPCM7XX_PINCFG(165, lpc, NONE, 0, espi, MFSEL4, 8, gpio, MFSEL1, 26, SLEWLPC),
+@@ -1102,25 +1101,25 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(172, smb6, MFSEL3, 1, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(173, smb7, MFSEL3, 2, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(174, smb7, MFSEL3, 2, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(175, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(176, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(177, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(178, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(179, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(180, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
++ NPCM7XX_PINCFG(175, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(176, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(177, pspi1, MFSEL3, 4, faninx, MFSEL3, 3, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(178, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(179, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(180, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
+ NPCM7XX_PINCFG(181, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(182, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(183, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(184, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW | GPO),
+- NPCM7XX_PINCFG(185, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW | GPO),
+- NPCM7XX_PINCFG(186, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(187, spi3cs1, MFSEL4, 17, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+- NPCM7XX_PINCFG(188, spi3quad, MFSEL4, 20, spi3cs2, MFSEL4, 18, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(189, spi3quad, MFSEL4, 20, spi3cs3, MFSEL4, 19, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(190, gpio, FLOCKR1, 20, nprd_smi, NONE, 0, none, NONE, 0, DS(2, 4)),
+- NPCM7XX_PINCFG(191, none, NONE, 0, none, NONE, 0, none, NONE, 0, DS(8, 12)), /* XX */
+-
+- NPCM7XX_PINCFG(192, none, NONE, 0, none, NONE, 0, none, NONE, 0, DS(8, 12)), /* XX */
++ NPCM7XX_PINCFG(183, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(184, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW | GPO),
++ NPCM7XX_PINCFG(185, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW | GPO),
++ NPCM7XX_PINCFG(186, spi3, MFSEL4, 16, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(187, spi3cs1, MFSEL4, 17, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
++ NPCM7XX_PINCFG(188, spi3quad, MFSEL4, 20, spi3cs2, MFSEL4, 18, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(189, spi3quad, MFSEL4, 20, spi3cs3, MFSEL4, 19, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(190, gpio, FLOCKR1, 20, nprd_smi, NONE, 0, none, NONE, 0, DSTR(2, 4)),
++ NPCM7XX_PINCFG(191, none, NONE, 0, none, NONE, 0, none, NONE, 0, DSTR(8, 12)), /* XX */
++
++ NPCM7XX_PINCFG(192, none, NONE, 0, none, NONE, 0, none, NONE, 0, DSTR(8, 12)), /* XX */
+ NPCM7XX_PINCFG(193, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(194, smb0b, I2CSEGSEL, 0, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(195, smb0b, I2CSEGSEL, 0, none, NONE, 0, none, NONE, 0, 0),
+@@ -1131,11 +1130,11 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(200, r2, MFSEL1, 14, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(201, r1, MFSEL3, 9, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(202, smb0c, I2CSEGSEL, 1, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(203, faninx, MFSEL3, 3, none, NONE, 0, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(203, faninx, MFSEL3, 3, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(204, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, SLEW),
+ NPCM7XX_PINCFG(205, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, SLEW),
+- NPCM7XX_PINCFG(206, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, DS(4, 8)),
+- NPCM7XX_PINCFG(207, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, DS(4, 8)),
++ NPCM7XX_PINCFG(206, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, DSTR(4, 8)),
++ NPCM7XX_PINCFG(207, ddc, NONE, 0, gpio, MFSEL3, 22, none, NONE, 0, DSTR(4, 8)),
+ NPCM7XX_PINCFG(208, rg2, MFSEL4, 24, ddr, MFSEL3, 26, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(209, rg2, MFSEL4, 24, ddr, MFSEL3, 26, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(210, rg2, MFSEL4, 24, ddr, MFSEL3, 26, none, NONE, 0, 0),
+@@ -1147,20 +1146,20 @@ static const struct npcm7xx_pincfg pincfg[] = {
+ NPCM7XX_PINCFG(216, rg2mdio, MFSEL4, 23, ddr, MFSEL3, 26, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(217, rg2mdio, MFSEL4, 23, ddr, MFSEL3, 26, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(218, wdog1, MFSEL3, 19, none, NONE, 0, none, NONE, 0, 0),
+- NPCM7XX_PINCFG(219, wdog2, MFSEL3, 20, none, NONE, 0, none, NONE, 0, DS(4, 8)),
++ NPCM7XX_PINCFG(219, wdog2, MFSEL3, 20, none, NONE, 0, none, NONE, 0, DSTR(4, 8)),
+ NPCM7XX_PINCFG(220, smb12, MFSEL3, 5, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(221, smb12, MFSEL3, 5, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(222, smb13, MFSEL3, 6, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(223, smb13, MFSEL3, 6, none, NONE, 0, none, NONE, 0, 0),
+
+ NPCM7XX_PINCFG(224, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, SLEW),
+- NPCM7XX_PINCFG(225, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW | GPO),
+- NPCM7XX_PINCFG(226, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW | GPO),
+- NPCM7XX_PINCFG(227, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(228, spixcs1, MFSEL4, 28, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(229, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(230, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DS(8, 12) | SLEW),
+- NPCM7XX_PINCFG(231, clkreq, MFSEL4, 9, none, NONE, 0, none, NONE, 0, DS(8, 12)),
++ NPCM7XX_PINCFG(225, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW | GPO),
++ NPCM7XX_PINCFG(226, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW | GPO),
++ NPCM7XX_PINCFG(227, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(228, spixcs1, MFSEL4, 28, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(229, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(230, spix, MFSEL4, 27, none, NONE, 0, none, NONE, 0, DSTR(8, 12) | SLEW),
++ NPCM7XX_PINCFG(231, clkreq, MFSEL4, 9, none, NONE, 0, none, NONE, 0, DSTR(8, 12)),
+ NPCM7XX_PINCFG(253, none, NONE, 0, none, NONE, 0, none, NONE, 0, GPI), /* SDHC1 power */
+ NPCM7XX_PINCFG(254, none, NONE, 0, none, NONE, 0, none, NONE, 0, GPI), /* SDHC2 power */
+ NPCM7XX_PINCFG(255, none, NONE, 0, none, NONE, 0, none, NONE, 0, GPI), /* DACOSEL */
+@@ -1561,7 +1560,7 @@ static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
+ {
+ struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
+
+- dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
++ dev_dbg(npcm->dev, "group size: %zu\n", ARRAY_SIZE(npcm7xx_groups));
+ return ARRAY_SIZE(npcm7xx_groups);
+ }
+
+diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
+index 22e8d4c4040e1..b1db28007986e 100644
+--- a/drivers/pinctrl/pinconf-generic.c
++++ b/drivers/pinctrl/pinconf-generic.c
+@@ -30,10 +30,10 @@ static const struct pin_config_item conf_items[] = {
+ PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
+ PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
+ PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
+- PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL, false),
++ PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", "ohms", true),
+ PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
+- "input bias pull to pin specific state", NULL, false),
+- PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
++ "input bias pull to pin specific state", "ohms", true),
++ PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", "ohms", true),
+ PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
+ PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
+ PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index bae9d429b813e..ecab9064a8458 100644
--- a/drivers/pinctrl/pinctrl-amd.c
@@ -100802,6 +146983,126 @@ index fb713f9c53d0e..3f0143087cc77 100644
return ret;
}
+diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
+index 2712f51eb2381..fa6becca17889 100644
+--- a/drivers/pinctrl/pinctrl-ingenic.c
++++ b/drivers/pinctrl/pinctrl-ingenic.c
+@@ -119,6 +119,8 @@ struct ingenic_chip_info {
+ unsigned int num_functions;
+
+ const u32 *pull_ups, *pull_downs;
++
++ const struct regmap_access_table *access_table;
+ };
+
+ struct ingenic_pinctrl {
+@@ -2179,6 +2181,17 @@ static const struct function_desc x1000_functions[] = {
+ { "mac", x1000_mac_groups, ARRAY_SIZE(x1000_mac_groups), },
+ };
+
++static const struct regmap_range x1000_access_ranges[] = {
++ regmap_reg_range(0x000, 0x400 - 4),
++ regmap_reg_range(0x700, 0x800 - 4),
++};
++
++/* shared with X1500 */
++static const struct regmap_access_table x1000_access_table = {
++ .yes_ranges = x1000_access_ranges,
++ .n_yes_ranges = ARRAY_SIZE(x1000_access_ranges),
++};
++
+ static const struct ingenic_chip_info x1000_chip_info = {
+ .num_chips = 4,
+ .reg_offset = 0x100,
+@@ -2189,6 +2202,7 @@ static const struct ingenic_chip_info x1000_chip_info = {
+ .num_functions = ARRAY_SIZE(x1000_functions),
+ .pull_ups = x1000_pull_ups,
+ .pull_downs = x1000_pull_downs,
++ .access_table = &x1000_access_table,
+ };
+
+ static int x1500_uart0_data_pins[] = { 0x4a, 0x4b, };
+@@ -2300,6 +2314,7 @@ static const struct ingenic_chip_info x1500_chip_info = {
+ .num_functions = ARRAY_SIZE(x1500_functions),
+ .pull_ups = x1000_pull_ups,
+ .pull_downs = x1000_pull_downs,
++ .access_table = &x1000_access_table,
+ };
+
+ static const u32 x1830_pull_ups[4] = {
+@@ -2506,6 +2521,16 @@ static const struct function_desc x1830_functions[] = {
+ { "mac", x1830_mac_groups, ARRAY_SIZE(x1830_mac_groups), },
+ };
+
++static const struct regmap_range x1830_access_ranges[] = {
++ regmap_reg_range(0x0000, 0x4000 - 4),
++ regmap_reg_range(0x7000, 0x8000 - 4),
++};
++
++static const struct regmap_access_table x1830_access_table = {
++ .yes_ranges = x1830_access_ranges,
++ .n_yes_ranges = ARRAY_SIZE(x1830_access_ranges),
++};
++
+ static const struct ingenic_chip_info x1830_chip_info = {
+ .num_chips = 4,
+ .reg_offset = 0x1000,
+@@ -2516,6 +2541,7 @@ static const struct ingenic_chip_info x1830_chip_info = {
+ .num_functions = ARRAY_SIZE(x1830_functions),
+ .pull_ups = x1830_pull_ups,
+ .pull_downs = x1830_pull_downs,
++ .access_table = &x1830_access_table,
+ };
+
+ static const u32 x2000_pull_ups[5] = {
+@@ -2969,6 +2995,17 @@ static const struct function_desc x2000_functions[] = {
+ { "otg", x2000_otg_groups, ARRAY_SIZE(x2000_otg_groups), },
+ };
+
++static const struct regmap_range x2000_access_ranges[] = {
++ regmap_reg_range(0x000, 0x500 - 4),
++ regmap_reg_range(0x700, 0x800 - 4),
++};
++
++/* shared with X2100 */
++static const struct regmap_access_table x2000_access_table = {
++ .yes_ranges = x2000_access_ranges,
++ .n_yes_ranges = ARRAY_SIZE(x2000_access_ranges),
++};
++
+ static const struct ingenic_chip_info x2000_chip_info = {
+ .num_chips = 5,
+ .reg_offset = 0x100,
+@@ -2979,6 +3016,7 @@ static const struct ingenic_chip_info x2000_chip_info = {
+ .num_functions = ARRAY_SIZE(x2000_functions),
+ .pull_ups = x2000_pull_ups,
+ .pull_downs = x2000_pull_downs,
++ .access_table = &x2000_access_table,
+ };
+
+ static const u32 x2100_pull_ups[5] = {
+@@ -3189,6 +3227,7 @@ static const struct ingenic_chip_info x2100_chip_info = {
+ .num_functions = ARRAY_SIZE(x2100_functions),
+ .pull_ups = x2100_pull_ups,
+ .pull_downs = x2100_pull_downs,
++ .access_table = &x2000_access_table,
+ };
+
+ static u32 ingenic_gpio_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
+@@ -4168,7 +4207,12 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ regmap_config = ingenic_pinctrl_regmap_config;
+- regmap_config.max_register = chip_info->num_chips * chip_info->reg_offset;
++ if (chip_info->access_table) {
++ regmap_config.rd_table = chip_info->access_table;
++ regmap_config.wr_table = chip_info->access_table;
++ } else {
++ regmap_config.max_register = chip_info->num_chips * chip_info->reg_offset - 4;
++ }
+
+ jzpc->map = devm_regmap_init_mmio(dev, base, &regmap_config);
+ if (IS_ERR(jzpc->map)) {
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
index 49e32684dbb25..ecab6bf63dc6d 100644
--- a/drivers/pinctrl/pinctrl-k210.c
@@ -100824,11 +147125,272 @@ index 49e32684dbb25..ecab6bf63dc6d 100644
break;
case PIN_CONFIG_DRIVE_STRENGTH:
arg *= 1000;
+diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c
+index 072bccdea2a5d..dfa374195694d 100644
+--- a/drivers/pinctrl/pinctrl-microchip-sgpio.c
++++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c
+@@ -17,6 +17,8 @@
+ #include <linux/pinctrl/pinmux.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
++#include <linux/reset.h>
++#include <linux/spinlock.h>
+
+ #include "core.h"
+ #include "pinconf.h"
+@@ -114,6 +116,7 @@ struct sgpio_priv {
+ u32 clock;
+ u32 __iomem *regs;
+ const struct sgpio_properties *properties;
++ spinlock_t lock;
+ };
+
+ struct sgpio_port_addr {
+@@ -215,6 +218,7 @@ static void sgpio_output_set(struct sgpio_priv *priv,
+ int value)
+ {
+ unsigned int bit = SGPIO_SRC_BITS * addr->bit;
++ unsigned long flags;
+ u32 clr, set;
+
+ switch (priv->properties->arch) {
+@@ -233,7 +237,10 @@ static void sgpio_output_set(struct sgpio_priv *priv,
+ default:
+ return;
+ }
++
++ spin_lock_irqsave(&priv->lock, flags);
+ sgpio_clrsetbits(priv, REG_PORT_CONFIG, addr->port, clr, set);
++ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ static int sgpio_output_get(struct sgpio_priv *priv,
+@@ -561,10 +568,13 @@ static void microchip_sgpio_irq_settype(struct irq_data *data,
+ struct sgpio_bank *bank = gpiochip_get_data(chip);
+ unsigned int gpio = irqd_to_hwirq(data);
+ struct sgpio_port_addr addr;
++ unsigned long flags;
+ u32 ena;
+
+ sgpio_pin_to_addr(bank->priv, gpio, &addr);
+
++ spin_lock_irqsave(&bank->priv->lock, flags);
++
+ /* Disable interrupt while changing type */
+ ena = sgpio_readl(bank->priv, REG_INT_ENABLE, addr.bit);
+ sgpio_writel(bank->priv, ena & ~BIT(addr.port), REG_INT_ENABLE, addr.bit);
+@@ -581,6 +591,8 @@ static void microchip_sgpio_irq_settype(struct irq_data *data,
+
+ /* Possibly re-enable interrupts */
+ sgpio_writel(bank->priv, ena, REG_INT_ENABLE, addr.bit);
++
++ spin_unlock_irqrestore(&bank->priv->lock, flags);
+ }
+
+ static void microchip_sgpio_irq_setreg(struct irq_data *data,
+@@ -591,13 +603,16 @@ static void microchip_sgpio_irq_setreg(struct irq_data *data,
+ struct sgpio_bank *bank = gpiochip_get_data(chip);
+ unsigned int gpio = irqd_to_hwirq(data);
+ struct sgpio_port_addr addr;
++ unsigned long flags;
+
+ sgpio_pin_to_addr(bank->priv, gpio, &addr);
+
++ spin_lock_irqsave(&bank->priv->lock, flags);
+ if (clear)
+ sgpio_clrsetbits(bank->priv, reg, addr.bit, BIT(addr.port), 0);
+ else
+ sgpio_clrsetbits(bank->priv, reg, addr.bit, 0, BIT(addr.port));
++ spin_unlock_irqrestore(&bank->priv->lock, flags);
+ }
+
+ static void microchip_sgpio_irq_mask(struct irq_data *data)
+@@ -803,6 +818,7 @@ static int microchip_sgpio_probe(struct platform_device *pdev)
+ int div_clock = 0, ret, port, i, nbanks;
+ struct device *dev = &pdev->dev;
+ struct fwnode_handle *fwnode;
++ struct reset_control *reset;
+ struct sgpio_priv *priv;
+ struct clk *clk;
+ u32 val;
+@@ -812,6 +828,12 @@ static int microchip_sgpio_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ priv->dev = dev;
++ spin_lock_init(&priv->lock);
++
++ reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch");
++ if (IS_ERR(reset))
++ return dev_err_probe(dev, PTR_ERR(reset), "Failed to get reset\n");
++ reset_control_reset(reset);
+
+ clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(clk))
+diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
+index 8d271c6b0ca41..5de691c630b4f 100644
+--- a/drivers/pinctrl/pinctrl-pistachio.c
++++ b/drivers/pinctrl/pinctrl-pistachio.c
+@@ -1374,10 +1374,10 @@ static int pistachio_gpio_register(struct pistachio_pinctrl *pctl)
+ }
+
+ irq = irq_of_parse_and_map(child, 0);
+- if (irq < 0) {
+- dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq);
++ if (!irq) {
++ dev_err(pctl->dev, "No IRQ for bank %u\n", i);
+ of_node_put(child);
+- ret = irq;
++ ret = -EINVAL;
+ goto err;
+ }
+
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
-index 5ce260f152ce5..dc52da94af0b9 100644
+index 5ce260f152ce5..543a4991cf700 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
-@@ -2748,7 +2748,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
+@@ -455,95 +455,110 @@ static struct rockchip_mux_recalced_data rk3128_mux_recalced_data[] = {
+
+ static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = {
+ {
++ /* gpio1b6_sel */
+ .num = 1,
+ .pin = 14,
+ .reg = 0x28,
+ .bit = 12,
+ .mask = 0xf
+ }, {
++ /* gpio1b7_sel */
+ .num = 1,
+ .pin = 15,
+ .reg = 0x2c,
+ .bit = 0,
+ .mask = 0x3
+ }, {
++ /* gpio1c2_sel */
+ .num = 1,
+ .pin = 18,
+ .reg = 0x30,
+ .bit = 4,
+ .mask = 0xf
+ }, {
++ /* gpio1c3_sel */
+ .num = 1,
+ .pin = 19,
+ .reg = 0x30,
+ .bit = 8,
+ .mask = 0xf
+ }, {
++ /* gpio1c4_sel */
+ .num = 1,
+ .pin = 20,
+ .reg = 0x30,
+ .bit = 12,
+ .mask = 0xf
+ }, {
++ /* gpio1c5_sel */
+ .num = 1,
+ .pin = 21,
+ .reg = 0x34,
+ .bit = 0,
+ .mask = 0xf
+ }, {
++ /* gpio1c6_sel */
+ .num = 1,
+ .pin = 22,
+ .reg = 0x34,
+ .bit = 4,
+ .mask = 0xf
+ }, {
++ /* gpio1c7_sel */
+ .num = 1,
+ .pin = 23,
+ .reg = 0x34,
+ .bit = 8,
+ .mask = 0xf
+ }, {
++ /* gpio3b4_sel */
+ .num = 3,
+ .pin = 12,
+ .reg = 0x68,
+ .bit = 8,
+ .mask = 0xf
+ }, {
++ /* gpio3b5_sel */
+ .num = 3,
+ .pin = 13,
+ .reg = 0x68,
+ .bit = 12,
+ .mask = 0xf
+ }, {
++ /* gpio2a2_sel */
+ .num = 2,
+ .pin = 2,
+- .reg = 0x608,
+- .bit = 0,
+- .mask = 0x7
++ .reg = 0x40,
++ .bit = 4,
++ .mask = 0x3
+ }, {
++ /* gpio2a3_sel */
+ .num = 2,
+ .pin = 3,
+- .reg = 0x608,
+- .bit = 4,
+- .mask = 0x7
++ .reg = 0x40,
++ .bit = 6,
++ .mask = 0x3
+ }, {
++ /* gpio2c0_sel */
+ .num = 2,
+ .pin = 16,
+- .reg = 0x610,
+- .bit = 8,
+- .mask = 0x7
++ .reg = 0x50,
++ .bit = 0,
++ .mask = 0x3
+ }, {
++ /* gpio3b2_sel */
+ .num = 3,
+ .pin = 10,
+- .reg = 0x610,
+- .bit = 0,
+- .mask = 0x7
++ .reg = 0x68,
++ .bit = 4,
++ .mask = 0x3
+ }, {
++ /* gpio3b3_sel */
+ .num = 3,
+ .pin = 11,
+- .reg = 0x610,
+- .bit = 4,
+- .mask = 0x7
++ .reg = 0x68,
++ .bit = 6,
++ .mask = 0x3
+ },
+ };
+
+@@ -2702,6 +2717,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ info->regmap_base = syscon_node_to_regmap(node);
++ of_node_put(node);
+ if (IS_ERR(info->regmap_base))
+ return PTR_ERR(info->regmap_base);
+ } else {
+@@ -2738,6 +2754,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
+ node = of_parse_phandle(np, "rockchip,pmu", 0);
+ if (node) {
+ info->regmap_pmu = syscon_node_to_regmap(node);
++ of_node_put(node);
+ if (IS_ERR(info->regmap_pmu))
+ return PTR_ERR(info->regmap_pmu);
+ }
+@@ -2748,7 +2765,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, info);
@@ -100900,10 +147462,29 @@ index 425d55a2ee19f..6853b5b8b0fe7 100644
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c
-index f2ab02225837e..f29130957e49a 100644
+index f2ab02225837e..bc17f3131de5c 100644
--- a/drivers/pinctrl/renesas/core.c
+++ b/drivers/pinctrl/renesas/core.c
-@@ -890,7 +890,7 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info,
+@@ -739,7 +739,7 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
+
+ #ifdef DEBUG
+ #define SH_PFC_MAX_REGS 300
+-#define SH_PFC_MAX_ENUMS 3000
++#define SH_PFC_MAX_ENUMS 5000
+
+ static unsigned int sh_pfc_errors __initdata = 0;
+ static unsigned int sh_pfc_warnings __initdata = 0;
+@@ -851,7 +851,8 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname,
+ sh_pfc_check_reg(drvname, cfg_reg->reg);
+
+ if (cfg_reg->field_width) {
+- n = cfg_reg->reg_width / cfg_reg->field_width;
++ fw = cfg_reg->field_width;
++ n = (cfg_reg->reg_width / fw) << fw;
+ /* Skip field checks (done at build time) */
+ goto check_enum_ids;
+ }
+@@ -890,7 +891,7 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info,
if (!field->pin && !field->offset && !field->size)
continue;
@@ -100912,6 +147493,28 @@ index f2ab02225837e..f29130957e49a 100644
if (mask & seen)
sh_pfc_err("drive_reg 0x%x: field %u overlap\n",
drive->reg, i);
+diff --git a/drivers/pinctrl/renesas/pfc-r8a77470.c b/drivers/pinctrl/renesas/pfc-r8a77470.c
+index e6e5487691c16..cf7153d06a953 100644
+--- a/drivers/pinctrl/renesas/pfc-r8a77470.c
++++ b/drivers/pinctrl/renesas/pfc-r8a77470.c
+@@ -2140,7 +2140,7 @@ static const unsigned int vin0_clk_mux[] = {
+ VI0_CLK_MARK,
+ };
+ /* - VIN1 ------------------------------------------------------------------- */
+-static const union vin_data vin1_data_pins = {
++static const union vin_data12 vin1_data_pins = {
+ .data12 = {
+ RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 2),
+ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 4),
+@@ -2150,7 +2150,7 @@ static const union vin_data vin1_data_pins = {
+ RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
+ },
+ };
+-static const union vin_data vin1_data_mux = {
++static const union vin_data12 vin1_data_mux = {
+ .data12 = {
+ VI1_DATA0_MARK, VI1_DATA1_MARK,
+ VI1_DATA2_MARK, VI1_DATA3_MARK,
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index dbf2f521bb272..20b2af889ca96 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -100925,11 +147528,192 @@ index dbf2f521bb272..20b2af889ca96 100644
RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS),
RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS),
RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+diff --git a/drivers/pinctrl/samsung/Kconfig b/drivers/pinctrl/samsung/Kconfig
+index dfd805e768624..7b0576f71376e 100644
+--- a/drivers/pinctrl/samsung/Kconfig
++++ b/drivers/pinctrl/samsung/Kconfig
+@@ -4,14 +4,13 @@
+ #
+ config PINCTRL_SAMSUNG
+ bool
+- depends on OF_GPIO
++ select GPIOLIB
+ select PINMUX
+ select PINCONF
+
+ config PINCTRL_EXYNOS
+ bool "Pinctrl common driver part for Samsung Exynos SoCs"
+- depends on OF_GPIO
+- depends on ARCH_EXYNOS || ARCH_S5PV210 || COMPILE_TEST
++ depends on ARCH_EXYNOS || ARCH_S5PV210 || (COMPILE_TEST && OF)
+ select PINCTRL_SAMSUNG
+ select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210)
+ select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS
+@@ -26,12 +25,10 @@ config PINCTRL_EXYNOS_ARM64
+
+ config PINCTRL_S3C24XX
+ bool "Samsung S3C24XX SoC pinctrl driver"
+- depends on OF_GPIO
+- depends on ARCH_S3C24XX || COMPILE_TEST
++ depends on ARCH_S3C24XX || (COMPILE_TEST && OF)
+ select PINCTRL_SAMSUNG
+
+ config PINCTRL_S3C64XX
+ bool "Samsung S3C64XX SoC pinctrl driver"
+- depends on OF_GPIO
+- depends on ARCH_S3C64XX || COMPILE_TEST
++ depends on ARCH_S3C64XX || (COMPILE_TEST && OF)
+ select PINCTRL_SAMSUNG
+diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+index fe5f6046fbd52..cc66f852ef7bc 100644
+--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
++++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+@@ -504,13 +504,11 @@ static const struct samsung_pin_ctrl exynos850_pin_ctrl[] __initconst = {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos850_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks0),
+- .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 1 CMGP data */
+ .pin_banks = exynos850_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks1),
+- .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 2 AUD data */
+diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
+index 2a0fc63516f12..463b9e578237e 100644
+--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
++++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
+@@ -1002,6 +1002,16 @@ samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev)
+ return &(of_data->ctrl[id]);
+ }
+
++static void samsung_banks_of_node_put(struct samsung_pinctrl_drv_data *d)
++{
++ struct samsung_pin_bank *bank;
++ unsigned int i;
++
++ bank = d->pin_banks;
++ for (i = 0; i < d->nr_banks; ++i, ++bank)
++ of_node_put(bank->of_node);
++}
++
+ /* retrieve the soc specific data */
+ static const struct samsung_pin_ctrl *
+ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
+@@ -1116,19 +1126,19 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
+ if (ctrl->retention_data) {
+ drvdata->retention_ctrl = ctrl->retention_data->init(drvdata,
+ ctrl->retention_data);
+- if (IS_ERR(drvdata->retention_ctrl))
+- return PTR_ERR(drvdata->retention_ctrl);
++ if (IS_ERR(drvdata->retention_ctrl)) {
++ ret = PTR_ERR(drvdata->retention_ctrl);
++ goto err_put_banks;
++ }
+ }
+
+ ret = samsung_pinctrl_register(pdev, drvdata);
+ if (ret)
+- return ret;
++ goto err_put_banks;
+
+ ret = samsung_gpiolib_register(pdev, drvdata);
+- if (ret) {
+- samsung_pinctrl_unregister(pdev, drvdata);
+- return ret;
+- }
++ if (ret)
++ goto err_unregister;
+
+ if (ctrl->eint_gpio_init)
+ ctrl->eint_gpio_init(drvdata);
+@@ -1138,6 +1148,12 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, drvdata);
+
+ return 0;
++
++err_unregister:
++ samsung_pinctrl_unregister(pdev, drvdata);
++err_put_banks:
++ samsung_banks_of_node_put(drvdata);
++ return ret;
+ }
+
+ /*
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
-index dfd8888a222a4..8934b4878fa85 100644
+index dfd8888a222a4..97a4fb5a93280 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
-@@ -1251,10 +1251,10 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
+@@ -225,6 +225,13 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset)
+ pinctrl_gpio_free(chip->base + offset);
+ }
+
++static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset)
++{
++ struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
++
++ return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
++}
++
+ static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+ struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+@@ -232,7 +239,7 @@ static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
+
+ clk_enable(bank->clk);
+
+- ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
++ ret = stm32_gpio_get_noclk(chip, offset);
+
+ clk_disable(bank->clk);
+
+@@ -311,8 +318,12 @@ static void stm32_gpio_irq_trigger(struct irq_data *d)
+ struct stm32_gpio_bank *bank = d->domain->host_data;
+ int level;
+
++ /* Do not access the GPIO if this is not LEVEL triggered IRQ. */
++ if (!(bank->irq_type[d->hwirq] & IRQ_TYPE_LEVEL_MASK))
++ return;
++
+ /* If level interrupt type then retrig */
+- level = stm32_gpio_get(&bank->gpio_chip, d->hwirq);
++ level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq);
+ if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) ||
+ (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH))
+ irq_chip_retrigger_hierarchy(d);
+@@ -354,6 +365,7 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
+ {
+ struct stm32_gpio_bank *bank = irq_data->domain->host_data;
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
++ unsigned long flags;
+ int ret;
+
+ ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq);
+@@ -367,6 +379,10 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
+ return ret;
+ }
+
++ flags = irqd_get_trigger_type(irq_data);
++ if (flags & IRQ_TYPE_LEVEL_MASK)
++ clk_enable(bank->clk);
++
+ return 0;
+ }
+
+@@ -374,6 +390,9 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data)
+ {
+ struct stm32_gpio_bank *bank = irq_data->domain->host_data;
+
++ if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK)
++ clk_disable(bank->clk);
++
+ gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq);
+ }
+
+@@ -1251,10 +1270,10 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK;
bank->gpio_chip.base = args.args[1];
@@ -100996,6 +147780,366 @@ index 862c84efb718f..ce3f9ea415117 100644
irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
handle_edge_irq);
irq_set_chip_data(irqno, pctl);
+diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
+index f901d2e43166c..88cbc434c06b2 100644
+--- a/drivers/platform/chrome/Makefile
++++ b/drivers/platform/chrome/Makefile
+@@ -2,6 +2,7 @@
+
+ # tell define_trace.h where to find the cros ec trace header
+ CFLAGS_cros_ec_trace.o:= -I$(src)
++CFLAGS_cros_ec_sensorhub_ring.o:= -I$(src)
+
+ obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
+ obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
+@@ -20,7 +21,7 @@ obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o
+ obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
+ obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
+ obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
+-cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o cros_ec_trace.o
++cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o
+ obj-$(CONFIG_CROS_EC_SENSORHUB) += cros-ec-sensorhub.o
+ obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
+ obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o
+diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
+index 272c89837d745..0dbceee87a4b1 100644
+--- a/drivers/platform/chrome/cros_ec_debugfs.c
++++ b/drivers/platform/chrome/cros_ec_debugfs.c
+@@ -25,6 +25,9 @@
+
+ #define CIRC_ADD(idx, size, value) (((idx) + (value)) & ((size) - 1))
+
++/* waitqueue for log readers */
++static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq);
++
+ /**
+ * struct cros_ec_debugfs - EC debugging information.
+ *
+@@ -33,7 +36,6 @@
+ * @log_buffer: circular buffer for console log information
+ * @read_msg: preallocated EC command and buffer to read console log
+ * @log_mutex: mutex to protect circular buffer
+- * @log_wq: waitqueue for log readers
+ * @log_poll_work: recurring task to poll EC for new console log data
+ * @panicinfo_blob: panicinfo debugfs blob
+ */
+@@ -44,7 +46,6 @@ struct cros_ec_debugfs {
+ struct circ_buf log_buffer;
+ struct cros_ec_command *read_msg;
+ struct mutex log_mutex;
+- wait_queue_head_t log_wq;
+ struct delayed_work log_poll_work;
+ /* EC panicinfo */
+ struct debugfs_blob_wrapper panicinfo_blob;
+@@ -107,7 +108,7 @@ static void cros_ec_console_log_work(struct work_struct *__work)
+ buf_space--;
+ }
+
+- wake_up(&debug_info->log_wq);
++ wake_up(&cros_ec_debugfs_log_wq);
+ }
+
+ mutex_unlock(&debug_info->log_mutex);
+@@ -141,7 +142,7 @@ static ssize_t cros_ec_console_log_read(struct file *file, char __user *buf,
+
+ mutex_unlock(&debug_info->log_mutex);
+
+- ret = wait_event_interruptible(debug_info->log_wq,
++ ret = wait_event_interruptible(cros_ec_debugfs_log_wq,
+ CIRC_CNT(cb->head, cb->tail, LOG_SIZE));
+ if (ret < 0)
+ return ret;
+@@ -173,7 +174,7 @@ static __poll_t cros_ec_console_log_poll(struct file *file,
+ struct cros_ec_debugfs *debug_info = file->private_data;
+ __poll_t mask = 0;
+
+- poll_wait(file, &debug_info->log_wq, wait);
++ poll_wait(file, &cros_ec_debugfs_log_wq, wait);
+
+ mutex_lock(&debug_info->log_mutex);
+ if (CIRC_CNT(debug_info->log_buffer.head,
+@@ -377,7 +378,6 @@ static int cros_ec_create_console_log(struct cros_ec_debugfs *debug_info)
+ debug_info->log_buffer.tail = 0;
+
+ mutex_init(&debug_info->log_mutex);
+- init_waitqueue_head(&debug_info->log_wq);
+
+ debugfs_create_file("console_log", S_IFREG | 0444, debug_info->dir,
+ debug_info, &cros_ec_console_log_fops);
+diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+index 98e37080f7609..71948dade0e2a 100644
+--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
++++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+@@ -17,7 +17,8 @@
+ #include <linux/sort.h>
+ #include <linux/slab.h>
+
+-#include "cros_ec_trace.h"
++#define CREATE_TRACE_POINTS
++#include "cros_ec_sensorhub_trace.h"
+
+ /* Precision of fixed point for the m values from the filter */
+ #define M_PRECISION BIT(23)
+diff --git a/drivers/platform/chrome/cros_ec_sensorhub_trace.h b/drivers/platform/chrome/cros_ec_sensorhub_trace.h
+new file mode 100644
+index 0000000000000..57d9b47859692
+--- /dev/null
++++ b/drivers/platform/chrome/cros_ec_sensorhub_trace.h
+@@ -0,0 +1,123 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Trace events for the ChromeOS Sensorhub kernel module
++ *
++ * Copyright 2021 Google LLC.
++ */
++
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM cros_ec
++
++#if !defined(_CROS_EC_SENSORHUB_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
++#define _CROS_EC_SENSORHUB_TRACE_H_
++
++#include <linux/types.h>
++#include <linux/platform_data/cros_ec_sensorhub.h>
++
++#include <linux/tracepoint.h>
++
++TRACE_EVENT(cros_ec_sensorhub_timestamp,
++ TP_PROTO(u32 ec_sample_timestamp, u32 ec_fifo_timestamp, s64 fifo_timestamp,
++ s64 current_timestamp, s64 current_time),
++ TP_ARGS(ec_sample_timestamp, ec_fifo_timestamp, fifo_timestamp, current_timestamp,
++ current_time),
++ TP_STRUCT__entry(
++ __field(u32, ec_sample_timestamp)
++ __field(u32, ec_fifo_timestamp)
++ __field(s64, fifo_timestamp)
++ __field(s64, current_timestamp)
++ __field(s64, current_time)
++ __field(s64, delta)
++ ),
++ TP_fast_assign(
++ __entry->ec_sample_timestamp = ec_sample_timestamp;
++ __entry->ec_fifo_timestamp = ec_fifo_timestamp;
++ __entry->fifo_timestamp = fifo_timestamp;
++ __entry->current_timestamp = current_timestamp;
++ __entry->current_time = current_time;
++ __entry->delta = current_timestamp - current_time;
++ ),
++ TP_printk("ec_ts: %9u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
++ __entry->ec_sample_timestamp,
++ __entry->ec_fifo_timestamp,
++ __entry->fifo_timestamp,
++ __entry->current_timestamp,
++ __entry->current_time,
++ __entry->delta
++ )
++);
++
++TRACE_EVENT(cros_ec_sensorhub_data,
++ TP_PROTO(u32 ec_sensor_num, u32 ec_fifo_timestamp, s64 fifo_timestamp,
++ s64 current_timestamp, s64 current_time),
++ TP_ARGS(ec_sensor_num, ec_fifo_timestamp, fifo_timestamp, current_timestamp, current_time),
++ TP_STRUCT__entry(
++ __field(u32, ec_sensor_num)
++ __field(u32, ec_fifo_timestamp)
++ __field(s64, fifo_timestamp)
++ __field(s64, current_timestamp)
++ __field(s64, current_time)
++ __field(s64, delta)
++ ),
++ TP_fast_assign(
++ __entry->ec_sensor_num = ec_sensor_num;
++ __entry->ec_fifo_timestamp = ec_fifo_timestamp;
++ __entry->fifo_timestamp = fifo_timestamp;
++ __entry->current_timestamp = current_timestamp;
++ __entry->current_time = current_time;
++ __entry->delta = current_timestamp - current_time;
++ ),
++ TP_printk("ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
++ __entry->ec_sensor_num,
++ __entry->ec_fifo_timestamp,
++ __entry->fifo_timestamp,
++ __entry->current_timestamp,
++ __entry->current_time,
++ __entry->delta
++ )
++);
++
++TRACE_EVENT(cros_ec_sensorhub_filter,
++ TP_PROTO(struct cros_ec_sensors_ts_filter_state *state, s64 dx, s64 dy),
++ TP_ARGS(state, dx, dy),
++ TP_STRUCT__entry(
++ __field(s64, dx)
++ __field(s64, dy)
++ __field(s64, median_m)
++ __field(s64, median_error)
++ __field(s64, history_len)
++ __field(s64, x)
++ __field(s64, y)
++ ),
++ TP_fast_assign(
++ __entry->dx = dx;
++ __entry->dy = dy;
++ __entry->median_m = state->median_m;
++ __entry->median_error = state->median_error;
++ __entry->history_len = state->history_len;
++ __entry->x = state->x_offset;
++ __entry->y = state->y_offset;
++ ),
++ TP_printk("dx: %12lld. dy: %12lld median_m: %12lld median_error: %12lld len: %lld x: %12lld y: %12lld",
++ __entry->dx,
++ __entry->dy,
++ __entry->median_m,
++ __entry->median_error,
++ __entry->history_len,
++ __entry->x,
++ __entry->y
++ )
++);
++
++
++#endif /* _CROS_EC_SENSORHUB_TRACE_H_ */
++
++/* this part must be outside header guard */
++
++#undef TRACE_INCLUDE_PATH
++#define TRACE_INCLUDE_PATH .
++
++#undef TRACE_INCLUDE_FILE
++#define TRACE_INCLUDE_FILE cros_ec_sensorhub_trace
++
++#include <trace/define_trace.h>
+diff --git a/drivers/platform/chrome/cros_ec_trace.h b/drivers/platform/chrome/cros_ec_trace.h
+index 7e7cfc98657a4..9bb5cd2c98b8b 100644
+--- a/drivers/platform/chrome/cros_ec_trace.h
++++ b/drivers/platform/chrome/cros_ec_trace.h
+@@ -15,7 +15,6 @@
+ #include <linux/types.h>
+ #include <linux/platform_data/cros_ec_commands.h>
+ #include <linux/platform_data/cros_ec_proto.h>
+-#include <linux/platform_data/cros_ec_sensorhub.h>
+
+ #include <linux/tracepoint.h>
+
+@@ -71,100 +70,6 @@ TRACE_EVENT(cros_ec_request_done,
+ __entry->retval)
+ );
+
+-TRACE_EVENT(cros_ec_sensorhub_timestamp,
+- TP_PROTO(u32 ec_sample_timestamp, u32 ec_fifo_timestamp, s64 fifo_timestamp,
+- s64 current_timestamp, s64 current_time),
+- TP_ARGS(ec_sample_timestamp, ec_fifo_timestamp, fifo_timestamp, current_timestamp,
+- current_time),
+- TP_STRUCT__entry(
+- __field(u32, ec_sample_timestamp)
+- __field(u32, ec_fifo_timestamp)
+- __field(s64, fifo_timestamp)
+- __field(s64, current_timestamp)
+- __field(s64, current_time)
+- __field(s64, delta)
+- ),
+- TP_fast_assign(
+- __entry->ec_sample_timestamp = ec_sample_timestamp;
+- __entry->ec_fifo_timestamp = ec_fifo_timestamp;
+- __entry->fifo_timestamp = fifo_timestamp;
+- __entry->current_timestamp = current_timestamp;
+- __entry->current_time = current_time;
+- __entry->delta = current_timestamp - current_time;
+- ),
+- TP_printk("ec_ts: %9u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
+- __entry->ec_sample_timestamp,
+- __entry->ec_fifo_timestamp,
+- __entry->fifo_timestamp,
+- __entry->current_timestamp,
+- __entry->current_time,
+- __entry->delta
+- )
+-);
+-
+-TRACE_EVENT(cros_ec_sensorhub_data,
+- TP_PROTO(u32 ec_sensor_num, u32 ec_fifo_timestamp, s64 fifo_timestamp,
+- s64 current_timestamp, s64 current_time),
+- TP_ARGS(ec_sensor_num, ec_fifo_timestamp, fifo_timestamp, current_timestamp, current_time),
+- TP_STRUCT__entry(
+- __field(u32, ec_sensor_num)
+- __field(u32, ec_fifo_timestamp)
+- __field(s64, fifo_timestamp)
+- __field(s64, current_timestamp)
+- __field(s64, current_time)
+- __field(s64, delta)
+- ),
+- TP_fast_assign(
+- __entry->ec_sensor_num = ec_sensor_num;
+- __entry->ec_fifo_timestamp = ec_fifo_timestamp;
+- __entry->fifo_timestamp = fifo_timestamp;
+- __entry->current_timestamp = current_timestamp;
+- __entry->current_time = current_time;
+- __entry->delta = current_timestamp - current_time;
+- ),
+- TP_printk("ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
+- __entry->ec_sensor_num,
+- __entry->ec_fifo_timestamp,
+- __entry->fifo_timestamp,
+- __entry->current_timestamp,
+- __entry->current_time,
+- __entry->delta
+- )
+-);
+-
+-TRACE_EVENT(cros_ec_sensorhub_filter,
+- TP_PROTO(struct cros_ec_sensors_ts_filter_state *state, s64 dx, s64 dy),
+- TP_ARGS(state, dx, dy),
+- TP_STRUCT__entry(
+- __field(s64, dx)
+- __field(s64, dy)
+- __field(s64, median_m)
+- __field(s64, median_error)
+- __field(s64, history_len)
+- __field(s64, x)
+- __field(s64, y)
+- ),
+- TP_fast_assign(
+- __entry->dx = dx;
+- __entry->dy = dy;
+- __entry->median_m = state->median_m;
+- __entry->median_error = state->median_error;
+- __entry->history_len = state->history_len;
+- __entry->x = state->x_offset;
+- __entry->y = state->y_offset;
+- ),
+- TP_printk("dx: %12lld. dy: %12lld median_m: %12lld median_error: %12lld len: %lld x: %12lld y: %12lld",
+- __entry->dx,
+- __entry->dy,
+- __entry->median_m,
+- __entry->median_error,
+- __entry->history_len,
+- __entry->x,
+- __entry->y
+- )
+-);
+-
+-
+ #endif /* _CROS_EC_TRACE_H_ */
+
+ /* this part must be outside header guard */
+diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
+index 262a891eded34..4027c3ef90d7c 100644
+--- a/drivers/platform/chrome/cros_ec_typec.c
++++ b/drivers/platform/chrome/cros_ec_typec.c
+@@ -1106,7 +1106,13 @@ static int cros_typec_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ typec->dev = dev;
++
+ typec->ec = dev_get_drvdata(pdev->dev.parent);
++ if (!typec->ec) {
++ dev_err(dev, "couldn't find parent EC device\n");
++ return -ENODEV;
++ }
++
+ platform_set_drvdata(pdev, typec);
+
+ ret = cros_typec_get_cmd_version(typec);
diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
index 04bc3b50aa7a4..65b4a819f1bdf 100644
--- a/drivers/platform/mellanox/mlxbf-pmc.c
@@ -101011,6 +148155,19 @@ index 04bc3b50aa7a4..65b4a819f1bdf 100644
ret = mlxbf_pmc_create_groups(dev, i);
if (ret)
+diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
+index c61bbeeec2dfd..54f86df77a37b 100644
+--- a/drivers/platform/surface/aggregator/core.c
++++ b/drivers/platform/surface/aggregator/core.c
+@@ -816,7 +816,7 @@ err_cpkg:
+ err_bus:
+ return status;
+ }
+-module_init(ssam_core_init);
++subsys_initcall(ssam_core_init);
+
+ static void __exit ssam_core_exit(void)
+ {
diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c
index 90c1568ea4e09..3cc004c68bdba 100644
--- a/drivers/platform/surface/surface3_power.c
@@ -101197,6 +148354,31 @@ index cc53f725c0419..ef24f53753c6e 100644
return ret;
}
+diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c
+index a2d846c4a7eef..eac3e6b4ea113 100644
+--- a/drivers/platform/x86/huawei-wmi.c
++++ b/drivers/platform/x86/huawei-wmi.c
+@@ -470,10 +470,17 @@ static DEVICE_ATTR_RW(charge_control_thresholds);
+
+ static int huawei_wmi_battery_add(struct power_supply *battery)
+ {
+- device_create_file(&battery->dev, &dev_attr_charge_control_start_threshold);
+- device_create_file(&battery->dev, &dev_attr_charge_control_end_threshold);
++ int err = 0;
+
+- return 0;
++ err = device_create_file(&battery->dev, &dev_attr_charge_control_start_threshold);
++ if (err)
++ return err;
++
++ err = device_create_file(&battery->dev, &dev_attr_charge_control_end_threshold);
++ if (err)
++ device_remove_file(&battery->dev, &dev_attr_charge_control_start_threshold);
++
++ return err;
+ }
+
+ static int huawei_wmi_battery_remove(struct power_supply *battery)
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 0b21468e1bd01..02e4481b384e4 100644
--- a/drivers/platform/x86/intel/Kconfig
@@ -101435,6 +148617,19 @@ index c9a85eb2e8600..e8424e70d81d2 100644
}
EXPORT_SYMBOL_GPL(isst_if_cdev_unregister);
+diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
+index 7ee010aa740aa..404bdb4cbfae4 100644
+--- a/drivers/platform/x86/samsung-laptop.c
++++ b/drivers/platform/x86/samsung-laptop.c
+@@ -1121,8 +1121,6 @@ static void kbd_led_set(struct led_classdev *led_cdev,
+
+ if (value > samsung->kbd_led.max_brightness)
+ value = samsung->kbd_led.max_brightness;
+- else if (value < 0)
+- value = 0;
+
+ samsung->kbd_led_wk = value;
+ queue_work(samsung->led_workqueue, &samsung->kbd_led_work);
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
index 9472aae72df29..c4d9c45350f7c 100644
--- a/drivers/platform/x86/think-lmi.c
@@ -101624,6 +148819,21 @@ index 026649409135c..64def79d557a8 100644
dev_err(&pdev->dev, "Could not map ram controller address\n");
of_node_put(np);
return -ENODEV;
+diff --git a/drivers/power/reset/gemini-poweroff.c b/drivers/power/reset/gemini-poweroff.c
+index 90e35c07240ae..b7f7a8225f22e 100644
+--- a/drivers/power/reset/gemini-poweroff.c
++++ b/drivers/power/reset/gemini-poweroff.c
+@@ -107,8 +107,8 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
+ return PTR_ERR(gpw->base);
+
+ irq = platform_get_irq(pdev, 0);
+- if (!irq)
+- return -EINVAL;
++ if (irq < 0)
++ return irq;
+
+ gpw->dev = dev;
+
diff --git a/drivers/power/reset/ltc2952-poweroff.c b/drivers/power/reset/ltc2952-poweroff.c
index 8688c8ba8894c..81be33c041d6b 100644
--- a/drivers/power/reset/ltc2952-poweroff.c
@@ -101653,6 +148863,131 @@ index 0532803e6cbc4..d90e76fcb9383 100644
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
+diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c
+index ff4b26b1cecae..b809fa5abbbaf 100644
+--- a/drivers/power/supply/ab8500_chargalg.c
++++ b/drivers/power/supply/ab8500_chargalg.c
+@@ -2019,11 +2019,11 @@ static int ab8500_chargalg_probe(struct platform_device *pdev)
+ psy_cfg.drv_data = di;
+
+ /* Initilialize safety timer */
+- hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
++ hrtimer_init(&di->safety_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ di->safety_timer.function = ab8500_chargalg_safety_timer_expired;
+
+ /* Initilialize maintenance timer */
+- hrtimer_init(&di->maintenance_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
++ hrtimer_init(&di->maintenance_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ di->maintenance_timer.function =
+ ab8500_chargalg_maintenance_timer_expired;
+
+diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
+index 05fe9724ba508..57799a8079d44 100644
+--- a/drivers/power/supply/ab8500_fg.c
++++ b/drivers/power/supply/ab8500_fg.c
+@@ -2545,8 +2545,10 @@ static int ab8500_fg_sysfs_init(struct ab8500_fg *di)
+ ret = kobject_init_and_add(&di->fg_kobject,
+ &ab8500_fg_ktype,
+ NULL, "battery");
+- if (ret < 0)
++ if (ret < 0) {
++ kobject_put(&di->fg_kobject);
+ dev_err(di->dev, "failed to create sysfs entry\n");
++ }
+
+ return ret;
+ }
+diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
+index 18a9db0df4b1f..335e12cc5e2f9 100644
+--- a/drivers/power/supply/axp20x_battery.c
++++ b/drivers/power/supply/axp20x_battery.c
+@@ -186,7 +186,6 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
+ union power_supply_propval *val)
+ {
+ struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
+- struct iio_channel *chan;
+ int ret = 0, reg, val1;
+
+ switch (psp) {
+@@ -266,12 +265,12 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
+ if (ret)
+ return ret;
+
+- if (reg & AXP20X_PWR_STATUS_BAT_CHARGING)
+- chan = axp20x_batt->batt_chrg_i;
+- else
+- chan = axp20x_batt->batt_dischrg_i;
+-
+- ret = iio_read_channel_processed(chan, &val->intval);
++ if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
++ ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
++ } else {
++ ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
++ val->intval = -val1;
++ }
+ if (ret)
+ return ret;
+
+diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c
+index b9553be9bed56..fb9db7f438951 100644
+--- a/drivers/power/supply/axp288_charger.c
++++ b/drivers/power/supply/axp288_charger.c
+@@ -41,11 +41,11 @@
+ #define VBUS_ISPOUT_CUR_LIM_1500MA 0x1 /* 1500mA */
+ #define VBUS_ISPOUT_CUR_LIM_2000MA 0x2 /* 2000mA */
+ #define VBUS_ISPOUT_CUR_NO_LIM 0x3 /* 2500mA */
+-#define VBUS_ISPOUT_VHOLD_SET_MASK 0x31
++#define VBUS_ISPOUT_VHOLD_SET_MASK 0x38
+ #define VBUS_ISPOUT_VHOLD_SET_BIT_POS 0x3
+ #define VBUS_ISPOUT_VHOLD_SET_OFFSET 4000 /* 4000mV */
+ #define VBUS_ISPOUT_VHOLD_SET_LSB_RES 100 /* 100mV */
+-#define VBUS_ISPOUT_VHOLD_SET_4300MV 0x3 /* 4300mV */
++#define VBUS_ISPOUT_VHOLD_SET_4400MV 0x4 /* 4400mV */
+ #define VBUS_ISPOUT_VBUS_PATH_DIS BIT(7)
+
+ #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */
+@@ -744,6 +744,16 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
+ ret = axp288_charger_vbus_path_select(info, true);
+ if (ret < 0)
+ return ret;
++ } else {
++ /* Set Vhold to the factory default / recommended 4.4V */
++ val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS;
++ ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
++ VBUS_ISPOUT_VHOLD_SET_MASK, val);
++ if (ret < 0) {
++ dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
++ AXP20X_VBUS_IPSOUT_MGMT, ret);
++ return ret;
++ }
+ }
+
+ /* Read current charge voltage and current limit */
+diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
+index 35ff0c8fe96f5..16c4876fe5afb 100644
+--- a/drivers/power/supply/bq24190_charger.c
++++ b/drivers/power/supply/bq24190_charger.c
+@@ -39,6 +39,7 @@
+ #define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0
+ #define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1
+ #define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2
++#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3
+ #define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1))
+ #define BQ24190_REG_POC_SYS_MIN_SHIFT 1
+ #define BQ24190_REG_POC_SYS_MIN_MIN 3000
+@@ -550,7 +551,11 @@ static int bq24190_vbus_is_enabled(struct regulator_dev *dev)
+ pm_runtime_mark_last_busy(bdi->dev);
+ pm_runtime_put_autosuspend(bdi->dev);
+
+- return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG;
++ if (ret)
++ return ret;
++
++ return (val == BQ24190_REG_POC_CHG_CONFIG_OTG ||
++ val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT);
+ }
+
+ static const struct regulator_ops bq24190_vbus_ops = {
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index 945c3257ca931..fe814805c68b5 100644
--- a/drivers/power/supply/bq25890_charger.c
@@ -101764,6 +149099,233 @@ index 9ad0afe83d1b7..7a23c70f48791 100644
return ret;
}
+diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c
+index 6fa65d118ec12..b08f7d0c41815 100644
+--- a/drivers/power/supply/sbs-charger.c
++++ b/drivers/power/supply/sbs-charger.c
+@@ -18,6 +18,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/regmap.h>
+ #include <linux/bitops.h>
++#include <linux/devm-helpers.h>
+
+ #define SBS_CHARGER_REG_SPEC_INFO 0x11
+ #define SBS_CHARGER_REG_STATUS 0x13
+@@ -209,7 +210,12 @@ static int sbs_probe(struct i2c_client *client,
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to request irq\n");
+ } else {
+- INIT_DELAYED_WORK(&chip->work, sbs_delayed_work);
++ ret = devm_delayed_work_autocancel(&client->dev, &chip->work,
++ sbs_delayed_work);
++ if (ret)
++ return dev_err_probe(&client->dev, ret,
++ "Failed to init work for polling\n");
++
+ schedule_delayed_work(&chip->work,
+ msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
+ }
+@@ -220,15 +226,6 @@ static int sbs_probe(struct i2c_client *client,
+ return 0;
+ }
+
+-static int sbs_remove(struct i2c_client *client)
+-{
+- struct sbs_info *chip = i2c_get_clientdata(client);
+-
+- cancel_delayed_work_sync(&chip->work);
+-
+- return 0;
+-}
+-
+ #ifdef CONFIG_OF
+ static const struct of_device_id sbs_dt_ids[] = {
+ { .compatible = "sbs,sbs-charger" },
+@@ -245,7 +242,6 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
+
+ static struct i2c_driver sbs_driver = {
+ .probe = sbs_probe,
+- .remove = sbs_remove,
+ .id_table = sbs_id,
+ .driver = {
+ .name = "sbs-charger",
+diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c
+index e05cee457471b..908cfd45d2624 100644
+--- a/drivers/power/supply/wm8350_power.c
++++ b/drivers/power/supply/wm8350_power.c
+@@ -408,44 +408,112 @@ static const struct power_supply_desc wm8350_usb_desc = {
+ * Initialisation
+ *********************************************************************/
+
+-static void wm8350_init_charger(struct wm8350 *wm8350)
++static int wm8350_init_charger(struct wm8350 *wm8350)
+ {
++ int ret;
++
+ /* register our interest in charger events */
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
+ wm8350_charger_handler, 0, "Battery hot", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
++ if (ret)
++ goto err;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
+ wm8350_charger_handler, 0, "Battery cold", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
++ if (ret)
++ goto free_chg_bat_hot;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
+ wm8350_charger_handler, 0, "Battery fail", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
++ if (ret)
++ goto free_chg_bat_cold;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
+ wm8350_charger_handler, 0,
+ "Charger timeout", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
++ if (ret)
++ goto free_chg_bat_fail;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
+ wm8350_charger_handler, 0,
+ "Charge end", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
++ if (ret)
++ goto free_chg_to;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
+ wm8350_charger_handler, 0,
+ "Charge start", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
++ if (ret)
++ goto free_chg_end;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
+ wm8350_charger_handler, 0,
+ "Fast charge ready", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
++ if (ret)
++ goto free_chg_start;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
+ wm8350_charger_handler, 0,
+ "Battery <3.9V", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
++ if (ret)
++ goto free_chg_fast_rdy;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
+ wm8350_charger_handler, 0,
+ "Battery <3.1V", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
++ if (ret)
++ goto free_chg_vbatt_lt_3p9;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
+ wm8350_charger_handler, 0,
+ "Battery <2.85V", wm8350);
++ if (ret)
++ goto free_chg_vbatt_lt_3p1;
+
+ /* and supply change events */
+- wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
+ wm8350_charger_handler, 0, "USB", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
++ if (ret)
++ goto free_chg_vbatt_lt_2p85;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
+ wm8350_charger_handler, 0, "Wall", wm8350);
+- wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
++ if (ret)
++ goto free_ext_usb_fb;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
+ wm8350_charger_handler, 0, "Battery", wm8350);
++ if (ret)
++ goto free_ext_wall_fb;
++
++ return 0;
++
++free_ext_wall_fb:
++ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
++free_ext_usb_fb:
++ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
++free_chg_vbatt_lt_2p85:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
++free_chg_vbatt_lt_3p1:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
++free_chg_vbatt_lt_3p9:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
++free_chg_fast_rdy:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
++free_chg_start:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
++free_chg_end:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
++free_chg_to:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
++free_chg_bat_fail:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
++free_chg_bat_cold:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
++free_chg_bat_hot:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
++err:
++ return ret;
+ }
+
+ static void free_charger_irq(struct wm8350 *wm8350)
+@@ -456,6 +524,7 @@ static void free_charger_irq(struct wm8350 *wm8350)
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
++ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
+diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
+index 35799e6401c99..2f4b11b4dfcd9 100644
+--- a/drivers/pps/clients/pps-gpio.c
++++ b/drivers/pps/clients/pps-gpio.c
+@@ -169,7 +169,7 @@ static int pps_gpio_probe(struct platform_device *pdev)
+ /* GPIO setup */
+ ret = pps_gpio_setup(dev);
+ if (ret)
+- return -EINVAL;
++ return ret;
+
+ /* IRQ setup */
+ ret = gpiod_to_irq(data->gpio_pin);
+diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
+index f9b2d66b04433..8a652a367625b 100644
+--- a/drivers/ptp/ptp_clock.c
++++ b/drivers/ptp/ptp_clock.c
+@@ -317,11 +317,18 @@ no_memory:
+ }
+ EXPORT_SYMBOL(ptp_clock_register);
+
++static int unregister_vclock(struct device *dev, void *data)
++{
++ struct ptp_clock *ptp = dev_get_drvdata(dev);
++
++ ptp_vclock_unregister(info_to_vclock(ptp->info));
++ return 0;
++}
++
+ int ptp_clock_unregister(struct ptp_clock *ptp)
+ {
+ if (ptp_vclock_in_use(ptp)) {
+- pr_err("ptp: virtual clock in use\n");
+- return -EBUSY;
++ device_for_each_child(&ptp->dev, NULL, unregister_vclock);
+ }
+
+ ptp->defunct = 1;
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index caf9b37c5eb1e..e238ae8e94709 100644
--- a/drivers/ptp/ptp_ocp.c
@@ -101793,6 +149355,28 @@ index caf9b37c5eb1e..e238ae8e94709 100644
bp_assign_entry(bp, r, mem);
+diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
+index 41b92dc2f011a..9233bfedeb174 100644
+--- a/drivers/ptp/ptp_sysfs.c
++++ b/drivers/ptp/ptp_sysfs.c
+@@ -14,7 +14,7 @@ static ssize_t clock_name_show(struct device *dev,
+ struct device_attribute *attr, char *page)
+ {
+ struct ptp_clock *ptp = dev_get_drvdata(dev);
+- return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
++ return sysfs_emit(page, "%s\n", ptp->info->name);
+ }
+ static DEVICE_ATTR_RO(clock_name);
+
+@@ -387,7 +387,7 @@ static ssize_t ptp_pin_show(struct device *dev, struct device_attribute *attr,
+
+ mutex_unlock(&ptp->pincfg_mux);
+
+- return snprintf(page, PAGE_SIZE, "%u %u\n", func, chan);
++ return sysfs_emit(page, "%u %u\n", func, chan);
+ }
+
+ static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
index baee0379482bc..ab1d233173e13 100644
--- a/drivers/ptp/ptp_vclock.c
@@ -101832,6 +149416,70 @@ index baee0379482bc..ab1d233173e13 100644
}
EXPORT_SYMBOL(ptp_convert_timestamp);
#endif
+diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c
+index 8e461f3baa05a..8cc8ae16553cf 100644
+--- a/drivers/pwm/pwm-lpc18xx-sct.c
++++ b/drivers/pwm/pwm-lpc18xx-sct.c
+@@ -395,12 +395,6 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
+ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
+ BIT(lpc18xx_pwm->period_event));
+
+- ret = pwmchip_add(&lpc18xx_pwm->chip);
+- if (ret < 0) {
+- dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
+- goto disable_pwmclk;
+- }
+-
+ for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) {
+ struct lpc18xx_pwm_data *data;
+
+@@ -410,14 +404,12 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
+ GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+- goto remove_pwmchip;
++ goto disable_pwmclk;
+ }
+
+ pwm_set_chip_data(pwm, data);
+ }
+
+- platform_set_drvdata(pdev, lpc18xx_pwm);
+-
+ val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
+ val &= ~LPC18XX_PWM_BIDIR;
+ val &= ~LPC18XX_PWM_CTRL_HALT;
+@@ -425,10 +417,16 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
+ val |= LPC18XX_PWM_PRE(0);
+ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
+
++ ret = pwmchip_add(&lpc18xx_pwm->chip);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
++ goto disable_pwmclk;
++ }
++
++ platform_set_drvdata(pdev, lpc18xx_pwm);
++
+ return 0;
+
+-remove_pwmchip:
+- pwmchip_remove(&lpc18xx_pwm->chip);
+ disable_pwmclk:
+ clk_disable_unprepare(lpc18xx_pwm->pwm_clk);
+ return ret;
+diff --git a/drivers/regulator/atc260x-regulator.c b/drivers/regulator/atc260x-regulator.c
+index 05147d2c38428..485e58b264c04 100644
+--- a/drivers/regulator/atc260x-regulator.c
++++ b/drivers/regulator/atc260x-regulator.c
+@@ -292,6 +292,7 @@ enum atc2603c_reg_ids {
+ .bypass_mask = BIT(5), \
+ .active_discharge_reg = ATC2603C_PMU_SWITCH_CTL, \
+ .active_discharge_mask = BIT(1), \
++ .active_discharge_on = BIT(1), \
+ .owner = THIS_MODULE, \
+ }
+
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba8a191a..46e76b5b21efe 100644
--- a/drivers/regulator/core.c
@@ -101894,7 +149542,7 @@ index b3da0dc58782f..639b71eb41ffe 100644
/* If we tried to recover for too many times it's not getting better */
if (vreg->ocp_irq_count > LABIBB_MAX_OCP_COUNT)
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
-index 198fcc6551f6d..8e077792bddd9 100644
+index 198fcc6551f6d..b6287f7e78f49 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -9,6 +9,7 @@
@@ -101905,7 +149553,7 @@ index 198fcc6551f6d..8e077792bddd9 100644
#include <linux/soc/qcom/smd-rpm.h>
struct qcom_rpm_reg {
-@@ -1190,52 +1191,91 @@ static const struct of_device_id rpm_of_match[] = {
+@@ -1190,52 +1191,93 @@ static const struct of_device_id rpm_of_match[] = {
};
MODULE_DEVICE_TABLE(of, rpm_of_match);
@@ -101996,8 +149644,13 @@ index 198fcc6551f6d..8e077792bddd9 100644
- for (reg = match->data; reg->name; reg++) {
+ for_each_available_child_of_node(dev->of_node, node) {
vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
- if (!vreg)
+- if (!vreg)
++ if (!vreg) {
++ of_node_put(node);
return -ENOMEM;
++ }
++
++ ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
- vreg->dev = &pdev->dev;
- vreg->type = reg->type;
@@ -102019,14 +149672,139 @@ index 198fcc6551f6d..8e077792bddd9 100644
- if (IS_ERR(rdev)) {
- dev_err(&pdev->dev, "failed to register %s\n", reg->name);
- return PTR_ERR(rdev);
-+ ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
-+
+ if (ret < 0) {
+ of_node_put(node);
+ return ret;
}
}
+diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c
+index ee46bfbf5eee7..991b4730d7687 100644
+--- a/drivers/regulator/rpi-panel-attiny-regulator.c
++++ b/drivers/regulator/rpi-panel-attiny-regulator.c
+@@ -37,11 +37,24 @@ static const struct regmap_config attiny_regmap_config = {
+ static int attiny_lcd_power_enable(struct regulator_dev *rdev)
+ {
+ unsigned int data;
++ int ret, i;
+
+ regmap_write(rdev->regmap, REG_POWERON, 1);
++ msleep(80);
++
+ /* Wait for nPWRDWN to go low to indicate poweron is done. */
+- regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data,
+- data & BIT(0), 10, 1000000);
++ for (i = 0; i < 20; i++) {
++ ret = regmap_read(rdev->regmap, REG_PORTB, &data);
++ if (!ret) {
++ if (data & BIT(0))
++ break;
++ }
++ usleep_range(10000, 12000);
++ }
++ usleep_range(10000, 12000);
++
++ if (ret)
++ pr_err("%s: regmap_read_poll_timeout failed %d\n", __func__, ret);
+
+ /* Default to the same orientation as the closed source
+ * firmware used for the panel. Runtime rotation
+@@ -57,23 +70,34 @@ static int attiny_lcd_power_disable(struct regulator_dev *rdev)
+ {
+ regmap_write(rdev->regmap, REG_PWM, 0);
+ regmap_write(rdev->regmap, REG_POWERON, 0);
+- udelay(1);
++ msleep(30);
+ return 0;
+ }
+
+ static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev)
+ {
+ unsigned int data;
+- int ret;
++ int ret, i;
+
+- ret = regmap_read(rdev->regmap, REG_POWERON, &data);
++ for (i = 0; i < 10; i++) {
++ ret = regmap_read(rdev->regmap, REG_POWERON, &data);
++ if (!ret)
++ break;
++ usleep_range(10000, 12000);
++ }
+ if (ret < 0)
+ return ret;
+
+ if (!(data & BIT(0)))
+ return 0;
+
+- ret = regmap_read(rdev->regmap, REG_PORTB, &data);
++ for (i = 0; i < 10; i++) {
++ ret = regmap_read(rdev->regmap, REG_PORTB, &data);
++ if (!ret)
++ break;
++ usleep_range(10000, 12000);
++ }
++
+ if (ret < 0)
+ return ret;
+
+@@ -103,20 +127,32 @@ static int attiny_update_status(struct backlight_device *bl)
+ {
+ struct regmap *regmap = bl_get_data(bl);
+ int brightness = bl->props.brightness;
++ int ret, i;
+
+ if (bl->props.power != FB_BLANK_UNBLANK ||
+ bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+- return regmap_write(regmap, REG_PWM, brightness);
++ for (i = 0; i < 10; i++) {
++ ret = regmap_write(regmap, REG_PWM, brightness);
++ if (!ret)
++ break;
++ }
++
++ return ret;
+ }
+
+ static int attiny_get_brightness(struct backlight_device *bl)
+ {
+ struct regmap *regmap = bl_get_data(bl);
+- int ret, brightness;
++ int ret, brightness, i;
++
++ for (i = 0; i < 10; i++) {
++ ret = regmap_read(regmap, REG_PWM, &brightness);
++ if (!ret)
++ break;
++ }
+
+- ret = regmap_read(regmap, REG_PWM, &brightness);
+ if (ret)
+ return ret;
+
+@@ -166,7 +202,7 @@ static int attiny_i2c_probe(struct i2c_client *i2c,
+ }
+
+ regmap_write(regmap, REG_POWERON, 0);
+- mdelay(1);
++ msleep(30);
+
+ config.dev = &i2c->dev;
+ config.regmap = regmap;
+diff --git a/drivers/regulator/rtq2134-regulator.c b/drivers/regulator/rtq2134-regulator.c
+index f21e3f8b21f23..8e13dea354a21 100644
+--- a/drivers/regulator/rtq2134-regulator.c
++++ b/drivers/regulator/rtq2134-regulator.c
+@@ -285,6 +285,7 @@ static const unsigned int rtq2134_buck_ramp_delay_table[] = {
+ .enable_mask = RTQ2134_VOUTEN_MASK, \
+ .active_discharge_reg = RTQ2134_REG_BUCK##_id##_CFG0, \
+ .active_discharge_mask = RTQ2134_ACTDISCHG_MASK, \
++ .active_discharge_on = RTQ2134_ACTDISCHG_MASK, \
+ .ramp_reg = RTQ2134_REG_BUCK##_id##_RSPCFG, \
+ .ramp_mask = RTQ2134_RSPUP_MASK, \
+ .ramp_delay_table = rtq2134_buck_ramp_delay_table, \
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 7c111bbdc2afa..35269f9982105 100644
--- a/drivers/regulator/s5m8767.c
@@ -102059,6 +149837,66 @@ index 7c111bbdc2afa..35269f9982105 100644
/* Initialize GPIO DVS registers */
for (i = 0; i < 8; i++) {
+diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
+index cadea0344486f..40befdd9dfa92 100644
+--- a/drivers/regulator/wm8994-regulator.c
++++ b/drivers/regulator/wm8994-regulator.c
+@@ -71,6 +71,35 @@ static const struct regulator_ops wm8994_ldo2_ops = {
+ };
+
+ static const struct regulator_desc wm8994_ldo_desc[] = {
++ {
++ .name = "LDO1",
++ .id = 1,
++ .type = REGULATOR_VOLTAGE,
++ .n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
++ .vsel_reg = WM8994_LDO_1,
++ .vsel_mask = WM8994_LDO1_VSEL_MASK,
++ .ops = &wm8994_ldo1_ops,
++ .min_uV = 2400000,
++ .uV_step = 100000,
++ .enable_time = 3000,
++ .off_on_delay = 36000,
++ .owner = THIS_MODULE,
++ },
++ {
++ .name = "LDO2",
++ .id = 2,
++ .type = REGULATOR_VOLTAGE,
++ .n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
++ .vsel_reg = WM8994_LDO_2,
++ .vsel_mask = WM8994_LDO2_VSEL_MASK,
++ .ops = &wm8994_ldo2_ops,
++ .enable_time = 3000,
++ .off_on_delay = 36000,
++ .owner = THIS_MODULE,
++ },
++};
++
++static const struct regulator_desc wm8958_ldo_desc[] = {
+ {
+ .name = "LDO1",
+ .id = 1,
+@@ -172,9 +201,16 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
+ * regulator core and we need not worry about it on the
+ * error path.
+ */
+- ldo->regulator = devm_regulator_register(&pdev->dev,
+- &wm8994_ldo_desc[id],
+- &config);
++ if (ldo->wm8994->type == WM8994) {
++ ldo->regulator = devm_regulator_register(&pdev->dev,
++ &wm8994_ldo_desc[id],
++ &config);
++ } else {
++ ldo->regulator = devm_regulator_register(&pdev->dev,
++ &wm8958_ldo_desc[id],
++ &config);
++ }
++
+ if (IS_ERR(ldo->regulator)) {
+ ret = PTR_ERR(ldo->regulator);
+ dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index d88f76f5305eb..05c39e1c56b49 100644
--- a/drivers/remoteproc/imx_rproc.c
@@ -102230,6 +150068,63 @@ index 7c007dd7b2000..aca21560e20b8 100644
found_existing:
/* Use two writel() as base is only aligned to 4 bytes on odd entries */
writel(base, entry + PIL_RELOC_NAME_LEN);
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 8b0d8bbacd2e4..c10d452c97032 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -406,6 +406,7 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
+ }
+
+ ret = of_address_to_resource(node, 0, &r);
++ of_node_put(node);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 423b31dfa5741..ca1c7387776b5 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -1624,18 +1624,20 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc)
+ * reserved memory regions from device's memory-region property.
+ */
+ child = of_get_child_by_name(qproc->dev->of_node, "mba");
+- if (!child)
++ if (!child) {
+ node = of_parse_phandle(qproc->dev->of_node,
+ "memory-region", 0);
+- else
++ } else {
+ node = of_parse_phandle(child, "memory-region", 0);
++ of_node_put(child);
++ }
+
+ ret = of_address_to_resource(node, 0, &r);
++ of_node_put(node);
+ if (ret) {
+ dev_err(qproc->dev, "unable to resolve mba region\n");
+ return ret;
+ }
+- of_node_put(node);
+
+ qproc->mba_phys = r.start;
+ qproc->mba_size = resource_size(&r);
+@@ -1646,14 +1648,15 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc)
+ } else {
+ child = of_get_child_by_name(qproc->dev->of_node, "mpss");
+ node = of_parse_phandle(child, "memory-region", 0);
++ of_node_put(child);
+ }
+
+ ret = of_address_to_resource(node, 0, &r);
++ of_node_put(node);
+ if (ret) {
+ dev_err(qproc->dev, "unable to resolve mpss region\n");
+ return ret;
+ }
+- of_node_put(node);
+
+ qproc->mpss_phys = qproc->mpss_reloc = r.start;
+ qproc->mpss_size = resource_size(&r);
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 401b1ec907852..699eaac5b760e 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
@@ -102242,6 +150137,18 @@ index 401b1ec907852..699eaac5b760e 100644
NULL
},
.ssr_name = "cdsp",
+diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
+index ebadc6c08e116..b17742eac9ffd 100644
+--- a/drivers/remoteproc/qcom_wcnss.c
++++ b/drivers/remoteproc/qcom_wcnss.c
+@@ -501,6 +501,7 @@ static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
+ }
+
+ ret = of_address_to_resource(node, 0, &r);
++ of_node_put(node);
+ if (ret)
+ return ret;
+
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 502b6604b757b..775df165eb450 100644
--- a/drivers/remoteproc/remoteproc_core.c
@@ -102282,6 +150189,19 @@ index aee657cc08c6a..c892f433a323e 100644
if (segment->dump) {
segment->dump(rproc, segment, dest, offset, size);
+diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
+index b5a1e3b697d9f..581930483ef84 100644
+--- a/drivers/remoteproc/remoteproc_debugfs.c
++++ b/drivers/remoteproc/remoteproc_debugfs.c
+@@ -76,7 +76,7 @@ static ssize_t rproc_coredump_write(struct file *filp,
+ int ret, err = 0;
+ char buf[20];
+
+- if (count > sizeof(buf))
++ if (count < 1 || count > sizeof(buf))
+ return -EINVAL;
+
+ ret = copy_from_user(buf, user_buf, count);
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 469c52e62faff..d635d19a5aa8a 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
@@ -102306,10 +150226,21 @@ index 469c52e62faff..d635d19a5aa8a 100644
memcpy(ptr, elf_data + offset, filesz);
}
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
-index e0704fd2b5336..1e83150388506 100644
+index e0704fd2b5336..a8dde46063602 100644
--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
-@@ -137,7 +137,12 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
+@@ -121,7 +121,9 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
+ return dev_err_probe(dev, PTR_ERR(priv->rstc),
+ "failed to get reset\n");
+
+- reset_control_deassert(priv->rstc);
++ error = reset_control_deassert(priv->rstc);
++ if (error)
++ return error;
+
+ priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
+ priv->rcdev.of_reset_n_cells = 1;
+@@ -137,7 +139,12 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
dev_set_drvdata(dev, priv);
pm_runtime_enable(&pdev->dev);
@@ -102323,33 +150254,6 @@ index e0704fd2b5336..1e83150388506 100644
/* put pll and phy into reset state */
spin_lock_irqsave(&priv->lock, flags);
-diff --git a/drivers/reset/tegra/reset-bpmp.c b/drivers/reset/tegra/reset-bpmp.c
-index 4c5bba52b1059..24d3395964cc4 100644
---- a/drivers/reset/tegra/reset-bpmp.c
-+++ b/drivers/reset/tegra/reset-bpmp.c
-@@ -20,7 +20,6 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc,
- struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc);
- struct mrq_reset_request request;
- struct tegra_bpmp_message msg;
-- int err;
-
- memset(&request, 0, sizeof(request));
- request.cmd = command;
-@@ -31,13 +30,7 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc,
- msg.tx.data = &request;
- msg.tx.size = sizeof(request);
-
-- err = tegra_bpmp_transfer(bpmp, &msg);
-- if (err)
-- return err;
-- if (msg.rx.ret)
-- return -EINVAL;
--
-- return 0;
-+ return tegra_bpmp_transfer(bpmp, &msg);
- }
-
- static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc,
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 2bebc9b2d1634..49dd5a2009982 100644
--- a/drivers/rpmsg/rpmsg_char.c
@@ -102464,11 +150368,81 @@ index 9151836190ce3..a71de08acc7b9 100644
out:
return err;
}
+diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
+index f77bc089eb6b7..0aef7df2ea704 100644
+--- a/drivers/rtc/class.c
++++ b/drivers/rtc/class.c
+@@ -26,6 +26,15 @@ struct class *rtc_class;
+ static void rtc_device_release(struct device *dev)
+ {
+ struct rtc_device *rtc = to_rtc_device(dev);
++ struct timerqueue_head *head = &rtc->timerqueue;
++ struct timerqueue_node *node;
++
++ mutex_lock(&rtc->ops_lock);
++ while ((node = timerqueue_getnext(head)))
++ timerqueue_del(head, node);
++ mutex_unlock(&rtc->ops_lock);
++
++ cancel_work_sync(&rtc->irqwork);
+
+ ida_simple_remove(&rtc_ida, rtc->id);
+ mutex_destroy(&rtc->ops_lock);
+diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
+index 9a2bd4947007c..3ee17c4d72987 100644
+--- a/drivers/rtc/interface.c
++++ b/drivers/rtc/interface.c
+@@ -793,9 +793,13 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
+ struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
+ struct rtc_time tm;
+ ktime_t now;
++ int err;
++
++ err = __rtc_read_time(rtc, &tm);
++ if (err)
++ return err;
+
+ timer->enabled = 1;
+- __rtc_read_time(rtc, &tm);
+ now = rtc_tm_to_ktime(tm);
+
+ /* Skip over expired timers */
+@@ -809,7 +813,6 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
+ trace_rtc_timer_enqueue(timer);
+ if (!next || ktime_before(timer->node.expires, next->expires)) {
+ struct rtc_wkalrm alarm;
+- int err;
+
+ alarm.time = rtc_ktime_to_tm(timer->node.expires);
+ alarm.enabled = 1;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
-index 4eb53412b8085..dc3f8b0dde989 100644
+index 4eb53412b8085..b90a603d6b12f 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
-@@ -457,7 +457,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+@@ -222,6 +222,8 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
+
+ static int cmos_read_time(struct device *dev, struct rtc_time *t)
+ {
++ int ret;
++
+ /*
+ * If pm_trace abused the RTC for storage, set the timespec to 0,
+ * which tells the caller that this RTC value is unusable.
+@@ -229,7 +231,12 @@ static int cmos_read_time(struct device *dev, struct rtc_time *t)
+ if (!pm_trace_rtc_valid())
+ return -EIO;
+
+- mc146818_get_time(t);
++ ret = mc146818_get_time(t);
++ if (ret < 0) {
++ dev_err_ratelimited(dev, "unable to read current time\n");
++ return ret;
++ }
++
+ return 0;
+ }
+
+@@ -457,7 +464,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
min = t->time.tm_min;
sec = t->time.tm_sec;
@@ -102479,6 +150453,27 @@ index 4eb53412b8085..dc3f8b0dde989 100644
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
/* Writing 0xff means "don't care" or "match all". */
mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
+@@ -790,16 +800,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
+
+ rename_region(ports, dev_name(&cmos_rtc.rtc->dev));
+
+- spin_lock_irq(&rtc_lock);
+-
+- /* Ensure that the RTC is accessible. Bit 6 must be 0! */
+- if ((CMOS_READ(RTC_VALID) & 0x40) != 0) {
+- spin_unlock_irq(&rtc_lock);
+- dev_warn(dev, "not accessible\n");
++ if (!mc146818_does_rtc_work()) {
++ dev_warn(dev, "broken or not accessible\n");
+ retval = -ENXIO;
+ goto cleanup1;
+ }
+
++ spin_lock_irq(&rtc_lock);
++
+ if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
+ /* force periodic irq to CMOS reset default of 1024Hz;
+ *
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index b3de6d2e680a4..2f83adef966eb 100644
--- a/drivers/rtc/rtc-ds1302.c
@@ -102527,10 +150522,68 @@ index 66fc8617d07ee..93ce72b9ae59e 100644
module_spi_driver(ds1390_driver);
diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c
-index dcfaf09946ee3..2065842f775d6 100644
+index dcfaf09946ee3..f3f5a87fe376e 100644
--- a/drivers/rtc/rtc-mc146818-lib.c
+++ b/drivers/rtc/rtc-mc146818-lib.c
-@@ -104,7 +104,7 @@ again:
+@@ -8,10 +8,36 @@
+ #include <linux/acpi.h>
+ #endif
+
+-unsigned int mc146818_get_time(struct rtc_time *time)
++/*
++ * If the UIP (Update-in-progress) bit of the RTC is set for more then
++ * 10ms, the RTC is apparently broken or not present.
++ */
++bool mc146818_does_rtc_work(void)
++{
++ int i;
++ unsigned char val;
++ unsigned long flags;
++
++ for (i = 0; i < 10; i++) {
++ spin_lock_irqsave(&rtc_lock, flags);
++ val = CMOS_READ(RTC_FREQ_SELECT);
++ spin_unlock_irqrestore(&rtc_lock, flags);
++
++ if ((val & RTC_UIP) == 0)
++ return true;
++
++ mdelay(1);
++ }
++
++ return false;
++}
++EXPORT_SYMBOL_GPL(mc146818_does_rtc_work);
++
++int mc146818_get_time(struct rtc_time *time)
+ {
+ unsigned char ctrl;
+ unsigned long flags;
++ unsigned int iter_count = 0;
+ unsigned char century = 0;
+ bool retry;
+
+@@ -20,13 +46,13 @@ unsigned int mc146818_get_time(struct rtc_time *time)
+ #endif
+
+ again:
+- spin_lock_irqsave(&rtc_lock, flags);
+- /* Ensure that the RTC is accessible. Bit 6 must be 0! */
+- if (WARN_ON_ONCE((CMOS_READ(RTC_VALID) & 0x40) != 0)) {
+- spin_unlock_irqrestore(&rtc_lock, flags);
+- memset(time, 0xff, sizeof(*time));
+- return 0;
++ if (iter_count > 10) {
++ memset(time, 0, sizeof(*time));
++ return -EIO;
+ }
++ iter_count++;
++
++ spin_lock_irqsave(&rtc_lock, flags);
+
+ /*
+ * Check whether there is an update in progress during which the
+@@ -104,7 +130,7 @@ again:
time->tm_year += real_year - 72;
#endif
@@ -102539,6 +150592,54 @@ index dcfaf09946ee3..2065842f775d6 100644
time->tm_year += (century - 19) * 100;
/*
+@@ -116,10 +142,21 @@ again:
+
+ time->tm_mon--;
+
+- return RTC_24H;
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mc146818_get_time);
+
++/* AMD systems don't allow access to AltCentury with DV1 */
++static bool apply_amd_register_a_behavior(void)
++{
++#ifdef CONFIG_X86
++ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
++ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
++ return true;
++#endif
++ return false;
++}
++
+ /* Set the current date and time in the real time clock. */
+ int mc146818_set_time(struct rtc_time *time)
+ {
+@@ -176,8 +213,10 @@ int mc146818_set_time(struct rtc_time *time)
+ if (yrs >= 100)
+ yrs -= 100;
+
+- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+- || RTC_ALWAYS_BCD) {
++ spin_lock_irqsave(&rtc_lock, flags);
++ save_control = CMOS_READ(RTC_CONTROL);
++ spin_unlock_irqrestore(&rtc_lock, flags);
++ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+@@ -191,7 +230,10 @@ int mc146818_set_time(struct rtc_time *time)
+ save_control = CMOS_READ(RTC_CONTROL);
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
++ if (apply_amd_register_a_behavior())
++ CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
++ else
++ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ #ifdef CONFIG_MACH_DECSTATION
+ CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c
index bad7792b6ca58..0d515b3df5710 100644
--- a/drivers/rtc/rtc-mcp795.c
@@ -102589,6 +150690,44 @@ index 0f58cac81d8c0..7473e6c8a183b 100644
};
module_spi_driver(pcf2123_driver);
+diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
+index 56c58b055dfff..43f8011070952 100644
+--- a/drivers/rtc/rtc-pcf2127.c
++++ b/drivers/rtc/rtc-pcf2127.c
+@@ -374,7 +374,8 @@ static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
+ static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+ {
+ struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+- unsigned int buf[5], ctrl2;
++ u8 buf[5];
++ unsigned int ctrl2;
+ int ret;
+
+ ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
+diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
+index e38ee88483855..bad6a5d9c6839 100644
+--- a/drivers/rtc/rtc-pl031.c
++++ b/drivers/rtc/rtc-pl031.c
+@@ -350,9 +350,6 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
+ }
+ }
+
+- if (!adev->irq[0])
+- clear_bit(RTC_FEATURE_ALARM, ldata->rtc->features);
+-
+ device_init_wakeup(&adev->dev, true);
+ ldata->rtc = devm_rtc_allocate_device(&adev->dev);
+ if (IS_ERR(ldata->rtc)) {
+@@ -360,6 +357,9 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
+ goto out;
+ }
+
++ if (!adev->irq[0])
++ clear_bit(RTC_FEATURE_ALARM, ldata->rtc->features);
++
+ ldata->rtc->ops = ops;
+ ldata->rtc->range_min = vendor->range_min;
+ ldata->rtc->range_max = vendor->range_max;
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index d2f1d8f754bf3..cf8119b6d3204 100644
--- a/drivers/rtc/rtc-pxa.c
@@ -102622,6 +150761,257 @@ index d63102d5cb1e4..1b62ed2f14594 100644
ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS |
FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8));
+diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
+index adec1b14a8deb..c551ebf0ac00f 100644
+--- a/drivers/rtc/rtc-sun6i.c
++++ b/drivers/rtc/rtc-sun6i.c
+@@ -138,7 +138,7 @@ struct sun6i_rtc_dev {
+ const struct sun6i_rtc_clk_data *data;
+ void __iomem *base;
+ int irq;
+- unsigned long alarm;
++ time64_t alarm;
+
+ struct clk_hw hw;
+ struct clk_hw *int_osc;
+@@ -510,10 +510,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
+ struct rtc_time *alrm_tm = &wkalrm->time;
+ struct rtc_time tm_now;
+- unsigned long time_now = 0;
+- unsigned long time_set = 0;
+- unsigned long time_gap = 0;
+- int ret = 0;
++ time64_t time_now, time_set;
++ int ret;
+
+ ret = sun6i_rtc_gettime(dev, &tm_now);
+ if (ret < 0) {
+@@ -528,9 +526,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ return -EINVAL;
+ }
+
+- time_gap = time_set - time_now;
+-
+- if (time_gap > U32_MAX) {
++ if ((time_set - time_now) > U32_MAX) {
+ dev_err(dev, "Date too far in the future\n");
+ return -EINVAL;
+ }
+@@ -539,7 +535,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ writel(0, chip->base + SUN6I_ALRM_COUNTER);
+ usleep_range(100, 300);
+
+- writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
++ writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
+ chip->alarm = time_set;
+
+ sun6i_rtc_setaie(wkalrm->enabled, chip);
+diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
+index 2018614f258f6..6eaa9321c0741 100644
+--- a/drivers/rtc/rtc-wm8350.c
++++ b/drivers/rtc/rtc-wm8350.c
+@@ -432,14 +432,21 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
+ wm8350_rtc_update_handler, 0,
+ "RTC Seconds", wm8350);
++ if (ret)
++ return ret;
++
+ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+
+- wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
+ wm8350_rtc_alarm_handler, 0,
+ "RTC Alarm", wm8350);
++ if (ret) {
++ wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
++ return ret;
++ }
+
+ return 0;
+ }
+diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
+index e34c6cc61983b..8240b804ef847 100644
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -1422,6 +1422,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
+ if (!cqr->lpm)
+ cqr->lpm = dasd_path_get_opm(device);
+ }
++ /*
++ * remember the amount of formatted tracks to prevent double format on
++ * ESE devices
++ */
++ if (cqr->block)
++ cqr->trkcount = atomic_read(&cqr->block->trkcount);
++
+ if (cqr->cpmode == 1) {
+ rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
+ (long) cqr, cqr->lpm);
+@@ -1639,6 +1646,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ unsigned long now;
+ int nrf_suppressed = 0;
+ int fp_suppressed = 0;
++ struct request *req;
+ u8 *sense = NULL;
+ int expires;
+
+@@ -1739,7 +1747,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ }
+
+ if (dasd_ese_needs_format(cqr->block, irb)) {
+- if (rq_data_dir((struct request *)cqr->callback_data) == READ) {
++ req = dasd_get_callback_data(cqr);
++ if (!req) {
++ cqr->status = DASD_CQR_ERROR;
++ return;
++ }
++ if (rq_data_dir(req) == READ) {
+ device->discipline->ese_read(cqr, irb);
+ cqr->status = DASD_CQR_SUCCESS;
+ cqr->stopclk = now;
+@@ -2762,8 +2775,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
+ * complete a request partially.
+ */
+ if (proc_bytes) {
+- blk_update_request(req, BLK_STS_OK,
+- blk_rq_bytes(req) - proc_bytes);
++ blk_update_request(req, BLK_STS_OK, proc_bytes);
+ blk_mq_requeue_request(req, true);
+ } else if (likely(!blk_should_fake_timeout(req->q))) {
+ blk_mq_complete_request(req);
+diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
+index 460e0f1cca533..ff7b7d470e96f 100644
+--- a/drivers/s390/block/dasd_eckd.c
++++ b/drivers/s390/block/dasd_eckd.c
+@@ -3095,13 +3095,24 @@ static int dasd_eckd_format_device(struct dasd_device *base,
+ }
+
+ static bool test_and_set_format_track(struct dasd_format_entry *to_format,
+- struct dasd_block *block)
++ struct dasd_ccw_req *cqr)
+ {
++ struct dasd_block *block = cqr->block;
+ struct dasd_format_entry *format;
+ unsigned long flags;
+ bool rc = false;
+
+ spin_lock_irqsave(&block->format_lock, flags);
++ if (cqr->trkcount != atomic_read(&block->trkcount)) {
++ /*
++ * The number of formatted tracks has changed after request
++ * start and we can not tell if the current track was involved.
++ * To avoid data corruption treat it as if the current track is
++ * involved
++ */
++ rc = true;
++ goto out;
++ }
+ list_for_each_entry(format, &block->format_list, list) {
+ if (format->track == to_format->track) {
+ rc = true;
+@@ -3121,6 +3132,7 @@ static void clear_format_track(struct dasd_format_entry *format,
+ unsigned long flags;
+
+ spin_lock_irqsave(&block->format_lock, flags);
++ atomic_inc(&block->trkcount);
+ list_del_init(&format->list);
+ spin_unlock_irqrestore(&block->format_lock, flags);
+ }
+@@ -3157,7 +3169,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
+ sector_t curr_trk;
+ int rc;
+
+- req = cqr->callback_data;
++ req = dasd_get_callback_data(cqr);
+ block = cqr->block;
+ base = block->base;
+ private = base->private;
+@@ -3182,8 +3194,11 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
+ }
+ format->track = curr_trk;
+ /* test if track is already in formatting by another thread */
+- if (test_and_set_format_track(format, block))
++ if (test_and_set_format_track(format, cqr)) {
++ /* this is no real error so do not count down retries */
++ cqr->retries++;
+ return ERR_PTR(-EEXIST);
++ }
+
+ fdata.start_unit = curr_trk;
+ fdata.stop_unit = curr_trk;
+@@ -3282,12 +3297,11 @@ static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb)
+ cqr->proc_bytes = blk_count * blksize;
+ return 0;
+ }
+- if (dst && !skip_block) {
+- dst += off;
++ if (dst && !skip_block)
+ memset(dst, 0, blksize);
+- } else {
++ else
+ skip_block--;
+- }
++ dst += blksize;
+ blk_count++;
+ }
+ }
+diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
+index fa966e0db6ca9..3a6f3af240fa7 100644
+--- a/drivers/s390/block/dasd_genhd.c
++++ b/drivers/s390/block/dasd_genhd.c
+@@ -14,6 +14,7 @@
+ #define KMSG_COMPONENT "dasd"
+
+ #include <linux/interrupt.h>
++#include <linux/major.h>
+ #include <linux/fs.h>
+ #include <linux/blkpg.h>
+
+diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
+index 155428bfed8ac..d94ae067f085e 100644
+--- a/drivers/s390/block/dasd_int.h
++++ b/drivers/s390/block/dasd_int.h
+@@ -188,6 +188,7 @@ struct dasd_ccw_req {
+ void (*callback)(struct dasd_ccw_req *, void *data);
+ void *callback_data;
+ unsigned int proc_bytes; /* bytes for partial completion */
++ unsigned int trkcount; /* count formatted tracks */
+ };
+
+ /*
+@@ -611,6 +612,7 @@ struct dasd_block {
+
+ struct list_head format_list;
+ spinlock_t format_lock;
++ atomic_t trkcount;
+ };
+
+ struct dasd_attention_data {
+@@ -757,6 +759,18 @@ dasd_check_blocksize(int bsize)
+ return 0;
+ }
+
++/*
++ * return the callback data of the original request in case there are
++ * ERP requests build on top of it
++ */
++static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr)
++{
++ while (cqr->refers)
++ cqr = cqr->refers;
++
++ return cqr->callback_data;
++}
++
+ /* externals in dasd.c */
+ #define DASD_PROFILE_OFF 0
+ #define DASD_PROFILE_ON 1
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 1f5fab617b679..f7e75d9fedf61 100644
--- a/drivers/s390/char/tape_std.c
@@ -102713,6 +151103,85 @@ index 9ea48bf0ee40d..032bf7b282bab 100644
if (aq->queue_count > 0)
mod_timer(&aq->timeout,
jiffies + aq->request_timeout);
+diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
+index f0436f555c62a..be03cb123ef48 100644
+--- a/drivers/s390/net/ctcm_mpc.c
++++ b/drivers/s390/net/ctcm_mpc.c
+@@ -626,8 +626,6 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
+ ctcm_clear_busy_do(dev);
+ }
+
+- kfree(mpcginfo);
+-
+ return;
+
+ }
+@@ -1192,10 +1190,10 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
+ CTCM_FUNTAIL, dev->name);
+ priv->stats.rx_dropped++;
+ /* mpcginfo only used for non-data transfers */
+- kfree(mpcginfo);
+ if (do_debug_data)
+ ctcmpc_dump_skb(pskb, -8);
+ }
++ kfree(mpcginfo);
+ }
+ done:
+
+@@ -1977,7 +1975,6 @@ static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
+ }
+ break;
+ }
+- kfree(mpcginfo);
+
+ CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+ __func__, ch->id, grp->outstanding_xid2,
+@@ -2038,7 +2035,6 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
+ mpc_validate_xid(mpcginfo);
+ break;
+ }
+- kfree(mpcginfo);
+ return;
+ }
+
+diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
+index ded1930a00b2d..e3813a7aa5e68 100644
+--- a/drivers/s390/net/ctcm_sysfs.c
++++ b/drivers/s390/net/ctcm_sysfs.c
+@@ -39,11 +39,12 @@ static ssize_t ctcm_buffer_write(struct device *dev,
+ struct ctcm_priv *priv = dev_get_drvdata(dev);
+ int rc;
+
+- ndev = priv->channel[CTCM_READ]->netdev;
+- if (!(priv && priv->channel[CTCM_READ] && ndev)) {
++ if (!(priv && priv->channel[CTCM_READ] &&
++ priv->channel[CTCM_READ]->netdev)) {
+ CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
+ return -ENODEV;
+ }
++ ndev = priv->channel[CTCM_READ]->netdev;
+
+ rc = kstrtouint(buf, 0, &bs1);
+ if (rc)
+diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
+index 440219bcaa2be..06a322bdced6d 100644
+--- a/drivers/s390/net/lcs.c
++++ b/drivers/s390/net/lcs.c
+@@ -1735,10 +1735,11 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
+ lcs_schedule_recovery(card);
+ break;
+ case LCS_CMD_STOPLAN:
+- pr_warn("Stoplan for %s initiated by LGW\n",
+- card->dev->name);
+- if (card->dev)
++ if (card->dev) {
++ pr_warn("Stoplan for %s initiated by LGW\n",
++ card->dev->name);
+ netif_carrier_off(card->dev);
++ }
+ break;
+ default:
+ LCS_DBF_TEXT(5, trace, "noLGWcmd");
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index d24cafe02708f..511bf8e0a436c 100644
--- a/drivers/s390/scsi/zfcp_fc.c
@@ -102766,6 +151235,145 @@ index ffb3919675734..97be0765cb9bd 100644
AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
v->err_code);
+diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
+index b13b5c85f3de0..75a5a4765f425 100644
+--- a/drivers/scsi/aha152x.c
++++ b/drivers/scsi/aha152x.c
+@@ -3370,13 +3370,11 @@ static int __init aha152x_setup(char *str)
+ setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
+ setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
+ setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
+- if (ints[0] > 8) { /*}*/
++ if (ints[0] > 8)
+ printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
+ "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
+- } else {
++ else
+ setup_count++;
+- return 0;
+- }
+
+ return 1;
+ }
+diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
+index 5ae1e3f789101..e049cdb3c286c 100644
+--- a/drivers/scsi/bfa/bfad_attr.c
++++ b/drivers/scsi/bfa/bfad_attr.c
+@@ -711,7 +711,7 @@ bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
+ char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+
+ bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
+- return snprintf(buf, PAGE_SIZE, "%s\n", serial_num);
++ return sysfs_emit(buf, "%s\n", serial_num);
+ }
+
+ static ssize_t
+@@ -725,7 +725,7 @@ bfad_im_model_show(struct device *dev, struct device_attribute *attr,
+ char model[BFA_ADAPTER_MODEL_NAME_LEN];
+
+ bfa_get_adapter_model(&bfad->bfa, model);
+- return snprintf(buf, PAGE_SIZE, "%s\n", model);
++ return sysfs_emit(buf, "%s\n", model);
+ }
+
+ static ssize_t
+@@ -805,7 +805,7 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Invalid Model");
+
+- return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
++ return sysfs_emit(buf, "%s\n", model_descr);
+ }
+
+ static ssize_t
+@@ -819,7 +819,7 @@ bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
+ u64 nwwn;
+
+ nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
+- return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn));
++ return sysfs_emit(buf, "0x%llx\n", cpu_to_be64(nwwn));
+ }
+
+ static ssize_t
+@@ -836,7 +836,7 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
+ bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+ strlcpy(symname, port_attr.port_cfg.sym_name.symname,
+ BFA_SYMNAME_MAXLEN);
+- return snprintf(buf, PAGE_SIZE, "%s\n", symname);
++ return sysfs_emit(buf, "%s\n", symname);
+ }
+
+ static ssize_t
+@@ -850,14 +850,14 @@ bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
+ char hw_ver[BFA_VERSION_LEN];
+
+ bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
+- return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver);
++ return sysfs_emit(buf, "%s\n", hw_ver);
+ }
+
+ static ssize_t
+ bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
++ return sysfs_emit(buf, "%s\n", BFAD_DRIVER_VERSION);
+ }
+
+ static ssize_t
+@@ -871,7 +871,7 @@ bfad_im_optionrom_version_show(struct device *dev,
+ char optrom_ver[BFA_VERSION_LEN];
+
+ bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
+- return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver);
++ return sysfs_emit(buf, "%s\n", optrom_ver);
+ }
+
+ static ssize_t
+@@ -885,7 +885,7 @@ bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
+ char fw_ver[BFA_VERSION_LEN];
+
+ bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
+- return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver);
++ return sysfs_emit(buf, "%s\n", fw_ver);
+ }
+
+ static ssize_t
+@@ -897,7 +897,7 @@ bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
+ (struct bfad_im_port_s *) shost->hostdata[0];
+ struct bfad_s *bfad = im_port->bfad;
+
+- return snprintf(buf, PAGE_SIZE, "%d\n",
++ return sysfs_emit(buf, "%d\n",
+ bfa_get_nports(&bfad->bfa));
+ }
+
+@@ -905,7 +905,7 @@ static ssize_t
+ bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
++ return sysfs_emit(buf, "%s\n", BFAD_DRIVER_NAME);
+ }
+
+ static ssize_t
+@@ -924,14 +924,14 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
+ rports = kcalloc(nrports, sizeof(struct bfa_rport_qualifier_s),
+ GFP_ATOMIC);
+ if (rports == NULL)
+- return snprintf(buf, PAGE_SIZE, "Failed\n");
++ return sysfs_emit(buf, "Failed\n");
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ kfree(rports);
+
+- return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
++ return sysfs_emit(buf, "%d\n", nrports);
+ }
+
+ static DEVICE_ATTR(serial_number, S_IRUGO,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 8863a74e6c57d..e2586472ecad4 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -102890,6 +151498,32 @@ index 8863a74e6c57d..e2586472ecad4 100644
bnx2fc_ulp_stop(hba);
/* unregister cnic device */
if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
+diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
+index 5521469ce678b..e16327a4b4c96 100644
+--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
++++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
+@@ -1977,7 +1977,7 @@ static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
+ if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
+ break;
+
+- if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) {
++ if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
+ if (nopin->op_code == ISCSI_OP_NOOP_IN &&
+ nopin->itt == (u16) RESERVED_ITT) {
+ printk(KERN_ALERT "bnx2i: Unsolicited "
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 1b5f3e143f071..2e5241d12dc3a 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1721,7 +1721,7 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
+ struct iscsi_conn *conn = ep->conn->cls_conn->dd_data;
+
+ /* Must suspend all rx queue activity for this ep */
+- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++ set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
+ }
+ /* CONN_DISCONNECT timeout may or may not be an issue depending
+ * on what transcribed in TCP layer, different targets behave
diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c
index dc98f51f466fb..d5ac938970232 100644
--- a/drivers/scsi/csiostor/csio_lnode.c
@@ -102903,6 +151537,25 @@ index dc98f51f466fb..d5ac938970232 100644
retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
if (retval != FW_SUCCESS) {
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index 8c7d4dda4cf29..4365d52c6430e 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -1634,11 +1634,11 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, conn 0x%p.\n", csk, conn);
+
+- if (unlikely(!conn || conn->suspend_rx)) {
++ if (unlikely(!conn || test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+- "csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n",
++ "csk 0x%p, conn 0x%p, id %d, conn flags 0x%lx!\n",
+ csk, conn, conn ? conn->id : 0xFF,
+- conn ? conn->suspend_rx : 0xFF);
++ conn ? conn->flags : 0xFF);
+ return;
+ }
+
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 24c7cefb0b78a..1c79e6c271630 100644
--- a/drivers/scsi/dc395x.c
@@ -102915,6 +151568,21 @@ index 24c7cefb0b78a..1c79e6c271630 100644
goto fail;
}
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index 37d06f993b761..1d9be771f3ee0 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -1172,9 +1172,8 @@ static blk_status_t alua_prep_fn(struct scsi_device *sdev, struct request *req)
+ case SCSI_ACCESS_STATE_OPTIMAL:
+ case SCSI_ACCESS_STATE_ACTIVE:
+ case SCSI_ACCESS_STATE_LBA:
+- return BLK_STS_OK;
+ case SCSI_ACCESS_STATE_TRANSITIONING:
+- return BLK_STS_AGAIN;
++ return BLK_STS_OK;
+ default:
+ req->rq_flags |= RQF_QUIET;
+ return BLK_STS_IOERR;
diff --git a/drivers/scsi/elx/libefc/efc_els.c b/drivers/scsi/elx/libefc/efc_els.c
index 24db0accb256e..5f690378fe9a9 100644
--- a/drivers/scsi/elx/libefc/efc_els.c
@@ -102959,6 +151627,159 @@ index 24db0accb256e..5f690378fe9a9 100644
return els;
}
+diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
+index f8afbfb468dca..d084a7db3925e 100644
+--- a/drivers/scsi/fnic/fnic_scsi.c
++++ b/drivers/scsi/fnic/fnic_scsi.c
+@@ -604,7 +604,7 @@ out:
+
+ FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
+ tag, sc, io_req, sg_count, cmd_trace,
+- (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
++ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
+ /* if only we issued IO, will we have the io lock */
+ if (io_lock_acquired)
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 3ab669dc806f6..1f5e0688c0c84 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -527,7 +527,7 @@ MODULE_PARM_DESC(intr_conv, "interrupt converge enable (0-1)");
+
+ /* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
+ static int prot_mask;
+-module_param(prot_mask, int, 0);
++module_param(prot_mask, int, 0444);
+ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 ");
+
+ static void debugfs_work_handler_v3_hw(struct work_struct *work);
+@@ -2392,17 +2392,25 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
+ return IRQ_WAKE_THREAD;
+ }
+
++static void hisi_sas_v3_free_vectors(void *data)
++{
++ struct pci_dev *pdev = data;
++
++ pci_free_irq_vectors(pdev);
++}
++
+ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
+ {
+ int vectors;
+ int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
+ struct Scsi_Host *shost = hisi_hba->shost;
++ struct pci_dev *pdev = hisi_hba->pci_dev;
+ struct irq_affinity desc = {
+ .pre_vectors = BASE_VECTORS_V3_HW,
+ };
+
+ min_msi = MIN_AFFINE_VECTORS_V3_HW;
+- vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
++ vectors = pci_alloc_irq_vectors_affinity(pdev,
+ min_msi, max_msi,
+ PCI_IRQ_MSI |
+ PCI_IRQ_AFFINITY,
+@@ -2414,6 +2422,7 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
+ hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
+ shost->nr_hw_queues = hisi_hba->cq_nvecs;
+
++ devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev);
+ return 0;
+ }
+
+@@ -3959,6 +3968,54 @@ static const struct file_operations debugfs_bist_phy_v3_hw_fops = {
+ .owner = THIS_MODULE,
+ };
+
++static ssize_t debugfs_bist_cnt_v3_hw_write(struct file *filp,
++ const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct seq_file *m = filp->private_data;
++ struct hisi_hba *hisi_hba = m->private;
++ unsigned int cnt;
++ int val;
++
++ if (hisi_hba->debugfs_bist_enable)
++ return -EPERM;
++
++ val = kstrtouint_from_user(buf, count, 0, &cnt);
++ if (val)
++ return val;
++
++ if (cnt)
++ return -EINVAL;
++
++ hisi_hba->debugfs_bist_cnt = 0;
++ return count;
++}
++
++static int debugfs_bist_cnt_v3_hw_show(struct seq_file *s, void *p)
++{
++ struct hisi_hba *hisi_hba = s->private;
++
++ seq_printf(s, "%u\n", hisi_hba->debugfs_bist_cnt);
++
++ return 0;
++}
++
++static int debugfs_bist_cnt_v3_hw_open(struct inode *inode,
++ struct file *filp)
++{
++ return single_open(filp, debugfs_bist_cnt_v3_hw_show,
++ inode->i_private);
++}
++
++static const struct file_operations debugfs_bist_cnt_v3_hw_ops = {
++ .open = debugfs_bist_cnt_v3_hw_open,
++ .read = seq_read,
++ .write = debugfs_bist_cnt_v3_hw_write,
++ .llseek = seq_lseek,
++ .release = single_release,
++ .owner = THIS_MODULE,
++};
++
+ static const struct {
+ int value;
+ char *name;
+@@ -4596,8 +4653,8 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba)
+ debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry,
+ hisi_hba, &debugfs_bist_phy_v3_hw_fops);
+
+- debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry,
+- &hisi_hba->debugfs_bist_cnt);
++ debugfs_create_file("cnt", 0600, hisi_hba->debugfs_bist_dentry,
++ hisi_hba, &debugfs_bist_cnt_v3_hw_ops);
+
+ debugfs_create_file("loopback_mode", 0600,
+ hisi_hba->debugfs_bist_dentry,
+@@ -4763,7 +4820,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ dev_err(dev, "%d hw queues\n", shost->nr_hw_queues);
+ rc = scsi_add_host(shost, dev);
+ if (rc)
+- goto err_out_free_irq_vectors;
++ goto err_out_debugfs;
+
+ rc = sas_register_ha(sha);
+ if (rc)
+@@ -4792,8 +4849,6 @@ err_out_hw_init:
+ sas_unregister_ha(sha);
+ err_out_register_ha:
+ scsi_remove_host(shost);
+-err_out_free_irq_vectors:
+- pci_free_irq_vectors(pdev);
+ err_out_debugfs:
+ debugfs_exit_v3_hw(hisi_hba);
+ err_out_ha:
+@@ -4821,7 +4876,6 @@ hisi_sas_v3_destroy_irqs(struct pci_dev *pdev, struct hisi_hba *hisi_hba)
+
+ devm_free_irq(&pdev->dev, pci_irq_vector(pdev, nr), cq);
+ }
+- pci_free_irq_vectors(pdev);
+ }
+
+ static void hisi_sas_v3_remove(struct pci_dev *pdev)
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 24b72ee4246fb..0165dad803001 100644
--- a/drivers/scsi/hosts.c
@@ -102971,11 +151792,120 @@ index 24b72ee4246fb..0165dad803001 100644
INIT_LIST_HEAD(&shost->eh_cmd_q);
INIT_LIST_HEAD(&shost->starved_list);
init_waitqueue_head(&shost->host_wait);
+diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+index 10b6c6daaacda..d43bb18f58fd5 100644
+--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
++++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+@@ -36,7 +36,7 @@
+
+ #define IBMVSCSIS_VERSION "v0.2"
+
+-#define INITIAL_SRP_LIMIT 800
++#define INITIAL_SRP_LIMIT 1024
+ #define DEFAULT_MAX_SECTORS 256
+ #define MAX_TXU 1024 * 1024
+
+diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
+index 841000445b9a1..aa223db4cf53c 100644
+--- a/drivers/scsi/libfc/fc_exch.c
++++ b/drivers/scsi/libfc/fc_exch.c
+@@ -1701,6 +1701,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
+ if (cancel_delayed_work_sync(&ep->timeout_work)) {
+ FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n");
+ fc_exch_release(ep); /* release from pending timer hold */
++ return;
+ }
+
+ spin_lock_bh(&ep->ex_lock);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
-index 5bc91d34df634..cbc263ec9d661 100644
+index 5bc91d34df634..0f2c7098f9d6e 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
-@@ -3101,6 +3101,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+@@ -678,7 +678,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ struct iscsi_task *task;
+ itt_t itt;
+
+- if (session->state == ISCSI_STATE_TERMINATE)
++ if (session->state == ISCSI_STATE_TERMINATE ||
++ !test_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags))
+ return NULL;
+
+ if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) {
+@@ -1392,8 +1393,8 @@ static bool iscsi_set_conn_failed(struct iscsi_conn *conn)
+ if (conn->stop_stage == 0)
+ session->state = ISCSI_STATE_FAILED;
+
+- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++ set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
++ set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
+ return true;
+ }
+
+@@ -1454,7 +1455,7 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
+ * Do this after dropping the extra ref because if this was a requeue
+ * it's removed from that list and cleanup_queued_task would miss it.
+ */
+- if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
++ if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
+ /*
+ * Save the task and ref in case we weren't cleaning up this
+ * task and get woken up again.
+@@ -1532,7 +1533,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ int rc = 0;
+
+ spin_lock_bh(&conn->session->frwd_lock);
+- if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
++ if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
+ ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
+ spin_unlock_bh(&conn->session->frwd_lock);
+ return -ENODATA;
+@@ -1746,7 +1747,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
+ goto fault;
+ }
+
+- if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
++ if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
+ reason = FAILURE_SESSION_IN_RECOVERY;
+ sc->result = DID_REQUEUE << 16;
+ goto fault;
+@@ -1935,7 +1936,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
+ void iscsi_suspend_queue(struct iscsi_conn *conn)
+ {
+ spin_lock_bh(&conn->session->frwd_lock);
+- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++ set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
+ spin_unlock_bh(&conn->session->frwd_lock);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
+@@ -1953,7 +1954,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn)
+ struct Scsi_Host *shost = conn->session->host;
+ struct iscsi_host *ihost = shost_priv(shost);
+
+- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++ set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
+ if (ihost->workq)
+ flush_workqueue(ihost->workq);
+ }
+@@ -1961,7 +1962,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+
+ static void iscsi_start_tx(struct iscsi_conn *conn)
+ {
+- clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++ clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
+ iscsi_conn_queue_work(conn);
+ }
+
+@@ -2214,6 +2215,8 @@ void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active)
+ iscsi_suspend_tx(conn);
+
+ spin_lock_bh(&session->frwd_lock);
++ clear_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags);
++
+ if (!is_active) {
+ /*
+ * if logout timed out before userspace could even send a PDU
+@@ -3101,6 +3104,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
@@ -102984,7 +151914,7 @@ index 5bc91d34df634..cbc263ec9d661 100644
del_timer_sync(&conn->transport_timer);
-@@ -3122,8 +3124,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+@@ -3122,8 +3127,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
spin_lock_bh(&session->frwd_lock);
free_pages((unsigned long) conn->data,
get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
@@ -102993,7 +151923,7 @@ index 5bc91d34df634..cbc263ec9d661 100644
/* regular RX path uses back_lock */
spin_lock_bh(&session->back_lock);
kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
-@@ -3135,6 +3135,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+@@ -3135,6 +3138,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
mutex_unlock(&session->eh_mutex);
iscsi_destroy_conn(cls_conn);
@@ -103002,6 +151932,52 @@ index 5bc91d34df634..cbc263ec9d661 100644
}
EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
+@@ -3310,6 +3315,8 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ spin_lock_bh(&session->frwd_lock);
+ if (is_leading)
+ session->leadconn = conn;
++
++ set_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags);
+ spin_unlock_bh(&session->frwd_lock);
+
+ /*
+@@ -3322,8 +3329,8 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ /*
+ * Unblock xmitworker(), Login Phase will pass through.
+ */
+- clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+- clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++ clear_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
++ clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_bind);
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 2e9ffe3d1a55e..883005757ddb8 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -927,7 +927,7 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+ */
+ conn->last_recv = jiffies;
+
+- if (unlikely(conn->suspend_rx)) {
++ if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
+ ISCSI_DBG_TCP(conn, "Rx suspended!\n");
+ *status = ISCSI_TCP_SUSPENDED;
+ return 0;
+diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
+index a315715b36227..7e0cde710fc3c 100644
+--- a/drivers/scsi/libsas/sas_ata.c
++++ b/drivers/scsi/libsas/sas_ata.c
+@@ -197,7 +197,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
+ task->total_xfer_len = qc->nbytes;
+ task->num_scatter = qc->n_elem;
+ task->data_dir = qc->dma_dir;
+- } else if (qc->tf.protocol == ATA_PROT_NODATA) {
++ } else if (!ata_is_data(qc->tf.protocol)) {
+ task->data_dir = DMA_NONE;
+ } else {
+ for_each_sg(qc->sg, sg, qc->n_elem, si)
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index befeb7c342903..1044832b60549 100644
--- a/drivers/scsi/lpfc/lpfc.h
@@ -103603,7 +152579,7 @@ index 7195ca0275f93..3bb7c2aa949f7 100644
if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) {
/* Already registered with backend, trigger rescan */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
-index 195169badb372..3eebcae52784d 100644
+index 195169badb372..16246526e4c1e 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2055,7 +2055,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
@@ -103660,6 +152636,15 @@ index 195169badb372..3eebcae52784d 100644
return;
out_free_dmabuf:
+@@ -15097,6 +15105,8 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
+ psli->sli_flag &= ~LPFC_SLI_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
++ /* Init cpu_map array */
++ lpfc_cpu_map_array_init(phba);
+ /* Configure and enable interrupt */
+ intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
+ if (intr_mode == LPFC_INTR_ERROR) {
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 27263f02ab9f6..fdf5e777bf113 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -104045,6 +153030,45 @@ index 026a1196a54d5..68d8e55c1205c 100644
}
spin_unlock_irqrestore(&pring->ring_lock, iflags);
}
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 7af2c23652b01..650210d2abb4d 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -2558,6 +2558,9 @@ struct megasas_instance_template {
+ #define MEGASAS_IS_LOGICAL(sdev) \
+ ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1)
+
++#define MEGASAS_IS_LUN_VALID(sdev) \
++ (((sdev)->lun == 0) ? 1 : 0)
++
+ #define MEGASAS_DEV_INDEX(scp) \
+ (((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
+ scp->device->id)
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 39d8754e63acf..bb3f78013a13b 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -2126,6 +2126,9 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
+ goto scan_target;
+ }
+ return -ENXIO;
++ } else if (!MEGASAS_IS_LUN_VALID(sdev)) {
++ sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
++ return -ENXIO;
+ }
+
+ scan_target:
+@@ -2156,6 +2159,10 @@ static void megasas_slave_destroy(struct scsi_device *sdev)
+ instance = megasas_lookup_instance(sdev->host->host_no);
+
+ if (MEGASAS_IS_LOGICAL(sdev)) {
++ if (!MEGASAS_IS_LUN_VALID(sdev)) {
++ sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
++ return;
++ }
+ ld_tgt_id = MEGASAS_TARGET_ID(sdev);
+ instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_DELETED;
+ if (megasas_dbg_lvl & LD_PD_DEBUG)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 26d0cf9353dd6..eb5ceb75a15ec 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -104090,11 +153114,15 @@ index 9787b53a2b598..2cc42432bd0c0 100644
#define MPI3MR_OP_REP_Q_SEG_SIZE 4096
#define MPI3MR_MAX_SEG_LIST_SIZE 4096
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
-index 4a8316c6bd41a..5af36c54cb596 100644
+index 4a8316c6bd41a..3ef6b6edef46d 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
-@@ -1278,7 +1278,7 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
- mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL;
+@@ -1275,10 +1275,10 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
+ MPI3MR_MAX_SEG_LIST_SIZE,
+ mrioc->req_qinfo[q_idx].q_segment_list,
+ mrioc->req_qinfo[q_idx].q_segment_list_dma);
+- mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL;
++ mrioc->req_qinfo[q_idx].q_segment_list = NULL;
}
} else
- size = mrioc->req_qinfo[q_idx].num_requests *
@@ -104111,8 +153139,21 @@ index 4a8316c6bd41a..5af36c54cb596 100644
op_reply_q->ci = 0;
op_reply_q->ephase = 1;
atomic_set(&op_reply_q->pend_ios, 0);
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
+index 3cae8803383b6..b2c650542bac5 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
+@@ -2204,6 +2204,8 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
+ scmd->result = DID_OK << 16;
+ goto out_success;
+ }
++
++ scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_count);
+ if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN &&
+ xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY ||
+ scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT ||
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
-index 27eb652b564f5..81dab9b82f79f 100644
+index 27eb652b564f5..c38e689432054 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -639,8 +639,8 @@ static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc)
@@ -104126,6 +153167,103 @@ index 27eb652b564f5..81dab9b82f79f 100644
init_completion(&ioc->scsih_cmds.done);
ioc->put_smid_default(ioc, smid);
dinitprintk(ioc, ioc_info(ioc,
+@@ -2011,9 +2011,10 @@ mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll)
+ enable_irq(reply_q->os_irq);
+ }
+ }
++
++ if (poll)
++ _base_process_reply_queue(reply_q);
+ }
+- if (poll)
+- _base_process_reply_queue(reply_q);
+ }
+
+ /**
+@@ -5736,14 +5737,13 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
+ */
+
+ static int
+-mpt3sas_check_same_4gb_region(long reply_pool_start_address, u32 pool_sz)
++mpt3sas_check_same_4gb_region(dma_addr_t start_address, u32 pool_sz)
+ {
+- long reply_pool_end_address;
++ dma_addr_t end_address;
+
+- reply_pool_end_address = reply_pool_start_address + pool_sz;
++ end_address = start_address + pool_sz - 1;
+
+- if (upper_32_bits(reply_pool_start_address) ==
+- upper_32_bits(reply_pool_end_address))
++ if (upper_32_bits(start_address) == upper_32_bits(end_address))
+ return 1;
+ else
+ return 0;
+@@ -5804,7 +5804,7 @@ _base_allocate_pcie_sgl_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz)
+ }
+
+ if (!mpt3sas_check_same_4gb_region(
+- (long)ioc->pcie_sg_lookup[i].pcie_sgl, sz)) {
++ ioc->pcie_sg_lookup[i].pcie_sgl_dma, sz)) {
+ ioc_err(ioc, "PCIE SGLs are not in same 4G !! pcie sgl (0x%p) dma = (0x%llx)\n",
+ ioc->pcie_sg_lookup[i].pcie_sgl,
+ (unsigned long long)
+@@ -5859,8 +5859,8 @@ _base_allocate_chain_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz)
+ GFP_KERNEL, &ctr->chain_buffer_dma);
+ if (!ctr->chain_buffer)
+ return -EAGAIN;
+- if (!mpt3sas_check_same_4gb_region((long)
+- ctr->chain_buffer, ioc->chain_segment_sz)) {
++ if (!mpt3sas_check_same_4gb_region(
++ ctr->chain_buffer_dma, ioc->chain_segment_sz)) {
+ ioc_err(ioc,
+ "Chain buffers are not in same 4G !!! Chain buff (0x%p) dma = (0x%llx)\n",
+ ctr->chain_buffer,
+@@ -5896,7 +5896,7 @@ _base_allocate_sense_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz)
+ GFP_KERNEL, &ioc->sense_dma);
+ if (!ioc->sense)
+ return -EAGAIN;
+- if (!mpt3sas_check_same_4gb_region((long)ioc->sense, sz)) {
++ if (!mpt3sas_check_same_4gb_region(ioc->sense_dma, sz)) {
+ dinitprintk(ioc, pr_err(
+ "Bad Sense Pool! sense (0x%p) sense_dma = (0x%llx)\n",
+ ioc->sense, (unsigned long long) ioc->sense_dma));
+@@ -5929,7 +5929,7 @@ _base_allocate_reply_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz)
+ &ioc->reply_dma);
+ if (!ioc->reply)
+ return -EAGAIN;
+- if (!mpt3sas_check_same_4gb_region((long)ioc->reply_free, sz)) {
++ if (!mpt3sas_check_same_4gb_region(ioc->reply_dma, sz)) {
+ dinitprintk(ioc, pr_err(
+ "Bad Reply Pool! Reply (0x%p) Reply dma = (0x%llx)\n",
+ ioc->reply, (unsigned long long) ioc->reply_dma));
+@@ -5964,7 +5964,7 @@ _base_allocate_reply_free_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz)
+ GFP_KERNEL, &ioc->reply_free_dma);
+ if (!ioc->reply_free)
+ return -EAGAIN;
+- if (!mpt3sas_check_same_4gb_region((long)ioc->reply_free, sz)) {
++ if (!mpt3sas_check_same_4gb_region(ioc->reply_free_dma, sz)) {
+ dinitprintk(ioc,
+ pr_err("Bad Reply Free Pool! Reply Free (0x%p) Reply Free dma = (0x%llx)\n",
+ ioc->reply_free, (unsigned long long) ioc->reply_free_dma));
+@@ -6003,7 +6003,7 @@ _base_allocate_reply_post_free_array(struct MPT3SAS_ADAPTER *ioc,
+ GFP_KERNEL, &ioc->reply_post_free_array_dma);
+ if (!ioc->reply_post_free_array)
+ return -EAGAIN;
+- if (!mpt3sas_check_same_4gb_region((long)ioc->reply_post_free_array,
++ if (!mpt3sas_check_same_4gb_region(ioc->reply_post_free_array_dma,
+ reply_post_free_array_sz)) {
+ dinitprintk(ioc, pr_err(
+ "Bad Reply Free Pool! Reply Free (0x%p) Reply Free dma = (0x%llx)\n",
+@@ -6068,7 +6068,7 @@ base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz)
+ * resources and set DMA mask to 32 and allocate.
+ */
+ if (!mpt3sas_check_same_4gb_region(
+- (long)ioc->reply_post[i].reply_post_free, sz)) {
++ ioc->reply_post[i].reply_post_free_dma, sz)) {
+ dinitprintk(ioc,
+ ioc_err(ioc, "bad Replypost free pool(0x%p)"
+ "reply_post_free_dma = (0x%llx)\n",
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index f87c0911f66ad..1b3a44ce65aae 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -104155,8 +153293,29 @@ index f87c0911f66ad..1b3a44ce65aae 100644
struct hba_port *port;
struct _sas_phy *phy;
struct list_head sas_port_list;
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
+index 0563078227de6..a8dd14c91efdb 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
+@@ -394,10 +394,13 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
+ retry_count++;
+ if (ioc->config_cmds.smid == smid)
+ mpt3sas_base_free_smid(ioc, smid);
+- if ((ioc->shost_recovery) || (ioc->config_cmds.status &
+- MPT3_CMD_RESET) || ioc->pci_error_recovery)
++ if (ioc->config_cmds.status & MPT3_CMD_RESET)
+ goto retry_config;
+- issue_host_reset = 1;
++ if (ioc->shost_recovery || ioc->pci_error_recovery) {
++ issue_host_reset = 0;
++ r = -EFAULT;
++ } else
++ issue_host_reset = 1;
+ goto free_mem;
+ }
+
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
-index ad1b6c2b37a74..c1f900c6ea003 100644
+index ad1b6c2b37a74..af275ac427954 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3869,7 +3869,7 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc,
@@ -104258,6 +153417,62 @@ index ad1b6c2b37a74..c1f900c6ea003 100644
sizeof(struct _sas_phy), GFP_KERNEL);
if (!ioc->sas_hba.phy) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
+@@ -10980,6 +11035,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
+ {
+ struct _sas_port *mpt3sas_port, *next;
+ unsigned long flags;
++ int port_id;
+
+ /* remove sibling ports attached to this expander */
+ list_for_each_entry_safe(mpt3sas_port, next,
+@@ -11000,6 +11056,8 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
+ mpt3sas_port->hba_port);
+ }
+
++ port_id = sas_expander->port->port_id;
++
+ mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
+ sas_expander->sas_address_parent, sas_expander->port);
+
+@@ -11007,7 +11065,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
+ "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
+ sas_expander->handle, (unsigned long long)
+ sas_expander->sas_address,
+- sas_expander->port->port_id);
++ port_id);
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ list_del(&sas_expander->list);
+diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
+index f18dd97035955..f6f8ca3c8c7f5 100644
+--- a/drivers/scsi/mvsas/mv_init.c
++++ b/drivers/scsi/mvsas/mv_init.c
+@@ -646,6 +646,7 @@ static struct pci_device_id mvs_pci_table[] = {
+ { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
+ { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
+ { PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
++ { PCI_VDEVICE(TTI, 0x2640), chip_6440 },
+ { PCI_VDEVICE(TTI, 0x2710), chip_9480 },
+ { PCI_VDEVICE(TTI, 0x2720), chip_9480 },
+ { PCI_VDEVICE(TTI, 0x2721), chip_9480 },
+@@ -696,7 +697,7 @@ static struct pci_driver mvs_pci_driver = {
+ static ssize_t driver_version_show(struct device *cdev,
+ struct device_attribute *attr, char *buffer)
+ {
+- return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION);
++ return sysfs_emit(buffer, "%s\n", DRV_VERSION);
+ }
+
+ static DEVICE_ATTR_RO(driver_version);
+@@ -744,7 +745,7 @@ static ssize_t interrupt_coalescing_store(struct device *cdev,
+ static ssize_t interrupt_coalescing_show(struct device *cdev,
+ struct device_attribute *attr, char *buffer)
+ {
+- return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing);
++ return sysfs_emit(buffer, "%d\n", interrupt_coalescing);
+ }
+
+ static DEVICE_ATTR_RW(interrupt_coalescing);
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index 07f274afd7e5e..a4d244ee4548c 100644
--- a/drivers/scsi/myrs.c
@@ -104273,7 +153488,7 @@ index 07f274afd7e5e..a4d244ee4548c 100644
cs->mmio_base = NULL;
}
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
-index 63690508313b7..5e6b23da4157c 100644
+index 63690508313b7..32fc450bf84b4 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1325,7 +1325,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
@@ -104287,7 +153502,72 @@ index 63690508313b7..5e6b23da4157c 100644
spin_lock_irqsave(&circularQ->iq_lock, flags);
rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
&pMessage);
-@@ -2693,7 +2695,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -1765,7 +1767,6 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+ }
+
+ task = sas_alloc_slow_task(GFP_ATOMIC);
+-
+ if (!task) {
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
+ return;
+@@ -1774,13 +1775,16 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+ task->task_done = pm8001_task_done;
+
+ res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+- if (res)
++ if (res) {
++ sas_free_task(task);
+ return;
++ }
+
+ ccb = &pm8001_ha->ccb_info[ccb_tag];
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
++ ccb->n_elem = 0;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+@@ -1791,8 +1795,10 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+ sizeof(task_abort), 0);
+- if (ret)
++ if (ret) {
++ sas_free_task(task);
+ pm8001_tag_free(pm8001_ha, ccb_tag);
++ }
+
+ }
+
+@@ -1842,6 +1848,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
++ ccb->n_elem = 0;
+ pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+ pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+@@ -1858,7 +1865,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
+
+ sata_cmd.tag = cpu_to_le32(ccb_tag);
+ sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+- sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
++ sata_cmd.ncqtag_atap_dir_m = cpu_to_le32((0x1 << 7) | (0x5 << 9));
+ memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+@@ -2419,7 +2426,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+ len = sizeof(struct pio_setup_fis);
+ pm8001_dbg(pm8001_ha, IO,
+ "PIO read len = %d\n", len);
+- } else if (t->ata_task.use_ncq) {
++ } else if (t->ata_task.use_ncq &&
++ t->data_dir != DMA_NONE) {
+ len = sizeof(struct set_dev_bits_fis);
+ pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
+ len);
+@@ -2693,7 +2701,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 tag = le32_to_cpu(psataPayload->tag);
u32 port_id = le32_to_cpu(psataPayload->port_id);
u32 dev_id = le32_to_cpu(psataPayload->device_id);
@@ -104295,7 +153575,7 @@ index 63690508313b7..5e6b23da4157c 100644
ccb = &pm8001_ha->ccb_info[tag];
-@@ -2733,8 +2734,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2733,8 +2740,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
@@ -104304,7 +153584,7 @@ index 63690508313b7..5e6b23da4157c 100644
break;
case IO_XFER_ERROR_BREAK:
pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
-@@ -2776,7 +2775,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2776,7 +2781,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_QUEUE_FULL;
@@ -104312,7 +153592,7 @@ index 63690508313b7..5e6b23da4157c 100644
return;
}
break;
-@@ -2862,20 +2860,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2862,20 +2866,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_OPEN_TO;
break;
}
@@ -104333,7 +153613,7 @@ index 63690508313b7..5e6b23da4157c 100644
}
/*See the comments for mpi_ssp_completion */
-@@ -3169,7 +3153,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -3169,7 +3159,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
* fw_control_context->usrAddr
*/
complete(pm8001_ha->nvmd_completion);
@@ -104342,6 +153622,93 @@ index 63690508313b7..5e6b23da4157c 100644
ccb->task = NULL;
ccb->ccb_tag = 0xFFFFFFFF;
pm8001_tag_free(pm8001_ha, tag);
+@@ -3726,12 +3716,11 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+ mb();
+
+ if (pm8001_dev->id & NCQ_ABORT_ALL_FLAG) {
+- pm8001_tag_free(pm8001_ha, tag);
+ sas_free_task(t);
+- /* clear the flag */
+- pm8001_dev->id &= 0xBFFFFFFF;
+- } else
++ pm8001_dev->id &= ~NCQ_ABORT_ALL_FLAG;
++ } else {
+ t->task_done(t);
++ }
+
+ return 0;
+ }
+@@ -4294,22 +4283,22 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ u32 opc = OPC_INB_SATA_HOST_OPSTART;
+ memset(&sata_cmd, 0, sizeof(sata_cmd));
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+- if (task->data_dir == DMA_NONE) {
++
++ if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
+ ATAP = 0x04; /* no data*/
+ pm8001_dbg(pm8001_ha, IO, "no data\n");
+ } else if (likely(!task->ata_task.device_control_reg_update)) {
+- if (task->ata_task.dma_xfer) {
++ if (task->ata_task.use_ncq &&
++ dev->sata_dev.class != ATA_DEV_ATAPI) {
++ ATAP = 0x07; /* FPDMA */
++ pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
++ } else if (task->ata_task.dma_xfer) {
+ ATAP = 0x06; /* DMA */
+ pm8001_dbg(pm8001_ha, IO, "DMA\n");
+ } else {
+ ATAP = 0x05; /* PIO*/
+ pm8001_dbg(pm8001_ha, IO, "PIO\n");
+ }
+- if (task->ata_task.use_ncq &&
+- dev->sata_dev.class != ATA_DEV_ATAPI) {
+- ATAP = 0x07; /* FPDMA */
+- pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
+- }
+ }
+ if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+ task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+@@ -4499,6 +4488,9 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
+ SAS_ADDR_SIZE);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
++ if (rc)
++ pm8001_tag_free(pm8001_ha, tag);
++
+ return rc;
+ }
+
+@@ -4649,7 +4641,7 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
+ memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8);
+ sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag);
+ if (pm8001_ha->chip_id != chip_8001)
+- sspTMCmd.ds_ads_m = 0x08;
++ sspTMCmd.ds_ads_m = cpu_to_le32(0x08);
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
+ sizeof(sspTMCmd), 0);
+@@ -4911,6 +4903,11 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
+ ccb->ccb_tag = tag;
+ rc = pm8001_chip_fw_flash_update_build(pm8001_ha, &flash_update_info,
+ tag);
++ if (rc) {
++ kfree(fw_control_context);
++ pm8001_tag_free(pm8001_ha, tag);
++ }
++
+ return rc;
+ }
+
+@@ -5015,6 +5012,9 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
+ payload.nds = cpu_to_le32(state);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
++ if (rc)
++ pm8001_tag_free(pm8001_ha, tag);
++
+ return rc;
+
+ }
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 47db7e0beae6f..a25a34535b7a4 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
@@ -104396,7 +153763,7 @@ index 47db7e0beae6f..a25a34535b7a4 100644
kfree(sha->sas_phy);
kfree(sha->sas_port);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
-index 32e60f0c3b148..491cecbbe1aa7 100644
+index 32e60f0c3b148..5fb08acbc0e5e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -753,8 +753,13 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
@@ -104413,6 +153780,18 @@ index 32e60f0c3b148..491cecbbe1aa7 100644
goto ex_err;
}
+@@ -826,10 +831,10 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
+
+ res = PM8001_CHIP_DISP->task_abort(pm8001_ha,
+ pm8001_dev, flag, task_tag, ccb_tag);
+-
+ if (res) {
+ del_timer(&task->slow_task->timer);
+ pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n");
++ pm8001_tag_free(pm8001_ha, ccb_tag);
+ goto ex_err;
+ }
+ wait_for_completion(&task->slow_task->completion);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 62d08b535a4b6..f40a41f450d9b 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
@@ -104444,10 +153823,212 @@ index 62d08b535a4b6..f40a41f450d9b 100644
#endif
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
-index 6ffe17b849ae8..3056f3615ab8a 100644
+index 6ffe17b849ae8..04746df26c6c9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
-@@ -2184,9 +2184,9 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -66,18 +66,16 @@ int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value)
+ }
+
+ static void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
+- const void *destination,
++ __le32 *destination,
+ u32 dw_count, u32 bus_base_number)
+ {
+ u32 index, value, offset;
+- u32 *destination1;
+- destination1 = (u32 *)destination;
+
+- for (index = 0; index < dw_count; index += 4, destination1++) {
++ for (index = 0; index < dw_count; index += 4, destination++) {
+ offset = (soffset + index);
+ if (offset < (64 * 1024)) {
+ value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
+- *destination1 = cpu_to_le32(value);
++ *destination = cpu_to_le32(value);
+ }
+ }
+ return;
+@@ -767,6 +765,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;
+
++ /* Enable higher IQs and OQs, 32 to 63, bit 16 */
++ if (pm8001_ha->max_q_num > 32)
++ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
++ 1 << 16;
+ /* Disable end to end CRC checking */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
+
+@@ -1028,6 +1030,13 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
+ if (0x0000 != gst_len_mpistate)
+ return -EBUSY;
+
++ /*
++ * As per controller datasheet, after successful MPI
++ * initialization minimum 500ms delay is required before
++ * issuing commands.
++ */
++ msleep(500);
++
+ return 0;
+ }
+
+@@ -1202,9 +1211,11 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
+ else
+ page_code = THERMAL_PAGE_CODE_8H;
+
+- payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) |
+- (THERMAL_ENABLE << 8) | page_code;
+- payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
++ payload.cfg_pg[0] =
++ cpu_to_le32((THERMAL_LOG_ENABLE << 9) |
++ (THERMAL_ENABLE << 8) | page_code);
++ payload.cfg_pg[1] =
++ cpu_to_le32((LTEMPHIL << 24) | (RTEMPHIL << 8));
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
+@@ -1244,43 +1255,41 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(tag);
+
+- SASConfigPage.pageCode = SAS_PROTOCOL_TIMER_CONFIG_PAGE;
+- SASConfigPage.MST_MSI = 3 << 15;
+- SASConfigPage.STP_SSP_MCT_TMO = (STP_MCT_TMO << 16) | SSP_MCT_TMO;
+- SASConfigPage.STP_FRM_TMO = (SAS_MAX_OPEN_TIME << 24) |
+- (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER;
+- SASConfigPage.STP_IDLE_TMO = STP_IDLE_TIME;
+-
+- if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF)
+- SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF;
+-
+-
+- SASConfigPage.OPNRJT_RTRY_INTVL = (SAS_MFD << 16) |
+- SAS_OPNRJT_RTRY_INTVL;
+- SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO = (SAS_DOPNRJT_RTRY_TMO << 16)
+- | SAS_COPNRJT_RTRY_TMO;
+- SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR = (SAS_DOPNRJT_RTRY_THR << 16)
+- | SAS_COPNRJT_RTRY_THR;
+- SASConfigPage.MAX_AIP = SAS_MAX_AIP;
++ SASConfigPage.pageCode = cpu_to_le32(SAS_PROTOCOL_TIMER_CONFIG_PAGE);
++ SASConfigPage.MST_MSI = cpu_to_le32(3 << 15);
++ SASConfigPage.STP_SSP_MCT_TMO =
++ cpu_to_le32((STP_MCT_TMO << 16) | SSP_MCT_TMO);
++ SASConfigPage.STP_FRM_TMO =
++ cpu_to_le32((SAS_MAX_OPEN_TIME << 24) |
++ (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER);
++ SASConfigPage.STP_IDLE_TMO = cpu_to_le32(STP_IDLE_TIME);
++
++ SASConfigPage.OPNRJT_RTRY_INTVL =
++ cpu_to_le32((SAS_MFD << 16) | SAS_OPNRJT_RTRY_INTVL);
++ SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =
++ cpu_to_le32((SAS_DOPNRJT_RTRY_TMO << 16) | SAS_COPNRJT_RTRY_TMO);
++ SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =
++ cpu_to_le32((SAS_DOPNRJT_RTRY_THR << 16) | SAS_COPNRJT_RTRY_THR);
++ SASConfigPage.MAX_AIP = cpu_to_le32(SAS_MAX_AIP);
+
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n",
+- SASConfigPage.pageCode);
++ le32_to_cpu(SASConfigPage.pageCode));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI 0x%08x\n",
+- SASConfigPage.MST_MSI);
++ le32_to_cpu(SASConfigPage.MST_MSI));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO 0x%08x\n",
+- SASConfigPage.STP_SSP_MCT_TMO);
++ le32_to_cpu(SASConfigPage.STP_SSP_MCT_TMO));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO 0x%08x\n",
+- SASConfigPage.STP_FRM_TMO);
++ le32_to_cpu(SASConfigPage.STP_FRM_TMO));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO 0x%08x\n",
+- SASConfigPage.STP_IDLE_TMO);
++ le32_to_cpu(SASConfigPage.STP_IDLE_TMO));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL 0x%08x\n",
+- SASConfigPage.OPNRJT_RTRY_INTVL);
++ le32_to_cpu(SASConfigPage.OPNRJT_RTRY_INTVL));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO 0x%08x\n",
+- SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO);
++ le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR 0x%08x\n",
+- SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR);
++ le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP 0x%08x\n",
+- SASConfigPage.MAX_AIP);
++ le32_to_cpu(SASConfigPage.MAX_AIP));
+
+ memcpy(&payload.cfg_pg, &SASConfigPage,
+ sizeof(SASProtocolTimerConfig_t));
+@@ -1406,12 +1415,13 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
+ /* Currently only one key is used. New KEK index is 1.
+ * Current KEK index is 1. Store KEK to NVRAM is 1.
+ */
+- payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
+- KEK_MGMT_SUBOP_KEYCARDUPDATE);
++ payload.new_curidx_ksop =
++ cpu_to_le32(((1 << 24) | (1 << 16) | (1 << 8) |
++ KEK_MGMT_SUBOP_KEYCARDUPDATE));
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "Saving Encryption info to flash. payload 0x%x\n",
+- payload.new_curidx_ksop);
++ le32_to_cpu(payload.new_curidx_ksop));
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
+@@ -1734,10 +1744,11 @@ static void
+ pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+ {
+ #ifdef PM8001_USE_MSIX
+- u32 mask;
+- mask = (u32)(1 << vec);
+-
+- pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF));
++ if (vec < 32)
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, 1U << vec);
++ else
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR_U,
++ 1U << (vec - 32));
+ return;
+ #endif
+ pm80xx_chip_intx_interrupt_enable(pm8001_ha);
+@@ -1753,12 +1764,15 @@ static void
+ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+ {
+ #ifdef PM8001_USE_MSIX
+- u32 mask;
+- if (vec == 0xFF)
+- mask = 0xFFFFFFFF;
++ if (vec == 0xFF) {
++ /* disable all vectors 0-31, 32-63 */
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 0xFFFFFFFF);
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 0xFFFFFFFF);
++ } else if (vec < 32)
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 1U << vec);
+ else
+- mask = (u32)(1 << vec);
+- pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF));
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U,
++ 1U << (vec - 32));
+ return;
+ #endif
+ pm80xx_chip_intx_interrupt_disable(pm8001_ha);
+@@ -1800,6 +1814,7 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
++ ccb->n_elem = 0;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+@@ -1881,7 +1896,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
+
+ sata_cmd.tag = cpu_to_le32(ccb_tag);
+ sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+- sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
++ sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
+ memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+@@ -2184,9 +2199,9 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_dbg(pm8001_ha, FAIL,
"task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
t, status, ts->resp, ts->stat);
@@ -104458,7 +154039,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-@@ -2379,7 +2379,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2379,7 +2394,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
/*See the comments for mpi_ssp_completion */
static void
@@ -104468,7 +154049,17 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
{
struct sas_task *t;
struct pm8001_ccb_info *ccb;
-@@ -2616,7 +2617,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2516,7 +2532,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+ len = sizeof(struct pio_setup_fis);
+ pm8001_dbg(pm8001_ha, IO,
+ "PIO read len = %d\n", len);
+- } else if (t->ata_task.use_ncq) {
++ } else if (t->ata_task.use_ncq &&
++ t->data_dir != DMA_NONE) {
+ len = sizeof(struct set_dev_bits_fis);
+ pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
+ len);
+@@ -2616,7 +2633,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_QUEUE_FULL;
@@ -104480,7 +154071,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2632,7 +2637,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2632,7 +2653,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_QUEUE_FULL;
@@ -104492,7 +154083,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2656,7 +2665,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2656,7 +2681,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_QUEUE_FULL;
@@ -104504,7 +154095,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2727,7 +2740,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2727,7 +2756,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_DS_NON_OPERATIONAL);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_QUEUE_FULL;
@@ -104516,7 +154107,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2747,7 +2764,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2747,7 +2780,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_DS_IN_ERROR);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_QUEUE_FULL;
@@ -104528,7 +154119,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2780,17 +2801,22 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2780,17 +2817,22 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_dbg(pm8001_ha, FAIL,
"task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
t, status, ts->resp, ts->stat);
@@ -104553,7 +154144,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
{
struct sas_task *t;
struct task_status_struct *ts;
-@@ -2802,7 +2828,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2802,7 +2844,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 tag = le32_to_cpu(psataPayload->tag);
u32 port_id = le32_to_cpu(psataPayload->port_id);
u32 dev_id = le32_to_cpu(psataPayload->device_id);
@@ -104561,7 +154152,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
ccb = &pm8001_ha->ccb_info[tag];
-@@ -2840,8 +2865,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2840,8 +2881,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
@@ -104570,7 +154161,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
break;
case IO_XFER_ERROR_BREAK:
pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
-@@ -2890,7 +2913,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2890,7 +2929,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_QUEUE_FULL;
@@ -104578,7 +154169,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return;
}
break;
-@@ -2990,20 +3012,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -2990,20 +3028,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_OPEN_TO;
break;
}
@@ -104599,7 +154190,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
}
/*See the comments for mpi_ssp_completion */
-@@ -3902,7 +3910,8 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
+@@ -3902,7 +3926,8 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
* @pm8001_ha: our hba card information
* @piomb: IO message buffer
*/
@@ -104609,7 +154200,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
{
__le32 pHeader = *(__le32 *)piomb;
u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF);
-@@ -3944,11 +3953,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
+@@ -3944,11 +3969,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case OPC_OUB_SATA_COMP:
pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n");
@@ -104623,7 +154214,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
break;
case OPC_OUB_SSP_EVENT:
pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n");
-@@ -4117,13 +4126,24 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+@@ -4117,13 +4142,24 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
void *pMsg1 = NULL;
u8 bc;
u32 ret = MPI_IO_STATUS_FAIL;
@@ -104651,7 +154242,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
pm8001_ha->controller_fatal_error = true;
pm8001_dbg(pm8001_ha, FAIL,
"Firmware Fatal error! Regval:0x%x\n",
-@@ -4134,7 +4154,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+@@ -4134,7 +4170,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
}
}
circularQ = &pm8001_ha->outbnd_q_tbl[vec];
@@ -104660,7 +154251,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
do {
/* spurious interrupt during setup if kexec-ing and
* driver doing a doorbell access w/ the pre-kexec oq
-@@ -4145,7 +4165,8 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+@@ -4145,7 +4181,8 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
if (MPI_IO_STATUS_SUCCESS == ret) {
/* process the outbound message */
@@ -104670,7 +154261,7 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
/* free the message from the outbound circular buffer */
pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
circularQ, bc);
-@@ -4160,7 +4181,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+@@ -4160,7 +4197,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
break;
}
} while (1);
@@ -104679,6 +154270,312 @@ index 6ffe17b849ae8..3056f3615ab8a 100644
return ret;
}
+@@ -4359,13 +4396,15 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ struct ssp_ini_io_start_req ssp_cmd;
+ u32 tag = ccb->ccb_tag;
+ int ret;
+- u64 phys_addr, start_addr, end_addr;
++ u64 phys_addr, end_addr;
+ u32 end_addr_high, end_addr_low;
+ struct inbound_queue_table *circularQ;
+ u32 q_index, cpu_id;
+ u32 opc = OPC_INB_SSPINIIOSTART;
++
+ memset(&ssp_cmd, 0, sizeof(ssp_cmd));
+ memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
++
+ /* data address domain added for spcv; set to 0 by host,
+ * used internally by controller
+ * 0 for SAS 1.1 and SAS 2.0 compatible TLR
+@@ -4376,7 +4415,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
+ ssp_cmd.tag = cpu_to_le32(tag);
+ if (task->ssp_task.enable_first_burst)
+- ssp_cmd.ssp_iu.efb_prio_attr |= 0x80;
++ ssp_cmd.ssp_iu.efb_prio_attr = 0x80;
+ ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
+ ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
+ memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
+@@ -4408,21 +4447,24 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
++
+ ssp_cmd.enc_addr_low =
+ cpu_to_le32(lower_32_bits(dma_addr));
+ ssp_cmd.enc_addr_high =
+ cpu_to_le32(upper_32_bits(dma_addr));
+ ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.enc_esgl = 0;
++
+ /* Check 4G Boundary */
+- start_addr = cpu_to_le64(dma_addr);
+- end_addr = (start_addr + ssp_cmd.enc_len) - 1;
+- end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
+- end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
+- if (end_addr_high != ssp_cmd.enc_addr_high) {
++ end_addr = dma_addr + le32_to_cpu(ssp_cmd.enc_len) - 1;
++ end_addr_low = lower_32_bits(end_addr);
++ end_addr_high = upper_32_bits(end_addr);
++
++ if (end_addr_high != le32_to_cpu(ssp_cmd.enc_addr_high)) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+- start_addr, ssp_cmd.enc_len,
++ dma_addr,
++ le32_to_cpu(ssp_cmd.enc_len),
+ end_addr_high, end_addr_low);
+ pm8001_chip_make_sg(task->scatter, 1,
+ ccb->buf_prd);
+@@ -4431,7 +4473,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ cpu_to_le32(lower_32_bits(phys_addr));
+ ssp_cmd.enc_addr_high =
+ cpu_to_le32(upper_32_bits(phys_addr));
+- ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
++ ssp_cmd.enc_esgl = cpu_to_le32(1U<<31);
+ }
+ } else if (task->num_scatter == 0) {
+ ssp_cmd.enc_addr_low = 0;
+@@ -4439,8 +4481,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.enc_esgl = 0;
+ }
++
+ /* XTS mode. All other fields are 0 */
+- ssp_cmd.key_cmode = 0x6 << 4;
++ ssp_cmd.key_cmode = cpu_to_le32(0x6 << 4);
++
+ /* set tweak values. Should be the start lba */
+ ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cmd->cmnd[2] << 24) |
+ (task->ssp_task.cmd->cmnd[3] << 16) |
+@@ -4462,20 +4506,22 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ ssp_cmd.esgl = cpu_to_le32(1<<31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
++
+ ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));
+ ssp_cmd.addr_high =
+ cpu_to_le32(upper_32_bits(dma_addr));
+ ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.esgl = 0;
++
+ /* Check 4G Boundary */
+- start_addr = cpu_to_le64(dma_addr);
+- end_addr = (start_addr + ssp_cmd.len) - 1;
+- end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
+- end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
+- if (end_addr_high != ssp_cmd.addr_high) {
++ end_addr = dma_addr + le32_to_cpu(ssp_cmd.len) - 1;
++ end_addr_low = lower_32_bits(end_addr);
++ end_addr_high = upper_32_bits(end_addr);
++ if (end_addr_high != le32_to_cpu(ssp_cmd.addr_high)) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+- start_addr, ssp_cmd.len,
++ dma_addr,
++ le32_to_cpu(ssp_cmd.len),
+ end_addr_high, end_addr_low);
+ pm8001_chip_make_sg(task->scatter, 1,
+ ccb->buf_prd);
+@@ -4509,7 +4555,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ u32 q_index, cpu_id;
+ struct sata_start_req sata_cmd;
+ u32 hdr_tag, ncg_tag = 0;
+- u64 phys_addr, start_addr, end_addr;
++ u64 phys_addr, end_addr;
+ u32 end_addr_high, end_addr_low;
+ u32 ATAP = 0x0;
+ u32 dir;
+@@ -4521,22 +4567,21 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
+ circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
+
+- if (task->data_dir == DMA_NONE) {
++ if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
+ ATAP = 0x04; /* no data*/
+ pm8001_dbg(pm8001_ha, IO, "no data\n");
+ } else if (likely(!task->ata_task.device_control_reg_update)) {
+- if (task->ata_task.dma_xfer) {
++ if (task->ata_task.use_ncq &&
++ dev->sata_dev.class != ATA_DEV_ATAPI) {
++ ATAP = 0x07; /* FPDMA */
++ pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
++ } else if (task->ata_task.dma_xfer) {
+ ATAP = 0x06; /* DMA */
+ pm8001_dbg(pm8001_ha, IO, "DMA\n");
+ } else {
+ ATAP = 0x05; /* PIO*/
+ pm8001_dbg(pm8001_ha, IO, "PIO\n");
+ }
+- if (task->ata_task.use_ncq &&
+- dev->sata_dev.class != ATA_DEV_ATAPI) {
+- ATAP = 0x07; /* FPDMA */
+- pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
+- }
+ }
+ if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+ task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+@@ -4570,32 +4615,38 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ pm8001_chip_make_sg(task->scatter,
+ ccb->n_elem, ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle;
+- sata_cmd.enc_addr_low = lower_32_bits(phys_addr);
+- sata_cmd.enc_addr_high = upper_32_bits(phys_addr);
++ sata_cmd.enc_addr_low =
++ cpu_to_le32(lower_32_bits(phys_addr));
++ sata_cmd.enc_addr_high =
++ cpu_to_le32(upper_32_bits(phys_addr));
+ sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
+- sata_cmd.enc_addr_low = lower_32_bits(dma_addr);
+- sata_cmd.enc_addr_high = upper_32_bits(dma_addr);
++
++ sata_cmd.enc_addr_low =
++ cpu_to_le32(lower_32_bits(dma_addr));
++ sata_cmd.enc_addr_high =
++ cpu_to_le32(upper_32_bits(dma_addr));
+ sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.enc_esgl = 0;
++
+ /* Check 4G Boundary */
+- start_addr = cpu_to_le64(dma_addr);
+- end_addr = (start_addr + sata_cmd.enc_len) - 1;
+- end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
+- end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
+- if (end_addr_high != sata_cmd.enc_addr_high) {
++ end_addr = dma_addr + le32_to_cpu(sata_cmd.enc_len) - 1;
++ end_addr_low = lower_32_bits(end_addr);
++ end_addr_high = upper_32_bits(end_addr);
++ if (end_addr_high != le32_to_cpu(sata_cmd.enc_addr_high)) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+- start_addr, sata_cmd.enc_len,
++ dma_addr,
++ le32_to_cpu(sata_cmd.enc_len),
+ end_addr_high, end_addr_low);
+ pm8001_chip_make_sg(task->scatter, 1,
+ ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle;
+ sata_cmd.enc_addr_low =
+- lower_32_bits(phys_addr);
++ cpu_to_le32(lower_32_bits(phys_addr));
+ sata_cmd.enc_addr_high =
+- upper_32_bits(phys_addr);
++ cpu_to_le32(upper_32_bits(phys_addr));
+ sata_cmd.enc_esgl =
+ cpu_to_le32(1 << 31);
+ }
+@@ -4606,7 +4657,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ sata_cmd.enc_esgl = 0;
+ }
+ /* XTS mode. All other fields are 0 */
+- sata_cmd.key_index_mode = 0x6 << 4;
++ sata_cmd.key_index_mode = cpu_to_le32(0x6 << 4);
++
+ /* set tweak values. Should be the start lba */
+ sata_cmd.twk_val0 =
+ cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |
+@@ -4632,31 +4684,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ phys_addr = ccb->ccb_dma_handle;
+ sata_cmd.addr_low = lower_32_bits(phys_addr);
+ sata_cmd.addr_high = upper_32_bits(phys_addr);
+- sata_cmd.esgl = cpu_to_le32(1 << 31);
++ sata_cmd.esgl = cpu_to_le32(1U << 31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
++
+ sata_cmd.addr_low = lower_32_bits(dma_addr);
+ sata_cmd.addr_high = upper_32_bits(dma_addr);
+ sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.esgl = 0;
++
+ /* Check 4G Boundary */
+- start_addr = cpu_to_le64(dma_addr);
+- end_addr = (start_addr + sata_cmd.len) - 1;
+- end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
+- end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
++ end_addr = dma_addr + le32_to_cpu(sata_cmd.len) - 1;
++ end_addr_low = lower_32_bits(end_addr);
++ end_addr_high = upper_32_bits(end_addr);
+ if (end_addr_high != sata_cmd.addr_high) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%xend_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+- start_addr, sata_cmd.len,
++ dma_addr,
++ le32_to_cpu(sata_cmd.len),
+ end_addr_high, end_addr_low);
+ pm8001_chip_make_sg(task->scatter, 1,
+ ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle;
+- sata_cmd.addr_low =
+- lower_32_bits(phys_addr);
+- sata_cmd.addr_high =
+- upper_32_bits(phys_addr);
+- sata_cmd.esgl = cpu_to_le32(1 << 31);
++ sata_cmd.addr_low = lower_32_bits(phys_addr);
++ sata_cmd.addr_high = upper_32_bits(phys_addr);
++ sata_cmd.esgl = cpu_to_le32(1U << 31);
+ }
+ } else if (task->num_scatter == 0) {
+ sata_cmd.addr_low = 0;
+@@ -4664,27 +4716,28 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.esgl = 0;
+ }
++
+ /* scsi cdb */
+ sata_cmd.atapi_scsi_cdb[0] =
+ cpu_to_le32(((task->ata_task.atapi_packet[0]) |
+- (task->ata_task.atapi_packet[1] << 8) |
+- (task->ata_task.atapi_packet[2] << 16) |
+- (task->ata_task.atapi_packet[3] << 24)));
++ (task->ata_task.atapi_packet[1] << 8) |
++ (task->ata_task.atapi_packet[2] << 16) |
++ (task->ata_task.atapi_packet[3] << 24)));
+ sata_cmd.atapi_scsi_cdb[1] =
+ cpu_to_le32(((task->ata_task.atapi_packet[4]) |
+- (task->ata_task.atapi_packet[5] << 8) |
+- (task->ata_task.atapi_packet[6] << 16) |
+- (task->ata_task.atapi_packet[7] << 24)));
++ (task->ata_task.atapi_packet[5] << 8) |
++ (task->ata_task.atapi_packet[6] << 16) |
++ (task->ata_task.atapi_packet[7] << 24)));
+ sata_cmd.atapi_scsi_cdb[2] =
+ cpu_to_le32(((task->ata_task.atapi_packet[8]) |
+- (task->ata_task.atapi_packet[9] << 8) |
+- (task->ata_task.atapi_packet[10] << 16) |
+- (task->ata_task.atapi_packet[11] << 24)));
++ (task->ata_task.atapi_packet[9] << 8) |
++ (task->ata_task.atapi_packet[10] << 16) |
++ (task->ata_task.atapi_packet[11] << 24)));
+ sata_cmd.atapi_scsi_cdb[3] =
+ cpu_to_le32(((task->ata_task.atapi_packet[12]) |
+- (task->ata_task.atapi_packet[13] << 8) |
+- (task->ata_task.atapi_packet[14] << 16) |
+- (task->ata_task.atapi_packet[15] << 24)));
++ (task->ata_task.atapi_packet[13] << 8) |
++ (task->ata_task.atapi_packet[14] << 16) |
++ (task->ata_task.atapi_packet[15] << 24)));
+ }
+
+ /* Check for read log for failed drive and return */
+@@ -4882,8 +4935,13 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
+ payload.tag = cpu_to_le32(tag);
+ payload.phyop_phyid =
+ cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
+- return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+- sizeof(payload), 0);
++
++ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
++ sizeof(payload), 0);
++ if (rc)
++ pm8001_tag_free(pm8001_ha, tag);
++
++ return rc;
+ }
+
+ static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index c7e5d93bea924..c41ed039c92ac 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -104777,11 +154674,150 @@ index d01cd829ef975..df9ce6ed52bf9 100644
wake_up_interruptible(&qedi_conn->wait_queue);
return;
+diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
+index c5260429c637e..04b40a6c1afff 100644
+--- a/drivers/scsi/qedi/qedi_iscsi.c
++++ b/drivers/scsi/qedi/qedi_iscsi.c
+@@ -859,6 +859,37 @@ static int qedi_task_xmit(struct iscsi_task *task)
+ return qedi_iscsi_send_ioreq(task);
+ }
+
++static void qedi_offload_work(struct work_struct *work)
++{
++ struct qedi_endpoint *qedi_ep =
++ container_of(work, struct qedi_endpoint, offload_work);
++ struct qedi_ctx *qedi;
++ int wait_delay = 5 * HZ;
++ int ret;
++
++ qedi = qedi_ep->qedi;
++
++ ret = qedi_iscsi_offload_conn(qedi_ep);
++ if (ret) {
++ QEDI_ERR(&qedi->dbg_ctx,
++ "offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n",
++ qedi_ep->iscsi_cid, qedi_ep, ret);
++ qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
++ return;
++ }
++
++ ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait,
++ (qedi_ep->state ==
++ EP_STATE_OFLDCONN_COMPL),
++ wait_delay);
++ if (ret <= 0 || qedi_ep->state != EP_STATE_OFLDCONN_COMPL) {
++ qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
++ QEDI_ERR(&qedi->dbg_ctx,
++ "Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n",
++ qedi_ep->iscsi_cid, qedi_ep);
++ }
++}
++
+ static struct iscsi_endpoint *
+ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ int non_blocking)
+@@ -907,6 +938,7 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ }
+ qedi_ep = ep->dd_data;
+ memset(qedi_ep, 0, sizeof(struct qedi_endpoint));
++ INIT_WORK(&qedi_ep->offload_work, qedi_offload_work);
+ qedi_ep->state = EP_STATE_IDLE;
+ qedi_ep->iscsi_cid = (u32)-1;
+ qedi_ep->qedi = qedi;
+@@ -1055,12 +1087,11 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
+ qedi_ep = ep->dd_data;
+ qedi = qedi_ep->qedi;
+
++ flush_work(&qedi_ep->offload_work);
++
+ if (qedi_ep->state == EP_STATE_OFLDCONN_START)
+ goto ep_exit_recover;
+
+- if (qedi_ep->state != EP_STATE_OFLDCONN_NONE)
+- flush_work(&qedi_ep->offload_work);
+-
+ if (qedi_ep->conn) {
+ qedi_conn = qedi_ep->conn;
+ abrt_conn = qedi_conn->abrt_conn;
+@@ -1234,37 +1265,6 @@ static int qedi_data_avail(struct qedi_ctx *qedi, u16 vlanid)
+ return rc;
+ }
+
+-static void qedi_offload_work(struct work_struct *work)
+-{
+- struct qedi_endpoint *qedi_ep =
+- container_of(work, struct qedi_endpoint, offload_work);
+- struct qedi_ctx *qedi;
+- int wait_delay = 5 * HZ;
+- int ret;
+-
+- qedi = qedi_ep->qedi;
+-
+- ret = qedi_iscsi_offload_conn(qedi_ep);
+- if (ret) {
+- QEDI_ERR(&qedi->dbg_ctx,
+- "offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n",
+- qedi_ep->iscsi_cid, qedi_ep, ret);
+- qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
+- return;
+- }
+-
+- ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait,
+- (qedi_ep->state ==
+- EP_STATE_OFLDCONN_COMPL),
+- wait_delay);
+- if ((ret <= 0) || (qedi_ep->state != EP_STATE_OFLDCONN_COMPL)) {
+- qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
+- QEDI_ERR(&qedi->dbg_ctx,
+- "Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n",
+- qedi_ep->iscsi_cid, qedi_ep);
+- }
+-}
+-
+ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
+ {
+ struct qedi_ctx *qedi;
+@@ -1380,7 +1380,6 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
+ qedi_ep->dst_addr, qedi_ep->dst_port);
+ }
+
+- INIT_WORK(&qedi_ep->offload_work, qedi_offload_work);
+ queue_work(qedi->offload_thread, &qedi_ep->offload_work);
+
+ ret = 0;
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
-index d09776b77af2e..cb5f2ecb652d3 100644
+index d09776b77af2e..d3534e7f2d214 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
-@@ -1868,6 +1868,18 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr,
+@@ -555,7 +555,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
+ if (!capable(CAP_SYS_ADMIN))
+ return -EINVAL;
+
+- if (IS_NOCACHE_VPD_TYPE(ha))
++ if (!IS_NOCACHE_VPD_TYPE(ha))
+ goto skip;
+
+ faddr = ha->flt_region_vpd << 2;
+@@ -745,7 +745,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
+ ql_log(ql_log_info, vha, 0x706f,
+ "Issuing MPI reset.\n");
+
+- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
++ if (IS_QLA83XX(ha)) {
+ uint32_t idc_control;
+
+ qla83xx_idc_lock(vha, 0);
+@@ -1056,9 +1056,6 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
+ continue;
+ if (iter->type == 3 && !(IS_CNA_CAPABLE(ha)))
+ continue;
+- if (iter->type == 0x27 &&
+- (!IS_QLA27XX(ha) || !IS_QLA28XX(ha)))
+- continue;
+
+ sysfs_remove_bin_file(&host->shost_gendev.kobj,
+ iter->attr);
+@@ -1868,6 +1865,18 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr,
return strlen(buf);
}
@@ -104800,7 +154836,7 @@ index d09776b77af2e..cb5f2ecb652d3 100644
static ssize_t
qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
char *buf)
-@@ -1875,7 +1887,8 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
+@@ -1875,7 +1884,8 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
ssize_t rval;
@@ -104810,7 +154846,7 @@ index d09776b77af2e..cb5f2ecb652d3 100644
rval = qla2x00_get_data_rate(vha);
if (rval != QLA_SUCCESS) {
-@@ -1884,7 +1897,14 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
+@@ -1884,7 +1894,14 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
@@ -104826,6 +154862,29 @@ index d09776b77af2e..cb5f2ecb652d3 100644
}
static ssize_t
+diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
+index 655cf5de604b8..c636165be52be 100644
+--- a/drivers/scsi/qla2xxx/qla_bsg.c
++++ b/drivers/scsi/qla2xxx/qla_bsg.c
+@@ -29,7 +29,8 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
+ "%s: sp hdl %x, result=%x bsg ptr %p\n",
+ __func__, sp->handle, res, bsg_job);
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+
+ bsg_reply->result = res;
+ bsg_job_done(bsg_job, bsg_reply->result,
+@@ -3010,6 +3011,7 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
+
+ done:
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return 0;
+ }
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 25549a8a2d72d..7cf1f78cbaeee 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
@@ -104840,8 +154899,59 @@ index 25549a8a2d72d..7cf1f78cbaeee 100644
va_start(va, fmt);
vaf.fmt = fmt;
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index be2eb75ee1a37..2ea35e47ea441 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -726,6 +726,11 @@ typedef struct srb {
+ * code.
+ */
+ void (*put_fn)(struct kref *kref);
++
++ /*
++ * Report completion for asynchronous commands.
++ */
++ void (*async_done)(struct srb *sp, int res);
+ } srb_t;
+
+ #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
+@@ -2886,7 +2891,11 @@ struct ct_fdmi2_hba_attributes {
+ #define FDMI_PORT_SPEED_8GB 0x10
+ #define FDMI_PORT_SPEED_16GB 0x20
+ #define FDMI_PORT_SPEED_32GB 0x40
+-#define FDMI_PORT_SPEED_64GB 0x80
++#define FDMI_PORT_SPEED_20GB 0x80
++#define FDMI_PORT_SPEED_40GB 0x100
++#define FDMI_PORT_SPEED_128GB 0x200
++#define FDMI_PORT_SPEED_64GB 0x400
++#define FDMI_PORT_SPEED_256GB 0x800
+ #define FDMI_PORT_SPEED_UNKNOWN 0x8000
+
+ #define FC_CLASS_2 0x04
+@@ -4261,8 +4270,10 @@ struct qla_hw_data {
+ #define QLA_ABTS_WAIT_ENABLED(_sp) \
+ (QLA_NVME_IOS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
+
+-#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+-#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
++#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
++ IS_QLA28XX(ha))
++#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
++ IS_QLA28XX(ha))
+ #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0)
+ #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
+@@ -5427,4 +5438,8 @@ struct ql_vnd_tgt_stats_resp {
+ #include "qla_gbl.h"
+ #include "qla_dbg.h"
+ #include "qla_inline.h"
++
++#define IS_SESSION_DELETED(_fcport) (_fcport->disc_state == DSC_DELETE_PEND || \
++ _fcport->disc_state == DSC_DELETED)
++
+ #endif
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
-index ad746c62f0d44..a04693498dc01 100644
+index ad746c62f0d44..a00fe88c60218 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -290,63 +290,6 @@ qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)
@@ -105000,7 +155110,28 @@ index ad746c62f0d44..a04693498dc01 100644
ql_dbg(ql_dbg_edif, vha, 0x911d,
"%s app start completed with 0x%x\n",
-@@ -800,15 +743,15 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -725,6 +668,11 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+ bsg_job->request_payload.sg_cnt, &appplogiok,
+ sizeof(struct auth_complete_cmd));
+
++ /* silent unaligned access warning */
++ portid.b.domain = appplogiok.u.d_id.b.domain;
++ portid.b.area = appplogiok.u.d_id.b.area;
++ portid.b.al_pa = appplogiok.u.d_id.b.al_pa;
++
+ switch (appplogiok.type) {
+ case PL_TYPE_WWPN:
+ fcport = qla2x00_find_fcport_by_wwpn(vha,
+@@ -735,7 +683,7 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+ __func__, appplogiok.u.wwpn);
+ break;
+ case PL_TYPE_DID:
+- fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id);
++ fcport = qla2x00_find_fcport_by_pid(vha, &portid);
+ if (!fcport)
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s d_id lookup failed: %x\n", __func__,
+@@ -800,15 +748,15 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
ql_dbg(ql_dbg_edif, vha, 0x911e,
"%s AUTH complete - RESUME with prli for wwpn %8phC\n",
__func__, fcport->port_name);
@@ -105020,7 +155151,28 @@ index ad746c62f0d44..a04693498dc01 100644
return rval;
}
-@@ -873,7 +816,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -834,6 +782,11 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+ bsg_job->request_payload.sg_cnt, &appplogifail,
+ sizeof(struct auth_complete_cmd));
+
++ /* silent unaligned access warning */
++ portid.b.domain = appplogifail.u.d_id.b.domain;
++ portid.b.area = appplogifail.u.d_id.b.area;
++ portid.b.al_pa = appplogifail.u.d_id.b.al_pa;
++
+ /*
+ * TODO: edif: app has failed this plogi. Inform driver to
+ * take any action (if any).
+@@ -845,7 +798,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ break;
+ case PL_TYPE_DID:
+- fcport = qla2x00_find_fcport_by_pid(vha, &appplogifail.u.d_id);
++ fcport = qla2x00_find_fcport_by_pid(vha, &portid);
+ if (!fcport)
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s d_id lookup failed: %x\n", __func__,
+@@ -873,7 +826,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
if (qla_ini_mode_enabled(fcport->vha)) {
fcport->send_els_logo = 1;
@@ -105029,7 +155181,7 @@ index ad746c62f0d44..a04693498dc01 100644
}
}
-@@ -891,7 +834,7 @@ static int
+@@ -891,7 +844,7 @@ static int
qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
{
int32_t rval = 0;
@@ -105038,7 +155190,7 @@ index ad746c62f0d44..a04693498dc01 100644
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
struct app_pinfo_req app_req;
struct app_pinfo_reply *app_reply;
-@@ -903,16 +846,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -903,16 +856,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
bsg_job->request_payload.sg_cnt, &app_req,
sizeof(struct app_pinfo_req));
@@ -105057,7 +155209,7 @@ index ad746c62f0d44..a04693498dc01 100644
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
if (!(fcport->flags & FCF_FCSP_DEVICE))
-@@ -924,7 +865,7 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -924,7 +875,7 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
"APP request entry - portid=%06x.\n", tdid.b24);
/* Ran out of space */
@@ -105066,7 +155218,7 @@ index ad746c62f0d44..a04693498dc01 100644
break;
if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24)
-@@ -981,9 +922,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -981,9 +932,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
SET_DID_STATUS(bsg_reply->result, DID_OK);
}
@@ -105081,7 +155233,7 @@ index ad746c62f0d44..a04693498dc01 100644
kfree(app_reply);
-@@ -1000,10 +943,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -1000,10 +953,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
{
int32_t rval = 0;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
@@ -105094,7 +155246,7 @@ index ad746c62f0d44..a04693498dc01 100644
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, &app_req,
-@@ -1019,18 +963,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -1019,18 +973,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
size = sizeof(struct app_stats_reply) +
(sizeof(struct app_sinfo) * app_req.num_ports);
@@ -105113,7 +155265,7 @@ index ad746c62f0d44..a04693498dc01 100644
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
if (fcport->edif.enable) {
-@@ -1054,9 +992,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+@@ -1054,9 +1002,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
SET_DID_STATUS(bsg_reply->result, DID_OK);
}
@@ -105126,7 +155278,7 @@ index ad746c62f0d44..a04693498dc01 100644
kfree(app_reply);
-@@ -1130,8 +1070,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
+@@ -1130,8 +1080,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
__func__,
bsg_request->rqst_data.h_vendor.vendor_cmd[1]);
rval = EXT_STATUS_INVALID_PARAM;
@@ -105136,7 +155288,29 @@ index ad746c62f0d44..a04693498dc01 100644
break;
}
-@@ -1651,6 +1590,40 @@ qla_enode_stop(scsi_qla_host_t *vha)
+@@ -1314,6 +1263,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
+ int result = 0;
+ struct qla_sa_update_frame sa_frame;
+ struct srb_iocb *iocb_cmd;
++ port_id_t portid;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d,
+ "%s entered, vha: 0x%p\n", __func__, vha);
+@@ -1337,7 +1287,12 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
+ goto done;
+ }
+
+- fcport = qla2x00_find_fcport_by_pid(vha, &sa_frame.port_id);
++ /* silent unaligned access warning */
++ portid.b.domain = sa_frame.port_id.b.domain;
++ portid.b.area = sa_frame.port_id.b.area;
++ portid.b.al_pa = sa_frame.port_id.b.al_pa;
++
++ fcport = qla2x00_find_fcport_by_pid(vha, &portid);
+ if (fcport) {
+ found = 1;
+ if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_TX_KEY)
+@@ -1651,6 +1606,40 @@ qla_enode_stop(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
}
@@ -105177,7 +155351,7 @@ index ad746c62f0d44..a04693498dc01 100644
/*
* allocate enode struct and populate buffer
* returns: enode pointer with buffers
-@@ -1850,6 +1823,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
+@@ -1850,6 +1839,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
node->ntype = N_UNDEF;
}
@@ -105235,7 +155409,17 @@ index ad746c62f0d44..a04693498dc01 100644
/* function called when app is stopping */
void
-@@ -2357,7 +2381,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
+@@ -2137,7 +2177,8 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr,
+
+ static void qla_noop_sp_done(srb_t *sp, int res)
+ {
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ /*
+@@ -2357,7 +2398,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
return;
}
@@ -105244,7 +155428,7 @@ index ad746c62f0d44..a04693498dc01 100644
ql_dbg(ql_dbg_edif, vha, 0x0910d,
"%s WARNING: verbose ELS frame received (totlen=%x)\n",
__func__, totlen);
-@@ -2436,7 +2460,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
+@@ -2436,7 +2477,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
ql_dbg(ql_dbg_edif, host, 0x0910c,
"%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
__func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24,
@@ -105253,7 +155437,7 @@ index ad746c62f0d44..a04693498dc01 100644
qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL);
}
-@@ -3459,3 +3483,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
+@@ -3459,3 +3500,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
}
}
@@ -105301,7 +155485,7 @@ index 58b718d35d19a..53026d82ebffe 100644
#define WWN_SIZE 8
#endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
-index 1c3f055d41b8e..2c7e91bffb827 100644
+index 1c3f055d41b8e..83912787fa2e0 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -142,6 +142,8 @@ void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport,
@@ -105321,7 +155505,25 @@ index 1c3f055d41b8e..2c7e91bffb827 100644
extern int ql2xdontresethba;
extern uint64_t ql2xmaxlun;
extern int ql2xmdcapmask;
-@@ -816,7 +817,6 @@ extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *);
+@@ -315,7 +316,8 @@ extern int qla2x00_start_sp(srb_t *);
+ extern int qla24xx_dif_start_scsi(srb_t *);
+ extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
+ extern int qla2xxx_dif_start_scsi_mq(srb_t *);
+-extern void qla2x00_init_timer(srb_t *sp, unsigned long tmo);
++extern void qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
++ void (*done)(struct srb *, int));
+ extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
+
+ extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
+@@ -331,6 +333,7 @@ extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
+ 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);
+
+ /*
+ * Global Function Prototypes in qla_mbx.c source file.
+@@ -816,7 +819,6 @@ extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *);
extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *);
extern void qlafx00_timer_routine(scsi_qla_host_t *);
extern int qlafx00_rescan_isp(scsi_qla_host_t *);
@@ -105329,11 +155531,871 @@ index 1c3f055d41b8e..2c7e91bffb827 100644
/* qla82xx related functions */
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index ebc8fdb0b43d3..da7080c4bd008 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -529,7 +529,6 @@ static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
+ if (!e)
+ goto err2;
+
+- del_timer(&sp->u.iocb_cmd.timer);
+ e->u.iosb.sp = sp;
+ qla2x00_post_work(vha, e);
+ return;
+@@ -556,8 +555,8 @@ err2:
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+
+- sp->free(sp);
+-
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return;
+ }
+
+@@ -592,13 +591,15 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
+ if (!vha->flags.online)
+ goto done;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "rft_id";
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_sns_sp_done);
+
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+@@ -638,8 +639,6 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
+ sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla2x00_async_sns_sp_done;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x.\n",
+@@ -653,7 +652,8 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
+ }
+ return rval;
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -676,8 +676,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
+ return (QLA_SUCCESS);
+ }
+
+- return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha),
+- FC4_TYPE_FCP_SCSI);
++ return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha), type);
+ }
+
+ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
+@@ -688,13 +687,15 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
+ srb_t *sp;
+ struct ct_sns_pkt *ct_sns;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "rff_id";
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_sns_sp_done);
+
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+@@ -727,13 +728,11 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
+ /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
+ ct_req->req.rff_id.port_id = port_id_to_be_id(*d_id);
+ ct_req->req.rff_id.fc4_feature = fc4feature;
+- ct_req->req.rff_id.fc4_type = fc4type; /* SCSI - FCP */
++ ct_req->req.rff_id.fc4_type = fc4type; /* SCSI-FCP or FC-NVMe */
+
+ sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla2x00_async_sns_sp_done;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
+@@ -749,7 +748,8 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -779,13 +779,15 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
+ srb_t *sp;
+ struct ct_sns_pkt *ct_sns;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "rnid";
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_sns_sp_done);
+
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+@@ -823,9 +825,6 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
+ sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla2x00_async_sns_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x\n",
+ sp->name, sp->handle, d_id->b24);
+@@ -840,7 +839,8 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -886,13 +886,15 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
+ srb_t *sp;
+ struct ct_sns_pkt *ct_sns;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "rsnn_nn";
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_sns_sp_done);
+
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
+@@ -936,9 +938,6 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla2x00_async_sns_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x.\n",
+ sp->name, sp->handle);
+@@ -953,7 +952,8 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -2892,7 +2892,8 @@ static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)
+ qla24xx_handle_gpsc_event(vha, &ea);
+
+ done:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+@@ -2904,6 +2905,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ return rval;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+@@ -2912,8 +2914,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->name = "gpsc";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla24xx_async_gpsc_sp_done);
+
+ /* CT_IU preamble */
+ ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
+@@ -2931,9 +2933,6 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
+
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla24xx_async_gpsc_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0x205e,
+ "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
+ sp->name, fcport->port_name, sp->handle,
+@@ -2946,7 +2945,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -2995,7 +2995,8 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
+ break;
+ }
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+@@ -3134,13 +3135,15 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
+ if (res) {
+ if (res == QLA_FUNCTION_TIMEOUT) {
+ qla24xx_post_gpnid_work(sp->vha, &ea.id);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return;
+ }
+ } else if (sp->gen1) {
+ /* There was another RSCN for this Nport ID */
+ qla24xx_post_gpnid_work(sp->vha, &ea.id);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return;
+ }
+
+@@ -3161,7 +3164,8 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return;
+ }
+
+@@ -3181,6 +3185,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
+ if (!vha->flags.online)
+ goto done;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+@@ -3189,14 +3194,16 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
+ sp->name = "gpnid";
+ sp->u.iocb_cmd.u.ctarg.id = *id;
+ sp->gen1 = 0;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_gpnid_sp_done);
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ list_for_each_entry(tsp, &vha->gpnid_list, elem) {
+ if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
+ tsp->gen1++;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ goto done;
+ }
+ }
+@@ -3237,9 +3244,6 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- sp->done = qla2x00_async_gpnid_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0x2067,
+ "Async-%s hdl=%x ID %3phC.\n", sp->name,
+ sp->handle, &ct_req->req.port_id.port_id);
+@@ -3269,8 +3273,8 @@ done_free_sp:
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+-
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -3325,7 +3329,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
+ ea.rc = res;
+
+ qla24xx_handle_gffid_event(vha, &ea);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ /* Get FC4 Feature with Nport ID. */
+@@ -3338,6 +3343,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ return rval;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ return rval;
+@@ -3347,9 +3353,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->name = "gffid";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla24xx_async_gffid_sp_done);
+
+ /* CT_IU preamble */
+ ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
+@@ -3367,8 +3372,6 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->done = qla24xx_async_gffid_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0x2132,
+ "Async-%s hdl=%x %8phC.\n", sp->name,
+ sp->handle, fcport->port_name);
+@@ -3379,7 +3382,8 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
+
+ return rval;
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+ }
+@@ -3766,7 +3770,6 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
+ "Async done-%s res %x FC4Type %x\n",
+ sp->name, res, sp->gen2);
+
+- del_timer(&sp->u.iocb_cmd.timer);
+ sp->rc = res;
+ if (res) {
+ unsigned long flags;
+@@ -3891,9 +3894,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
+ sp->name = "gnnft";
+ sp->gen1 = vha->hw->base_qpair->chip_reset;
+ sp->gen2 = fc4_type;
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_gpnft_gnnft_sp_done);
+
+ memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+ memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+@@ -3909,8 +3911,6 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
+ sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+ sp->handle, ct_req->req.gpn_ft.port_type);
+@@ -3937,8 +3937,8 @@ done_free_sp:
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+-
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -3990,9 +3990,12 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ "%s: Performing FCP Scan\n", __func__);
+
+- if (sp)
+- sp->free(sp); /* should not happen */
++ if (sp) {
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
++ }
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp) {
+ spin_lock_irqsave(&vha->work_lock, flags);
+@@ -4037,6 +4040,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
++ /* ref: INIT */
+ qla2x00_rel_sp(sp);
+ return rval;
+ }
+@@ -4056,9 +4060,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
+ sp->name = "gpnft";
+ sp->gen1 = vha->hw->base_qpair->chip_reset;
+ sp->gen2 = fc4_type;
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_gpnft_gnnft_sp_done);
+
+ rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
+ memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+@@ -4073,8 +4076,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
+
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+ sp->handle, ct_req->req.gpn_ft.port_type);
+@@ -4102,7 +4103,8 @@ done_free_sp:
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -4166,7 +4168,8 @@ static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
+
+ qla24xx_handle_gnnid_event(vha, &ea);
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+@@ -4179,6 +4182,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ return rval;
+
+ qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp)
+ goto done;
+@@ -4188,9 +4192,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->name = "gnnid";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_gnnid_sp_done);
+
+ /* CT_IU preamble */
+ ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
+@@ -4209,8 +4212,6 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->done = qla2x00_async_gnnid_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
+ sp->name, fcport->port_name,
+@@ -4222,7 +4223,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ done:
+ return rval;
+@@ -4296,7 +4298,8 @@ static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)
+
+ qla24xx_handle_gfpnid_event(vha, &ea);
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+@@ -4308,6 +4311,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ return rval;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp)
+ goto done;
+@@ -4316,9 +4320,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->name = "gfpnid";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_gfpnid_sp_done);
+
+ /* CT_IU preamble */
+ ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
+@@ -4337,8 +4340,6 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- sp->done = qla2x00_async_gfpnid_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
+ sp->name, fcport->port_name,
+@@ -4351,7 +4352,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
-index 5fc7697f0af4c..847a6e5d9cb07 100644
+index 5fc7697f0af4c..af8df5a800c61 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
-@@ -987,8 +987,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
+@@ -51,6 +51,9 @@ qla2x00_sp_timeout(struct timer_list *t)
+ WARN_ON(irqs_disabled());
+ iocb = &sp->u.iocb_cmd;
+ iocb->timeout(sp);
++
++ /* ref: TMR */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ void qla2x00_sp_free(srb_t *sp)
+@@ -125,8 +128,13 @@ static void qla24xx_abort_iocb_timeout(void *data)
+ }
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+- if (sp->cmd_sp)
++ if (sp->cmd_sp) {
++ /*
++ * This done function should take care of
++ * original command ref: INIT
++ */
+ sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
++ }
+
+ abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
+ sp->done(sp, QLA_OS_TIMER_EXPIRED);
+@@ -140,11 +148,11 @@ static void qla24xx_abort_sp_done(srb_t *sp, int res)
+ if (orig_sp)
+ qla_wait_nvme_release_cmd_kref(orig_sp);
+
+- del_timer(&sp->u.iocb_cmd.timer);
+ if (sp->flags & SRB_WAKEUP_ON_COMP)
+ complete(&abt->u.abt.comp);
+ else
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+@@ -154,6 +162,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+
++ /* ref: INIT for ABTS command */
+ sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
+ GFP_ATOMIC);
+ if (!sp)
+@@ -167,23 +176,22 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+ if (wait)
+ sp->flags = SRB_WAKEUP_ON_COMP;
+
+- abt_iocb->timeout = qla24xx_abort_iocb_timeout;
+ init_completion(&abt_iocb->u.abt.comp);
+ /* FW can send 2 x ABTS's timeout/20s */
+- qla2x00_init_timer(sp, 42);
++ qla2x00_init_async_sp(sp, 42, qla24xx_abort_sp_done);
++ sp->u.iocb_cmd.timeout = qla24xx_abort_iocb_timeout;
+
+ abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
+ abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id);
+
+- sp->done = qla24xx_abort_sp_done;
+-
+ ql_dbg(ql_dbg_async, vha, 0x507c,
+ "Abort command issued - hdl=%x, type=%x\n", cmd_sp->handle,
+ cmd_sp->type);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return rval;
+ }
+
+@@ -191,7 +199,8 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+ wait_for_completion(&abt_iocb->u.abt.comp);
+ rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
+ QLA_SUCCESS : QLA_ERR_FROM_FW;
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ return rval;
+@@ -286,10 +295,13 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res)
+ ea.iop[0] = lio->u.logio.iop[0];
+ ea.iop[1] = lio->u.logio.iop[1];
+ ea.sp = sp;
++ if (res)
++ ea.data[0] = MBS_COMMAND_ERROR;
+ qla24xx_handle_plogi_done_event(vha, &ea);
+ }
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int
+@@ -308,6 +320,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
+ return rval;
+ }
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+@@ -320,12 +333,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
+ sp->name = "login";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_login_sp_done);
+
+ lio = &sp->u.iocb_cmd;
+- lio->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+-
+- sp->done = qla2x00_async_login_sp_done;
+ if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) {
+ lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY;
+ } else {
+@@ -359,7 +370,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ done:
+ fcport->flags &= ~FCF_ASYNC_ACTIVE;
+@@ -371,29 +383,26 @@ static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
+ sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ sp->fcport->login_gen++;
+ qlt_logo_completion_handler(sp->fcport, sp->u.iocb_cmd.u.logio.data[0]);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int
+ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+ srb_t *sp;
+- struct srb_iocb *lio;
+ int rval = QLA_FUNCTION_FAILED;
+
+ fcport->flags |= FCF_ASYNC_SENT;
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_LOGOUT_CMD;
+ sp->name = "logout";
+-
+- lio = &sp->u.iocb_cmd;
+- lio->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+-
+- sp->done = qla2x00_async_logout_sp_done;
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_logout_sp_done),
+
+ ql_dbg(ql_dbg_disc, vha, 0x2070,
+ "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC explicit %d.\n",
+@@ -407,7 +416,8 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ return rval;
+@@ -433,29 +443,26 @@ static void qla2x00_async_prlo_sp_done(srb_t *sp, int res)
+ if (!test_bit(UNLOADING, &vha->dpc_flags))
+ qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
+ lio->u.logio.data);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int
+ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+ srb_t *sp;
+- struct srb_iocb *lio;
+ int rval;
+
+ rval = QLA_FUNCTION_FAILED;
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_PRLO_CMD;
+ sp->name = "prlo";
+-
+- lio = &sp->u.iocb_cmd;
+- lio->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+-
+- sp->done = qla2x00_async_prlo_sp_done;
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_prlo_sp_done);
+
+ ql_dbg(ql_dbg_disc, vha, 0x2070,
+ "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+@@ -469,7 +476,8 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ fcport->flags &= ~FCF_ASYNC_ACTIVE;
+ return rval;
+@@ -552,10 +560,12 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
+ ea.iop[1] = lio->u.logio.iop[1];
+ ea.fcport = sp->fcport;
+ ea.sp = sp;
++ if (res)
++ ea.data[0] = MBS_COMMAND_ERROR;
+
+ qla24xx_handle_adisc_event(vha, &ea);
+-
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int
+@@ -566,26 +576,34 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
+ struct srb_iocb *lio;
+ int rval = QLA_FUNCTION_FAILED;
+
++ if (IS_SESSION_DELETED(fcport)) {
++ ql_log(ql_log_warn, vha, 0xffff,
++ "%s: %8phC is being delete - not sending command.\n",
++ __func__, fcport->port_name);
++ fcport->flags &= ~FCF_ASYNC_ACTIVE;
++ return rval;
++ }
++
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ return rval;
+
+ fcport->flags |= FCF_ASYNC_SENT;
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_ADISC_CMD;
+ sp->name = "adisc";
+-
+- lio = &sp->u.iocb_cmd;
+- lio->timeout = qla2x00_async_iocb_timeout;
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_adisc_sp_done);
+
+- sp->done = qla2x00_async_adisc_sp_done;
+- if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
++ if (data[1] & QLA_LOGIO_LOGIN_RETRIED) {
++ lio = &sp->u.iocb_cmd;
+ lio->u.logio.flags |= SRB_LOGIN_RETRIED;
++ }
+
+ ql_dbg(ql_dbg_disc, vha, 0x206f,
+ "Async-adisc - hdl=%x loopid=%x portid=%06x %8phC.\n",
+@@ -598,7 +616,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ qla2x00_post_async_adisc_work(vha, fcport, data);
+@@ -964,6 +983,9 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ }
+ break;
++ case ISP_CFG_NL:
++ qla24xx_fcport_handle_login(vha, fcport);
++ break;
+ default:
+ break;
+ }
+@@ -987,8 +1009,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
sp->u.iocb_cmd.u.mbx.in_mb[2]);
@@ -105342,7 +156404,7 @@ index 5fc7697f0af4c..847a6e5d9cb07 100644
sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
memset(&ea, 0, sizeof(ea));
-@@ -1026,8 +1024,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
+@@ -1026,8 +1046,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
@@ -105352,7 +156414,205 @@ index 5fc7697f0af4c..847a6e5d9cb07 100644
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
ea.fcport = fcport;
-@@ -1786,16 +1784,52 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+@@ -1081,13 +1101,13 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
+ }
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+ srb_t *sp;
+- struct srb_iocb *mbx;
+ int rval = QLA_FUNCTION_FAILED;
+ unsigned long flags;
+ u16 *mb;
+@@ -1112,6 +1132,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ vha->gnl.sent = 1;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+@@ -1120,10 +1141,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ sp->name = "gnlist";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- mbx = &sp->u.iocb_cmd;
+- mbx->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla24xx_async_gnl_sp_done);
+
+ mb = sp->u.iocb_cmd.u.mbx.out_mb;
+ mb[0] = MBC_PORT_NODE_NAME_LIST;
+@@ -1135,8 +1154,6 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ mb[8] = vha->gnl.size;
+ mb[9] = vha->vp_idx;
+
+- sp->done = qla24xx_async_gnl_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0x20da,
+ "Async-%s - OUT WWPN %8phC hndl %x\n",
+ sp->name, fcport->port_name, sp->handle);
+@@ -1148,7 +1165,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
+ return rval;
+@@ -1194,7 +1212,7 @@ done:
+ dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
+ sp->u.iocb_cmd.u.mbx.in_dma);
+
+- sp->free(sp);
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+@@ -1235,11 +1253,13 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
+ ea.sp = sp;
+ if (res == QLA_OS_TIMER_EXPIRED)
+ ea.data[0] = QLA_OS_TIMER_EXPIRED;
++ else if (res)
++ ea.data[0] = MBS_COMMAND_ERROR;
+
+ qla24xx_handle_prli_done_event(vha, &ea);
+ }
+
+- sp->free(sp);
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int
+@@ -1272,12 +1292,10 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
+
+ sp->type = SRB_PRLI_CMD;
+ sp->name = "prli";
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_prli_sp_done);
+
+ lio = &sp->u.iocb_cmd;
+- lio->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+-
+- sp->done = qla2x00_async_prli_sp_done;
+ lio->u.logio.flags = 0;
+
+ if (NVME_TARGET(vha->hw, fcport))
+@@ -1299,7 +1317,8 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+ }
+@@ -1328,14 +1347,21 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+ struct port_database_24xx *pd;
+ struct qla_hw_data *ha = vha->hw;
+
+- if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
+- fcport->loop_id == FC_NO_LOOP_ID) {
++ if (IS_SESSION_DELETED(fcport)) {
+ ql_log(ql_log_warn, vha, 0xffff,
+- "%s: %8phC - not sending command.\n",
+- __func__, fcport->port_name);
++ "%s: %8phC is being delete - not sending command.\n",
++ __func__, fcport->port_name);
++ fcport->flags &= ~FCF_ASYNC_ACTIVE;
+ return rval;
+ }
+
++ if (!vha->flags.online || fcport->flags & FCF_ASYNC_SENT) {
++ ql_log(ql_log_warn, vha, 0xffff,
++ "%s: %8phC online %d flags %x - not sending command.\n",
++ __func__, fcport->port_name, vha->flags.online, fcport->flags);
++ goto done;
++ }
++
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+@@ -1347,10 +1373,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+ sp->name = "gpdb";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+-
+- mbx = &sp->u.iocb_cmd;
+- mbx->timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla24xx_async_gpdb_sp_done);
+
+ pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
+ if (pd == NULL) {
+@@ -1369,11 +1393,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+ mb[9] = vha->vp_idx;
+ mb[10] = opt;
+
+- mbx->u.mbx.in = pd;
++ mbx = &sp->u.iocb_cmd;
++ mbx->u.mbx.in = (void *)pd;
+ mbx->u.mbx.in_dma = pd_dma;
+
+- sp->done = qla24xx_async_gpdb_sp_done;
+-
+ ql_dbg(ql_dbg_disc, vha, 0x20dc,
+ "Async-%s %8phC hndl %x opt %x\n",
+ sp->name, fcport->port_name, sp->handle, opt);
+@@ -1387,7 +1410,7 @@ done_free_sp:
+ if (pd)
+ dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+
+- sp->free(sp);
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ done:
+ fcport->flags &= ~FCF_ASYNC_ACTIVE;
+@@ -1559,6 +1582,11 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+ u8 login = 0;
+ int rc;
+
++ ql_dbg(ql_dbg_disc, vha, 0x307b,
++ "%s %8phC DS %d LS %d lid %d retries=%d\n",
++ __func__, fcport->port_name, fcport->disc_state,
++ fcport->fw_login_state, fcport->loop_id, fcport->login_retry);
++
+ if (qla_tgt_mode_enabled(vha))
+ return;
+
+@@ -1617,7 +1645,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+ fcport->login_gen, fcport->loop_id, fcport->scan_state,
+ fcport->fc4_type);
+
+- if (fcport->scan_state != QLA_FCPORT_FOUND)
++ if (fcport->scan_state != QLA_FCPORT_FOUND ||
++ fcport->disc_state == DSC_DELETE_PEND)
+ return 0;
+
+ if ((fcport->loop_id != FC_NO_LOOP_ID) &&
+@@ -1638,7 +1667,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+ if (vha->host->active_mode == MODE_TARGET && !N2N_TOPO(vha->hw))
+ return 0;
+
+- if (fcport->flags & FCF_ASYNC_SENT) {
++ if (fcport->flags & (FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE)) {
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ return 0;
+ }
+@@ -1786,16 +1815,52 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
fc_port_t *fcport;
unsigned long flags;
@@ -105414,7 +156674,117 @@ index 5fc7697f0af4c..847a6e5d9cb07 100644
}
spin_lock_irqsave(&vha->work_lock, flags);
-@@ -4433,6 +4467,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+@@ -1917,22 +1982,21 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+- tm_iocb = &sp->u.iocb_cmd;
+ sp->type = SRB_TM_CMD;
+ sp->name = "tmf";
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha),
++ qla2x00_tmf_sp_done);
++ sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
+
+- tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
++ tm_iocb = &sp->u.iocb_cmd;
+ init_completion(&tm_iocb->u.tmf.comp);
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
+-
+ tm_iocb->u.tmf.flags = flags;
+ tm_iocb->u.tmf.lun = lun;
+- tm_iocb->u.tmf.data = tag;
+- sp->done = qla2x00_tmf_sp_done;
+
+ ql_dbg(ql_dbg_taskm, vha, 0x802f,
+ "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+@@ -1962,7 +2026,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
+ }
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ done:
+ return rval;
+@@ -2021,13 +2086,6 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
+ qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ break;
+ default:
+- if ((ea->iop[0] == LSC_SCODE_ELS_REJECT) &&
+- (ea->iop[1] == 0x50000)) { /* reson 5=busy expl:0x0 */
+- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+- ea->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
+- break;
+- }
+-
+ sp = ea->sp;
+ ql_dbg(ql_dbg_disc, vha, 0x2118,
+ "%s %d %8phC priority %s, fc4type %x prev try %s\n",
+@@ -2171,12 +2229,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
+ ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
+ __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
+
+- ea->fcport->flags &= ~FCF_ASYNC_SENT;
+- qla2x00_set_fcport_disc_state(ea->fcport, DSC_LOGIN_FAILED);
+- if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
+- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+- else
+- qla2x00_mark_device_lost(vha, ea->fcport, 1);
++ qlt_schedule_sess_for_deletion(ea->fcport);
+ break;
+ case MBS_LOOP_ID_USED:
+ /* data[1] = IO PARAM 1 = nport ID */
+@@ -3419,6 +3472,14 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ struct rsp_que *rsp = ha->rsp_q_map[0];
+ struct qla2xxx_fw_dump *fw_dump;
+
++ if (ha->fw_dump) {
++ ql_dbg(ql_dbg_init, vha, 0x00bd,
++ "Firmware dump already allocated.\n");
++ return;
++ }
++
++ ha->fw_dumped = 0;
++ ha->fw_dump_cap_flags = 0;
+ dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
+ req_q_size = rsp_q_size = 0;
+
+@@ -3429,7 +3490,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ mem_size = (ha->fw_memory_size - 0x11000 + 1) *
+ sizeof(uint16_t);
+ } else if (IS_FWI2_CAPABLE(ha)) {
+- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
++ if (IS_QLA83XX(ha))
+ fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
+ else if (IS_QLA81XX(ha))
+ fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
+@@ -3441,8 +3502,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ mem_size = (ha->fw_memory_size - 0x100000 + 1) *
+ sizeof(uint32_t);
+ if (ha->mqenable) {
+- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) &&
+- !IS_QLA28XX(ha))
++ if (!IS_QLA83XX(ha))
+ mq_size = sizeof(struct qla2xxx_mq_chain);
+ /*
+ * Allocate maximum buffer size for all queues - Q0.
+@@ -4003,8 +4063,7 @@ enable_82xx_npiv:
+ ha->fw_major_version, ha->fw_minor_version,
+ ha->fw_subminor_version);
+
+- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+- IS_QLA28XX(ha)) {
++ if (IS_QLA83XX(ha)) {
+ ha->flags.fac_supported = 0;
+ rval = QLA_SUCCESS;
+ }
+@@ -4433,6 +4492,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
(ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
}
@@ -105425,7 +156795,7 @@ index 5fc7697f0af4c..847a6e5d9cb07 100644
rval = qla2x00_init_firmware(vha, ha->init_cb_size);
next_check:
if (rval) {
-@@ -5335,15 +5373,14 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
+@@ -5335,15 +5398,14 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
"LOOP READY.\n");
ha->flags.fw_init_done = 1;
@@ -105448,11 +156818,318 @@ index 5fc7697f0af4c..847a6e5d9cb07 100644
/*
* Process any ATIO queue entries that came in
+@@ -5547,6 +5609,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
+ memcpy(fcport->node_name, new_fcport->node_name,
+ WWN_SIZE);
+ fcport->scan_state = QLA_FCPORT_FOUND;
++ if (fcport->login_retry == 0) {
++ fcport->login_retry = vha->hw->login_retry_count;
++ ql_dbg(ql_dbg_disc, vha, 0x2135,
++ "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
++ fcport->port_name, fcport->loop_id,
++ fcport->login_retry);
++ }
+ found++;
+ break;
+ }
+@@ -5680,6 +5749,8 @@ 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 |
+@@ -5787,6 +5858,7 @@ 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);
+@@ -5801,8 +5873,6 @@ 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;
+@@ -9333,7 +9403,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
+ qpair->rsp->req = qpair->req;
+ qpair->rsp->qpair = qpair;
+ /* init qpair to this cpu. Will adjust at run time. */
+- qla_cpu_update(qpair, smp_processor_id());
++ qla_cpu_update(qpair, raw_smp_processor_id());
+
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
+ if (ha->fw_attributes & BIT_4)
+diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
+index 5f3b7995cc8f3..db17f7f410cdd 100644
+--- a/drivers/scsi/qla2xxx/qla_inline.h
++++ b/drivers/scsi/qla2xxx/qla_inline.h
+@@ -184,6 +184,8 @@ static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha,
+ sp->vha = vha;
+ sp->qpair = qpair;
+ sp->cmd_type = TYPE_SRB;
++ /* ref : INIT - normal flow */
++ kref_init(&sp->cmd_kref);
+ INIT_LIST_HEAD(&sp->elem);
+ }
+
+diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
+index 9d4ad1d2b00a2..606228f4a8b53 100644
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -2560,11 +2560,38 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
+ }
+ }
+
+-void qla2x00_init_timer(srb_t *sp, unsigned long tmo)
++static void
++qla2x00_async_done(struct srb *sp, int res)
++{
++ if (del_timer(&sp->u.iocb_cmd.timer)) {
++ /*
++ * Successfully cancelled the timeout handler
++ * ref: TMR
++ */
++ if (kref_put(&sp->cmd_kref, qla2x00_sp_release))
++ return;
++ }
++ sp->async_done(sp, res);
++}
++
++void
++qla2x00_sp_release(struct kref *kref)
++{
++ struct srb *sp = container_of(kref, struct srb, cmd_kref);
++
++ sp->free(sp);
++}
++
++void
++qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
++ void (*done)(struct srb *sp, int res))
+ {
+ timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0);
+- sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
++ sp->done = qla2x00_async_done;
++ sp->async_done = done;
+ sp->free = qla2x00_sp_free;
++ sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
++ sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
+ if (IS_QLAFX00(sp->vha->hw) && sp->type == SRB_FXIOCB_DCMD)
+ init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
+ sp->start_timer = 1;
+@@ -2651,7 +2678,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+ return -ENOMEM;
+ }
+
+- /* Alloc SRB structure */
++ /* Alloc SRB structure
++ * ref: INIT
++ */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ kfree(fcport);
+@@ -2672,18 +2701,19 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+ sp->type = SRB_ELS_DCMD;
+ sp->name = "ELS_DCMD";
+ sp->fcport = fcport;
+- elsio->timeout = qla2x00_els_dcmd_iocb_timeout;
+- qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+- init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
+- sp->done = qla2x00_els_dcmd_sp_done;
++ qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT,
++ qla2x00_els_dcmd_sp_done);
+ sp->free = qla2x00_els_dcmd_sp_free;
++ sp->u.iocb_cmd.timeout = qla2x00_els_dcmd_iocb_timeout;
++ init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
+
+ elsio->u.els_logo.els_logo_pyld = dma_alloc_coherent(&ha->pdev->dev,
+ DMA_POOL_SIZE, &elsio->u.els_logo.els_logo_pyld_dma,
+ GFP_KERNEL);
+
+ if (!elsio->u.els_logo.els_logo_pyld) {
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return QLA_FUNCTION_FAILED;
+ }
+
+@@ -2706,7 +2736,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return QLA_FUNCTION_FAILED;
+ }
+
+@@ -2717,7 +2748,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+
+ wait_for_completion(&elsio->u.els_logo.comp);
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return rval;
+ }
+
+@@ -2850,7 +2882,6 @@ 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);
+- del_timer(&sp->u.iocb_cmd.timer);
+
+ if (sp->flags & SRB_WAKEUP_ON_COMP)
+ complete(&lio->u.els_plogi.comp);
+@@ -2927,6 +2958,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
+ set_bit(ISP_ABORT_NEEDED,
+ &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
++ break;
+ }
+ fallthrough;
+ default:
+@@ -2936,9 +2968,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
+ fw_status[0], fw_status[1], fw_status[2]);
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+- qla2x00_set_fcport_disc_state(fcport,
+- DSC_LOGIN_FAILED);
+- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
++ qlt_schedule_sess_for_deletion(fcport);
+ break;
+ }
+ break;
+@@ -2950,8 +2980,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
+ fw_status[0], fw_status[1], fw_status[2]);
+
+ sp->fcport->flags &= ~FCF_ASYNC_SENT;
+- qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_FAILED);
+- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
++ qlt_schedule_sess_for_deletion(fcport);
+ break;
+ }
+
+@@ -2960,7 +2989,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
+ struct srb_iocb *elsio = &sp->u.iocb_cmd;
+
+ qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return;
+ }
+ e->u.iosb.sp = sp;
+@@ -2978,7 +3008,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ int rval = QLA_SUCCESS;
+ void *ptr, *resp_ptr;
+
+- /* Alloc SRB structure */
++ /* Alloc SRB structure
++ * ref: INIT
++ */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ ql_log(ql_log_info, vha, 0x70e6,
+@@ -2993,17 +3025,16 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ ql_dbg(ql_dbg_io, vha, 0x3073,
+ "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24);
+
+- sp->type = SRB_ELS_DCMD;
+- sp->name = "ELS_DCMD";
+- sp->fcport = fcport;
+-
+- elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
+ if (wait)
+ sp->flags = SRB_WAKEUP_ON_COMP;
+
+- qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT + 2);
++ sp->type = SRB_ELS_DCMD;
++ sp->name = "ELS_DCMD";
++ sp->fcport = fcport;
++ qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT + 2,
++ qla2x00_els_dcmd2_sp_done);
++ sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout;
+
+- sp->done = qla2x00_els_dcmd2_sp_done;
+ elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE;
+
+ ptr = elsio->u.els_plogi.els_plogi_pyld =
+@@ -3069,7 +3100,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ out:
+ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+@@ -3880,8 +3912,15 @@ qla2x00_start_sp(srb_t *sp)
+ break;
+ }
+
+- if (sp->start_timer)
++ if (sp->start_timer) {
++ /* ref: TMR timer ref
++ * this code should be just before start_iocbs function
++ * This will make sure that caller function don't to do
++ * kref_put even on failure
++ */
++ kref_get(&sp->cmd_kref);
+ add_timer(&sp->u.iocb_cmd.timer);
++ }
+
+ wmb();
+ qla2x00_start_iocbs(vha, qp->req);
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index b26f2699adb27..62d2f14848e7b 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -2494,6 +2494,7 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
+ iocb->u.tmf.data = QLA_FUNCTION_FAILED;
+ } else if ((le16_to_cpu(sts->scsi_status) &
+ SS_RESPONSE_INFO_LEN_VALID)) {
++ host_to_fcp_swap(sts->data, sizeof(sts->data));
+ if (le32_to_cpu(sts->rsp_data_len) < 4) {
+ ql_log(ql_log_warn, fcport->vha, 0x503b,
+ "Async-%s error - hdl=%x not enough response(%d).\n",
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
-index 7811c4952035b..a6debeea30798 100644
+index 7811c4952035b..950c5903e7992 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
-@@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
+@@ -9,6 +9,12 @@
+ #include <linux/delay.h>
+ #include <linux/gfp.h>
+
++#ifdef CONFIG_PPC
++#define IS_PPCARCH true
++#else
++#define IS_PPCARCH false
++#endif
++
+ static struct mb_cmd_name {
+ uint16_t cmd;
+ const char *str;
+@@ -728,6 +734,9 @@ again:
+ vha->min_supported_speed =
+ nv->min_supported_speed;
+ }
++
++ if (IS_PPCARCH)
++ mcp->mb[11] |= BIT_4;
+ }
+
+ if (ha->flags.exlogins_enabled)
+@@ -1695,10 +1704,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
if (IS_FWI2_CAPABLE(vha->hw))
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
@@ -105465,8 +157142,99 @@ index 7811c4952035b..a6debeea30798 100644
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
+@@ -3031,8 +3038,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
+ ha->orig_fw_iocb_count = mcp->mb[10];
+ if (ha->flags.npiv_supported)
+ ha->max_npiv_vports = mcp->mb[11];
+- if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+- IS_QLA28XX(ha))
++ if (IS_QLA81XX(ha) || IS_QLA83XX(ha))
+ ha->fw_max_fcf_count = mcp->mb[12];
+ }
+
+@@ -5623,7 +5629,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+- mcp->in_mb |= MBX_3;
++ mcp->in_mb |= MBX_4|MBX_3;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+@@ -6481,23 +6487,21 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
+ if (!vha->hw->flags.fw_started)
+ goto done;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+- sp->type = SRB_MB_IOCB;
+- sp->name = mb_to_str(mcp->mb[0]);
+-
+ c = &sp->u.iocb_cmd;
+- c->timeout = qla2x00_async_iocb_timeout;
+ init_completion(&c->u.mbx.comp);
+
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ sp->type = SRB_MB_IOCB;
++ sp->name = mb_to_str(mcp->mb[0]);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_mb_sp_done);
+
+ memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
+
+- sp->done = qla2x00_async_mb_sp_done;
+-
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1018,
+@@ -6529,7 +6533,8 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
+ }
+
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
+index 1c024055f8c50..e6b5c4ccce97b 100644
+--- a/drivers/scsi/qla2xxx/qla_mid.c
++++ b/drivers/scsi/qla2xxx/qla_mid.c
+@@ -965,6 +965,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
+ if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
+ return QLA_PARAMETER_ERROR;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
+ if (!sp)
+ return rval;
+@@ -972,9 +973,8 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
+ sp->type = SRB_CTRL_VP;
+ sp->name = "ctrl_vp";
+ sp->comp = &comp;
+- sp->done = qla_ctrlvp_sp_done;
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla_ctrlvp_sp_done);
+ sp->u.iocb_cmd.u.ctrlvp.cmd = cmd;
+ sp->u.iocb_cmd.u.ctrlvp.vp_index = vp_index;
+
+@@ -1008,6 +1008,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
+ break;
+ }
+ done:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ return rval;
+ }
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
-index 6e920da64863e..350b0c4346fb6 100644
+index 6e920da64863e..f726eb8449c5e 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -738,29 +738,6 @@ qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag)
@@ -105499,11 +157267,91 @@ index 6e920da64863e..350b0c4346fb6 100644
int
qlafx00_iospace_config(struct qla_hw_data *ha)
{
+@@ -1810,17 +1787,18 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
+ struct register_host_info *preg_hsi;
+ struct new_utsname *p_sysid = NULL;
+
++ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_FXIOCB_DCMD;
+ sp->name = "fxdisc";
++ qla2x00_init_async_sp(sp, FXDISC_TIMEOUT,
++ qla2x00_fxdisc_sp_done);
++ sp->u.iocb_cmd.timeout = qla2x00_fxdisc_iocb_timeout;
+
+ fdisc = &sp->u.iocb_cmd;
+- fdisc->timeout = qla2x00_fxdisc_iocb_timeout;
+- qla2x00_init_timer(sp, FXDISC_TIMEOUT);
+-
+ switch (fx_type) {
+ case FXDISC_GET_CONFIG_INFO:
+ fdisc->u.fxiocb.flags =
+@@ -1921,7 +1899,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
+ }
+
+ fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type);
+- sp->done = qla2x00_fxdisc_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+@@ -1997,7 +1974,8 @@ done_unmap_req:
+ dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
+ fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
+ done_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ return rval;
+ }
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
-index 1c5da2dbd6f97..877b2b6250204 100644
+index 1c5da2dbd6f97..42b29f4fd9371 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
-@@ -228,6 +228,8 @@ static void qla_nvme_abort_work(struct work_struct *work)
+@@ -35,6 +35,11 @@ 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));
+@@ -165,6 +170,18 @@ out:
+ qla2xxx_rel_qpair_sp(sp->qpair, sp);
+ }
+
++static void qla_nvme_ls_unmap(struct srb *sp, struct nvmefc_ls_req *fd)
++{
++ if (sp->flags & SRB_DMA_VALID) {
++ struct srb_iocb *nvme = &sp->u.iocb_cmd;
++ struct qla_hw_data *ha = sp->fcport->vha->hw;
++
++ dma_unmap_single(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
++ fd->rqstlen, DMA_TO_DEVICE);
++ sp->flags &= ~SRB_DMA_VALID;
++ }
++}
++
+ static void qla_nvme_release_ls_cmd_kref(struct kref *kref)
+ {
+ struct srb *sp = container_of(kref, struct srb, cmd_kref);
+@@ -181,6 +198,8 @@ static void qla_nvme_release_ls_cmd_kref(struct kref *kref)
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+
+ fd = priv->fd;
++
++ qla_nvme_ls_unmap(sp, fd);
+ fd->done(fd, priv->comp_status);
+ out:
+ qla2x00_rel_sp(sp);
+@@ -228,6 +247,8 @@ static void qla_nvme_abort_work(struct work_struct *work)
fc_port_t *fcport = sp->fcport;
struct qla_hw_data *ha = fcport->vha->hw;
int rval, abts_done_called = 1;
@@ -105512,7 +157360,7 @@ index 1c5da2dbd6f97..877b2b6250204 100644
ql_dbg(ql_dbg_io, fcport->vha, 0xffff,
"%s called for sp=%p, hndl=%x on fcport=%p desc=%p deleted=%d\n",
-@@ -244,12 +246,20 @@ static void qla_nvme_abort_work(struct work_struct *work)
+@@ -244,12 +265,20 @@ static void qla_nvme_abort_work(struct work_struct *work)
goto out;
}
@@ -105534,7 +157382,7 @@ index 1c5da2dbd6f97..877b2b6250204 100644
/*
* If async tmf is enabled, the abort callback is called only on
-@@ -264,7 +274,7 @@ static void qla_nvme_abort_work(struct work_struct *work)
+@@ -264,7 +293,7 @@ static void qla_nvme_abort_work(struct work_struct *work)
* are waited until ABTS complete. This kref is decreased
* at qla24xx_abort_sp_done function.
*/
@@ -105543,8 +157391,25 @@ index 1c5da2dbd6f97..877b2b6250204 100644
return;
out:
/* kref_get was done before work was schedule. */
+@@ -341,6 +370,8 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
+ dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
+ fd->rqstlen, DMA_TO_DEVICE);
+
++ sp->flags |= SRB_DMA_VALID;
++
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x700e,
+@@ -348,6 +379,7 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
+ wake_up(&sp->nvme_ls_waitq);
+ sp->priv = NULL;
+ priv->sp = NULL;
++ qla_nvme_ls_unmap(sp, fd);
+ qla2x00_rel_sp(sp);
+ return rval;
+ }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
-index 836fedcea241b..8d87cfae9c598 100644
+index 836fedcea241b..77c0bf06f162b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -202,12 +202,6 @@ MODULE_PARM_DESC(ql2xdbwr,
@@ -105560,7 +157425,63 @@ index 836fedcea241b..8d87cfae9c598 100644
int ql2xgffidenable;
module_param(ql2xgffidenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xgffidenable,
-@@ -1258,6 +1252,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+@@ -734,7 +728,8 @@ void qla2x00_sp_compl(srb_t *sp, int res)
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ struct completion *comp = sp->comp;
+
+- sp->free(sp);
++ /* kref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ cmd->result = res;
+ CMD_SP(cmd) = NULL;
+ cmd->scsi_done(cmd);
+@@ -825,7 +820,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ struct completion *comp = sp->comp;
+
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ cmd->result = res;
+ CMD_SP(cmd) = NULL;
+ cmd->scsi_done(cmd);
+@@ -925,6 +921,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+ goto qc24_target_busy;
+
+ sp = scsi_cmd_priv(cmd);
++ /* ref: INIT */
+ qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
+
+ sp->u.scmd.cmd = cmd;
+@@ -944,7 +941,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+ return 0;
+
+ qc24_host_busy_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+
+ qc24_target_busy:
+ return SCSI_MLQUEUE_TARGET_BUSY;
+@@ -1014,6 +1012,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
+ goto qc24_target_busy;
+
+ sp = scsi_cmd_priv(cmd);
++ /* ref: INIT */
+ qla2xxx_init_sp(sp, vha, qpair, fcport);
+
+ sp->u.scmd.cmd = cmd;
+@@ -1032,7 +1031,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
+ return 0;
+
+ qc24_host_busy_free_sp:
+- sp->free(sp);
++ /* ref: INIT */
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+
+ qc24_target_busy:
+ return SCSI_MLQUEUE_TARGET_BUSY;
+@@ -1258,6 +1258,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
uint32_t ratov_j;
struct qla_qpair *qpair;
unsigned long flags;
@@ -105568,7 +157489,7 @@ index 836fedcea241b..8d87cfae9c598 100644
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8042,
-@@ -1266,9 +1261,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+@@ -1266,9 +1267,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
return FAILED;
}
@@ -105580,7 +157501,7 @@ index 836fedcea241b..8d87cfae9c598 100644
sp = scsi_cmd_priv(cmd);
qpair = sp->qpair;
-@@ -1276,7 +1272,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+@@ -1276,7 +1278,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
vha->cmd_timeout_cnt++;
if ((sp->fcport && sp->fcport->deleted) || !qpair)
@@ -105589,7 +157510,7 @@ index 836fedcea241b..8d87cfae9c598 100644
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
sp->comp = &comp;
-@@ -1311,7 +1307,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+@@ -1311,7 +1313,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
__func__, ha->r_a_tov/10);
ret = FAILED;
} else {
@@ -105598,7 +157519,7 @@ index 836fedcea241b..8d87cfae9c598 100644
}
break;
default:
-@@ -1693,27 +1689,10 @@ int
+@@ -1693,27 +1695,10 @@ int
qla2x00_loop_reset(scsi_qla_host_t *vha)
{
int ret;
@@ -105628,7 +157549,17 @@ index 836fedcea241b..8d87cfae9c598 100644
if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {
atomic_set(&vha->loop_state, LOOP_DOWN);
-@@ -4358,7 +4337,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
+@@ -3754,8 +3739,7 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha)
+ if (ha->mqiobase)
+ iounmap(ha->mqiobase);
+
+- if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
+- ha->msixbase)
++ if (ha->msixbase)
+ iounmap(ha->msixbase);
+ }
+ }
+@@ -4358,7 +4342,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
/* allocate the purex dma pool */
ha->purex_dma_pool = dma_pool_create(name, &ha->pdev->dev,
@@ -105637,11 +157568,112 @@ index 836fedcea241b..8d87cfae9c598 100644
if (!ha->purex_dma_pool) {
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b,
+@@ -5532,6 +5516,11 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
+ memset(&ea, 0, sizeof(ea));
+ ea.fcport = fcport;
+ qla24xx_handle_relogin_event(vha, &ea);
++ } else if (vha->hw->current_topology ==
++ ISP_CFG_NL &&
++ IS_QLA2XXX_MIDTYPE(vha->hw)) {
++ (void)qla24xx_fcport_handle_login(vha,
++ fcport);
+ } else if (vha->hw->current_topology ==
+ ISP_CFG_NL) {
+ fcport->login_retry--;
+@@ -7656,7 +7645,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+
+ switch (state) {
+ case pci_channel_io_normal:
+- ha->flags.eeh_busy = 0;
++ qla_pci_set_eeh_busy(vha);
+ if (ql2xmqsupport || ql2xnvmeenable) {
+ set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+@@ -7697,9 +7686,16 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
+ "mmio enabled\n");
+
+ ha->pci_error_state = QLA_PCI_MMIO_ENABLED;
++
+ if (IS_QLA82XX(ha))
+ return PCI_ERS_RESULT_RECOVERED;
+
++ if (qla2x00_isp_reg_stat(ha)) {
++ ql_log(ql_log_info, base_vha, 0x803f,
++ "During mmio enabled, PCI/Register disconnect still detected.\n");
++ goto out;
++ }
++
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ if (IS_QLA2100(ha) || IS_QLA2200(ha)){
+ stat = rd_reg_word(&reg->hccr);
+@@ -7721,6 +7717,7 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
+ "RISC paused -- mmio_enabled, Dumping firmware.\n");
+ qla2xxx_dump_fw(base_vha);
+ }
++out:
+ /* set PCI_ERS_RESULT_NEED_RESET to trigger call to qla2xxx_pci_slot_reset */
+ ql_dbg(ql_dbg_aer, base_vha, 0x600d,
+ "mmio enabled returning.\n");
+diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
+index a0aeba69513d4..c092a6b1ced4f 100644
+--- a/drivers/scsi/qla2xxx/qla_sup.c
++++ b/drivers/scsi/qla2xxx/qla_sup.c
+@@ -844,7 +844,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
+ ha->flt_region_nvram = start;
+ break;
+ case FLT_REG_IMG_PRI_27XX:
+- if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
++ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ ha->flt_region_img_status_pri = start;
+ break;
+ case FLT_REG_IMG_SEC_27XX:
+@@ -1356,7 +1356,7 @@ next:
+ flash_data_addr(ha, faddr), le32_to_cpu(*dwptr));
+ if (ret) {
+ ql_dbg(ql_dbg_user, vha, 0x7006,
+- "Failed slopw write %x (%x)\n", faddr, *dwptr);
++ "Failed slow write %x (%x)\n", faddr, *dwptr);
+ break;
+ }
+ }
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
-index 7d8242c120fc7..1aaa4238cb722 100644
+index 7d8242c120fc7..ae5eaa4a9283a 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
-@@ -1003,6 +1003,7 @@ void qlt_free_session_done(struct work_struct *work)
+@@ -620,7 +620,7 @@ static void qla2x00_async_nack_sp_done(srb_t *sp, int res)
+ }
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+- sp->free(sp);
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+
+ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
+@@ -656,12 +656,10 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
+
+ sp->type = type;
+ sp->name = "nack";
+-
+- sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+- qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
++ qla2x00_async_nack_sp_done);
+
+ sp->u.iocb_cmd.u.nack.ntfy = ntfy;
+- sp->done = qla2x00_async_nack_sp_done;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20f4,
+ "Async-%s %8phC hndl %x %s\n",
+@@ -674,7 +672,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
+ return rval;
+
+ done_free_sp:
+- sp->free(sp);
++ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+@@ -1003,6 +1001,7 @@ void qlt_free_session_done(struct work_struct *work)
"%s bypassing release_all_sadb\n",
__func__);
}
@@ -105649,6 +157681,54 @@ index 7d8242c120fc7..1aaa4238cb722 100644
qla_edif_sess_down(vha, sess);
}
qla2x00_mark_device_lost(vha, sess, 0);
+@@ -3319,6 +3318,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
+ "RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
+ vha->flags.online, qla2x00_reset_active(vha),
+ cmd->reset_count, qpair->chip_reset);
++ res = 0;
+ goto out_unmap_unlock;
+ }
+
+@@ -3837,6 +3837,9 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
+
+ spin_lock_irqsave(&cmd->cmd_lock, flags);
+ if (cmd->aborted) {
++ if (cmd->sg_mapped)
++ qlt_unmap_sg(vha, cmd);
++
+ spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+ /*
+ * It's normal to see 2 calls in this path:
+@@ -7220,8 +7223,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
+
+- if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+- IS_QLA28XX(ha)) {
++ if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
+ ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
+ } else {
+diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
+index 26c13a953b975..b0a74b036cf4b 100644
+--- a/drivers/scsi/qla2xxx/qla_tmpl.c
++++ b/drivers/scsi/qla2xxx/qla_tmpl.c
+@@ -435,8 +435,13 @@ qla27xx_fwdt_entry_t266(struct scsi_qla_host *vha,
+ {
+ ql_dbg(ql_dbg_misc, vha, 0xd20a,
+ "%s: reset risc [%lx]\n", __func__, *len);
+- if (buf)
+- WARN_ON_ONCE(qla24xx_soft_reset(vha->hw) != QLA_SUCCESS);
++ if (buf) {
++ if (qla24xx_soft_reset(vha->hw) != QLA_SUCCESS) {
++ ql_dbg(ql_dbg_async, vha, 0x5001,
++ "%s: unable to soft reset\n", __func__);
++ return INVALID_ENTRY;
++ }
++ }
+
+ return qla27xx_next_entry(ent);
+ }
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 291ecc33b1fe6..4fc9466d820a7 100644
--- a/drivers/scsi/scsi.c
@@ -105905,7 +157985,7 @@ index d9109771f274d..db8517f1a485a 100644
#undef SCSI_CMD_FLAG_NAME
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
-index b6c86cce57bfa..408d49c304b8d 100644
+index b6c86cce57bfa..bb5a6e0fa49ab 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -135,6 +135,23 @@ static bool scsi_eh_should_retry_cmd(struct scsi_cmnd *cmd)
@@ -105974,6 +158054,22 @@ index b6c86cce57bfa..408d49c304b8d 100644
spin_unlock_irqrestore(shost->host_lock, flags);
scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED;
+@@ -460,8 +485,13 @@ static void scsi_report_sense(struct scsi_device *sdev,
+
+ if (sshdr->asc == 0x29) {
+ evt_type = SDEV_EVT_POWER_ON_RESET_OCCURRED;
+- sdev_printk(KERN_WARNING, sdev,
+- "Power-on or device reset occurred\n");
++ /*
++ * Do not print message if it is an expected side-effect
++ * of runtime PM.
++ */
++ if (!sdev->silence_suspend)
++ sdev_printk(KERN_WARNING, sdev,
++ "Power-on or device reset occurred\n");
+ }
+
+ if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) {
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 6ff2207bd45a0..a06c61f22742e 100644
--- a/drivers/scsi/scsi_ioctl.c
@@ -106087,10 +158183,10 @@ index 3717eea37ecb3..e91a0a5bc7a3e 100644
return err;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
-index fe22191522a3b..7266880c70c21 100644
+index fe22191522a3b..9466474ff01b6 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
-@@ -198,6 +198,48 @@ static void scsi_unlock_floptical(struct scsi_device *sdev,
+@@ -198,6 +198,53 @@ static void scsi_unlock_floptical(struct scsi_device *sdev,
SCSI_TIMEOUT, 3, NULL);
}
@@ -106103,6 +158199,8 @@ index fe22191522a3b..7266880c70c21 100644
+ int ret;
+ struct sbitmap sb_backup;
+
++ depth = min_t(unsigned int, depth, scsi_device_max_queue_depth(sdev));
++
+ /*
+ * realloc if new shift is calculated, which is caused by setting
+ * up one new default queue depth after calling ->slave_configure
@@ -106125,6 +158223,9 @@ index fe22191522a3b..7266880c70c21 100644
+ scsi_device_max_queue_depth(sdev),
+ new_shift, GFP_KERNEL,
+ sdev->request_queue->node, false, true);
++ if (!ret)
++ sbitmap_resize(&sdev->budget_map, depth);
++
+ if (need_free) {
+ if (ret)
+ sdev->budget_map = sb_backup;
@@ -106139,7 +158240,7 @@ index fe22191522a3b..7266880c70c21 100644
/**
* scsi_alloc_sdev - allocate and setup a scsi_Device
* @starget: which target to allocate a &scsi_device for
-@@ -291,11 +333,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
+@@ -291,11 +338,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
* default device queue depth to figure out sbitmap shift
* since we use this queue depth most of times.
*/
@@ -106152,7 +158253,7 @@ index fe22191522a3b..7266880c70c21 100644
put_device(&starget->dev);
kfree(sdev);
goto out;
-@@ -1001,6 +1039,13 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
+@@ -1001,6 +1044,13 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
}
return SCSI_SCAN_NO_RESPONSE;
}
@@ -106225,11 +158326,240 @@ index a35841b34bfd9..920aae661c5b2 100644
sdev_printk(KERN_INFO, sdev,
"Failed to register bsg queue, errno=%d\n",
error);
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 60e406bcf42a9..a2524106206db 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -34,7 +34,7 @@ static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
+ static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
+ static void fc_bsg_remove(struct request_queue *);
+ static void fc_bsg_goose_queue(struct fc_rport *);
+-static void fc_li_stats_update(struct fc_fn_li_desc *li_desc,
++static void fc_li_stats_update(u16 event_type,
+ struct fc_fpin_stats *stats);
+ static void fc_delivery_stats_update(u32 reason_code,
+ struct fc_fpin_stats *stats);
+@@ -670,42 +670,34 @@ fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn)
+ EXPORT_SYMBOL(fc_find_rport_by_wwpn);
+
+ static void
+-fc_li_stats_update(struct fc_fn_li_desc *li_desc,
++fc_li_stats_update(u16 event_type,
+ struct fc_fpin_stats *stats)
+ {
+- stats->li += be32_to_cpu(li_desc->event_count);
+- switch (be16_to_cpu(li_desc->event_type)) {
++ stats->li++;
++ switch (event_type) {
+ case FPIN_LI_UNKNOWN:
+- stats->li_failure_unknown +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_failure_unknown++;
+ break;
+ case FPIN_LI_LINK_FAILURE:
+- stats->li_link_failure_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_link_failure_count++;
+ break;
+ case FPIN_LI_LOSS_OF_SYNC:
+- stats->li_loss_of_sync_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_loss_of_sync_count++;
+ break;
+ case FPIN_LI_LOSS_OF_SIG:
+- stats->li_loss_of_signals_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_loss_of_signals_count++;
+ break;
+ case FPIN_LI_PRIM_SEQ_ERR:
+- stats->li_prim_seq_err_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_prim_seq_err_count++;
+ break;
+ case FPIN_LI_INVALID_TX_WD:
+- stats->li_invalid_tx_word_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_invalid_tx_word_count++;
+ break;
+ case FPIN_LI_INVALID_CRC:
+- stats->li_invalid_crc_count +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_invalid_crc_count++;
+ break;
+ case FPIN_LI_DEVICE_SPEC:
+- stats->li_device_specific +=
+- be32_to_cpu(li_desc->event_count);
++ stats->li_device_specific++;
+ break;
+ }
+ }
+@@ -767,6 +759,7 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
+ struct fc_rport *attach_rport = NULL;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
++ u16 event_type = be16_to_cpu(li_desc->event_type);
+ u64 wwpn;
+
+ rport = fc_find_rport_by_wwpn(shost,
+@@ -775,7 +768,7 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
+ (rport->roles & FC_PORT_ROLE_FCP_TARGET ||
+ rport->roles & FC_PORT_ROLE_NVME_TARGET)) {
+ attach_rport = rport;
+- fc_li_stats_update(li_desc, &attach_rport->fpin_stats);
++ fc_li_stats_update(event_type, &attach_rport->fpin_stats);
+ }
+
+ if (be32_to_cpu(li_desc->pname_count) > 0) {
+@@ -789,14 +782,14 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
+ rport->roles & FC_PORT_ROLE_NVME_TARGET)) {
+ if (rport == attach_rport)
+ continue;
+- fc_li_stats_update(li_desc,
++ fc_li_stats_update(event_type,
+ &rport->fpin_stats);
+ }
+ }
+ }
+
+ if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn))
+- fc_li_stats_update(li_desc, &fc_host->fpin_stats);
++ fc_li_stats_update(event_type, &fc_host->fpin_stats);
+ }
+
+ /*
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
-index 78343d3f93857..554b6f7842236 100644
+index 78343d3f93857..bcdfcb25349ad 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
-@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work)
+@@ -86,6 +86,9 @@ struct iscsi_internal {
+ struct transport_container session_cont;
+ };
+
++static DEFINE_IDR(iscsi_ep_idr);
++static DEFINE_MUTEX(iscsi_ep_idr_mutex);
++
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+ static struct workqueue_struct *iscsi_eh_timer_workq;
+
+@@ -169,6 +172,11 @@ struct device_attribute dev_attr_##_prefix##_##_name = \
+ static void iscsi_endpoint_release(struct device *dev)
+ {
+ struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
++
++ mutex_lock(&iscsi_ep_idr_mutex);
++ idr_remove(&iscsi_ep_idr, ep->id);
++ mutex_unlock(&iscsi_ep_idr_mutex);
++
+ kfree(ep);
+ }
+
+@@ -181,7 +189,7 @@ static ssize_t
+ show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+- return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id);
++ return sysfs_emit(buf, "%d\n", ep->id);
+ }
+ static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
+
+@@ -194,48 +202,32 @@ static struct attribute_group iscsi_endpoint_group = {
+ .attrs = iscsi_endpoint_attrs,
+ };
+
+-#define ISCSI_MAX_EPID -1
+-
+-static int iscsi_match_epid(struct device *dev, const void *data)
+-{
+- struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+- const uint64_t *epid = data;
+-
+- return *epid == ep->id;
+-}
+-
+ struct iscsi_endpoint *
+ iscsi_create_endpoint(int dd_size)
+ {
+- struct device *dev;
+ struct iscsi_endpoint *ep;
+- uint64_t id;
+- int err;
+-
+- for (id = 1; id < ISCSI_MAX_EPID; id++) {
+- dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
+- iscsi_match_epid);
+- if (!dev)
+- break;
+- else
+- put_device(dev);
+- }
+- if (id == ISCSI_MAX_EPID) {
+- printk(KERN_ERR "Too many connections. Max supported %u\n",
+- ISCSI_MAX_EPID - 1);
+- return NULL;
+- }
++ int err, id;
+
+ ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
+ if (!ep)
+ return NULL;
+
++ mutex_lock(&iscsi_ep_idr_mutex);
++ id = idr_alloc(&iscsi_ep_idr, ep, 0, -1, GFP_NOIO);
++ if (id < 0) {
++ mutex_unlock(&iscsi_ep_idr_mutex);
++ printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n",
++ id);
++ goto free_ep;
++ }
++ mutex_unlock(&iscsi_ep_idr_mutex);
++
+ ep->id = id;
+ ep->dev.class = &iscsi_endpoint_class;
+- dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
++ dev_set_name(&ep->dev, "ep-%d", id);
+ err = device_register(&ep->dev);
+ if (err)
+- goto free_ep;
++ goto free_id;
+
+ err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
+ if (err)
+@@ -249,6 +241,10 @@ unregister_dev:
+ device_unregister(&ep->dev);
+ return NULL;
+
++free_id:
++ mutex_lock(&iscsi_ep_idr_mutex);
++ idr_remove(&iscsi_ep_idr, id);
++ mutex_unlock(&iscsi_ep_idr_mutex);
+ free_ep:
+ kfree(ep);
+ return NULL;
+@@ -276,14 +272,17 @@ EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
+ */
+ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ {
+- struct device *dev;
++ struct iscsi_endpoint *ep;
+
+- dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
+- iscsi_match_epid);
+- if (!dev)
+- return NULL;
++ mutex_lock(&iscsi_ep_idr_mutex);
++ ep = idr_find(&iscsi_ep_idr, handle);
++ if (!ep)
++ goto unlock;
+
+- return iscsi_dev_to_endpoint(dev);
++ get_device(&ep->dev);
++unlock:
++ mutex_unlock(&iscsi_ep_idr_mutex);
++ return ep;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
+
+@@ -1899,12 +1898,12 @@ static void session_recovery_timedout(struct work_struct *work)
}
spin_unlock_irqrestore(&session->lock, flags);
@@ -106245,11 +158575,314 @@ index 78343d3f93857..554b6f7842236 100644
}
static void __iscsi_unblock_session(struct work_struct *work)
+@@ -2221,10 +2220,10 @@ static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
+
+ switch (flag) {
+ case STOP_CONN_RECOVER:
+- conn->state = ISCSI_CONN_FAILED;
++ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
+ break;
+ case STOP_CONN_TERM:
+- conn->state = ISCSI_CONN_DOWN;
++ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
+ break;
+ default:
+ iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
+@@ -2236,6 +2235,49 @@ static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
+ }
+
++static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
++{
++ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
++ struct iscsi_endpoint *ep;
++
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
++ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
++
++ if (!conn->ep || !session->transport->ep_disconnect)
++ return;
++
++ ep = conn->ep;
++ conn->ep = NULL;
++
++ session->transport->unbind_conn(conn, is_active);
++ session->transport->ep_disconnect(ep);
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
++}
++
++static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
++ struct iscsi_endpoint *ep,
++ bool is_active)
++{
++ /* Check if this was a conn error and the kernel took ownership */
++ spin_lock_irq(&conn->lock);
++ if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
++ iscsi_ep_disconnect(conn, is_active);
++ } else {
++ spin_unlock_irq(&conn->lock);
++ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
++ mutex_unlock(&conn->ep_mutex);
++
++ flush_work(&conn->cleanup_work);
++ /*
++ * Userspace is now done with the EP so we can release the ref
++ * iscsi_cleanup_conn_work_fn took.
++ */
++ iscsi_put_endpoint(ep);
++ mutex_lock(&conn->ep_mutex);
++ }
++}
++
+ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+ {
+@@ -2256,12 +2298,25 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ cancel_work_sync(&conn->cleanup_work);
+ iscsi_stop_conn(conn, flag);
+ } else {
++ /*
++ * For offload, when iscsid is restarted it won't know about
++ * existing endpoints so it can't do a ep_disconnect. We clean
++ * it up here for userspace.
++ */
++ mutex_lock(&conn->ep_mutex);
++ if (conn->ep)
++ iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
++ mutex_unlock(&conn->ep_mutex);
++
+ /*
+ * Figure out if it was the kernel or userspace initiating this.
+ */
++ spin_lock_irq(&conn->lock);
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
+ iscsi_stop_conn(conn, flag);
+ } else {
++ spin_unlock_irq(&conn->lock);
+ ISCSI_DBG_TRANS_CONN(conn,
+ "flush kernel conn cleanup.\n");
+ flush_work(&conn->cleanup_work);
+@@ -2270,31 +2325,14 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ * Only clear for recovery to avoid extra cleanup runs during
+ * termination.
+ */
++ spin_lock_irq(&conn->lock);
+ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
++ spin_unlock_irq(&conn->lock);
+ }
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
+ return 0;
+ }
+
+-static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
+-{
+- struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
+- struct iscsi_endpoint *ep;
+-
+- ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
+- conn->state = ISCSI_CONN_FAILED;
+-
+- if (!conn->ep || !session->transport->ep_disconnect)
+- return;
+-
+- ep = conn->ep;
+- conn->ep = NULL;
+-
+- session->transport->unbind_conn(conn, is_active);
+- session->transport->ep_disconnect(ep);
+- ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
+-}
+-
+ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
+ {
+ struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
+@@ -2303,18 +2341,11 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
+
+ mutex_lock(&conn->ep_mutex);
+ /*
+- * If we are not at least bound there is nothing for us to do. Userspace
+- * will do a ep_disconnect call if offload is used, but will not be
+- * doing a stop since there is nothing to clean up, so we have to clear
+- * the cleanup bit here.
++ * Get a ref to the ep, so we don't release its ID until after
++ * userspace is done referencing it in iscsi_if_disconnect_bound_ep.
+ */
+- if (conn->state != ISCSI_CONN_BOUND && conn->state != ISCSI_CONN_UP) {
+- ISCSI_DBG_TRANS_CONN(conn, "Got error while conn is already failed. Ignoring.\n");
+- clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
+- mutex_unlock(&conn->ep_mutex);
+- return;
+- }
+-
++ if (conn->ep)
++ get_device(&conn->ep->dev);
+ iscsi_ep_disconnect(conn, false);
+
+ if (system_state != SYSTEM_RUNNING) {
+@@ -2370,11 +2401,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ conn->dd_data = &conn[1];
+
+ mutex_init(&conn->ep_mutex);
++ spin_lock_init(&conn->lock);
+ INIT_LIST_HEAD(&conn->conn_list);
+ INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
+ conn->transport = transport;
+ conn->cid = cid;
+- conn->state = ISCSI_CONN_DOWN;
++ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
+
+ /* this is released in the dev's release function */
+ if (!get_device(&session->dev))
+@@ -2561,9 +2593,32 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ struct iscsi_uevent *ev;
+ struct iscsi_internal *priv;
+ int len = nlmsg_total_size(sizeof(*ev));
++ unsigned long flags;
++ int state;
+
+- if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags))
+- queue_work(iscsi_conn_cleanup_workq, &conn->cleanup_work);
++ spin_lock_irqsave(&conn->lock, flags);
++ /*
++ * Userspace will only do a stop call if we are at least bound. And, we
++ * only need to do the in kernel cleanup if in the UP state so cmds can
++ * be released to upper layers. If in other states just wait for
++ * userspace to avoid races that can leave the cleanup_work queued.
++ */
++ state = READ_ONCE(conn->state);
++ switch (state) {
++ case ISCSI_CONN_BOUND:
++ case ISCSI_CONN_UP:
++ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP,
++ &conn->flags)) {
++ queue_work(iscsi_conn_cleanup_workq,
++ &conn->cleanup_work);
++ }
++ break;
++ default:
++ ISCSI_DBG_TRANS_CONN(conn, "Got conn error in state %d\n",
++ state);
++ break;
++ }
++ spin_unlock_irqrestore(&conn->lock, flags);
+
+ priv = iscsi_if_transport_lookup(conn->transport);
+ if (!priv)
+@@ -2913,7 +2968,7 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ char *data = (char*)ev + sizeof(*ev);
+ struct iscsi_cls_conn *conn;
+ struct iscsi_cls_session *session;
+- int err = 0, value = 0;
++ int err = 0, value = 0, state;
+
+ if (ev->u.set_param.len > PAGE_SIZE)
+ return -EINVAL;
+@@ -2930,8 +2985,8 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ session->recovery_tmo = value;
+ break;
+ default:
+- if ((conn->state == ISCSI_CONN_BOUND) ||
+- (conn->state == ISCSI_CONN_UP)) {
++ state = READ_ONCE(conn->state);
++ if (state == ISCSI_CONN_BOUND || state == ISCSI_CONN_UP) {
+ err = transport->set_param(conn, ev->u.set_param.param,
+ data, ev->u.set_param.len);
+ } else {
+@@ -3003,16 +3058,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ }
+
+ mutex_lock(&conn->ep_mutex);
+- /* Check if this was a conn error and the kernel took ownership */
+- if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
+- ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
+- mutex_unlock(&conn->ep_mutex);
+-
+- flush_work(&conn->cleanup_work);
+- goto put_ep;
+- }
+-
+- iscsi_ep_disconnect(conn, false);
++ iscsi_if_disconnect_bound_ep(conn, ep, false);
+ mutex_unlock(&conn->ep_mutex);
+ put_ep:
+ iscsi_put_endpoint(ep);
+@@ -3715,24 +3761,17 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+ return -EINVAL;
+
+ mutex_lock(&conn->ep_mutex);
++ spin_lock_irq(&conn->lock);
+ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
+ mutex_unlock(&conn->ep_mutex);
+ ev->r.retcode = -ENOTCONN;
+ return 0;
+ }
++ spin_unlock_irq(&conn->lock);
+
+ switch (nlh->nlmsg_type) {
+ case ISCSI_UEVENT_BIND_CONN:
+- if (conn->ep) {
+- /*
+- * For offload boot support where iscsid is restarted
+- * during the pivot root stage, the ep will be intact
+- * here when the new iscsid instance starts up and
+- * reconnects.
+- */
+- iscsi_ep_disconnect(conn, true);
+- }
+-
+ session = iscsi_session_lookup(ev->u.b_conn.sid);
+ if (!session) {
+ err = -EINVAL;
+@@ -3743,7 +3782,7 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+ ev->u.b_conn.transport_eph,
+ ev->u.b_conn.is_leading);
+ if (!ev->r.retcode)
+- conn->state = ISCSI_CONN_BOUND;
++ WRITE_ONCE(conn->state, ISCSI_CONN_BOUND);
+
+ if (ev->r.retcode || !transport->ep_connect)
+ break;
+@@ -3762,7 +3801,8 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+ case ISCSI_UEVENT_START_CONN:
+ ev->r.retcode = transport->start_conn(conn);
+ if (!ev->r.retcode)
+- conn->state = ISCSI_CONN_UP;
++ WRITE_ONCE(conn->state, ISCSI_CONN_UP);
++
+ break;
+ case ISCSI_UEVENT_SEND_PDU:
+ pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
+@@ -4070,10 +4110,11 @@ static ssize_t show_conn_state(struct device *dev,
+ {
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
+ const char *state = "unknown";
++ int conn_state = READ_ONCE(conn->state);
+
+- if (conn->state >= 0 &&
+- conn->state < ARRAY_SIZE(connection_state_names))
+- state = connection_state_names[conn->state];
++ if (conn_state >= 0 &&
++ conn_state < ARRAY_SIZE(connection_state_names))
++ state = connection_state_names[conn_state];
+
+ return sysfs_emit(buf, "%s\n", state);
+ }
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
-index fce63335084ed..78ead3369779c 100644
+index fce63335084ed..a713babaee0f5 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
-@@ -2607,6 +2607,13 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage,
+@@ -48,6 +48,7 @@
+ #include <linux/blkpg.h>
+ #include <linux/blk-pm.h>
+ #include <linux/delay.h>
++#include <linux/major.h>
+ #include <linux/mutex.h>
+ #include <linux/string_helpers.h>
+ #include <linux/async.h>
+@@ -2607,6 +2608,13 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage,
unsigned char *buffer, int len, struct scsi_mode_data *data,
struct scsi_sense_hdr *sshdr)
{
@@ -106263,8 +158896,40 @@ index fce63335084ed..78ead3369779c 100644
return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len,
SD_TIMEOUT, sdkp->max_retries, data,
sshdr);
+@@ -3620,7 +3628,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
+ return 0;
+
+ if (sdkp->WCE && sdkp->media_present) {
+- sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
++ if (!sdkp->device->silence_suspend)
++ sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+ ret = sd_sync_cache(sdkp, &sshdr);
+
+ if (ret) {
+@@ -3642,7 +3651,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
+ }
+
+ if (sdkp->device->manage_start_stop) {
+- sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
++ if (!sdkp->device->silence_suspend)
++ sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+ /* an error is not worth aborting a system sleep */
+ ret = sd_start_stop_device(sdkp, 0);
+ if (ignore_stop_errors)
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index 8f05248920e8e..3c98f08dc25d9 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -31,6 +31,7 @@ static int sg_version_num = 30536; /* 2 digits for each component */
+ #include <linux/errno.h>
+ #include <linux/mtio.h>
+ #include <linux/ioctl.h>
++#include <linux/major.h>
+ #include <linux/slab.h>
+ #include <linux/fcntl.h>
+ #include <linux/init.h>
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
-index ecb2af3f43ca3..a5453f5e87c3e 100644
+index ecb2af3f43ca3..2e690d8a34440 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -234,15 +234,46 @@ static inline bool pqi_is_hba_lunid(u8 *scsi3addr)
@@ -106324,7 +158989,28 @@ index ecb2af3f43ca3..a5453f5e87c3e 100644
}
pqi_firmware_feature_status(ctrl_info, firmware_feature);
-@@ -7627,6 +7659,11 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
+@@ -7621,12 +7653,32 @@ static int pqi_force_sis_mode(struct pqi_ctrl_info *ctrl_info)
+ return pqi_revert_to_sis_mode(ctrl_info);
+ }
+
++static void pqi_perform_lockup_action(void)
++{
++ switch (pqi_lockup_action) {
++ case PANIC:
++ panic("FATAL: Smart Family Controller lockup detected");
++ break;
++ case REBOOT:
++ emergency_restart();
++ break;
++ case NONE:
++ default:
++ break;
++ }
++}
++
+ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
+ {
+ int rc;
u32 product_id;
if (reset_devices) {
@@ -106336,6 +159022,45 @@ index ecb2af3f43ca3..a5453f5e87c3e 100644
sis_soft_reset(ctrl_info);
msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ);
} else {
+@@ -7640,8 +7692,15 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
+ * commands.
+ */
+ rc = sis_wait_for_ctrl_ready(ctrl_info);
+- if (rc)
++ if (rc) {
++ if (reset_devices) {
++ dev_err(&ctrl_info->pci_dev->dev,
++ "kdump init failed with error %d\n", rc);
++ pqi_lockup_action = REBOOT;
++ pqi_perform_lockup_action();
++ }
+ return rc;
++ }
+
+ /*
+ * Get the controller properties. This allows us to determine
+@@ -8365,21 +8424,6 @@ static int pqi_ofa_ctrl_restart(struct pqi_ctrl_info *ctrl_info, unsigned int de
+ return pqi_ctrl_init_resume(ctrl_info);
+ }
+
+-static void pqi_perform_lockup_action(void)
+-{
+- switch (pqi_lockup_action) {
+- case PANIC:
+- panic("FATAL: Smart Family Controller lockup detected");
+- break;
+- case REBOOT:
+- emergency_restart();
+- break;
+- case NONE:
+- default:
+- break;
+- }
+-}
+-
+ static struct pqi_raid_error_info pqi_ctrl_offline_raid_error_info = {
+ .data_out_result = PQI_DATA_IN_OUT_HARDWARE_ERROR,
+ .status = SAM_STAT_CHECK_CONDITION,
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c
index d63c46a8e38bb..8acd3a80f5822 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -106429,10 +159154,27 @@ index d29c1352a826a..c1db93054c863 100644
#endif /* _SMARTPQI_SIS_H */
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
-index 8b17b35283aa5..1203374828b97 100644
+index 8b17b35283aa5..652cd81d77753 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
-@@ -851,7 +851,7 @@ static void get_capabilities(struct scsi_cd *cd)
+@@ -44,6 +44,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
++#include <linux/major.h>
+ #include <linux/blkdev.h>
+ #include <linux/blk-pm.h>
+ #include <linux/mutex.h>
+@@ -578,7 +579,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
+
+ scsi_autopm_get_device(sdev);
+
+- if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
++ if (cmd != CDROMCLOSETRAY && cmd != CDROMEJECT) {
+ ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
+ if (ret != -ENOSYS)
+ goto put;
+@@ -851,7 +852,7 @@ static void get_capabilities(struct scsi_cd *cd)
/* allocate transfer buffer */
@@ -106441,6 +159183,82 @@ index 8b17b35283aa5..1203374828b97 100644
if (!buffer) {
sr_printk(KERN_ERR, cd, "out of memory.\n");
return;
+diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
+index ddd00efc48825..fbdb5124d7f7d 100644
+--- a/drivers/scsi/sr_ioctl.c
++++ b/drivers/scsi/sr_ioctl.c
+@@ -41,7 +41,7 @@ static int sr_read_tochdr(struct cdrom_device_info *cdi,
+ int result;
+ unsigned char *buffer;
+
+- buffer = kmalloc(32, GFP_KERNEL);
++ buffer = kzalloc(32, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+@@ -55,10 +55,13 @@ static int sr_read_tochdr(struct cdrom_device_info *cdi,
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
++ if (result)
++ goto err;
+
+ tochdr->cdth_trk0 = buffer[2];
+ tochdr->cdth_trk1 = buffer[3];
+
++err:
+ kfree(buffer);
+ return result;
+ }
+@@ -71,7 +74,7 @@ static int sr_read_tocentry(struct cdrom_device_info *cdi,
+ int result;
+ unsigned char *buffer;
+
+- buffer = kmalloc(32, GFP_KERNEL);
++ buffer = kzalloc(32, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+@@ -86,6 +89,8 @@ static int sr_read_tocentry(struct cdrom_device_info *cdi,
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
++ if (result)
++ goto err;
+
+ tocentry->cdte_ctrl = buffer[5] & 0xf;
+ tocentry->cdte_adr = buffer[5] >> 4;
+@@ -98,6 +103,7 @@ static int sr_read_tocentry(struct cdrom_device_info *cdi,
+ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
+ + buffer[10]) << 8) + buffer[11];
+
++err:
+ kfree(buffer);
+ return result;
+ }
+@@ -384,7 +390,7 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+ {
+ Scsi_CD *cd = cdi->handle;
+ struct packet_command cgc;
+- char *buffer = kmalloc(32, GFP_KERNEL);
++ char *buffer = kzalloc(32, GFP_KERNEL);
+ int result;
+
+ if (!buffer)
+@@ -400,10 +406,13 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+ cgc.data_direction = DMA_FROM_DEVICE;
+ cgc.timeout = IOCTL_TIMEOUT;
+ result = sr_do_ioctl(cd, &cgc);
++ if (result)
++ goto err;
+
+ memcpy(mcn->medium_catalog_number, buffer + 9, 13);
+ mcn->medium_catalog_number[13] = 0;
+
++err:
+ kfree(buffer);
+ return result;
+ }
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 1f988a1b9166f..a61635326ae0a 100644
--- a/drivers/scsi/sr_vendor.c
@@ -106463,6 +159281,18 @@ index 1f988a1b9166f..a61635326ae0a 100644
if (!buffer)
return -ENOMEM;
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index ae8636d3780b6..9933722acfd96 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -32,6 +32,7 @@ static const char *verstr = "20160209";
+ #include <linux/slab.h>
+ #include <linux/errno.h>
+ #include <linux/mtio.h>
++#include <linux/major.h>
+ #include <linux/cdrom.h>
+ #include <linux/ioctl.h>
+ #include <linux/fcntl.h>
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index 679289e1a78e6..7b08e2e07cc5f 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -106489,10 +159319,10 @@ index 80b3545dd17d6..4e53857605de8 100644
else
host->caps |= UFS_MTK_CAP_VA09_PWR_CTRL;
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
-index 51424557810da..f76692053ca17 100644
+index 51424557810da..e892b9feffb11 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
-@@ -421,6 +421,13 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba)
+@@ -421,6 +421,19 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba)
return err;
}
@@ -106503,10 +159333,16 @@ index 51424557810da..f76692053ca17 100644
+ return ufs_intel_common_init(hba);
+}
+
++static int ufs_intel_mtl_init(struct ufs_hba *hba)
++{
++ hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN;
++ return ufs_intel_common_init(hba);
++}
++
static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = {
.name = "intel-pci",
.init = ufs_intel_common_init,
-@@ -449,6 +456,15 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = {
+@@ -449,6 +462,25 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = {
.device_reset = ufs_intel_device_reset,
};
@@ -106519,10 +159355,20 @@ index 51424557810da..f76692053ca17 100644
+ .device_reset = ufs_intel_device_reset,
+};
+
++static struct ufs_hba_variant_ops ufs_intel_mtl_hba_vops = {
++ .name = "intel-pci",
++ .init = ufs_intel_mtl_init,
++ .exit = ufs_intel_common_exit,
++ .hce_enable_notify = ufs_intel_hce_enable_notify,
++ .link_startup_notify = ufs_intel_link_startup_notify,
++ .resume = ufs_intel_resume,
++ .device_reset = ufs_intel_device_reset,
++};
++
#ifdef CONFIG_PM_SLEEP
static int ufshcd_pci_restore(struct device *dev)
{
-@@ -522,8 +538,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -522,8 +554,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return err;
}
@@ -106531,12 +159377,13 @@ index 51424557810da..f76692053ca17 100644
hba->vops = (struct ufs_hba_variant_ops *)id->driver_data;
err = ufshcd_init(hba, mmio_base, pdev->irq);
-@@ -563,6 +577,8 @@ static const struct pci_device_id ufshcd_pci_tbl[] = {
+@@ -563,6 +593,9 @@ static const struct pci_device_id ufshcd_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops },
{ PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops },
{ PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops },
+ { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops },
+ { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops },
++ { PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
{ } /* terminate list */
};
@@ -106579,7 +159426,7 @@ index 8859c13f4e091..87975d1a21c8b 100644
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
-index 41f2ff35f82b2..cdec85bcc4ccc 100644
+index 41f2ff35f82b2..b55e0a07363f2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -125,8 +125,9 @@ EXPORT_SYMBOL_GPL(ufshcd_dump_regs);
@@ -106604,7 +159451,54 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba);
-@@ -1658,7 +1658,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
+@@ -358,7 +358,7 @@ static void ufshcd_add_uic_command_trace(struct ufs_hba *hba,
+ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
+ enum ufs_trace_str_t str_t)
+ {
+- u64 lba;
++ u64 lba = 0;
+ u8 opcode = 0, group_id = 0;
+ u32 intr, doorbell;
+ struct ufshcd_lrb *lrbp = &hba->lrb[tag];
+@@ -375,7 +375,6 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
+ return;
+
+ opcode = cmd->cmnd[0];
+- lba = scsi_get_lba(cmd);
+
+ if (opcode == READ_10 || opcode == WRITE_10) {
+ /*
+@@ -383,6 +382,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
+ */
+ transfer_len =
+ be32_to_cpu(lrbp->ucd_req_ptr->sc.exp_data_transfer_len);
++ lba = scsi_get_lba(cmd);
+ if (opcode == WRITE_10)
+ group_id = lrbp->cmd->cmnd[6];
+ } else if (opcode == UNMAP) {
+@@ -390,6 +390,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
+ * The number of Bytes to be unmapped beginning with the lba.
+ */
+ transfer_len = blk_rq_bytes(rq);
++ lba = scsi_get_lba(cmd);
+ }
+
+ intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+@@ -576,7 +577,12 @@ static void ufshcd_print_pwr_info(struct ufs_hba *hba)
+ "INVALID MODE",
+ };
+
+- dev_err(hba->dev, "%s:[RX, TX]: gear=[%d, %d], lane[%d, %d], pwr[%s, %s], rate = %d\n",
++ /*
++ * Using dev_dbg to avoid messages during runtime PM to avoid
++ * never-ending cycles of messages written back to storage by user space
++ * causing runtime resume, causing more messages and so on.
++ */
++ dev_dbg(hba->dev, "%s:[RX, TX]: gear=[%d, %d], lane[%d, %d], pwr[%s, %s], rate = %d\n",
+ __func__,
+ hba->pwr_info.gear_rx, hba->pwr_info.gear_tx,
+ hba->pwr_info.lane_rx, hba->pwr_info.lane_tx,
+@@ -1658,7 +1664,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
bool flush_result;
unsigned long flags;
@@ -106614,7 +159508,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
goto out;
spin_lock_irqsave(hba->host->host_lock, flags);
hba->clk_gating.active_reqs++;
-@@ -1818,7 +1819,7 @@ static void __ufshcd_release(struct ufs_hba *hba)
+@@ -1818,7 +1825,7 @@ static void __ufshcd_release(struct ufs_hba *hba)
if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended ||
hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL ||
@@ -106623,7 +159517,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
hba->active_uic_cmd || hba->uic_async_done ||
hba->clk_gating.state == CLKS_OFF)
return;
-@@ -1953,11 +1954,15 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
+@@ -1953,11 +1960,15 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
{
if (!hba->clk_gating.is_initialized)
return;
@@ -106642,7 +159536,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
}
/* Must be called with host lock acquired */
-@@ -2181,6 +2186,7 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
+@@ -2181,6 +2192,7 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
hba->nutmrs =
((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1;
@@ -106650,7 +159544,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
/* Read crypto capabilities */
err = ufshcd_hba_init_crypto_capabilities(hba);
-@@ -2906,30 +2912,15 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
+@@ -2906,30 +2918,15 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
enum dev_cmd_type cmd_type, int timeout)
{
@@ -106685,7 +159579,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
-@@ -2947,8 +2938,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
+@@ -2947,8 +2944,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
(struct utp_upiu_req *)lrbp->ucd_rsp_ptr);
out:
@@ -106694,7 +159588,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
up_read(&hba->clk_scaling_lock);
return err;
}
-@@ -4073,8 +4062,6 @@ int ufshcd_link_recovery(struct ufs_hba *hba)
+@@ -4073,8 +4068,6 @@ int ufshcd_link_recovery(struct ufs_hba *hba)
if (ret)
dev_err(hba->dev, "%s: link recovery failed, err %d",
__func__, ret);
@@ -106703,7 +159597,20 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
return ret;
}
-@@ -5959,7 +5946,6 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
+@@ -4980,6 +4973,12 @@ static int ufshcd_slave_configure(struct scsi_device *sdev)
+ pm_runtime_get_noresume(&sdev->sdev_gendev);
+ else if (ufshcd_is_rpm_autosuspend_allowed(hba))
+ sdev->rpm_autosuspend = 1;
++ /*
++ * Do not print messages during runtime PM to avoid never-ending cycles
++ * of messages written back to storage by user space causing runtime
++ * resume, causing more messages and so on.
++ */
++ sdev->silence_suspend = 1;
+
+ ufshcd_crypto_setup_rq_keyslot_manager(hba, q);
+
+@@ -5959,7 +5958,6 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
ufshcd_release(hba);
if (ufshcd_is_clkscaling_supported(hba))
ufshcd_clk_scaling_suspend(hba, false);
@@ -106711,7 +159618,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
ufshcd_rpm_put(hba);
}
-@@ -6386,9 +6372,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
+@@ -6386,9 +6384,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
irqreturn_t ret = IRQ_NONE;
int tag;
@@ -106722,7 +159629,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
issued = hba->outstanding_tasks & ~pending;
for_each_set_bit(tag, &issued, hba->nutmrs) {
struct request *req = hba->tmf_rqs[tag];
-@@ -6545,11 +6530,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+@@ -6545,11 +6542,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
err = wait_for_completion_io_timeout(&wait,
msecs_to_jiffies(TM_CMD_TIMEOUT));
if (!err) {
@@ -106734,7 +159641,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR);
dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
__func__, tm_function);
-@@ -6645,28 +6625,16 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+@@ -6645,28 +6637,16 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
enum dev_cmd_type cmd_type,
enum query_opcode desc_op)
{
@@ -106767,7 +159674,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
-@@ -6735,9 +6703,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+@@ -6735,9 +6715,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
ufshcd_add_query_upiu_trace(hba, err ? UFS_QUERY_ERR : UFS_QUERY_COMP,
(struct utp_upiu_req *)lrbp->ucd_rsp_ptr);
@@ -106777,7 +159684,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
up_read(&hba->clk_scaling_lock);
return err;
}
-@@ -7044,6 +7009,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
+@@ -7044,6 +7021,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto release;
}
@@ -106785,7 +159692,22 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
err = SUCCESS;
release:
-@@ -7875,8 +7841,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
+@@ -7233,7 +7211,13 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
+
+ if (!hba->vreg_info.vcc || !hba->vreg_info.vccq ||
+ !hba->vreg_info.vccq2) {
+- dev_err(hba->dev,
++ /*
++ * Using dev_dbg to avoid messages during runtime PM to avoid
++ * never-ending cycles of messages written back to storage by
++ * user space causing runtime resume, causing more messages and
++ * so on.
++ */
++ dev_dbg(hba->dev,
+ "%s: Regulator capability was not set, actvIccLevel=%d",
+ __func__, icc_level);
+ goto out;
+@@ -7875,8 +7859,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
if (ret)
goto out;
@@ -106794,7 +159716,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
/* Initialize devfreq after UFS device is detected */
if (ufshcd_is_clkscaling_supported(hba)) {
memcpy(&hba->clk_scaling.saved_pwr_info.info,
-@@ -7902,116 +7866,6 @@ out:
+@@ -7902,116 +7884,6 @@ out:
return ret;
}
@@ -106911,7 +159833,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
/**
* ufshcd_probe_hba - probe hba to detect device and initialize it
* @hba: per-adapter instance
-@@ -8062,8 +7916,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
+@@ -8062,8 +7934,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
/* UFS device is also active now */
ufshcd_set_ufs_dev_active(hba);
ufshcd_force_reset_auto_bkops(hba);
@@ -106920,7 +159842,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
/* Gear up to HS gear if supported */
if (hba->max_pwr_info.is_valid) {
-@@ -8591,7 +8443,7 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
+@@ -8591,7 +8461,7 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
* @pwr_mode: device power mode to set
*
* Returns 0 if requested power mode is set successfully
@@ -106929,7 +159851,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
*/
static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
enum ufs_dev_pwr_mode pwr_mode)
-@@ -8600,7 +8452,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
+@@ -8600,7 +8470,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
struct scsi_sense_hdr sshdr;
struct scsi_device *sdp;
unsigned long flags;
@@ -106938,7 +159860,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
spin_lock_irqsave(hba->host->host_lock, flags);
sdp = hba->sdev_ufs_device;
-@@ -8625,8 +8477,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
+@@ -8625,8 +8495,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
* handling context.
*/
hba->host->eh_noresume = 1;
@@ -106947,7 +159869,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
cmd[4] = pwr_mode << 4;
-@@ -8635,14 +8485,23 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
+@@ -8635,14 +8503,23 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
* callbacks hence set the RQF_PM flag so that it doesn't resume the
* already suspended childs.
*/
@@ -106975,7 +159897,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
}
if (!ret)
-@@ -9485,6 +9344,13 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
+@@ -9485,6 +9362,13 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
struct device *dev = hba->dev;
char eh_wq_name[sizeof("ufs_eh_wq_00")];
@@ -106989,7 +159911,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
if (!mmio_base) {
dev_err(hba->dev,
"Invalid memory reference for mmio_base is NULL\n");
-@@ -9527,8 +9393,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
+@@ -9527,8 +9411,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Configure LRB */
ufshcd_host_memory_configure(hba);
@@ -107000,7 +159922,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
host->max_id = UFSHCD_MAX_ID;
host->max_lun = UFS_MAX_LUNS;
host->max_channel = UFSHCD_MAX_CHANNEL;
-@@ -9699,10 +9565,6 @@ void ufshcd_resume_complete(struct device *dev)
+@@ -9699,10 +9583,6 @@ void ufshcd_resume_complete(struct device *dev)
ufshcd_rpm_put(hba);
hba->complete_put = false;
}
@@ -107011,7 +159933,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
}
EXPORT_SYMBOL_GPL(ufshcd_resume_complete);
-@@ -9725,10 +9587,6 @@ int ufshcd_suspend_prepare(struct device *dev)
+@@ -9725,10 +9605,6 @@ int ufshcd_suspend_prepare(struct device *dev)
}
hba->complete_put = true;
}
@@ -107022,7 +159944,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
return 0;
}
EXPORT_SYMBOL_GPL(ufshcd_suspend_prepare);
-@@ -9797,49 +9655,6 @@ static struct scsi_driver ufs_dev_wlun_template = {
+@@ -9797,49 +9673,6 @@ static struct scsi_driver ufs_dev_wlun_template = {
},
};
@@ -107072,7 +159994,7 @@ index 41f2ff35f82b2..cdec85bcc4ccc 100644
static int __init ufshcd_core_init(void)
{
int ret;
-@@ -9848,24 +9663,13 @@ static int __init ufshcd_core_init(void)
+@@ -9848,24 +9681,13 @@ static int __init ufshcd_core_init(void)
ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv);
if (ret)
@@ -107166,7 +160088,7 @@ index de95be5d11d4e..3ed60068c4ea6 100644
/* HCS - Host Controller Status 30h */
#define DEVICE_PRESENT 0x1
diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
-index 026a133149dce..a86d0cc50de21 100644
+index 026a133149dce..14300896c57fe 100644
--- a/drivers/scsi/ufs/ufshpb.c
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -394,8 +394,6 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
@@ -107178,7 +160100,65 @@ index 026a133149dce..a86d0cc50de21 100644
if (hpb->is_hcm) {
/*
* in host control mode, reads are the main source for
-@@ -1572,7 +1570,7 @@ static void ufshpb_lu_parameter_init(struct ufs_hba *hba,
+@@ -872,12 +870,6 @@ static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb)
+ struct ufshpb_region *rgn, *victim_rgn = NULL;
+
+ list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn) {
+- if (!rgn) {
+- dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+- "%s: no region allocated\n",
+- __func__);
+- return NULL;
+- }
+ if (ufshpb_check_srgns_issue_state(hpb, rgn))
+ continue;
+
+@@ -893,6 +885,11 @@ static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb)
+ break;
+ }
+
++ if (!victim_rgn)
++ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
++ "%s: no region allocated\n",
++ __func__);
++
+ return victim_rgn;
+ }
+
+@@ -1260,6 +1257,13 @@ void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+ struct utp_hpb_rsp *rsp_field = &lrbp->ucd_rsp_ptr->hr;
+ int data_seg_len;
+
++ data_seg_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2)
++ & MASK_RSP_UPIU_DATA_SEG_LEN;
++
++ /* If data segment length is zero, rsp_field is not valid */
++ if (!data_seg_len)
++ return;
++
+ if (unlikely(lrbp->lun != rsp_field->lun)) {
+ struct scsi_device *sdev;
+ bool found = false;
+@@ -1294,18 +1298,6 @@ void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+ return;
+ }
+
+- data_seg_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2)
+- & MASK_RSP_UPIU_DATA_SEG_LEN;
+-
+- /* To flush remained rsp_list, we queue the map_work task */
+- if (!data_seg_len) {
+- if (!ufshpb_is_general_lun(hpb->lun))
+- return;
+-
+- ufshpb_kick_map_work(hpb);
+- return;
+- }
+-
+ BUILD_BUG_ON(sizeof(struct utp_hpb_rsp) != UTP_HPB_RSP_SIZE);
+
+ if (!ufshpb_is_hpb_rsp_valid(hba, lrbp, rsp_field))
+@@ -1572,7 +1564,7 @@ static void ufshpb_lu_parameter_init(struct ufs_hba *hba,
if (ufshpb_is_legacy(hba))
hpb->pre_req_max_tr_len = HPB_LEGACY_CHUNK_HIGH;
else
@@ -107187,7 +160167,7 @@ index 026a133149dce..a86d0cc50de21 100644
hpb->lu_pinned_start = hpb_lu_info->pinned_start;
hpb->lu_pinned_end = hpb_lu_info->num_pinned ?
-@@ -2371,11 +2369,11 @@ static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun,
+@@ -2371,11 +2363,11 @@ static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun,
ufshcd_map_desc_id_to_length(hba, QUERY_DESC_IDN_UNIT, &size);
@@ -107201,7 +160181,7 @@ index 026a133149dce..a86d0cc50de21 100644
if (ret) {
dev_err(hba->dev,
-@@ -2582,7 +2580,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
+@@ -2582,7 +2574,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
{
struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev;
int version, ret;
@@ -107210,7 +160190,7 @@ index 026a133149dce..a86d0cc50de21 100644
hpb_dev_info->control_mode = desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL];
-@@ -2598,21 +2596,22 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
+@@ -2598,21 +2590,22 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
if (version == HPB_SUPPORT_LEGACY_VERSION)
hpb_dev_info->is_legacy = true;
@@ -107292,6 +160272,19 @@ index 0204e314b4825..17b8c88840873 100644
}
kfree(shadow->sg);
+diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c
+index 27b9e2baab1a6..7acf9193a9e80 100644
+--- a/drivers/scsi/zorro7xx.c
++++ b/drivers/scsi/zorro7xx.c
+@@ -159,6 +159,8 @@ static void zorro7xx_remove_one(struct zorro_dev *z)
+ scsi_remove_host(host);
+
+ NCR_700_release(host);
++ if (host->base > 0x01000000)
++ iounmap(hostdata->base);
+ kfree(hostdata);
+ free_irq(host->irq, host);
+ zorro_release_device(z);
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index bd0fbcdbdefe9..e24e220e56eea 100644
--- a/drivers/sh/maple/maple.c
@@ -107316,6 +160309,22 @@ index bd0fbcdbdefe9..e24e220e56eea 100644
goto cleanup_cache;
}
baseunits[i] = mdev[i];
+diff --git a/drivers/slimbus/qcom-ctrl.c b/drivers/slimbus/qcom-ctrl.c
+index f04b961b96cd4..ec58091fc948a 100644
+--- a/drivers/slimbus/qcom-ctrl.c
++++ b/drivers/slimbus/qcom-ctrl.c
+@@ -510,9 +510,9 @@ static int qcom_slim_probe(struct platform_device *pdev)
+ }
+
+ ctrl->irq = platform_get_irq(pdev, 0);
+- if (!ctrl->irq) {
++ if (ctrl->irq < 0) {
+ dev_err(&pdev->dev, "no slimbus IRQ\n");
+- return -ENODEV;
++ return ctrl->irq;
+ }
+
+ sctrl = &ctrl->ctrl;
diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
index 72771e018c42e..258894ed234b3 100644
--- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c
@@ -107498,6 +160507,20 @@ index ac6d856ba228d..77bc12039c3d4 100644
if (of_machine_is_compatible("fsl,ls1021a"))
return 0;
+diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c
+index b762bc40f56bd..afd2fd74802d2 100644
+--- a/drivers/soc/mediatek/mtk-pm-domains.c
++++ b/drivers/soc/mediatek/mtk-pm-domains.c
+@@ -443,6 +443,9 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
+ pd->genpd.power_off = scpsys_power_off;
+ pd->genpd.power_on = scpsys_power_on;
+
++ if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
++ pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
++
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
+ pm_genpd_init(&pd->genpd, NULL, true);
+ else
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 475a57b435b24..2e455d9e3d94a 100644
--- a/drivers/soc/qcom/apr.c
@@ -107543,6 +160566,132 @@ index 15a36dcab990e..e53109a5c3da9 100644
{ LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
{ LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
{ LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
+diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
+index f1875dc31ae2c..85f82e195ef8b 100644
+--- a/drivers/soc/qcom/ocmem.c
++++ b/drivers/soc/qcom/ocmem.c
+@@ -206,6 +206,7 @@ struct ocmem *of_get_ocmem(struct device *dev)
+ ocmem = platform_get_drvdata(pdev);
+ if (!ocmem) {
+ dev_err(dev, "Cannot get ocmem\n");
++ put_device(&pdev->dev);
+ return ERR_PTR(-ENODEV);
+ }
+ return ocmem;
+diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
+index 536c3e4114fb9..8583c1e558aeb 100644
+--- a/drivers/soc/qcom/qcom_aoss.c
++++ b/drivers/soc/qcom/qcom_aoss.c
+@@ -8,10 +8,12 @@
+ #include <linux/io.h>
+ #include <linux/mailbox_client.h>
+ #include <linux/module.h>
++#include <linux/of_platform.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_domain.h>
+ #include <linux/thermal.h>
+ #include <linux/slab.h>
++#include <linux/soc/qcom/qcom_aoss.h>
+
+ #define QMP_DESC_MAGIC 0x0
+ #define QMP_DESC_VERSION 0x4
+@@ -223,11 +225,14 @@ static bool qmp_message_empty(struct qmp *qmp)
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+-static int qmp_send(struct qmp *qmp, const void *data, size_t len)
++int qmp_send(struct qmp *qmp, const void *data, size_t len)
+ {
+ long time_left;
+ int ret;
+
++ if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data))
++ return -EINVAL;
++
+ if (WARN_ON(len + sizeof(u32) > qmp->size))
+ return -EINVAL;
+
+@@ -261,6 +266,7 @@ static int qmp_send(struct qmp *qmp, const void *data, size_t len)
+
+ return ret;
+ }
++EXPORT_SYMBOL(qmp_send);
+
+ static int qmp_qdss_clk_prepare(struct clk_hw *hw)
+ {
+@@ -519,6 +525,55 @@ static void qmp_cooling_devices_remove(struct qmp *qmp)
+ thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
+ }
+
++/**
++ * qmp_get() - get a qmp handle from a device
++ * @dev: client device pointer
++ *
++ * Return: handle to qmp device on success, ERR_PTR() on failure
++ */
++struct qmp *qmp_get(struct device *dev)
++{
++ struct platform_device *pdev;
++ struct device_node *np;
++ struct qmp *qmp;
++
++ if (!dev || !dev->of_node)
++ return ERR_PTR(-EINVAL);
++
++ np = of_parse_phandle(dev->of_node, "qcom,qmp", 0);
++ if (!np)
++ return ERR_PTR(-ENODEV);
++
++ pdev = of_find_device_by_node(np);
++ of_node_put(np);
++ if (!pdev)
++ return ERR_PTR(-EINVAL);
++
++ qmp = platform_get_drvdata(pdev);
++
++ if (!qmp) {
++ put_device(&pdev->dev);
++ return ERR_PTR(-EPROBE_DEFER);
++ }
++ return qmp;
++}
++EXPORT_SYMBOL(qmp_get);
++
++/**
++ * qmp_put() - release a qmp handle
++ * @qmp: qmp handle obtained from qmp_get()
++ */
++void qmp_put(struct qmp *qmp)
++{
++ /*
++ * Match get_device() inside of_find_device_by_node() in
++ * qmp_get()
++ */
++ if (!IS_ERR_OR_NULL(qmp))
++ put_device(qmp->dev);
++}
++EXPORT_SYMBOL(qmp_put);
++
+ static int qmp_probe(struct platform_device *pdev)
+ {
+ struct resource *res;
+@@ -548,7 +603,7 @@ static int qmp_probe(struct platform_device *pdev)
+ }
+
+ irq = platform_get_irq(pdev, 0);
+- ret = devm_request_irq(&pdev->dev, irq, qmp_intr, IRQF_ONESHOT,
++ ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0,
+ "aoss-qmp", qmp);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request interrupt\n");
+@@ -615,6 +670,7 @@ static struct platform_driver qmp_driver = {
+ .driver = {
+ .name = "qcom_aoss_qmp",
+ .of_match_table = qmp_dt_match,
++ .suppress_bind_attrs = true,
+ },
+ .probe = qmp_probe,
+ .remove = qmp_remove,
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
index fa209b479ab35..d98cc8c2e5d5c 100644
--- a/drivers/soc/qcom/rpmhpd.c
@@ -107612,6 +160761,20 @@ index fa209b479ab35..d98cc8c2e5d5c 100644
/*
* The AUX data may be zero padded. These 0 valued entries at
* the end of the map must be ignored.
+diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
+index dbf494e925743..9f07274b0d281 100644
+--- a/drivers/soc/qcom/rpmpd.c
++++ b/drivers/soc/qcom/rpmpd.c
+@@ -546,6 +546,9 @@ static int rpmpd_probe(struct platform_device *pdev)
+
+ data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
+ GFP_KERNEL);
++ if (!data->domains)
++ return -ENOMEM;
++
+ data->num_domains = num;
+
+ for (i = 0; i < num; i++) {
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 52e5811671155..5beb452f24013 100644
--- a/drivers/soc/qcom/socinfo.c
@@ -107691,6 +160854,22 @@ index 49da387d77494..b36779309e49b 100644
return -ENODEV;
}
+diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
+index 09abd17065ba5..8b3ff44fd9010 100644
+--- a/drivers/soc/ti/wkup_m3_ipc.c
++++ b/drivers/soc/ti/wkup_m3_ipc.c
+@@ -449,9 +449,9 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
+ return PTR_ERR(m3_ipc->ipc_mem_base);
+
+ irq = platform_get_irq(pdev, 0);
+- if (!irq) {
++ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+- return -ENXIO;
++ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, wkup_m3_txev_handler,
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 1b115734a8f6b..67369e941d0d6 100644
--- a/drivers/soundwire/bus.c
@@ -107717,11 +160896,49 @@ index b6cad0d59b7b9..49900cd207bc7 100644
bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root);
}
+diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
+index 0ca2a3e3a02e2..747983743a14b 100644
+--- a/drivers/soundwire/dmi-quirks.c
++++ b/drivers/soundwire/dmi-quirks.c
+@@ -59,7 +59,7 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+- DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
+ },
+diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
+index 78037ffdb09ba..f72d36654ac2a 100644
+--- a/drivers/soundwire/intel.c
++++ b/drivers/soundwire/intel.c
+@@ -448,8 +448,8 @@ static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
+
+ /* Clear wake status */
+ wake_sts = intel_readw(shim, SDW_SHIM_WAKESTS);
+- wake_sts |= (SDW_SHIM_WAKEEN_ENABLE << link_id);
+- intel_writew(shim, SDW_SHIM_WAKESTS_STATUS, wake_sts);
++ wake_sts |= (SDW_SHIM_WAKESTS_STATUS << link_id);
++ intel_writew(shim, SDW_SHIM_WAKESTS, wake_sts);
+ }
+ mutex_unlock(sdw->link_res->shim_lock);
+ }
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
-index 95d4fa32c2995..92d9610df1fd8 100644
+index 95d4fa32c2995..938017a60c8ed 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
-@@ -310,7 +310,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
+@@ -277,6 +277,9 @@ static int atmel_qspi_find_mode(const struct spi_mem_op *op)
+ static bool atmel_qspi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+ {
++ if (!spi_mem_default_supports_op(mem, op))
++ return false;
++
+ if (atmel_qspi_find_mode(op) < 0)
+ return false;
+
+@@ -310,7 +313,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
return mode;
ifr |= atmel_qspi_modes[mode].config;
@@ -107744,7 +160961,7 @@ index 46feafe4e201c..d8cc4b270644a 100644
spi_master_put(master);
out:
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
-index 3043677ba2226..ae8c86be77869 100644
+index 3043677ba2226..bd7c7fc739610 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -395,7 +395,8 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
@@ -107766,6 +160983,24 @@ index 3043677ba2226..ae8c86be77869 100644
rd = bcm_qspi_read(qspi, CHIP_SELECT, 0);
wr = (rd & ~0xff) | (1 << cs);
if (rd == wr)
+@@ -1032,7 +1033,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem,
+ addr = op->addr.val;
+ len = op->data.nbytes;
+
+- if (bcm_qspi_bspi_ver_three(qspi) == true) {
++ if (has_bspi(qspi) && bcm_qspi_bspi_ver_three(qspi) == true) {
+ /*
+ * The address coming into this function is a raw flash offset.
+ * But for BSPI <= V3, we need to convert it to a remapped BSPI
+@@ -1051,7 +1052,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem,
+ len < 4)
+ mspi_read = true;
+
+- if (mspi_read)
++ if (!has_bspi(qspi) || mspi_read)
+ return bcm_qspi_mspi_exec_mem_op(spi, op);
+
+ ret = bcm_qspi_bspi_set_mode(qspi, op, 0);
@@ -1460,7 +1461,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
&qspi->dev_ids[val]);
if (ret < 0) {
@@ -107792,6 +161027,206 @@ index 3043677ba2226..ae8c86be77869 100644
clk_disable_unprepare(qspi->clk);
qspi_probe_err:
kfree(qspi->dev_ids);
+diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
+index 101cc71bffa75..2714ba02b176b 100644
+--- a/drivers/spi/spi-cadence-quadspi.c
++++ b/drivers/spi/spi-cadence-quadspi.c
+@@ -18,6 +18,7 @@
+ #include <linux/iopoll.h>
+ #include <linux/jiffies.h>
+ #include <linux/kernel.h>
++#include <linux/log2.h>
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+ #include <linux/of.h>
+@@ -35,6 +36,7 @@
+ /* Quirks */
+ #define CQSPI_NEEDS_WR_DELAY BIT(0)
+ #define CQSPI_DISABLE_DAC_MODE BIT(1)
++#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
+
+ /* Capabilities */
+ #define CQSPI_SUPPORTS_OCTAL BIT(0)
+@@ -82,6 +84,7 @@ struct cqspi_st {
+ u32 wr_delay;
+ bool use_direct_mode;
+ struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
++ bool wr_completion;
+ };
+
+ struct cqspi_driver_platdata {
+@@ -93,12 +96,6 @@ struct cqspi_driver_platdata {
+ #define CQSPI_TIMEOUT_MS 500
+ #define CQSPI_READ_TIMEOUT_MS 10
+
+-/* Instruction type */
+-#define CQSPI_INST_TYPE_SINGLE 0
+-#define CQSPI_INST_TYPE_DUAL 1
+-#define CQSPI_INST_TYPE_QUAD 2
+-#define CQSPI_INST_TYPE_OCTAL 3
+-
+ #define CQSPI_DUMMY_CLKS_PER_BYTE 8
+ #define CQSPI_DUMMY_BYTES_MAX 4
+ #define CQSPI_DUMMY_CLKS_MAX 31
+@@ -322,10 +319,6 @@ static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op, bool dtr)
+ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
+ const struct spi_mem_op *op)
+ {
+- f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE;
+- f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE;
+- f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
+-
+ /*
+ * For an op to be DTR, cmd phase along with every other non-empty
+ * phase should have dtr field set to 1. If an op phase has zero
+@@ -335,32 +328,23 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
+ (!op->addr.nbytes || op->addr.dtr) &&
+ (!op->data.nbytes || op->data.dtr);
+
+- switch (op->data.buswidth) {
+- case 0:
+- break;
+- case 1:
+- f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
+- break;
+- case 2:
+- f_pdata->data_width = CQSPI_INST_TYPE_DUAL;
+- break;
+- case 4:
+- f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
+- break;
+- case 8:
+- f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+- break;
+- default:
+- return -EINVAL;
+- }
++ f_pdata->inst_width = 0;
++ if (op->cmd.buswidth)
++ f_pdata->inst_width = ilog2(op->cmd.buswidth);
++
++ f_pdata->addr_width = 0;
++ if (op->addr.buswidth)
++ f_pdata->addr_width = ilog2(op->addr.buswidth);
++
++ f_pdata->data_width = 0;
++ if (op->data.buswidth)
++ f_pdata->data_width = ilog2(op->data.buswidth);
+
+ /* Right now we only support 8-8-8 DTR mode. */
+ if (f_pdata->dtr) {
+ switch (op->cmd.buswidth) {
+ case 0:
+- break;
+ case 8:
+- f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL;
+ break;
+ default:
+ return -EINVAL;
+@@ -368,9 +352,7 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
+
+ switch (op->addr.buswidth) {
+ case 0:
+- break;
+ case 8:
+- f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL;
+ break;
+ default:
+ return -EINVAL;
+@@ -378,9 +360,7 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
+
+ switch (op->data.buswidth) {
+ case 0:
+- break;
+ case 8:
+- f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+ break;
+ default:
+ return -EINVAL;
+@@ -819,9 +799,11 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata,
+ * polling on the controller's side. spinand and spi-nor will take
+ * care of polling the status register.
+ */
+- reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
+- reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
+- writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
++ if (cqspi->wr_completion) {
++ reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
++ reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
++ writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
++ }
+
+ reg = readl(reg_base + CQSPI_REG_SIZE);
+ reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
+@@ -1248,9 +1230,24 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
+ all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
+ !op->data.dtr;
+
+- /* Mixed DTR modes not supported. */
+- if (!(all_true || all_false))
++ if (all_true) {
++ /* Right now we only support 8-8-8 DTR mode. */
++ if (op->cmd.nbytes && op->cmd.buswidth != 8)
++ return false;
++ if (op->addr.nbytes && op->addr.buswidth != 8)
++ return false;
++ if (op->data.nbytes && op->data.buswidth != 8)
++ return false;
++ } else if (all_false) {
++ /* Only 1-1-X ops are supported without DTR */
++ if (op->cmd.nbytes && op->cmd.buswidth > 1)
++ return false;
++ if (op->addr.nbytes && op->addr.buswidth > 1)
++ return false;
++ } else {
++ /* Mixed DTR modes are not supported. */
+ return false;
++ }
+
+ if (all_true)
+ return spi_mem_dtr_supports_op(mem, op);
+@@ -1539,6 +1536,10 @@ static int cqspi_probe(struct platform_device *pdev)
+
+ cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
+ master->max_speed_hz = cqspi->master_ref_clk_hz;
++
++ /* write completion is supported by default */
++ cqspi->wr_completion = true;
++
+ ddata = of_device_get_match_data(dev);
+ if (ddata) {
+ if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
+@@ -1548,6 +1549,8 @@ static int cqspi_probe(struct platform_device *pdev)
+ master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
+ if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE))
+ cqspi->use_direct_mode = true;
++ if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
++ cqspi->wr_completion = false;
+ }
+
+ ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0,
+@@ -1656,6 +1659,10 @@ static const struct cqspi_driver_platdata intel_lgm_qspi = {
+ .quirks = CQSPI_DISABLE_DAC_MODE,
+ };
+
++static const struct cqspi_driver_platdata socfpga_qspi = {
++ .quirks = CQSPI_NO_SUPPORT_WR_COMPLETION,
++};
++
+ static const struct of_device_id cqspi_dt_ids[] = {
+ {
+ .compatible = "cdns,qspi-nor",
+@@ -1673,6 +1680,10 @@ static const struct of_device_id cqspi_dt_ids[] = {
+ .compatible = "intel,lgm-qspi",
+ .data = &intel_lgm_qspi,
+ },
++ {
++ .compatible = "intel,socfpga-qspi",
++ .data = (void *)&socfpga_qspi,
++ },
+ { /* end of table */ }
+ };
+
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
index 58b823a16fc4d..525cc0143a305 100644
--- a/drivers/spi/spi-hisi-kunpeng.c
@@ -107881,10 +161316,41 @@ index 8eca6f24cb799..c8ed7815c4ba6 100644
spi_master_put(master);
return ret;
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index a15de10ee286a..753bd313e6fda 100644
+index a15de10ee286a..2ca19b01948a2 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
-@@ -624,7 +624,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+@@ -43,8 +43,11 @@
+ #define SPI_CFG1_PACKET_LOOP_OFFSET 8
+ #define SPI_CFG1_PACKET_LENGTH_OFFSET 16
+ #define SPI_CFG1_GET_TICK_DLY_OFFSET 29
++#define SPI_CFG1_GET_TICK_DLY_OFFSET_V1 30
+
+ #define SPI_CFG1_GET_TICK_DLY_MASK 0xe0000000
++#define SPI_CFG1_GET_TICK_DLY_MASK_V1 0xc0000000
++
+ #define SPI_CFG1_CS_IDLE_MASK 0xff
+ #define SPI_CFG1_PACKET_LOOP_MASK 0xff00
+ #define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000
+@@ -346,9 +349,15 @@ static int mtk_spi_prepare_message(struct spi_master *master,
+
+ /* tick delay */
+ reg_val = readl(mdata->base + SPI_CFG1_REG);
+- reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
+- reg_val |= ((chip_config->tick_delay & 0x7)
+- << SPI_CFG1_GET_TICK_DLY_OFFSET);
++ if (mdata->dev_comp->enhance_timing) {
++ reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
++ reg_val |= ((chip_config->tick_delay & 0x7)
++ << SPI_CFG1_GET_TICK_DLY_OFFSET);
++ } else {
++ reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1;
++ reg_val |= ((chip_config->tick_delay & 0x3)
++ << SPI_CFG1_GET_TICK_DLY_OFFSET_V1);
++ }
+ writel(reg_val, mdata->base + SPI_CFG1_REG);
+
+ /* set hw cs timing */
+@@ -624,7 +633,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
else
mdata->state = MTK_SPI_IDLE;
@@ -107894,7 +161360,7 @@ index a15de10ee286a..753bd313e6fda 100644
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
-index 41e7b341d2616..5c93730615f8d 100644
+index 41e7b341d2616..6d203477c04b1 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -160,7 +160,7 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op)
@@ -107906,6 +161372,156 @@ index 41e7b341d2616..5c93730615f8d 100644
dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth;
if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) {
+@@ -909,7 +909,17 @@ static int __maybe_unused mtk_nor_suspend(struct device *dev)
+
+ static int __maybe_unused mtk_nor_resume(struct device *dev)
+ {
+- return pm_runtime_force_resume(dev);
++ struct spi_controller *ctlr = dev_get_drvdata(dev);
++ struct mtk_nor *sp = spi_controller_get_devdata(ctlr);
++ int ret;
++
++ ret = pm_runtime_force_resume(dev);
++ if (ret)
++ return ret;
++
++ mtk_nor_init(sp);
++
++ return 0;
+ }
+
+ static const struct dev_pm_ops mtk_nor_pm_ops = {
+diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
+index 45889947afed8..03fce4493aa79 100644
+--- a/drivers/spi/spi-mxic.c
++++ b/drivers/spi/spi-mxic.c
+@@ -304,25 +304,21 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
+
+ writel(data, mxic->regs + TXD(nbytes % 4));
+
++ ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
++ sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
++ if (ret)
++ return ret;
++
++ ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
++ sts & INT_RX_NOT_EMPTY, 0,
++ USEC_PER_SEC);
++ if (ret)
++ return ret;
++
++ data = readl(mxic->regs + RXD);
+ if (rxbuf) {
+- ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+- sts & INT_TX_EMPTY, 0,
+- USEC_PER_SEC);
+- if (ret)
+- return ret;
+-
+- ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+- sts & INT_RX_NOT_EMPTY, 0,
+- USEC_PER_SEC);
+- if (ret)
+- return ret;
+-
+- data = readl(mxic->regs + RXD);
+ data >>= (8 * (4 - nbytes));
+ memcpy(rxbuf + pos, &data, nbytes);
+- WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
+- } else {
+- readl(mxic->regs + RXD);
+ }
+ WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
+
+diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
+index 2e134eb4bd2c9..6502fda6243e0 100644
+--- a/drivers/spi/spi-pxa2xx-pci.c
++++ b/drivers/spi/spi-pxa2xx-pci.c
+@@ -76,14 +76,23 @@ static bool lpss_dma_filter(struct dma_chan *chan, void *param)
+ return true;
+ }
+
++static void lpss_dma_put_device(void *dma_dev)
++{
++ pci_dev_put(dma_dev);
++}
++
+ static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+ {
+ struct pci_dev *dma_dev;
++ int ret;
+
+ c->num_chipselect = 1;
+ c->max_clk_rate = 50000000;
+
+ dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
++ ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev);
++ if (ret)
++ return ret;
+
+ if (c->tx_param) {
+ struct dw_dma_slave *slave = c->tx_param;
+@@ -107,8 +116,9 @@ static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+
+ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+ {
+- struct pci_dev *dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0));
+ struct dw_dma_slave *tx, *rx;
++ struct pci_dev *dma_dev;
++ int ret;
+
+ switch (PCI_FUNC(dev->devfn)) {
+ case 0:
+@@ -133,6 +143,11 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+ return -ENODEV;
+ }
+
++ dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0));
++ ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev);
++ if (ret)
++ return ret;
++
+ tx = c->tx_param;
+ tx->dma_dev = &dma_dev->dev;
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 553b6b9d02222..c6a1bb09be056 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -585,6 +585,12 @@ static int rockchip_spi_slave_abort(struct spi_controller *ctlr)
+ {
+ struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+
++ if (atomic_read(&rs->state) & RXDMA)
++ dmaengine_terminate_sync(ctlr->dma_rx);
++ if (atomic_read(&rs->state) & TXDMA)
++ dmaengine_terminate_sync(ctlr->dma_tx);
++ atomic_set(&rs->state, 0);
++ spi_enable_chip(rs, false);
+ rs->slave_abort = true;
+ spi_finalize_current_transfer(ctlr);
+
+@@ -654,7 +660,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ struct spi_controller *ctlr;
+ struct resource *mem;
+ struct device_node *np = pdev->dev.of_node;
+- u32 rsd_nsecs;
++ u32 rsd_nsecs, num_cs;
+ bool slave_mode;
+
+ slave_mode = of_property_read_bool(np, "spi-slave");
+@@ -764,8 +770,9 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ * rk spi0 has two native cs, spi1..5 one cs only
+ * if num-cs is missing in the dts, default to 1
+ */
+- if (of_property_read_u16(np, "num-cs", &ctlr->num_chipselect))
+- ctlr->num_chipselect = 1;
++ if (of_property_read_u32(np, "num-cs", &num_cs))
++ num_cs = 1;
++ ctlr->num_chipselect = num_cs;
+ ctlr->use_gpio_descriptors = true;
+ }
+ ctlr->dev.of_node = pdev->dev.of_node;
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index c53138ce00309..83796a4ead34a 100644
--- a/drivers/spi/spi-rpc-if.c
@@ -108042,6 +161658,54 @@ index 27f35aa2d746d..ffdc55f87e821 100644
/* disable qspi */
writel_relaxed(0, qspi->io_base + QSPI_CR);
stm32_qspi_dma_free(qspi);
+diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
+index e9de1d958bbd2..8f345247a8c32 100644
+--- a/drivers/spi/spi-tegra114.c
++++ b/drivers/spi/spi-tegra114.c
+@@ -1352,6 +1352,10 @@ static int tegra_spi_probe(struct platform_device *pdev)
+ tspi->phys = r->start;
+
+ spi_irq = platform_get_irq(pdev, 0);
++ if (spi_irq < 0) {
++ ret = spi_irq;
++ goto exit_free_master;
++ }
+ tspi->irq = spi_irq;
+
+ tspi->clk = devm_clk_get(&pdev->dev, "spi");
+diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
+index 3226c4e1c7c0d..3b44ca455049d 100644
+--- a/drivers/spi/spi-tegra20-slink.c
++++ b/drivers/spi/spi-tegra20-slink.c
+@@ -1003,14 +1003,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
+ struct resource *r;
+ int ret, spi_irq;
+ const struct tegra_slink_chip_data *cdata = NULL;
+- const struct of_device_id *match;
+
+- match = of_match_device(tegra_slink_of_match, &pdev->dev);
+- if (!match) {
+- dev_err(&pdev->dev, "Error: No device match found\n");
+- return -ENODEV;
+- }
+- cdata = match->data;
++ cdata = of_device_get_match_data(&pdev->dev);
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
+ if (!master) {
+diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c
+index 2354ca1e38581..7967073c13545 100644
+--- a/drivers/spi/spi-tegra210-quad.c
++++ b/drivers/spi/spi-tegra210-quad.c
+@@ -1249,6 +1249,8 @@ static int tegra_qspi_probe(struct platform_device *pdev)
+
+ tqspi->phys = r->start;
+ qspi_irq = platform_get_irq(pdev, 0);
++ if (qspi_irq < 0)
++ return qspi_irq;
+ tqspi->irq = qspi_irq;
+
+ tqspi->clk = devm_clk_get(&pdev->dev, "qspi");
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index 8900e51e1a1cc..cc0da48222311 100644
--- a/drivers/spi/spi-uniphier.c
@@ -108128,8 +161792,24 @@ index cfa222c9bd5e7..78f31b61a2aac 100644
memset(tmpbuf, 0xff, op->dummy.nbytes);
reinit_completion(&xqspi->data_completion);
xqspi->txbuf = tmpbuf;
+diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
+index 328b6559bb19a..2b5afae8ff7fc 100644
+--- a/drivers/spi/spi-zynqmp-gqspi.c
++++ b/drivers/spi/spi-zynqmp-gqspi.c
+@@ -1172,7 +1172,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
+ goto clk_dis_all;
+ }
+
+- dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
++ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
++ if (ret)
++ goto clk_dis_all;
++
+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+ ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;
+ ctlr->mem_ops = &zynqmp_qspi_mem_ops;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
-index 926b68aa45d3e..a42b9e8521ce0 100644
+index 926b68aa45d3e..d0bbf8f9414d4 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -451,6 +451,47 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
@@ -108207,7 +161887,36 @@ index 926b68aa45d3e..a42b9e8521ce0 100644
spi_delay_exec(&spi->cs_inactive, NULL);
}
}
-@@ -2979,12 +3019,6 @@ void spi_unregister_controller(struct spi_controller *ctlr)
+@@ -902,10 +942,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
+ int i, ret;
+
+ if (vmalloced_buf || kmap_buf) {
+- desc_len = min_t(int, max_seg_size, PAGE_SIZE);
++ desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE);
+ sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
+ } else if (virt_addr_valid(buf)) {
+- desc_len = min_t(int, max_seg_size, ctlr->max_dma_len);
++ desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len);
+ sgs = DIV_ROUND_UP(len, desc_len);
+ } else {
+ return -EINVAL;
+@@ -1032,11 +1072,15 @@ static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg)
+
+ if (ctlr->dma_tx)
+ tx_dev = ctlr->dma_tx->device->dev;
++ else if (ctlr->dma_map_dev)
++ tx_dev = ctlr->dma_map_dev;
+ else
+ tx_dev = ctlr->dev.parent;
+
+ if (ctlr->dma_rx)
+ rx_dev = ctlr->dma_rx->device->dev;
++ else if (ctlr->dma_map_dev)
++ rx_dev = ctlr->dma_map_dev;
+ else
+ rx_dev = ctlr->dev.parent;
+
+@@ -2979,12 +3023,6 @@ void spi_unregister_controller(struct spi_controller *ctlr)
device_del(&ctlr->dev);
@@ -108220,7 +161929,7 @@ index 926b68aa45d3e..a42b9e8521ce0 100644
/* free bus id */
mutex_lock(&board_lock);
if (found == ctlr)
-@@ -2993,6 +3027,12 @@ void spi_unregister_controller(struct spi_controller *ctlr)
+@@ -2993,6 +3031,12 @@ void spi_unregister_controller(struct spi_controller *ctlr)
if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
mutex_unlock(&ctlr->add_lock);
@@ -108331,6 +162040,28 @@ index 76f8c090a8370..06afaa9d505ba 100644
} \
\
static void __exit fbtft_driver_module_exit(void) \
+diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
+index e390c924ec1c8..3c680ed4429c1 100644
+--- a/drivers/staging/gdm724x/gdm_lte.c
++++ b/drivers/staging/gdm724x/gdm_lte.c
+@@ -76,14 +76,15 @@ static void tx_complete(void *arg)
+
+ static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
+ {
+- int ret;
++ int ret, len;
+
++ len = skb->len + ETH_HLEN;
+ ret = netif_rx_ni(skb);
+ if (ret == NET_RX_DROP) {
+ nic->stats.rx_dropped++;
+ } else {
+ nic->stats.rx_packets++;
+- nic->stats.rx_bytes += skb->len + ETH_HLEN;
++ nic->stats.rx_bytes += len;
+ }
+
+ return 0;
diff --git a/drivers/staging/greybus/audio_helper.c b/drivers/staging/greybus/audio_helper.c
index 1ed4772d27715..843760675876a 100644
--- a/drivers/staging/greybus/audio_helper.c
@@ -108533,6 +162264,22 @@ index 1e613d42d8237..62d7674852bec 100644
control->items = le32_to_cpu(gbenum->items);
} else {
csize = sizeof(struct gb_audio_control);
+diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
+index fef0055b89909..20183b2ea1279 100644
+--- a/drivers/staging/iio/adc/ad7280a.c
++++ b/drivers/staging/iio/adc/ad7280a.c
+@@ -107,9 +107,9 @@
+ static unsigned int ad7280a_devaddr(unsigned int addr)
+ {
+ return ((addr & 0x1) << 4) |
+- ((addr & 0x2) << 3) |
++ ((addr & 0x2) << 2) |
+ (addr & 0x4) |
+- ((addr & 0x8) >> 3) |
++ ((addr & 0x8) >> 2) |
+ ((addr & 0x10) >> 4);
+ }
+
diff --git a/drivers/staging/ks7010/Kconfig b/drivers/staging/ks7010/Kconfig
index 0987fdc2f70db..8ea6c09286798 100644
--- a/drivers/staging/ks7010/Kconfig
@@ -108748,6 +162495,74 @@ index 874115f35fcad..798b28e134b64 100644
{0x370a, 0x21},
{0x3801, 0x00},
{0x3802, 0x00},
+diff --git a/drivers/staging/media/atomisp/pci/atomisp_acc.c b/drivers/staging/media/atomisp/pci/atomisp_acc.c
+index 9a1751895ab03..28cb271663c47 100644
+--- a/drivers/staging/media/atomisp/pci/atomisp_acc.c
++++ b/drivers/staging/media/atomisp/pci/atomisp_acc.c
+@@ -439,6 +439,18 @@ int atomisp_acc_s_mapped_arg(struct atomisp_sub_device *asd,
+ return 0;
+ }
+
++static void atomisp_acc_unload_some_extensions(struct atomisp_sub_device *asd,
++ int i,
++ struct atomisp_acc_fw *acc_fw)
++{
++ while (--i >= 0) {
++ if (acc_fw->flags & acc_flag_to_pipe[i].flag) {
++ atomisp_css_unload_acc_extension(asd, acc_fw->fw,
++ acc_flag_to_pipe[i].pipe_id);
++ }
++ }
++}
++
+ /*
+ * Appends the loaded acceleration binary extensions to the
+ * current ISP mode. Must be called just before sh_css_start().
+@@ -479,16 +491,20 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
+ acc_fw->fw,
+ acc_flag_to_pipe[i].pipe_id,
+ acc_fw->type);
+- if (ret)
++ if (ret) {
++ atomisp_acc_unload_some_extensions(asd, i, acc_fw);
+ goto error;
++ }
+
+ ext_loaded = true;
+ }
+ }
+
+ ret = atomisp_css_set_acc_parameters(acc_fw);
+- if (ret < 0)
++ if (ret < 0) {
++ atomisp_acc_unload_some_extensions(asd, i, acc_fw);
+ goto error;
++ }
+ }
+
+ if (!ext_loaded)
+@@ -497,6 +513,7 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
+ ret = atomisp_css_update_stream(asd);
+ if (ret) {
+ dev_err(isp->dev, "%s: update stream failed.\n", __func__);
++ atomisp_acc_unload_extensions(asd);
+ goto error;
+ }
+
+@@ -504,13 +521,6 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
+ return 0;
+
+ error:
+- while (--i >= 0) {
+- if (acc_fw->flags & acc_flag_to_pipe[i].flag) {
+- atomisp_css_unload_acc_extension(asd, acc_fw->fw,
+- acc_flag_to_pipe[i].pipe_id);
+- }
+- }
+-
+ list_for_each_entry_continue_reverse(acc_fw, &asd->acc.fw, list) {
+ if (acc_fw->type != ATOMISP_ACC_FW_LOAD_TYPE_OUTPUT &&
+ acc_fw->type != ATOMISP_ACC_FW_LOAD_TYPE_VIEWFINDER)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 366161cff5602..ef0b0963cf930 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -108965,7 +162780,7 @@ index f82bf082aa796..18fff47bd25d2 100644
return -EACCES;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
-index d8c9e31314b2e..62dc06e224765 100644
+index d8c9e31314b2e..cd0a771454da4 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
@@ -481,7 +481,7 @@ fail:
@@ -108977,6 +162792,38 @@ index d8c9e31314b2e..62dc06e224765 100644
static u8 pmic_i2c_addr;
if (pmic_id)
+@@ -729,6 +729,21 @@ static int axp_regulator_set(struct device *dev, struct gmin_subdev *gs,
+ return 0;
+ }
+
++/*
++ * Some boards contain a hw-bug where turning eldo2 back on after having turned
++ * it off causes the CPLM3218 ambient-light-sensor on the image-sensor's I2C bus
++ * to crash, hanging the bus. Do not turn eldo2 off on these systems.
++ */
++static const struct dmi_system_id axp_leave_eldo2_on_ids[] = {
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab duo W1 10.1 (VT4)"),
++ },
++ },
++ { }
++};
++
+ static int axp_v1p8_on(struct device *dev, struct gmin_subdev *gs)
+ {
+ int ret;
+@@ -763,6 +778,9 @@ static int axp_v1p8_off(struct device *dev, struct gmin_subdev *gs)
+ if (ret)
+ return ret;
+
++ if (dmi_check_system(axp_leave_eldo2_on_ids))
++ return 0;
++
+ ret = axp_regulator_set(dev, gs, gs->eldo2_sel_reg, gs->eldo2_1p8v,
+ ELDO_CTRL_REG, gs->eldo2_ctrl_shift, false);
+ return ret;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index c8a625667e81e..b7dda4b96d49c 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -109427,6 +163274,38 @@ index 81bb356b81720..72611b8286a4a 100644
void atomisp_acc_init(struct atomisp_acc_pipe *video, const char *name);
void atomisp_video_unregister(struct atomisp_video_pipe *video);
void atomisp_acc_unregister(struct atomisp_acc_pipe *video);
+diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm.c b/drivers/staging/media/atomisp/pci/hmm/hmm.c
+index 6a5ee46070898..c1cda16f2dc01 100644
+--- a/drivers/staging/media/atomisp/pci/hmm/hmm.c
++++ b/drivers/staging/media/atomisp/pci/hmm/hmm.c
+@@ -39,7 +39,7 @@
+ struct hmm_bo_device bo_device;
+ struct hmm_pool dynamic_pool;
+ struct hmm_pool reserved_pool;
+-static ia_css_ptr dummy_ptr;
++static ia_css_ptr dummy_ptr = mmgr_EXCEPTION;
+ static bool hmm_initialized;
+ struct _hmm_mem_stat hmm_mem_stat;
+
+@@ -209,7 +209,7 @@ int hmm_init(void)
+
+ void hmm_cleanup(void)
+ {
+- if (!dummy_ptr)
++ if (dummy_ptr == mmgr_EXCEPTION)
+ return;
+ sysfs_remove_group(&atomisp_dev->kobj, atomisp_attribute_group);
+
+@@ -288,7 +288,8 @@ void hmm_free(ia_css_ptr virt)
+
+ dev_dbg(atomisp_dev, "%s: free 0x%08x\n", __func__, virt);
+
+- WARN_ON(!virt);
++ if (WARN_ON(virt == mmgr_EXCEPTION))
++ return;
+
+ bo = hmm_bo_device_search_start(&bo_device, (unsigned int)virt);
+
diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
index c4b35cbab3737..ba25d0da8b811 100644
--- a/drivers/staging/media/atomisp/pci/sh_css.c
@@ -109627,9 +163506,18 @@ index 20e5081588719..281aa585e3375 100644
pm_runtime_disable(vpu->dev);
return ret;
diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
-index 56cf261a8e958..9cd713c02a455 100644
+index 56cf261a8e958..686d813f5c626 100644
--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
+++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
+@@ -23,7 +23,7 @@ static void hantro_h1_set_src_img_ctrl(struct hantro_dev *vpu,
+
+ reg = H1_REG_IN_IMG_CTRL_ROW_LEN(pix_fmt->width)
+ | H1_REG_IN_IMG_CTRL_OVRFLR_D4(0)
+- | H1_REG_IN_IMG_CTRL_OVRFLB_D4(0)
++ | H1_REG_IN_IMG_CTRL_OVRFLB(0)
+ | H1_REG_IN_IMG_CTRL_FMT(ctx->vpu_src_fmt->enc_fmt);
+ vepu_write_relaxed(vpu, reg, H1_REG_IN_IMG_CTRL);
+ }
@@ -140,7 +140,7 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
return 0;
}
@@ -109639,6 +163527,19 @@ index 56cf261a8e958..9cd713c02a455 100644
{
struct hantro_dev *vpu = ctx->dev;
u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8;
+diff --git a/drivers/staging/media/hantro/hantro_h1_regs.h b/drivers/staging/media/hantro/hantro_h1_regs.h
+index d6e9825bb5c7b..30e7e7b920b55 100644
+--- a/drivers/staging/media/hantro/hantro_h1_regs.h
++++ b/drivers/staging/media/hantro/hantro_h1_regs.h
+@@ -47,7 +47,7 @@
+ #define H1_REG_IN_IMG_CTRL 0x03c
+ #define H1_REG_IN_IMG_CTRL_ROW_LEN(x) ((x) << 12)
+ #define H1_REG_IN_IMG_CTRL_OVRFLR_D4(x) ((x) << 10)
+-#define H1_REG_IN_IMG_CTRL_OVRFLB_D4(x) ((x) << 6)
++#define H1_REG_IN_IMG_CTRL_OVRFLB(x) ((x) << 6)
+ #define H1_REG_IN_IMG_CTRL_FMT(x) ((x) << 2)
+ #define H1_REG_ENC_CTRL0 0x040
+ #define H1_REG_ENC_CTRL0_INIT_QP(x) ((x) << 26)
diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h
index df7b5e3a57b9b..fd738653a5735 100644
--- a/drivers/staging/media/hantro/hantro_hw.h
@@ -109721,6 +163622,190 @@ index d186179388d03..4d873726a461b 100644
media_device_init(&imxmd->md);
+diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
+index 41e33535de552..d35e523741168 100644
+--- a/drivers/staging/media/imx/imx7-mipi-csis.c
++++ b/drivers/staging/media/imx/imx7-mipi-csis.c
+@@ -32,7 +32,6 @@
+ #include <media/v4l2-subdev.h>
+
+ #define CSIS_DRIVER_NAME "imx7-mipi-csis"
+-#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
+
+ #define CSIS_PAD_SINK 0
+ #define CSIS_PAD_SOURCE 1
+@@ -311,7 +310,6 @@ struct csi_state {
+ struct reset_control *mrst;
+ struct regulator *mipi_phy_regulator;
+ const struct mipi_csis_info *info;
+- u8 index;
+
+ struct v4l2_subdev sd;
+ struct media_pad pads[CSIS_PADS_NUM];
+@@ -1303,8 +1301,8 @@ static int mipi_csis_subdev_init(struct csi_state *state)
+
+ v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
+ sd->owner = THIS_MODULE;
+- snprintf(sd->name, sizeof(sd->name), "%s.%d",
+- CSIS_SUBDEV_NAME, state->index);
++ snprintf(sd->name, sizeof(sd->name), "csis-%s",
++ dev_name(state->dev));
+
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->ctrl_handler = NULL;
+diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+index a6f562009b9a0..1d28313dbed7d 100644
+--- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
++++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+@@ -398,9 +398,6 @@ static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret = 0;
+
+- imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK,
+- CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE);
+-
+ if (enable) {
+ ret = pm_runtime_resume_and_get(state->dev);
+ if (ret < 0)
+@@ -696,7 +693,7 @@ err_parse:
+ * Suspend/resume
+ */
+
+-static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime)
++static int imx8mq_mipi_csi_pm_suspend(struct device *dev)
+ {
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+@@ -708,36 +705,21 @@ static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime)
+ imx8mq_mipi_csi_stop_stream(state);
+ imx8mq_mipi_csi_clk_disable(state);
+ state->state &= ~ST_POWERED;
+- if (!runtime)
+- state->state |= ST_SUSPENDED;
+ }
+
+ mutex_unlock(&state->lock);
+
+- ret = icc_set_bw(state->icc_path, 0, 0);
+- if (ret)
+- dev_err(dev, "icc_set_bw failed with %d\n", ret);
+-
+ return ret ? -EAGAIN : 0;
+ }
+
+-static int imx8mq_mipi_csi_pm_resume(struct device *dev, bool runtime)
++static int imx8mq_mipi_csi_pm_resume(struct device *dev)
+ {
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret = 0;
+
+- ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
+- if (ret) {
+- dev_err(dev, "icc_set_bw failed with %d\n", ret);
+- return ret;
+- }
+-
+ mutex_lock(&state->lock);
+
+- if (!runtime && !(state->state & ST_SUSPENDED))
+- goto unlock;
+-
+ if (!(state->state & ST_POWERED)) {
+ state->state |= ST_POWERED;
+ ret = imx8mq_mipi_csi_clk_enable(state);
+@@ -758,22 +740,60 @@ unlock:
+
+ static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev)
+ {
+- return imx8mq_mipi_csi_pm_suspend(dev, false);
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct csi_state *state = mipi_sd_to_csi2_state(sd);
++ int ret;
++
++ ret = imx8mq_mipi_csi_pm_suspend(dev);
++ if (ret)
++ return ret;
++
++ state->state |= ST_SUSPENDED;
++
++ return ret;
+ }
+
+ static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev)
+ {
+- return imx8mq_mipi_csi_pm_resume(dev, false);
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct csi_state *state = mipi_sd_to_csi2_state(sd);
++
++ if (!(state->state & ST_SUSPENDED))
++ return 0;
++
++ return imx8mq_mipi_csi_pm_resume(dev);
+ }
+
+ static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev)
+ {
+- return imx8mq_mipi_csi_pm_suspend(dev, true);
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct csi_state *state = mipi_sd_to_csi2_state(sd);
++ int ret;
++
++ ret = imx8mq_mipi_csi_pm_suspend(dev);
++ if (ret)
++ return ret;
++
++ ret = icc_set_bw(state->icc_path, 0, 0);
++ if (ret)
++ dev_err(dev, "icc_set_bw failed with %d\n", ret);
++
++ return ret;
+ }
+
+ static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev)
+ {
+- return imx8mq_mipi_csi_pm_resume(dev, true);
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct csi_state *state = mipi_sd_to_csi2_state(sd);
++ int ret;
++
++ ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
++ if (ret) {
++ dev_err(dev, "icc_set_bw failed with %d\n", ret);
++ return ret;
++ }
++
++ return imx8mq_mipi_csi_pm_resume(dev);
+ }
+
+ static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
+@@ -921,7 +941,7 @@ static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
+ /* Enable runtime PM. */
+ pm_runtime_enable(dev);
+ if (!pm_runtime_enabled(dev)) {
+- ret = imx8mq_mipi_csi_pm_resume(dev, true);
++ ret = imx8mq_mipi_csi_runtime_resume(dev);
+ if (ret < 0)
+ goto icc;
+ }
+@@ -934,7 +954,7 @@ static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
+
+ cleanup:
+ pm_runtime_disable(&pdev->dev);
+- imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
++ imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
+
+ media_entity_cleanup(&state->sd.entity);
+ v4l2_async_notifier_unregister(&state->notifier);
+@@ -958,7 +978,7 @@ static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
+ v4l2_async_unregister_subdev(&state->sd);
+
+ pm_runtime_disable(&pdev->dev);
+- imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
++ imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
+ media_entity_cleanup(&state->sd.entity);
+ mutex_destroy(&state->lock);
+ pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.c b/drivers/staging/media/ipu3/ipu3-css-fw.c
index 45aff76198e2c..981693eed8155 100644
--- a/drivers/staging/media/ipu3/ipu3-css-fw.c
@@ -109782,6 +163867,70 @@ index 38a2407645096..90c86ba5040e3 100644
fmts[i] = NULL;
continue;
}
+diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
+index db7022707ff8d..86ccc8937afca 100644
+--- a/drivers/staging/media/meson/vdec/esparser.c
++++ b/drivers/staging/media/meson/vdec/esparser.c
+@@ -328,7 +328,12 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+
+ offset = esparser_get_offset(sess);
+
+- amvdec_add_ts(sess, vb->timestamp, vbuf->timecode, offset, vbuf->flags);
++ ret = amvdec_add_ts(sess, vb->timestamp, vbuf->timecode, offset, vbuf->flags);
++ if (ret) {
++ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
++ return ret;
++ }
++
+ dev_dbg(core->dev, "esparser: ts = %llu pld_size = %u offset = %08X flags = %08X\n",
+ vb->timestamp, payload_size, offset, vbuf->flags);
+
+diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c
+index b9125c295d1d3..06fd66539797a 100644
+--- a/drivers/staging/media/meson/vdec/vdec_helpers.c
++++ b/drivers/staging/media/meson/vdec/vdec_helpers.c
+@@ -227,13 +227,16 @@ int amvdec_set_canvases(struct amvdec_session *sess,
+ }
+ EXPORT_SYMBOL_GPL(amvdec_set_canvases);
+
+-void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
+- struct v4l2_timecode tc, u32 offset, u32 vbuf_flags)
++int amvdec_add_ts(struct amvdec_session *sess, u64 ts,
++ struct v4l2_timecode tc, u32 offset, u32 vbuf_flags)
+ {
+ struct amvdec_timestamp *new_ts;
+ unsigned long flags;
+
+ new_ts = kzalloc(sizeof(*new_ts), GFP_KERNEL);
++ if (!new_ts)
++ return -ENOMEM;
++
+ new_ts->ts = ts;
+ new_ts->tc = tc;
+ new_ts->offset = offset;
+@@ -242,6 +245,7 @@ void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
+ spin_lock_irqsave(&sess->ts_spinlock, flags);
+ list_add_tail(&new_ts->list, &sess->timestamps);
+ spin_unlock_irqrestore(&sess->ts_spinlock, flags);
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(amvdec_add_ts);
+
+diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.h b/drivers/staging/media/meson/vdec/vdec_helpers.h
+index cfaed52ab5265..798e5a8a9b3f1 100644
+--- a/drivers/staging/media/meson/vdec/vdec_helpers.h
++++ b/drivers/staging/media/meson/vdec/vdec_helpers.h
+@@ -55,8 +55,8 @@ void amvdec_dst_buf_done_offset(struct amvdec_session *sess,
+ * @offset: offset in the VIFIFO where the associated packet was written
+ * @flags the vb2_v4l2_buffer flags
+ */
+-void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
+- struct v4l2_timecode tc, u32 offset, u32 flags);
++int amvdec_add_ts(struct amvdec_session *sess, u64 ts,
++ struct v4l2_timecode tc, u32 offset, u32 flags);
+ void amvdec_remove_ts(struct amvdec_session *sess, u64 ts);
+
+ /**
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index 76e97cbe25123..951e19231da21 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -109872,6 +164021,277 @@ index 7131156c1f2cf..3f3f96488d741 100644
if (ret)
return ret;
+diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+index de7442d4834dc..d3e26bfe6c90b 100644
+--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+@@ -38,7 +38,7 @@ struct cedrus_h264_sram_ref_pic {
+
+ #define CEDRUS_H264_FRAME_NUM 18
+
+-#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K)
++#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (32 * SZ_1K)
+ #define CEDRUS_MIN_PIC_INFO_BUF_SIZE (130 * SZ_1K)
+
+ static void cedrus_h264_write_sram(struct cedrus_dev *dev,
+diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+index ef0311a16d019..754942ecf064c 100644
+--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+@@ -23,7 +23,7 @@
+ * Subsequent BSP implementations seem to double the neighbor info buffer size
+ * for the H6 SoC, which may be related to 10 bit H265 support.
+ */
+-#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K)
++#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K)
+ #define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K)
+ #define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160
+
+diff --git a/drivers/staging/media/zoran/zoran.h b/drivers/staging/media/zoran/zoran.h
+index b1ad2a2b914cd..50d5a7acfab6c 100644
+--- a/drivers/staging/media/zoran/zoran.h
++++ b/drivers/staging/media/zoran/zoran.h
+@@ -313,6 +313,6 @@ static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
+
+ #endif
+
+-int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq);
++int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir);
+ void zoran_queue_exit(struct zoran *zr);
+ int zr_set_buf(struct zoran *zr);
+diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c
+index f259585b06897..11d415c0c05d2 100644
+--- a/drivers/staging/media/zoran/zoran_card.c
++++ b/drivers/staging/media/zoran/zoran_card.c
+@@ -803,6 +803,52 @@ int zoran_check_jpg_settings(struct zoran *zr,
+ return 0;
+ }
+
++static int zoran_init_video_device(struct zoran *zr, struct video_device *video_dev, int dir)
++{
++ int err;
++
++ /* Now add the template and register the device unit. */
++ *video_dev = zoran_template;
++ video_dev->v4l2_dev = &zr->v4l2_dev;
++ video_dev->lock = &zr->lock;
++ video_dev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | dir;
++
++ strscpy(video_dev->name, ZR_DEVNAME(zr), sizeof(video_dev->name));
++ /*
++ * It's not a mem2mem device, but you can both capture and output from one and the same
++ * device. This should really be split up into two device nodes, but that's a job for
++ * another day.
++ */
++ video_dev->vfl_dir = VFL_DIR_M2M;
++ zoran_queue_init(zr, &zr->vq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
++
++ err = video_register_device(video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
++ if (err < 0)
++ return err;
++ video_set_drvdata(video_dev, zr);
++ return 0;
++}
++
++static void zoran_exit_video_devices(struct zoran *zr)
++{
++ video_unregister_device(zr->video_dev);
++ kfree(zr->video_dev);
++}
++
++static int zoran_init_video_devices(struct zoran *zr)
++{
++ int err;
++
++ zr->video_dev = video_device_alloc();
++ if (!zr->video_dev)
++ return -ENOMEM;
++
++ err = zoran_init_video_device(zr, zr->video_dev, V4L2_CAP_VIDEO_CAPTURE);
++ if (err)
++ kfree(zr->video_dev);
++ return err;
++}
++
+ void zoran_open_init_params(struct zoran *zr)
+ {
+ int i;
+@@ -874,17 +920,11 @@ static int zr36057_init(struct zoran *zr)
+ zoran_open_init_params(zr);
+
+ /* allocate memory *before* doing anything to the hardware in case allocation fails */
+- zr->video_dev = video_device_alloc();
+- if (!zr->video_dev) {
+- err = -ENOMEM;
+- goto exit;
+- }
+ zr->stat_com = dma_alloc_coherent(&zr->pci_dev->dev,
+ BUZ_NUM_STAT_COM * sizeof(u32),
+ &zr->p_sc, GFP_KERNEL);
+ if (!zr->stat_com) {
+- err = -ENOMEM;
+- goto exit_video;
++ return -ENOMEM;
+ }
+ for (j = 0; j < BUZ_NUM_STAT_COM; j++)
+ zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
+@@ -897,26 +937,9 @@ static int zr36057_init(struct zoran *zr)
+ goto exit_statcom;
+ }
+
+- /* Now add the template and register the device unit. */
+- *zr->video_dev = zoran_template;
+- zr->video_dev->v4l2_dev = &zr->v4l2_dev;
+- zr->video_dev->lock = &zr->lock;
+- zr->video_dev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
+-
+- strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name));
+- /*
+- * It's not a mem2mem device, but you can both capture and output from one and the same
+- * device. This should really be split up into two device nodes, but that's a job for
+- * another day.
+- */
+- zr->video_dev->vfl_dir = VFL_DIR_M2M;
+-
+- zoran_queue_init(zr, &zr->vq);
+-
+- err = video_register_device(zr->video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
+- if (err < 0)
++ err = zoran_init_video_devices(zr);
++ if (err)
+ goto exit_statcomb;
+- video_set_drvdata(zr->video_dev, zr);
+
+ zoran_init_hardware(zr);
+ if (!pass_through) {
+@@ -931,9 +954,6 @@ exit_statcomb:
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
+ exit_statcom:
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32), zr->stat_com, zr->p_sc);
+-exit_video:
+- kfree(zr->video_dev);
+-exit:
+ return err;
+ }
+
+@@ -965,7 +985,7 @@ static void zoran_remove(struct pci_dev *pdev)
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
+ pci_release_regions(pdev);
+ pci_disable_device(zr->pci_dev);
+- video_unregister_device(zr->video_dev);
++ zoran_exit_video_devices(zr);
+ exit_free:
+ v4l2_ctrl_handler_free(&zr->hdl);
+ v4l2_device_unregister(&zr->v4l2_dev);
+@@ -1069,8 +1089,10 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err)
+- return -ENODEV;
+- vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
++ return err;
++ err = vb2_dma_contig_set_max_seg_size(&pdev->dev, U32_MAX);
++ if (err)
++ return err;
+
+ nr = zoran_num++;
+ if (nr >= BUZ_MAX) {
+diff --git a/drivers/staging/media/zoran/zoran_device.c b/drivers/staging/media/zoran/zoran_device.c
+index 5b12a730a2290..fb1f0465ca87f 100644
+--- a/drivers/staging/media/zoran/zoran_device.c
++++ b/drivers/staging/media/zoran/zoran_device.c
+@@ -814,7 +814,7 @@ static void zoran_reap_stat_com(struct zoran *zr)
+ if (zr->jpg_settings.tmp_dcm == 1)
+ i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+ else
+- i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2 + 1;
++ i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+
+ stat_com = le32_to_cpu(zr->stat_com[i]);
+ if ((stat_com & 1) == 0) {
+@@ -826,6 +826,11 @@ static void zoran_reap_stat_com(struct zoran *zr)
+ size = (stat_com & GENMASK(22, 1)) >> 1;
+
+ buf = zr->inuse[i];
++ if (!buf) {
++ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
++ pci_err(zr->pci_dev, "No buffer at slot %d\n", i);
++ return;
++ }
+ buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
+
+ if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
+index 46382e43f1bf7..84665637ebb79 100644
+--- a/drivers/staging/media/zoran/zoran_driver.c
++++ b/drivers/staging/media/zoran/zoran_driver.c
+@@ -255,8 +255,6 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
+ strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
+ strscpy(cap->driver, "zoran", sizeof(cap->driver));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev));
+- cap->device_caps = zr->video_dev->device_caps;
+- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+ }
+
+@@ -582,6 +580,9 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
+ struct zoran *zr = video_drvdata(file);
+ int res = 0;
+
++ if (zr->norm == std)
++ return 0;
++
+ if (zr->running != ZORAN_MAP_MODE_NONE)
+ return -EBUSY;
+
+@@ -739,6 +740,7 @@ static int zoran_g_parm(struct file *file, void *priv, struct v4l2_streamparm *p
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
++ parm->parm.capture.readbuffers = 9;
+ return 0;
+ }
+
+@@ -869,6 +871,10 @@ int zr_set_buf(struct zoran *zr)
+ vbuf = &buf->vbuf;
+
+ buf->vbuf.field = V4L2_FIELD_INTERLACED;
++ if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
++ buf->vbuf.field = V4L2_FIELD_INTERLACED;
++ else
++ buf->vbuf.field = V4L2_FIELD_TOP;
+ vb2_set_plane_payload(&buf->vbuf.vb2_buf, 0, zr->buffer_size);
+ vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
+ zr->inuse[0] = NULL;
+@@ -928,6 +934,7 @@ static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
+ zr->stat_com[j] = cpu_to_le32(1);
+ zr->inuse[j] = NULL;
+ }
++ zr->vbseq = 0;
+
+ if (zr->map_mode != ZORAN_MAP_MODE_RAW) {
+ pci_info(zr->pci_dev, "START JPG\n");
+@@ -1008,7 +1015,7 @@ static const struct vb2_ops zr_video_qops = {
+ .wait_finish = vb2_ops_wait_finish,
+ };
+
+-int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq)
++int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
+ {
+ int err;
+
+@@ -1016,8 +1023,9 @@ int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq)
+ INIT_LIST_HEAD(&zr->queued_bufs);
+
+ vq->dev = &zr->pci_dev->dev;
+- vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- vq->io_modes = VB2_USERPTR | VB2_DMABUF | VB2_MMAP | VB2_READ | VB2_WRITE;
++ vq->type = dir;
++
++ vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ | VB2_WRITE;
+ vq->drv_priv = zr;
+ vq->buf_struct_size = sizeof(struct zr_buffer);
+ vq->ops = &zr_video_qops;
diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile
index 861adacf6c729..5f9612af3fa3c 100644
--- a/drivers/staging/most/dim2/Makefile
@@ -110122,6 +164542,331 @@ index 24277a17cff3d..09115cf4ed00e 100644
-bool dim2_sysfs_get_state_cb(void);
-
#endif /* DIM2_SYSFS_H */
+diff --git a/drivers/staging/mt7621-dts/gbpc1.dts b/drivers/staging/mt7621-dts/gbpc1.dts
+index b65d716868146..02fd9be5e1734 100644
+--- a/drivers/staging/mt7621-dts/gbpc1.dts
++++ b/drivers/staging/mt7621-dts/gbpc1.dts
+@@ -11,7 +11,8 @@
+
+ memory@0 {
+ device_type = "memory";
+- reg = <0x0 0x1c000000>, <0x20000000 0x4000000>;
++ reg = <0x00000000 0x1c000000>,
++ <0x20000000 0x04000000>;
+ };
+
+ chosen {
+@@ -37,24 +38,16 @@
+ gpio-leds {
+ compatible = "gpio-leds";
+
+- system {
+- label = "gb-pc1:green:system";
++ power {
++ label = "green:power";
+ gpios = <&gpio 6 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "default-on";
+ };
+
+- status {
+- label = "gb-pc1:green:status";
++ system {
++ label = "green:system";
+ gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
+- };
+-
+- lan1 {
+- label = "gb-pc1:green:lan1";
+- gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
+- };
+-
+- lan2 {
+- label = "gb-pc1:green:lan2";
+- gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "disk-activity";
+ };
+ };
+ };
+@@ -94,9 +87,8 @@
+
+ partition@50000 {
+ label = "firmware";
+- reg = <0x50000 0x1FB0000>;
++ reg = <0x50000 0x1fb0000>;
+ };
+-
+ };
+ };
+
+@@ -105,9 +97,12 @@
+ };
+
+ &pinctrl {
+- state_default: pinctrl0 {
+- default_gpio: gpio {
+- groups = "wdt", "rgmii2", "uart3";
++ pinctrl-names = "default";
++ pinctrl-0 = <&state_default>;
++
++ state_default: state-default {
++ gpio-pinmux {
++ groups = "rgmii2", "uart3", "wdt";
+ function = "gpio";
+ };
+ };
+@@ -116,12 +111,13 @@
+ &switch0 {
+ ports {
+ port@0 {
++ status = "okay";
+ label = "ethblack";
+- status = "ok";
+ };
++
+ port@4 {
++ status = "okay";
+ label = "ethblue";
+- status = "ok";
+ };
+ };
+ };
+diff --git a/drivers/staging/mt7621-dts/gbpc2.dts b/drivers/staging/mt7621-dts/gbpc2.dts
+index 52760e7351f6c..6f6fed071dda0 100644
+--- a/drivers/staging/mt7621-dts/gbpc2.dts
++++ b/drivers/staging/mt7621-dts/gbpc2.dts
+@@ -1,21 +1,121 @@
+ /dts-v1/;
+
+-#include "gbpc1.dts"
++#include "mt7621.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
+
+ / {
+ compatible = "gnubee,gb-pc2", "mediatek,mt7621-soc";
+ model = "GB-PC2";
++
++ memory@0 {
++ device_type = "memory";
++ reg = <0x00000000 0x1c000000>,
++ <0x20000000 0x04000000>;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,57600";
++ };
++
++ palmbus: palmbus@1e000000 {
++ i2c@900 {
++ status = "okay";
++ };
++ };
++
++ gpio-keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "reset";
++ gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++};
++
++&sdhci {
++ status = "okay";
++};
++
++&spi0 {
++ status = "okay";
++
++ m25p80@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <50000000>;
++ broken-flash-reset;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-boot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ factory: partition@40000 {
++ label = "factory";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++
++ partition@50000 {
++ label = "firmware";
++ reg = <0x50000 0x1fb0000>;
++ };
++ };
+ };
+
+-&default_gpio {
+- groups = "wdt", "uart3";
+- function = "gpio";
++&pcie {
++ status = "okay";
+ };
+
+-&gmac1 {
+- status = "ok";
++&pinctrl {
++ pinctrl-names = "default";
++ pinctrl-0 = <&state_default>;
++
++ state_default: state-default {
++ gpio-pinmux {
++ groups = "wdt";
++ function = "gpio";
++ };
++ };
+ };
+
+-&phy_external {
+- status = "ok";
++&ethernet {
++ gmac1: mac@1 {
++ status = "okay";
++ phy-handle = <&ethphy7>;
++ };
++
++ mdio-bus {
++ ethphy7: ethernet-phy@7 {
++ reg = <7>;
++ phy-mode = "rgmii-rxid";
++ };
++ };
++};
++
++&switch0 {
++ ports {
++ port@0 {
++ status = "okay";
++ label = "ethblack";
++ };
++
++ port@4 {
++ status = "okay";
++ label = "ethblue";
++ };
++ };
+ };
+diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
+index eeabe9c0f4fb8..59a9ce282a3b3 100644
+--- a/drivers/staging/mt7621-dts/mt7621.dtsi
++++ b/drivers/staging/mt7621-dts/mt7621.dtsi
+@@ -36,9 +36,9 @@
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ regulator-always-on;
+- };
++ };
+
+- mmc_fixed_1v8_io: fixedregulator@1 {
++ mmc_fixed_1v8_io: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+@@ -391,37 +391,32 @@
+
+ mediatek,ethsys = <&sysc>;
+
++ pinctrl-names = "default";
++ pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>, <&rgmii2_pins>;
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "rgmii";
++
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+ };
++
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ status = "off";
+ phy-mode = "rgmii-rxid";
+- phy-handle = <&phy_external>;
+ };
++
+ mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+- phy_external: ethernet-phy@5 {
+- status = "off";
+- reg = <5>;
+- phy-mode = "rgmii-rxid";
+-
+- pinctrl-names = "default";
+- pinctrl-0 = <&rgmii2_pins>;
+- };
+-
+ switch0: switch0@0 {
+ compatible = "mediatek,mt7621";
+ #address-cells = <1>;
+@@ -439,36 +434,43 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
++
+ port@0 {
+ status = "off";
+ reg = <0>;
+ label = "lan0";
+ };
++
+ port@1 {
+ status = "off";
+ reg = <1>;
+ label = "lan1";
+ };
++
+ port@2 {
+ status = "off";
+ reg = <2>;
+ label = "lan2";
+ };
++
+ port@3 {
+ status = "off";
+ reg = <3>;
+ label = "lan3";
+ };
++
+ port@4 {
+ status = "off";
+ reg = <4>;
+ label = "lan4";
+ };
++
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "trgmii";
++
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
diff --git a/drivers/staging/r8188eu/core/rtw_led.c b/drivers/staging/r8188eu/core/rtw_led.c
index b33e34cce12e4..f9a8cdd9a1689 100644
--- a/drivers/staging/r8188eu/core/rtw_led.c
@@ -110182,6 +164927,37 @@ index 5a472a4954b0f..63d312d01171e 100644
if (!pevtcmd) {
kfree(pcmd_obj);
return;
+diff --git a/drivers/staging/r8188eu/core/rtw_recv.c b/drivers/staging/r8188eu/core/rtw_recv.c
+index e082edfbaad82..30ca9f1e03639 100644
+--- a/drivers/staging/r8188eu/core/rtw_recv.c
++++ b/drivers/staging/r8188eu/core/rtw_recv.c
+@@ -1942,8 +1942,7 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
+ struct recv_frame *pending_frame;
+ int cnt = 0;
+
+- pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
+- while (pending_frame) {
++ while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
+ cnt++;
+ recv_func_posthandle(padapter, pending_frame);
+ }
+diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
+index 14758361960cc..9f2b86f9b6604 100644
+--- a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
++++ b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
+@@ -572,10 +572,10 @@ static int load_firmware(struct rt_firmware *pFirmware, struct device *device)
+ }
+ memcpy(pFirmware->szFwBuffer, fw->data, fw->size);
+ pFirmware->ulFwLength = fw->size;
+- release_firmware(fw);
+- DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, pFirmware->ulFwLength);
++ dev_dbg(device, "!bUsedWoWLANFw, FmrmwareLen:%d+\n", pFirmware->ulFwLength);
+
+ Exit:
++ release_firmware(fw);
+ return rtStatus;
+ }
+
diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c
index 1fd3750760018..0eccce57c63a6 100644
--- a/drivers/staging/r8188eu/os_dep/ioctl_linux.c
@@ -110522,7 +165298,7 @@ index ab6a24d70cc96..cf79bec916c51 100644
rtw_reset_securitypriv(adapter);
_set_timer(&pmlmepriv->assoc_timer, 1);
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
-index 375d2a742dd2d..ad9c237054c4b 100644
+index 375d2a742dd2d..1a4b4c75c4bf5 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -1489,9 +1489,7 @@ unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
@@ -110545,67 +165321,8 @@ index 375d2a742dd2d..ad9c237054c4b 100644
netdev_dbg(padapter->pnetdev,
"ap recv disassoc reason code(%d) sta:%pM\n",
-@@ -5919,7 +5915,6 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
- struct sta_info *psta_bmc;
- struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
- struct xmit_frame *pxmitframe = NULL;
-- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- /* for BC/MC Frames */
-@@ -5930,8 +5925,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
- if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
- msleep(10);/* 10ms, ATIM(HIQ) Windows */
-
-- /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
-- spin_lock_bh(&pxmitpriv->lock);
-+ spin_lock_bh(&psta_bmc->sleep_q.lock);
-
- xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
- list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
-@@ -5954,8 +5948,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
- rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
- }
-
-- /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
-- spin_unlock_bh(&pxmitpriv->lock);
-+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
-
- /* check hi queue and bmc_sleepq */
- rtw_chk_hi_queue_cmd(padapter);
-diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
-index 5b0a596eefb77..3564e2af5741b 100644
---- a/drivers/staging/rtl8723bs/core/rtw_recv.c
-+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
-@@ -953,10 +953,8 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
- if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
- struct list_head *xmitframe_plist, *xmitframe_phead;
- struct xmit_frame *pxmitframe = NULL;
-- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
-- /* spin_lock_bh(&psta->sleep_q.lock); */
-- spin_lock_bh(&pxmitpriv->lock);
-+ spin_lock_bh(&psta->sleep_q.lock);
-
- xmitframe_phead = get_list_head(&psta->sleep_q);
- xmitframe_plist = get_next(xmitframe_phead);
-@@ -987,12 +985,10 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
- update_beacon(padapter, WLAN_EID_TIM, NULL, true);
- }
-
-- /* spin_unlock_bh(&psta->sleep_q.lock); */
-- spin_unlock_bh(&pxmitpriv->lock);
-+ spin_unlock_bh(&psta->sleep_q.lock);
-
- } else {
-- /* spin_unlock_bh(&psta->sleep_q.lock); */
-- spin_unlock_bh(&pxmitpriv->lock);
-+ spin_unlock_bh(&psta->sleep_q.lock);
-
- if (pstapriv->tim_bitmap&BIT(psta->aid)) {
- if (psta->sleepq_len == 0) {
diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
-index 67ca219f95bf8..3d269842677dd 100644
+index 67ca219f95bf8..5eae3ccb1ff59 100644
--- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
@@ -263,7 +263,6 @@ exit:
@@ -110616,62 +165333,7 @@ index 67ca219f95bf8..3d269842677dd 100644
u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
{
int i;
-@@ -289,51 +288,55 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
-
- /* list_del_init(&psta->wakeup_list); */
-
-- spin_lock_bh(&pxmitpriv->lock);
--
-+ spin_lock_bh(&psta->sleep_q.lock);
- rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
- psta->sleepq_len = 0;
-+ spin_unlock_bh(&psta->sleep_q.lock);
-+
-+ spin_lock_bh(&pxmitpriv->lock);
-
- /* vo */
-- /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */
-+ spin_lock_bh(&pstaxmitpriv->vo_q.sta_pending.lock);
- rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
- phwxmit = pxmitpriv->hwxmits;
- phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
- pstaxmitpriv->vo_q.qcnt = 0;
-- /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */
-+ spin_unlock_bh(&pstaxmitpriv->vo_q.sta_pending.lock);
-
- /* vi */
-- /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */
-+ spin_lock_bh(&pstaxmitpriv->vi_q.sta_pending.lock);
- rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
- phwxmit = pxmitpriv->hwxmits+1;
- phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
- pstaxmitpriv->vi_q.qcnt = 0;
-- /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */
-+ spin_unlock_bh(&pstaxmitpriv->vi_q.sta_pending.lock);
-
- /* be */
-- /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */
-+ spin_lock_bh(&pstaxmitpriv->be_q.sta_pending.lock);
- rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
- list_del_init(&(pstaxmitpriv->be_q.tx_pending));
- phwxmit = pxmitpriv->hwxmits+2;
- phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
- pstaxmitpriv->be_q.qcnt = 0;
-- /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */
-+ spin_unlock_bh(&pstaxmitpriv->be_q.sta_pending.lock);
-
- /* bk */
-- /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */
-+ spin_lock_bh(&pstaxmitpriv->bk_q.sta_pending.lock);
- rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
- list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
- phwxmit = pxmitpriv->hwxmits+3;
- phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
- pstaxmitpriv->bk_q.qcnt = 0;
-- /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */
-+ spin_unlock_bh(&pstaxmitpriv->bk_q.sta_pending.lock);
+@@ -332,8 +331,10 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
spin_unlock_bh(&pxmitpriv->lock);
@@ -110682,7 +165344,7 @@ index 67ca219f95bf8..3d269842677dd 100644
/* re-init sta_info; 20061114 will be init in alloc_stainfo */
/* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */
-@@ -428,6 +431,7 @@ void rtw_free_all_stainfo(struct adapter *padapter)
+@@ -428,6 +429,7 @@ void rtw_free_all_stainfo(struct adapter *padapter)
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
@@ -110690,7 +165352,7 @@ index 67ca219f95bf8..3d269842677dd 100644
if (pstapriv->asoc_sta_count == 1)
return;
-@@ -440,11 +444,16 @@ void rtw_free_all_stainfo(struct adapter *padapter)
+@@ -440,11 +442,16 @@ void rtw_free_all_stainfo(struct adapter *padapter)
psta = list_entry(plist, struct sta_info, hash_list);
if (pbcmc_stainfo != psta)
@@ -110708,105 +165370,6 @@ index 67ca219f95bf8..3d269842677dd 100644
}
/* any station allocated can be searched by hash list */
-diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
-index 79e4d7df1ef57..6b37b42ec2266 100644
---- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
-+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
-@@ -1723,15 +1723,12 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram
- struct list_head *plist, *phead, *tmp;
- struct xmit_frame *pxmitframe;
-
-- spin_lock_bh(&pframequeue->lock);
--
- phead = get_list_head(pframequeue);
- list_for_each_safe(plist, tmp, phead) {
- pxmitframe = list_entry(plist, struct xmit_frame, list);
-
- rtw_free_xmitframe(pxmitpriv, pxmitframe);
- }
-- spin_unlock_bh(&pframequeue->lock);
- }
-
- s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
-@@ -1786,6 +1783,7 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
- struct sta_info *psta;
- struct tx_servq *ptxservq;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ struct xmit_priv *xmit_priv = &padapter->xmitpriv;
- struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
- signed int res = _SUCCESS;
-
-@@ -1803,12 +1801,14 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
-
- ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
-
-+ spin_lock_bh(&xmit_priv->lock);
- if (list_empty(&ptxservq->tx_pending))
- list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
-
- list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
- ptxservq->qcnt++;
- phwxmits[ac_index].accnt++;
-+ spin_unlock_bh(&xmit_priv->lock);
-
- exit:
-
-@@ -2191,11 +2191,10 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
- struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
- struct xmit_frame *pxmitframe = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
-- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- psta_bmc = rtw_get_bcmc_stainfo(padapter);
-
-- spin_lock_bh(&pxmitpriv->lock);
-+ spin_lock_bh(&psta->sleep_q.lock);
-
- xmitframe_phead = get_list_head(&psta->sleep_q);
- list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
-@@ -2296,7 +2295,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
-
- _exit:
-
-- spin_unlock_bh(&pxmitpriv->lock);
-+ spin_unlock_bh(&psta->sleep_q.lock);
-
- if (update_mask)
- update_beacon(padapter, WLAN_EID_TIM, NULL, true);
-@@ -2308,9 +2307,8 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
- struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
- struct xmit_frame *pxmitframe = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
-- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
-- spin_lock_bh(&pxmitpriv->lock);
-+ spin_lock_bh(&psta->sleep_q.lock);
-
- xmitframe_phead = get_list_head(&psta->sleep_q);
- list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
-@@ -2363,7 +2361,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
- }
- }
-
-- spin_unlock_bh(&pxmitpriv->lock);
-+ spin_unlock_bh(&psta->sleep_q.lock);
- }
-
- void enqueue_pending_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
-diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
-index 156d6aba18ca1..5f5c4719b5868 100644
---- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
-+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
-@@ -507,9 +507,7 @@ s32 rtl8723bs_hal_xmit(
- rtw_issue_addbareq_cmd(padapter, pxmitframe);
- }
-
-- spin_lock_bh(&pxmitpriv->lock);
- err = rtw_xmitframe_enqueue(padapter, pxmitframe);
-- spin_unlock_bh(&pxmitpriv->lock);
- if (err != _SUCCESS) {
- rtw_free_xmitframe(pxmitpriv, pxmitframe);
-
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index 9d4a233a861e3..295121c268bd4 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -110822,7 +165385,7 @@ index 9d4a233a861e3..295121c268bd4 100644
psta = NULL;
}
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-index 967f10b9582a8..ea9a53bdb4174 100644
+index 967f10b9582a8..099359fc01152 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -1033,15 +1033,27 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
@@ -110885,6 +165448,40 @@ index 967f10b9582a8..ea9a53bdb4174 100644
if (skip_completion)
return VCHIQ_SUCCESS;
+@@ -1173,6 +1189,9 @@ int vchiq_dump_platform_instances(void *dump_context)
+ int len;
+ int i;
+
++ if (!state)
++ return -ENOTCONN;
++
+ /*
+ * There is no list of instances, so instead scan all services,
+ * marking those that have been dumped.
+diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+index 9429b8a642fbb..630ed0dc24c39 100644
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+@@ -2421,6 +2421,9 @@ void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header)
+ struct vchiq_service *service = find_service_by_handle(handle);
+ int pos;
+
++ if (!service)
++ return;
++
+ while (service->msg_queue_write == service->msg_queue_read +
+ VCHIQ_MAX_SLOTS) {
+ if (wait_for_completion_interruptible(&service->msg_queue_pop))
+@@ -2441,6 +2444,9 @@ struct vchiq_header *vchiq_msg_hold(unsigned int handle)
+ struct vchiq_header *header;
+ int pos;
+
++ if (!service)
++ return NULL;
++
+ if (service->msg_queue_write == service->msg_queue_read)
+ return NULL;
+
diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c
index e06d7e1ebe9c3..61b8cc05f2935 100644
--- a/drivers/staging/wfx/bus_sdio.c
@@ -110919,6 +165516,31 @@ index e06d7e1ebe9c3..61b8cc05f2935 100644
}
static int wfx_sdio_irq_unsubscribe(void *priv)
+diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c
+index 4b9fdf99981b1..9ff69c5e0ae97 100644
+--- a/drivers/staging/wfx/main.c
++++ b/drivers/staging/wfx/main.c
+@@ -309,7 +309,8 @@ struct wfx_dev *wfx_init_common(struct device *dev,
+ wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(wdev->pdata.gpio_wakeup))
+- return NULL;
++ goto err;
++
+ if (wdev->pdata.gpio_wakeup)
+ gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup");
+
+@@ -328,6 +329,10 @@ struct wfx_dev *wfx_init_common(struct device *dev,
+ return NULL;
+
+ return wdev;
++
++err:
++ ieee80211_free_hw(hw);
++ return NULL;
+ }
+
+ int wfx_probe(struct wfx_dev *wdev)
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 8c8524679ba38..0d869b5e309c0 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -111250,6 +165872,34 @@ index 14c6f2bb1b01d..72edf5bd75ee6 100644
}
static void transport_complete_qf(struct se_cmd *cmd)
+diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
+index 9f552f48084cd..0ca5ec14d3dbe 100644
+--- a/drivers/target/target_core_user.c
++++ b/drivers/target/target_core_user.c
+@@ -1821,6 +1821,7 @@ static struct page *tcmu_try_get_data_page(struct tcmu_dev *udev, uint32_t dpi)
+ mutex_lock(&udev->cmdr_lock);
+ page = xa_load(&udev->data_pages, dpi);
+ if (likely(page)) {
++ get_page(page);
+ mutex_unlock(&udev->cmdr_lock);
+ return page;
+ }
+@@ -1877,6 +1878,7 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
+ /* For the vmalloc()ed cmd area pages */
+ addr = (void *)(unsigned long)info->mem[mi].addr + offset;
+ page = vmalloc_to_page(addr);
++ get_page(page);
+ } else {
+ uint32_t dpi;
+
+@@ -1887,7 +1889,6 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
+ return VM_FAULT_SIGBUS;
+ }
+
+- get_page(page);
+ vmf->page = page;
+ return 0;
+ }
diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c
index da6b88e80dc07..297dc62bca298 100644
--- a/drivers/tee/amdtee/core.c
@@ -112001,9 +166651,36 @@ index 45c31f3d6054b..5d046de96a5d0 100644
Newer laptops and tablets that use ACPI may have thermal sensors and
other devices with thermal control capabilities outside the core
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
-index 19926beeb3b71..176b8e5d21246 100644
+index 19926beeb3b71..6aa5fe9736138 100644
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+@@ -53,7 +53,7 @@ struct int3400_thermal_priv {
+ struct art *arts;
+ int trt_count;
+ struct trt *trts;
+- u8 uuid_bitmap;
++ u32 uuid_bitmap;
+ int rel_misc_dev_res;
+ int current_uuid_index;
+ char *data_vault;
+@@ -67,7 +67,7 @@ static int evaluate_odvp(struct int3400_thermal_priv *priv);
+ struct odvp_attr {
+ int odvp;
+ struct int3400_thermal_priv *priv;
+- struct kobj_attribute attr;
++ struct device_attribute attr;
+ };
+
+ static ssize_t data_vault_read(struct file *file, struct kobject *kobj,
+@@ -272,7 +272,7 @@ static int int3400_thermal_run_osc(acpi_handle handle,
+ return result;
+ }
+
+-static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute *attr,
++static ssize_t odvp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+ struct odvp_attr *odvp_attr;
@@ -405,6 +405,10 @@ static void int3400_notify(acpi_handle handle,
thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event);
thermal_prop[4] = NULL;
@@ -112015,6 +166692,18 @@ index 19926beeb3b71..176b8e5d21246 100644
}
static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
+@@ -465,6 +469,11 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv)
+ priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer,
+ obj->package.elements[0].buffer.length,
+ GFP_KERNEL);
++ if (!priv->data_vault) {
++ kfree(buffer.pointer);
++ return;
++ }
++
+ bin_attr_data_vault.private = priv->data_vault;
+ bin_attr_data_vault.size = obj->package.elements[0].buffer.length;
+ kfree(buffer.pointer);
diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
index acebc8ba94e29..217786fba185c 100644
--- a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
@@ -112703,6 +167392,21 @@ index b67e72d5644b3..7c9597a339295 100644
}
out_put:
+diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
+index 82a76cac94deb..32366caca6623 100644
+--- a/drivers/tty/hvc/hvc_iucv.c
++++ b/drivers/tty/hvc/hvc_iucv.c
+@@ -1417,7 +1417,9 @@ out_error:
+ */
+ static int __init hvc_iucv_config(char *val)
+ {
+- return kstrtoul(val, 10, &hvc_iucv_devices);
++ if (kstrtoul(val, 10, &hvc_iucv_devices))
++ pr_warn("hvc_iucv= invalid parameter value '%s'\n", val);
++ return 1;
+ }
+
+
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index f0bf01ea069ae..8ee7ce1206925 100644
--- a/drivers/tty/hvc/hvc_xen.c
@@ -112773,7 +167477,7 @@ index f0bf01ea069ae..8ee7ce1206925 100644
if (info->irq < 0)
info->irq = 0; /* NO_IRQ */
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
-index 1216f3985e18e..da375851af4e6 100644
+index 1216f3985e18e..3b3e169c1f699 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -261,7 +261,6 @@ struct mxser_port {
@@ -112784,7 +167488,51 @@ index 1216f3985e18e..da375851af4e6 100644
spinlock_t slock;
};
-@@ -923,7 +922,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
+@@ -712,6 +711,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+ struct mxser_port *info = container_of(port, struct mxser_port, port);
+ unsigned long page;
+ unsigned long flags;
++ int ret;
+
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
+@@ -721,9 +721,9 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+
+ if (!info->type) {
+ set_bit(TTY_IO_ERROR, &tty->flags);
+- free_page(page);
+ spin_unlock_irqrestore(&info->slock, flags);
+- return 0;
++ ret = 0;
++ goto err_free_xmit;
+ }
+ info->port.xmit_buf = (unsigned char *) page;
+
+@@ -749,8 +749,10 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+ if (capable(CAP_SYS_ADMIN)) {
+ set_bit(TTY_IO_ERROR, &tty->flags);
+ return 0;
+- } else
+- return -ENODEV;
++ }
++
++ ret = -ENODEV;
++ goto err_free_xmit;
+ }
+
+ /*
+@@ -795,6 +797,10 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ return 0;
++err_free_xmit:
++ free_page(page);
++ info->port.xmit_buf = NULL;
++ return ret;
+ }
+
+ /*
+@@ -923,7 +929,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
@@ -112792,7 +167540,7 @@ index 1216f3985e18e..da375851af4e6 100644
mutex_lock(&port->mutex);
mxser_close_port(port);
mxser_flush_buffer(tty);
-@@ -932,7 +930,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
+@@ -932,7 +937,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
mxser_shutdown_port(port);
tty_port_set_initialized(port, 0);
mutex_unlock(&port->mutex);
@@ -112800,7 +167548,7 @@ index 1216f3985e18e..da375851af4e6 100644
/* Right now the tty_port set is done outside of the close_end helper
as we don't yet have everyone using refcounts */
tty_port_close_end(port, tty);
-@@ -1693,7 +1690,7 @@ static bool mxser_port_isr(struct mxser_port *port)
+@@ -1693,7 +1697,7 @@ static bool mxser_port_isr(struct mxser_port *port)
iir &= MOXA_MUST_IIR_MASK;
tty = tty_port_tty_get(&port->port);
@@ -112810,10 +167558,27 @@ index 1216f3985e18e..da375851af4e6 100644
outb(MOXA_MUST_FCR_GDA_MODE_ENABLE | UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
-index 1d92d2a848894..8643b143c408e 100644
+index 1d92d2a848894..1767503de7446 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
-@@ -318,6 +318,7 @@ static struct tty_driver *gsm_tty_driver;
+@@ -73,6 +73,8 @@ module_param(debug, int, 0600);
+ */
+ #define MAX_MRU 1500
+ #define MAX_MTU 1500
++/* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */
++#define PROT_OVERHEAD 7
+ #define GSM_NET_TX_TIMEOUT (HZ*10)
+
+ /*
+@@ -231,6 +233,7 @@ struct gsm_mux {
+ int initiator; /* Did we initiate connection */
+ bool dead; /* Has the mux been shut down */
+ struct gsm_dlci *dlci[NUM_DLCI];
++ int old_c_iflag; /* termios c_iflag value before attach */
+ bool constipated; /* Asked by remote to shut up */
+
+ spinlock_t tx_lock;
+@@ -318,6 +321,7 @@ static struct tty_driver *gsm_tty_driver;
#define GSM1_ESCAPE_BITS 0x20
#define XON 0x11
#define XOFF 0x13
@@ -112821,7 +167586,7 @@ index 1d92d2a848894..8643b143c408e 100644
static const struct tty_port_operations gsm_port_ops;
-@@ -434,7 +435,7 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
+@@ -434,7 +438,7 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
modembits |= MDM_RTR;
if (dlci->modem_tx & TIOCM_RI)
modembits |= MDM_IC;
@@ -112830,7 +167595,7 @@ index 1d92d2a848894..8643b143c408e 100644
modembits |= MDM_DV;
return modembits;
}
-@@ -527,7 +528,8 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len)
+@@ -527,7 +531,8 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len)
int olen = 0;
while (len--) {
if (*input == GSM1_SOF || *input == GSM1_ESCAPE
@@ -112840,7 +167605,16 @@ index 1d92d2a848894..8643b143c408e 100644
*output++ = GSM1_ESCAPE;
*output++ = *input++ ^ GSM1_ESCAPE_BITS;
olen++;
-@@ -1007,25 +1009,25 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data,
+@@ -818,7 +823,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
+ break;
+ case 2: /* Unstructed with modem bits.
+ Always one byte as we never send inline break data */
+- *dp++ = gsm_encode_modem(dlci);
++ *dp++ = (gsm_encode_modem(dlci) << 1) | EA;
+ break;
+ }
+ WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len);
+@@ -1007,25 +1012,25 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data,
* @tty: virtual tty bound to the DLCI
* @dlci: DLCI to affect
* @modem: modem bits (full EA)
@@ -112873,15 +167647,18 @@ index 1d92d2a848894..8643b143c408e 100644
modem = modem & 0x7f;
else {
brk = modem & 0x7f;
-@@ -1082,6 +1084,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
- unsigned int brk = 0;
+@@ -1079,9 +1084,9 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
+ {
+ unsigned int addr = 0;
+ unsigned int modem = 0;
+- unsigned int brk = 0;
struct gsm_dlci *dlci;
int len = clen;
+ int slen;
const u8 *dp = data;
struct tty_struct *tty;
-@@ -1101,6 +1104,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
+@@ -1101,23 +1106,15 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
return;
dlci = gsm->dlci[addr];
@@ -112889,26 +167666,87 @@ index 1d92d2a848894..8643b143c408e 100644
while (gsm_read_ea(&modem, *dp++) == 0) {
len--;
if (len == 0)
-@@ -1117,7 +1121,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
- modem |= (brk & 0x7f);
+ return;
}
+ len--;
+- if (len > 0) {
+- while (gsm_read_ea(&brk, *dp++) == 0) {
+- len--;
+- if (len == 0)
+- return;
+- }
+- modem <<= 7;
+- modem |= (brk & 0x7f);
+- }
tty = tty_port_tty_get(&dlci->port);
- gsm_process_modem(tty, dlci, modem, clen);
-+ gsm_process_modem(tty, dlci, modem, slen);
++ gsm_process_modem(tty, dlci, modem, slen - len);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
-@@ -1427,6 +1431,9 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
+@@ -1296,11 +1293,12 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
+
+ static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl)
+ {
+- struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype);
++ struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 2, gsm->ftype);
+ if (msg == NULL)
+ return;
+- msg->data[0] = (ctrl->cmd << 1) | 2 | EA; /* command */
+- memcpy(msg->data + 1, ctrl->data, ctrl->len);
++ msg->data[0] = (ctrl->cmd << 1) | CR | EA; /* command */
++ msg->data[1] = (ctrl->len << 1) | EA;
++ memcpy(msg->data + 2, ctrl->data, ctrl->len);
+ gsm_data_queue(gsm->dlci[0], msg);
+ }
+
+@@ -1323,7 +1321,6 @@ static void gsm_control_retransmit(struct timer_list *t)
+ spin_lock_irqsave(&gsm->control_lock, flags);
+ ctrl = gsm->pending_cmd;
+ if (ctrl) {
+- gsm->cretries--;
+ if (gsm->cretries == 0) {
+ gsm->pending_cmd = NULL;
+ ctrl->error = -ETIMEDOUT;
+@@ -1332,6 +1329,7 @@ static void gsm_control_retransmit(struct timer_list *t)
+ wake_up(&gsm->event);
+ return;
+ }
++ gsm->cretries--;
+ gsm_control_transmit(gsm, ctrl);
+ mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100);
+ }
+@@ -1372,7 +1370,7 @@ retry:
+
+ /* If DLCI0 is in ADM mode skip retries, it won't respond */
+ if (gsm->dlci[0]->mode == DLCI_MODE_ADM)
+- gsm->cretries = 1;
++ gsm->cretries = 0;
+ else
+ gsm->cretries = gsm->n2;
+
+@@ -1420,13 +1418,20 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control)
+
+ static void gsm_dlci_close(struct gsm_dlci *dlci)
+ {
++ unsigned long flags;
++
+ del_timer(&dlci->t1);
+ if (debug & 8)
+ pr_debug("DLCI %d goes closed.\n", dlci->addr);
+ dlci->state = DLCI_CLOSED;
if (dlci->addr != 0) {
tty_port_tty_hangup(&dlci->port, false);
++ spin_lock_irqsave(&dlci->lock, flags);
kfifo_reset(&dlci->fifo);
++ spin_unlock_irqrestore(&dlci->lock, flags);
+ /* Ensure that gsmtty_open() can return. */
+ tty_port_set_initialized(&dlci->port, 0);
+ wake_up_interruptible(&dlci->port.open_wait);
} else
dlci->gsm->dead = true;
wake_up(&dlci->gsm->event);
-@@ -1486,7 +1493,7 @@ static void gsm_dlci_t1(struct timer_list *t)
+@@ -1486,7 +1491,7 @@ static void gsm_dlci_t1(struct timer_list *t)
dlci->mode = DLCI_MODE_ADM;
gsm_dlci_open(dlci);
} else {
@@ -112917,7 +167755,7 @@ index 1d92d2a848894..8643b143c408e 100644
}
break;
-@@ -1565,6 +1572,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
+@@ -1565,6 +1570,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
struct tty_struct *tty;
unsigned int modem = 0;
int len = clen;
@@ -112925,7 +167763,7 @@ index 1d92d2a848894..8643b143c408e 100644
if (debug & 16)
pr_debug("%d bytes for tty\n", len);
-@@ -1577,12 +1585,14 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
+@@ -1577,12 +1583,16 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
case 2: /* Asynchronous serial with line state in each frame */
while (gsm_read_ea(&modem, *data++) == 0) {
len--;
@@ -112933,11 +167771,13 @@ index 1d92d2a848894..8643b143c408e 100644
if (len == 0)
return;
}
++ len--;
+ slen++;
tty = tty_port_tty_get(port);
if (tty) {
- gsm_process_modem(tty, dlci, modem, clen);
+ gsm_process_modem(tty, dlci, modem, slen);
++ tty_wakeup(tty);
tty_kref_put(tty);
}
fallthrough;
@@ -112955,7 +167795,385 @@ index 1d92d2a848894..8643b143c408e 100644
tty_port_tty_set(&dlci->port, NULL);
tty_kref_put(tty);
-@@ -3173,9 +3188,9 @@ static void gsmtty_throttle(struct tty_struct *tty)
+@@ -1803,7 +1818,6 @@ static void gsm_queue(struct gsm_mux *gsm)
+ gsm_response(gsm, address, UA);
+ gsm_dlci_close(dlci);
+ break;
+- case UA:
+ case UA|PF:
+ if (cr == 0 || dlci == NULL)
+ break;
+@@ -1947,6 +1961,16 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
+
+ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
+ {
++ /* handle XON/XOFF */
++ if ((c & ISO_IEC_646_MASK) == XON) {
++ gsm->constipated = true;
++ return;
++ } else if ((c & ISO_IEC_646_MASK) == XOFF) {
++ gsm->constipated = false;
++ /* Kick the link in case it is idling */
++ gsm_data_kick(gsm, NULL);
++ return;
++ }
+ if (c == GSM1_SOF) {
+ /* EOF is only valid in frame if we have got to the data state
+ and received at least one byte (the FCS) */
+@@ -1961,7 +1985,8 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
+ }
+ /* Any partial frame was a runt so go back to start */
+ if (gsm->state != GSM_START) {
+- gsm->malformed++;
++ if (gsm->state != GSM_SEARCH)
++ gsm->malformed++;
+ gsm->state = GSM_START;
+ }
+ /* A SOF in GSM_START means we are still reading idling or
+@@ -2033,74 +2058,43 @@ static void gsm_error(struct gsm_mux *gsm,
+ gsm->io_error++;
+ }
+
+-static int gsm_disconnect(struct gsm_mux *gsm)
+-{
+- struct gsm_dlci *dlci = gsm->dlci[0];
+- struct gsm_control *gc;
+-
+- if (!dlci)
+- return 0;
+-
+- /* In theory disconnecting DLCI 0 is sufficient but for some
+- modems this is apparently not the case. */
+- gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
+- if (gc)
+- gsm_control_wait(gsm, gc);
+-
+- del_timer_sync(&gsm->t2_timer);
+- /* Now we are sure T2 has stopped */
+-
+- gsm_dlci_begin_close(dlci);
+- wait_event_interruptible(gsm->event,
+- dlci->state == DLCI_CLOSED);
+-
+- if (signal_pending(current))
+- return -EINTR;
+-
+- return 0;
+-}
+-
+ /**
+ * gsm_cleanup_mux - generic GSM protocol cleanup
+ * @gsm: our mux
++ * @disc: disconnect link?
+ *
+ * Clean up the bits of the mux which are the same for all framing
+ * protocols. Remove the mux from the mux table, stop all the timers
+ * and then shut down each device hanging up the channels as we go.
+ */
+
+-static void gsm_cleanup_mux(struct gsm_mux *gsm)
++static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
+ {
+ int i;
+ struct gsm_dlci *dlci = gsm->dlci[0];
+ struct gsm_msg *txq, *ntxq;
+
+ gsm->dead = true;
++ mutex_lock(&gsm->mutex);
+
+- spin_lock(&gsm_mux_lock);
+- for (i = 0; i < MAX_MUX; i++) {
+- if (gsm_mux[i] == gsm) {
+- gsm_mux[i] = NULL;
+- break;
++ if (dlci) {
++ if (disc && dlci->state != DLCI_CLOSED) {
++ gsm_dlci_begin_close(dlci);
++ wait_event(gsm->event, dlci->state == DLCI_CLOSED);
+ }
++ dlci->dead = true;
+ }
+- spin_unlock(&gsm_mux_lock);
+- /* open failed before registering => nothing to do */
+- if (i == MAX_MUX)
+- return;
+
++ /* Finish outstanding timers, making sure they are done */
+ del_timer_sync(&gsm->t2_timer);
+- /* Now we are sure T2 has stopped */
+- if (dlci)
+- dlci->dead = true;
+
+- /* Free up any link layer users */
+- mutex_lock(&gsm->mutex);
+- for (i = 0; i < NUM_DLCI; i++)
++ /* Free up any link layer users and finally the control channel */
++ for (i = NUM_DLCI - 1; i >= 0; i--)
+ if (gsm->dlci[i])
+ gsm_dlci_release(gsm->dlci[i]);
+ mutex_unlock(&gsm->mutex);
+ /* Now wipe the queues */
++ tty_ldisc_flush(gsm->tty);
+ list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
+ kfree(txq);
+ INIT_LIST_HEAD(&gsm->tx_list);
+@@ -2118,7 +2112,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
+ static int gsm_activate_mux(struct gsm_mux *gsm)
+ {
+ struct gsm_dlci *dlci;
+- int i = 0;
+
+ timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+ init_waitqueue_head(&gsm->event);
+@@ -2130,18 +2123,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
+ else
+ gsm->receive = gsm1_receive;
+
+- spin_lock(&gsm_mux_lock);
+- for (i = 0; i < MAX_MUX; i++) {
+- if (gsm_mux[i] == NULL) {
+- gsm->num = i;
+- gsm_mux[i] = gsm;
+- break;
+- }
+- }
+- spin_unlock(&gsm_mux_lock);
+- if (i == MAX_MUX)
+- return -EBUSY;
+-
+ dlci = gsm_dlci_alloc(gsm, 0);
+ if (dlci == NULL)
+ return -ENOMEM;
+@@ -2157,6 +2138,15 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
+ */
+ static void gsm_free_mux(struct gsm_mux *gsm)
+ {
++ int i;
++
++ for (i = 0; i < MAX_MUX; i++) {
++ if (gsm == gsm_mux[i]) {
++ gsm_mux[i] = NULL;
++ break;
++ }
++ }
++ mutex_destroy(&gsm->mutex);
+ kfree(gsm->txframe);
+ kfree(gsm->buf);
+ kfree(gsm);
+@@ -2176,12 +2166,20 @@ static void gsm_free_muxr(struct kref *ref)
+
+ static inline void mux_get(struct gsm_mux *gsm)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&gsm_mux_lock, flags);
+ kref_get(&gsm->ref);
++ spin_unlock_irqrestore(&gsm_mux_lock, flags);
+ }
+
+ static inline void mux_put(struct gsm_mux *gsm)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&gsm_mux_lock, flags);
+ kref_put(&gsm->ref, gsm_free_muxr);
++ spin_unlock_irqrestore(&gsm_mux_lock, flags);
+ }
+
+ static inline unsigned int mux_num_to_base(struct gsm_mux *gsm)
+@@ -2202,6 +2200,7 @@ static inline unsigned int mux_line_to_num(unsigned int line)
+
+ static struct gsm_mux *gsm_alloc_mux(void)
+ {
++ int i;
+ struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL);
+ if (gsm == NULL)
+ return NULL;
+@@ -2210,7 +2209,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
+ kfree(gsm);
+ return NULL;
+ }
+- gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL);
++ gsm->txframe = kmalloc(2 * (MAX_MTU + PROT_OVERHEAD - 1), GFP_KERNEL);
+ if (gsm->txframe == NULL) {
+ kfree(gsm->buf);
+ kfree(gsm);
+@@ -2231,6 +2230,26 @@ static struct gsm_mux *gsm_alloc_mux(void)
+ gsm->mtu = 64;
+ gsm->dead = true; /* Avoid early tty opens */
+
++ /* Store the instance to the mux array or abort if no space is
++ * available.
++ */
++ spin_lock(&gsm_mux_lock);
++ for (i = 0; i < MAX_MUX; i++) {
++ if (!gsm_mux[i]) {
++ gsm_mux[i] = gsm;
++ gsm->num = i;
++ break;
++ }
++ }
++ spin_unlock(&gsm_mux_lock);
++ if (i == MAX_MUX) {
++ mutex_destroy(&gsm->mutex);
++ kfree(gsm->txframe);
++ kfree(gsm->buf);
++ kfree(gsm);
++ return NULL;
++ }
++
+ return gsm;
+ }
+
+@@ -2257,6 +2276,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm,
+
+ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
+ {
++ int ret = 0;
+ int need_close = 0;
+ int need_restart = 0;
+
+@@ -2266,7 +2286,7 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
+ /* Check the MRU/MTU range looks sane */
+ if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
+ return -EINVAL;
+- if (c->n2 < 3)
++ if (c->n2 > 255)
+ return -EINVAL;
+ if (c->encapsulation > 1) /* Basic, advanced, no I */
+ return -EINVAL;
+@@ -2297,19 +2317,11 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
+
+ /*
+ * Close down what is needed, restart and initiate the new
+- * configuration
++ * configuration. On the first time there is no DLCI[0]
++ * and closing or cleaning up is not necessary.
+ */
+-
+- if (need_close || need_restart) {
+- int ret;
+-
+- ret = gsm_disconnect(gsm);
+-
+- if (ret)
+- return ret;
+- }
+- if (need_restart)
+- gsm_cleanup_mux(gsm);
++ if (need_close || need_restart)
++ gsm_cleanup_mux(gsm, true);
+
+ gsm->initiator = c->initiator;
+ gsm->mru = c->mru;
+@@ -2332,10 +2344,13 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
+ * FIXME: We need to separate activation/deactivation from adding
+ * and removing from the mux array
+ */
+- if (need_restart)
+- gsm_activate_mux(gsm);
+- if (gsm->initiator && need_close)
+- gsm_dlci_begin_open(gsm->dlci[0]);
++ if (gsm->dead) {
++ ret = gsm_activate_mux(gsm);
++ if (ret)
++ return ret;
++ if (gsm->initiator)
++ gsm_dlci_begin_open(gsm->dlci[0]);
++ }
+ return 0;
+ }
+
+@@ -2378,6 +2393,9 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
+ 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);
+@@ -2418,7 +2436,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
+ WARN_ON(tty != gsm->tty);
+ for (i = 1; i < NUM_DLCI; i++)
+ tty_unregister_device(gsm_tty_driver, base + i);
+- gsm_cleanup_mux(gsm);
++ /* Restore tty XON/XOFF handling. */
++ gsm->tty->termios.c_iflag = gsm->old_c_iflag;
+ tty_kref_put(gsm->tty);
+ gsm->tty = NULL;
+ }
+@@ -2483,6 +2502,12 @@ static void gsmld_close(struct tty_struct *tty)
+ {
+ struct gsm_mux *gsm = tty->disc_data;
+
++ /* The ldisc locks and closes the port before calling our close. This
++ * means we have no way to do a proper disconnect. We will not bother
++ * to do one.
++ */
++ gsm_cleanup_mux(gsm, false);
++
+ gsmld_detach_gsm(tty, gsm);
+
+ gsmld_flush_buffer(tty);
+@@ -2521,7 +2546,7 @@ static int gsmld_open(struct tty_struct *tty)
+
+ ret = gsmld_attach_gsm(tty, gsm);
+ if (ret != 0) {
+- gsm_cleanup_mux(gsm);
++ gsm_cleanup_mux(gsm, false);
+ mux_put(gsm);
+ }
+ return ret;
+@@ -2880,19 +2905,19 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
+
+ static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk)
+ {
+- u8 modembits[5];
++ u8 modembits[3];
+ struct gsm_control *ctrl;
+ int len = 2;
+
+- if (brk)
++ modembits[0] = (dlci->addr << 2) | 2 | EA; /* DLCI, Valid, EA */
++ if (!brk) {
++ modembits[1] = (gsm_encode_modem(dlci) << 1) | EA;
++ } else {
++ modembits[1] = gsm_encode_modem(dlci) << 1;
++ modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */
+ len++;
+-
+- modembits[0] = len << 1 | EA; /* Data bytes */
+- modembits[1] = dlci->addr << 2 | 3; /* DLCI, EA, 1 */
+- modembits[2] = gsm_encode_modem(dlci) << 1 | EA;
+- if (brk)
+- modembits[3] = brk << 4 | 2 | EA; /* Valid, EA */
+- ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1);
++ }
++ ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len);
+ if (ctrl == NULL)
+ return -ENOMEM;
+ return gsm_control_wait(dlci->gsm, ctrl);
+@@ -3077,13 +3102,17 @@ static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty)
+ static void gsmtty_flush_buffer(struct tty_struct *tty)
+ {
+ struct gsm_dlci *dlci = tty->driver_data;
++ unsigned long flags;
++
+ if (dlci->state == DLCI_CLOSED)
+ return;
+ /* Caution needed: If we implement reliable transport classes
+ then the data being transmitted can't simply be junked once
+ it has first hit the stack. Until then we can just blow it
+ away */
++ spin_lock_irqsave(&dlci->lock, flags);
+ kfifo_reset(&dlci->fifo);
++ spin_unlock_irqrestore(&dlci->lock, flags);
+ /* Need to unhook this DLCI from the transmit queue logic */
+ }
+
+@@ -3173,9 +3202,9 @@ static void gsmtty_throttle(struct tty_struct *tty)
if (dlci->state == DLCI_CLOSED)
return;
if (C_CRTSCTS(tty))
@@ -112967,7 +168185,7 @@ index 1d92d2a848894..8643b143c408e 100644
gsmtty_modem_update(dlci, 0);
}
-@@ -3185,9 +3200,9 @@ static void gsmtty_unthrottle(struct tty_struct *tty)
+@@ -3185,9 +3214,9 @@ static void gsmtty_unthrottle(struct tty_struct *tty)
if (dlci->state == DLCI_CLOSED)
return;
if (C_CRTSCTS(tty))
@@ -113091,6 +168309,19 @@ index 0ec93f1a61f5d..de5b45de50402 100644
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n",
__func__, eol, found, n, c, tail, more);
+diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+index 2350fb3bb5e4c..c2cecc6f47db4 100644
+--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
++++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+@@ -487,7 +487,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
+ port.port.irq = irq_of_parse_and_map(np, 0);
+ port.port.handle_irq = aspeed_vuart_handle_irq;
+ port.port.iotype = UPIO_MEM;
+- port.port.type = PORT_16550A;
++ port.port.type = PORT_ASPEED_VUART;
+ port.port.uartclk = clk;
+ port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
+ | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 7f656fac503fe..0877cf24f7de0 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
@@ -113177,6 +168408,31 @@ index 7f656fac503fe..0877cf24f7de0 100644
return 0;
}
+diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
+index 890fa7ddaa7f3..b3c3f7e5851ab 100644
+--- a/drivers/tty/serial/8250/8250_dma.c
++++ b/drivers/tty/serial/8250/8250_dma.c
+@@ -64,10 +64,19 @@ int serial8250_tx_dma(struct uart_8250_port *p)
+ struct uart_8250_dma *dma = p->dma;
+ struct circ_buf *xmit = &p->port.state->xmit;
+ struct dma_async_tx_descriptor *desc;
++ struct uart_port *up = &p->port;
+ int ret;
+
+- if (dma->tx_running)
++ if (dma->tx_running) {
++ if (up->x_char) {
++ dmaengine_pause(dma->txchan);
++ uart_xchar_out(up, UART_TX);
++ dmaengine_resume(dma->txchan);
++ }
+ return 0;
++ } else if (up->x_char) {
++ uart_xchar_out(up, UART_TX);
++ }
+
+ if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
+ /* We have been called from __dma_tx_complete() */
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a3a0154da567d..49559731bbcf1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
@@ -113241,6 +168497,236 @@ index 673cda3d011d0..948d0a1c6ae8e 100644
if (!dev->irq && (dev->id.sversion == 0xad))
dev->irq = iosapic_serial_irq(dev);
#endif
+diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
+index 848d81e3838c2..49ae73f4d3a04 100644
+--- a/drivers/tty/serial/8250/8250_lpss.c
++++ b/drivers/tty/serial/8250/8250_lpss.c
+@@ -121,8 +121,7 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+ {
+ struct dw_dma_slave *param = &lpss->dma_param;
+ struct pci_dev *pdev = to_pci_dev(port->dev);
+- unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+- struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
++ struct pci_dev *dma_dev;
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_BYT_UART1:
+@@ -141,6 +140,8 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+ return -EINVAL;
+ }
+
++ dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
++
+ param->dma_dev = &dma_dev->dev;
+ param->m_master = 0;
+ param->p_master = 1;
+@@ -156,6 +157,14 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+ return 0;
+ }
+
++static void byt_serial_exit(struct lpss8250 *lpss)
++{
++ struct dw_dma_slave *param = &lpss->dma_param;
++
++ /* Paired with pci_get_slot() in the byt_serial_setup() above */
++ put_device(param->dma_dev);
++}
++
+ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+ {
+ struct uart_8250_dma *dma = &lpss->data.dma;
+@@ -171,6 +180,13 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+ return 0;
+ }
+
++static void ehl_serial_exit(struct lpss8250 *lpss)
++{
++ struct uart_8250_port *up = serial8250_get_port(lpss->data.line);
++
++ up->dma = NULL;
++}
++
+ #ifdef CONFIG_SERIAL_8250_DMA
+ static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
+ .nr_channels = 2,
+@@ -345,8 +361,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ return 0;
+
+ err_exit:
+- if (lpss->board->exit)
+- lpss->board->exit(lpss);
++ lpss->board->exit(lpss);
+ pci_free_irq_vectors(pdev);
+ return ret;
+ }
+@@ -357,8 +372,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
+
+ serial8250_unregister_port(lpss->data.line);
+
+- if (lpss->board->exit)
+- lpss->board->exit(lpss);
++ lpss->board->exit(lpss);
+ pci_free_irq_vectors(pdev);
+ }
+
+@@ -366,12 +380,14 @@ static const struct lpss8250_board byt_board = {
+ .freq = 100000000,
+ .base_baud = 2764800,
+ .setup = byt_serial_setup,
++ .exit = byt_serial_exit,
+ };
+
+ static const struct lpss8250_board ehl_board = {
+ .freq = 200000000,
+ .base_baud = 12500000,
+ .setup = ehl_serial_setup,
++ .exit = ehl_serial_exit,
+ };
+
+ static const struct lpss8250_board qrk_board = {
+diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
+index efa0515139f8e..e6c1791609ddf 100644
+--- a/drivers/tty/serial/8250/8250_mid.c
++++ b/drivers/tty/serial/8250/8250_mid.c
+@@ -73,6 +73,11 @@ static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
+ return 0;
+ }
+
++static void pnw_exit(struct mid8250 *mid)
++{
++ pci_dev_put(mid->dma_dev);
++}
++
+ static int tng_handle_irq(struct uart_port *p)
+ {
+ struct mid8250 *mid = p->private_data;
+@@ -124,6 +129,11 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
+ return 0;
+ }
+
++static void tng_exit(struct mid8250 *mid)
++{
++ pci_dev_put(mid->dma_dev);
++}
++
+ static int dnv_handle_irq(struct uart_port *p)
+ {
+ struct mid8250 *mid = p->private_data;
+@@ -330,9 +340,9 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ pci_set_drvdata(pdev, mid);
+ return 0;
++
+ err:
+- if (mid->board->exit)
+- mid->board->exit(mid);
++ mid->board->exit(mid);
+ return ret;
+ }
+
+@@ -342,8 +352,7 @@ static void mid8250_remove(struct pci_dev *pdev)
+
+ serial8250_unregister_port(mid->line);
+
+- if (mid->board->exit)
+- mid->board->exit(mid);
++ mid->board->exit(mid);
+ }
+
+ static const struct mid8250_board pnw_board = {
+@@ -351,6 +360,7 @@ static const struct mid8250_board pnw_board = {
+ .freq = 50000000,
+ .base_baud = 115200,
+ .setup = pnw_setup,
++ .exit = pnw_exit,
+ };
+
+ static const struct mid8250_board tng_board = {
+@@ -358,6 +368,7 @@ static const struct mid8250_board tng_board = {
+ .freq = 38400000,
+ .base_baud = 1843200,
+ .setup = tng_setup,
++ .exit = tng_exit,
+ };
+
+ static const struct mid8250_board dnv_board = {
+diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
+index fb65dc601b237..de48a58460f47 100644
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -37,6 +37,7 @@
+ #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */
+ #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */
+
++#define MTK_UART_EFR 38 /* I/O: Extended Features Register */
+ #define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */
+ #define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */
+ #define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */
+@@ -53,6 +54,9 @@
+ #define MTK_UART_TX_TRIGGER 1
+ #define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
+
++#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
++#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
++
+ #ifdef CONFIG_SERIAL_8250_DMA
+ enum dma_rx_status {
+ DMA_RX_START = 0,
+@@ -169,7 +173,7 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
+ MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_out(up, UART_EFR, UART_EFR_ECB);
++ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, lcr);
+
+ if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0)
+@@ -232,7 +236,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+ int lcr = serial_in(up, UART_LCR);
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_out(up, UART_EFR, UART_EFR_ECB);
++ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, lcr);
+ lcr = serial_in(up, UART_LCR);
+
+@@ -241,7 +245,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+ serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR);
+ serial_out(up, MTK_UART_ESCAPE_EN, 0x00);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_out(up, UART_EFR, serial_in(up, UART_EFR) &
++ serial_out(up, MTK_UART_EFR, serial_in(up, MTK_UART_EFR) &
+ (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)));
+ serial_out(up, UART_LCR, lcr);
+ mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI |
+@@ -255,8 +259,8 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ /*enable hw flow control*/
+- serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC |
+- (serial_in(up, UART_EFR) &
++ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_HW_FC |
++ (serial_in(up, MTK_UART_EFR) &
+ (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
+
+ serial_out(up, UART_LCR, lcr);
+@@ -270,12 +274,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ /*enable sw flow control */
+- serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
+- (serial_in(up, UART_EFR) &
++ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
++ (serial_in(up, MTK_UART_EFR) &
+ (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
+
+- serial_out(up, UART_XON1, START_CHAR(port->state->port.tty));
+- serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty));
++ serial_out(up, MTK_UART_XON1, START_CHAR(port->state->port.tty));
++ serial_out(up, MTK_UART_XOFF1, STOP_CHAR(port->state->port.tty));
+ serial_out(up, UART_LCR, lcr);
+ mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI);
+ mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI);
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index bce28729dd7bd..be8626234627e 100644
--- a/drivers/tty/serial/8250/8250_of.c
@@ -113265,7 +168751,7 @@ index bce28729dd7bd..be8626234627e 100644
port->iotype = UPIO_MEM;
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
-index 726912b16a559..114a49da564a9 100644
+index 726912b16a559..e7b9805903f4c 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1349,29 +1349,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
@@ -113336,6 +168822,37 @@ index 726912b16a559..114a49da564a9 100644
{
.vendor = PCI_VENDOR_ID_ACCESIO,
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
+@@ -2929,7 +2940,7 @@ enum pci_board_num_t {
+ pbn_panacom2,
+ pbn_panacom4,
+ pbn_plx_romulus,
+- pbn_endrun_2_4000000,
++ pbn_endrun_2_3906250,
+ pbn_oxsemi,
+ pbn_oxsemi_1_3906250,
+ pbn_oxsemi_2_3906250,
+@@ -3461,10 +3472,10 @@ static struct pciserial_board pci_boards[] = {
+ * signal now many ports are available
+ * 2 port 952 Uart support
+ */
+- [pbn_endrun_2_4000000] = {
++ [pbn_endrun_2_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+@@ -4407,7 +4418,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ */
+ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_endrun_2_4000000 },
++ pbn_endrun_2_3906250 },
+ /*
+ * Quatech cards. These actually have configurable clocks but for
+ * now we just use the default.
@@ -5192,8 +5203,30 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
@@ -113348,7 +168865,8 @@ index 726912b16a559..114a49da564a9 100644
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ pbn_b2_2_115200 },
-+ /*
+ /*
+- * BrainBoxes UC-260
+ * Brainboxes UC-235/246
+ */
+ { PCI_VENDOR_ID_INTASHIELD, 0x0AA1,
@@ -113362,8 +168880,7 @@ index 726912b16a559..114a49da564a9 100644
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ pbn_b2_2_115200 },
- /*
-- * BrainBoxes UC-260
++ /*
+ * Brainboxes UC-260/271/701/756
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0D21,
@@ -113452,10 +168969,55 @@ index 726912b16a559..114a49da564a9 100644
/*
* Perle PCI-RAS cards
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
-index 66374704747ec..ec88b706e882f 100644
+index 66374704747ec..2285ef9477556 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
+@@ -307,6 +307,14 @@ static const struct serial8250_config uart_config[] = {
+ .rxtrig_bytes = {1, 32, 64, 112},
+ .flags = UART_CAP_FIFO | UART_CAP_SLEEP,
+ },
++ [PORT_ASPEED_VUART] = {
++ .name = "ASPEED VUART",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
++ .rxtrig_bytes = {1, 4, 8, 14},
++ .flags = UART_CAP_FIFO,
++ },
+ };
+
+ /* Uart divisor latch read */
+@@ -1615,6 +1623,18 @@ static inline void start_tx_rs485(struct uart_port *port)
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct uart_8250_em485 *em485 = up->em485;
+
++ /*
++ * While serial8250_em485_handle_stop_tx() is a noop if
++ * em485->active_timer != &em485->stop_tx_timer, it might happen that
++ * the timer is still armed and triggers only after the current bunch of
++ * chars is send and em485->active_timer == &em485->stop_tx_timer again.
++ * So cancel the timer. There is still a theoretical race condition if
++ * the timer is already running and only comes around to check for
++ * em485->active_timer when &em485->stop_tx_timer is armed again.
++ */
++ if (em485->active_timer == &em485->stop_tx_timer)
++ hrtimer_try_to_cancel(&em485->stop_tx_timer);
++
+ em485->active_timer = NULL;
+
+ if (em485->tx_stopped) {
+@@ -1799,9 +1819,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
+ int count;
+
+ if (port->x_char) {
+- serial_out(up, UART_TX, port->x_char);
+- port->icount.tx++;
+- port->x_char = 0;
++ uart_xchar_out(port, UART_TX);
+ return;
+ }
+ if (uart_tx_stopped(port)) {
+@@ -2024,13 +2042,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr;
@@ -113469,7 +169031,7 @@ index 66374704747ec..ec88b706e882f 100644
mcr = serial8250_TIOCM_to_MCR(mctrl);
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-@@ -2696,21 +2689,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
+@@ -2696,21 +2707,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
{
struct uart_8250_port *up = up_to_u8250p(port);
@@ -113505,7 +169067,7 @@ index 66374704747ec..ec88b706e882f 100644
baud = serial8250_get_baud_rate(port, termios, NULL);
quot = serial8250_get_divisor(port, baud, &frac);
-@@ -2727,7 +2731,9 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
+@@ -2727,7 +2749,9 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
serial8250_rpm_put(up);
out_lock:
@@ -113516,6 +169078,15 @@ index 66374704747ec..ec88b706e882f 100644
}
EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
+@@ -3316,7 +3340,7 @@ static void serial8250_console_restore(struct uart_8250_port *up)
+
+ serial8250_set_divisor(port, baud, quot, frac);
+ serial_port_out(port, UART_LCR, up->lcr);
+- serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
++ serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
+ }
+
+ /*
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index e744b953ca346..47654073123d6 100644
--- a/drivers/tty/serial/amba-pl010.c
@@ -113536,10 +169107,30 @@ index e744b953ca346..47654073123d6 100644
quot -= 1;
writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
-index d361cd84ff8cf..da54f827c5efc 100644
+index d361cd84ff8cf..3d40306971b81 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
-@@ -1615,8 +1615,12 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
+@@ -1288,13 +1288,18 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
+
+ static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
+ {
++ /*
++ * To be on the safe side only time out after twice as many iterations
++ * as fifo size.
++ */
++ const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2;
+ struct uart_port *port = &uap->port;
+ int i = 0;
+ u32 cr;
+
+ /* Wait until hardware tx queue is empty */
+ while (!pl011_tx_empty(port)) {
+- if (i == port->fifosize) {
++ if (i > MAX_TX_DRAIN_ITERS) {
+ dev_warn(port->dev,
+ "timeout while draining hardware tx queue\n");
+ break;
+@@ -1615,8 +1620,12 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port);
unsigned int cr;
@@ -113554,7 +169145,16 @@ index d361cd84ff8cf..da54f827c5efc 100644
cr = pl011_read(uap, REG_CR);
-@@ -2105,9 +2109,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+@@ -2095,7 +2104,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+ * with the given baud rate. We use this as the poll interval when we
+ * wait for the tx queue to empty.
+ */
+- uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud;
++ uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud);
+
+ pl011_setup_status_masks(port, termios);
+
+@@ -2105,9 +2114,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
if (port->rs485.flags & SER_RS485_ENABLED)
termios->c_cflag &= ~CRTSCTS;
@@ -113564,7 +169164,7 @@ index d361cd84ff8cf..da54f827c5efc 100644
if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS)
-@@ -2183,32 +2185,13 @@ static const char *pl011_type(struct uart_port *port)
+@@ -2183,32 +2190,13 @@ static const char *pl011_type(struct uart_port *port)
return uap->port.type == PORT_AMBA ? uap->type : NULL;
}
@@ -113598,7 +169198,7 @@ index d361cd84ff8cf..da54f827c5efc 100644
}
/*
-@@ -2223,6 +2206,8 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
+@@ -2223,6 +2211,8 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
@@ -113607,7 +169207,7 @@ index d361cd84ff8cf..da54f827c5efc 100644
return ret;
}
-@@ -2275,8 +2260,6 @@ static const struct uart_ops amba_pl011_pops = {
+@@ -2275,8 +2265,6 @@ static const struct uart_ops amba_pl011_pops = {
.flush_buffer = pl011_dma_flush_buffer,
.set_termios = pl011_set_termios,
.type = pl011_type,
@@ -113616,7 +169216,7 @@ index d361cd84ff8cf..da54f827c5efc 100644
.config_port = pl011_config_port,
.verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
-@@ -2306,8 +2289,6 @@ static const struct uart_ops sbsa_uart_pops = {
+@@ -2306,8 +2294,6 @@ static const struct uart_ops sbsa_uart_pops = {
.shutdown = sbsa_uart_shutdown,
.set_termios = sbsa_uart_set_termios,
.type = pl011_type,
@@ -113625,7 +169225,7 @@ index d361cd84ff8cf..da54f827c5efc 100644
.config_port = pl011_config_port,
.verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
-@@ -2947,6 +2928,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match);
+@@ -2947,6 +2933,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match);
static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = {
{ "ARMH0011", 0 },
@@ -113685,8 +169285,26 @@ index c719aa2b18328..d6d3db9c3b1f8 100644
#endif /* CONFIG_CONSOLE_POLL */
+diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
+index 13ac36e2da4f0..c7f81aa1ce912 100644
+--- a/drivers/tty/serial/digicolor-usart.c
++++ b/drivers/tty/serial/digicolor-usart.c
+@@ -471,11 +471,10 @@ static int digicolor_uart_probe(struct platform_device *pdev)
+ if (IS_ERR(uart_clk))
+ return PTR_ERR(uart_clk);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- dp->port.mapbase = res->start;
+- dp->port.membase = devm_ioremap_resource(&pdev->dev, res);
++ dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(dp->port.membase))
+ return PTR_ERR(dp->port.membase);
++ dp->port.mapbase = res->start;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
-index b1e7190ae4836..ac5112def40d1 100644
+index b1e7190ae4836..33e5eba6ff043 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2625,6 +2625,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
@@ -113697,8 +169315,56 @@ index b1e7190ae4836..ac5112def40d1 100644
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
+@@ -2649,6 +2650,7 @@ static int lpuart_probe(struct platform_device *pdev)
+ struct device_node *np = pdev->dev.of_node;
+ struct lpuart_port *sport;
+ struct resource *res;
++ irq_handler_t handler;
+ int ret;
+
+ sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
+@@ -2726,17 +2728,11 @@ static int lpuart_probe(struct platform_device *pdev)
+
+ if (lpuart_is_32(sport)) {
+ lpuart_reg.cons = LPUART32_CONSOLE;
+- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,
+- DRIVER_NAME, sport);
++ handler = lpuart32_int;
+ } else {
+ lpuart_reg.cons = LPUART_CONSOLE;
+- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0,
+- DRIVER_NAME, sport);
++ handler = lpuart_int;
+ }
+-
+- if (ret)
+- goto failed_irq_request;
+-
+ ret = uart_add_one_port(&lpuart_reg, &sport->port);
+ if (ret)
+ goto failed_attach_port;
+@@ -2758,13 +2754,18 @@ static int lpuart_probe(struct platform_device *pdev)
+
+ sport->port.rs485_config(&sport->port, &sport->port.rs485);
+
++ ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0,
++ DRIVER_NAME, sport);
++ if (ret)
++ goto failed_irq_request;
++
+ return 0;
+
++failed_irq_request:
+ failed_get_rs485:
+ failed_reset:
+ uart_remove_one_port(&lpuart_reg, &sport->port);
+ failed_attach_port:
+-failed_irq_request:
+ lpuart_disable_clks(sport);
+ failed_clock_enable:
+ failed_out_of_range:
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
-index 8b121cd869e94..7820049aba5af 100644
+index 8b121cd869e94..b7ef075a4005b 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -486,18 +486,21 @@ static void imx_uart_stop_tx(struct uart_port *port)
@@ -113724,6 +169390,15 @@ index 8b121cd869e94..7820049aba5af 100644
ucr2 &= ~UCR2_RXEN;
imx_uart_writel(sport, ucr2, UCR2);
+@@ -1435,7 +1438,7 @@ static int imx_uart_startup(struct uart_port *port)
+ imx_uart_writel(sport, ucr1, UCR1);
+
+ ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR);
+- if (!sport->dma_is_enabled)
++ if (!dma_is_inited)
+ ucr4 |= UCR4_OREN;
+ if (sport->inverted_rx)
+ ucr4 |= UCR4_INVR;
@@ -1544,7 +1547,7 @@ static void imx_uart_shutdown(struct uart_port *port)
imx_uart_writel(sport, ucr1, UCR1);
@@ -113751,6 +169426,30 @@ index 8b121cd869e94..7820049aba5af 100644
imx_uart_console_setup(struct console *co, char *options)
{
struct imx_port *sport;
+diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
+index 49d0c7f2b29b8..79b7db8580e05 100644
+--- a/drivers/tty/serial/kgdboc.c
++++ b/drivers/tty/serial/kgdboc.c
+@@ -403,16 +403,16 @@ static int kgdboc_option_setup(char *opt)
+ {
+ if (!opt) {
+ pr_err("config string not provided\n");
+- return -EINVAL;
++ return 1;
+ }
+
+ if (strlen(opt) >= MAX_CONFIG_LEN) {
+ pr_err("config string too long\n");
+- return -ENOSPC;
++ return 1;
+ }
+ strcpy(config, opt);
+
+- return 0;
++ return 1;
+ }
+
+ __setup("kgdboc=", kgdboc_option_setup);
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index dbc0559a91575..7f74bf7bdcff8 100644
--- a/drivers/tty/serial/liteuart.c
@@ -113816,6 +169515,23 @@ index fcef7a961430b..489d19274f9ad 100644
if (!dma->chan)
return;
+diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
+index e2f49863e9c2d..319533b3c32a5 100644
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -922,11 +922,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
+ return;
+ }
+
+- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+- spin_unlock(&port->lock);
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+- spin_lock(&port->lock);
+- }
+
+ if (uart_circ_empty(xmit))
+ s3c24xx_serial_stop_tx(port);
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index acbb615dd28fd..0ab788058fa2a 100644
--- a/drivers/tty/serial/sc16is7xx.c
@@ -113859,7 +169575,7 @@ index 45e2e4109acd0..b6223fab0687d 100644
};
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
-index 0e2e35ab64c79..dc6129ddef85d 100644
+index 0e2e35ab64c79..eb15423f935a3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -162,7 +162,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise)
@@ -113905,7 +169621,28 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
if (!tty || C_HUPCL(tty))
uart_port_dtr_rts(uport, 0);
-@@ -1068,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+@@ -645,6 +652,20 @@ static void uart_flush_buffer(struct tty_struct *tty)
+ tty_port_tty_wakeup(&state->port);
+ }
+
++/*
++ * This function performs low-level write of high-priority XON/XOFF
++ * character and accounting for it.
++ *
++ * Requires uart_port to implement .serial_out().
++ */
++void uart_xchar_out(struct uart_port *uport, int offset)
++{
++ serial_port_out(uport, offset, uport->x_char);
++ uport->icount.tx++;
++ uport->x_char = 0;
++}
++EXPORT_SYMBOL_GPL(uart_xchar_out);
++
+ /*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+@@ -1068,6 +1089,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
goto out;
if (!tty_io_error(tty)) {
@@ -113917,7 +169654,7 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
uart_update_mctrl(uport, set, clear);
ret = 0;
}
-@@ -1542,6 +1554,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
+@@ -1542,6 +1568,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = uart_port_check(state);
@@ -113925,7 +169662,7 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
/*
* At this point, we stop accepting input. To do this, we
-@@ -1563,8 +1576,18 @@ static void uart_tty_port_shutdown(struct tty_port *port)
+@@ -1563,8 +1590,18 @@ static void uart_tty_port_shutdown(struct tty_port *port)
*/
tty_port_set_suspended(port, 0);
@@ -113937,15 +169674,15 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
+ buf = state->xmit.buf;
+ state->xmit.buf = NULL;
+ spin_unlock_irq(&uport->lock);
-+
+
+ if (buf)
+ free_page((unsigned long)buf);
-
++
+ uart_change_pm(state, UART_PM_STATE_OFF);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
-@@ -2094,8 +2117,11 @@ uart_set_options(struct uart_port *port, struct console *co,
+@@ -2094,8 +2131,11 @@ uart_set_options(struct uart_port *port, struct console *co,
* Allow the setting of the UART parameters with a NULL console
* too:
*/
@@ -113958,7 +169695,7 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
return 0;
}
-@@ -2229,6 +2255,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
+@@ -2229,6 +2269,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
*/
memset(&termios, 0, sizeof(struct ktermios));
termios.c_cflag = uport->cons->cflag;
@@ -113967,7 +169704,7 @@ index 0e2e35ab64c79..dc6129ddef85d 100644
/*
* If that's unset, use the tty termios setting.
-@@ -2365,7 +2393,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+@@ -2365,7 +2407,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
* We probably don't need a spinlock around this, but
*/
spin_lock_irqsave(&port->lock, flags);
@@ -114099,7 +169836,7 @@ index 3639bb6dc372e..58013698635f0 100644
ret = vc_allocate(arg);
console_unlock();
diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
-index 1f3b4a1422126..f9af7ebe003d7 100644
+index 1f3b4a1422126..d6d515d598dc0 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
@@ -114137,6 +169874,402 @@ index 1f3b4a1422126..f9af7ebe003d7 100644
}
if (!request->stream_id) {
+@@ -2696,6 +2684,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
+ struct usb_request *request;
+ struct cdns3_request *priv_req;
+ struct cdns3_trb *trb = NULL;
++ struct cdns3_trb trb_tmp;
+ int ret;
+ int val;
+
+@@ -2705,8 +2694,10 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
+ if (request) {
+ priv_req = to_cdns3_request(request);
+ trb = priv_req->trb;
+- if (trb)
++ if (trb) {
++ trb_tmp = *trb;
+ trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE);
++ }
+ }
+
+ writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
+@@ -2721,7 +2712,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
+
+ if (request) {
+ if (trb)
+- trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE);
++ *trb = trb_tmp;
+
+ cdns3_rearm_transfer(priv_ep, 1);
+ }
+diff --git a/drivers/usb/cdns3/cdnsp-debug.h b/drivers/usb/cdns3/cdnsp-debug.h
+index a8776df2d4e0c..f0ca865cce2a0 100644
+--- a/drivers/usb/cdns3/cdnsp-debug.h
++++ b/drivers/usb/cdns3/cdnsp-debug.h
+@@ -182,208 +182,211 @@ static inline const char *cdnsp_decode_trb(char *str, size_t size, u32 field0,
+ int ep_id = TRB_TO_EP_INDEX(field3) - 1;
+ int type = TRB_FIELD_TO_TYPE(field3);
+ unsigned int ep_num;
+- int ret = 0;
++ int ret;
+ u32 temp;
+
+ ep_num = DIV_ROUND_UP(ep_id, 2);
+
+ switch (type) {
+ case TRB_LINK:
+- ret += snprintf(str, size,
+- "LINK %08x%08x intr %ld type '%s' flags %c:%c:%c:%c",
+- field1, field0, GET_INTR_TARGET(field2),
+- cdnsp_trb_type_string(type),
+- field3 & TRB_IOC ? 'I' : 'i',
+- field3 & TRB_CHAIN ? 'C' : 'c',
+- field3 & TRB_TC ? 'T' : 't',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "LINK %08x%08x intr %ld type '%s' flags %c:%c:%c:%c",
++ field1, field0, GET_INTR_TARGET(field2),
++ cdnsp_trb_type_string(type),
++ field3 & TRB_IOC ? 'I' : 'i',
++ field3 & TRB_CHAIN ? 'C' : 'c',
++ field3 & TRB_TC ? 'T' : 't',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_TRANSFER:
+ case TRB_COMPLETION:
+ case TRB_PORT_STATUS:
+ case TRB_HC_EVENT:
+- ret += snprintf(str, size,
+- "ep%d%s(%d) type '%s' TRB %08x%08x status '%s'"
+- " len %ld slot %ld flags %c:%c",
+- ep_num, ep_id % 2 ? "out" : "in",
+- TRB_TO_EP_INDEX(field3),
+- cdnsp_trb_type_string(type), field1, field0,
+- cdnsp_trb_comp_code_string(GET_COMP_CODE(field2)),
+- EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3),
+- field3 & EVENT_DATA ? 'E' : 'e',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "ep%d%s(%d) type '%s' TRB %08x%08x status '%s'"
++ " len %ld slot %ld flags %c:%c",
++ ep_num, ep_id % 2 ? "out" : "in",
++ TRB_TO_EP_INDEX(field3),
++ cdnsp_trb_type_string(type), field1, field0,
++ cdnsp_trb_comp_code_string(GET_COMP_CODE(field2)),
++ EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3),
++ field3 & EVENT_DATA ? 'E' : 'e',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_MFINDEX_WRAP:
+- ret += snprintf(str, size, "%s: flags %c",
+- cdnsp_trb_type_string(type),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size, "%s: flags %c",
++ cdnsp_trb_type_string(type),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_SETUP:
+- ret += snprintf(str, size,
+- "type '%s' bRequestType %02x bRequest %02x "
+- "wValue %02x%02x wIndex %02x%02x wLength %d "
+- "length %ld TD size %ld intr %ld Setup ID %ld "
+- "flags %c:%c:%c",
+- cdnsp_trb_type_string(type),
+- field0 & 0xff,
+- (field0 & 0xff00) >> 8,
+- (field0 & 0xff000000) >> 24,
+- (field0 & 0xff0000) >> 16,
+- (field1 & 0xff00) >> 8,
+- field1 & 0xff,
+- (field1 & 0xff000000) >> 16 |
+- (field1 & 0xff0000) >> 16,
+- TRB_LEN(field2), GET_TD_SIZE(field2),
+- GET_INTR_TARGET(field2),
+- TRB_SETUPID_TO_TYPE(field3),
+- field3 & TRB_IDT ? 'D' : 'd',
+- field3 & TRB_IOC ? 'I' : 'i',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "type '%s' bRequestType %02x bRequest %02x "
++ "wValue %02x%02x wIndex %02x%02x wLength %d "
++ "length %ld TD size %ld intr %ld Setup ID %ld "
++ "flags %c:%c:%c",
++ cdnsp_trb_type_string(type),
++ field0 & 0xff,
++ (field0 & 0xff00) >> 8,
++ (field0 & 0xff000000) >> 24,
++ (field0 & 0xff0000) >> 16,
++ (field1 & 0xff00) >> 8,
++ field1 & 0xff,
++ (field1 & 0xff000000) >> 16 |
++ (field1 & 0xff0000) >> 16,
++ TRB_LEN(field2), GET_TD_SIZE(field2),
++ GET_INTR_TARGET(field2),
++ TRB_SETUPID_TO_TYPE(field3),
++ field3 & TRB_IDT ? 'D' : 'd',
++ field3 & TRB_IOC ? 'I' : 'i',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_DATA:
+- ret += snprintf(str, size,
+- "type '%s' Buffer %08x%08x length %ld TD size %ld "
+- "intr %ld flags %c:%c:%c:%c:%c:%c:%c",
+- cdnsp_trb_type_string(type),
+- field1, field0, TRB_LEN(field2),
+- GET_TD_SIZE(field2),
+- GET_INTR_TARGET(field2),
+- field3 & TRB_IDT ? 'D' : 'i',
+- field3 & TRB_IOC ? 'I' : 'i',
+- field3 & TRB_CHAIN ? 'C' : 'c',
+- field3 & TRB_NO_SNOOP ? 'S' : 's',
+- field3 & TRB_ISP ? 'I' : 'i',
+- field3 & TRB_ENT ? 'E' : 'e',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "type '%s' Buffer %08x%08x length %ld TD size %ld "
++ "intr %ld flags %c:%c:%c:%c:%c:%c:%c",
++ cdnsp_trb_type_string(type),
++ field1, field0, TRB_LEN(field2),
++ GET_TD_SIZE(field2),
++ GET_INTR_TARGET(field2),
++ field3 & TRB_IDT ? 'D' : 'i',
++ field3 & TRB_IOC ? 'I' : 'i',
++ field3 & TRB_CHAIN ? 'C' : 'c',
++ field3 & TRB_NO_SNOOP ? 'S' : 's',
++ field3 & TRB_ISP ? 'I' : 'i',
++ field3 & TRB_ENT ? 'E' : 'e',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_STATUS:
+- ret += snprintf(str, size,
+- "Buffer %08x%08x length %ld TD size %ld intr"
+- "%ld type '%s' flags %c:%c:%c:%c",
+- field1, field0, TRB_LEN(field2),
+- GET_TD_SIZE(field2),
+- GET_INTR_TARGET(field2),
+- cdnsp_trb_type_string(type),
+- field3 & TRB_IOC ? 'I' : 'i',
+- field3 & TRB_CHAIN ? 'C' : 'c',
+- field3 & TRB_ENT ? 'E' : 'e',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "Buffer %08x%08x length %ld TD size %ld intr"
++ "%ld type '%s' flags %c:%c:%c:%c",
++ field1, field0, TRB_LEN(field2),
++ GET_TD_SIZE(field2),
++ GET_INTR_TARGET(field2),
++ cdnsp_trb_type_string(type),
++ field3 & TRB_IOC ? 'I' : 'i',
++ field3 & TRB_CHAIN ? 'C' : 'c',
++ field3 & TRB_ENT ? 'E' : 'e',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_NORMAL:
+ case TRB_ISOC:
+ case TRB_EVENT_DATA:
+ case TRB_TR_NOOP:
+- ret += snprintf(str, size,
+- "type '%s' Buffer %08x%08x length %ld "
+- "TD size %ld intr %ld "
+- "flags %c:%c:%c:%c:%c:%c:%c:%c:%c",
+- cdnsp_trb_type_string(type),
+- field1, field0, TRB_LEN(field2),
+- GET_TD_SIZE(field2),
+- GET_INTR_TARGET(field2),
+- field3 & TRB_BEI ? 'B' : 'b',
+- field3 & TRB_IDT ? 'T' : 't',
+- field3 & TRB_IOC ? 'I' : 'i',
+- field3 & TRB_CHAIN ? 'C' : 'c',
+- field3 & TRB_NO_SNOOP ? 'S' : 's',
+- field3 & TRB_ISP ? 'I' : 'i',
+- field3 & TRB_ENT ? 'E' : 'e',
+- field3 & TRB_CYCLE ? 'C' : 'c',
+- !(field3 & TRB_EVENT_INVALIDATE) ? 'V' : 'v');
++ ret = snprintf(str, size,
++ "type '%s' Buffer %08x%08x length %ld "
++ "TD size %ld intr %ld "
++ "flags %c:%c:%c:%c:%c:%c:%c:%c:%c",
++ cdnsp_trb_type_string(type),
++ field1, field0, TRB_LEN(field2),
++ GET_TD_SIZE(field2),
++ GET_INTR_TARGET(field2),
++ field3 & TRB_BEI ? 'B' : 'b',
++ field3 & TRB_IDT ? 'T' : 't',
++ field3 & TRB_IOC ? 'I' : 'i',
++ field3 & TRB_CHAIN ? 'C' : 'c',
++ field3 & TRB_NO_SNOOP ? 'S' : 's',
++ field3 & TRB_ISP ? 'I' : 'i',
++ field3 & TRB_ENT ? 'E' : 'e',
++ field3 & TRB_CYCLE ? 'C' : 'c',
++ !(field3 & TRB_EVENT_INVALIDATE) ? 'V' : 'v');
+ break;
+ case TRB_CMD_NOOP:
+ case TRB_ENABLE_SLOT:
+- ret += snprintf(str, size, "%s: flags %c",
+- cdnsp_trb_type_string(type),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size, "%s: flags %c",
++ cdnsp_trb_type_string(type),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_DISABLE_SLOT:
+- ret += snprintf(str, size, "%s: slot %ld flags %c",
+- cdnsp_trb_type_string(type),
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size, "%s: slot %ld flags %c",
++ cdnsp_trb_type_string(type),
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_ADDR_DEV:
+- ret += snprintf(str, size,
+- "%s: ctx %08x%08x slot %ld flags %c:%c",
+- cdnsp_trb_type_string(type), field1, field0,
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_BSR ? 'B' : 'b',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ctx %08x%08x slot %ld flags %c:%c",
++ cdnsp_trb_type_string(type), field1, field0,
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_BSR ? 'B' : 'b',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_CONFIG_EP:
+- ret += snprintf(str, size,
+- "%s: ctx %08x%08x slot %ld flags %c:%c",
+- cdnsp_trb_type_string(type), field1, field0,
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_DC ? 'D' : 'd',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ctx %08x%08x slot %ld flags %c:%c",
++ cdnsp_trb_type_string(type), field1, field0,
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_DC ? 'D' : 'd',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_EVAL_CONTEXT:
+- ret += snprintf(str, size,
+- "%s: ctx %08x%08x slot %ld flags %c",
+- cdnsp_trb_type_string(type), field1, field0,
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ctx %08x%08x slot %ld flags %c",
++ cdnsp_trb_type_string(type), field1, field0,
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_RESET_EP:
+ case TRB_HALT_ENDPOINT:
+ case TRB_FLUSH_ENDPOINT:
+- ret += snprintf(str, size,
+- "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c",
+- cdnsp_trb_type_string(type),
+- ep_num, ep_id % 2 ? "out" : "in",
+- TRB_TO_EP_INDEX(field3), field1, field0,
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c",
++ cdnsp_trb_type_string(type),
++ ep_num, ep_id % 2 ? "out" : "in",
++ TRB_TO_EP_INDEX(field3), field1, field0,
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_STOP_RING:
+- ret += snprintf(str, size,
+- "%s: ep%d%s(%d) slot %ld sp %d flags %c",
+- cdnsp_trb_type_string(type),
+- ep_num, ep_id % 2 ? "out" : "in",
+- TRB_TO_EP_INDEX(field3),
+- TRB_TO_SLOT_ID(field3),
+- TRB_TO_SUSPEND_PORT(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ep%d%s(%d) slot %ld sp %d flags %c",
++ cdnsp_trb_type_string(type),
++ ep_num, ep_id % 2 ? "out" : "in",
++ TRB_TO_EP_INDEX(field3),
++ TRB_TO_SLOT_ID(field3),
++ TRB_TO_SUSPEND_PORT(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_SET_DEQ:
+- ret += snprintf(str, size,
+- "%s: ep%d%s(%d) deq %08x%08x stream %ld slot %ld flags %c",
+- cdnsp_trb_type_string(type),
+- ep_num, ep_id % 2 ? "out" : "in",
+- TRB_TO_EP_INDEX(field3), field1, field0,
+- TRB_TO_STREAM_ID(field2),
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size,
++ "%s: ep%d%s(%d) deq %08x%08x stream %ld slot %ld flags %c",
++ cdnsp_trb_type_string(type),
++ ep_num, ep_id % 2 ? "out" : "in",
++ TRB_TO_EP_INDEX(field3), field1, field0,
++ TRB_TO_STREAM_ID(field2),
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_RESET_DEV:
+- ret += snprintf(str, size, "%s: slot %ld flags %c",
+- cdnsp_trb_type_string(type),
+- TRB_TO_SLOT_ID(field3),
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ ret = snprintf(str, size, "%s: slot %ld flags %c",
++ cdnsp_trb_type_string(type),
++ TRB_TO_SLOT_ID(field3),
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_ENDPOINT_NRDY:
+- temp = TRB_TO_HOST_STREAM(field2);
+-
+- ret += snprintf(str, size,
+- "%s: ep%d%s(%d) H_SID %x%s%s D_SID %lx flags %c:%c",
+- cdnsp_trb_type_string(type),
+- ep_num, ep_id % 2 ? "out" : "in",
+- TRB_TO_EP_INDEX(field3), temp,
+- temp == STREAM_PRIME_ACK ? "(PRIME)" : "",
+- temp == STREAM_REJECTED ? "(REJECTED)" : "",
+- TRB_TO_DEV_STREAM(field0),
+- field3 & TRB_STAT ? 'S' : 's',
+- field3 & TRB_CYCLE ? 'C' : 'c');
++ temp = TRB_TO_HOST_STREAM(field2);
++
++ ret = snprintf(str, size,
++ "%s: ep%d%s(%d) H_SID %x%s%s D_SID %lx flags %c:%c",
++ cdnsp_trb_type_string(type),
++ ep_num, ep_id % 2 ? "out" : "in",
++ TRB_TO_EP_INDEX(field3), temp,
++ temp == STREAM_PRIME_ACK ? "(PRIME)" : "",
++ temp == STREAM_REJECTED ? "(REJECTED)" : "",
++ TRB_TO_DEV_STREAM(field0),
++ field3 & TRB_STAT ? 'S' : 's',
++ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ default:
+- ret += snprintf(str, size,
+- "type '%s' -> raw %08x %08x %08x %08x",
+- cdnsp_trb_type_string(type),
+- field0, field1, field2, field3);
++ ret = snprintf(str, size,
++ "type '%s' -> raw %08x %08x %08x %08x",
++ cdnsp_trb_type_string(type),
++ field0, field1, field2, field3);
+ }
+
++ if (ret >= size)
++ pr_info("CDNSP: buffer overflowed.\n");
++
+ return str;
+ }
+
diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c
index 27df0c6978978..e85bf768c66da 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.c
@@ -114355,6 +170488,69 @@ index 2b18f5088ae4a..a56f06368d142 100644
}
static int ci_controller_resume(struct device *dev)
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index fdf79bcf7eb09..0d99ba64ea528 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -774,6 +774,7 @@ static int wdm_release(struct inode *inode, struct file *file)
+ poison_urbs(desc);
+ spin_lock_irq(&desc->iuspin);
+ desc->resp_count = 0;
++ clear_bit(WDM_RESPONDING, &desc->flags);
+ spin_unlock_irq(&desc->iuspin);
+ desc->manage_power(desc->intf, 0);
+ unpoison_urbs(desc);
+diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
+index 73f419adce610..4bb6d304eb4b2 100644
+--- a/drivers/usb/class/usbtmc.c
++++ b/drivers/usb/class/usbtmc.c
+@@ -1919,6 +1919,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ struct usbtmc_ctrlrequest request;
+ u8 *buffer = NULL;
+ int rv;
++ unsigned int is_in, pipe;
+ unsigned long res;
+
+ res = copy_from_user(&request, arg, sizeof(struct usbtmc_ctrlrequest));
+@@ -1928,12 +1929,14 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ if (request.req.wLength > USBTMC_BUFSIZE)
+ return -EMSGSIZE;
+
++ is_in = request.req.bRequestType & USB_DIR_IN;
++
+ if (request.req.wLength) {
+ buffer = kmalloc(request.req.wLength, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+- if ((request.req.bRequestType & USB_DIR_IN) == 0) {
++ if (!is_in) {
+ /* Send control data to device */
+ res = copy_from_user(buffer, request.data,
+ request.req.wLength);
+@@ -1944,8 +1947,12 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ }
+ }
+
++ if (is_in)
++ pipe = usb_rcvctrlpipe(data->usb_dev, 0);
++ else
++ pipe = usb_sndctrlpipe(data->usb_dev, 0);
+ rv = usb_control_msg(data->usb_dev,
+- usb_rcvctrlpipe(data->usb_dev, 0),
++ pipe,
+ request.req.bRequest,
+ request.req.bRequestType,
+ request.req.wValue,
+@@ -1957,7 +1964,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ goto exit;
+ }
+
+- if (rv && (request.req.bRequestType & USB_DIR_IN)) {
++ if (rv && is_in) {
+ /* Read control data from device */
+ res = copy_to_user(request.data, buffer, rv);
+ if (res)
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 4169cf40a03b5..5509d3847af4b 100644
--- a/drivers/usb/common/ulpi.c
@@ -114434,7 +170630,7 @@ index b199eb65f3780..00e28456e4cc2 100644
}
fallthrough;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
-index 9618ba622a2d0..fa66e6e587928 100644
+index 9618ba622a2d0..656ba91c32831 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -32,6 +32,7 @@
@@ -114502,7 +170698,7 @@ index 9618ba622a2d0..fa66e6e587928 100644
ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest,
ctrl->wIndex);
-@@ -1122,51 +1164,63 @@ static int do_proc_control(struct usb_dev_state *ps,
+@@ -1122,51 +1164,71 @@ static int do_proc_control(struct usb_dev_state *ps,
sizeof(struct usb_ctrlrequest));
if (ret)
return ret;
@@ -114547,6 +170743,10 @@ index 9618ba622a2d0..fa66e6e587928 100644
- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
- tbuf, ctrl->wLength, tmo);
+ i = usbfs_start_wait_urb(urb, tmo, &actlen);
++
++ /* Linger a bit, prior to the next control message. */
++ if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
++ msleep(200);
usb_lock_device(dev);
- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
- tbuf, max(i, 0));
@@ -114556,8 +170756,7 @@ index 9618ba622a2d0..fa66e6e587928 100644
+ if (!i && actlen) {
+ if (copy_to_user(ctrl->data, tbuf, actlen)) {
ret = -EFAULT;
-- goto done;
-+ goto recv_fault;
+ goto done;
}
}
} else {
@@ -114581,30 +170780,30 @@ index 9618ba622a2d0..fa66e6e587928 100644
- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
- tbuf, ctrl->wLength, tmo);
+ i = usbfs_start_wait_urb(urb, tmo, &actlen);
++
++ /* Linger a bit, prior to the next control message. */
++ if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
++ msleep(200);
usb_lock_device(dev);
- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
+ snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0);
}
if (i < 0 && i != -EPIPE) {
dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
-@@ -1174,8 +1228,15 @@ static int do_proc_control(struct usb_dev_state *ps,
+@@ -1174,8 +1236,11 @@ static int do_proc_control(struct usb_dev_state *ps,
current->comm, ctrl->bRequestType, ctrl->bRequest,
ctrl->wLength, i);
}
- ret = i;
+ ret = (i < 0 ? i : actlen);
+
-+ recv_fault:
-+ /* Linger a bit, prior to the next control message. */
-+ if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
-+ msleep(200);
done:
+ kfree(dr);
+ usb_free_urb(urb);
free_page((unsigned long) tbuf);
usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
sizeof(struct usb_ctrlrequest));
-@@ -1195,10 +1256,11 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+@@ -1195,10 +1260,11 @@ static int do_proc_bulk(struct usb_dev_state *ps,
struct usbdevfs_bulktransfer *bulk)
{
struct usb_device *dev = ps->dev;
@@ -114618,7 +170817,7 @@ index 9618ba622a2d0..fa66e6e587928 100644
ret = findintfep(ps->dev, bulk->ep);
if (ret < 0)
-@@ -1206,14 +1268,17 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+@@ -1206,14 +1272,17 @@ static int do_proc_bulk(struct usb_dev_state *ps,
ret = checkintf(ps, ret);
if (ret)
return ret;
@@ -114640,7 +170839,7 @@ index 9618ba622a2d0..fa66e6e587928 100644
return -EINVAL;
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
if (ret)
-@@ -1223,17 +1288,29 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+@@ -1223,17 +1292,29 @@ static int do_proc_bulk(struct usb_dev_state *ps,
* len1 can be almost arbitrarily large. Don't WARN if it's
* too big, just fail the request.
*/
@@ -114673,7 +170872,7 @@ index 9618ba622a2d0..fa66e6e587928 100644
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2);
-@@ -1253,12 +1330,13 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+@@ -1253,12 +1334,13 @@ static int do_proc_bulk(struct usb_dev_state *ps,
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
usb_unlock_device(dev);
@@ -114931,10 +171130,20 @@ index 86658a81d2844..ac6c5ccfe1cb7 100644
if (ret < 0)
goto re_enumerate;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
-index 8239fe7129dd7..d3c14b5ed4a1f 100644
+index 8239fe7129dd7..97b44a68668a5 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
-@@ -434,6 +434,12 @@ static const struct usb_device_id usb_quirk_list[] = {
+@@ -404,6 +404,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
+ USB_QUIRK_IGNORE_REMOTE_WAKEUP },
+
++ /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/
++ { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
++
+ /* Realtek hub in Dell WD19 (Type-C) */
+ { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM },
+
+@@ -434,6 +437,12 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1532, 0x0116), .driver_info =
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
@@ -114947,6 +171156,16 @@ index 8239fe7129dd7..d3c14b5ed4a1f 100644
/* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */
{ USB_DEVICE(0x17ef, 0xa012), .driver_info =
USB_QUIRK_DISCONNECT_SUSPEND },
+@@ -501,6 +510,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ /* DJI CineSSD */
+ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
+
++ /* VCOM device */
++ { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
++
+ /* INTEL VALUE SSD */
+ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 30727729a44cc..33d62d7e3929f 100644
--- a/drivers/usb/core/urb.c
@@ -115210,10 +171429,35 @@ index c8f18f3ba9e35..c331a5128c2c0 100644
retval = dwc2_drd_init(hsotg);
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
-index 0104a80b185e1..357b7805896e7 100644
+index 0104a80b185e1..5cb1350ec66d1 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
-@@ -1565,9 +1565,11 @@ static int dwc3_probe(struct platform_device *pdev)
+@@ -275,7 +275,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg |= DWC3_DCTL_CSFTRST;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ reg &= ~DWC3_DCTL_RUN_STOP;
++ dwc3_gadget_dctl_write_safe(dwc, reg);
+
+ /*
+ * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit
+@@ -1268,10 +1269,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
+ u8 lpm_nyet_threshold;
+ u8 tx_de_emphasis;
+ u8 hird_threshold;
+- u8 rx_thr_num_pkt_prd;
+- u8 rx_max_burst_prd;
+- u8 tx_thr_num_pkt_prd;
+- u8 tx_max_burst_prd;
++ u8 rx_thr_num_pkt_prd = 0;
++ u8 rx_max_burst_prd = 0;
++ u8 tx_thr_num_pkt_prd = 0;
++ u8 tx_max_burst_prd = 0;
+ u8 tx_fifo_resize_max_num;
+ const char *usb_psy_name;
+ int ret;
+@@ -1565,9 +1566,11 @@ static int dwc3_probe(struct platform_device *pdev)
dwc3_get_properties(dwc);
@@ -115249,6 +171493,32 @@ index 5612bfdf37da9..fd5d42ec53501 100644
/* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN BIT(31)
+diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
+index d7f76835137fa..f148b0370f829 100644
+--- a/drivers/usb/dwc3/drd.c
++++ b/drivers/usb/dwc3/drd.c
+@@ -571,16 +571,15 @@ int dwc3_drd_init(struct dwc3 *dwc)
+ {
+ int ret, irq;
+
++ if (ROLE_SWITCH &&
++ device_property_read_bool(dwc->dev, "usb-role-switch"))
++ return dwc3_setup_role_switch(dwc);
++
+ dwc->edev = dwc3_get_extcon(dwc);
+ if (IS_ERR(dwc->edev))
+ return PTR_ERR(dwc->edev);
+
+- if (ROLE_SWITCH &&
+- device_property_read_bool(dwc->dev, "usb-role-switch")) {
+- ret = dwc3_setup_role_switch(dwc);
+- if (ret < 0)
+- return ret;
+- } else if (dwc->edev) {
++ if (dwc->edev) {
+ dwc->edev_nb.notifier_call = dwc3_drd_notifier;
+ ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
+ &dwc->edev_nb);
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index d0f9b7c296b0d..bd814df3bf8b8 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -115312,11 +171582,34 @@ index d0f9b7c296b0d..bd814df3bf8b8 100644
ret = priv->drvdata->usb_init(priv);
if (ret)
+diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
+index e196673f5c647..efaf0db595f46 100644
+--- a/drivers/usb/dwc3/dwc3-omap.c
++++ b/drivers/usb/dwc3/dwc3-omap.c
+@@ -242,7 +242,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
+ break;
+
+ case OMAP_DWC3_ID_FLOAT:
+- if (omap->vbus_reg)
++ if (omap->vbus_reg && regulator_is_enabled(omap->vbus_reg))
+ regulator_disable(omap->vbus_reg);
+ val = dwc3_omap_read_utmi_ctrl(omap);
+ val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG;
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
-index 7ff8fc8f79a9b..1ecedbb1684c8 100644
+index 7ff8fc8f79a9b..f08b2178fd32d 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
-@@ -85,8 +85,8 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
+@@ -43,6 +43,9 @@
+ #define PCI_DEVICE_ID_INTEL_ADLP 0x51ee
+ #define PCI_DEVICE_ID_INTEL_ADLM 0x54ee
+ #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1
++#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
++#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
++#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
+ #define PCI_DEVICE_ID_INTEL_TGL 0x9a15
+ #define PCI_DEVICE_ID_AMD_MR 0x163a
+
+@@ -85,8 +88,8 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
static struct gpiod_lookup_table platform_bytcr_gpios = {
.dev_id = "0000:00:16.0",
.table = {
@@ -115327,7 +171620,7 @@ index 7ff8fc8f79a9b..1ecedbb1684c8 100644
{}
},
};
-@@ -119,6 +119,13 @@ static const struct property_entry dwc3_pci_intel_properties[] = {
+@@ -119,6 +122,13 @@ static const struct property_entry dwc3_pci_intel_properties[] = {
{}
};
@@ -115341,7 +171634,7 @@ index 7ff8fc8f79a9b..1ecedbb1684c8 100644
static const struct property_entry dwc3_pci_mrfld_properties[] = {
PROPERTY_ENTRY_STRING("dr_mode", "otg"),
PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
-@@ -161,6 +168,10 @@ static const struct software_node dwc3_pci_intel_swnode = {
+@@ -161,6 +171,10 @@ static const struct software_node dwc3_pci_intel_swnode = {
.properties = dwc3_pci_intel_properties,
};
@@ -115352,6 +171645,38 @@ index 7ff8fc8f79a9b..1ecedbb1684c8 100644
static const struct software_node dwc3_pci_intel_mrfld_swnode = {
.properties = dwc3_pci_mrfld_properties,
};
+@@ -173,7 +187,8 @@ static const struct software_node dwc3_pci_amd_mr_swnode = {
+ .properties = dwc3_pci_mr_properties,
+ };
+
+-static int dwc3_pci_quirks(struct dwc3_pci *dwc)
++static int dwc3_pci_quirks(struct dwc3_pci *dwc,
++ const struct software_node *swnode)
+ {
+ struct pci_dev *pdev = dwc->pci;
+
+@@ -230,7 +245,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
+ }
+ }
+
+- return 0;
++ return device_add_software_node(&dwc->dwc3->dev, swnode);
+ }
+
+ #ifdef CONFIG_PM
+@@ -295,11 +310,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
+ dwc->dwc3->dev.parent = dev;
+ ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev));
+
+- ret = device_add_software_node(&dwc->dwc3->dev, (void *)id->driver_data);
+- if (ret < 0)
+- goto err;
+-
+- ret = dwc3_pci_quirks(dwc);
++ ret = dwc3_pci_quirks(dwc, (void *)id->driver_data);
+ if (ret)
+ goto err;
+
@@ -344,7 +355,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
@@ -115361,6 +171686,22 @@ index 7ff8fc8f79a9b..1ecedbb1684c8 100644
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
(kernel_ulong_t) &dwc3_pci_intel_mrfld_swnode, },
+@@ -409,6 +420,15 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
+ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
++ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
++
++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
++ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
++
++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
++ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
++
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL),
+ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 9abbd01028c5f..b81a9e1c13153 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
@@ -115458,7 +171799,7 @@ index 9cc3ad701a295..a6f3a9b38789e 100644
* This routes the USB DMA traffic to go through FPD path instead
* of reaching DDR directly. This traffic routing is needed to
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
-index 4519d06c9ca2b..00cf8ebcb338c 100644
+index 4519d06c9ca2b..c32f3116d1a0f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -310,13 +310,24 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
@@ -115545,7 +171886,52 @@ index 4519d06c9ca2b..00cf8ebcb338c 100644
trb->ctrl |= DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_enq(dep);
-@@ -3246,6 +3276,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
+@@ -3169,6 +3199,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
+ const struct dwc3_event_depevt *event,
+ struct dwc3_request *req, int status)
+ {
++ int request_status;
+ int ret;
+
+ if (req->request.num_mapped_sgs)
+@@ -3189,7 +3220,35 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
+ req->needs_extra_trb = false;
+ }
+
+- dwc3_gadget_giveback(dep, req, status);
++ /*
++ * The event status only reflects the status of the TRB with IOC set.
++ * For the requests that don't set interrupt on completion, the driver
++ * needs to check and return the status of the completed TRBs associated
++ * with the request. Use the status of the last TRB of the request.
++ */
++ if (req->request.no_interrupt) {
++ struct dwc3_trb *trb;
++
++ trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue);
++ switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) {
++ case DWC3_TRBSTS_MISSED_ISOC:
++ /* Isoc endpoint only */
++ request_status = -EXDEV;
++ break;
++ case DWC3_TRB_STS_XFER_IN_PROG:
++ /* Applicable when End Transfer with ForceRM=0 */
++ case DWC3_TRBSTS_SETUP_PENDING:
++ /* Control endpoint only */
++ case DWC3_TRBSTS_OK:
++ default:
++ request_status = 0;
++ break;
++ }
++ } else {
++ request_status = status;
++ }
++
++ dwc3_gadget_giveback(dep, req, request_status);
+
+ out:
+ return ret;
+@@ -3246,6 +3305,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
struct dwc3 *dwc = dep->dwc;
bool no_started_trb = true;
@@ -115555,7 +171941,7 @@ index 4519d06c9ca2b..00cf8ebcb338c 100644
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
-@@ -3293,6 +3326,9 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
+@@ -3293,6 +3355,9 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
{
int status = 0;
@@ -115565,7 +171951,7 @@ index 4519d06c9ca2b..00cf8ebcb338c 100644
if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
dwc3_gadget_endpoint_frame_from_event(dep, event);
-@@ -3346,6 +3382,14 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
+@@ -3346,6 +3411,14 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
if (cmd != DWC3_DEPCMD_ENDTRANSFER)
return;
@@ -115580,7 +171966,7 @@ index 4519d06c9ca2b..00cf8ebcb338c 100644
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
-@@ -3568,14 +3612,6 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+@@ -3568,14 +3641,6 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
WARN_ON_ONCE(ret);
dep->resource_index = 0;
@@ -115595,7 +171981,7 @@ index 4519d06c9ca2b..00cf8ebcb338c 100644
if (!interrupt)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
else
-@@ -4095,9 +4131,11 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_evt)
+@@ -4095,9 +4160,11 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_evt)
unsigned long flags;
irqreturn_t ret = IRQ_NONE;
@@ -115682,6 +172068,19 @@ index 504c1cbc255d1..553382ce38378 100644
if (!cdev->req->buf)
goto fail;
+diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
+index 477e72a1d11e7..5ade844db4046 100644
+--- a/drivers/usb/gadget/configfs.c
++++ b/drivers/usb/gadget/configfs.c
+@@ -1447,6 +1447,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
+ usb_ep_autoconfig_reset(cdev->gadget);
+ spin_lock_irqsave(&gi->spinlock, flags);
+ cdev->gadget = NULL;
++ cdev->deactivations = 0;
++ gadget->deactivated = false;
+ set_gadget_data(gadget, NULL);
+ spin_unlock_irqrestore(&gi->spinlock, flags);
+ }
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 8260f38025b72..02f70c5c65fc2 100644
--- a/drivers/usb/gadget/function/f_fs.c
@@ -115856,17 +172255,84 @@ index ef55b8bb5870a..5226a47b68fda 100644
.bAssocTerminal = 0,
/* .bSourceID = DYNAMIC */
/* .bCSourceID = DYNAMIC */
+diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
+index 9d87c0fb8f92e..bf0a3fc2d7767 100644
+--- a/drivers/usb/gadget/function/f_uvc.c
++++ b/drivers/usb/gadget/function/f_uvc.c
+@@ -884,17 +884,42 @@ static void uvc_free(struct usb_function *f)
+ kfree(uvc);
+ }
+
+-static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
++static void uvc_function_unbind(struct usb_configuration *c,
++ struct usb_function *f)
+ {
+ struct usb_composite_dev *cdev = c->cdev;
+ struct uvc_device *uvc = to_uvc(f);
++ long wait_ret = 1;
+
+- uvcg_info(f, "%s\n", __func__);
++ uvcg_info(f, "%s()\n", __func__);
++
++ /* If we know we're connected via v4l2, then there should be a cleanup
++ * of the device from userspace either via UVC_EVENT_DISCONNECT or
++ * though the video device removal uevent. Allow some time for the
++ * application to close out before things get deleted.
++ */
++ if (uvc->func_connected) {
++ uvcg_dbg(f, "waiting for clean disconnect\n");
++ wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
++ uvc->func_connected == false, msecs_to_jiffies(500));
++ uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret);
++ }
+
+ device_remove_file(&uvc->vdev.dev, &dev_attr_function_name);
+ video_unregister_device(&uvc->vdev);
+ v4l2_device_unregister(&uvc->v4l2_dev);
+
++ if (uvc->func_connected) {
++ /* Wait for the release to occur to ensure there are no longer any
++ * pending operations that may cause panics when resources are cleaned
++ * up.
++ */
++ uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__);
++ wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
++ uvc->func_connected == false, msecs_to_jiffies(1000));
++ uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret);
++ }
++
+ usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+ kfree(uvc->control_buf);
+
+@@ -913,6 +938,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
+
+ mutex_init(&uvc->video.mutex);
+ uvc->state = UVC_STATE_DISCONNECTED;
++ init_waitqueue_head(&uvc->func_connected_queue);
+ opts = fi_to_f_uvc_opts(fi);
+
+ mutex_lock(&opts->lock);
+@@ -943,7 +969,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
+ /* Register the function. */
+ uvc->func.name = "uvc";
+ uvc->func.bind = uvc_function_bind;
+- uvc->func.unbind = uvc_unbind;
++ uvc->func.unbind = uvc_function_unbind;
+ uvc->func.get_alt = uvc_function_get_alt;
+ uvc->func.set_alt = uvc_function_set_alt;
+ uvc->func.disable = uvc_function_disable;
diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c
-index 64de9f1b874c5..0f14c5291af07 100644
+index 64de9f1b874c5..4150de96b937a 100644
--- a/drivers/usb/gadget/function/rndis.c
+++ b/drivers/usb/gadget/function/rndis.c
-@@ -637,14 +637,17 @@ static int rndis_set_response(struct rndis_params *params,
+@@ -637,14 +637,18 @@ static int rndis_set_response(struct rndis_params *params,
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
+ BufLength = le32_to_cpu(buf->InformationBufferLength);
+ BufOffset = le32_to_cpu(buf->InformationBufferOffset);
+ if ((BufLength > RNDIS_MAX_TOTAL_SIZE) ||
++ (BufOffset > RNDIS_MAX_TOTAL_SIZE) ||
+ (BufOffset + 8 >= RNDIS_MAX_TOTAL_SIZE))
+ return -EINVAL;
+
@@ -115881,7 +172347,7 @@ index 64de9f1b874c5..0f14c5291af07 100644
#ifdef VERBOSE_DEBUG
pr_debug("%s: Length: %d\n", __func__, BufLength);
pr_debug("%s: Offset: %d\n", __func__, BufOffset);
-@@ -919,6 +922,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v)
+@@ -919,6 +923,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v)
params->resp_avail = resp_avail;
params->v = v;
INIT_LIST_HEAD(&params->resp_queue);
@@ -115889,7 +172355,7 @@ index 64de9f1b874c5..0f14c5291af07 100644
pr_debug("%s: configNr = %d\n", __func__, i);
return params;
-@@ -1012,12 +1016,14 @@ void rndis_free_response(struct rndis_params *params, u8 *buf)
+@@ -1012,12 +1017,14 @@ void rndis_free_response(struct rndis_params *params, u8 *buf)
{
rndis_resp_t *r, *n;
@@ -115904,7 +172370,7 @@ index 64de9f1b874c5..0f14c5291af07 100644
}
EXPORT_SYMBOL_GPL(rndis_free_response);
-@@ -1027,14 +1033,17 @@ u8 *rndis_get_next_response(struct rndis_params *params, u32 *length)
+@@ -1027,14 +1034,17 @@ u8 *rndis_get_next_response(struct rndis_params *params, u32 *length)
if (!length) return NULL;
@@ -115922,7 +172388,7 @@ index 64de9f1b874c5..0f14c5291af07 100644
return NULL;
}
EXPORT_SYMBOL_GPL(rndis_get_next_response);
-@@ -1051,7 +1060,9 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length)
+@@ -1051,7 +1061,9 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length)
r->length = length;
r->send = 0;
@@ -116020,18 +172486,27 @@ index 85a3f6d4b5af3..d15a54f6c24b9 100644
return status;
}
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
-index 255a61bd6a6a8..9d5f17b551bbd 100644
+index 255a61bd6a6a8..0966c5aa24921 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
-@@ -126,6 +126,7 @@ struct uvc_device {
+@@ -14,6 +14,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/usb/composite.h>
+ #include <linux/videodev2.h>
++#include <linux/wait.h>
+
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-dev.h>
+@@ -126,6 +127,8 @@ struct uvc_device {
enum uvc_state state;
struct usb_function func;
struct uvc_video video;
+ bool func_connected;
++ wait_queue_head_t func_connected_queue;
/* Descriptors */
struct {
-@@ -156,6 +157,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f)
+@@ -156,6 +159,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f)
struct uvc_file_handle {
struct v4l2_fh vfh;
struct uvc_video *device;
@@ -116039,11 +172514,24 @@ index 255a61bd6a6a8..9d5f17b551bbd 100644
};
#define to_uvc_file_handle(handle) \
+diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
+index 7d00ad7c154c2..99dc9adf56efa 100644
+--- a/drivers/usb/gadget/function/uvc_queue.c
++++ b/drivers/usb/gadget/function/uvc_queue.c
+@@ -264,6 +264,8 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
+ buf->state = UVC_BUF_STATE_ERROR;
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
++ queue->buf_used = 0;
++
+ /* This must be protected by the irqlock spinlock to avoid race
+ * conditions between uvc_queue_buffer and the disconnection event that
+ * could result in an interruptible wait in uvc_dequeue_buffer. Do not
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
-index 4ca89eab61590..197c26f7aec63 100644
+index 4ca89eab61590..65abd55ce2348 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
-@@ -227,17 +227,55 @@ static int
+@@ -227,17 +227,56 @@ static int
uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub)
{
@@ -116073,10 +172561,11 @@ index 4ca89eab61590..197c26f7aec63 100644
+
+static void uvc_v4l2_disable(struct uvc_device *uvc)
+{
-+ uvc->func_connected = false;
+ uvc_function_disconnect(uvc);
+ uvcg_video_enable(&uvc->video, 0);
+ uvcg_free_buffers(&uvc->video.queue);
++ uvc->func_connected = false;
++ wake_up_interruptible(&uvc->func_connected_queue);
}
static int
@@ -116101,7 +172590,7 @@ index 4ca89eab61590..197c26f7aec63 100644
}
static long
-@@ -292,7 +330,6 @@ uvc_v4l2_open(struct file *file)
+@@ -292,7 +331,6 @@ uvc_v4l2_open(struct file *file)
handle->device = &uvc->video;
file->private_data = &handle->vfh;
@@ -116109,7 +172598,7 @@ index 4ca89eab61590..197c26f7aec63 100644
return 0;
}
-@@ -304,11 +341,9 @@ uvc_v4l2_release(struct file *file)
+@@ -304,11 +342,9 @@ uvc_v4l2_release(struct file *file)
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
struct uvc_video *video = handle->device;
@@ -116246,10 +172735,26 @@ index 539220d7f5b62..3279b4767424c 100644
pr_debug ("%s: %s fail %zd, %p\n", shortname, __func__, value, dev);
kfree (dev->buf);
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
-index c5a2c734234a5..d86c3a36441ee 100644
+index c5a2c734234a5..3427ce37a5c5b 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
-@@ -1004,7 +1004,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
+@@ -145,6 +145,7 @@ enum dev_state {
+ STATE_DEV_INVALID = 0,
+ STATE_DEV_OPENED,
+ STATE_DEV_INITIALIZED,
++ STATE_DEV_REGISTERING,
+ STATE_DEV_RUNNING,
+ STATE_DEV_CLOSED,
+ STATE_DEV_FAILED
+@@ -508,6 +509,7 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value)
+ ret = -EINVAL;
+ goto out_unlock;
+ }
++ dev->state = STATE_DEV_REGISTERING;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ ret = usb_gadget_probe_driver(&dev->driver);
+@@ -1004,7 +1006,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
ret = -EBUSY;
goto out_unlock;
}
@@ -116270,6 +172775,34 @@ index 8c614bb86c665..69394dc1cdfb6 100644
help
Some of Freescale PowerPC processors have a Full Speed
QE/CPM2 USB controller, which support device mode with 4
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 14fdf918ecfeb..61099f2d057dc 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1434,7 +1434,6 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ usb_gadget_udc_stop(udc);
+
+ udc->driver = NULL;
+- udc->dev.driver = NULL;
+ udc->gadget->dev.driver = NULL;
+ }
+
+@@ -1496,7 +1495,6 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
+ driver->function);
+
+ udc->driver = driver;
+- udc->dev.driver = &driver->driver;
+ udc->gadget->dev.driver = &driver->driver;
+
+ usb_gadget_udc_set_speed(udc, driver->max_speed);
+@@ -1519,7 +1517,6 @@ err1:
+ dev_err(&udc->dev, "failed to start %s: %d\n",
+ udc->driver->function, ret);
+ udc->driver = NULL;
+- udc->dev.driver = NULL;
+ udc->gadget->dev.driver = NULL;
+ return ret;
+ }
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 57d417a7c3e0a..601829a6b4bad 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
@@ -116283,6 +172816,66 @@ index 57d417a7c3e0a..601829a6b4bad 100644
if (usb3->driver)
usb3_disconnect(usb3);
usb3_vbus_out(usb3, false);
+diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
+index 43f1b0d461c1e..be76f891b9c52 100644
+--- a/drivers/usb/gadget/udc/tegra-xudc.c
++++ b/drivers/usb/gadget/udc/tegra-xudc.c
+@@ -32,9 +32,6 @@
+ #include <linux/workqueue.h>
+
+ /* XUSB_DEV registers */
+-#define SPARAM 0x000
+-#define SPARAM_ERSTMAX_MASK GENMASK(20, 16)
+-#define SPARAM_ERSTMAX(x) (((x) << 16) & SPARAM_ERSTMAX_MASK)
+ #define DB 0x004
+ #define DB_TARGET_MASK GENMASK(15, 8)
+ #define DB_TARGET(x) (((x) << 8) & DB_TARGET_MASK)
+@@ -275,8 +272,10 @@ BUILD_EP_CONTEXT_RW(deq_hi, deq_hi, 0, 0xffffffff)
+ BUILD_EP_CONTEXT_RW(avg_trb_len, tx_info, 0, 0xffff)
+ BUILD_EP_CONTEXT_RW(max_esit_payload, tx_info, 16, 0xffff)
+ BUILD_EP_CONTEXT_RW(edtla, rsvd[0], 0, 0xffffff)
+-BUILD_EP_CONTEXT_RW(seq_num, rsvd[0], 24, 0xff)
++BUILD_EP_CONTEXT_RW(rsvd, rsvd[0], 24, 0x1)
+ BUILD_EP_CONTEXT_RW(partial_td, rsvd[0], 25, 0x1)
++BUILD_EP_CONTEXT_RW(splitxstate, rsvd[0], 26, 0x1)
++BUILD_EP_CONTEXT_RW(seq_num, rsvd[0], 27, 0x1f)
+ BUILD_EP_CONTEXT_RW(cerrcnt, rsvd[1], 18, 0x3)
+ BUILD_EP_CONTEXT_RW(data_offset, rsvd[2], 0, 0x1ffff)
+ BUILD_EP_CONTEXT_RW(numtrbs, rsvd[2], 22, 0x1f)
+@@ -1557,6 +1556,9 @@ static int __tegra_xudc_ep_set_halt(struct tegra_xudc_ep *ep, bool halt)
+ ep_reload(xudc, ep->index);
+
+ ep_ctx_write_state(ep->context, EP_STATE_RUNNING);
++ ep_ctx_write_rsvd(ep->context, 0);
++ ep_ctx_write_partial_td(ep->context, 0);
++ ep_ctx_write_splitxstate(ep->context, 0);
+ ep_ctx_write_seq_num(ep->context, 0);
+
+ ep_reload(xudc, ep->index);
+@@ -2812,7 +2814,10 @@ static void tegra_xudc_reset(struct tegra_xudc *xudc)
+ xudc->setup_seq_num = 0;
+ xudc->queued_setup_packet = false;
+
+- ep_ctx_write_seq_num(ep0->context, xudc->setup_seq_num);
++ ep_ctx_write_rsvd(ep0->context, 0);
++ ep_ctx_write_partial_td(ep0->context, 0);
++ ep_ctx_write_splitxstate(ep0->context, 0);
++ ep_ctx_write_seq_num(ep0->context, 0);
+
+ deq_ptr = trb_virt_to_phys(ep0, &ep0->transfer_ring[ep0->deq_ptr]);
+
+@@ -3295,11 +3300,6 @@ static void tegra_xudc_init_event_ring(struct tegra_xudc *xudc)
+ unsigned int i;
+ u32 val;
+
+- val = xudc_readl(xudc, SPARAM);
+- val &= ~(SPARAM_ERSTMAX_MASK);
+- val |= SPARAM_ERSTMAX(XUDC_NR_EVENT_RINGS);
+- xudc_writel(xudc, val, SPARAM);
+-
+ for (i = 0; i < ARRAY_SIZE(xudc->event_ring); i++) {
+ memset(xudc->event_ring[i], 0, XUDC_EVENT_RING_SIZE *
+ sizeof(*xudc->event_ring[i]));
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index fb4ffedd6f0dd..9cf43731bcd18 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
@@ -116347,6 +172940,33 @@ index 1776c05d0a486..1440803216297 100644
up_write(&ehci_cf_port_reset_rwsem);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index e87cf3a00fa4b..638f03b897394 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -21,6 +21,9 @@ static const char hcd_name[] = "ehci-pci";
+ /* defined here to avoid adding to pci_ids.h for single instance use */
+ #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70
+
++#define PCI_VENDOR_ID_ASPEED 0x1a03
++#define PCI_DEVICE_ID_ASPEED_EHCI 0x2603
++
+ /*-------------------------------------------------------------------------*/
+ #define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939
+ static inline bool is_intel_quark_x1000(struct pci_dev *pdev)
+@@ -222,6 +225,12 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ ehci->has_synopsys_hc_bug = 1;
+ }
+ break;
++ case PCI_VENDOR_ID_ASPEED:
++ if (pdev->device == PCI_DEVICE_ID_ASPEED_EHCI) {
++ ehci_info(ehci, "applying Aspeed HC workaround\n");
++ ehci->is_aspeed = 1;
++ }
++ break;
+ }
+
+ /* optional debug port, normally in the first BAR */
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index c70f2d0b4aaf0..c3dc906274d93 100644
--- a/drivers/usb/host/ehci-platform.c
@@ -116470,7 +173090,7 @@ index 70dbd95c3f063..be9e9db7cad10 100644
dev_info(&pdev->dev,
"Enabled Aspeed implementation workarounds\n");
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
-index a3f875eea7519..df3522dab31b5 100644
+index a3f875eea7519..f65f1ba2b5929 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -257,7 +257,6 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
@@ -116505,11 +173125,87 @@ index a3f875eea7519..df3522dab31b5 100644
if (retval)
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
i, retval);
+@@ -760,7 +762,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
+ }
+ pm_runtime_allow(xhci_to_hcd(xhci)->self.controller);
+ xhci->test_mode = 0;
+- return xhci_reset(xhci);
++ return xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+ }
+
+ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
+@@ -1086,6 +1088,9 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
+ if (link_state == XDEV_U2)
+ *status |= USB_PORT_STAT_L1;
+ if (link_state == XDEV_U0) {
++ if (bus_state->resume_done[portnum])
++ usb_hcd_end_port_resume(&port->rhub->hcd->self,
++ portnum);
+ bus_state->resume_done[portnum] = 0;
+ clear_bit(portnum, &bus_state->resuming_ports);
+ if (bus_state->suspended_ports & (1 << portnum)) {
+@@ -1429,7 +1434,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ }
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex],
+- msecs_to_jiffies(100)))
++ msecs_to_jiffies(500)))
+ xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n",
+ hcd->self.busnum, wIndex + 1);
+ spin_lock_irqsave(&xhci->lock, flags);
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 0e312066c5c63..b398d3fdabf61 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2583,7 +2583,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+
+ fail:
+ xhci_halt(xhci);
+- xhci_reset(xhci);
++ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+ xhci_mem_cleanup(xhci);
+ return -ENOMEM;
+ }
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
-index 134f4789bd897..b4c84b3635074 100644
+index 134f4789bd897..f91a304320563 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
-@@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+@@ -465,7 +465,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
+ */
+ for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+ k = XHCI_MTK_BW_INDEX(base + j);
+- tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
++ tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe;
+ if (tmp > FS_PAYLOAD_MAX)
+ return -ESCH_BW_OVERFLOW;
+ }
+@@ -539,19 +539,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
+ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
+ {
+ struct mu3h_sch_tt *tt = sch_ep->sch_tt;
++ int bw_updated;
+ u32 base;
+- int i, j, k;
++ int i, j;
++
++ bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);
+
+ for (i = 0; i < sch_ep->num_esit; i++) {
+ base = sch_ep->offset + i * sch_ep->esit;
+
+- for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+- k = XHCI_MTK_BW_INDEX(base + j);
+- if (used)
+- tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
+- else
+- tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
+- }
++ for (j = 0; j < sch_ep->num_budget_microframes; j++)
++ tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
+ }
+
+ if (used)
+@@ -781,7 +779,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
ret = xhci_check_bandwidth(hcd, udev);
if (!ret)
@@ -116519,10 +173215,17 @@ index 134f4789bd897..b4c84b3635074 100644
return ret;
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
-index 2484a9d38ce2b..de9a9ea2cabc2 100644
+index 2484a9d38ce2b..cb8b481a94990 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
-@@ -65,6 +65,15 @@
+@@ -59,12 +59,22 @@
+ #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13
+ #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138
+ #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
++#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
+
+ #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
+ #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
@@ -116538,7 +173241,7 @@ index 2484a9d38ce2b..de9a9ea2cabc2 100644
#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242
-@@ -114,7 +123,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+@@ -114,7 +124,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
/* Look for vendor-specific quirks */
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
@@ -116546,7 +173249,7 @@ index 2484a9d38ce2b..de9a9ea2cabc2 100644
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
pdev->revision == 0x0) {
-@@ -149,6 +157,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+@@ -149,6 +158,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009)
xhci->quirks |= XHCI_BROKEN_STREAMS;
@@ -116557,7 +173260,17 @@ index 2484a9d38ce2b..de9a9ea2cabc2 100644
if (pdev->vendor == PCI_VENDOR_ID_NEC)
xhci->quirks |= XHCI_NEC_HOST;
-@@ -317,6 +329,17 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+@@ -254,7 +267,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+ pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI ||
+- pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI))
++ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI ||
++ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI))
+ xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
+
+ if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
+@@ -317,6 +331,17 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
xhci->quirks |= XHCI_NO_SOFT_RETRY;
@@ -116590,7 +173303,7 @@ index c1edcc9b13cec..dc570ce4e8319 100644
if (ret)
return ret;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
-index 311597bba80e2..d0b6806275e01 100644
+index 311597bba80e2..f9707997969d4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
@@ -116637,10 +173350,34 @@ index 311597bba80e2..d0b6806275e01 100644
}
static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
+@@ -3135,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ if (event_loop++ < TRBS_PER_SEGMENT / 2)
+ continue;
+ xhci_update_erst_dequeue(xhci, event_ring_deq);
++ event_ring_deq = xhci->event_ring->dequeue;
+
+ /* ring is half-full, force isoc trbs to interrupt more often */
+ if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
-index 1bf494b649bd2..c8af2cd2216d6 100644
+index 1bf494b649bd2..996958a6565c3 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
+@@ -1034,13 +1034,13 @@ static int tegra_xusb_unpowergate_partitions(struct tegra_xusb *tegra)
+ int rc;
+
+ if (tegra->use_genpd) {
+- rc = pm_runtime_get_sync(tegra->genpd_dev_ss);
++ rc = pm_runtime_resume_and_get(tegra->genpd_dev_ss);
+ if (rc < 0) {
+ dev_err(dev, "failed to enable XUSB SS partition\n");
+ return rc;
+ }
+
+- rc = pm_runtime_get_sync(tegra->genpd_dev_host);
++ rc = pm_runtime_resume_and_get(tegra->genpd_dev_host);
+ if (rc < 0) {
+ dev_err(dev, "failed to enable XUSB Host partition\n");
+ pm_runtime_put_sync(tegra->genpd_dev_ss);
@@ -1400,6 +1400,7 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra)
static int tegra_xusb_probe(struct platform_device *pdev)
@@ -116723,10 +173460,57 @@ index 1bf494b649bd2..c8af2cd2216d6 100644
tegra_xusb_powergate_partitions(tegra);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
-index 541fe4dcc43a2..d7c0bf494d930 100644
+index 541fe4dcc43a2..90f5a3ce7c348 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
-@@ -692,7 +692,6 @@ int xhci_run(struct usb_hcd *hcd)
+@@ -65,7 +65,7 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
+ * handshake done). There are two failure modes: "usec" have passed (major
+ * hardware flakeout), or the register reads as all-ones (hardware removed).
+ */
+-int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
++int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
+ {
+ u32 result;
+ int ret;
+@@ -73,7 +73,7 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
+ ret = readl_poll_timeout_atomic(ptr, result,
+ (result & mask) == done ||
+ result == U32_MAX,
+- 1, usec);
++ 1, timeout_us);
+ if (result == U32_MAX) /* card removed */
+ return -ENODEV;
+
+@@ -162,7 +162,7 @@ int xhci_start(struct xhci_hcd *xhci)
+ * Transactions will be terminated immediately, and operational registers
+ * will be set to their defaults.
+ */
+-int xhci_reset(struct xhci_hcd *xhci)
++int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
+ {
+ u32 command;
+ u32 state;
+@@ -195,8 +195,7 @@ int xhci_reset(struct xhci_hcd *xhci)
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ udelay(1000);
+
+- ret = xhci_handshake(&xhci->op_regs->command,
+- CMD_RESET, 0, 10 * 1000 * 1000);
++ ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
+ if (ret)
+ return ret;
+
+@@ -209,8 +208,7 @@ int xhci_reset(struct xhci_hcd *xhci)
+ * xHCI cannot write to any doorbells or operational registers other
+ * than status until the "Controller Not Ready" flag is cleared.
+ */
+- ret = xhci_handshake(&xhci->op_regs->status,
+- STS_CNR, 0, 10 * 1000 * 1000);
++ ret = xhci_handshake(&xhci->op_regs->status, STS_CNR, 0, timeout_us);
+
+ xhci->usb2_rhub.bus_state.port_c_suspend = 0;
+ xhci->usb2_rhub.bus_state.suspended_ports = 0;
+@@ -692,7 +690,6 @@ int xhci_run(struct usb_hcd *hcd)
if (ret)
xhci_free_command(xhci, command);
}
@@ -116734,7 +173518,40 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Finished xhci_run for USB2 roothub");
-@@ -1092,6 +1091,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+@@ -732,7 +729,7 @@ static void xhci_stop(struct usb_hcd *hcd)
+ xhci->xhc_state |= XHCI_STATE_HALTED;
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+ xhci_halt(xhci);
+- xhci_reset(xhci);
++ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+ spin_unlock_irq(&xhci->lock);
+
+ xhci_cleanup_msix(xhci);
+@@ -781,11 +778,22 @@ void xhci_shutdown(struct usb_hcd *hcd)
+ if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
+ usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
+
++ /* Don't poll the roothubs after shutdown. */
++ xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
++ __func__, hcd->self.busnum);
++ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
++ del_timer_sync(&hcd->rh_timer);
++
++ if (xhci->shared_hcd) {
++ clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
++ del_timer_sync(&xhci->shared_hcd->rh_timer);
++ }
++
+ spin_lock_irq(&xhci->lock);
+ xhci_halt(xhci);
+ /* Workaround for spurious wakeups at shutdown with HSW */
+ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+- xhci_reset(xhci);
++ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+ spin_unlock_irq(&xhci->lock);
+
+ xhci_cleanup_msix(xhci);
+@@ -1092,6 +1100,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
int retval = 0;
bool comp_timer_running = false;
bool pending_portevent = false;
@@ -116742,7 +173559,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
if (!hcd->state)
return 0;
-@@ -1108,10 +1108,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+@@ -1108,10 +1117,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
spin_lock_irq(&xhci->lock);
@@ -116757,7 +173574,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
/*
* Some controllers might lose power during suspend, so wait
* for controller not ready bit to clear, just as in xHC init.
-@@ -1144,12 +1145,17 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+@@ -1144,12 +1154,17 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
}
@@ -116767,18 +173584,27 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
- /* If restore operation fails, re-initialize the HC during resume */
- if ((temp & STS_SRE) || hibernated) {
+ temp = readl(&xhci->op_regs->status);
-+
+
+ /* re-initialize the HC on Restore Error, or Host Controller Error */
+ if (temp & (STS_SRE | STS_HCE)) {
+ reinit_xhc = true;
+ xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
+ }
-
++
+ if (reinit_xhc) {
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
!(xhci_all_ports_seen_u0(xhci))) {
del_timer_sync(&xhci->comp_mode_recovery_timer);
-@@ -1605,9 +1611,12 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
+@@ -1164,7 +1179,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ xhci_dbg(xhci, "Stop HCD\n");
+ xhci_halt(xhci);
+ xhci_zero_64b_regs(xhci);
+- retval = xhci_reset(xhci);
++ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
+ spin_unlock_irq(&xhci->lock);
+ if (retval)
+ return retval;
+@@ -1605,9 +1620,12 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
struct urb_priv *urb_priv;
int num_tds;
@@ -116793,7 +173619,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
slot_id = urb->dev->slot_id;
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
-@@ -3324,7 +3333,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
+@@ -3324,7 +3342,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
return -EINVAL;
ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
if (ret <= 0)
@@ -116802,7 +173628,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
if (usb_ss_max_streams(&ep->ss_ep_comp) == 0) {
xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion"
" descriptor for ep 0x%x does not support streams\n",
-@@ -3935,7 +3944,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
+@@ -3935,7 +3953,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_slot_ctx *slot_ctx;
int i, ret;
@@ -116810,7 +173636,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
/*
* We called pm_runtime_get_noresume when the device was attached.
* Decrement the counter here to allow controller to runtime suspend
-@@ -3943,7 +3951,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
+@@ -3943,7 +3960,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
*/
if (xhci->quirks & XHCI_RESET_ON_RESUME)
pm_runtime_put_noidle(hcd->self.controller);
@@ -116818,7 +173644,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
/* If the host is halted due to driver unload, we still need to free the
-@@ -3962,9 +3969,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
+@@ -3962,9 +3978,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
virt_dev->udev = NULL;
@@ -116830,7 +173656,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
}
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
-@@ -3974,7 +3980,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
+@@ -3974,7 +3989,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
u32 state;
int ret = 0;
@@ -116839,7 +173665,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
if (!command)
return -ENOMEM;
-@@ -3999,6 +4005,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
+@@ -3999,6 +4014,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -116855,7 +173681,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
return ret;
}
-@@ -4095,23 +4110,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
+@@ -4095,23 +4119,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
xhci_debugfs_create_slot(xhci, slot_id);
@@ -116881,7 +173707,7 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
return 0;
}
-@@ -4241,6 +4253,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
+@@ -4241,6 +4262,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
mutex_unlock(&xhci->mutex);
ret = xhci_disable_slot(xhci, udev->slot_id);
@@ -116889,6 +173715,65 @@ index 541fe4dcc43a2..d7c0bf494d930 100644
if (!ret)
xhci_alloc_dev(hcd, udev);
kfree(command->completion);
+@@ -5305,7 +5327,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+
+ xhci_dbg(xhci, "Resetting HCD\n");
+ /* Reset the internal HC memory state and registers. */
+- retval = xhci_reset(xhci);
++ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
+ if (retval)
+ return retval;
+ xhci_dbg(xhci, "Reset complete\n");
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 5a75fe5631238..bc0789229527f 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -229,6 +229,9 @@ struct xhci_op_regs {
+ #define CMD_ETE (1 << 14)
+ /* bits 15:31 are reserved (and should be preserved on writes). */
+
++#define XHCI_RESET_LONG_USEC (10 * 1000 * 1000)
++#define XHCI_RESET_SHORT_USEC (250 * 1000)
++
+ /* IMAN - Interrupt Management Register */
+ #define IMAN_IE (1 << 1)
+ #define IMAN_IP (1 << 0)
+@@ -2083,11 +2086,11 @@ void xhci_free_container_ctx(struct xhci_hcd *xhci,
+
+ /* xHCI host controller glue */
+ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
+-int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
++int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us);
+ void xhci_quiesce(struct xhci_hcd *xhci);
+ int xhci_halt(struct xhci_hcd *xhci);
+ int xhci_start(struct xhci_hcd *xhci);
+-int xhci_reset(struct xhci_hcd *xhci);
++int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us);
+ int xhci_run(struct usb_hcd *hcd);
+ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
+ void xhci_shutdown(struct usb_hcd *hcd);
+@@ -2467,6 +2470,8 @@ static inline const char *xhci_decode_ctrl_ctx(char *str,
+ unsigned int bit;
+ int ret = 0;
+
++ str[0] = '\0';
++
+ if (drop) {
+ ret = sprintf(str, "Drop:");
+ for_each_set_bit(bit, &drop, 32)
+@@ -2624,8 +2629,11 @@ static inline const char *xhci_decode_usbsts(char *str, u32 usbsts)
+ {
+ int ret = 0;
+
++ ret = sprintf(str, " 0x%08x", usbsts);
++
+ if (usbsts == ~(u32)0)
+- return " 0xffffffff";
++ return str;
++
+ if (usbsts & STS_HALT)
+ ret += sprintf(str + ret, " HCHalted");
+ if (usbsts & STS_FATAL)
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index e5a8fcdbb78e7..6c38c62d29b26 100644
--- a/drivers/usb/misc/ftdi-elan.c
@@ -116934,6 +173819,51 @@ index efbd317f2f252..988a8c02e7e24 100644
}
/*---------------------*/
+diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
+index 748139d262633..0be8efcda15d5 100644
+--- a/drivers/usb/misc/uss720.c
++++ b/drivers/usb/misc/uss720.c
+@@ -71,6 +71,7 @@ static void destroy_priv(struct kref *kref)
+
+ dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n");
+ usb_put_dev(priv->usbdev);
++ priv->usbdev = NULL;
+ kfree(priv);
+ }
+
+@@ -736,7 +737,6 @@ static int uss720_probe(struct usb_interface *intf,
+ parport_announce_port(pp);
+
+ usb_set_intfdata(intf, pp);
+- usb_put_dev(usbdev);
+ return 0;
+
+ probe_abort:
+@@ -754,7 +754,6 @@ static void uss720_disconnect(struct usb_interface *intf)
+ usb_set_intfdata(intf, NULL);
+ if (pp) {
+ priv = pp->private_data;
+- priv->usbdev = NULL;
+ priv->pp = NULL;
+ dev_dbg(&intf->dev, "parport_remove_port\n");
+ parport_remove_port(pp);
+diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c
+index a6b04831b20bf..9b8aded3d95e9 100644
+--- a/drivers/usb/mtu3/mtu3_dr.c
++++ b/drivers/usb/mtu3/mtu3_dr.c
+@@ -21,10 +21,8 @@ static inline struct ssusb_mtk *otg_sx_to_ssusb(struct otg_switch_mtk *otg_sx)
+
+ static void toggle_opstate(struct ssusb_mtk *ssusb)
+ {
+- if (!ssusb->otg_switch.is_u3_drd) {
+- mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
+- mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
+- }
++ mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
++ mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
+ }
+
+ /* only port0 supports dual-role mode */
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index a9a65b4bbfede..9977600616d7e 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
@@ -117051,6 +173981,36 @@ index c968ecda42aa8..7ed4cc348d993 100644
musb->async = mem->start;
/* dma address for sync dma */
+diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
+index 661a229c105dd..34b9f81401871 100644
+--- a/drivers/usb/phy/phy-generic.c
++++ b/drivers/usb/phy/phy-generic.c
+@@ -268,6 +268,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
+ return -EPROBE_DEFER;
+ }
+
++ nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus");
++ if (PTR_ERR(nop->vbus_draw) == -ENODEV)
++ nop->vbus_draw = NULL;
++ if (IS_ERR(nop->vbus_draw))
++ return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
++ "could not get vbus regulator\n");
++
+ nop->dev = dev;
+ nop->phy.dev = nop->dev;
+ nop->phy.label = "nop-xceiv";
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index de5c012570603..ef8d1c73c7545 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -66,6 +66,7 @@ config USB_SERIAL_SIMPLE
+ - Libtransistor USB console
+ - a number of Motorola phones
+ - Motorola Tetra devices
++ - Nokia mobile phones
+ - Novatel Wireless GPS receivers
+ - Siemens USB/MPI adapter.
+ - ViVOtech ViVOpay USB device.
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 2db917eab7995..b5a1864e9cfdc 100644
--- a/drivers/usb/serial/ch341.c
@@ -117068,7 +174028,7 @@ index 2db917eab7995..b5a1864e9cfdc 100644
{ USB_DEVICE(0x9986, 0x7523) },
{ },
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
-index 189279869a8b0..08554e1548420 100644
+index 189279869a8b0..bd006e1712ccb 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -51,6 +51,7 @@ static void cp210x_enable_event_mode(struct usb_serial_port *port);
@@ -117087,7 +174047,16 @@ index 189279869a8b0..08554e1548420 100644
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
-@@ -1682,6 +1684,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
+@@ -192,6 +194,8 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
+ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
++ { USB_DEVICE(0x17A8, 0x0101) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Int Ant) */
++ { USB_DEVICE(0x17A8, 0x0102) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Ext Ant) */
+ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
+ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+@@ -1682,6 +1686,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
/* 2 banks of GPIO - One for the pins taken from each serial port */
if (intf_num == 0) {
@@ -117096,7 +174065,7 @@ index 189279869a8b0..08554e1548420 100644
if (mode.eci == CP210X_PIN_MODE_MODEM) {
/* mark all GPIOs of this interface as reserved */
priv->gpio_altfunc = 0xff;
-@@ -1692,8 +1696,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
+@@ -1692,8 +1698,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
CP210X_ECI_GPIO_MODE_MASK) >>
CP210X_ECI_GPIO_MODE_OFFSET);
@@ -117107,7 +174076,7 @@ index 189279869a8b0..08554e1548420 100644
if (mode.sci == CP210X_PIN_MODE_MODEM) {
/* mark all GPIOs of this interface as reserved */
priv->gpio_altfunc = 0xff;
-@@ -1704,7 +1709,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
+@@ -1704,7 +1711,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
CP210X_SCI_GPIO_MODE_MASK) >>
CP210X_SCI_GPIO_MODE_OFFSET);
@@ -117207,7 +174176,7 @@ index 87b89c99d5177..1cfcd805f2868 100644
return -ENOMEM;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
-index a484ff5e4ebf8..e7755d9cfc61a 100644
+index a484ff5e4ebf8..152ad882657d7 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -198,6 +198,8 @@ static void option_instat_callback(struct urb *urb);
@@ -117219,7 +174188,16 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
-@@ -1063,6 +1065,10 @@ static const struct usb_device_id option_ids[] = {
+@@ -430,6 +432,8 @@ static void option_instat_callback(struct urb *urb);
+ #define CINTERION_PRODUCT_CLS8 0x00b0
+ #define CINTERION_PRODUCT_MV31_MBIM 0x00b3
+ #define CINTERION_PRODUCT_MV31_RMNET 0x00b7
++#define CINTERION_PRODUCT_MV32_WA 0x00f1
++#define CINTERION_PRODUCT_MV32_WB 0x00f2
+
+ /* Olivetti products */
+ #define OLIVETTI_VENDOR_ID 0x0b3c
+@@ -1063,6 +1067,10 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5821E_ESIM),
.driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
@@ -117230,7 +174208,18 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
-@@ -1219,6 +1225,14 @@ static const struct usb_device_id option_ids[] = {
+@@ -1211,6 +1219,10 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */
+ .driver_info = NCTRL(2) | RSVD(3) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1057, 0xff), /* Telit FN980 */
++ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1058, 0xff), /* Telit FN980 (PCIe) */
++ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1060, 0xff), /* Telit LN920 (rmnet) */
+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1061, 0xff), /* Telit LN920 (MBIM) */
+@@ -1219,6 +1231,16 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */
.driver_info = NCTRL(0) | RSVD(1) },
@@ -117242,10 +174231,12 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
+ .driver_info = NCTRL(2) | RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */
++ .driver_info = RSVD(0) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
-@@ -1265,8 +1279,16 @@ static const struct usb_device_id option_ids[] = {
+@@ -1265,8 +1287,16 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */
.driver_info = NCTRL(2) },
@@ -117262,7 +174253,7 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) },
-@@ -1639,6 +1661,8 @@ static const struct usb_device_id option_ids[] = {
+@@ -1639,6 +1669,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(2) },
{ USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) }, /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */
@@ -117271,7 +174262,29 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
-@@ -2094,6 +2118,9 @@ static const struct usb_device_id option_ids[] = {
+@@ -1945,6 +1977,10 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = RSVD(3)},
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff),
+ .driver_info = RSVD(0)},
++ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
++ .driver_info = RSVD(3)},
++ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
++ .driver_info = RSVD(3)},
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100),
+ .driver_info = RSVD(4) },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120),
+@@ -2087,13 +2123,20 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = RSVD(3) },
+ { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
+ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
++ { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
++ { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
+ { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
+ .driver_info = RSVD(4) | RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
+ .driver_info = RSVD(6) },
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
@@ -117282,17 +174295,462 @@ index a484ff5e4ebf8..e7755d9cfc61a 100644
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
-index f45ca7ddf78ea..a70fd86f735ca 100644
+index f45ca7ddf78ea..1d878d05a6584 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
-@@ -432,6 +432,7 @@ static int pl2303_detect_type(struct usb_serial *serial)
+@@ -106,6 +106,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) },
++ { USB_DEVICE(HP_VENDOR_ID, HP_LM930_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) },
+ { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
+@@ -116,6 +117,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530GC_PRODUCT_ID) },
+ { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
+ { USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) },
++ { USB_DEVICE(IBM_VENDOR_ID, IBM_PRODUCT_ID) },
+ { } /* Terminating entry */
+ };
+
+@@ -432,8 +434,10 @@ static int pl2303_detect_type(struct usb_serial *serial)
case 0x200:
switch (bcdDevice) {
case 0x100:
+ case 0x105:
case 0x305:
case 0x405:
++ case 0x605:
/*
+ * Assume it's an HXN-type if the device doesn't
+ * support the old read request value.
+diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
+index 6097ee8fccb25..732f9b13ad5d5 100644
+--- a/drivers/usb/serial/pl2303.h
++++ b/drivers/usb/serial/pl2303.h
+@@ -35,6 +35,9 @@
+ #define ATEN_PRODUCT_UC232B 0x2022
+ #define ATEN_PRODUCT_ID2 0x2118
+
++#define IBM_VENDOR_ID 0x04b3
++#define IBM_PRODUCT_ID 0x4016
++
+ #define IODATA_VENDOR_ID 0x04bb
+ #define IODATA_PRODUCT_ID 0x0a03
+ #define IODATA_PRODUCT_ID_RSAQ5 0x0a0e
+@@ -132,6 +135,7 @@
+ #define HP_TD620_PRODUCT_ID 0x0956
+ #define HP_LD960_PRODUCT_ID 0x0b39
+ #define HP_LD381_PRODUCT_ID 0x0f7f
++#define HP_LM930_PRODUCT_ID 0x0f9b
+ #define HP_LCM220_PRODUCT_ID 0x3139
+ #define HP_LCM960_PRODUCT_ID 0x3239
+ #define HP_LD220_PRODUCT_ID 0x3524
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index c18bf8164bc2e..586ef5551e76e 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -166,6 +166,8 @@ static const struct usb_device_id id_table[] = {
+ {DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */
+ {DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */
+ {DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */
++ {DEVICE_SWI(0x1199, 0xc080)}, /* Sierra Wireless EM7590 QDL */
++ {DEVICE_SWI(0x1199, 0xc081)}, /* Sierra Wireless EM7590 */
+ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
+index bd23a7cb1be2b..4c6747889a194 100644
+--- a/drivers/usb/serial/usb-serial-simple.c
++++ b/drivers/usb/serial/usb-serial-simple.c
+@@ -91,6 +91,11 @@ DEVICE(moto_modem, MOTO_IDS);
+ { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */
+ DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
+
++/* Nokia mobile phone driver */
++#define NOKIA_IDS() \
++ { USB_DEVICE(0x0421, 0x069a) } /* Nokia 130 (RM-1035) */
++DEVICE(nokia, NOKIA_IDS);
++
+ /* Novatel Wireless GPS driver */
+ #define NOVATEL_IDS() \
+ { USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */
+@@ -123,6 +128,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
+ &vivopay_device,
+ &moto_modem_device,
+ &motorola_tetra_device,
++ &nokia_device,
+ &novatel_gps_device,
+ &hp4x_device,
+ &suunto_device,
+@@ -140,6 +146,7 @@ static const struct usb_device_id id_table[] = {
+ VIVOPAY_IDS(),
+ MOTO_IDS(),
+ MOTOROLA_TETRA_IDS(),
++ NOKIA_IDS(),
+ NOVATEL_IDS(),
+ HP4X_IDS(),
+ SUUNTO_IDS(),
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index da65d14c9ed5e..06aad0d727ddc 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -584,9 +584,8 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
+ switch (command) {
+ case WHITEHEAT_GET_DTR_RTS:
+ info = usb_get_serial_port_data(port);
+- memcpy(&info->mcr, command_info->result_buffer,
+- sizeof(struct whiteheat_dr_info));
+- break;
++ info->mcr = command_info->result_buffer[0];
++ break;
+ }
+ }
+ exit:
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 5f7d678502be4..6012603f3630e 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -237,36 +237,33 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
+ #define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0))
+
+
+-struct SD_STATUS {
+- u8 Insert:1;
+- u8 Ready:1;
+- u8 MediaChange:1;
+- u8 IsMMC:1;
+- u8 HiCapacity:1;
+- u8 HiSpeed:1;
+- u8 WtP:1;
+- u8 Reserved:1;
+-};
+-
+-struct MS_STATUS {
+- u8 Insert:1;
+- u8 Ready:1;
+- u8 MediaChange:1;
+- u8 IsMSPro:1;
+- u8 IsMSPHG:1;
+- u8 Reserved1:1;
+- u8 WtP:1;
+- u8 Reserved2:1;
+-};
+-
+-struct SM_STATUS {
+- u8 Insert:1;
+- u8 Ready:1;
+- u8 MediaChange:1;
+- u8 Reserved:3;
+- u8 WtP:1;
+- u8 IsMS:1;
+-};
++/* SD_STATUS bits */
++#define SD_Insert BIT(0)
++#define SD_Ready BIT(1)
++#define SD_MediaChange BIT(2)
++#define SD_IsMMC BIT(3)
++#define SD_HiCapacity BIT(4)
++#define SD_HiSpeed BIT(5)
++#define SD_WtP BIT(6)
++ /* Bit 7 reserved */
++
++/* MS_STATUS bits */
++#define MS_Insert BIT(0)
++#define MS_Ready BIT(1)
++#define MS_MediaChange BIT(2)
++#define MS_IsMSPro BIT(3)
++#define MS_IsMSPHG BIT(4)
++ /* Bit 5 reserved */
++#define MS_WtP BIT(6)
++ /* Bit 7 reserved */
++
++/* SM_STATUS bits */
++#define SM_Insert BIT(0)
++#define SM_Ready BIT(1)
++#define SM_MediaChange BIT(2)
++ /* Bits 3-5 reserved */
++#define SM_WtP BIT(6)
++#define SM_IsMS BIT(7)
+
+ struct ms_bootblock_cis {
+ u8 bCistplDEVICE[6]; /* 0 */
+@@ -437,9 +434,9 @@ struct ene_ub6250_info {
+ u8 *bbuf;
+
+ /* for 6250 code */
+- struct SD_STATUS SD_Status;
+- struct MS_STATUS MS_Status;
+- struct SM_STATUS SM_Status;
++ u8 SD_Status;
++ u8 MS_Status;
++ u8 SM_Status;
+
+ /* ----- SD Control Data ---------------- */
+ /*SD_REGISTER SD_Regs; */
+@@ -602,7 +599,7 @@ static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+- if (info->SD_Status.Insert && info->SD_Status.Ready)
++ if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready))
+ return USB_STOR_TRANSPORT_GOOD;
+ else {
+ ene_sd_init(us);
+@@ -622,7 +619,7 @@ static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+- if (info->SD_Status.WtP)
++ if (info->SD_Status & SD_WtP)
+ usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ else
+ usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+@@ -641,9 +638,9 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ usb_stor_dbg(us, "sd_scsi_read_capacity\n");
+- if (info->SD_Status.HiCapacity) {
++ if (info->SD_Status & SD_HiCapacity) {
+ bl_len = 0x200;
+- if (info->SD_Status.IsMMC)
++ if (info->SD_Status & SD_IsMMC)
+ bl_num = info->HC_C_SIZE-1;
+ else
+ bl_num = (info->HC_C_SIZE + 1) * 1024 - 1;
+@@ -693,7 +690,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+- if (info->SD_Status.HiCapacity)
++ if (info->SD_Status & SD_HiCapacity)
+ bnByte = bn;
+
+ /* set up the command wrapper */
+@@ -733,7 +730,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+- if (info->SD_Status.HiCapacity)
++ if (info->SD_Status & SD_HiCapacity)
+ bnByte = bn;
+
+ /* set up the command wrapper */
+@@ -1456,7 +1453,7 @@ static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ /* pr_info("MS_SCSI_Test_Unit_Ready\n"); */
+- if (info->MS_Status.Insert && info->MS_Status.Ready) {
++ if ((info->MS_Status & MS_Insert) && (info->MS_Status & MS_Ready)) {
+ return USB_STOR_TRANSPORT_GOOD;
+ } else {
+ ene_ms_init(us);
+@@ -1476,7 +1473,7 @@ static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+- if (info->MS_Status.WtP)
++ if (info->MS_Status & MS_WtP)
+ usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ else
+ usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+@@ -1495,7 +1492,7 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+
+ usb_stor_dbg(us, "ms_scsi_read_capacity\n");
+ bl_len = 0x200;
+- if (info->MS_Status.IsMSPro)
++ if (info->MS_Status & MS_IsMSPro)
+ bl_num = info->MSP_TotalBlock - 1;
+ else
+ bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
+@@ -1650,7 +1647,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+- if (info->MS_Status.IsMSPro) {
++ if (info->MS_Status & MS_IsMSPro) {
+ result = ene_load_bincode(us, MSP_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");
+@@ -1751,7 +1748,7 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+- if (info->MS_Status.IsMSPro) {
++ if (info->MS_Status & MS_IsMSPro) {
+ result = ene_load_bincode(us, MSP_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("Load MSP RW pattern Fail !!\n");
+@@ -1859,12 +1856,12 @@ static int ene_get_card_status(struct us_data *us, u8 *buf)
+
+ tmpreg = (u16) reg4b;
+ reg4b = *(u32 *)(&buf[0x14]);
+- if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
++ if ((info->SD_Status & SD_HiCapacity) && !(info->SD_Status & SD_IsMMC))
+ info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+
+ info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
+ info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07;
+- if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
++ if ((info->SD_Status & SD_HiCapacity) && (info->SD_Status & SD_IsMMC))
+ info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+
+ if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
+@@ -2076,6 +2073,7 @@ static int ene_ms_init(struct us_data *us)
+ u16 MSP_BlockSize, MSP_UserAreaBlocks;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ u8 *bbuf = info->bbuf;
++ unsigned int s;
+
+ printk(KERN_INFO "transport --- ENE_MSInit\n");
+
+@@ -2100,15 +2098,16 @@ static int ene_ms_init(struct us_data *us)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ /* the same part to test ENE */
+- info->MS_Status = *(struct MS_STATUS *) bbuf;
+-
+- if (info->MS_Status.Insert && info->MS_Status.Ready) {
+- printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert);
+- printk(KERN_INFO "Ready = %x\n", info->MS_Status.Ready);
+- printk(KERN_INFO "IsMSPro = %x\n", info->MS_Status.IsMSPro);
+- printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG);
+- printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
+- if (info->MS_Status.IsMSPro) {
++ info->MS_Status = bbuf[0];
++
++ s = info->MS_Status;
++ if ((s & MS_Insert) && (s & MS_Ready)) {
++ printk(KERN_INFO "Insert = %x\n", !!(s & MS_Insert));
++ printk(KERN_INFO "Ready = %x\n", !!(s & MS_Ready));
++ printk(KERN_INFO "IsMSPro = %x\n", !!(s & MS_IsMSPro));
++ printk(KERN_INFO "IsMSPHG = %x\n", !!(s & MS_IsMSPHG));
++ printk(KERN_INFO "WtP= %x\n", !!(s & MS_WtP));
++ if (s & MS_IsMSPro) {
+ MSP_BlockSize = (bbuf[6] << 8) | bbuf[7];
+ MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
+ info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+@@ -2169,17 +2168,17 @@ static int ene_sd_init(struct us_data *us)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+- info->SD_Status = *(struct SD_STATUS *) bbuf;
+- if (info->SD_Status.Insert && info->SD_Status.Ready) {
+- struct SD_STATUS *s = &info->SD_Status;
++ info->SD_Status = bbuf[0];
++ if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready)) {
++ unsigned int s = info->SD_Status;
+
+ ene_get_card_status(us, bbuf);
+- usb_stor_dbg(us, "Insert = %x\n", s->Insert);
+- usb_stor_dbg(us, "Ready = %x\n", s->Ready);
+- usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC);
+- usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity);
+- usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed);
+- usb_stor_dbg(us, "WtP = %x\n", s->WtP);
++ usb_stor_dbg(us, "Insert = %x\n", !!(s & SD_Insert));
++ usb_stor_dbg(us, "Ready = %x\n", !!(s & SD_Ready));
++ usb_stor_dbg(us, "IsMMC = %x\n", !!(s & SD_IsMMC));
++ usb_stor_dbg(us, "HiCapacity = %x\n", !!(s & SD_HiCapacity));
++ usb_stor_dbg(us, "HiSpeed = %x\n", !!(s & SD_HiSpeed));
++ usb_stor_dbg(us, "WtP = %x\n", !!(s & SD_WtP));
+ } else {
+ usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
+ return USB_STOR_TRANSPORT_ERROR;
+@@ -2201,14 +2200,14 @@ static int ene_init(struct us_data *us)
+
+ misc_reg03 = bbuf[0];
+ if (misc_reg03 & 0x01) {
+- if (!info->SD_Status.Ready) {
++ if (!(info->SD_Status & SD_Ready)) {
+ result = ene_sd_init(us);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ }
+ if (misc_reg03 & 0x02) {
+- if (!info->MS_Status.Ready) {
++ if (!(info->MS_Status & MS_Ready)) {
+ result = ene_ms_init(us);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+@@ -2307,14 +2306,14 @@ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+
+ /*US_DEBUG(usb_stor_show_command(us, srb)); */
+ scsi_set_resid(srb, 0);
+- if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready)))
++ if (unlikely(!(info->SD_Status & SD_Ready) || (info->MS_Status & MS_Ready)))
+ result = ene_init(us);
+ if (result == USB_STOR_XFER_GOOD) {
+ result = USB_STOR_TRANSPORT_ERROR;
+- if (info->SD_Status.Ready)
++ if (info->SD_Status & SD_Ready)
+ result = sd_scsi_irp(us, srb);
+
+- if (info->MS_Status.Ready)
++ if (info->MS_Status & MS_Ready)
+ result = ms_scsi_irp(us, srb);
+ }
+ return result;
+@@ -2378,7 +2377,6 @@ static int ene_ub6250_probe(struct usb_interface *intf,
+
+ static int ene_ub6250_resume(struct usb_interface *iface)
+ {
+- u8 tmp = 0;
+ struct us_data *us = usb_get_intfdata(iface);
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+@@ -2390,17 +2388,16 @@ static int ene_ub6250_resume(struct usb_interface *iface)
+ mutex_unlock(&us->dev_mutex);
+
+ info->Power_IsResum = true;
+- /*info->SD_Status.Ready = 0; */
+- info->SD_Status = *(struct SD_STATUS *)&tmp;
+- info->MS_Status = *(struct MS_STATUS *)&tmp;
+- info->SM_Status = *(struct SM_STATUS *)&tmp;
++ /* info->SD_Status &= ~SD_Ready; */
++ info->SD_Status = 0;
++ info->MS_Status = 0;
++ info->SM_Status = 0;
+
+ return 0;
+ }
+
+ static int ene_ub6250_reset_resume(struct usb_interface *iface)
+ {
+- u8 tmp = 0;
+ struct us_data *us = usb_get_intfdata(iface);
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+@@ -2412,10 +2409,10 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface)
+ * the device
+ */
+ info->Power_IsResum = true;
+- /*info->SD_Status.Ready = 0; */
+- info->SD_Status = *(struct SD_STATUS *)&tmp;
+- info->MS_Status = *(struct MS_STATUS *)&tmp;
+- info->SM_Status = *(struct SM_STATUS *)&tmp;
++ /* info->SD_Status &= ~SD_Ready; */
++ info->SD_Status = 0;
++ info->MS_Status = 0;
++ info->SM_Status = 0;
+
+ return 0;
+ }
+diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
+index 3789698d9d3c6..0c423916d7bfa 100644
+--- a/drivers/usb/storage/realtek_cr.c
++++ b/drivers/usb/storage/realtek_cr.c
+@@ -365,7 +365,7 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
+
+ buf = kmalloc(len, GFP_NOIO);
+ if (buf == NULL)
+- return USB_STOR_TRANSPORT_ERROR;
++ return -ENOMEM;
+
+ usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
+
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c6b3fcf901805..1a05e3dcfec8a 100644
--- a/drivers/usb/storage/unusual_devs.h
@@ -117382,7 +174840,7 @@ index 7a2a17866a823..72f9001b07921 100644
default:
break;
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
-index c15eec9cc460a..7d540afdb7cc3 100644
+index c15eec9cc460a..64e248117c41a 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -75,9 +75,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
@@ -117428,6 +174886,15 @@ index c15eec9cc460a..7d540afdb7cc3 100644
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
if (ret < 0)
return ret;
+@@ -851,7 +877,7 @@ static int tcpci_remove(struct i2c_client *client)
+ /* Disable chip interrupts before unregistering port */
+ err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0);
+ if (err < 0)
+- return err;
++ dev_warn(&client->dev, "Failed to disable irqs (%pe)\n", ERR_PTR(err));
+
+ tcpci_unregister_port(chip->tcpci);
+
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 2be7a77d400ef..b2edd45f13c68 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
@@ -117440,6 +174907,57 @@ index 2be7a77d400ef..b2edd45f13c68 100644
#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0)
#define TCPC_FAULT_STATUS 0x1f
+diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
+index f1bd9e09bc87f..8a952eaf90163 100644
+--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
++++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
+@@ -15,6 +15,9 @@
+
+ #include "tcpci.h"
+
++#define MT6360_REG_PHYCTRL1 0x80
++#define MT6360_REG_PHYCTRL3 0x82
++#define MT6360_REG_PHYCTRL7 0x86
+ #define MT6360_REG_VCONNCTRL1 0x8C
+ #define MT6360_REG_MODECTRL2 0x8F
+ #define MT6360_REG_SWRESET 0xA0
+@@ -22,6 +25,8 @@
+ #define MT6360_REG_DRPCTRL1 0xA2
+ #define MT6360_REG_DRPCTRL2 0xA3
+ #define MT6360_REG_I2CTORST 0xBF
++#define MT6360_REG_PHYCTRL11 0xCA
++#define MT6360_REG_RXCTRL1 0xCE
+ #define MT6360_REG_RXCTRL2 0xCF
+ #define MT6360_REG_CTDCTRL2 0xEC
+
+@@ -106,6 +111,27 @@ static int mt6360_tcpc_init(struct tcpci *tcpci, struct tcpci_data *tdata)
+ if (ret)
+ return ret;
+
++ /* BMC PHY */
++ ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL1, 0x3A70);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(regmap, MT6360_REG_PHYCTRL3, 0x82);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(regmap, MT6360_REG_PHYCTRL7, 0x36);
++ if (ret)
++ return ret;
++
++ ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL11, 0x3C60);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(regmap, MT6360_REG_RXCTRL1, 0xE8);
++ if (ret)
++ return ret;
++
+ /* Set shipping mode off, AUTOIDLE on */
+ return regmap_write(regmap, MT6360_REG_MODECTRL2, 0x7A);
+ }
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 7f2f3ff1b3911..5fce795b69c7f 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
@@ -117552,7 +175070,7 @@ index 7f2f3ff1b3911..5fce795b69c7f 100644
EXPORT_SYMBOL_GPL(tcpm_unregister_port);
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
-index ea4cc0a6e40cc..d229d2db44ff0 100644
+index ea4cc0a6e40cc..23a8b9b0b1fef 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -117,7 +117,7 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len)
@@ -117564,7 +175082,26 @@ index ea4cc0a6e40cc..d229d2db44ff0 100644
return -EINVAL;
if (!tps->i2c_protocol)
-@@ -618,12 +618,12 @@ static int tps6598x_probe(struct i2c_client *client)
+@@ -246,6 +246,10 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
+ typec_set_pwr_opmode(tps->port, mode);
+ typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+ typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
++ if (TPS_STATUS_TO_UPSIDE_DOWN(status))
++ typec_set_orientation(tps->port, TYPEC_ORIENTATION_REVERSE);
++ else
++ typec_set_orientation(tps->port, TYPEC_ORIENTATION_NORMAL);
+ tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), true);
+
+ tps->partner = typec_register_partner(tps->port, &desc);
+@@ -268,6 +272,7 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
+ typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB);
+ typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+ typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
++ typec_set_orientation(tps->port, TYPEC_ORIENTATION_NONE);
+ tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), false);
+
+ power_supply_changed(tps->psy);
+@@ -618,12 +623,12 @@ static int tps6598x_probe(struct i2c_client *client)
ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
if (ret < 0)
@@ -117579,7 +175116,7 @@ index ea4cc0a6e40cc..d229d2db44ff0 100644
/*
* This fwnode has a "compatible" property, but is never populated as a
-@@ -712,7 +712,8 @@ err_role_put:
+@@ -712,7 +717,8 @@ err_role_put:
usb_role_switch_put(tps->role_sw);
err_fwnode_put:
fwnode_handle_put(fwnode);
@@ -117589,6 +175126,80 @@ index ea4cc0a6e40cc..d229d2db44ff0 100644
return ret;
}
+diff --git a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h
+index 003a577be2164..1f59b9fa3fad2 100644
+--- a/drivers/usb/typec/tipd/tps6598x.h
++++ b/drivers/usb/typec/tipd/tps6598x.h
+@@ -17,6 +17,7 @@
+ /* TPS_REG_STATUS bits */
+ #define TPS_STATUS_PLUG_PRESENT BIT(0)
+ #define TPS_STATUS_PLUG_UPSIDE_DOWN BIT(4)
++#define TPS_STATUS_TO_UPSIDE_DOWN(s) (!!((s) & TPS_STATUS_PLUG_UPSIDE_DOWN))
+ #define TPS_STATUS_PORTROLE BIT(5)
+ #define TPS_STATUS_TO_TYPEC_PORTROLE(s) (!!((s) & TPS_STATUS_PORTROLE))
+ #define TPS_STATUS_DATAROLE BIT(6)
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 5ef5bd0e87cf2..8a7e2dd52ad5a 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -955,6 +955,8 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
+ role == TYPEC_HOST))
+ goto out_unlock;
+
++ reinit_completion(&con->complete);
++
+ command = UCSI_SET_UOR | UCSI_CONNECTOR_NUMBER(con->num);
+ command |= UCSI_SET_UOR_ROLE(role);
+ command |= UCSI_SET_UOR_ACCEPT_ROLE_SWAPS;
+@@ -962,14 +964,18 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
+ if (ret < 0)
+ goto out_unlock;
+
++ mutex_unlock(&con->lock);
++
+ if (!wait_for_completion_timeout(&con->complete,
+- msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
+- ret = -ETIMEDOUT;
++ msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
++ return -ETIMEDOUT;
++
++ return 0;
+
+ out_unlock:
+ mutex_unlock(&con->lock);
+
+- return ret < 0 ? ret : 0;
++ return ret;
+ }
+
+ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
+@@ -991,6 +997,8 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
+ if (cur_role == role)
+ goto out_unlock;
+
++ reinit_completion(&con->complete);
++
+ command = UCSI_SET_PDR | UCSI_CONNECTOR_NUMBER(con->num);
+ command |= UCSI_SET_PDR_ROLE(role);
+ command |= UCSI_SET_PDR_ACCEPT_ROLE_SWAPS;
+@@ -998,11 +1006,13 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
+ if (ret < 0)
+ goto out_unlock;
+
++ mutex_unlock(&con->lock);
++
+ if (!wait_for_completion_timeout(&con->complete,
+- msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) {
+- ret = -ETIMEDOUT;
+- goto out_unlock;
+- }
++ msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
++ return -ETIMEDOUT;
++
++ mutex_lock(&con->lock);
+
+ /* Something has gone wrong while swapping the role */
+ if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index bff96d64dddff..6db7c8ddd51cd 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -117792,11 +175403,34 @@ index dcd648e1f7e7e..003530b19b4ee 100644
adapter->vdpa.mdev = &ifcvf_mgmt_dev->mdev;
ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring);
+diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
+index 01a848adf5903..81dc3d88d3ddd 100644
+--- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h
++++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
+@@ -63,7 +63,7 @@ struct mlx5_control_vq {
+ unsigned short head;
+ };
+
+-struct mlx5_ctrl_wq_ent {
++struct mlx5_vdpa_wq_ent {
+ struct work_struct work;
+ struct mlx5_vdpa_dev *mvdev;
+ };
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
-index bd56de7484dcb..1afbda216df52 100644
+index bd56de7484dcb..e4258f40dcd74 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
-@@ -873,8 +873,6 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
+@@ -161,6 +161,9 @@ struct mlx5_vdpa_net {
+ bool setup;
+ u16 mtu;
+ u32 cur_num_vqs;
++ struct notifier_block nb;
++ struct vdpa_callback config_cb;
++ struct mlx5_vdpa_wq_ent cvq_ent;
+ };
+
+ static void free_resources(struct mlx5_vdpa_net *ndev);
+@@ -873,8 +876,6 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
MLX5_SET(virtio_q, vq_ctx, umem_3_id, mvq->umem3.id);
MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem3.size);
MLX5_SET(virtio_q, vq_ctx, pd, ndev->mvdev.res.pdn);
@@ -117805,7 +175439,7 @@ index bd56de7484dcb..1afbda216df52 100644
err = mlx5_cmd_exec(ndev->mvdev.mdev, in, inlen, out, sizeof(out));
if (err)
-@@ -1512,9 +1510,11 @@ static int change_num_qps(struct mlx5_vdpa_dev *mvdev, int newqps)
+@@ -1512,9 +1513,11 @@ static int change_num_qps(struct mlx5_vdpa_dev *mvdev, int newqps)
return 0;
clean_added:
@@ -117818,7 +175452,153 @@ index bd56de7484dcb..1afbda216df52 100644
return err;
}
-@@ -2192,7 +2192,6 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev)
+@@ -1529,11 +1532,27 @@ static virtio_net_ctrl_ack handle_ctrl_mq(struct mlx5_vdpa_dev *mvdev, u8 cmd)
+
+ switch (cmd) {
+ case VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET:
++ /* This mq feature check aligns with pre-existing userspace
++ * implementation.
++ *
++ * Without it, an untrusted driver could fake a multiqueue config
++ * request down to a non-mq device that may cause kernel to
++ * panic due to uninitialized resources for extra vqs. Even with
++ * a well behaving guest driver, it is not expected to allow
++ * changing the number of vqs on a non-mq device.
++ */
++ if (!MLX5_FEATURE(mvdev, VIRTIO_NET_F_MQ))
++ break;
++
+ read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->riov, (void *)&mq, sizeof(mq));
+ if (read != sizeof(mq))
+ break;
+
+ newqps = mlx5vdpa16_to_cpu(mvdev, mq.virtqueue_pairs);
++ if (newqps < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
++ newqps > mlx5_vdpa_max_qps(mvdev->max_vqs))
++ break;
++
+ if (ndev->cur_num_vqs == 2 * newqps) {
+ status = VIRTIO_NET_OK;
+ break;
+@@ -1557,22 +1576,22 @@ static void mlx5_cvq_kick_handler(struct work_struct *work)
+ {
+ virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+ struct virtio_net_ctrl_hdr ctrl;
+- struct mlx5_ctrl_wq_ent *wqent;
++ struct mlx5_vdpa_wq_ent *wqent;
+ struct mlx5_vdpa_dev *mvdev;
+ struct mlx5_control_vq *cvq;
+ struct mlx5_vdpa_net *ndev;
+ size_t read, write;
+ int err;
+
+- wqent = container_of(work, struct mlx5_ctrl_wq_ent, work);
++ wqent = container_of(work, struct mlx5_vdpa_wq_ent, work);
+ mvdev = wqent->mvdev;
+ ndev = to_mlx5_vdpa_ndev(mvdev);
+ cvq = &mvdev->cvq;
+ if (!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)))
+- goto out;
++ return;
+
+ if (!cvq->ready)
+- goto out;
++ return;
+
+ while (true) {
+ err = vringh_getdesc_iotlb(&cvq->vring, &cvq->riov, &cvq->wiov, &cvq->head,
+@@ -1606,9 +1625,10 @@ static void mlx5_cvq_kick_handler(struct work_struct *work)
+
+ if (vringh_need_notify_iotlb(&cvq->vring))
+ vringh_notify(&cvq->vring);
++
++ queue_work(mvdev->wq, &wqent->work);
++ break;
+ }
+-out:
+- kfree(wqent);
+ }
+
+ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
+@@ -1616,7 +1636,6 @@ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
+ struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
+ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
+ struct mlx5_vdpa_virtqueue *mvq;
+- struct mlx5_ctrl_wq_ent *wqent;
+
+ if (!is_index_valid(mvdev, idx))
+ return;
+@@ -1625,13 +1644,7 @@ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
+ if (!mvdev->cvq.ready)
+ return;
+
+- wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC);
+- if (!wqent)
+- return;
+-
+- wqent->mvdev = mvdev;
+- INIT_WORK(&wqent->work, mlx5_cvq_kick_handler);
+- queue_work(mvdev->wq, &wqent->work);
++ queue_work(mvdev->wq, &ndev->cvq_ent.work);
+ return;
+ }
+
+@@ -1852,16 +1865,31 @@ static u64 mlx5_vdpa_get_features(struct vdpa_device *vdev)
+ ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_NET_F_CTRL_VQ);
+ ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR);
+ ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_NET_F_MQ);
++ ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_NET_F_STATUS);
+
+ print_features(mvdev, ndev->mvdev.mlx_features, false);
+ return ndev->mvdev.mlx_features;
+ }
+
+-static int verify_min_features(struct mlx5_vdpa_dev *mvdev, u64 features)
++static int verify_driver_features(struct mlx5_vdpa_dev *mvdev, u64 features)
+ {
++ /* Minimum features to expect */
+ if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)))
+ return -EOPNOTSUPP;
+
++ /* Double check features combination sent down by the driver.
++ * Fail invalid features due to absence of the depended feature.
++ *
++ * Per VIRTIO v1.1 specification, section 5.1.3.1 Feature bit
++ * requirements: "VIRTIO_NET_F_MQ Requires VIRTIO_NET_F_CTRL_VQ".
++ * By failing the invalid features sent down by untrusted drivers,
++ * we're assured the assumption made upon is_index_valid() and
++ * is_ctrl_vq_idx() will not be compromised.
++ */
++ if ((features & (BIT_ULL(VIRTIO_NET_F_MQ) | BIT_ULL(VIRTIO_NET_F_CTRL_VQ))) ==
++ BIT_ULL(VIRTIO_NET_F_MQ))
++ return -EINVAL;
++
+ return 0;
+ }
+
+@@ -1937,7 +1965,7 @@ static int mlx5_vdpa_set_features(struct vdpa_device *vdev, u64 features)
+
+ print_features(mvdev, features, true);
+
+- err = verify_min_features(mvdev, features);
++ err = verify_driver_features(mvdev, features);
+ if (err)
+ return err;
+
+@@ -1950,8 +1978,10 @@ static int mlx5_vdpa_set_features(struct vdpa_device *vdev, u64 features)
+
+ static void mlx5_vdpa_set_config_cb(struct vdpa_device *vdev, struct vdpa_callback *cb)
+ {
+- /* not implemented */
+- mlx5_vdpa_warn(to_mvdev(vdev), "set config callback not supported\n");
++ struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
++ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
++
++ ndev->config_cb = *cb;
+ }
+
+ #define MLX5_VDPA_MAX_VQ_ENTRIES 256
+@@ -2192,7 +2222,6 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev)
clear_vqs_ready(ndev);
mlx5_vdpa_destroy_mr(&ndev->mvdev);
ndev->mvdev.status = 0;
@@ -117826,6 +175606,129 @@ index bd56de7484dcb..1afbda216df52 100644
memset(ndev->event_cbs, 0, sizeof(ndev->event_cbs));
ndev->mvdev.actual_features = 0;
++mvdev->generation;
+@@ -2404,6 +2433,82 @@ struct mlx5_vdpa_mgmtdev {
+ struct mlx5_vdpa_net *ndev;
+ };
+
++static u8 query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
++{
++ u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
++ u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
++ int err;
++
++ MLX5_SET(query_vport_state_in, in, opcode, MLX5_CMD_OP_QUERY_VPORT_STATE);
++ MLX5_SET(query_vport_state_in, in, op_mod, opmod);
++ MLX5_SET(query_vport_state_in, in, vport_number, vport);
++ if (vport)
++ MLX5_SET(query_vport_state_in, in, other_vport, 1);
++
++ err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out);
++ if (err)
++ return 0;
++
++ return MLX5_GET(query_vport_state_out, out, state);
++}
++
++static bool get_link_state(struct mlx5_vdpa_dev *mvdev)
++{
++ if (query_vport_state(mvdev->mdev, MLX5_VPORT_STATE_OP_MOD_VNIC_VPORT, 0) ==
++ VPORT_STATE_UP)
++ return true;
++
++ return false;
++}
++
++static void update_carrier(struct work_struct *work)
++{
++ struct mlx5_vdpa_wq_ent *wqent;
++ struct mlx5_vdpa_dev *mvdev;
++ struct mlx5_vdpa_net *ndev;
++
++ wqent = container_of(work, struct mlx5_vdpa_wq_ent, work);
++ mvdev = wqent->mvdev;
++ ndev = to_mlx5_vdpa_ndev(mvdev);
++ if (get_link_state(mvdev))
++ ndev->config.status |= cpu_to_mlx5vdpa16(mvdev, VIRTIO_NET_S_LINK_UP);
++ else
++ ndev->config.status &= cpu_to_mlx5vdpa16(mvdev, ~VIRTIO_NET_S_LINK_UP);
++
++ if (ndev->config_cb.callback)
++ ndev->config_cb.callback(ndev->config_cb.private);
++
++ kfree(wqent);
++}
++
++static int event_handler(struct notifier_block *nb, unsigned long event, void *param)
++{
++ struct mlx5_vdpa_net *ndev = container_of(nb, struct mlx5_vdpa_net, nb);
++ struct mlx5_eqe *eqe = param;
++ int ret = NOTIFY_DONE;
++ struct mlx5_vdpa_wq_ent *wqent;
++
++ if (event == MLX5_EVENT_TYPE_PORT_CHANGE) {
++ switch (eqe->sub_type) {
++ case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
++ case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
++ wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC);
++ if (!wqent)
++ return NOTIFY_DONE;
++
++ wqent->mvdev = &ndev->mvdev;
++ INIT_WORK(&wqent->work, update_carrier);
++ queue_work(ndev->mvdev.wq, &wqent->work);
++ ret = NOTIFY_OK;
++ break;
++ default:
++ return NOTIFY_DONE;
++ }
++ return ret;
++ }
++ return ret;
++}
++
+ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
+ {
+ struct mlx5_vdpa_mgmtdev *mgtdev = container_of(v_mdev, struct mlx5_vdpa_mgmtdev, mgtdev);
+@@ -2448,6 +2553,11 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
+ if (err)
+ goto err_mtu;
+
++ if (get_link_state(mvdev))
++ ndev->config.status |= cpu_to_mlx5vdpa16(mvdev, VIRTIO_NET_S_LINK_UP);
++ else
++ ndev->config.status &= cpu_to_mlx5vdpa16(mvdev, ~VIRTIO_NET_S_LINK_UP);
++
+ if (!is_zero_ether_addr(config->mac)) {
+ pfmdev = pci_get_drvdata(pci_physfn(mdev->pdev));
+ err = mlx5_mpfs_add_mac(pfmdev, config->mac);
+@@ -2473,12 +2583,16 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
+ if (err)
+ goto err_mr;
+
+- mvdev->wq = create_singlethread_workqueue("mlx5_vdpa_ctrl_wq");
++ ndev->cvq_ent.mvdev = mvdev;
++ INIT_WORK(&ndev->cvq_ent.work, mlx5_cvq_kick_handler);
++ mvdev->wq = create_singlethread_workqueue("mlx5_vdpa_wq");
+ if (!mvdev->wq) {
+ err = -ENOMEM;
+ goto err_res2;
+ }
+
++ ndev->nb.notifier_call = event_handler;
++ mlx5_notifier_register(mdev, &ndev->nb);
+ ndev->cur_num_vqs = 2 * mlx5_vdpa_max_qps(max_vqs);
+ mvdev->vdev.mdev = &mgtdev->mgtdev;
+ err = _vdpa_register_device(&mvdev->vdev, ndev->cur_num_vqs + 1);
+@@ -2509,7 +2623,9 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device *
+ {
+ struct mlx5_vdpa_mgmtdev *mgtdev = container_of(v_mdev, struct mlx5_vdpa_mgmtdev, mgtdev);
+ struct mlx5_vdpa_dev *mvdev = to_mvdev(dev);
++ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
+
++ mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
+ destroy_workqueue(mvdev->wq);
+ _vdpa_unregister_device(dev);
+ mgtdev->ndev = NULL;
diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
index 1dc121a07a934..12bf3d16a40ff 100644
--- a/drivers/vdpa/vdpa.c
@@ -117858,6 +175761,19 @@ index 5f484fff8dbec..41b0cd17fcbac 100644
kvfree(vdpasim->buffer);
if (vdpasim->iommu)
vhost_iotlb_free(vdpasim->iommu);
+diff --git a/drivers/vdpa/vdpa_user/iova_domain.c b/drivers/vdpa/vdpa_user/iova_domain.c
+index 1daae26088609..0678c25141973 100644
+--- a/drivers/vdpa/vdpa_user/iova_domain.c
++++ b/drivers/vdpa/vdpa_user/iova_domain.c
+@@ -302,7 +302,7 @@ vduse_domain_alloc_iova(struct iova_domain *iovad,
+ iova_len = roundup_pow_of_two(iova_len);
+ iova_pfn = alloc_iova_fast(iovad, iova_len, limit >> shift, true);
+
+- return iova_pfn << shift;
++ return (dma_addr_t)iova_pfn << shift;
+ }
+
+ static void vduse_domain_free_iova(struct iova_domain *iovad,
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 841667a896dd0..8c3de5a76282a 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -117882,11 +175798,446 @@ index 841667a896dd0..8c3de5a76282a 100644
config.length > dev->config_size - config.offset)
break;
+diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c
+index 5bcd00246d2e8..dead832b4571f 100644
+--- a/drivers/vdpa/virtio_pci/vp_vdpa.c
++++ b/drivers/vdpa/virtio_pci/vp_vdpa.c
+@@ -513,8 +513,8 @@ static void vp_vdpa_remove(struct pci_dev *pdev)
+ {
+ struct vp_vdpa *vp_vdpa = pci_get_drvdata(pdev);
+
+- vdpa_unregister_device(&vp_vdpa->vdpa);
+ vp_modern_remove(&vp_vdpa->mdev);
++ vdpa_unregister_device(&vp_vdpa->vdpa);
+ }
+
+ static struct pci_driver vp_vdpa_driver = {
+diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
+index a03b5a99c2dac..f3916e6b16b9d 100644
+--- a/drivers/vfio/pci/vfio_pci_core.c
++++ b/drivers/vfio/pci/vfio_pci_core.c
+@@ -36,6 +36,10 @@ static bool nointxmask;
+ static bool disable_vga;
+ static bool disable_idle_d3;
+
++/* List of PF's that vfio_pci_core_sriov_configure() has been called on */
++static DEFINE_MUTEX(vfio_pci_sriov_pfs_mutex);
++static LIST_HEAD(vfio_pci_sriov_pfs);
++
+ static inline bool vfio_vga_disabled(void)
+ {
+ #ifdef CONFIG_VFIO_PCI_VGA
+@@ -228,6 +232,19 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
+ if (!ret) {
+ /* D3 might be unsupported via quirk, skip unless in D3 */
+ if (needs_save && pdev->current_state >= PCI_D3hot) {
++ /*
++ * The current PCI state will be saved locally in
++ * 'pm_save' during the D3hot transition. When the
++ * device state is changed to D0 again with the current
++ * function, then pci_store_saved_state() will restore
++ * the state and will free the memory pointed by
++ * 'pm_save'. There are few cases where the PCI power
++ * state can be changed to D0 without the involvement
++ * of the driver. For these cases, free the earlier
++ * allocated memory first before overwriting 'pm_save'
++ * to prevent the memory leak.
++ */
++ kfree(vdev->pm_save);
+ vdev->pm_save = pci_store_saved_state(pdev);
+ } else if (needs_restore) {
+ pci_load_and_free_saved_state(pdev, &vdev->pm_save);
+@@ -322,6 +339,17 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
+ /* For needs_reset */
+ lockdep_assert_held(&vdev->vdev.dev_set->lock);
+
++ /*
++ * This function can be invoked while the power state is non-D0.
++ * This function calls __pci_reset_function_locked() which internally
++ * can use pci_pm_reset() for the function reset. pci_pm_reset() will
++ * fail if the power state is non-D0. Also, for the devices which
++ * have NoSoftRst-, the reset function can cause the PCI config space
++ * reset without restoring the original state (saved locally in
++ * 'vdev->pm_save').
++ */
++ vfio_pci_set_power_state(vdev, PCI_D0);
++
+ /* Stop the device from further DMA */
+ pci_clear_master(pdev);
+
+@@ -410,47 +438,17 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(vfio_pci_core_disable);
+
+-static struct vfio_pci_core_device *get_pf_vdev(struct vfio_pci_core_device *vdev)
+-{
+- struct pci_dev *physfn = pci_physfn(vdev->pdev);
+- struct vfio_device *pf_dev;
+-
+- if (!vdev->pdev->is_virtfn)
+- return NULL;
+-
+- pf_dev = vfio_device_get_from_dev(&physfn->dev);
+- if (!pf_dev)
+- return NULL;
+-
+- if (pci_dev_driver(physfn) != pci_dev_driver(vdev->pdev)) {
+- vfio_device_put(pf_dev);
+- return NULL;
+- }
+-
+- return container_of(pf_dev, struct vfio_pci_core_device, vdev);
+-}
+-
+-static void vfio_pci_vf_token_user_add(struct vfio_pci_core_device *vdev, int val)
+-{
+- struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
+-
+- if (!pf_vdev)
+- return;
+-
+- mutex_lock(&pf_vdev->vf_token->lock);
+- pf_vdev->vf_token->users += val;
+- WARN_ON(pf_vdev->vf_token->users < 0);
+- mutex_unlock(&pf_vdev->vf_token->lock);
+-
+- vfio_device_put(&pf_vdev->vdev);
+-}
+-
+ void vfio_pci_core_close_device(struct vfio_device *core_vdev)
+ {
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+
+- vfio_pci_vf_token_user_add(vdev, -1);
++ if (vdev->sriov_pf_core_dev) {
++ mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
++ WARN_ON(!vdev->sriov_pf_core_dev->vf_token->users);
++ vdev->sriov_pf_core_dev->vf_token->users--;
++ mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
++ }
+ vfio_spapr_pci_eeh_release(vdev->pdev);
+ vfio_pci_core_disable(vdev);
+
+@@ -471,7 +469,12 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
+ {
+ vfio_pci_probe_mmaps(vdev);
+ vfio_spapr_pci_eeh_open(vdev->pdev);
+- vfio_pci_vf_token_user_add(vdev, 1);
++
++ if (vdev->sriov_pf_core_dev) {
++ mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
++ vdev->sriov_pf_core_dev->vf_token->users++;
++ mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
++ }
+ }
+ EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable);
+
+@@ -921,6 +924,19 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
+ return -EINVAL;
+
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
++
++ /*
++ * This function can be invoked while the power state is non-D0.
++ * If pci_try_reset_function() has been called while the power
++ * state is non-D0, then pci_try_reset_function() will
++ * internally set the power state to D0 without vfio driver
++ * involvement. For the devices which have NoSoftRst-, the
++ * reset function can cause the PCI config space reset without
++ * restoring the original state (saved locally in
++ * 'vdev->pm_save').
++ */
++ vfio_pci_set_power_state(vdev, PCI_D0);
++
+ ret = pci_try_reset_function(vdev->pdev);
+ up_write(&vdev->memory_lock);
+
+@@ -1566,11 +1582,8 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
+ *
+ * If the VF token is provided but unused, an error is generated.
+ */
+- if (!vdev->pdev->is_virtfn && !vdev->vf_token && !vf_token)
+- return 0; /* No VF token provided or required */
+-
+ if (vdev->pdev->is_virtfn) {
+- struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
++ struct vfio_pci_core_device *pf_vdev = vdev->sriov_pf_core_dev;
+ bool match;
+
+ if (!pf_vdev) {
+@@ -1583,7 +1596,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
+ }
+
+ if (!vf_token) {
+- vfio_device_put(&pf_vdev->vdev);
+ pci_info_ratelimited(vdev->pdev,
+ "VF token required to access device\n");
+ return -EACCES;
+@@ -1593,8 +1605,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
+ match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
+ mutex_unlock(&pf_vdev->vf_token->lock);
+
+- vfio_device_put(&pf_vdev->vdev);
+-
+ if (!match) {
+ pci_info_ratelimited(vdev->pdev,
+ "Incorrect VF token provided for device\n");
+@@ -1715,8 +1725,30 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb,
+ static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
+ {
+ struct pci_dev *pdev = vdev->pdev;
++ struct vfio_pci_core_device *cur;
++ struct pci_dev *physfn;
+ int ret;
+
++ if (pdev->is_virtfn) {
++ /*
++ * If this VF was created by our vfio_pci_core_sriov_configure()
++ * then we can find the PF vfio_pci_core_device now, and due to
++ * the locking in pci_disable_sriov() it cannot change until
++ * this VF device driver is removed.
++ */
++ physfn = pci_physfn(vdev->pdev);
++ mutex_lock(&vfio_pci_sriov_pfs_mutex);
++ list_for_each_entry(cur, &vfio_pci_sriov_pfs, sriov_pfs_item) {
++ if (cur->pdev == physfn) {
++ vdev->sriov_pf_core_dev = cur;
++ break;
++ }
++ }
++ mutex_unlock(&vfio_pci_sriov_pfs_mutex);
++ return 0;
++ }
++
++ /* Not a SRIOV PF */
+ if (!pdev->is_physfn)
+ return 0;
+
+@@ -1788,6 +1820,7 @@ void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
+ INIT_LIST_HEAD(&vdev->ioeventfds_list);
+ mutex_init(&vdev->vma_lock);
+ INIT_LIST_HEAD(&vdev->vma_list);
++ INIT_LIST_HEAD(&vdev->sriov_pfs_item);
+ init_rwsem(&vdev->memory_lock);
+ }
+ EXPORT_SYMBOL_GPL(vfio_pci_core_init_device);
+@@ -1886,7 +1919,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
+ {
+ struct pci_dev *pdev = vdev->pdev;
+
+- pci_disable_sriov(pdev);
++ vfio_pci_core_sriov_configure(pdev, 0);
+
+ vfio_unregister_group_dev(&vdev->vdev);
+
+@@ -1926,21 +1959,49 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
+
+ int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
+ {
++ struct vfio_pci_core_device *vdev;
+ struct vfio_device *device;
+ int ret = 0;
+
++ device_lock_assert(&pdev->dev);
++
+ device = vfio_device_get_from_dev(&pdev->dev);
+ if (!device)
+ return -ENODEV;
+
+- if (nr_virtfn == 0)
+- pci_disable_sriov(pdev);
+- else
++ vdev = container_of(device, struct vfio_pci_core_device, vdev);
++
++ if (nr_virtfn) {
++ mutex_lock(&vfio_pci_sriov_pfs_mutex);
++ /*
++ * The thread that adds the vdev to the list is the only thread
++ * that gets to call pci_enable_sriov() and we will only allow
++ * it to be called once without going through
++ * pci_disable_sriov()
++ */
++ if (!list_empty(&vdev->sriov_pfs_item)) {
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++ list_add_tail(&vdev->sriov_pfs_item, &vfio_pci_sriov_pfs);
++ mutex_unlock(&vfio_pci_sriov_pfs_mutex);
+ ret = pci_enable_sriov(pdev, nr_virtfn);
++ if (ret)
++ goto out_del;
++ ret = nr_virtfn;
++ goto out_put;
++ }
+
+- vfio_device_put(device);
++ pci_disable_sriov(pdev);
+
+- return ret < 0 ? ret : nr_virtfn;
++out_del:
++ mutex_lock(&vfio_pci_sriov_pfs_mutex);
++ list_del_init(&vdev->sriov_pfs_item);
++out_unlock:
++ mutex_unlock(&vfio_pci_sriov_pfs_mutex);
++out_put:
++ vfio_device_put(device);
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(vfio_pci_core_sriov_configure);
+
+@@ -2064,6 +2125,18 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
+ }
+ cur_mem = NULL;
+
++ /*
++ * The pci_reset_bus() will reset all the devices in the bus.
++ * The power state can be non-D0 for some of the devices in the bus.
++ * For these devices, the pci_reset_bus() will internally set
++ * the power state to D0 without vfio driver involvement.
++ * For the devices which have NoSoftRst-, the reset function can
++ * cause the PCI config space reset without restoring the original
++ * state (saved locally in 'vdev->pm_save').
++ */
++ list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list)
++ vfio_pci_set_power_state(cur, PCI_D0);
++
+ ret = pci_reset_bus(pdev);
+
+ err_undo:
+@@ -2117,6 +2190,18 @@ static bool vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
+ if (!pdev)
+ return false;
+
++ /*
++ * The pci_reset_bus() will reset all the devices in the bus.
++ * The power state can be non-D0 for some of the devices in the bus.
++ * For these devices, the pci_reset_bus() will internally set
++ * the power state to D0 without vfio driver involvement.
++ * For the devices which have NoSoftRst-, the reset function can
++ * cause the PCI config space reset without restoring the original
++ * state (saved locally in 'vdev->pm_save').
++ */
++ list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list)
++ vfio_pci_set_power_state(cur, PCI_D0);
++
+ ret = pci_reset_bus(pdev);
+ if (ret)
+ return false;
+diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
+index 57d3b2cbbd8e5..82ac1569deb05 100644
+--- a/drivers/vfio/pci/vfio_pci_rdwr.c
++++ b/drivers/vfio/pci/vfio_pci_rdwr.c
+@@ -288,6 +288,7 @@ out:
+ return done;
+ }
+
++#ifdef CONFIG_VFIO_PCI_VGA
+ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+ {
+@@ -355,6 +356,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+
+ return done;
+ }
++#endif
+
+ static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
+ bool test_mem)
+diff --git a/drivers/vhost/iotlb.c b/drivers/vhost/iotlb.c
+index 670d56c879e50..5829cf2d0552d 100644
+--- a/drivers/vhost/iotlb.c
++++ b/drivers/vhost/iotlb.c
+@@ -57,6 +57,21 @@ int vhost_iotlb_add_range_ctx(struct vhost_iotlb *iotlb,
+ if (last < start)
+ return -EFAULT;
+
++ /* If the range being mapped is [0, ULONG_MAX], split it into two entries
++ * otherwise its size would overflow u64.
++ */
++ if (start == 0 && last == ULONG_MAX) {
++ u64 mid = last / 2;
++ int err = vhost_iotlb_add_range_ctx(iotlb, start, mid, addr,
++ perm, opaque);
++
++ if (err)
++ return err;
++
++ addr += mid + 1;
++ start = mid + 1;
++ }
++
+ if (iotlb->limit &&
+ iotlb->nmaps == iotlb->limit &&
+ iotlb->flags & VHOST_IOTLB_FLAG_RETIRE) {
+diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
+index 28ef323882fb2..297b5db474545 100644
+--- a/drivers/vhost/net.c
++++ b/drivers/vhost/net.c
+@@ -473,6 +473,7 @@ static void vhost_tx_batch(struct vhost_net *net,
+ goto signal_used;
+
+ msghdr->msg_control = &ctl;
++ msghdr->msg_controllen = sizeof(ctl);
+ err = sock->ops->sendmsg(sock, msghdr, 0);
+ if (unlikely(err < 0)) {
+ vq_err(&nvq->vq, "Fail to batch sending packets\n");
+@@ -1449,13 +1450,9 @@ err:
+ return ERR_PTR(r);
+ }
+
+-static struct ptr_ring *get_tap_ptr_ring(int fd)
++static struct ptr_ring *get_tap_ptr_ring(struct file *file)
+ {
+ struct ptr_ring *ring;
+- struct file *file = fget(fd);
+-
+- if (!file)
+- return NULL;
+ ring = tun_get_tx_ring(file);
+ if (!IS_ERR(ring))
+ goto out;
+@@ -1464,7 +1461,6 @@ static struct ptr_ring *get_tap_ptr_ring(int fd)
+ goto out;
+ ring = NULL;
+ out:
+- fput(file);
+ return ring;
+ }
+
+@@ -1551,8 +1547,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
+ r = vhost_net_enable_vq(n, vq);
+ if (r)
+ goto err_used;
+- if (index == VHOST_NET_VQ_RX)
+- nvq->rx_ring = get_tap_ptr_ring(fd);
++ if (index == VHOST_NET_VQ_RX) {
++ if (sock)
++ nvq->rx_ring = get_tap_ptr_ring(sock->file);
++ else
++ nvq->rx_ring = NULL;
++ }
+
+ oldubufs = nvq->ubufs;
+ nvq->ubufs = ubufs;
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
-index 39039e0461175..d62f05d056b7b 100644
+index 39039e0461175..299a995326185 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
-@@ -197,7 +197,7 @@ static int vhost_vdpa_config_validate(struct vhost_vdpa *v,
+@@ -97,8 +97,11 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid)
+ return;
+
+ irq = ops->get_vq_irq(vdpa, qid);
++ if (irq < 0)
++ return;
++
+ irq_bypass_unregister_producer(&vq->call_ctx.producer);
+- if (!vq->call_ctx.ctx || irq < 0)
++ if (!vq->call_ctx.ctx)
+ return;
+
+ vq->call_ctx.producer.token = vq->call_ctx.ctx;
+@@ -197,7 +200,7 @@ static int vhost_vdpa_config_validate(struct vhost_vdpa *v,
struct vdpa_device *vdpa = v->vdpa;
long size = vdpa->config->get_config_size(vdpa);
@@ -117895,8 +176246,26 @@ index 39039e0461175..d62f05d056b7b 100644
return -EINVAL;
if (c->len > size - c->off)
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index 59edb5a1ffe28..6942472cffb0f 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -1170,6 +1170,13 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
+ goto done;
+ }
+
++ if ((msg.type == VHOST_IOTLB_UPDATE ||
++ msg.type == VHOST_IOTLB_INVALIDATE) &&
++ msg.size == 0) {
++ ret = -EINVAL;
++ goto done;
++ }
++
+ if (dev->msg_handler)
+ ret = dev->msg_handler(dev, &msg);
+ else
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
-index 938aefbc75ecc..d07a20bbc07b7 100644
+index 938aefbc75ecc..dcb1585819a1d 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -554,7 +554,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
@@ -117932,9 +176301,13 @@ index 938aefbc75ecc..d07a20bbc07b7 100644
for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
struct vhost_virtqueue *vq = &vsock->vqs[i];
-@@ -757,7 +759,12 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
+@@ -755,9 +757,15 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
+
+ /* Iterating over all connections for all CIDs to find orphans is
* inefficient. Room for improvement here. */
- vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
+- vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
++ vsock_for_each_connected_socket(&vhost_transport.transport,
++ vhost_vsock_reset_orphans);
- vhost_vsock_stop(vsock);
+ /* Don't check the owner, because we are in the release path, so we
@@ -117946,7 +176319,7 @@ index 938aefbc75ecc..d07a20bbc07b7 100644
vhost_vsock_flush(vsock);
vhost_dev_stop(&vsock->dev);
-@@ -872,7 +879,7 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
+@@ -872,7 +880,7 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
if (start)
return vhost_vsock_start(vsock);
else
@@ -118318,6 +176691,62 @@ index ef9c57ce09066..9a49ea6b5112f 100644
c->vc_complement_mask = 0x7700;
if (vga_512_chars)
c->vc_hi_font_mask = 0x0800;
+diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
+index e3812a8ff55a4..29e650ecfceb1 100644
+--- a/drivers/video/fbdev/atafb.c
++++ b/drivers/video/fbdev/atafb.c
+@@ -1683,9 +1683,9 @@ static int falcon_setcolreg(unsigned int regno, unsigned int red,
+ ((blue & 0xfc00) >> 8));
+ if (regno < 16) {
+ shifter_tt.color_reg[regno] =
+- (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
+- (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
+- ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
++ ((((red & 0xe000) >> 13) | ((red & 0x1000) >> 12)) << 8) |
++ ((((green & 0xe000) >> 13) | ((green & 0x1000) >> 12)) << 4) |
++ ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11));
+@@ -1971,9 +1971,9 @@ static int stste_setcolreg(unsigned int regno, unsigned int red,
+ green >>= 12;
+ if (ATARIHW_PRESENT(EXTD_SHIFTER))
+ shifter_tt.color_reg[regno] =
+- (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
+- (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
+- ((blue & 0xe) >> 1) | ((blue & 1) << 3);
++ ((((red & 0xe) >> 1) | ((red & 1) << 3)) << 8) |
++ ((((green & 0xe) >> 1) | ((green & 1) << 3)) << 4) |
++ ((blue & 0xe) >> 1) | ((blue & 1) << 3);
+ else
+ shifter_tt.color_reg[regno] =
+ ((red & 0xe) << 7) |
+diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c
+index 355b6120dc4f0..1fc8de4ecbebf 100644
+--- a/drivers/video/fbdev/atmel_lcdfb.c
++++ b/drivers/video/fbdev/atmel_lcdfb.c
+@@ -1062,15 +1062,16 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+
+ INIT_LIST_HEAD(&info->modelist);
+
+- if (pdev->dev.of_node) {
+- ret = atmel_lcdfb_of_init(sinfo);
+- if (ret)
+- goto free_info;
+- } else {
++ if (!pdev->dev.of_node) {
+ dev_err(dev, "cannot get default configuration\n");
+ goto free_info;
+ }
+
++ ret = atmel_lcdfb_of_init(sinfo);
++ if (ret)
++ goto free_info;
++
++ ret = -ENODEV;
+ if (!sinfo->config)
+ goto free_info;
+
diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c
index 998067b701fa0..393894af26f84 100644
--- a/drivers/video/fbdev/chipsfb.c
@@ -118331,6 +176760,62 @@ index 998067b701fa0..393894af26f84 100644
p->fix = chipsfb_fix;
p->fix.smem_start = addr;
+diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c
+index 93802abbbc72a..3d47c347b8970 100644
+--- a/drivers/video/fbdev/cirrusfb.c
++++ b/drivers/video/fbdev/cirrusfb.c
+@@ -469,7 +469,7 @@ static int cirrusfb_check_mclk(struct fb_info *info, long freq)
+ return 0;
+ }
+
+-static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
++static int cirrusfb_check_pixclock(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+ {
+ long freq;
+@@ -478,9 +478,7 @@ static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
+ unsigned maxclockidx = var->bits_per_pixel >> 3;
+
+ /* convert from ps to kHz */
+- freq = PICOS2KHZ(var->pixclock);
+-
+- dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
++ freq = PICOS2KHZ(var->pixclock ? : 1);
+
+ maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
+ cinfo->multiplexing = 0;
+@@ -488,11 +486,13 @@ static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
+ /* If the frequency is greater than we can support, we might be able
+ * to use multiplexing for the video mode */
+ if (freq > maxclock) {
+- dev_err(info->device,
+- "Frequency greater than maxclock (%ld kHz)\n",
+- maxclock);
+- return -EINVAL;
++ var->pixclock = KHZ2PICOS(maxclock);
++
++ while ((freq = PICOS2KHZ(var->pixclock)) > maxclock)
++ var->pixclock++;
+ }
++ dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
++
+ /*
+ * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
+ * pixel clock
+diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c
+index 509311471d515..bd59e7b11ed53 100644
+--- a/drivers/video/fbdev/controlfb.c
++++ b/drivers/video/fbdev/controlfb.c
+@@ -67,7 +67,9 @@
+ #define out_8(addr, val) (void)(val)
+ #define in_le32(addr) 0
+ #define out_le32(addr, val) (void)(val)
++#ifndef pgprot_cached_wthru
+ #define pgprot_cached_wthru(prot) (prot)
++#endif
+ #else
+ static void invalid_vram_cache(void __force *addr)
+ {
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 22bb3892f6bd1..a53c1f6906f09 100644
--- a/drivers/video/fbdev/core/fbcon.c
@@ -118650,11 +177135,143 @@ index 8d5e66b1bdfbb..23bc045769d08 100644
int err;
xoffset = vxres - info->var.xres - ops->var.xoffset;
+diff --git a/drivers/video/fbdev/core/fbcvt.c b/drivers/video/fbdev/core/fbcvt.c
+index 55d2bd0ce5c02..64843464c6613 100644
+--- a/drivers/video/fbdev/core/fbcvt.c
++++ b/drivers/video/fbdev/core/fbcvt.c
+@@ -214,9 +214,11 @@ static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
+ static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+ {
+ u32 pixcount, pixcount_mod;
+- int cnt = 255, offset = 0, read = 0;
+- u8 *buf = kzalloc(256, GFP_KERNEL);
++ int size = 256;
++ int off = 0;
++ u8 *buf;
+
++ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return;
+
+@@ -224,43 +226,30 @@ static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+ pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
+ pixcount_mod /= 1000;
+
+- read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
+- cvt->xres, cvt->yres, cvt->refresh);
+- offset += read;
+- cnt -= read;
++ off += scnprintf(buf + off, size - off, "fbcvt: %dx%d@%d: CVT Name - ",
++ cvt->xres, cvt->yres, cvt->refresh);
+
+- if (cvt->status)
+- snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
+- "Pixel Image\n", pixcount, pixcount_mod);
+- else {
+- if (pixcount) {
+- read = snprintf(buf+offset, cnt, "%d", pixcount);
+- cnt -= read;
+- offset += read;
+- }
++ if (cvt->status) {
++ off += scnprintf(buf + off, size - off,
++ "Not a CVT standard - %d.%03d Mega Pixel Image\n",
++ pixcount, pixcount_mod);
++ } else {
++ if (pixcount)
++ off += scnprintf(buf + off, size - off, "%d", pixcount);
+
+- read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
+- cnt -= read;
+- offset += read;
++ off += scnprintf(buf + off, size - off, ".%03dM", pixcount_mod);
+
+ if (cvt->aspect_ratio == 0)
+- read = snprintf(buf+offset, cnt, "3");
++ off += scnprintf(buf + off, size - off, "3");
+ else if (cvt->aspect_ratio == 3)
+- read = snprintf(buf+offset, cnt, "4");
++ off += scnprintf(buf + off, size - off, "4");
+ else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
+- read = snprintf(buf+offset, cnt, "9");
++ off += scnprintf(buf + off, size - off, "9");
+ else if (cvt->aspect_ratio == 2)
+- read = snprintf(buf+offset, cnt, "A");
+- else
+- read = 0;
+- cnt -= read;
+- offset += read;
+-
+- if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+- read = snprintf(buf+offset, cnt, "-R");
+- cnt -= read;
+- offset += read;
+- }
++ off += scnprintf(buf + off, size - off, "A");
++
++ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
++ off += scnprintf(buf + off, size - off, "-R");
+ }
+
+ printk(KERN_INFO "%s\n", buf);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
-index 7420d2c16e47e..7bd5e2a4a9da5 100644
+index 7420d2c16e47e..0371ad233fdf2 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
-@@ -1759,6 +1759,53 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
+@@ -25,6 +25,7 @@
+ #include <linux/init.h>
+ #include <linux/linux_logo.h>
+ #include <linux/proc_fs.h>
++#include <linux/platform_device.h>
+ #include <linux/seq_file.h>
+ #include <linux/console.h>
+ #include <linux/kmod.h>
+@@ -1557,18 +1558,43 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
+ /* check all firmware fbs and kick off if the base addr overlaps */
+ for_each_registered_fb(i) {
+ struct apertures_struct *gen_aper;
++ struct device *device;
+
+ if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
+ continue;
+
+ gen_aper = registered_fb[i]->apertures;
++ device = registered_fb[i]->device;
+ if (fb_do_apertures_overlap(gen_aper, a) ||
+ (primary && gen_aper && gen_aper->count &&
+ gen_aper->ranges[0].base == VGA_FB_PHYS)) {
+
+ printk(KERN_INFO "fb%d: switching to %s from %s\n",
+ i, name, registered_fb[i]->fix.id);
+- do_unregister_framebuffer(registered_fb[i]);
++
++ /*
++ * If we kick-out a firmware driver, we also want to remove
++ * the underlying platform device, such as simple-framebuffer,
++ * VESA, EFI, etc. A native driver will then be able to
++ * allocate the memory range.
++ *
++ * If it's not a platform device, at least print a warning. A
++ * fix would add code to remove the device from the system.
++ */
++ if (!device) {
++ /* TODO: Represent each OF framebuffer as its own
++ * device in the device hierarchy. For now, offb
++ * doesn't have such a device, so unregister the
++ * framebuffer as before without warning.
++ */
++ do_unregister_framebuffer(registered_fb[i]);
++ } else if (dev_is_platform(device)) {
++ registered_fb[i]->forced_out = true;
++ platform_device_unregister(to_platform_device(device));
++ } else {
++ pr_warn("fb%d: cannot remove device\n", i);
++ do_unregister_framebuffer(registered_fb[i]);
++ }
+ }
+ }
+ }
+@@ -1759,6 +1785,53 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);
@@ -118708,8 +177325,39 @@ index 7420d2c16e47e..7bd5e2a4a9da5 100644
/**
* remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
* @pdev: PCI device
+@@ -1848,9 +1921,13 @@ EXPORT_SYMBOL(register_framebuffer);
+ void
+ unregister_framebuffer(struct fb_info *fb_info)
+ {
+- mutex_lock(&registration_lock);
++ bool forced_out = fb_info->forced_out;
++
++ if (!forced_out)
++ mutex_lock(&registration_lock);
+ do_unregister_framebuffer(fb_info);
+- mutex_unlock(&registration_lock);
++ if (!forced_out)
++ mutex_unlock(&registration_lock);
+ }
+ EXPORT_SYMBOL(unregister_framebuffer);
+
+diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
+index 65dae05fff8e6..ce699396d6bad 100644
+--- a/drivers/video/fbdev/core/fbsysfs.c
++++ b/drivers/video/fbdev/core/fbsysfs.c
+@@ -80,6 +80,10 @@ void framebuffer_release(struct fb_info *info)
+ {
+ if (!info)
+ return;
++
++ if (WARN_ON(refcount_read(&info->count)))
++ return;
++
+ kfree(info->apertures);
+ kfree(info);
+ }
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
-index 8ea8f079cde26..ea42ba6445b2d 100644
+index 8ea8f079cde26..b3d5f884c5445 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -47,6 +47,8 @@ static bool use_bgrt = true;
@@ -118721,8 +177369,14 @@ index 8ea8f079cde26..ea42ba6445b2d 100644
static struct fb_var_screeninfo efifb_defined = {
.activate = FB_ACTIVATE_NOW,
.height = -1,
-@@ -243,6 +245,9 @@ static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+@@ -241,18 +243,28 @@ error:
+ static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+ #endif
++/*
++ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
++ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
++ */
static void efifb_destroy(struct fb_info *info)
{
+ if (efifb_pci_dev)
@@ -118731,7 +177385,20 @@ index 8ea8f079cde26..ea42ba6445b2d 100644
if (info->screen_base) {
if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
iounmap(info->screen_base);
-@@ -333,7 +338,6 @@ ATTRIBUTE_GROUPS(efifb);
+ else
+ memunmap(info->screen_base);
+ }
++
+ if (request_mem_succeeded)
+ release_mem_region(info->apertures->ranges[0].base,
+ info->apertures->ranges[0].size);
+ fb_dealloc_cmap(&info->cmap);
++
++ framebuffer_release(info);
+ }
+
+ static const struct fb_ops efifb_ops = {
+@@ -333,7 +345,6 @@ ATTRIBUTE_GROUPS(efifb);
static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
@@ -118739,7 +177406,7 @@ index 8ea8f079cde26..ea42ba6445b2d 100644
static struct resource *bar_resource;
static u64 bar_offset;
-@@ -347,6 +351,17 @@ static int efifb_probe(struct platform_device *dev)
+@@ -347,6 +358,17 @@ static int efifb_probe(struct platform_device *dev)
char *option = NULL;
efi_memory_desc_t md;
@@ -118757,7 +177424,7 @@ index 8ea8f079cde26..ea42ba6445b2d 100644
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
-@@ -569,17 +584,22 @@ static int efifb_probe(struct platform_device *dev)
+@@ -569,17 +591,22 @@ static int efifb_probe(struct platform_device *dev)
pr_err("efifb: cannot allocate colormap\n");
goto err_groups;
}
@@ -118784,10 +177451,14 @@ index 8ea8f079cde26..ea42ba6445b2d 100644
fb_dealloc_cmap(&info->cmap);
err_groups:
sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
-@@ -603,8 +623,6 @@ static int efifb_remove(struct platform_device *pdev)
+@@ -600,11 +627,9 @@ static int efifb_remove(struct platform_device *pdev)
+ {
+ struct fb_info *info = platform_get_drvdata(pdev);
+
++ /* efifb_destroy takes care of info cleanup */
unregister_framebuffer(info);
sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
- framebuffer_release(info);
+- framebuffer_release(info);
- if (efifb_pci_dev)
- pm_runtime_put(&efifb_pci_dev->dev);
@@ -118848,11 +177519,143 @@ index 23999df527393..c8e0ea27caf1d 100644
ret = hvfb_getmem(hdev, info);
if (ret) {
+diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
+index 5c82611e93d99..236521b19daf7 100644
+--- a/drivers/video/fbdev/matrox/matroxfb_base.c
++++ b/drivers/video/fbdev/matrox/matroxfb_base.c
+@@ -1377,7 +1377,7 @@ static struct video_board vbG200 = {
+ .lowlevel = &matrox_G100
+ };
+ static struct video_board vbG200eW = {
+- .maxvram = 0x800000,
++ .maxvram = 0x100000,
+ .maxdisplayable = 0x800000,
+ .accelID = FB_ACCEL_MATROX_MGAG200,
+ .lowlevel = &matrox_G100
+diff --git a/drivers/video/fbdev/nvidia/nv_i2c.c b/drivers/video/fbdev/nvidia/nv_i2c.c
+index d7994a1732459..0b48965a6420c 100644
+--- a/drivers/video/fbdev/nvidia/nv_i2c.c
++++ b/drivers/video/fbdev/nvidia/nv_i2c.c
+@@ -86,7 +86,7 @@ static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
+ {
+ int rc;
+
+- strcpy(chan->adapter.name, name);
++ strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.class = i2c_class;
+ chan->adapter.algo_data = &chan->algo;
+diff --git a/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c
+index 2fa436475b406..c8ad3ef42bd31 100644
+--- a/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c
++++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c
+@@ -246,6 +246,7 @@ static int dvic_probe_of(struct platform_device *pdev)
+ adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
+ if (adapter_node) {
+ adapter = of_get_i2c_adapter_by_node(adapter_node);
++ of_node_put(adapter_node);
+ if (adapter == NULL) {
+ dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
+ omap_dss_put_device(ddata->in);
+diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+index 4b0793abdd84b..a2c7c5cb15234 100644
+--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
++++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+@@ -409,7 +409,7 @@ static ssize_t dsicm_num_errors_show(struct device *dev,
+ if (r)
+ return r;
+
+- return snprintf(buf, PAGE_SIZE, "%d\n", errors);
++ return sysfs_emit(buf, "%d\n", errors);
+ }
+
+ static ssize_t dsicm_hw_revision_show(struct device *dev,
+@@ -439,7 +439,7 @@ static ssize_t dsicm_hw_revision_show(struct device *dev,
+ if (r)
+ return r;
+
+- return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
++ return sysfs_emit(buf, "%02x.%02x.%02x\n", id1, id2, id3);
+ }
+
+ static ssize_t dsicm_store_ulps(struct device *dev,
+@@ -487,7 +487,7 @@ static ssize_t dsicm_show_ulps(struct device *dev,
+ t = ddata->ulps_enabled;
+ mutex_unlock(&ddata->lock);
+
+- return snprintf(buf, PAGE_SIZE, "%u\n", t);
++ return sysfs_emit(buf, "%u\n", t);
+ }
+
+ static ssize_t dsicm_store_ulps_timeout(struct device *dev,
+@@ -532,7 +532,7 @@ static ssize_t dsicm_show_ulps_timeout(struct device *dev,
+ t = ddata->ulps_timeout;
+ mutex_unlock(&ddata->lock);
+
+- return snprintf(buf, PAGE_SIZE, "%u\n", t);
++ return sysfs_emit(buf, "%u\n", t);
+ }
+
+ static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
+diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c
+index 8d8b5ff7d43c8..3696eb09b69b4 100644
+--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c
++++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c
+@@ -476,7 +476,7 @@ static ssize_t show_cabc_available_modes(struct device *dev,
+ int i;
+
+ if (!ddata->has_cabc)
+- return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
++ return sysfs_emit(buf, "%s\n", cabc_modes[0]);
+
+ for (i = 0, len = 0;
+ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
+diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c
+index afac1d9445aa2..57b7d1f490962 100644
+--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c
++++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c
+@@ -169,7 +169,7 @@ static ssize_t tpo_td043_vmirror_show(struct device *dev,
+ {
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
+
+- return snprintf(buf, PAGE_SIZE, "%d\n", ddata->vmirror);
++ return sysfs_emit(buf, "%d\n", ddata->vmirror);
+ }
+
+ static ssize_t tpo_td043_vmirror_store(struct device *dev,
+@@ -199,7 +199,7 @@ static ssize_t tpo_td043_mode_show(struct device *dev,
+ {
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
+
+- return snprintf(buf, PAGE_SIZE, "%d\n", ddata->mode);
++ return sysfs_emit(buf, "%d\n", ddata->mode);
+ }
+
+ static ssize_t tpo_td043_mode_store(struct device *dev,
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
-index 62f0ded706815..b63074fd892e5 100644
+index 62f0ded706815..a2e3a46900252 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
-@@ -407,6 +407,17 @@ static int simplefb_probe(struct platform_device *pdev)
+@@ -70,12 +70,18 @@ struct simplefb_par;
+ static void simplefb_clocks_destroy(struct simplefb_par *par);
+ static void simplefb_regulators_destroy(struct simplefb_par *par);
+
++/*
++ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
++ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
++ */
+ static void simplefb_destroy(struct fb_info *info)
+ {
+ simplefb_regulators_destroy(info->par);
+ simplefb_clocks_destroy(info->par);
+ if (info->screen_base)
+ iounmap(info->screen_base);
++
++ framebuffer_release(info);
+ }
+
+ static const struct fb_ops simplefb_ops = {
+@@ -407,6 +413,17 @@ static int simplefb_probe(struct platform_device *pdev)
struct simplefb_par *par;
struct resource *mem;
@@ -118870,6 +177673,239 @@ index 62f0ded706815..b63074fd892e5 100644
if (fb_get_options("simplefb", NULL))
return -ENODEV;
+@@ -509,8 +526,8 @@ static int simplefb_remove(struct platform_device *pdev)
+ {
+ struct fb_info *info = platform_get_drvdata(pdev);
+
++ /* simplefb_destroy takes care of info cleanup */
+ unregister_framebuffer(info);
+- framebuffer_release(info);
+
+ return 0;
+ }
+diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c
+index 0dbc6bf8268ac..092a1caa1208e 100644
+--- a/drivers/video/fbdev/sm712fb.c
++++ b/drivers/video/fbdev/sm712fb.c
+@@ -1047,7 +1047,7 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
+ if (count + p > total_size)
+ count = total_size - p;
+
+- buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
++ buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+@@ -1059,25 +1059,14 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
+ while (count) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ dst = buffer;
+- for (i = c >> 2; i--;) {
+- *dst = fb_readl(src++);
+- *dst = big_swap(*dst);
++ for (i = (c + 3) >> 2; i--;) {
++ u32 val;
++
++ val = fb_readl(src);
++ *dst = big_swap(val);
++ src++;
+ dst++;
+ }
+- if (c & 3) {
+- u8 *dst8 = (u8 *)dst;
+- u8 __iomem *src8 = (u8 __iomem *)src;
+-
+- for (i = c & 3; i--;) {
+- if (i & 1) {
+- *dst8++ = fb_readb(++src8);
+- } else {
+- *dst8++ = fb_readb(--src8);
+- src8 += 2;
+- }
+- }
+- src = (u32 __iomem *)src8;
+- }
+
+ if (copy_to_user(buf, buffer, c)) {
+ err = -EFAULT;
+@@ -1130,7 +1119,7 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
+ count = total_size - p;
+ }
+
+- buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
++ buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+@@ -1148,24 +1137,11 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
+ break;
+ }
+
+- for (i = c >> 2; i--;) {
+- fb_writel(big_swap(*src), dst++);
++ for (i = (c + 3) >> 2; i--;) {
++ fb_writel(big_swap(*src), dst);
++ dst++;
+ src++;
+ }
+- if (c & 3) {
+- u8 *src8 = (u8 *)src;
+- u8 __iomem *dst8 = (u8 __iomem *)dst;
+-
+- for (i = c & 3; i--;) {
+- if (i & 1) {
+- fb_writeb(*src8++, ++dst8);
+- } else {
+- fb_writeb(*src8++, --dst8);
+- dst8 += 2;
+- }
+- }
+- dst = (u32 __iomem *)dst8;
+- }
+
+ *ppos += c;
+ buf += c;
+diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
+index bfac3ee4a6422..28768c272b73d 100644
+--- a/drivers/video/fbdev/smscufx.c
++++ b/drivers/video/fbdev/smscufx.c
+@@ -1656,6 +1656,7 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ info->par = dev;
+ info->pseudo_palette = dev->pseudo_palette;
+ info->fbops = &ufx_ops;
++ INIT_LIST_HEAD(&info->modelist);
+
+ retval = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (retval < 0) {
+@@ -1666,8 +1667,6 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+ ufx_free_framebuffer_work);
+
+- INIT_LIST_HEAD(&info->modelist);
+-
+ retval = ufx_reg_read(dev, 0x3000, &id_rev);
+ check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
+ dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
+diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
+index b9cdd02c10009..d9eec1b60e665 100644
+--- a/drivers/video/fbdev/udlfb.c
++++ b/drivers/video/fbdev/udlfb.c
+@@ -1426,7 +1426,7 @@ static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dlfb = fb_info->par;
+- return snprintf(buf, PAGE_SIZE, "%u\n",
++ return sysfs_emit(buf, "%u\n",
+ atomic_read(&dlfb->bytes_rendered));
+ }
+
+@@ -1434,7 +1434,7 @@ static ssize_t metrics_bytes_identical_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dlfb = fb_info->par;
+- return snprintf(buf, PAGE_SIZE, "%u\n",
++ return sysfs_emit(buf, "%u\n",
+ atomic_read(&dlfb->bytes_identical));
+ }
+
+@@ -1442,7 +1442,7 @@ static ssize_t metrics_bytes_sent_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dlfb = fb_info->par;
+- return snprintf(buf, PAGE_SIZE, "%u\n",
++ return sysfs_emit(buf, "%u\n",
+ atomic_read(&dlfb->bytes_sent));
+ }
+
+@@ -1450,7 +1450,7 @@ static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dlfb = fb_info->par;
+- return snprintf(buf, PAGE_SIZE, "%u\n",
++ return sysfs_emit(buf, "%u\n",
+ atomic_read(&dlfb->cpu_kcycles_used));
+ }
+
+@@ -1649,8 +1649,9 @@ static int dlfb_usb_probe(struct usb_interface *intf,
+ const struct device_attribute *attr;
+ struct dlfb_data *dlfb;
+ struct fb_info *info;
+- int retval = -ENOMEM;
++ int retval;
+ struct usb_device *usbdev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *out;
+
+ /* usb initialization */
+ dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL);
+@@ -1664,6 +1665,12 @@ static int dlfb_usb_probe(struct usb_interface *intf,
+ dlfb->udev = usb_get_dev(usbdev);
+ usb_set_intfdata(intf, dlfb);
+
++ retval = usb_find_common_endpoints(intf->cur_altsetting, NULL, &out, NULL, NULL);
++ if (retval) {
++ dev_err(&intf->dev, "Device should have at lease 1 bulk endpoint!\n");
++ goto error;
++ }
++
+ dev_dbg(&intf->dev, "console enable=%d\n", console);
+ dev_dbg(&intf->dev, "fb_defio enable=%d\n", fb_defio);
+ dev_dbg(&intf->dev, "shadow enable=%d\n", shadow);
+@@ -1673,6 +1680,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
+ if (!dlfb_parse_vendor_descriptor(dlfb, intf)) {
+ dev_err(&intf->dev,
+ "firmware not recognized, incompatible device?\n");
++ retval = -ENODEV;
+ goto error;
+ }
+
+@@ -1686,8 +1694,10 @@ static int dlfb_usb_probe(struct usb_interface *intf,
+
+ /* allocates framebuffer driver structure, not framebuffer memory */
+ info = framebuffer_alloc(0, &dlfb->udev->dev);
+- if (!info)
++ if (!info) {
++ retval = -ENOMEM;
+ goto error;
++ }
+
+ dlfb->info = info;
+ info->par = dlfb;
+diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
+index df6de5a9dd4cd..e25e8de5ff672 100644
+--- a/drivers/video/fbdev/vesafb.c
++++ b/drivers/video/fbdev/vesafb.c
+@@ -179,6 +179,10 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ return err;
+ }
+
++/*
++ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
++ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
++ */
+ static void vesafb_destroy(struct fb_info *info)
+ {
+ struct vesafb_par *par = info->par;
+@@ -188,6 +192,8 @@ static void vesafb_destroy(struct fb_info *info)
+ if (info->screen_base)
+ iounmap(info->screen_base);
+ release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
++
++ framebuffer_release(info);
+ }
+
+ static struct fb_ops vesafb_ops = {
+@@ -484,10 +490,10 @@ static int vesafb_remove(struct platform_device *pdev)
+ {
+ struct fb_info *info = platform_get_drvdata(pdev);
+
++ /* vesafb_destroy takes care of info cleanup */
+ unregister_framebuffer(info);
+ if (((struct vesafb_par *)(info->par))->region)
+ release_region(0x3c0, 32);
+- framebuffer_release(info);
+
+ return 0;
+ }
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
index e2757ff1c23d2..96e312a3eac75 100644
--- a/drivers/video/fbdev/vga16fb.c
@@ -118912,6 +177948,133 @@ index e2757ff1c23d2..96e312a3eac75 100644
ret = platform_driver_register(&vga16fb_driver);
if (!ret) {
+diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c
+index d96ab28f8ce4a..4e641a780726e 100644
+--- a/drivers/video/fbdev/w100fb.c
++++ b/drivers/video/fbdev/w100fb.c
+@@ -770,12 +770,18 @@ out:
+ fb_dealloc_cmap(&info->cmap);
+ kfree(info->pseudo_palette);
+ }
+- if (remapped_fbuf != NULL)
++ if (remapped_fbuf != NULL) {
+ iounmap(remapped_fbuf);
+- if (remapped_regs != NULL)
++ remapped_fbuf = NULL;
++ }
++ if (remapped_regs != NULL) {
+ iounmap(remapped_regs);
+- if (remapped_base != NULL)
++ remapped_regs = NULL;
++ }
++ if (remapped_base != NULL) {
+ iounmap(remapped_base);
++ remapped_base = NULL;
++ }
+ if (info)
+ framebuffer_release(info);
+ return err;
+@@ -795,8 +801,11 @@ static int w100fb_remove(struct platform_device *pdev)
+ fb_dealloc_cmap(&info->cmap);
+
+ iounmap(remapped_base);
++ remapped_base = NULL;
+ iounmap(remapped_regs);
++ remapped_regs = NULL;
+ iounmap(remapped_fbuf);
++ remapped_fbuf = NULL;
+
+ framebuffer_release(info);
+
+diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
+index 130e12b8652a6..af889cee66805 100644
+--- a/drivers/virt/acrn/hsm.c
++++ b/drivers/virt/acrn/hsm.c
+@@ -134,8 +134,10 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
+ if (IS_ERR(vm_param))
+ return PTR_ERR(vm_param);
+
+- if ((vm_param->reserved0 | vm_param->reserved1) != 0)
++ if ((vm_param->reserved0 | vm_param->reserved1) != 0) {
++ kfree(vm_param);
+ return -EINVAL;
++ }
+
+ vm = acrn_vm_create(vm, vm_param);
+ if (!vm) {
+@@ -180,21 +182,29 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
+ return PTR_ERR(cpu_regs);
+
+ for (i = 0; i < ARRAY_SIZE(cpu_regs->reserved); i++)
+- if (cpu_regs->reserved[i])
++ if (cpu_regs->reserved[i]) {
++ kfree(cpu_regs);
+ return -EINVAL;
++ }
+
+ for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.reserved_32); i++)
+- if (cpu_regs->vcpu_regs.reserved_32[i])
++ if (cpu_regs->vcpu_regs.reserved_32[i]) {
++ kfree(cpu_regs);
+ return -EINVAL;
++ }
+
+ for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.reserved_64); i++)
+- if (cpu_regs->vcpu_regs.reserved_64[i])
++ if (cpu_regs->vcpu_regs.reserved_64[i]) {
++ kfree(cpu_regs);
+ return -EINVAL;
++ }
+
+ for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.gdt.reserved); i++)
+ if (cpu_regs->vcpu_regs.gdt.reserved[i] |
+- cpu_regs->vcpu_regs.idt.reserved[i])
++ cpu_regs->vcpu_regs.idt.reserved[i]) {
++ kfree(cpu_regs);
+ return -EINVAL;
++ }
+
+ ret = hcall_set_vcpu_regs(vm->vmid, virt_to_phys(cpu_regs));
+ if (ret < 0)
+diff --git a/drivers/virt/acrn/mm.c b/drivers/virt/acrn/mm.c
+index c4f2e15c8a2ba..3b1b1e7a844b4 100644
+--- a/drivers/virt/acrn/mm.c
++++ b/drivers/virt/acrn/mm.c
+@@ -162,10 +162,34 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+ void *remap_vaddr;
+ int ret, pinned;
+ u64 user_vm_pa;
++ unsigned long pfn;
++ struct vm_area_struct *vma;
+
+ if (!vm || !memmap)
+ return -EINVAL;
+
++ mmap_read_lock(current->mm);
++ vma = vma_lookup(current->mm, memmap->vma_base);
++ if (vma && ((vma->vm_flags & VM_PFNMAP) != 0)) {
++ if ((memmap->vma_base + memmap->len) > vma->vm_end) {
++ mmap_read_unlock(current->mm);
++ return -EINVAL;
++ }
++
++ ret = follow_pfn(vma, memmap->vma_base, &pfn);
++ mmap_read_unlock(current->mm);
++ if (ret < 0) {
++ dev_dbg(acrn_dev.this_device,
++ "Failed to lookup PFN at VMA:%pK.\n", (void *)memmap->vma_base);
++ return ret;
++ }
++
++ return acrn_mm_region_add(vm, memmap->user_vm_pa,
++ PFN_PHYS(pfn), memmap->len,
++ ACRN_MEM_TYPE_WB, memmap->attr);
++ }
++ mmap_read_unlock(current->mm);
++
+ /* Get the page number of the map region */
+ nr_pages = memmap->len >> PAGE_SHIFT;
+ pages = vzalloc(nr_pages * sizeof(struct page *));
diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c
index e21e1e86ad15f..fe7a8e4034097 100644
--- a/drivers/virt/nitro_enclaves/ne_misc_dev.c
@@ -118928,6 +178091,95 @@ index e21e1e86ad15f..fe7a8e4034097 100644
if (gup_rc < 0) {
rc = gup_rc;
+diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
+index 236081afe9a2a..c2b733ef95b0d 100644
+--- a/drivers/virtio/virtio.c
++++ b/drivers/virtio/virtio.c
+@@ -166,14 +166,13 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status)
+ }
+ EXPORT_SYMBOL_GPL(virtio_add_status);
+
+-int virtio_finalize_features(struct virtio_device *dev)
++/* Do some validation, then set FEATURES_OK */
++static int virtio_features_ok(struct virtio_device *dev)
+ {
+- int ret = dev->config->finalize_features(dev);
+ unsigned status;
++ int ret;
+
+ might_sleep();
+- if (ret)
+- return ret;
+
+ ret = arch_has_restricted_virtio_memory_access();
+ if (ret) {
+@@ -202,7 +201,6 @@ int virtio_finalize_features(struct virtio_device *dev)
+ }
+ return 0;
+ }
+-EXPORT_SYMBOL_GPL(virtio_finalize_features);
+
+ static int virtio_dev_probe(struct device *_d)
+ {
+@@ -239,17 +237,6 @@ static int virtio_dev_probe(struct device *_d)
+ driver_features_legacy = driver_features;
+ }
+
+- /*
+- * Some devices detect legacy solely via F_VERSION_1. Write
+- * F_VERSION_1 to force LE config space accesses before FEATURES_OK for
+- * these when needed.
+- */
+- if (drv->validate && !virtio_legacy_is_little_endian()
+- && device_features & BIT_ULL(VIRTIO_F_VERSION_1)) {
+- dev->features = BIT_ULL(VIRTIO_F_VERSION_1);
+- dev->config->finalize_features(dev);
+- }
+-
+ if (device_features & (1ULL << VIRTIO_F_VERSION_1))
+ dev->features = driver_features & device_features;
+ else
+@@ -260,13 +247,26 @@ static int virtio_dev_probe(struct device *_d)
+ if (device_features & (1ULL << i))
+ __virtio_set_bit(dev, i);
+
++ err = dev->config->finalize_features(dev);
++ if (err)
++ goto err;
++
+ if (drv->validate) {
++ u64 features = dev->features;
++
+ err = drv->validate(dev);
+ if (err)
+ goto err;
++
++ /* Did validation change any features? Then write them again. */
++ if (features != dev->features) {
++ err = dev->config->finalize_features(dev);
++ if (err)
++ goto err;
++ }
+ }
+
+- err = virtio_finalize_features(dev);
++ err = virtio_features_ok(dev);
+ if (err)
+ goto err;
+
+@@ -490,7 +490,11 @@ int virtio_device_restore(struct virtio_device *dev)
+ /* We have a driver! */
+ virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
+
+- ret = virtio_finalize_features(dev);
++ ret = dev->config->finalize_features(dev);
++ if (ret)
++ goto err;
++
++ ret = virtio_features_ok(dev);
+ if (ret)
+ goto err;
+
diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index bef8ad6bf4661..4624a2c3d0553 100644
--- a/drivers/virtio/virtio_mem.c
@@ -119042,6 +178294,33 @@ index e4f336111edc6..6cef6e2edb892 100644
}
static DEVICE_ATTR_RW(crccheck);
+diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
+index ca70c5f032060..9cbeeb4923ecf 100644
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -2090,16 +2090,20 @@ static ssize_t w1_seq_show(struct device *device,
+ if (sl->reg_num.id == reg_num->id)
+ seq = i;
+
++ if (w1_reset_bus(sl->master))
++ goto error;
++
++ /* Put the device into chain DONE state */
++ w1_write_8(sl->master, W1_MATCH_ROM);
++ w1_write_block(sl->master, (u8 *)&rn, 8);
+ w1_write_8(sl->master, W1_42_CHAIN);
+ w1_write_8(sl->master, W1_42_CHAIN_DONE);
+ w1_write_8(sl->master, W1_42_CHAIN_DONE_INV);
+- w1_read_block(sl->master, &ack, sizeof(ack));
+
+ /* check for acknowledgment */
+ ack = w1_read_8(sl->master);
+ if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
+ goto error;
+-
+ }
+
+ /* Exit from CHAIN state */
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index bf59faeb3de1b..d937f957f8df8 100644
--- a/drivers/watchdog/Kconfig
@@ -119078,6 +178357,440 @@ index f60beec1bbaea..f7d82d2619133 100644
mutex_unlock(&watchdog.lock);
return 0;
+diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
+index 359302f71f7ef..ae7f9357bb871 100644
+--- a/drivers/watchdog/rti_wdt.c
++++ b/drivers/watchdog/rti_wdt.c
+@@ -229,6 +229,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
+ ret = pm_runtime_get_sync(dev);
+ if (ret) {
+ pm_runtime_put_noidle(dev);
++ pm_runtime_disable(&pdev->dev);
+ return dev_err_probe(dev, ret, "runtime pm failed\n");
+ }
+
+diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
+index a730ecbf78cd5..4820af929a826 100644
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -48,7 +48,7 @@
+ /* internal variables */
+
+ enum tco_reg_layout {
+- sp5100, sb800, efch
++ sp5100, sb800, efch, efch_mmio
+ };
+
+ struct sp5100_tco {
+@@ -85,6 +85,10 @@ static enum tco_reg_layout tco_reg_layout(struct pci_dev *dev)
+ dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
+ dev->revision < 0x40) {
+ return sp5100;
++ } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
++ sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
++ sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) {
++ return efch_mmio;
+ } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ ((dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
+ dev->revision >= 0x41) ||
+@@ -201,6 +205,8 @@ static void tco_timer_enable(struct sp5100_tco *tco)
+ ~EFCH_PM_WATCHDOG_DISABLE,
+ EFCH_PM_DECODEEN_SECOND_RES);
+ break;
++ default:
++ break;
+ }
+ }
+
+@@ -215,14 +221,195 @@ static u32 sp5100_tco_read_pm_reg32(u8 index)
+ return val;
+ }
+
++static u32 sp5100_tco_request_region(struct device *dev,
++ u32 mmio_addr,
++ const char *dev_name)
++{
++ if (!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
++ dev_name)) {
++ dev_dbg(dev, "MMIO address 0x%08x already in use\n", mmio_addr);
++ return 0;
++ }
++
++ return mmio_addr;
++}
++
++static u32 sp5100_tco_prepare_base(struct sp5100_tco *tco,
++ u32 mmio_addr,
++ u32 alt_mmio_addr,
++ const char *dev_name)
++{
++ struct device *dev = tco->wdd.parent;
++
++ dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr);
++
++ if (!mmio_addr && !alt_mmio_addr)
++ return -ENODEV;
++
++ /* Check for MMIO address and alternate MMIO address conflicts */
++ if (mmio_addr)
++ mmio_addr = sp5100_tco_request_region(dev, mmio_addr, dev_name);
++
++ if (!mmio_addr && alt_mmio_addr)
++ mmio_addr = sp5100_tco_request_region(dev, alt_mmio_addr, dev_name);
++
++ if (!mmio_addr) {
++ dev_err(dev, "Failed to reserve MMIO or alternate MMIO region\n");
++ return -EBUSY;
++ }
++
++ tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
++ if (!tco->tcobase) {
++ dev_err(dev, "MMIO address 0x%08x failed mapping\n", mmio_addr);
++ devm_release_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
++ return -ENOMEM;
++ }
++
++ dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
++
++ return 0;
++}
++
++static int sp5100_tco_timer_init(struct sp5100_tco *tco)
++{
++ struct watchdog_device *wdd = &tco->wdd;
++ struct device *dev = wdd->parent;
++ u32 val;
++
++ val = readl(SP5100_WDT_CONTROL(tco->tcobase));
++ if (val & SP5100_WDT_DISABLED) {
++ dev_err(dev, "Watchdog hardware is disabled\n");
++ return -ENODEV;
++ }
++
++ /*
++ * Save WatchDogFired status, because WatchDogFired flag is
++ * cleared here.
++ */
++ if (val & SP5100_WDT_FIRED)
++ wdd->bootstatus = WDIOF_CARDRESET;
++
++ /* Set watchdog action to reset the system */
++ val &= ~SP5100_WDT_ACTION_RESET;
++ writel(val, SP5100_WDT_CONTROL(tco->tcobase));
++
++ /* Set a reasonable heartbeat before we stop the timer */
++ tco_timer_set_timeout(wdd, wdd->timeout);
++
++ /*
++ * Stop the TCO before we change anything so we don't race with
++ * a zeroed timer.
++ */
++ tco_timer_stop(wdd);
++
++ return 0;
++}
++
++static u8 efch_read_pm_reg8(void __iomem *addr, u8 index)
++{
++ return readb(addr + index);
++}
++
++static void efch_update_pm_reg8(void __iomem *addr, u8 index, u8 reset, u8 set)
++{
++ u8 val;
++
++ val = readb(addr + index);
++ val &= reset;
++ val |= set;
++ writeb(val, addr + index);
++}
++
++static void tco_timer_enable_mmio(void __iomem *addr)
++{
++ efch_update_pm_reg8(addr, EFCH_PM_DECODEEN3,
++ ~EFCH_PM_WATCHDOG_DISABLE,
++ EFCH_PM_DECODEEN_SECOND_RES);
++}
++
++static int sp5100_tco_setupdevice_mmio(struct device *dev,
++ struct watchdog_device *wdd)
++{
++ struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
++ const char *dev_name = SB800_DEVNAME;
++ u32 mmio_addr = 0, alt_mmio_addr = 0;
++ struct resource *res;
++ void __iomem *addr;
++ int ret;
++ u32 val;
++
++ res = request_mem_region_muxed(EFCH_PM_ACPI_MMIO_PM_ADDR,
++ EFCH_PM_ACPI_MMIO_PM_SIZE,
++ "sp5100_tco");
++
++ if (!res) {
++ dev_err(dev,
++ "Memory region 0x%08x already in use\n",
++ EFCH_PM_ACPI_MMIO_PM_ADDR);
++ return -EBUSY;
++ }
++
++ addr = ioremap(EFCH_PM_ACPI_MMIO_PM_ADDR, EFCH_PM_ACPI_MMIO_PM_SIZE);
++ if (!addr) {
++ dev_err(dev, "Address mapping failed\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ /*
++ * EFCH_PM_DECODEEN_WDT_TMREN is dual purpose. This bitfield
++ * enables sp5100_tco register MMIO space decoding. The bitfield
++ * also starts the timer operation. Enable if not already enabled.
++ */
++ val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
++ if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
++ efch_update_pm_reg8(addr, EFCH_PM_DECODEEN, 0xff,
++ EFCH_PM_DECODEEN_WDT_TMREN);
++ }
++
++ /* Error if the timer could not be enabled */
++ val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
++ if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
++ dev_err(dev, "Failed to enable the timer\n");
++ ret = -EFAULT;
++ goto out;
++ }
++
++ mmio_addr = EFCH_PM_WDT_ADDR;
++
++ /* Determine alternate MMIO base address */
++ val = efch_read_pm_reg8(addr, EFCH_PM_ISACONTROL);
++ if (val & EFCH_PM_ISACONTROL_MMIOEN)
++ alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
++ EFCH_PM_ACPI_MMIO_WDT_OFFSET;
++
++ ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
++ if (!ret) {
++ tco_timer_enable_mmio(addr);
++ ret = sp5100_tco_timer_init(tco);
++ }
++
++out:
++ if (addr)
++ iounmap(addr);
++
++ release_resource(res);
++
++ return ret;
++}
++
+ static int sp5100_tco_setupdevice(struct device *dev,
+ struct watchdog_device *wdd)
+ {
+ struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
+ const char *dev_name;
+ u32 mmio_addr = 0, val;
++ u32 alt_mmio_addr = 0;
+ int ret;
+
++ if (tco->tco_reg_layout == efch_mmio)
++ return sp5100_tco_setupdevice_mmio(dev, wdd);
++
+ /* Request the IO ports used by this driver */
+ if (!request_muxed_region(SP5100_IO_PM_INDEX_REG,
+ SP5100_PM_IOPORTS_SIZE, "sp5100_tco")) {
+@@ -239,138 +426,55 @@ static int sp5100_tco_setupdevice(struct device *dev,
+ dev_name = SP5100_DEVNAME;
+ mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) &
+ 0xfffffff8;
++
++ /*
++ * Secondly, find the watchdog timer MMIO address
++ * from SBResource_MMIO register.
++ */
++
++ /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
++ pci_read_config_dword(sp5100_tco_pci,
++ SP5100_SB_RESOURCE_MMIO_BASE,
++ &val);
++
++ /* Verify MMIO is enabled and using bar0 */
++ if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
++ alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
+ break;
+ case sb800:
+ dev_name = SB800_DEVNAME;
+ mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) &
+ 0xfffffff8;
++
++ /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
++ val = sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
++
++ /* Verify MMIO is enabled and using bar0 */
++ if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
++ alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
+ break;
+ case efch:
+ dev_name = SB800_DEVNAME;
+- /*
+- * On Family 17h devices, the EFCH_PM_DECODEEN_WDT_TMREN bit of
+- * EFCH_PM_DECODEEN not only enables the EFCH_PM_WDT_ADDR memory
+- * region, it also enables the watchdog itself.
+- */
+- if (boot_cpu_data.x86 == 0x17) {
+- val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
+- if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
+- sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN, 0xff,
+- EFCH_PM_DECODEEN_WDT_TMREN);
+- }
+- }
+ val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
+ if (val & EFCH_PM_DECODEEN_WDT_TMREN)
+ mmio_addr = EFCH_PM_WDT_ADDR;
++
++ val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
++ if (val & EFCH_PM_ISACONTROL_MMIOEN)
++ alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
++ EFCH_PM_ACPI_MMIO_WDT_OFFSET;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+- /* Check MMIO address conflict */
+- if (!mmio_addr ||
+- !devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
+- dev_name)) {
+- if (mmio_addr)
+- dev_dbg(dev, "MMIO address 0x%08x already in use\n",
+- mmio_addr);
+- switch (tco->tco_reg_layout) {
+- case sp5100:
+- /*
+- * Secondly, Find the watchdog timer MMIO address
+- * from SBResource_MMIO register.
+- */
+- /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
+- pci_read_config_dword(sp5100_tco_pci,
+- SP5100_SB_RESOURCE_MMIO_BASE,
+- &mmio_addr);
+- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
+- SB800_ACPI_MMIO_SEL)) !=
+- SB800_ACPI_MMIO_DECODE_EN) {
+- ret = -ENODEV;
+- goto unreg_region;
+- }
+- mmio_addr &= ~0xFFF;
+- mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+- break;
+- case sb800:
+- /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
+- mmio_addr =
+- sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
+- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
+- SB800_ACPI_MMIO_SEL)) !=
+- SB800_ACPI_MMIO_DECODE_EN) {
+- ret = -ENODEV;
+- goto unreg_region;
+- }
+- mmio_addr &= ~0xFFF;
+- mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+- break;
+- case efch:
+- val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
+- if (!(val & EFCH_PM_ISACONTROL_MMIOEN)) {
+- ret = -ENODEV;
+- goto unreg_region;
+- }
+- mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
+- EFCH_PM_ACPI_MMIO_WDT_OFFSET;
+- break;
+- }
+- dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n",
+- mmio_addr);
+- if (!devm_request_mem_region(dev, mmio_addr,
+- SP5100_WDT_MEM_MAP_SIZE,
+- dev_name)) {
+- dev_dbg(dev, "MMIO address 0x%08x already in use\n",
+- mmio_addr);
+- ret = -EBUSY;
+- goto unreg_region;
+- }
+- }
+-
+- tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
+- if (!tco->tcobase) {
+- dev_err(dev, "failed to get tcobase address\n");
+- ret = -ENOMEM;
+- goto unreg_region;
+- }
+-
+- dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
+-
+- /* Setup the watchdog timer */
+- tco_timer_enable(tco);
+-
+- val = readl(SP5100_WDT_CONTROL(tco->tcobase));
+- if (val & SP5100_WDT_DISABLED) {
+- dev_err(dev, "Watchdog hardware is disabled\n");
+- ret = -ENODEV;
+- goto unreg_region;
++ ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
++ if (!ret) {
++ /* Setup the watchdog timer */
++ tco_timer_enable(tco);
++ ret = sp5100_tco_timer_init(tco);
+ }
+
+- /*
+- * Save WatchDogFired status, because WatchDogFired flag is
+- * cleared here.
+- */
+- if (val & SP5100_WDT_FIRED)
+- wdd->bootstatus = WDIOF_CARDRESET;
+- /* Set watchdog action to reset the system */
+- val &= ~SP5100_WDT_ACTION_RESET;
+- writel(val, SP5100_WDT_CONTROL(tco->tcobase));
+-
+- /* Set a reasonable heartbeat before we stop the timer */
+- tco_timer_set_timeout(wdd, wdd->timeout);
+-
+- /*
+- * Stop the TCO before we change anything so we don't race with
+- * a zeroed timer.
+- */
+- tco_timer_stop(wdd);
+-
+- release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
+-
+- return 0;
+-
+-unreg_region:
+ release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
+ return ret;
+ }
+diff --git a/drivers/watchdog/sp5100_tco.h b/drivers/watchdog/sp5100_tco.h
+index adf015aa4126f..6a0986d2c94b7 100644
+--- a/drivers/watchdog/sp5100_tco.h
++++ b/drivers/watchdog/sp5100_tco.h
+@@ -58,6 +58,7 @@
+ #define SB800_PM_WATCHDOG_SECOND_RES GENMASK(1, 0)
+ #define SB800_ACPI_MMIO_DECODE_EN BIT(0)
+ #define SB800_ACPI_MMIO_SEL BIT(1)
++#define SB800_ACPI_MMIO_MASK GENMASK(1, 0)
+
+ #define SB800_PM_WDT_MMIO_OFFSET 0xB00
+
+@@ -82,4 +83,10 @@
+ #define EFCH_PM_ISACONTROL_MMIOEN BIT(1)
+
+ #define EFCH_PM_ACPI_MMIO_ADDR 0xfed80000
++#define EFCH_PM_ACPI_MMIO_PM_OFFSET 0x00000300
+ #define EFCH_PM_ACPI_MMIO_WDT_OFFSET 0x00000b00
++
++#define EFCH_PM_ACPI_MMIO_PM_ADDR (EFCH_PM_ACPI_MMIO_ADDR + \
++ EFCH_PM_ACPI_MMIO_PM_OFFSET)
++#define EFCH_PM_ACPI_MMIO_PM_SIZE 8
++#define AMD_ZEN_SMBUS_PCI_REV 0x51
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 3a50f097ed3ed..8db96b5e72536 100644
--- a/drivers/xen/balloon.c
@@ -119521,6 +179234,19 @@ index 7984645b59563..bbe337dc296e3 100644
if (!bytes)
goto out;
+diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
+index e56a5faac395c..cbdff89799807 100644
+--- a/drivers/xen/swiotlb-xen.c
++++ b/drivers/xen/swiotlb-xen.c
+@@ -380,7 +380,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
+ */
+ trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
+
+- map = swiotlb_tbl_map_single(dev, phys, size, size, dir, attrs);
++ map = swiotlb_tbl_map_single(dev, phys, size, size, 0, dir, attrs);
+ if (map == (phys_addr_t)DMA_MAPPING_ERROR)
+ return DMA_MAPPING_ERROR;
+
diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
index 22f13abbe9130..5e53b4817f167 100644
--- a/drivers/xen/xen-pciback/conf_space_capability.c
@@ -119726,6 +179452,34 @@ index e6c447ae91f38..b165377179c3c 100644
up_write(&vnode->volume->cell->fs_open_mmaps_lock);
}
+diff --git a/fs/afs/inode.c b/fs/afs/inode.c
+index 8fcffea2daf50..a47666ba48f56 100644
+--- a/fs/afs/inode.c
++++ b/fs/afs/inode.c
+@@ -728,10 +728,22 @@ int afs_getattr(struct user_namespace *mnt_userns, const struct path *path,
+ {
+ struct inode *inode = d_inode(path->dentry);
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+- int seq = 0;
++ struct key *key;
++ int ret, seq = 0;
+
+ _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
+
++ if (!(query_flags & AT_STATX_DONT_SYNC) &&
++ !test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
++ key = afs_request_key(vnode->volume->cell);
++ if (IS_ERR(key))
++ return PTR_ERR(key);
++ ret = afs_validate(vnode, key);
++ key_put(key);
++ if (ret < 0)
++ return ret;
++ }
++
+ do {
+ read_seqbegin_or_lock(&vnode->cb_lock, &seq);
+ generic_fillattr(&init_user_ns, inode, stat);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index d110def8aa8eb..34c68724c98be 100644
--- a/fs/afs/super.c
@@ -120047,6 +179801,371 @@ index 473d21b3a86de..66899b6e9bd86 100644
return true;
if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
return true;
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index a813b70f594e6..c93150f36a52a 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -170,8 +170,8 @@ static int padzero(unsigned long elf_bss)
+
+ static int
+ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
+- unsigned long load_addr, unsigned long interp_load_addr,
+- unsigned long e_entry)
++ unsigned long interp_load_addr,
++ unsigned long e_entry, unsigned long phdr_addr)
+ {
+ struct mm_struct *mm = current->mm;
+ unsigned long p = bprm->p;
+@@ -257,7 +257,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
+ NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
+ NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
+ NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
+- NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
++ NEW_AUX_ENT(AT_PHDR, phdr_addr);
+ NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
+ NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
+ NEW_AUX_ENT(AT_BASE, interp_load_addr);
+@@ -823,7 +823,7 @@ static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
+ static int load_elf_binary(struct linux_binprm *bprm)
+ {
+ struct file *interpreter = NULL; /* to shut gcc up */
+- unsigned long load_addr = 0, load_bias = 0;
++ unsigned long load_addr, load_bias = 0, phdr_addr = 0;
+ int load_addr_set = 0;
+ unsigned long error;
+ struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
+@@ -1156,6 +1156,17 @@ out_free_interp:
+ reloc_func_desc = load_bias;
+ }
+ }
++
++ /*
++ * Figure out which segment in the file contains the Program
++ * Header table, and map to the associated memory address.
++ */
++ if (elf_ppnt->p_offset <= elf_ex->e_phoff &&
++ elf_ex->e_phoff < elf_ppnt->p_offset + elf_ppnt->p_filesz) {
++ phdr_addr = elf_ex->e_phoff - elf_ppnt->p_offset +
++ elf_ppnt->p_vaddr;
++ }
++
+ k = elf_ppnt->p_vaddr;
+ if ((elf_ppnt->p_flags & PF_X) && k < start_code)
+ start_code = k;
+@@ -1191,6 +1202,7 @@ out_free_interp:
+ }
+
+ e_entry = elf_ex->e_entry + load_bias;
++ phdr_addr += load_bias;
+ elf_bss += load_bias;
+ elf_brk += load_bias;
+ start_code += load_bias;
+@@ -1254,8 +1266,8 @@ out_free_interp:
+ goto out;
+ #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
+- retval = create_elf_tables(bprm, elf_ex,
+- load_addr, interp_load_addr, e_entry);
++ retval = create_elf_tables(bprm, elf_ex, interp_load_addr,
++ e_entry, phdr_addr);
+ if (retval < 0)
+ goto out;
+
+@@ -1606,17 +1618,16 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
+ * long file_ofs
+ * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
+ */
+-static int fill_files_note(struct memelfnote *note)
++static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm)
+ {
+- struct mm_struct *mm = current->mm;
+- struct vm_area_struct *vma;
+ unsigned count, size, names_ofs, remaining, n;
+ user_long_t *data;
+ user_long_t *start_end_ofs;
+ char *name_base, *name_curpos;
++ int i;
+
+ /* *Estimated* file count and total data size needed */
+- count = mm->map_count;
++ count = cprm->vma_count;
+ if (count > UINT_MAX / 64)
+ return -EINVAL;
+ size = count * 64;
+@@ -1638,11 +1649,12 @@ static int fill_files_note(struct memelfnote *note)
+ name_base = name_curpos = ((char *)data) + names_ofs;
+ remaining = size - names_ofs;
+ count = 0;
+- for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct core_vma_metadata *m = &cprm->vma_meta[i];
+ struct file *file;
+ const char *filename;
+
+- file = vma->vm_file;
++ file = m->file;
+ if (!file)
+ continue;
+ filename = file_path(file, name_curpos, remaining);
+@@ -1662,9 +1674,9 @@ static int fill_files_note(struct memelfnote *note)
+ memmove(name_curpos, filename, n);
+ name_curpos += n;
+
+- *start_end_ofs++ = vma->vm_start;
+- *start_end_ofs++ = vma->vm_end;
+- *start_end_ofs++ = vma->vm_pgoff;
++ *start_end_ofs++ = m->start;
++ *start_end_ofs++ = m->end;
++ *start_end_ofs++ = m->pgoff;
+ count++;
+ }
+
+@@ -1675,7 +1687,7 @@ static int fill_files_note(struct memelfnote *note)
+ * Count usually is less than mm->map_count,
+ * we need to move filenames down.
+ */
+- n = mm->map_count - count;
++ n = cprm->vma_count - count;
+ if (n != 0) {
+ unsigned shift_bytes = n * 3 * sizeof(data[0]);
+ memmove(name_base - shift_bytes, name_base,
+@@ -1787,7 +1799,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
+
+ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ struct elf_note_info *info,
+- const kernel_siginfo_t *siginfo, struct pt_regs *regs)
++ struct coredump_params *cprm)
+ {
+ struct task_struct *dump_task = current;
+ const struct user_regset_view *view = task_user_regset_view(dump_task);
+@@ -1859,7 +1871,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ * Now fill in each thread's information.
+ */
+ for (t = info->thread; t != NULL; t = t->next)
+- if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size))
++ if (!fill_thread_core_info(t, view, cprm->siginfo->si_signo, &info->size))
+ return 0;
+
+ /*
+@@ -1868,13 +1880,13 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
+ info->size += notesize(&info->psinfo);
+
+- fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
++ fill_siginfo_note(&info->signote, &info->csigdata, cprm->siginfo);
+ info->size += notesize(&info->signote);
+
+ fill_auxv_note(&info->auxv, current->mm);
+ info->size += notesize(&info->auxv);
+
+- if (fill_files_note(&info->files) == 0)
++ if (fill_files_note(&info->files, cprm) == 0)
+ info->size += notesize(&info->files);
+
+ return 1;
+@@ -2016,7 +2028,7 @@ static int elf_note_info_init(struct elf_note_info *info)
+
+ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ struct elf_note_info *info,
+- const kernel_siginfo_t *siginfo, struct pt_regs *regs)
++ struct coredump_params *cprm)
+ {
+ struct core_thread *ct;
+ struct elf_thread_status *ets;
+@@ -2037,13 +2049,13 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ list_for_each_entry(ets, &info->thread_list, list) {
+ int sz;
+
+- sz = elf_dump_thread_status(siginfo->si_signo, ets);
++ sz = elf_dump_thread_status(cprm->siginfo->si_signo, ets);
+ info->thread_status_size += sz;
+ }
+ /* now collect the dump for the current */
+ memset(info->prstatus, 0, sizeof(*info->prstatus));
+- fill_prstatus(&info->prstatus->common, current, siginfo->si_signo);
+- elf_core_copy_regs(&info->prstatus->pr_reg, regs);
++ fill_prstatus(&info->prstatus->common, current, cprm->siginfo->si_signo);
++ elf_core_copy_regs(&info->prstatus->pr_reg, cprm->regs);
+
+ /* Set up header */
+ fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS);
+@@ -2059,18 +2071,18 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
+ fill_note(info->notes + 1, "CORE", NT_PRPSINFO,
+ sizeof(*info->psinfo), info->psinfo);
+
+- fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo);
++ fill_siginfo_note(info->notes + 2, &info->csigdata, cprm->siginfo);
+ fill_auxv_note(info->notes + 3, current->mm);
+ info->numnote = 4;
+
+- if (fill_files_note(info->notes + info->numnote) == 0) {
++ if (fill_files_note(info->notes + info->numnote, cprm) == 0) {
+ info->notes_files = info->notes + info->numnote;
+ info->numnote++;
+ }
+
+ /* Try to dump the FPU. */
+- info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs,
+- info->fpu);
++ info->prstatus->pr_fpvalid =
++ elf_core_copy_task_fpregs(current, cprm->regs, info->fpu);
+ if (info->prstatus->pr_fpvalid)
+ fill_note(info->notes + info->numnote++,
+ "CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
+@@ -2156,8 +2168,7 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
+ static int elf_core_dump(struct coredump_params *cprm)
+ {
+ int has_dumped = 0;
+- int vma_count, segs, i;
+- size_t vma_data_size;
++ int segs, i;
+ struct elfhdr elf;
+ loff_t offset = 0, dataoff;
+ struct elf_note_info info = { };
+@@ -2165,16 +2176,12 @@ static int elf_core_dump(struct coredump_params *cprm)
+ struct elf_shdr *shdr4extnum = NULL;
+ Elf_Half e_phnum;
+ elf_addr_t e_shoff;
+- struct core_vma_metadata *vma_meta;
+-
+- if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
+- return 0;
+
+ /*
+ * The number of segs are recored into ELF header as 16bit value.
+ * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
+ */
+- segs = vma_count + elf_core_extra_phdrs();
++ segs = cprm->vma_count + elf_core_extra_phdrs();
+
+ /* for notes section */
+ segs++;
+@@ -2188,7 +2195,7 @@ static int elf_core_dump(struct coredump_params *cprm)
+ * Collect all the non-memory information about the process for the
+ * notes. This also sets up the file header.
+ */
+- if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs))
++ if (!fill_note_info(&elf, e_phnum, &info, cprm))
+ goto end_coredump;
+
+ has_dumped = 1;
+@@ -2213,7 +2220,7 @@ static int elf_core_dump(struct coredump_params *cprm)
+
+ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+
+- offset += vma_data_size;
++ offset += cprm->vma_data_size;
+ offset += elf_core_extra_data_size();
+ e_shoff = offset;
+
+@@ -2233,8 +2240,8 @@ static int elf_core_dump(struct coredump_params *cprm)
+ goto end_coredump;
+
+ /* Write program headers for segments dump */
+- for (i = 0; i < vma_count; i++) {
+- struct core_vma_metadata *meta = vma_meta + i;
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct core_vma_metadata *meta = cprm->vma_meta + i;
+ struct elf_phdr phdr;
+
+ phdr.p_type = PT_LOAD;
+@@ -2271,8 +2278,8 @@ static int elf_core_dump(struct coredump_params *cprm)
+ /* Align to page */
+ dump_skip_to(cprm, dataoff);
+
+- for (i = 0; i < vma_count; i++) {
+- struct core_vma_metadata *meta = vma_meta + i;
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct core_vma_metadata *meta = cprm->vma_meta + i;
+
+ if (!dump_user_range(cprm, meta->start, meta->dump_size))
+ goto end_coredump;
+@@ -2289,7 +2296,6 @@ static int elf_core_dump(struct coredump_params *cprm)
+ end_coredump:
+ free_note_info(&info);
+ kfree(shdr4extnum);
+- kvfree(vma_meta);
+ kfree(phdr4note);
+ return has_dumped;
+ }
+diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
+index 6d8fd6030cbb5..830a6a876ffea 100644
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -1465,7 +1465,7 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm,
+ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ {
+ int has_dumped = 0;
+- int vma_count, segs;
++ int segs;
+ int i;
+ struct elfhdr *elf = NULL;
+ loff_t offset = 0, dataoff;
+@@ -1480,8 +1480,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ elf_addr_t e_shoff;
+ struct core_thread *ct;
+ struct elf_thread_status *tmp;
+- struct core_vma_metadata *vma_meta = NULL;
+- size_t vma_data_size;
+
+ /* alloc memory for large data structures: too large to be on stack */
+ elf = kmalloc(sizeof(*elf), GFP_KERNEL);
+@@ -1491,9 +1489,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ if (!psinfo)
+ goto end_coredump;
+
+- if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
+- goto end_coredump;
+-
+ for (ct = current->mm->core_state->dumper.next;
+ ct; ct = ct->next) {
+ tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
+@@ -1513,7 +1508,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ tmp->next = thread_list;
+ thread_list = tmp;
+
+- segs = vma_count + elf_core_extra_phdrs();
++ segs = cprm->vma_count + elf_core_extra_phdrs();
+
+ /* for notes section */
+ segs++;
+@@ -1558,7 +1553,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ /* Page-align dumped data */
+ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+
+- offset += vma_data_size;
++ offset += cprm->vma_data_size;
+ offset += elf_core_extra_data_size();
+ e_shoff = offset;
+
+@@ -1578,8 +1573,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+ goto end_coredump;
+
+ /* write program headers for segments dump */
+- for (i = 0; i < vma_count; i++) {
+- struct core_vma_metadata *meta = vma_meta + i;
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct core_vma_metadata *meta = cprm->vma_meta + i;
+ struct elf_phdr phdr;
+ size_t sz;
+
+@@ -1628,7 +1623,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
+
+ dump_skip_to(cprm, dataoff);
+
+- if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count))
++ if (!elf_fdpic_dump_segments(cprm, cprm->vma_meta, cprm->vma_count))
+ goto end_coredump;
+
+ if (!elf_core_write_extra_data(cprm))
+@@ -1652,7 +1647,6 @@ end_coredump:
+ thread_list = thread_list->next;
+ kfree(tmp);
+ }
+- kvfree(vma_meta);
+ kfree(phdr4note);
+ kfree(elf);
+ kfree(psinfo);
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 309516e6a9682..43c89952b7d25 100644
--- a/fs/btrfs/async-thread.c
@@ -120120,10 +180239,28 @@ index f735b8798ba12..8b090c40daf77 100644
eie = eie->next;
eie->next = ref->inode_list;
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
-index a3b830b8410a8..d721c66d0b41b 100644
+index a3b830b8410a8..37418b183b078 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
-@@ -902,6 +902,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
+@@ -123,7 +123,16 @@ void btrfs_put_block_group(struct btrfs_block_group *cache)
+ {
+ if (refcount_dec_and_test(&cache->refs)) {
+ WARN_ON(cache->pinned > 0);
+- WARN_ON(cache->reserved > 0);
++ /*
++ * If there was a failure to cleanup a log tree, very likely due
++ * to an IO failure on a writeback attempt of one or more of its
++ * extent buffers, we could not do proper (and cheap) unaccounting
++ * of their reserved space, so don't warn on reserved > 0 in that
++ * case.
++ */
++ if (!(cache->flags & BTRFS_BLOCK_GROUP_METADATA) ||
++ !BTRFS_FS_LOG_CLEANUP_ERROR(cache->fs_info))
++ WARN_ON(cache->reserved > 0);
+
+ /*
+ * A block_group shouldn't be on the discard_list anymore.
+@@ -902,6 +911,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
spin_unlock(&cluster->refill_lock);
btrfs_clear_treelog_bg(block_group);
@@ -120131,7 +180268,59 @@ index a3b830b8410a8..d721c66d0b41b 100644
path = btrfs_alloc_path();
if (!path) {
-@@ -2510,6 +2511,19 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
+@@ -1490,13 +1500,16 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
+ container_of(work, struct btrfs_fs_info, reclaim_bgs_work);
+ struct btrfs_block_group *bg;
+ struct btrfs_space_info *space_info;
+- LIST_HEAD(again_list);
+
+ if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
+ return;
+
+- if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE))
++ sb_start_write(fs_info->sb);
++
++ if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
++ sb_end_write(fs_info->sb);
+ return;
++ }
+
+ /*
+ * Long running balances can keep us blocked here for eternity, so
+@@ -1504,6 +1517,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
+ */
+ if (!mutex_trylock(&fs_info->reclaim_bgs_lock)) {
+ btrfs_exclop_finish(fs_info);
++ sb_end_write(fs_info->sb);
+ return;
+ }
+
+@@ -1561,21 +1575,18 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
+ div64_u64(zone_unusable * 100, bg->length));
+ trace_btrfs_reclaim_block_group(bg);
+ ret = btrfs_relocate_chunk(fs_info, bg->start);
+- if (ret && ret != -EAGAIN)
++ if (ret)
+ btrfs_err(fs_info, "error relocating chunk %llu",
+ bg->start);
+
+ next:
++ btrfs_put_block_group(bg);
+ spin_lock(&fs_info->unused_bgs_lock);
+- if (ret == -EAGAIN && list_empty(&bg->bg_list))
+- list_add_tail(&bg->bg_list, &again_list);
+- else
+- btrfs_put_block_group(bg);
+ }
+- list_splice_tail(&again_list, &fs_info->reclaim_bgs);
+ spin_unlock(&fs_info->unused_bgs_lock);
+ mutex_unlock(&fs_info->reclaim_bgs_lock);
+ btrfs_exclop_finish(fs_info);
++ sb_end_write(fs_info->sb);
+ }
+
+ void btrfs_reclaim_bgs(struct btrfs_fs_info *fs_info)
+@@ -2510,6 +2521,19 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
int ret;
bool dirty_bg_running;
@@ -120151,13 +180340,91 @@ index a3b830b8410a8..d721c66d0b41b 100644
do {
trans = btrfs_join_transaction(fs_info->extent_root);
if (IS_ERR(trans))
+@@ -2858,7 +2882,6 @@ int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans)
+ struct btrfs_path *path = NULL;
+ LIST_HEAD(dirty);
+ struct list_head *io = &cur_trans->io_bgs;
+- int num_started = 0;
+ int loops = 0;
+
+ spin_lock(&cur_trans->dirty_bgs_lock);
+@@ -2924,7 +2947,6 @@ again:
+ cache->io_ctl.inode = NULL;
+ ret = btrfs_write_out_cache(trans, cache, path);
+ if (ret == 0 && cache->io_ctl.inode) {
+- num_started++;
+ should_put = 0;
+
+ /*
+@@ -3025,7 +3047,6 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)
+ int should_put;
+ struct btrfs_path *path;
+ struct list_head *io = &cur_trans->io_bgs;
+- int num_started = 0;
+
+ path = btrfs_alloc_path();
+ if (!path)
+@@ -3083,7 +3104,6 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)
+ cache->io_ctl.inode = NULL;
+ ret = btrfs_write_out_cache(trans, cache, path);
+ if (ret == 0 && cache->io_ctl.inode) {
+- num_started++;
+ should_put = 0;
+ list_add_tail(&cache->io_list, io);
+ } else {
+@@ -3879,9 +3899,22 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
+ * important and indicates a real bug if this happens.
+ */
+ if (WARN_ON(space_info->bytes_pinned > 0 ||
+- space_info->bytes_reserved > 0 ||
+ space_info->bytes_may_use > 0))
+ btrfs_dump_space_info(info, space_info, 0, 0);
++
++ /*
++ * If there was a failure to cleanup a log tree, very likely due
++ * to an IO failure on a writeback attempt of one or more of its
++ * extent buffers, we could not do proper (and cheap) unaccounting
++ * of their reserved space, so don't warn on bytes_reserved > 0 in
++ * that case.
++ */
++ if (!(space_info->flags & BTRFS_BLOCK_GROUP_METADATA) ||
++ !BTRFS_FS_LOG_CLEANUP_ERROR(info)) {
++ if (WARN_ON(space_info->bytes_reserved > 0))
++ btrfs_dump_space_info(info, space_info, 0, 0);
++ }
++
+ WARN_ON(space_info->reclaim_size > 0);
+ list_del(&space_info->list);
+ btrfs_sysfs_remove_space_info(space_info);
+diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
+index 0913ee50e6c34..701fbd1b56766 100644
+--- a/fs/btrfs/compression.c
++++ b/fs/btrfs/compression.c
+@@ -550,7 +550,6 @@ static noinline int add_ra_bio_pages(struct inode *inode,
+ u64 isize = i_size_read(inode);
+ int ret;
+ struct page *page;
+- unsigned long nr_pages = 0;
+ struct extent_map *em;
+ struct address_space *mapping = inode->i_mapping;
+ struct extent_map_tree *em_tree;
+@@ -646,7 +645,6 @@ static noinline int add_ra_bio_pages(struct inode *inode,
+ PAGE_SIZE, 0);
+
+ if (ret == PAGE_SIZE) {
+- nr_pages++;
+ put_page(page);
+ } else {
+ unlock_extent(tree, last_offset, end);
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
-index 84627cbd5b5b5..95a6a63caf047 100644
+index 84627cbd5b5b5..899f854459252 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
-@@ -1568,12 +1568,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
+@@ -1566,35 +1566,13 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
+ struct btrfs_path *p,
+ int write_lock_level)
{
- struct btrfs_fs_info *fs_info = root->fs_info;
+- struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_buffer *b;
- int root_lock;
+ int root_lock = 0;
@@ -120167,9 +180434,32 @@ index 84627cbd5b5b5..95a6a63caf047 100644
- root_lock = BTRFS_READ_LOCK;
-
if (p->search_commit_root) {
+- /*
+- * The commit roots are read only so we always do read locks,
+- * and we always must hold the commit_root_sem when doing
+- * searches on them, the only exception is send where we don't
+- * want to block transaction commits for a long time, so
+- * we need to clone the commit root in order to avoid races
+- * with transaction commits that create a snapshot of one of
+- * the roots used by a send operation.
+- */
+- if (p->need_commit_sem) {
+- down_read(&fs_info->commit_root_sem);
+- b = btrfs_clone_extent_buffer(root->commit_root);
+- up_read(&fs_info->commit_root_sem);
+- if (!b)
+- return ERR_PTR(-ENOMEM);
+-
+- } else {
+- b = root->commit_root;
+- atomic_inc(&b->refs);
+- }
++ b = root->commit_root;
++ atomic_inc(&b->refs);
+ level = btrfs_header_level(b);
/*
- * The commit roots are read only so we always do read locks,
-@@ -1611,6 +1608,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
+ * Ensure that all callers have set skip_locking when
+@@ -1611,6 +1589,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
goto out;
}
@@ -120179,7 +180469,7 @@ index 84627cbd5b5b5..95a6a63caf047 100644
/*
* If the level is set to maximum, we can skip trying to get the read
* lock.
-@@ -1637,6 +1637,17 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
+@@ -1637,6 +1618,17 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
level = btrfs_header_level(b);
out:
@@ -120197,11 +180487,159 @@ index 84627cbd5b5b5..95a6a63caf047 100644
p->nodes[level] = b;
if (!p->skip_locking)
p->locks[level] = root_lock;
+@@ -1646,6 +1638,42 @@ out:
+ return b;
+ }
+
++/*
++ * Replace the extent buffer at the lowest level of the path with a cloned
++ * version. The purpose is to be able to use it safely, after releasing the
++ * commit root semaphore, even if relocation is happening in parallel, the
++ * transaction used for relocation is committed and the extent buffer is
++ * reallocated in the next transaction.
++ *
++ * This is used in a context where the caller does not prevent transaction
++ * commits from happening, either by holding a transaction handle or holding
++ * some lock, while it's doing searches through a commit root.
++ * At the moment it's only used for send operations.
++ */
++static int finish_need_commit_sem_search(struct btrfs_path *path)
++{
++ const int i = path->lowest_level;
++ const int slot = path->slots[i];
++ struct extent_buffer *lowest = path->nodes[i];
++ struct extent_buffer *clone;
++
++ ASSERT(path->need_commit_sem);
++
++ if (!lowest)
++ return 0;
++
++ lockdep_assert_held_read(&lowest->fs_info->commit_root_sem);
++
++ clone = btrfs_clone_extent_buffer(lowest);
++ if (!clone)
++ return -ENOMEM;
++
++ btrfs_release_path(path);
++ path->nodes[i] = clone;
++ path->slots[i] = slot;
++
++ return 0;
++}
+
+ /*
+ * btrfs_search_slot - look for a key in a tree and perform necessary
+@@ -1682,6 +1710,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+ const struct btrfs_key *key, struct btrfs_path *p,
+ int ins_len, int cow)
+ {
++ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct extent_buffer *b;
+ int slot;
+ int ret;
+@@ -1723,6 +1752,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+
+ min_write_lock_level = write_lock_level;
+
++ if (p->need_commit_sem) {
++ ASSERT(p->search_commit_root);
++ down_read(&fs_info->commit_root_sem);
++ }
++
+ again:
+ prev_cmp = -1;
+ b = btrfs_search_slot_get_root(root, p, write_lock_level);
+@@ -1917,6 +1951,16 @@ cow_done:
+ done:
+ if (ret < 0 && !p->skip_release_on_error)
+ btrfs_release_path(p);
++
++ if (p->need_commit_sem) {
++ int ret2;
++
++ ret2 = finish_need_commit_sem_search(p);
++ up_read(&fs_info->commit_root_sem);
++ if (ret2)
++ ret = ret2;
++ }
++
+ return ret;
+ }
+ ALLOW_ERROR_INJECTION(btrfs_search_slot, ERRNO);
+@@ -4385,7 +4429,9 @@ int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
+ int level;
+ struct extent_buffer *c;
+ struct extent_buffer *next;
++ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct btrfs_key key;
++ bool need_commit_sem = false;
+ u32 nritems;
+ int ret;
+ int i;
+@@ -4402,14 +4448,20 @@ again:
+
+ path->keep_locks = 1;
+
+- if (time_seq)
++ if (time_seq) {
+ ret = btrfs_search_old_slot(root, &key, path, time_seq);
+- else
++ } else {
++ if (path->need_commit_sem) {
++ path->need_commit_sem = 0;
++ need_commit_sem = true;
++ down_read(&fs_info->commit_root_sem);
++ }
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
++ }
+ path->keep_locks = 0;
+
+ if (ret < 0)
+- return ret;
++ goto done;
+
+ nritems = btrfs_header_nritems(path->nodes[0]);
+ /*
+@@ -4532,6 +4584,15 @@ again:
+ ret = 0;
+ done:
+ unlock_up(path, 0, 1, 0, NULL);
++ if (need_commit_sem) {
++ int ret2;
++
++ path->need_commit_sem = 1;
++ ret2 = finish_need_commit_sem_search(path);
++ up_read(&fs_info->commit_root_sem);
++ if (ret2)
++ ret = ret2;
++ }
+
+ return ret;
+ }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
-index c0cebcf745cef..b46409801647b 100644
+index c0cebcf745cef..21c44846b0022 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
-@@ -593,6 +593,9 @@ enum {
+@@ -142,6 +142,9 @@ enum {
+ BTRFS_FS_STATE_DEV_REPLACING,
+ /* The btrfs_fs_info created for self-tests */
+ BTRFS_FS_STATE_DUMMY_FS_INFO,
++
++ /* Indicates there was an error cleaning up a log tree. */
++ BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
+ };
+
+ #define BTRFS_BACKREF_REV_MAX 256
+@@ -568,7 +571,6 @@ enum {
+ /*
+ * Indicate that relocation of a chunk has started, it's set per chunk
+ * and is toggled between chunks.
+- * Set, tested and cleared while holding fs_info::send_reloc_lock.
+ */
+ BTRFS_FS_RELOC_RUNNING,
+
+@@ -593,6 +595,9 @@ enum {
/* Indicate whether there are any tree modification log users */
BTRFS_FS_TREE_MOD_LOG_USERS,
@@ -120211,7 +180649,34 @@ index c0cebcf745cef..b46409801647b 100644
#if BITS_PER_LONG == 32
/* Indicate if we have error/warn message printed on 32bit systems */
BTRFS_FS_32BIT_ERROR,
-@@ -1017,6 +1020,13 @@ struct btrfs_fs_info {
+@@ -665,6 +670,12 @@ struct btrfs_fs_info {
+
+ u64 generation;
+ u64 last_trans_committed;
++ /*
++ * Generation of the last transaction used for block group relocation
++ * since the filesystem was last mounted (or 0 if none happened yet).
++ * Must be written and read while holding btrfs_fs_info::commit_root_sem.
++ */
++ u64 last_reloc_trans;
+ u64 avg_delayed_ref_runtime;
+
+ /*
+@@ -994,13 +1005,6 @@ struct btrfs_fs_info {
+
+ struct crypto_shash *csum_shash;
+
+- spinlock_t send_reloc_lock;
+- /*
+- * Number of send operations in progress.
+- * Updated while holding fs_info::send_reloc_lock.
+- */
+- int send_in_progress;
+-
+ /* Type of exclusive operation running, protected by super_lock */
+ enum btrfs_exclusive_operation exclusive_operation;
+
+@@ -1017,6 +1021,13 @@ struct btrfs_fs_info {
spinlock_t treelog_bg_lock;
u64 treelog_bg;
@@ -120225,7 +180690,7 @@ index c0cebcf745cef..b46409801647b 100644
#ifdef CONFIG_BTRFS_FS_REF_VERIFY
spinlock_t ref_verify_lock;
struct rb_root block_tree;
-@@ -1091,8 +1101,15 @@ enum {
+@@ -1091,8 +1102,15 @@ enum {
BTRFS_ROOT_HAS_LOG_TREE,
/* Qgroup flushing is in progress */
BTRFS_ROOT_QGROUP_FLUSHING,
@@ -120241,7 +180706,18 @@ index c0cebcf745cef..b46409801647b 100644
/*
* Record swapped tree blocks of a subvolume tree for delayed subtree trace
* code. For detail check comment in fs/btrfs/qgroup.c.
-@@ -3842,6 +3859,11 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info)
+@@ -3563,6 +3581,10 @@ do { \
+ (errno), fmt, ##args); \
+ } while (0)
+
++#define BTRFS_FS_LOG_CLEANUP_ERROR(fs_info) \
++ (unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \
++ &(fs_info)->fs_state)))
++
+ __printf(5, 6)
+ __cold
+ void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function,
+@@ -3842,6 +3864,11 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info)
return fs_info->zoned != 0;
}
@@ -120300,10 +180776,48 @@ index d029be40ea6f0..bdbc310a8f8c5 100644
goto error;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
-index 355ea88d5c5f7..2180fcef56cab 100644
+index 355ea88d5c5f7..8cbed2f08d1bd 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
-@@ -1500,7 +1500,7 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
+@@ -441,17 +441,31 @@ static int csum_one_extent_buffer(struct extent_buffer *eb)
+ else
+ ret = btrfs_check_leaf_full(eb);
+
+- if (ret < 0) {
+- btrfs_print_tree(eb, 0);
++ if (ret < 0)
++ goto error;
++
++ /*
++ * Also check the generation, the eb reached here must be newer than
++ * last committed. Or something seriously wrong happened.
++ */
++ if (unlikely(btrfs_header_generation(eb) <= fs_info->last_trans_committed)) {
++ ret = -EUCLEAN;
+ btrfs_err(fs_info,
+- "block=%llu write time tree block corruption detected",
+- eb->start);
+- WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+- return ret;
++ "block=%llu bad generation, have %llu expect > %llu",
++ eb->start, btrfs_header_generation(eb),
++ fs_info->last_trans_committed);
++ goto error;
+ }
+ write_extent_buffer(eb, result, 0, fs_info->csum_size);
+
+ return 0;
++
++error:
++ btrfs_print_tree(eb, 0);
++ btrfs_err(fs_info, "block=%llu write time tree block corruption detected",
++ eb->start);
++ WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
++ return ret;
+ }
+
+ /* Checksum all dirty extent buffers in one bio_vec */
+@@ -1500,7 +1514,7 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
goto fail;
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
@@ -120312,7 +180826,17 @@ index 355ea88d5c5f7..2180fcef56cab 100644
set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
btrfs_check_and_init_root_item(&root->root_item);
}
-@@ -1731,6 +1731,14 @@ again:
+@@ -1724,13 +1738,22 @@ again:
+
+ ret = btrfs_insert_fs_root(fs_info, root);
+ if (ret) {
+- btrfs_put_root(root);
+- if (ret == -EEXIST)
++ if (ret == -EEXIST) {
++ btrfs_put_root(root);
+ goto again;
++ }
+ goto fail;
}
return root;
fail:
@@ -120327,7 +180851,15 @@ index 355ea88d5c5f7..2180fcef56cab 100644
btrfs_put_root(root);
return ERR_PTR(ret);
}
-@@ -2883,6 +2891,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
+@@ -2851,6 +2874,7 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
+ /* All successful */
+ fs_info->generation = generation;
+ fs_info->last_trans_committed = generation;
++ fs_info->last_reloc_trans = 0;
+
+ /* Always begin writing backup roots after the one being used */
+ if (backup_index < 0) {
+@@ -2883,6 +2907,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
spin_lock_init(&fs_info->buffer_lock);
spin_lock_init(&fs_info->unused_bgs_lock);
spin_lock_init(&fs_info->treelog_bg_lock);
@@ -120335,7 +180867,17 @@ index 355ea88d5c5f7..2180fcef56cab 100644
rwlock_init(&fs_info->tree_mod_log_lock);
mutex_init(&fs_info->unused_bg_unpin_mutex);
mutex_init(&fs_info->reclaim_bgs_lock);
-@@ -3228,12 +3237,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+@@ -2983,9 +3008,6 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
+ spin_lock_init(&fs_info->swapfile_pins_lock);
+ fs_info->swapfile_pins = RB_ROOT;
+
+- spin_lock_init(&fs_info->send_reloc_lock);
+- fs_info->send_in_progress = 0;
+-
+ fs_info->bg_reclaim_threshold = BTRFS_DEFAULT_RECLAIM_THRESH;
+ INIT_WORK(&fs_info->reclaim_bgs_work, btrfs_reclaim_bgs_work);
+ }
+@@ -3228,12 +3250,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
btrfs_init_btree_inode(fs_info);
@@ -120350,7 +180892,25 @@ index 355ea88d5c5f7..2180fcef56cab 100644
if (IS_ERR(disk_super)) {
err = PTR_ERR(disk_super);
goto fail_alloc;
-@@ -3465,7 +3474,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+@@ -3393,6 +3415,17 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+ }
+
+ if (sectorsize != PAGE_SIZE) {
++ /*
++ * V1 space cache has some hardcoded PAGE_SIZE usage, and is
++ * going to be deprecated.
++ *
++ * Force to use v2 cache for subpage case.
++ */
++ btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
++ btrfs_set_and_info(fs_info, FREE_SPACE_TREE,
++ "forcing free space tree for sector size %u with page size %lu",
++ sectorsize, PAGE_SIZE);
++
+ btrfs_warn(fs_info,
+ "read-write for sector size %u with page size %lu is experimental",
+ sectorsize, PAGE_SIZE);
+@@ -3465,7 +3498,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
* below in btrfs_init_dev_replace().
*/
btrfs_free_extra_devids(fs_devices);
@@ -120359,7 +180919,7 @@ index 355ea88d5c5f7..2180fcef56cab 100644
btrfs_err(fs_info, "failed to read devices");
goto fail_tree_roots;
}
-@@ -3556,7 +3565,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+@@ -3556,7 +3589,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
goto fail_sysfs;
}
@@ -120371,7 +180931,7 @@ index 355ea88d5c5f7..2180fcef56cab 100644
btrfs_warn(fs_info,
"writable mount is not allowed due to too many missing devices");
goto fail_sysfs;
-@@ -3647,6 +3659,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+@@ -3647,6 +3683,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
set_bit(BTRFS_FS_OPEN, &fs_info->flags);
@@ -120382,7 +180942,7 @@ index 355ea88d5c5f7..2180fcef56cab 100644
clear_oneshot:
btrfs_clear_oneshot_options(fs_info);
return 0;
-@@ -3968,11 +3984,23 @@ static void btrfs_end_empty_barrier(struct bio *bio)
+@@ -3968,11 +4008,23 @@ static void btrfs_end_empty_barrier(struct bio *bio)
*/
static void write_dev_flush(struct btrfs_device *device)
{
@@ -120407,7 +180967,7 @@ index 355ea88d5c5f7..2180fcef56cab 100644
bio_reset(bio);
bio->bi_end_io = btrfs_end_empty_barrier;
-@@ -4316,6 +4344,12 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
+@@ -4316,6 +4368,12 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
*/
kthread_park(fs_info->cleaner_kthread);
@@ -120610,7 +181170,7 @@ index 0ab456cb4bf80..514adc83577f0 100644
* So if we need to stop dropping the snapshot for whatever reason we
* need to make sure to add it back to the dead root list so that we
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
-index aaddd72253481..50a5cc4fd25b8 100644
+index aaddd72253481..96aeb16bd65c9 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3327,7 +3327,7 @@ static int alloc_new_bio(struct btrfs_inode *inode,
@@ -120622,7 +181182,26 @@ index aaddd72253481..50a5cc4fd25b8 100644
bio_set_dev(bio, bdev);
wbc_init_bio(wbc, bio);
}
-@@ -4284,6 +4284,12 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb)
+@@ -3561,7 +3561,6 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
+ u64 cur_end;
+ struct extent_map *em;
+ int ret = 0;
+- int nr = 0;
+ size_t pg_offset = 0;
+ size_t iosize;
+ size_t blocksize = inode->i_sb->s_blocksize;
+@@ -3727,9 +3726,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
+ end_bio_extent_readpage, 0,
+ this_bio_flag,
+ force_bio_submit);
+- if (!ret) {
+- nr++;
+- } else {
++ if (ret) {
+ unlock_extent(tree, cur, cur + iosize - 1);
+ end_page_read(page, false, cur, iosize);
+ goto out;
+@@ -4284,6 +4281,12 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb)
if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
return;
@@ -120635,7 +181214,7 @@ index aaddd72253481..50a5cc4fd25b8 100644
/*
* If we error out, we should add back the dirty_metadata_bytes
* to make it consistent.
-@@ -5120,6 +5126,9 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
+@@ -5120,6 +5123,9 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
int extent_writepages(struct address_space *mapping,
struct writeback_control *wbc)
{
@@ -120645,7 +181224,7 @@ index aaddd72253481..50a5cc4fd25b8 100644
int ret = 0;
struct extent_page_data epd = {
.bio_ctrl = { 0 },
-@@ -5127,7 +5136,15 @@ int extent_writepages(struct address_space *mapping,
+@@ -5127,7 +5133,15 @@ int extent_writepages(struct address_space *mapping,
.sync_io = wbc->sync_mode == WB_SYNC_ALL,
};
@@ -120661,7 +181240,7 @@ index aaddd72253481..50a5cc4fd25b8 100644
ASSERT(ret <= 0);
if (ret < 0) {
end_write_bio(&epd, ret);
-@@ -6530,6 +6547,14 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
+@@ -6530,6 +6544,14 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
return 0;
@@ -120676,7 +181255,7 @@ index aaddd72253481..50a5cc4fd25b8 100644
if (eb->fs_info->sectorsize < PAGE_SIZE)
return read_extent_buffer_subpage(eb, wait, mirror_num);
-@@ -6776,14 +6801,24 @@ static void assert_eb_page_uptodate(const struct extent_buffer *eb,
+@@ -6776,14 +6798,24 @@ static void assert_eb_page_uptodate(const struct extent_buffer *eb,
{
struct btrfs_fs_info *fs_info = eb->fs_info;
@@ -120704,8 +181283,279 @@ index aaddd72253481..50a5cc4fd25b8 100644
}
}
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index 53abdc280451b..f7ab6ba8238e1 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -117,7 +117,7 @@ struct btrfs_bio_ctrl {
+ */
+ struct extent_changeset {
+ /* How many bytes are set/cleared in this operation */
+- unsigned int bytes_changed;
++ u64 bytes_changed;
+
+ /* Changed ranges */
+ struct ulist range_changed;
+diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
+index 0b9401a5afd33..161a69d7e117e 100644
+--- a/fs/btrfs/file-item.c
++++ b/fs/btrfs/file-item.c
+@@ -303,7 +303,7 @@ found:
+ read_extent_buffer(path->nodes[0], dst, (unsigned long)item,
+ ret * csum_size);
+ out:
+- if (ret == -ENOENT)
++ if (ret == -ENOENT || ret == -EFBIG)
+ ret = 0;
+ return ret;
+ }
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index a1762363f61fa..ff578c934bbcf 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1709,7 +1709,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
+ * Fault pages before locking them in prepare_pages
+ * to avoid recursive lock
+ */
+- if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) {
++ if (unlikely(fault_in_iov_iter_readable(i, write_bytes))) {
+ ret = -EFAULT;
+ break;
+ }
+@@ -1903,16 +1903,17 @@ static ssize_t check_direct_IO(struct btrfs_fs_info *fs_info,
+
+ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
+ {
++ const bool is_sync_write = (iocb->ki_flags & IOCB_DSYNC);
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+ loff_t pos;
+ ssize_t written = 0;
+ ssize_t written_buffered;
++ size_t prev_left = 0;
+ loff_t endbyte;
+ ssize_t err;
+ unsigned int ilock_flags = 0;
+- struct iomap_dio *dio = NULL;
+
+ if (iocb->ki_flags & IOCB_NOWAIT)
+ ilock_flags |= BTRFS_ILOCK_TRY;
+@@ -1955,23 +1956,80 @@ relock:
+ goto buffered;
+ }
+
+- dio = __iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
+- 0);
++ /*
++ * We remove IOCB_DSYNC so that we don't deadlock when iomap_dio_rw()
++ * calls generic_write_sync() (through iomap_dio_complete()), because
++ * that results in calling fsync (btrfs_sync_file()) which will try to
++ * lock the inode in exclusive/write mode.
++ */
++ if (is_sync_write)
++ iocb->ki_flags &= ~IOCB_DSYNC;
+
+- btrfs_inode_unlock(inode, ilock_flags);
++ /*
++ * The iov_iter can be mapped to the same file range we are writing to.
++ * If that's the case, then we will deadlock in the iomap code, because
++ * it first calls our callback btrfs_dio_iomap_begin(), which will create
++ * an ordered extent, and after that it will fault in the pages that the
++ * iov_iter refers to. During the fault in we end up in the readahead
++ * pages code (starting at btrfs_readahead()), which will lock the range,
++ * find that ordered extent and then wait for it to complete (at
++ * btrfs_lock_and_flush_ordered_range()), resulting in a deadlock since
++ * obviously the ordered extent can never complete as we didn't submit
++ * yet the respective bio(s). This always happens when the buffer is
++ * memory mapped to the same file range, since the iomap DIO code always
++ * invalidates pages in the target file range (after starting and waiting
++ * for any writeback).
++ *
++ * So here we disable page faults in the iov_iter and then retry if we
++ * got -EFAULT, faulting in the pages before the retry.
++ */
++again:
++ from->nofault = true;
++ err = iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
++ IOMAP_DIO_PARTIAL, written);
++ from->nofault = false;
+
+- if (IS_ERR_OR_NULL(dio)) {
+- err = PTR_ERR_OR_ZERO(dio);
+- if (err < 0 && err != -ENOTBLK)
+- goto out;
+- } else {
+- written = iomap_dio_complete(dio);
++ /* No increment (+=) because iomap returns a cumulative value. */
++ if (err > 0)
++ written = err;
++
++ if (iov_iter_count(from) > 0 && (err == -EFAULT || err > 0)) {
++ const size_t left = iov_iter_count(from);
++ /*
++ * We have more data left to write. Try to fault in as many as
++ * possible of the remainder pages and retry. We do this without
++ * releasing and locking again the inode, to prevent races with
++ * truncate.
++ *
++ * Also, in case the iov refers to pages in the file range of the
++ * file we want to write to (due to a mmap), we could enter an
++ * infinite loop if we retry after faulting the pages in, since
++ * iomap will invalidate any pages in the range early on, before
++ * it tries to fault in the pages of the iov. So we keep track of
++ * how much was left of iov in the previous EFAULT and fallback
++ * to buffered IO in case we haven't made any progress.
++ */
++ if (left == prev_left) {
++ err = -ENOTBLK;
++ } else {
++ fault_in_iov_iter_readable(from, left);
++ prev_left = left;
++ goto again;
++ }
+ }
+
+- if (written < 0 || !iov_iter_count(from)) {
+- err = written;
++ btrfs_inode_unlock(inode, ilock_flags);
++
++ /*
++ * Add back IOCB_DSYNC. Our caller, btrfs_file_write_iter(), will do
++ * the fsync (call generic_write_sync()).
++ */
++ if (is_sync_write)
++ iocb->ki_flags |= IOCB_DSYNC;
++
++ /* If 'err' is -ENOTBLK then it means we must fallback to buffered IO. */
++ if ((err < 0 && err != -ENOTBLK) || !iov_iter_count(from))
+ goto out;
+- }
+
+ buffered:
+ pos = iocb->ki_pos;
+@@ -1996,7 +2054,7 @@ buffered:
+ invalidate_mapping_pages(file->f_mapping, pos >> PAGE_SHIFT,
+ endbyte >> PAGE_SHIFT);
+ out:
+- return written ? written : err;
++ return err < 0 ? err : written;
+ }
+
+ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
+@@ -2878,8 +2936,9 @@ out:
+ return ret;
+ }
+
+-static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
++static int btrfs_punch_hole(struct file *file, loff_t offset, loff_t len)
+ {
++ struct inode *inode = file_inode(file);
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct extent_state *cached_state = NULL;
+@@ -2911,6 +2970,10 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
+ goto out_only_mutex;
+ }
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_only_mutex;
++
+ lockstart = round_up(offset, btrfs_inode_sectorsize(BTRFS_I(inode)));
+ lockend = round_down(offset + len,
+ btrfs_inode_sectorsize(BTRFS_I(inode))) - 1;
+@@ -3351,7 +3414,7 @@ static long btrfs_fallocate(struct file *file, int mode,
+ return -EOPNOTSUPP;
+
+ if (mode & FALLOC_FL_PUNCH_HOLE)
+- return btrfs_punch_hole(inode, offset, len);
++ return btrfs_punch_hole(file, offset, len);
+
+ /*
+ * Only trigger disk allocation, don't trigger qgroup reserve
+@@ -3373,6 +3436,10 @@ static long btrfs_fallocate(struct file *file, int mode,
+ goto out;
+ }
+
++ ret = file_modified(file);
++ if (ret)
++ goto out;
++
+ /*
+ * TODO: Move these two operations after we have checked
+ * accurate reserved space, or fallocate can still fail but
+@@ -3650,6 +3717,8 @@ static int check_direct_read(struct btrfs_fs_info *fs_info,
+ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to)
+ {
+ struct inode *inode = file_inode(iocb->ki_filp);
++ size_t prev_left = 0;
++ ssize_t read = 0;
+ ssize_t ret;
+
+ if (fsverity_active(inode))
+@@ -3659,9 +3728,57 @@ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to)
+ return 0;
+
+ btrfs_inode_lock(inode, BTRFS_ILOCK_SHARED);
+- ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops, 0);
++again:
++ /*
++ * This is similar to what we do for direct IO writes, see the comment
++ * at btrfs_direct_write(), but we also disable page faults in addition
++ * to disabling them only at the iov_iter level. This is because when
++ * reading from a hole or prealloc extent, iomap calls iov_iter_zero(),
++ * which can still trigger page fault ins despite having set ->nofault
++ * to true of our 'to' iov_iter.
++ *
++ * The difference to direct IO writes is that we deadlock when trying
++ * to lock the extent range in the inode's tree during he page reads
++ * triggered by the fault in (while for writes it is due to waiting for
++ * our own ordered extent). This is because for direct IO reads,
++ * btrfs_dio_iomap_begin() returns with the extent range locked, which
++ * is only unlocked in the endio callback (end_bio_extent_readpage()).
++ */
++ pagefault_disable();
++ to->nofault = true;
++ ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
++ IOMAP_DIO_PARTIAL, read);
++ to->nofault = false;
++ pagefault_enable();
++
++ /* No increment (+=) because iomap returns a cumulative value. */
++ if (ret > 0)
++ read = ret;
++
++ if (iov_iter_count(to) > 0 && (ret == -EFAULT || ret > 0)) {
++ const size_t left = iov_iter_count(to);
++
++ if (left == prev_left) {
++ /*
++ * We didn't make any progress since the last attempt,
++ * fallback to a buffered read for the remainder of the
++ * range. This is just to avoid any possibility of looping
++ * for too long.
++ */
++ ret = read;
++ } else {
++ /*
++ * We made some progress since the last retry or this is
++ * the first time we are retrying. Fault in as many pages
++ * as possible and retry.
++ */
++ fault_in_iov_iter_writeable(to, left);
++ prev_left = left;
++ goto again;
++ }
++ }
+ btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
+- return ret;
++ return ret < 0 ? ret : read;
+ }
+
+ static ssize_t btrfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
-index 7c096ab9bb5eb..58053b5f0ce19 100644
+index 7c096ab9bb5eb..044d584c3467c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -60,8 +60,6 @@ struct btrfs_iget_args {
@@ -120717,7 +181567,15 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
ssize_t submitted;
struct extent_changeset *data_reserved;
};
-@@ -1151,7 +1149,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+@@ -1077,7 +1075,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+ int ret = 0;
+
+ if (btrfs_is_free_space_inode(inode)) {
+- WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+@@ -1151,7 +1148,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
* fails during the stage where it updates the bytenr of file extent
* items.
*/
@@ -120726,7 +181584,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
min_alloc_size = num_bytes;
else
min_alloc_size = fs_info->sectorsize;
-@@ -1187,8 +1185,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+@@ -1187,8 +1184,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
if (ret)
goto out_drop_extent_cache;
@@ -120736,7 +181594,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
ret = btrfs_reloc_clone_csums(inode, start,
cur_alloc_size);
/*
-@@ -1504,8 +1501,7 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page,
+@@ -1504,8 +1500,7 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page,
int *page_started, unsigned long *nr_written)
{
const bool is_space_ino = btrfs_is_free_space_inode(inode);
@@ -120746,7 +181604,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
const u64 range_bytes = end + 1 - start;
struct extent_io_tree *io_tree = &inode->io_tree;
u64 range_start = start;
-@@ -1867,8 +1863,7 @@ out_check:
+@@ -1867,8 +1862,7 @@ out_check:
btrfs_dec_nocow_writers(fs_info, disk_bytenr);
nocow = false;
@@ -120756,7 +181614,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
/*
* Error handled later, as we must prevent
* extent_clear_unlock_delalloc() in error handler
-@@ -1948,7 +1943,15 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
+@@ -1948,7 +1942,15 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
const bool zoned = btrfs_is_zoned(inode->root->fs_info);
if (should_nocow(inode, start, end)) {
@@ -120773,7 +181631,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
ret = run_delalloc_nocow(inode, locked_page, start, end,
page_started, nr_written);
} else if (!inode_can_compress(inode) ||
-@@ -2207,7 +2210,7 @@ void btrfs_clear_delalloc_extent(struct inode *vfs_inode,
+@@ -2207,7 +2209,7 @@ void btrfs_clear_delalloc_extent(struct inode *vfs_inode,
if (btrfs_is_testing(fs_info))
return;
@@ -120782,7 +181640,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
do_list && !(state->state & EXTENT_NORESERVE) &&
(*bits & EXTENT_CLEAR_DATA_RESV))
btrfs_free_reserved_data_space_noquota(fs_info, len);
-@@ -2532,7 +2535,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
+@@ -2532,7 +2534,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
goto mapit;
} else if (async && !skip_sum) {
/* csum items have already been cloned */
@@ -120791,7 +181649,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
goto mapit;
/* we're doing a write, do the async checksumming */
ret = btrfs_wq_submit_bio(inode, bio, mirror_num, bio_flags,
-@@ -3304,7 +3307,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_io_bio *io_bio, u32 bio_offset,
+@@ -3304,7 +3306,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_io_bio *io_bio, u32 bio_offset,
u64 file_offset = pg_off + page_offset(page);
int ret;
@@ -120800,7 +181658,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
test_range_bit(io_tree, file_offset,
file_offset + sectorsize - 1,
EXTENT_NODATASUM, 1, NULL)) {
-@@ -4005,7 +4008,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
+@@ -4005,7 +4007,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
* without delay
*/
if (!btrfs_is_free_space_inode(inode)
@@ -120809,7 +181667,21 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
&& !test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) {
btrfs_update_root_times(trans, root);
-@@ -7758,6 +7761,10 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
+@@ -4447,6 +4449,13 @@ int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry)
+ dest->root_key.objectid);
+ return -EPERM;
+ }
++ if (atomic_read(&dest->nr_swapfiles)) {
++ spin_unlock(&dest->root_item_lock);
++ btrfs_warn(fs_info,
++ "attempt to delete subvolume %llu with active swapfile",
++ root->root_key.objectid);
++ return -EPERM;
++ }
+ root_flags = btrfs_root_flags(&dest->root_item);
+ btrfs_set_root_flags(&dest->root_item,
+ root_flags | BTRFS_ROOT_SUBVOL_DEAD);
+@@ -7758,6 +7767,11 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
{
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct extent_map *em = *map;
@@ -120817,10 +181689,11 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
+ u64 block_start, orig_start, orig_block_len, ram_bytes;
+ bool can_nocow = false;
+ bool space_reserved = false;
++ u64 prev_len;
int ret = 0;
/*
-@@ -7772,9 +7779,6 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
+@@ -7772,9 +7786,6 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) ||
((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) &&
em->block_start != EXTENT_MAP_HOLE)) {
@@ -120830,7 +181703,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
type = BTRFS_ORDERED_PREALLOC;
else
-@@ -7784,53 +7788,92 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
+@@ -7784,53 +7795,91 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
if (can_nocow_extent(inode, start, &len, &orig_start,
&orig_block_len, &ram_bytes, false) == 1 &&
@@ -120840,6 +181713,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
+ can_nocow = true;
+ }
+
++ prev_len = len;
+ if (can_nocow) {
+ struct extent_map *em2;
@@ -120895,8 +181769,6 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
+ goto out;
+ }
+ } else {
-+ const u64 prev_len = len;
-+
+ /* Our caller expects us to free the input extent map. */
+ free_extent_map(em);
+ *map = NULL;
@@ -120928,7 +181800,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
+ * We have created our ordered extent, so we can now release our reservation
+ * for an outstanding extent.
+ */
-+ btrfs_delalloc_release_extents(BTRFS_I(inode), len);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), prev_len);
-skip_cow:
/*
@@ -120955,7 +181827,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
return ret;
}
-@@ -7872,18 +7915,6 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
+@@ -7872,18 +7921,6 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
if (!dio_data)
return -ENOMEM;
@@ -120974,7 +181846,42 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
iomap->private = dio_data;
-@@ -7962,7 +7993,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
+@@ -7924,6 +7961,34 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
+ }
+
+ len = min(len, em->len - (start - em->start));
++
++ /*
++ * If we have a NOWAIT request and the range contains multiple extents
++ * (or a mix of extents and holes), then we return -EAGAIN to make the
++ * caller fallback to a context where it can do a blocking (without
++ * NOWAIT) request. This way we avoid doing partial IO and returning
++ * success to the caller, which is not optimal for writes and for reads
++ * it can result in unexpected behaviour for an application.
++ *
++ * When doing a read, because we use IOMAP_DIO_PARTIAL when calling
++ * iomap_dio_rw(), we can end up returning less data then what the caller
++ * asked for, resulting in an unexpected, and incorrect, short read.
++ * That is, the caller asked to read N bytes and we return less than that,
++ * which is wrong unless we are crossing EOF. This happens if we get a
++ * page fault error when trying to fault in pages for the buffer that is
++ * associated to the struct iov_iter passed to iomap_dio_rw(), and we
++ * have previously submitted bios for other extents in the range, in
++ * which case iomap_dio_rw() may return us EIOCBQUEUED if not all of
++ * those bios have completed by the time we get the page fault error,
++ * which we return back to our caller - we should only return EIOCBQUEUED
++ * after we have submitted bios for all the extents in the range.
++ */
++ if ((flags & IOMAP_NOWAIT) && len < length) {
++ free_extent_map(em);
++ ret = -EAGAIN;
++ goto unlock_err;
++ }
++
+ if (write) {
+ ret = btrfs_get_blocks_direct_write(&em, inode, dio_data,
+ start, len);
+@@ -7962,7 +8027,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
iomap->type = IOMAP_MAPPED;
}
iomap->offset = start;
@@ -120983,7 +181890,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
iomap->length = len;
if (write && btrfs_use_zone_append(BTRFS_I(inode), em->block_start))
-@@ -7976,14 +8007,8 @@ unlock_err:
+@@ -7976,14 +8041,8 @@ unlock_err:
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
&cached_state);
err:
@@ -121000,7 +181907,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
return ret;
}
-@@ -8013,14 +8038,8 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length,
+@@ -8013,14 +8072,8 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length,
ret = -ENOTBLK;
}
@@ -121016,7 +181923,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
out:
kfree(dio_data);
iomap->private = NULL;
-@@ -10581,9 +10600,19 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis,
+@@ -10581,9 +10634,19 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis,
struct btrfs_swap_info *bsi)
{
unsigned long nr_pages;
@@ -121036,7 +181943,7 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
first_ppage = ALIGN(bsi->block_start, PAGE_SIZE) >> PAGE_SHIFT;
next_ppage = ALIGN_DOWN(bsi->block_start + bsi->block_len,
PAGE_SIZE) >> PAGE_SHIFT;
-@@ -10591,6 +10620,7 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis,
+@@ -10591,6 +10654,7 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis,
if (first_ppage >= next_ppage)
return 0;
nr_pages = next_ppage - first_ppage;
@@ -121044,8 +181951,32 @@ index 7c096ab9bb5eb..58053b5f0ce19 100644
first_ppage_reported = first_ppage;
if (bsi->start == 0)
+@@ -10691,8 +10755,23 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
+ * set. We use this counter to prevent snapshots. We must increment it
+ * before walking the extents because we don't want a concurrent
+ * snapshot to run after we've already checked the extents.
++ *
++ * It is possible that subvolume is marked for deletion but still not
++ * removed yet. To prevent this race, we check the root status before
++ * activating the swapfile.
+ */
++ spin_lock(&root->root_item_lock);
++ if (btrfs_root_dead(root)) {
++ spin_unlock(&root->root_item_lock);
++
++ btrfs_exclop_finish(fs_info);
++ btrfs_warn(fs_info,
++ "cannot activate swapfile because subvolume %llu is being deleted",
++ root->root_key.objectid);
++ return -EPERM;
++ }
+ atomic_inc(&root->nr_swapfiles);
++ spin_unlock(&root->root_item_lock);
+
+ isize = ALIGN_DOWN(inode->i_size, fs_info->sectorsize);
+
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
-index cc61813213d83..6a863b3f6de03 100644
+index cc61813213d83..bf53af8694f8e 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -775,10 +775,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
@@ -121060,7 +181991,19 @@ index cc61813213d83..6a863b3f6de03 100644
ret = btrfs_commit_transaction(trans);
if (ret)
-@@ -3098,10 +3095,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
+@@ -2261,9 +2258,8 @@ static noinline int search_ioctl(struct inode *inode,
+ key.offset = sk->min_offset;
+
+ while (1) {
+- ret = fault_in_pages_writeable(ubuf + sk_offset,
+- *buf_size - sk_offset);
+- if (ret)
++ ret = -EFAULT;
++ if (fault_in_writeable(ubuf + sk_offset, *buf_size - sk_offset))
+ break;
+
+ ret = btrfs_search_forward(root, &key, path, sk->min_transid);
+@@ -3098,10 +3094,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
btrfs_inode_lock(inode, 0);
err = btrfs_delete_subvolume(dir, dentry);
btrfs_inode_unlock(inode, 0);
@@ -121202,10 +182145,24 @@ index db680f5be745a..2c803108ea944 100644
if (ret) {
diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c
-index 9b0814318e726..c71e49782e86d 100644
+index 9b0814318e726..fa60af00ebca2 100644
--- a/fs/btrfs/reflink.c
+++ b/fs/btrfs/reflink.c
-@@ -649,7 +649,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len,
+@@ -505,8 +505,11 @@ process_slot:
+ */
+ ASSERT(key.offset == 0);
+ ASSERT(datal <= fs_info->sectorsize);
+- if (key.offset != 0 || datal > fs_info->sectorsize)
+- return -EUCLEAN;
++ if (WARN_ON(key.offset != 0) ||
++ WARN_ON(datal > fs_info->sectorsize)) {
++ ret = -EUCLEAN;
++ goto out;
++ }
+
+ ret = clone_copy_inline_extent(inode, path, &new_key,
+ drop_start, datal, size,
+@@ -649,7 +652,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len,
static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
struct inode *dst, u64 dst_loff)
{
@@ -121215,7 +182172,7 @@ index 9b0814318e726..c71e49782e86d 100644
struct btrfs_root *root_dst = BTRFS_I(dst)->root;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
-index 914d403b4415d..a050f9748fa7f 100644
+index 914d403b4415d..a6661f2ad2c00 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2852,31 +2852,6 @@ static noinline_for_stack int prealloc_file_extent_cluster(
@@ -121290,7 +182247,43 @@ index 914d403b4415d..a050f9748fa7f 100644
btrfs_mark_buffer_dirty(leaf);
out:
btrfs_free_path(path);
-@@ -3998,6 +3967,19 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start)
+@@ -3885,25 +3854,14 @@ out:
+ * 0 success
+ * -EINPROGRESS operation is already in progress, that's probably a bug
+ * -ECANCELED cancellation request was set before the operation started
+- * -EAGAIN can not start because there are ongoing send operations
+ */
+ static int reloc_chunk_start(struct btrfs_fs_info *fs_info)
+ {
+- spin_lock(&fs_info->send_reloc_lock);
+- if (fs_info->send_in_progress) {
+- btrfs_warn_rl(fs_info,
+-"cannot run relocation while send operations are in progress (%d in progress)",
+- fs_info->send_in_progress);
+- spin_unlock(&fs_info->send_reloc_lock);
+- return -EAGAIN;
+- }
+ if (test_and_set_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags)) {
+ /* This should not happen */
+- spin_unlock(&fs_info->send_reloc_lock);
+ btrfs_err(fs_info, "reloc already running, cannot start");
+ return -EINPROGRESS;
+ }
+- spin_unlock(&fs_info->send_reloc_lock);
+
+ if (atomic_read(&fs_info->reloc_cancel_req) > 0) {
+ btrfs_info(fs_info, "chunk relocation canceled on start");
+@@ -3925,9 +3883,7 @@ static void reloc_chunk_end(struct btrfs_fs_info *fs_info)
+ /* Requested after start, clear bit first so any waiters can continue */
+ if (atomic_read(&fs_info->reloc_cancel_req) > 0)
+ btrfs_info(fs_info, "chunk relocation canceled during operation");
+- spin_lock(&fs_info->send_reloc_lock);
+ clear_and_wake_up_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags);
+- spin_unlock(&fs_info->send_reloc_lock);
+ atomic_set(&fs_info->reloc_cancel_req, 0);
+ }
+
+@@ -3998,6 +3954,19 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start)
int rw = 0;
int err = 0;
@@ -121310,7 +182303,7 @@ index 914d403b4415d..a050f9748fa7f 100644
bg = btrfs_lookup_block_group(fs_info, group_start);
if (!bg)
return -ENOENT;
-@@ -4386,8 +4368,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
+@@ -4386,8 +4355,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
if (!rc)
return 0;
@@ -121372,10 +182365,61 @@ index 088641ba7a8e6..62f4bafbe54bb 100644
struct scrub_recover *recover;
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
-index 72f9b865e8479..5612e8bf2ace4 100644
+index 72f9b865e8479..4d2c6ce29fe58 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
-@@ -4978,6 +4978,10 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
+@@ -24,6 +24,7 @@
+ #include "transaction.h"
+ #include "compression.h"
+ #include "xattr.h"
++#include "print-tree.h"
+
+ /*
+ * Maximum number of references an extent can have in order for us to attempt to
+@@ -95,6 +96,15 @@ struct send_ctx {
+ struct btrfs_path *right_path;
+ struct btrfs_key *cmp_key;
+
++ /*
++ * Keep track of the generation of the last transaction that was used
++ * for relocating a block group. This is periodically checked in order
++ * to detect if a relocation happened since the last check, so that we
++ * don't operate on stale extent buffers for nodes (level >= 1) or on
++ * stale disk_bytenr values of file extent items.
++ */
++ u64 last_reloc_trans;
++
+ /*
+ * infos of the currently processed inode. In case of deleted inodes,
+ * these are the values from the deleted inode.
+@@ -1415,6 +1425,26 @@ static int find_extent_clone(struct send_ctx *sctx,
+ if (ret < 0)
+ goto out;
+
++ down_read(&fs_info->commit_root_sem);
++ if (fs_info->last_reloc_trans > sctx->last_reloc_trans) {
++ /*
++ * A transaction commit for a transaction in which block group
++ * relocation was done just happened.
++ * The disk_bytenr of the file extent item we processed is
++ * possibly stale, referring to the extent's location before
++ * relocation. So act as if we haven't found any clone sources
++ * and fallback to write commands, which will read the correct
++ * data from the new extent location. Otherwise we will fail
++ * below because we haven't found our own back reference or we
++ * could be getting incorrect sources in case the old extent
++ * was already reallocated after the relocation.
++ */
++ up_read(&fs_info->commit_root_sem);
++ ret = -ENOENT;
++ goto out;
++ }
++ up_read(&fs_info->commit_root_sem);
++
+ if (!backref_ctx.found_itself) {
+ /* found a bug in backref code? */
+ ret = -EIO;
+@@ -4978,6 +5008,10 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
lock_page(page);
if (!PageUptodate(page)) {
unlock_page(page);
@@ -121386,6 +182430,560 @@ index 72f9b865e8479..5612e8bf2ace4 100644
put_page(page);
ret = -EIO;
break;
+@@ -6592,6 +6626,50 @@ static int changed_cb(struct btrfs_path *left_path,
+ {
+ int ret = 0;
+
++ /*
++ * We can not hold the commit root semaphore here. This is because in
++ * the case of sending and receiving to the same filesystem, using a
++ * pipe, could result in a deadlock:
++ *
++ * 1) The task running send blocks on the pipe because it's full;
++ *
++ * 2) The task running receive, which is the only consumer of the pipe,
++ * is waiting for a transaction commit (for example due to a space
++ * reservation when doing a write or triggering a transaction commit
++ * when creating a subvolume);
++ *
++ * 3) The transaction is waiting to write lock the commit root semaphore,
++ * but can not acquire it since it's being held at 1).
++ *
++ * Down this call chain we write to the pipe through kernel_write().
++ * The same type of problem can also happen when sending to a file that
++ * is stored in the same filesystem - when reserving space for a write
++ * into the file, we can trigger a transaction commit.
++ *
++ * Our caller has supplied us with clones of leaves from the send and
++ * parent roots, so we're safe here from a concurrent relocation and
++ * further reallocation of metadata extents while we are here. Below we
++ * also assert that the leaves are clones.
++ */
++ lockdep_assert_not_held(&sctx->send_root->fs_info->commit_root_sem);
++
++ /*
++ * We always have a send root, so left_path is never NULL. We will not
++ * have a leaf when we have reached the end of the send root but have
++ * not yet reached the end of the parent root.
++ */
++ if (left_path->nodes[0])
++ ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED,
++ &left_path->nodes[0]->bflags));
++ /*
++ * When doing a full send we don't have a parent root, so right_path is
++ * NULL. When doing an incremental send, we may have reached the end of
++ * the parent root already, so we don't have a leaf at right_path.
++ */
++ if (right_path && right_path->nodes[0])
++ ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED,
++ &right_path->nodes[0]->bflags));
++
+ if (result == BTRFS_COMPARE_TREE_SAME) {
+ if (key->type == BTRFS_INODE_REF_KEY ||
+ key->type == BTRFS_INODE_EXTREF_KEY) {
+@@ -6638,14 +6716,46 @@ out:
+ return ret;
+ }
+
++static int search_key_again(const struct send_ctx *sctx,
++ struct btrfs_root *root,
++ struct btrfs_path *path,
++ const struct btrfs_key *key)
++{
++ int ret;
++
++ if (!path->need_commit_sem)
++ lockdep_assert_held_read(&root->fs_info->commit_root_sem);
++
++ /*
++ * Roots used for send operations are readonly and no one can add,
++ * update or remove keys from them, so we should be able to find our
++ * key again. The only exception is deduplication, which can operate on
++ * readonly roots and add, update or remove keys to/from them - but at
++ * the moment we don't allow it to run in parallel with send.
++ */
++ ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
++ ASSERT(ret <= 0);
++ if (ret > 0) {
++ btrfs_print_tree(path->nodes[path->lowest_level], false);
++ btrfs_err(root->fs_info,
++"send: key (%llu %u %llu) not found in %s root %llu, lowest_level %d, slot %d",
++ key->objectid, key->type, key->offset,
++ (root == sctx->parent_root ? "parent" : "send"),
++ root->root_key.objectid, path->lowest_level,
++ path->slots[path->lowest_level]);
++ return -EUCLEAN;
++ }
++
++ return ret;
++}
++
+ static int full_send_tree(struct send_ctx *sctx)
+ {
+ int ret;
+ struct btrfs_root *send_root = sctx->send_root;
+ struct btrfs_key key;
++ struct btrfs_fs_info *fs_info = send_root->fs_info;
+ struct btrfs_path *path;
+- struct extent_buffer *eb;
+- int slot;
+
+ path = alloc_path_for_send();
+ if (!path)
+@@ -6656,6 +6766,10 @@ static int full_send_tree(struct send_ctx *sctx)
+ key.type = BTRFS_INODE_ITEM_KEY;
+ key.offset = 0;
+
++ down_read(&fs_info->commit_root_sem);
++ sctx->last_reloc_trans = fs_info->last_reloc_trans;
++ up_read(&fs_info->commit_root_sem);
++
+ ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0);
+ if (ret < 0)
+ goto out;
+@@ -6663,15 +6777,35 @@ static int full_send_tree(struct send_ctx *sctx)
+ goto out_finish;
+
+ while (1) {
+- eb = path->nodes[0];
+- slot = path->slots[0];
+- btrfs_item_key_to_cpu(eb, &key, slot);
++ btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+
+ ret = changed_cb(path, NULL, &key,
+ BTRFS_COMPARE_TREE_NEW, sctx);
+ if (ret < 0)
+ goto out;
+
++ down_read(&fs_info->commit_root_sem);
++ if (fs_info->last_reloc_trans > sctx->last_reloc_trans) {
++ sctx->last_reloc_trans = fs_info->last_reloc_trans;
++ up_read(&fs_info->commit_root_sem);
++ /*
++ * A transaction used for relocating a block group was
++ * committed or is about to finish its commit. Release
++ * our path (leaf) and restart the search, so that we
++ * avoid operating on any file extent items that are
++ * stale, with a disk_bytenr that reflects a pre
++ * relocation value. This way we avoid as much as
++ * possible to fallback to regular writes when checking
++ * if we can clone file ranges.
++ */
++ btrfs_release_path(path);
++ ret = search_key_again(sctx, send_root, path, &key);
++ if (ret < 0)
++ goto out;
++ } else {
++ up_read(&fs_info->commit_root_sem);
++ }
++
+ ret = btrfs_next_item(send_root, path);
+ if (ret < 0)
+ goto out;
+@@ -6689,6 +6823,20 @@ out:
+ return ret;
+ }
+
++static int replace_node_with_clone(struct btrfs_path *path, int level)
++{
++ struct extent_buffer *clone;
++
++ clone = btrfs_clone_extent_buffer(path->nodes[level]);
++ if (!clone)
++ return -ENOMEM;
++
++ free_extent_buffer(path->nodes[level]);
++ path->nodes[level] = clone;
++
++ return 0;
++}
++
+ static int tree_move_down(struct btrfs_path *path, int *level, u64 reada_min_gen)
+ {
+ struct extent_buffer *eb;
+@@ -6698,6 +6846,8 @@ static int tree_move_down(struct btrfs_path *path, int *level, u64 reada_min_gen
+ u64 reada_max;
+ u64 reada_done = 0;
+
++ lockdep_assert_held_read(&parent->fs_info->commit_root_sem);
++
+ BUG_ON(*level == 0);
+ eb = btrfs_read_node_slot(parent, slot);
+ if (IS_ERR(eb))
+@@ -6721,6 +6871,10 @@ static int tree_move_down(struct btrfs_path *path, int *level, u64 reada_min_gen
+ path->nodes[*level - 1] = eb;
+ path->slots[*level - 1] = 0;
+ (*level)--;
++
++ if (*level == 0)
++ return replace_node_with_clone(path, 0);
++
+ return 0;
+ }
+
+@@ -6734,8 +6888,10 @@ static int tree_move_next_or_upnext(struct btrfs_path *path,
+ path->slots[*level]++;
+
+ while (path->slots[*level] >= nritems) {
+- if (*level == root_level)
++ if (*level == root_level) {
++ path->slots[*level] = nritems - 1;
+ return -1;
++ }
+
+ /* move upnext */
+ path->slots[*level] = 0;
+@@ -6767,14 +6923,20 @@ static int tree_advance(struct btrfs_path *path,
+ } else {
+ ret = tree_move_down(path, level, reada_min_gen);
+ }
+- if (ret >= 0) {
+- if (*level == 0)
+- btrfs_item_key_to_cpu(path->nodes[*level], key,
+- path->slots[*level]);
+- else
+- btrfs_node_key_to_cpu(path->nodes[*level], key,
+- path->slots[*level]);
+- }
++
++ /*
++ * Even if we have reached the end of a tree, ret is -1, update the key
++ * anyway, so that in case we need to restart due to a block group
++ * relocation, we can assert that the last key of the root node still
++ * exists in the tree.
++ */
++ if (*level == 0)
++ btrfs_item_key_to_cpu(path->nodes[*level], key,
++ path->slots[*level]);
++ else
++ btrfs_node_key_to_cpu(path->nodes[*level], key,
++ path->slots[*level]);
++
+ return ret;
+ }
+
+@@ -6803,6 +6965,97 @@ static int tree_compare_item(struct btrfs_path *left_path,
+ return 0;
+ }
+
++/*
++ * A transaction used for relocating a block group was committed or is about to
++ * finish its commit. Release our paths and restart the search, so that we are
++ * not using stale extent buffers:
++ *
++ * 1) For levels > 0, we are only holding references of extent buffers, without
++ * any locks on them, which does not prevent them from having been relocated
++ * and reallocated after the last time we released the commit root semaphore.
++ * The exception are the root nodes, for which we always have a clone, see
++ * the comment at btrfs_compare_trees();
++ *
++ * 2) For leaves, level 0, we are holding copies (clones) of extent buffers, so
++ * we are safe from the concurrent relocation and reallocation. However they
++ * can have file extent items with a pre relocation disk_bytenr value, so we
++ * restart the start from the current commit roots and clone the new leaves so
++ * that we get the post relocation disk_bytenr values. Not doing so, could
++ * make us clone the wrong data in case there are new extents using the old
++ * disk_bytenr that happen to be shared.
++ */
++static int restart_after_relocation(struct btrfs_path *left_path,
++ struct btrfs_path *right_path,
++ const struct btrfs_key *left_key,
++ const struct btrfs_key *right_key,
++ int left_level,
++ int right_level,
++ const struct send_ctx *sctx)
++{
++ int root_level;
++ int ret;
++
++ lockdep_assert_held_read(&sctx->send_root->fs_info->commit_root_sem);
++
++ btrfs_release_path(left_path);
++ btrfs_release_path(right_path);
++
++ /*
++ * Since keys can not be added or removed to/from our roots because they
++ * are readonly and we do not allow deduplication to run in parallel
++ * (which can add, remove or change keys), the layout of the trees should
++ * not change.
++ */
++ left_path->lowest_level = left_level;
++ ret = search_key_again(sctx, sctx->send_root, left_path, left_key);
++ if (ret < 0)
++ return ret;
++
++ right_path->lowest_level = right_level;
++ ret = search_key_again(sctx, sctx->parent_root, right_path, right_key);
++ if (ret < 0)
++ return ret;
++
++ /*
++ * If the lowest level nodes are leaves, clone them so that they can be
++ * safely used by changed_cb() while not under the protection of the
++ * commit root semaphore, even if relocation and reallocation happens in
++ * parallel.
++ */
++ if (left_level == 0) {
++ ret = replace_node_with_clone(left_path, 0);
++ if (ret < 0)
++ return ret;
++ }
++
++ if (right_level == 0) {
++ ret = replace_node_with_clone(right_path, 0);
++ if (ret < 0)
++ return ret;
++ }
++
++ /*
++ * Now clone the root nodes (unless they happen to be the leaves we have
++ * already cloned). This is to protect against concurrent snapshotting of
++ * the send and parent roots (see the comment at btrfs_compare_trees()).
++ */
++ root_level = btrfs_header_level(sctx->send_root->commit_root);
++ if (root_level > 0) {
++ ret = replace_node_with_clone(left_path, root_level);
++ if (ret < 0)
++ return ret;
++ }
++
++ root_level = btrfs_header_level(sctx->parent_root->commit_root);
++ if (root_level > 0) {
++ ret = replace_node_with_clone(right_path, root_level);
++ if (ret < 0)
++ return ret;
++ }
++
++ return 0;
++}
++
+ /*
+ * This function compares two trees and calls the provided callback for
+ * every changed/new/deleted item it finds.
+@@ -6831,10 +7084,10 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ int right_root_level;
+ int left_level;
+ int right_level;
+- int left_end_reached;
+- int right_end_reached;
+- int advance_left;
+- int advance_right;
++ int left_end_reached = 0;
++ int right_end_reached = 0;
++ int advance_left = 0;
++ int advance_right = 0;
+ u64 left_blockptr;
+ u64 right_blockptr;
+ u64 left_gen;
+@@ -6902,12 +7155,18 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ down_read(&fs_info->commit_root_sem);
+ left_level = btrfs_header_level(left_root->commit_root);
+ left_root_level = left_level;
++ /*
++ * We clone the root node of the send and parent roots to prevent races
++ * with snapshot creation of these roots. Snapshot creation COWs the
++ * root node of a tree, so after the transaction is committed the old
++ * extent can be reallocated while this send operation is still ongoing.
++ * So we clone them, under the commit root semaphore, to be race free.
++ */
+ left_path->nodes[left_level] =
+ btrfs_clone_extent_buffer(left_root->commit_root);
+ if (!left_path->nodes[left_level]) {
+- up_read(&fs_info->commit_root_sem);
+ ret = -ENOMEM;
+- goto out;
++ goto out_unlock;
+ }
+
+ right_level = btrfs_header_level(right_root->commit_root);
+@@ -6915,9 +7174,8 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ right_path->nodes[right_level] =
+ btrfs_clone_extent_buffer(right_root->commit_root);
+ if (!right_path->nodes[right_level]) {
+- up_read(&fs_info->commit_root_sem);
+ ret = -ENOMEM;
+- goto out;
++ goto out_unlock;
+ }
+ /*
+ * Our right root is the parent root, while the left root is the "send"
+@@ -6927,7 +7185,6 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ * will need to read them at some point.
+ */
+ reada_min_gen = btrfs_header_generation(right_root->commit_root);
+- up_read(&fs_info->commit_root_sem);
+
+ if (left_level == 0)
+ btrfs_item_key_to_cpu(left_path->nodes[left_level],
+@@ -6942,11 +7199,26 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ btrfs_node_key_to_cpu(right_path->nodes[right_level],
+ &right_key, right_path->slots[right_level]);
+
+- left_end_reached = right_end_reached = 0;
+- advance_left = advance_right = 0;
++ sctx->last_reloc_trans = fs_info->last_reloc_trans;
+
+ while (1) {
+- cond_resched();
++ if (need_resched() ||
++ rwsem_is_contended(&fs_info->commit_root_sem)) {
++ up_read(&fs_info->commit_root_sem);
++ cond_resched();
++ down_read(&fs_info->commit_root_sem);
++ }
++
++ if (fs_info->last_reloc_trans > sctx->last_reloc_trans) {
++ ret = restart_after_relocation(left_path, right_path,
++ &left_key, &right_key,
++ left_level, right_level,
++ sctx);
++ if (ret < 0)
++ goto out_unlock;
++ sctx->last_reloc_trans = fs_info->last_reloc_trans;
++ }
++
+ if (advance_left && !left_end_reached) {
+ ret = tree_advance(left_path, &left_level,
+ left_root_level,
+@@ -6955,7 +7227,7 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ if (ret == -1)
+ left_end_reached = ADVANCE;
+ else if (ret < 0)
+- goto out;
++ goto out_unlock;
+ advance_left = 0;
+ }
+ if (advance_right && !right_end_reached) {
+@@ -6966,54 +7238,55 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ if (ret == -1)
+ right_end_reached = ADVANCE;
+ else if (ret < 0)
+- goto out;
++ goto out_unlock;
+ advance_right = 0;
+ }
+
+ if (left_end_reached && right_end_reached) {
+ ret = 0;
+- goto out;
++ goto out_unlock;
+ } else if (left_end_reached) {
+ if (right_level == 0) {
++ up_read(&fs_info->commit_root_sem);
+ ret = changed_cb(left_path, right_path,
+ &right_key,
+ BTRFS_COMPARE_TREE_DELETED,
+ sctx);
+ if (ret < 0)
+ goto out;
++ down_read(&fs_info->commit_root_sem);
+ }
+ advance_right = ADVANCE;
+ continue;
+ } else if (right_end_reached) {
+ if (left_level == 0) {
++ up_read(&fs_info->commit_root_sem);
+ ret = changed_cb(left_path, right_path,
+ &left_key,
+ BTRFS_COMPARE_TREE_NEW,
+ sctx);
+ if (ret < 0)
+ goto out;
++ down_read(&fs_info->commit_root_sem);
+ }
+ advance_left = ADVANCE;
+ continue;
+ }
+
+ if (left_level == 0 && right_level == 0) {
++ up_read(&fs_info->commit_root_sem);
+ cmp = btrfs_comp_cpu_keys(&left_key, &right_key);
+ if (cmp < 0) {
+ ret = changed_cb(left_path, right_path,
+ &left_key,
+ BTRFS_COMPARE_TREE_NEW,
+ sctx);
+- if (ret < 0)
+- goto out;
+ advance_left = ADVANCE;
+ } else if (cmp > 0) {
+ ret = changed_cb(left_path, right_path,
+ &right_key,
+ BTRFS_COMPARE_TREE_DELETED,
+ sctx);
+- if (ret < 0)
+- goto out;
+ advance_right = ADVANCE;
+ } else {
+ enum btrfs_compare_tree_result result;
+@@ -7027,11 +7300,13 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ result = BTRFS_COMPARE_TREE_SAME;
+ ret = changed_cb(left_path, right_path,
+ &left_key, result, sctx);
+- if (ret < 0)
+- goto out;
+ advance_left = ADVANCE;
+ advance_right = ADVANCE;
+ }
++
++ if (ret < 0)
++ goto out;
++ down_read(&fs_info->commit_root_sem);
+ } else if (left_level == right_level) {
+ cmp = btrfs_comp_cpu_keys(&left_key, &right_key);
+ if (cmp < 0) {
+@@ -7071,6 +7346,8 @@ static int btrfs_compare_trees(struct btrfs_root *left_root,
+ }
+ }
+
++out_unlock:
++ up_read(&fs_info->commit_root_sem);
+ out:
+ btrfs_free_path(left_path);
+ btrfs_free_path(right_path);
+@@ -7409,21 +7686,7 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
+ if (ret)
+ goto out;
+
+- spin_lock(&fs_info->send_reloc_lock);
+- if (test_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags)) {
+- spin_unlock(&fs_info->send_reloc_lock);
+- btrfs_warn_rl(fs_info,
+- "cannot run send because a relocation operation is in progress");
+- ret = -EAGAIN;
+- goto out;
+- }
+- fs_info->send_in_progress++;
+- spin_unlock(&fs_info->send_reloc_lock);
+-
+ ret = send_subvol(sctx);
+- spin_lock(&fs_info->send_reloc_lock);
+- fs_info->send_in_progress--;
+- spin_unlock(&fs_info->send_reloc_lock);
+ if (ret < 0)
+ goto out;
+
+diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
+index aa5be0b24987a..5ed66a794e577 100644
+--- a/fs/btrfs/space-info.c
++++ b/fs/btrfs/space-info.c
+@@ -1054,7 +1054,6 @@ static void btrfs_preempt_reclaim_metadata_space(struct work_struct *work)
+ trans_rsv->reserved;
+ if (block_rsv_size < space_info->bytes_may_use)
+ delalloc_size = space_info->bytes_may_use - block_rsv_size;
+- spin_unlock(&space_info->lock);
+
+ /*
+ * We don't want to include the global_rsv in our calculation,
+@@ -1085,6 +1084,8 @@ static void btrfs_preempt_reclaim_metadata_space(struct work_struct *work)
+ flush = FLUSH_DELAYED_REFS_NR;
+ }
+
++ spin_unlock(&space_info->lock);
++
+ /*
+ * We don't want to reclaim everything, just a portion, so scale
+ * down the to_reclaim by 1/4. If it takes us down to 0,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 537d90bf5d844..7f91d62c2225a 100644
--- a/fs/btrfs/super.c
@@ -121436,10 +183034,21 @@ index 537d90bf5d844..7f91d62c2225a 100644
}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
-index 14b9fdc8aaa9a..9a6009108ea55 100644
+index 14b9fdc8aaa9a..642cd2b55fa08 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
-@@ -846,7 +846,37 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
+@@ -163,6 +163,10 @@ static noinline void switch_commit_roots(struct btrfs_trans_handle *trans)
+ struct btrfs_caching_control *caching_ctl, *next;
+
+ down_write(&fs_info->commit_root_sem);
++
++ if (test_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags))
++ fs_info->last_reloc_trans = trans->transid;
++
+ list_for_each_entry_safe(root, tmp, &cur_trans->switch_commits,
+ dirty_list) {
+ list_del_init(&root->dirty_list);
+@@ -846,7 +850,37 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
static noinline void wait_for_commit(struct btrfs_transaction *commit,
const enum btrfs_trans_state min_state)
{
@@ -121478,7 +183087,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
}
int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
-@@ -1310,6 +1340,32 @@ again:
+@@ -1310,6 +1344,32 @@ again:
return 0;
}
@@ -121511,7 +183120,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
/*
* dead roots are old snapshots that need to be deleted. This allocates
* a dirty root struct and adds it into the list of dead roots that need to
-@@ -1322,7 +1378,12 @@ void btrfs_add_dead_root(struct btrfs_root *root)
+@@ -1322,7 +1382,12 @@ void btrfs_add_dead_root(struct btrfs_root *root)
spin_lock(&fs_info->trans_lock);
if (list_empty(&root->root_list)) {
btrfs_grab_root(root);
@@ -121525,7 +183134,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
}
spin_unlock(&fs_info->trans_lock);
}
-@@ -2014,16 +2075,24 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
+@@ -2014,16 +2079,24 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
{
/*
@@ -121552,7 +183161,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
return 0;
}
-@@ -2033,6 +2102,27 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
+@@ -2033,6 +2106,27 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
}
@@ -121580,7 +183189,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
{
struct btrfs_fs_info *fs_info = trans->fs_info;
-@@ -2106,6 +2196,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
+@@ -2106,6 +2200,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED;
@@ -121589,7 +183198,7 @@ index 14b9fdc8aaa9a..9a6009108ea55 100644
spin_unlock(&fs_info->trans_lock);
refcount_inc(&cur_trans->use_count);
-@@ -2196,6 +2288,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
+@@ -2196,6 +2292,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
* COMMIT_DOING so make sure to wait for num_writers to == 1 again.
*/
spin_lock(&fs_info->trans_lock);
@@ -121666,7 +183275,7 @@ index 7733e8ac0a698..51382d2be3d44 100644
/* Here we use super block generation + 1 to handle log tree */
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
-index b415c5ec03ea0..8ef65073ce8ce 100644
+index b415c5ec03ea0..1221d8483d63b 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1153,6 +1153,7 @@ again:
@@ -121737,7 +183346,45 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
} else {
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
clear_extent_buffer_dirty(next);
-@@ -3410,8 +3434,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
+@@ -3192,6 +3216,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ ret = btrfs_alloc_log_tree_node(trans, log_root_tree);
+ if (ret) {
+ mutex_unlock(&fs_info->tree_root->log_mutex);
++ blk_finish_plug(&plug);
+ goto out;
+ }
+ }
+@@ -3399,6 +3424,29 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
+ if (log->node) {
+ ret = walk_log_tree(trans, log, &wc);
+ if (ret) {
++ /*
++ * We weren't able to traverse the entire log tree, the
++ * typical scenario is getting an -EIO when reading an
++ * extent buffer of the tree, due to a previous writeback
++ * failure of it.
++ */
++ set_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
++ &log->fs_info->fs_state);
++
++ /*
++ * Some extent buffers of the log tree may still be dirty
++ * and not yet written back to storage, because we may
++ * have updates to a log tree without syncing a log tree,
++ * such as during rename and link operations. So flush
++ * them out and wait for their writeback to complete, so
++ * that we properly cleanup their state and pages.
++ */
++ btrfs_write_marked_extents(log->fs_info,
++ &log->dirty_log_pages,
++ EXTENT_DIRTY | EXTENT_NEW);
++ btrfs_wait_tree_log_extents(log,
++ EXTENT_DIRTY | EXTENT_NEW);
++
+ if (trans)
+ btrfs_abort_transaction(trans, ret);
+ else
+@@ -3410,8 +3458,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT);
extent_io_tree_release(&log->log_csum_range);
@@ -121746,7 +183393,7 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
btrfs_put_root(log);
}
-@@ -4419,7 +4441,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
+@@ -4419,7 +4465,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
/*
* Log all prealloc extents beyond the inode's i_size to make sure we do not
@@ -121755,7 +183402,7 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
* subvolume's root instead of iterating the inode's extent map tree because
* otherwise we can log incorrect extent items based on extent map conversion.
* That can happen due to the fact that extent maps are merged when they
-@@ -5204,6 +5226,7 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
+@@ -5204,6 +5250,7 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
struct btrfs_log_ctx *ctx,
bool *need_log_inode_item)
{
@@ -121763,7 +183410,7 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
struct btrfs_root *root = inode->root;
int ins_start_slot = 0;
int ins_nr = 0;
-@@ -5224,13 +5247,21 @@ again:
+@@ -5224,13 +5271,21 @@ again:
if (min_key->type > max_key->type)
break;
@@ -121791,7 +183438,7 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
u64 other_ino = 0;
u64 other_parent = 0;
-@@ -5261,10 +5292,8 @@ again:
+@@ -5261,10 +5316,8 @@ again:
btrfs_release_path(path);
goto next_key;
}
@@ -121804,7 +183451,7 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
if (ins_nr == 0)
goto next_slot;
ret = copy_items(trans, inode, dst_path, path,
-@@ -5317,9 +5346,21 @@ next_key:
+@@ -5317,9 +5370,21 @@ next_key:
break;
}
}
@@ -121827,8 +183474,36 @@ index b415c5ec03ea0..8ef65073ce8ce 100644
return ret;
}
+@@ -5418,6 +5483,18 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ mutex_lock(&inode->log_mutex);
+ }
+
++ /*
++ * For symlinks, we must always log their content, which is stored in an
++ * inline extent, otherwise we could end up with an empty symlink after
++ * log replay, which is invalid on linux (symlink(2) returns -ENOENT if
++ * one attempts to create an empty symlink).
++ * We don't need to worry about flushing delalloc, because when we create
++ * the inline extent when the symlink is created (we never have delalloc
++ * for symlinks).
++ */
++ if (S_ISLNK(inode->vfs_inode.i_mode))
++ inode_only = LOG_INODE_ALL;
++
+ /*
+ * This is for cases where logging a directory could result in losing a
+ * a file after replaying the log. For example, if we move a file from a
+@@ -5788,7 +5865,7 @@ process_leaf:
+ }
+
+ ctx->log_new_dentries = false;
+- if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK)
++ if (type == BTRFS_FT_DIR)
+ log_mode = LOG_INODE_ALL;
+ ret = btrfs_log_inode(trans, root, BTRFS_I(di_inode),
+ log_mode, ctx);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
-index 2ec3b8ac8fa35..06a1a7c2254ce 100644
+index 2ec3b8ac8fa35..471cc4706a074 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -14,6 +14,7 @@
@@ -121839,7 +183514,71 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
#include "misc.h"
#include "ctree.h"
#include "extent_map.h"
-@@ -1091,7 +1092,7 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices)
+@@ -529,15 +530,48 @@ error:
+ return ret;
+ }
+
+-static bool device_path_matched(const char *path, struct btrfs_device *device)
++/*
++ * Check if the device in the path matches the device in the given struct device.
++ *
++ * Returns:
++ * true If it is the same device.
++ * false If it is not the same device or on error.
++ */
++static bool device_matched(const struct btrfs_device *device, const char *path)
+ {
+- int found;
++ char *device_name;
++ dev_t dev_old;
++ dev_t dev_new;
++ int ret;
++
++ /*
++ * If we are looking for a device with the matching dev_t, then skip
++ * device without a name (a missing device).
++ */
++ if (!device->name)
++ return false;
++
++ device_name = kzalloc(BTRFS_PATH_NAME_MAX, GFP_KERNEL);
++ if (!device_name)
++ return false;
+
+ rcu_read_lock();
+- found = strcmp(rcu_str_deref(device->name), path);
++ scnprintf(device_name, BTRFS_PATH_NAME_MAX, "%s", rcu_str_deref(device->name));
+ rcu_read_unlock();
+
+- return found == 0;
++ ret = lookup_bdev(device_name, &dev_old);
++ kfree(device_name);
++ if (ret)
++ return false;
++
++ ret = lookup_bdev(path, &dev_new);
++ if (ret)
++ return false;
++
++ if (dev_old == dev_new)
++ return true;
++
++ return false;
+ }
+
+ /*
+@@ -570,9 +604,7 @@ static int btrfs_free_stale_devices(const char *path,
+ &fs_devices->devices, dev_list) {
+ if (skip_device && skip_device == device)
+ continue;
+- if (path && !device->name)
+- continue;
+- if (path && !device_path_matched(path, device))
++ if (path && !device_matched(device, path))
+ continue;
+ if (fs_devices->opened) {
+ /* for an already deleted device return 0 */
+@@ -1091,7 +1123,7 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices)
list_for_each_entry(seed_dev, &fs_devices->seed_list, seed_list)
__btrfs_free_extra_devids(seed_dev, &latest_dev);
@@ -121848,7 +183587,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
mutex_unlock(&uuid_mutex);
}
-@@ -1122,8 +1123,10 @@ static void btrfs_close_one_device(struct btrfs_device *device)
+@@ -1122,8 +1154,10 @@ static void btrfs_close_one_device(struct btrfs_device *device)
if (device->devid == BTRFS_DEV_REPLACE_DEVID)
clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
@@ -121860,7 +183599,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
btrfs_close_bdev(device);
if (device->bdev) {
-@@ -1222,7 +1225,7 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
+@@ -1222,7 +1256,7 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
return -EINVAL;
fs_devices->opened = 1;
@@ -121869,7 +183608,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
fs_devices->total_rw_bytes = 0;
fs_devices->chunk_alloc_policy = BTRFS_CHUNK_ALLOC_REGULAR;
fs_devices->read_policy = BTRFS_READ_POLICY_PID;
-@@ -1363,8 +1366,10 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
+@@ -1363,8 +1397,10 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
bytenr_orig = btrfs_sb_offset(0);
ret = btrfs_sb_log_location_bdev(bdev, 0, READ, &bytenr);
@@ -121882,7 +183621,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr_orig);
if (IS_ERR(disk_super)) {
-@@ -1882,18 +1887,22 @@ out:
+@@ -1882,18 +1918,22 @@ out:
/*
* Function to update ctime/mtime for a given device path.
* Mainly used for ctime/mtime based probe like libblkid.
@@ -121911,7 +183650,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
}
static int btrfs_rm_dev_item(struct btrfs_device *device)
-@@ -1986,7 +1995,7 @@ static struct btrfs_device * btrfs_find_next_active_device(
+@@ -1986,7 +2026,7 @@ static struct btrfs_device * btrfs_find_next_active_device(
}
/*
@@ -121920,7 +183659,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
* and replace it with the provided or the next active device, in the context
* where this function called, there should be always be another device (or
* this_dev) which is active.
-@@ -2005,8 +2014,8 @@ void __cold btrfs_assign_next_active_device(struct btrfs_device *device,
+@@ -2005,8 +2045,8 @@ void __cold btrfs_assign_next_active_device(struct btrfs_device *device,
(fs_info->sb->s_bdev == device->bdev))
fs_info->sb->s_bdev = next_device->bdev;
@@ -121931,7 +183670,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
}
/*
-@@ -2069,7 +2078,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
+@@ -2069,7 +2109,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
/* Update ctime/mtime for device path for libblkid */
@@ -121940,7 +183679,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
}
int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
-@@ -2081,8 +2090,11 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
+@@ -2081,8 +2121,11 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
u64 num_devices;
int ret = 0;
@@ -121954,7 +183693,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
num_devices = btrfs_num_devices(fs_info);
ret = btrfs_check_raid_min_devices(fs_info, num_devices - 1);
-@@ -2126,11 +2138,9 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
+@@ -2126,11 +2169,9 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
mutex_unlock(&fs_info->chunk_mutex);
}
@@ -121966,7 +183705,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
if (ret)
goto error_undo;
-@@ -2217,7 +2227,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
+@@ -2217,7 +2258,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
}
out:
@@ -121974,7 +183713,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
return ret;
error_undo:
-@@ -2305,13 +2314,6 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
+@@ -2305,13 +2345,6 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
mutex_unlock(&fs_devices->device_list_mutex);
@@ -121988,7 +183727,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
btrfs_scratch_superblocks(tgtdev->fs_info, tgtdev->bdev,
tgtdev->name->str);
-@@ -2594,7 +2596,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
+@@ -2594,7 +2627,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
device->fs_info = fs_info;
device->bdev = bdev;
@@ -121997,7 +183736,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
if (ret)
goto error_free_device;
-@@ -2627,6 +2629,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
+@@ -2627,6 +2660,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
btrfs_abort_transaction(trans, ret);
goto error_trans;
}
@@ -122006,7 +183745,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
}
device->fs_devices = fs_devices;
-@@ -2733,7 +2737,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
+@@ -2733,7 +2768,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
btrfs_forget_devices(device_path);
/* Update ctime/mtime for blkid or udev */
@@ -122015,7 +183754,20 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
return ret;
-@@ -7481,6 +7485,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
+@@ -4354,10 +4389,12 @@ static int balance_kthread(void *data)
+ struct btrfs_fs_info *fs_info = data;
+ int ret = 0;
+
++ sb_start_write(fs_info->sb);
+ mutex_lock(&fs_info->balance_mutex);
+ if (fs_info->balance_ctl)
+ ret = btrfs_balance(fs_info, fs_info->balance_ctl, NULL);
+ mutex_unlock(&fs_info->balance_mutex);
++ sb_end_write(fs_info->sb);
+
+ return ret;
+ }
+@@ -7481,6 +7518,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
*/
fs_info->fs_devices->total_rw_bytes = 0;
@@ -122035,7 +183787,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
/*
* Read all device items, and then all the chunk items. All
* device items are found before any chunk item (their object id
-@@ -7506,10 +7523,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
+@@ -7506,10 +7556,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
goto error;
break;
}
@@ -122046,7 +183798,7 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
node = path->nodes[1];
if (node) {
if (last_ra_node != node->start) {
-@@ -7537,7 +7550,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
+@@ -7537,7 +7583,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
* requirement for chunk allocation, see the comment on
* top of btrfs_chunk_alloc() for details.
*/
@@ -122054,6 +183806,27 @@ index 2ec3b8ac8fa35..06a1a7c2254ce 100644
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
ret = read_one_chunk(&found_key, leaf, chunk);
if (ret)
+@@ -8173,10 +8218,12 @@ static int relocating_repair_kthread(void *data)
+ target = cache->start;
+ btrfs_put_block_group(cache);
+
++ sb_start_write(fs_info->sb);
+ if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
+ btrfs_info(fs_info,
+ "zoned: skip relocating block group %llu to repair: EBUSY",
+ target);
++ sb_end_write(fs_info->sb);
+ return -EBUSY;
+ }
+
+@@ -8204,6 +8251,7 @@ out:
+ btrfs_put_block_group(cache);
+ mutex_unlock(&fs_info->reclaim_bgs_lock);
+ btrfs_exclop_finish(fs_info);
++ sb_end_write(fs_info->sb);
+
+ return ret;
+ }
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 2183361db614d..4db10d071d67f 100644
--- a/fs/btrfs/volumes.h
@@ -122071,6 +183844,30 @@ index 2183361db614d..4db10d071d67f 100644
/* all of the devices in the FS, protected by a mutex
* so we can safely walk it to write out the supers without
+diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
+index 8a4514283a4b8..c5c5b97c2a852 100644
+--- a/fs/btrfs/xattr.c
++++ b/fs/btrfs/xattr.c
+@@ -264,7 +264,8 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
+ inode_inc_iversion(inode);
+ inode->i_ctime = current_time(inode);
+ ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
+- BUG_ON(ret);
++ if (ret)
++ btrfs_abort_transaction(trans, ret);
+ out:
+ if (start_trans)
+ btrfs_end_transaction(trans);
+@@ -418,7 +419,8 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
+ inode_inc_iversion(inode);
+ inode->i_ctime = current_time(inode);
+ ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
+- BUG_ON(ret);
++ if (ret)
++ btrfs_abort_transaction(trans, ret);
+ }
+
+ btrfs_end_transaction(trans);
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 47af1ab3bf120..596b2148807d4 100644
--- a/fs/btrfs/zoned.c
@@ -122319,8 +184116,34 @@ index 4b299705bb12b..813aa3cddc11f 100644
#endif
static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
+diff --git a/fs/buffer.c b/fs/buffer.c
+index c615387aedcae..f6d2835794918 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -1235,16 +1235,18 @@ static void bh_lru_install(struct buffer_head *bh)
+ int i;
+
+ check_irqs_on();
++ bh_lru_lock();
++
+ /*
+ * the refcount of buffer_head in bh_lru prevents dropping the
+ * attached page(i.e., try_to_free_buffers) so it could cause
+ * failing page migration.
+ * Skip putting upcoming bh into bh_lru until migration is done.
+ */
+- if (lru_cache_disabled())
++ if (lru_cache_disabled()) {
++ bh_lru_unlock();
+ return;
+-
+- bh_lru_lock();
++ }
+
+ b = this_cpu_ptr(&bh_lrus);
+ for (i = 0; i < BH_LRU_SIZE; i++) {
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
-index 8f537f1d9d1d3..09900a9015ea6 100644
+index 8f537f1d9d1d3..d1faa9d2f1e8a 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2217,6 +2217,7 @@ static int unsafe_request_wait(struct inode *inode)
@@ -122331,7 +184154,7 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
int ret, err = 0;
spin_lock(&ci->i_unsafe_lock);
-@@ -2234,37 +2235,45 @@ static int unsafe_request_wait(struct inode *inode)
+@@ -2234,37 +2235,47 @@ static int unsafe_request_wait(struct inode *inode)
}
spin_unlock(&ci->i_unsafe_lock);
@@ -122380,6 +184203,8 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
r_unsafe_dir_item) {
s = req->r_session;
- if (unlikely(s->s_mds >= max)) {
++ if (!s)
++ continue;
+ if (unlikely(s->s_mds >= max_sessions)) {
spin_unlock(&ci->i_unsafe_lock);
+ for (i = 0; i < max_sessions; i++) {
@@ -122391,11 +184216,13 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
goto retry;
}
if (!sessions[s->s_mds]) {
-@@ -2277,8 +2286,14 @@ retry:
+@@ -2277,8 +2288,16 @@ retry:
list_for_each_entry(req, &ci->i_unsafe_iops,
r_unsafe_target_item) {
s = req->r_session;
- if (unlikely(s->s_mds >= max)) {
++ if (!s)
++ continue;
+ if (unlikely(s->s_mds >= max_sessions)) {
spin_unlock(&ci->i_unsafe_lock);
+ for (i = 0; i < max_sessions; i++) {
@@ -122407,7 +184234,7 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
goto retry;
}
if (!sessions[s->s_mds]) {
-@@ -2299,7 +2314,7 @@ retry:
+@@ -2299,7 +2318,7 @@ retry:
spin_unlock(&ci->i_ceph_lock);
/* send flush mdlog request to MDSes */
@@ -122416,7 +184243,7 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
s = sessions[i];
if (s) {
send_flush_mdlog(s);
-@@ -2316,15 +2331,19 @@ retry:
+@@ -2316,15 +2335,19 @@ retry:
ceph_timeout_jiffies(req1->r_timeout));
if (ret)
err = -EIO;
@@ -122438,7 +184265,7 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
return err;
}
-@@ -4349,7 +4368,7 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
+@@ -4349,7 +4372,7 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(ci->vfs_inode.i_sb);
int bits = (fmode << 1) | 1;
@@ -122447,7 +184274,7 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
int i;
if (count == 1)
-@@ -4357,19 +4376,19 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
+@@ -4357,19 +4380,19 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
spin_lock(&ci->i_ceph_lock);
for (i = 0; i < CEPH_FILE_MODE_BITS; i++) {
@@ -122474,8 +184301,38 @@ index 8f537f1d9d1d3..09900a9015ea6 100644
percpu_counter_inc(&mdsc->metric.opened_inodes);
spin_unlock(&ci->i_ceph_lock);
}
+diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
+index 133dbd9338e73..d91fa53e12b33 100644
+--- a/fs/ceph/dir.c
++++ b/fs/ceph/dir.c
+@@ -478,8 +478,11 @@ more:
+ 2 : (fpos_off(rde->offset) + 1);
+ err = note_last_dentry(dfi, rde->name, rde->name_len,
+ next_offset);
+- if (err)
++ if (err) {
++ ceph_mdsc_put_request(dfi->last_readdir);
++ dfi->last_readdir = NULL;
+ return err;
++ }
+ } else if (req->r_reply_info.dir_end) {
+ dfi->next_offset = 2;
+ /* keep last name */
+@@ -520,6 +523,12 @@ more:
+ if (!dir_emit(ctx, rde->name, rde->name_len,
+ ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)),
+ le32_to_cpu(rde->inode.in->mode) >> 12)) {
++ /*
++ * NOTE: Here no need to put the 'dfi->last_readdir',
++ * because when dir_emit stops us it's most likely
++ * doesn't have enough memory, etc. So for next readdir
++ * it will continue.
++ */
+ dout("filldir stopping us...\n");
+ return 0;
+ }
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
-index e61018d9764ee..6180df6f8e61e 100644
+index e61018d9764ee..e34d52df4a13c 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -577,6 +577,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
@@ -122486,7 +184343,26 @@ index e61018d9764ee..6180df6f8e61e 100644
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
struct ceph_vino vino = { .ino = req->r_deleg_ino,
.snap = CEPH_NOSNAP };
-@@ -603,17 +604,35 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
+@@ -591,9 +592,15 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
+ iinfo.change_attr = 1;
+ ceph_encode_timespec64(&iinfo.btime, &now);
+
+- iinfo.xattr_len = ARRAY_SIZE(xattr_buf);
+- iinfo.xattr_data = xattr_buf;
+- memset(iinfo.xattr_data, 0, iinfo.xattr_len);
++ if (req->r_pagelist) {
++ iinfo.xattr_len = req->r_pagelist->length;
++ iinfo.xattr_data = req->r_pagelist->mapped_tail;
++ } else {
++ /* fake it */
++ iinfo.xattr_len = ARRAY_SIZE(xattr_buf);
++ iinfo.xattr_data = xattr_buf;
++ memset(iinfo.xattr_data, 0, iinfo.xattr_len);
++ }
+
+ in.ino = cpu_to_le64(vino.ino);
+ in.snapid = cpu_to_le64(CEPH_NOSNAP);
+@@ -603,17 +610,35 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
in.cap.realm = cpu_to_le64(ci->i_snap_realm->ino);
in.cap.flags = CEPH_CAP_FLAG_AUTH;
in.ctime = in.mtime = in.atime = iinfo.btime;
@@ -122525,7 +184401,18 @@ index e61018d9764ee..6180df6f8e61e 100644
down_read(&mdsc->snap_rwsem);
ret = ceph_fill_inode(inode, NULL, &iinfo, NULL, req->r_session,
-@@ -732,8 +751,10 @@ retry:
+@@ -687,6 +712,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
+ err = ceph_security_init_secctx(dentry, mode, &as_ctx);
+ if (err < 0)
+ goto out_ctx;
++ /* Async create can't handle more than a page of xattrs */
++ if (as_ctx.pagelist &&
++ !list_is_singular(&as_ctx.pagelist->head))
++ try_async = false;
+ } else if (!d_in_lookup(dentry)) {
+ /* If it's not being looked up, it's negative */
+ return -ENOENT;
+@@ -732,8 +761,10 @@ retry:
restore_deleg_ino(dir, req->r_deleg_ino);
ceph_mdsc_put_request(req);
try_async = false;
@@ -122536,6 +184423,39 @@ index e61018d9764ee..6180df6f8e61e 100644
goto out_req;
}
}
+diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
+index 1c7574105478f..42e449d3f18b8 100644
+--- a/fs/ceph/inode.c
++++ b/fs/ceph/inode.c
+@@ -87,13 +87,13 @@ struct inode *ceph_get_snapdir(struct inode *parent)
+ if (!S_ISDIR(parent->i_mode)) {
+ pr_warn_once("bad snapdir parent type (mode=0%o)\n",
+ parent->i_mode);
+- return ERR_PTR(-ENOTDIR);
++ goto err;
+ }
+
+ if (!(inode->i_state & I_NEW) && !S_ISDIR(inode->i_mode)) {
+ pr_warn_once("bad snapdir inode type (mode=0%o)\n",
+ inode->i_mode);
+- return ERR_PTR(-ENOTDIR);
++ goto err;
+ }
+
+ inode->i_mode = parent->i_mode;
+@@ -113,6 +113,12 @@ struct inode *ceph_get_snapdir(struct inode *parent)
+ }
+
+ return inode;
++err:
++ if ((inode->i_state & I_NEW))
++ discard_new_inode(inode);
++ else
++ iput(inode);
++ return ERR_PTR(-ENOTDIR);
+ }
+
+ const struct inode_operations ceph_file_iops = {
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index d64413adc0fd2..e9409c460acd0 100644
--- a/fs/ceph/mds_client.c
@@ -122674,10 +184594,65 @@ index ee3aab3dd4ac6..bf861fef2f0c3 100644
nsecdesclen += 5 * sizeof(struct cifs_ace);
} else { /* chown */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
-index 9fa930dfd78d6..21bf82fc22783 100644
+index 9fa930dfd78d6..8f8d281e31510 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
-@@ -909,6 +909,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
+@@ -210,6 +210,9 @@ cifs_read_super(struct super_block *sb)
+ if (rc)
+ goto out_no_root;
+ /* tune readahead according to rsize if readahead size not set on mount */
++ if (cifs_sb->ctx->rsize == 0)
++ cifs_sb->ctx->rsize =
++ tcon->ses->server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
+ if (cifs_sb->ctx->rasize)
+ sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
+ else
+@@ -254,26 +257,33 @@ static void cifs_kill_sb(struct super_block *sb)
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon;
+ struct cached_fid *cfid;
++ struct rb_root *root = &cifs_sb->tlink_tree;
++ struct rb_node *node;
++ struct tcon_link *tlink;
+
+ /*
+ * We ned to release all dentries for the cached directories
+ * before we kill the sb.
+ */
+ if (cifs_sb->root) {
++ for (node = rb_first(root); node; node = rb_next(node)) {
++ tlink = rb_entry(node, struct tcon_link, tl_rbnode);
++ tcon = tlink_tcon(tlink);
++ if (IS_ERR(tcon))
++ continue;
++ cfid = &tcon->crfid;
++ mutex_lock(&cfid->fid_mutex);
++ if (cfid->dentry) {
++ dput(cfid->dentry);
++ cfid->dentry = NULL;
++ }
++ mutex_unlock(&cfid->fid_mutex);
++ }
++
++ /* finally release root dentry */
+ dput(cifs_sb->root);
+ cifs_sb->root = NULL;
+ }
+- tcon = cifs_sb_master_tcon(cifs_sb);
+- if (tcon) {
+- cfid = &tcon->crfid;
+- mutex_lock(&cfid->fid_mutex);
+- if (cfid->dentry) {
+-
+- dput(cfid->dentry);
+- cfid->dentry = NULL;
+- }
+- mutex_unlock(&cfid->fid_mutex);
+- }
+
+ kill_anon_super(sb);
+ cifs_umount(cifs_sb);
+@@ -909,6 +919,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
out_super:
deactivate_locked_super(sb);
@@ -122685,6 +184660,15 @@ index 9fa930dfd78d6..21bf82fc22783 100644
out:
if (cifs_sb) {
kfree(cifs_sb->prepath);
+@@ -925,7 +936,7 @@ cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+ ssize_t rc;
+ struct inode *inode = file_inode(iocb->ki_filp);
+
+- if (iocb->ki_filp->f_flags & O_DIRECT)
++ if (iocb->ki_flags & IOCB_DIRECT)
+ return cifs_user_readv(iocb, iter);
+
+ rc = cifs_revalidate_mapping(inode);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index e916470468ea9..b33835b2943e9 100644
--- a/fs/cifs/cifsglob.h
@@ -122875,7 +184859,7 @@ index c3b94c1e45913..70da1d27be3db 100644
rc = cifs_negotiate_protocol(xid, ses);
if (!rc)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
-index 13f3182cf7969..82bbaf8e92b79 100644
+index 13f3182cf7969..b23f6b489bb9d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2692,12 +2692,23 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
@@ -122940,6 +184924,30 @@ index 13f3182cf7969..82bbaf8e92b79 100644
free_xid(xid);
return rc;
}
+@@ -3711,6 +3734,11 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
+ break;
+ }
+
++ if (cifs_sb->ctx->rsize == 0)
++ cifs_sb->ctx->rsize =
++ server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
++ cifs_sb->ctx);
++
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
+ &rsize, credits);
+ if (rc)
+@@ -4489,6 +4517,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
+ break;
+ }
+
++ if (cifs_sb->ctx->rsize == 0)
++ cifs_sb->ctx->rsize =
++ server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
++ cifs_sb->ctx);
++
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
+ &rsize, credits);
+ if (rc)
diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 3109def8e1998..3b8ed36b37113 100644
--- a/fs/cifs/fs_context.c
@@ -123064,6 +185072,20 @@ index a42ba71d7a81f..29601a4eb4116 100644
char *UNC;
char *nodename;
char *iocharset; /* local code page for mapping to and from Unicode */
+diff --git a/fs/cifs/link.c b/fs/cifs/link.c
+index 852e54ee82c28..bbdf3281559c8 100644
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -85,6 +85,9 @@ parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
+ if (rc != 1)
+ return -EINVAL;
+
++ if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
++ return -EINVAL;
++
+ rc = symlink_hash(link_len, link_str, md5_hash);
+ if (rc) {
+ cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index bb1185fff8cc4..0a0d0724c4294 100644
--- a/fs/cifs/misc.c
@@ -123210,6 +185232,257 @@ index 23e02db7923f6..5500ea7837845 100644
out:
ses->binding = false;
ses->binding_chan = NULL;
+diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
+index bda606dc72b1f..0c1af2dd9069e 100644
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1631,6 +1631,7 @@ smb2_ioctl_query_info(const unsigned int xid,
+ unsigned int size[2];
+ void *data[2];
+ int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR;
++ void (*free_req1_func)(struct smb_rqst *r);
+
+ vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
+ if (vars == NULL)
+@@ -1640,27 +1641,29 @@ smb2_ioctl_query_info(const unsigned int xid,
+
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+
+- if (copy_from_user(&qi, arg, sizeof(struct smb_query_info)))
+- goto e_fault;
+-
++ if (copy_from_user(&qi, arg, sizeof(struct smb_query_info))) {
++ rc = -EFAULT;
++ goto free_vars;
++ }
+ if (qi.output_buffer_length > 1024) {
+- kfree(vars);
+- return -EINVAL;
++ rc = -EINVAL;
++ goto free_vars;
+ }
+
+ if (!ses || !server) {
+- kfree(vars);
+- return -EIO;
++ rc = -EIO;
++ goto free_vars;
+ }
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+- buffer = memdup_user(arg + sizeof(struct smb_query_info),
+- qi.output_buffer_length);
+- if (IS_ERR(buffer)) {
+- kfree(vars);
+- return PTR_ERR(buffer);
++ if (qi.output_buffer_length) {
++ buffer = memdup_user(arg + sizeof(struct smb_query_info), qi.output_buffer_length);
++ if (IS_ERR(buffer)) {
++ rc = PTR_ERR(buffer);
++ goto free_vars;
++ }
+ }
+
+ /* Open */
+@@ -1698,45 +1701,45 @@ smb2_ioctl_query_info(const unsigned int xid,
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, path);
+ if (rc)
+- goto iqinf_exit;
++ goto free_output_buffer;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+ /* Query */
+ if (qi.flags & PASSTHRU_FSCTL) {
+ /* Can eventually relax perm check since server enforces too */
+- if (!capable(CAP_SYS_ADMIN))
++ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EPERM;
+- else {
+- rqst[1].rq_iov = &vars->io_iov[0];
+- rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
+-
+- rc = SMB2_ioctl_init(tcon, server,
+- &rqst[1],
+- COMPOUND_FID, COMPOUND_FID,
+- qi.info_type, true, buffer,
+- qi.output_buffer_length,
+- CIFSMaxBufSize -
+- MAX_SMB2_CREATE_RESPONSE_SIZE -
+- MAX_SMB2_CLOSE_RESPONSE_SIZE);
++ goto free_open_req;
+ }
++ rqst[1].rq_iov = &vars->io_iov[0];
++ rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
++
++ rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
++ qi.info_type, true, buffer, qi.output_buffer_length,
++ CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
++ MAX_SMB2_CLOSE_RESPONSE_SIZE);
++ free_req1_func = SMB2_ioctl_free;
+ } else if (qi.flags == PASSTHRU_SET_INFO) {
+ /* Can eventually relax perm check since server enforces too */
+- if (!capable(CAP_SYS_ADMIN))
++ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EPERM;
+- else {
+- rqst[1].rq_iov = &vars->si_iov[0];
+- rqst[1].rq_nvec = 1;
+-
+- size[0] = 8;
+- data[0] = buffer;
+-
+- rc = SMB2_set_info_init(tcon, server,
+- &rqst[1],
+- COMPOUND_FID, COMPOUND_FID,
+- current->tgid,
+- FILE_END_OF_FILE_INFORMATION,
+- SMB2_O_INFO_FILE, 0, data, size);
++ goto free_open_req;
++ }
++ if (qi.output_buffer_length < 8) {
++ rc = -EINVAL;
++ goto free_open_req;
+ }
++ rqst[1].rq_iov = &vars->si_iov[0];
++ rqst[1].rq_nvec = 1;
++
++ /* MS-FSCC 2.4.13 FileEndOfFileInformation */
++ size[0] = 8;
++ data[0] = buffer;
++
++ rc = SMB2_set_info_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
++ current->tgid, FILE_END_OF_FILE_INFORMATION,
++ SMB2_O_INFO_FILE, 0, data, size);
++ free_req1_func = SMB2_set_info_free;
+ } else if (qi.flags == PASSTHRU_QUERY_INFO) {
+ rqst[1].rq_iov = &vars->qi_iov[0];
+ rqst[1].rq_nvec = 1;
+@@ -1747,6 +1750,7 @@ smb2_ioctl_query_info(const unsigned int xid,
+ qi.info_type, qi.additional_information,
+ qi.input_buffer_length,
+ qi.output_buffer_length, buffer);
++ free_req1_func = SMB2_query_info_free;
+ } else { /* unknown flags */
+ cifs_tcon_dbg(VFS, "Invalid passthru query flags: 0x%x\n",
+ qi.flags);
+@@ -1754,7 +1758,7 @@ smb2_ioctl_query_info(const unsigned int xid,
+ }
+
+ if (rc)
+- goto iqinf_exit;
++ goto free_open_req;
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+@@ -1765,14 +1769,14 @@ smb2_ioctl_query_info(const unsigned int xid,
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+- goto iqinf_exit;
++ goto free_req_1;
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+ if (rc)
+- goto iqinf_exit;
++ goto out;
+
+ /* No need to bump num_remote_opens since handle immediately closed */
+ if (qi.flags & PASSTHRU_FSCTL) {
+@@ -1782,18 +1786,22 @@ smb2_ioctl_query_info(const unsigned int xid,
+ qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount);
+ if (qi.input_buffer_length > 0 &&
+ le32_to_cpu(io_rsp->OutputOffset) + qi.input_buffer_length
+- > rsp_iov[1].iov_len)
+- goto e_fault;
++ > rsp_iov[1].iov_len) {
++ rc = -EFAULT;
++ goto out;
++ }
+
+ if (copy_to_user(&pqi->input_buffer_length,
+ &qi.input_buffer_length,
+- sizeof(qi.input_buffer_length)))
+- goto e_fault;
++ sizeof(qi.input_buffer_length))) {
++ rc = -EFAULT;
++ goto out;
++ }
+
+ if (copy_to_user((void __user *)pqi + sizeof(struct smb_query_info),
+ (const void *)io_rsp + le32_to_cpu(io_rsp->OutputOffset),
+ qi.input_buffer_length))
+- goto e_fault;
++ rc = -EFAULT;
+ } else {
+ pqi = (struct smb_query_info __user *)arg;
+ qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+@@ -1801,28 +1809,30 @@ smb2_ioctl_query_info(const unsigned int xid,
+ qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength);
+ if (copy_to_user(&pqi->input_buffer_length,
+ &qi.input_buffer_length,
+- sizeof(qi.input_buffer_length)))
+- goto e_fault;
++ sizeof(qi.input_buffer_length))) {
++ rc = -EFAULT;
++ goto out;
++ }
+
+ if (copy_to_user(pqi + 1, qi_rsp->Buffer,
+ qi.input_buffer_length))
+- goto e_fault;
++ rc = -EFAULT;
+ }
+
+- iqinf_exit:
+- cifs_small_buf_release(rqst[0].rq_iov[0].iov_base);
+- cifs_small_buf_release(rqst[1].rq_iov[0].iov_base);
+- cifs_small_buf_release(rqst[2].rq_iov[0].iov_base);
++out:
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+- kfree(vars);
++ SMB2_close_free(&rqst[2]);
++free_req_1:
++ free_req1_func(&rqst[1]);
++free_open_req:
++ SMB2_open_free(&rqst[0]);
++free_output_buffer:
+ kfree(buffer);
++free_vars:
++ kfree(vars);
+ return rc;
+-
+-e_fault:
+- rc = -EFAULT;
+- goto iqinf_exit;
+ }
+
+ static ssize_t
+@@ -1839,9 +1849,17 @@ smb2_copychunk_range(const unsigned int xid,
+ int chunks_copied = 0;
+ bool chunk_sizes_updated = false;
+ ssize_t bytes_written, total_bytes_written = 0;
++ struct inode *inode;
+
+ pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
+
++ /*
++ * We need to flush all unwritten data before we can send the
++ * copychunk ioctl to the server.
++ */
++ inode = d_inode(trgtfile->dentry);
++ filemap_write_and_wait(inode->i_mapping);
++
+ if (pcchunk == NULL)
+ return -ENOMEM;
+
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index b7379329b741c..61ea3d3f95b4a 100644
--- a/fs/cifs/transport.c
@@ -123320,6 +185593,185 @@ index 1466b5d01cbb9..d1f9d26322027 100644
configfs_release_fs();
}
+diff --git a/fs/coredump.c b/fs/coredump.c
+index 3224dee44d30e..26eb5a095832f 100644
+--- a/fs/coredump.c
++++ b/fs/coredump.c
+@@ -41,6 +41,7 @@
+ #include <linux/fs.h>
+ #include <linux/path.h>
+ #include <linux/timekeeping.h>
++#include <linux/elf.h>
+
+ #include <linux/uaccess.h>
+ #include <asm/mmu_context.h>
+@@ -52,6 +53,9 @@
+
+ #include <trace/events/sched.h>
+
++static bool dump_vma_snapshot(struct coredump_params *cprm);
++static void free_vma_snapshot(struct coredump_params *cprm);
++
+ int core_uses_pid;
+ unsigned int core_pipe_limit;
+ char core_pattern[CORENAME_MAX_SIZE] = "core";
+@@ -600,6 +604,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+ * by any locks.
+ */
+ .mm_flags = mm->flags,
++ .vma_meta = NULL,
+ };
+
+ audit_core_dumps(siginfo->si_signo);
+@@ -814,6 +819,9 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+ pr_info("Core dump to |%s disabled\n", cn.corename);
+ goto close_fail;
+ }
++ if (!dump_vma_snapshot(&cprm))
++ goto close_fail;
++
+ file_start_write(cprm.file);
+ core_dumped = binfmt->core_dump(&cprm);
+ /*
+@@ -827,6 +835,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+ dump_emit(&cprm, "", 1);
+ }
+ file_end_write(cprm.file);
++ free_vma_snapshot(&cprm);
+ }
+ if (ispipe && core_pipe_limit)
+ wait_for_dump_helpers(cprm.file);
+@@ -992,6 +1001,8 @@ static bool always_dump_vma(struct vm_area_struct *vma)
+ return false;
+ }
+
++#define DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER 1
++
+ /*
+ * Decide how much of @vma's contents should be included in a core dump.
+ */
+@@ -1051,9 +1062,20 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
+ * dump the first page to aid in determining what was mapped here.
+ */
+ if (FILTER(ELF_HEADERS) &&
+- vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ) &&
+- (READ_ONCE(file_inode(vma->vm_file)->i_mode) & 0111) != 0)
+- return PAGE_SIZE;
++ vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
++ if ((READ_ONCE(file_inode(vma->vm_file)->i_mode) & 0111) != 0)
++ return PAGE_SIZE;
++
++ /*
++ * ELF libraries aren't always executable.
++ * We'll want to check whether the mapping starts with the ELF
++ * magic, but not now - we're holding the mmap lock,
++ * so copy_from_user() doesn't work here.
++ * Use a placeholder instead, and fix it up later in
++ * dump_vma_snapshot().
++ */
++ return DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER;
++ }
+
+ #undef FILTER
+
+@@ -1090,18 +1112,29 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
+ return gate_vma;
+ }
+
++static void free_vma_snapshot(struct coredump_params *cprm)
++{
++ if (cprm->vma_meta) {
++ int i;
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct file *file = cprm->vma_meta[i].file;
++ if (file)
++ fput(file);
++ }
++ kvfree(cprm->vma_meta);
++ cprm->vma_meta = NULL;
++ }
++}
++
+ /*
+ * Under the mmap_lock, take a snapshot of relevant information about the task's
+ * VMAs.
+ */
+-int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
+- struct core_vma_metadata **vma_meta,
+- size_t *vma_data_size_ptr)
++static bool dump_vma_snapshot(struct coredump_params *cprm)
+ {
+ struct vm_area_struct *vma, *gate_vma;
+ struct mm_struct *mm = current->mm;
+ int i;
+- size_t vma_data_size = 0;
+
+ /*
+ * Once the stack expansion code is fixed to not change VMA bounds
+@@ -1109,36 +1142,51 @@ int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
+ * mmap_lock in read mode.
+ */
+ if (mmap_write_lock_killable(mm))
+- return -EINTR;
++ return false;
+
++ cprm->vma_data_size = 0;
+ gate_vma = get_gate_vma(mm);
+- *vma_count = mm->map_count + (gate_vma ? 1 : 0);
++ cprm->vma_count = mm->map_count + (gate_vma ? 1 : 0);
+
+- *vma_meta = kvmalloc_array(*vma_count, sizeof(**vma_meta), GFP_KERNEL);
+- if (!*vma_meta) {
++ cprm->vma_meta = kvmalloc_array(cprm->vma_count, sizeof(*cprm->vma_meta), GFP_KERNEL);
++ if (!cprm->vma_meta) {
+ mmap_write_unlock(mm);
+- return -ENOMEM;
++ return false;
+ }
+
+ for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
+ vma = next_vma(vma, gate_vma), i++) {
+- struct core_vma_metadata *m = (*vma_meta) + i;
++ struct core_vma_metadata *m = cprm->vma_meta + i;
+
+ m->start = vma->vm_start;
+ m->end = vma->vm_end;
+ m->flags = vma->vm_flags;
+ m->dump_size = vma_dump_size(vma, cprm->mm_flags);
++ m->pgoff = vma->vm_pgoff;
+
+- vma_data_size += m->dump_size;
++ m->file = vma->vm_file;
++ if (m->file)
++ get_file(m->file);
+ }
+
+ mmap_write_unlock(mm);
+
+- if (WARN_ON(i != *vma_count)) {
+- kvfree(*vma_meta);
+- return -EFAULT;
++ for (i = 0; i < cprm->vma_count; i++) {
++ struct core_vma_metadata *m = cprm->vma_meta + i;
++
++ if (m->dump_size == DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER) {
++ char elfmag[SELFMAG];
++
++ if (copy_from_user(elfmag, (void __user *)m->start, SELFMAG) ||
++ memcmp(elfmag, ELFMAG, SELFMAG) != 0) {
++ m->dump_size = 0;
++ } else {
++ m->dump_size = PAGE_SIZE;
++ }
++ }
++
++ cprm->vma_data_size += m->dump_size;
+ }
+
+- *vma_data_size_ptr = vma_data_size;
+- return 0;
++ return true;
+ }
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 3fa965eb3336d..cb25ef0cdf1f3 100644
--- a/fs/crypto/fscrypt_private.h
@@ -123589,6 +186041,19 @@ index 8f715c620e1f8..7a8efce1c343e 100644
}
/* below sendcon only handling */
+diff --git a/fs/erofs/data.c b/fs/erofs/data.c
+index 9db8297156527..16a41d0db55a3 100644
+--- a/fs/erofs/data.c
++++ b/fs/erofs/data.c
+@@ -287,7 +287,7 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+
+ if (!err)
+ return iomap_dio_rw(iocb, to, &erofs_iomap_ops,
+- NULL, 0);
++ NULL, 0, 0);
+ if (err < 0)
+ return err;
+ }
diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
index a5bc4b1b7813e..ad3f31380e6b2 100644
--- a/fs/erofs/decompressor.c
@@ -123708,10 +186173,26 @@ index dfd7fe0503bb1..b05464f4a8083 100644
if (ctor->index >= ctor->nr)
z_erofs_pagevec_ctor_pagedown(ctor, false);
diff --git a/fs/exec.c b/fs/exec.c
-index a098c133d8d74..ac7b51b51f38a 100644
+index a098c133d8d74..29e865c59854a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
-@@ -1852,7 +1852,7 @@ out:
+@@ -494,8 +494,14 @@ static int bprm_stack_limits(struct linux_binprm *bprm)
+ * the stack. They aren't stored until much later when we can't
+ * signal to the parent that the child has run out of stack space.
+ * Instead, calculate it here so it's possible to fail gracefully.
++ *
++ * In the case of argc = 0, make sure there is space for adding a
++ * empty string (which will bump argc to 1), to ensure confused
++ * userspace programs don't start processing from argv[1], thinking
++ * argc can never be 0, to keep them from walking envp by accident.
++ * See do_execveat_common().
+ */
+- ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
++ ptr_size = (max(bprm->argc, 1) + bprm->envc) * sizeof(void *);
+ if (limit <= ptr_size)
+ return -E2BIG;
+ limit -= ptr_size;
+@@ -1852,7 +1858,7 @@ out:
* SIGSEGV.
*/
if (bprm->point_of_no_return && !fatal_signal_pending(current))
@@ -123720,6 +186201,45 @@ index a098c133d8d74..ac7b51b51f38a 100644
out_unmark:
current->fs->in_exec = 0;
+@@ -1895,6 +1901,9 @@ static int do_execveat_common(int fd, struct filename *filename,
+ }
+
+ retval = count(argv, MAX_ARG_STRINGS);
++ if (retval == 0)
++ pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n",
++ current->comm, bprm->filename);
+ if (retval < 0)
+ goto out_free;
+ bprm->argc = retval;
+@@ -1921,6 +1930,19 @@ static int do_execveat_common(int fd, struct filename *filename,
+ if (retval < 0)
+ goto out_free;
+
++ /*
++ * When argv is empty, add an empty string ("") as argv[0] to
++ * ensure confused userspace programs that start processing
++ * from argv[1] won't end up walking envp. See also
++ * bprm_stack_limits().
++ */
++ if (bprm->argc == 0) {
++ retval = copy_string_kernel("", bprm);
++ if (retval < 0)
++ goto out_free;
++ bprm->argc = 1;
++ }
++
+ retval = bprm_execve(bprm, fd, filename, flags);
+ out_free:
+ free_bprm(bprm);
+@@ -1949,6 +1971,8 @@ int kernel_execve(const char *kernel_filename,
+ }
+
+ retval = count_strings_kernel(argv);
++ if (WARN_ON_ONCE(retval == 0))
++ retval = -EINVAL;
+ if (retval < 0)
+ goto out_free;
+ bprm->argc = retval;
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 6af0191b648f1..d890fd34bb2d0 100644
--- a/fs/exfat/file.c
@@ -123855,8 +186375,26 @@ index 5539ffc20d164..4b5d02b1df585 100644
exfat_save_attr(inode, ATTR_SUBDIR);
inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index d8d580b609baa..3d21279fe2cb5 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -753,8 +753,12 @@ static loff_t ext2_max_size(int bits)
+ res += 1LL << (bits-2);
+ res += 1LL << (2*(bits-2));
+ res += 1LL << (3*(bits-2));
++ /* Compute how many metadata blocks are needed */
++ meta_blocks = 1;
++ meta_blocks += 1 + ppb;
++ meta_blocks += 1 + ppb + ppb * ppb;
+ /* Does block tree limit file size? */
+- if (res < upper_limit)
++ if (res + meta_blocks <= upper_limit)
+ goto check_lfs;
+
+ res = upper_limit;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
-index 3825195539d74..db981619f6c8e 100644
+index 3825195539d74..a0a9878578949 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1724,9 +1724,9 @@ struct ext4_sb_info {
@@ -123892,7 +186430,18 @@ index 3825195539d74..db981619f6c8e 100644
};
static inline void ext4_set_mount_flag(struct super_block *sb, int bit)
-@@ -2924,9 +2921,7 @@ void __ext4_fc_track_create(handle_t *handle, struct inode *inode,
+@@ -2270,6 +2267,10 @@ static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
+ * Structure of a directory entry
+ */
+ #define EXT4_NAME_LEN 255
++/*
++ * Base length of the ext4 directory entry excluding the name length
++ */
++#define EXT4_BASE_DIR_LEN (sizeof(struct ext4_dir_entry_2) - EXT4_NAME_LEN)
+
+ struct ext4_dir_entry {
+ __le32 inode; /* Inode number */
+@@ -2924,9 +2925,7 @@ void __ext4_fc_track_create(handle_t *handle, struct inode *inode,
struct dentry *dentry);
void ext4_fc_track_create(handle_t *handle, struct dentry *dentry);
void ext4_fc_track_inode(handle_t *handle, struct inode *inode);
@@ -123903,7 +186452,7 @@ index 3825195539d74..db981619f6c8e 100644
void ext4_fc_start_update(struct inode *inode);
void ext4_fc_stop_update(struct inode *inode);
void ext4_fc_del(struct inode *inode);
-@@ -2934,6 +2929,10 @@ bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block);
+@@ -2934,6 +2933,10 @@ bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block);
void ext4_fc_replay_cleanup(struct super_block *sb);
int ext4_fc_commit(journal_t *journal, tid_t commit_tid);
int __init ext4_fc_init_dentry_cache(void);
@@ -123914,6 +186463,15 @@ index 3825195539d74..db981619f6c8e 100644
/* mballoc.c */
extern const struct seq_operations ext4_mb_seq_groups_ops;
+@@ -3028,7 +3031,7 @@ extern int ext4_inode_attach_jinode(struct inode *inode);
+ extern int ext4_can_truncate(struct inode *inode);
+ extern int ext4_truncate(struct inode *);
+ extern int ext4_break_layouts(struct inode *);
+-extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
++extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
+ extern void ext4_set_inode_flags(struct inode *, bool init);
+ extern int ext4_alloc_da_blocks(struct inode *inode);
+ extern void ext4_set_aops(struct inode *inode);
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 6def7339056db..3477a16d08aee 100644
--- a/fs/ext4/ext4_jbd2.c
@@ -123928,7 +186486,7 @@ index 6def7339056db..3477a16d08aee 100644
handle->h_revoke_credits >= revoke_cred)
return 0;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
-index 0e02571f2f828..b81c008e66755 100644
+index 0e02571f2f828..44d00951e6092 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -136,15 +136,25 @@ int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode,
@@ -124176,7 +186734,30 @@ index 0e02571f2f828..b81c008e66755 100644
if (IS_ERR(bh)) {
/* should we reset i_size? */
err = PTR_ERR(bh);
-@@ -4612,8 +4645,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+@@ -4471,9 +4504,9 @@ retry:
+ return ret > 0 ? ret2 : ret;
+ }
+
+-static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len);
++static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len);
+
+-static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len);
++static int ext4_insert_range(struct file *file, loff_t offset, loff_t len);
+
+ static long ext4_zero_range(struct file *file, loff_t offset,
+ loff_t len, int mode)
+@@ -4545,6 +4578,10 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ inode_dio_wait(inode);
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_mutex;
++
+ /* Preallocate the range including the unaligned edges */
+ if (partial_begin || partial_end) {
+ ret = ext4_alloc_file_blocks(file,
+@@ -4612,8 +4649,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
ret = ext4_mark_inode_dirty(handle, inode);
if (unlikely(ret))
goto out_handle;
@@ -124185,7 +186766,42 @@ index 0e02571f2f828..b81c008e66755 100644
/* Zero out partial block at the edges of the range */
ret = ext4_zero_partial_blocks(handle, inode, offset, len);
if (ret >= 0)
-@@ -4977,36 +5008,6 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
+@@ -4665,7 +4700,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ ext4_fc_start_update(inode);
+
+ if (mode & FALLOC_FL_PUNCH_HOLE) {
+- ret = ext4_punch_hole(inode, offset, len);
++ ret = ext4_punch_hole(file, offset, len);
+ goto exit;
+ }
+
+@@ -4674,12 +4709,12 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ goto exit;
+
+ if (mode & FALLOC_FL_COLLAPSE_RANGE) {
+- ret = ext4_collapse_range(inode, offset, len);
++ ret = ext4_collapse_range(file, offset, len);
+ goto exit;
+ }
+
+ if (mode & FALLOC_FL_INSERT_RANGE) {
+- ret = ext4_insert_range(inode, offset, len);
++ ret = ext4_insert_range(file, offset, len);
+ goto exit;
+ }
+
+@@ -4715,6 +4750,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ inode_dio_wait(inode);
+
++ ret = file_modified(file);
++ if (ret)
++ goto out;
++
+ ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags);
+ if (ret)
+ goto out;
+@@ -4977,36 +5016,6 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
return ext4_fill_es_cache_info(inode, start_blk, len_blks, fieinfo);
}
@@ -124222,7 +186838,7 @@ index 0e02571f2f828..b81c008e66755 100644
/*
* ext4_ext_shift_path_extents:
* Shift the extents of a path structure lying between path[depth].p_ext
-@@ -5021,6 +5022,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
+@@ -5021,6 +5030,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
int depth, err = 0;
struct ext4_extent *ex_start, *ex_last;
bool update = false;
@@ -124230,7 +186846,7 @@ index 0e02571f2f828..b81c008e66755 100644
depth = path->p_depth;
while (depth >= 0) {
-@@ -5030,13 +5032,26 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
+@@ -5030,13 +5040,26 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
return -EFSCORRUPTED;
ex_last = EXT_LAST_EXTENT(path[depth].p_hdr);
@@ -124261,7 +186877,7 @@ index 0e02571f2f828..b81c008e66755 100644
while (ex_start <= ex_last) {
if (SHIFT == SHIFT_LEFT) {
-@@ -5067,7 +5082,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
+@@ -5067,7 +5090,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
}
/* Update index too */
@@ -124270,7 +186886,7 @@ index 0e02571f2f828..b81c008e66755 100644
if (err)
goto out;
-@@ -5106,6 +5121,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+@@ -5106,6 +5129,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
int ret = 0, depth;
struct ext4_extent *extent;
ext4_lblk_t stop, *iterator, ex_start, ex_end;
@@ -124278,7 +186894,7 @@ index 0e02571f2f828..b81c008e66755 100644
/* Let path point to the last extent */
path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL,
-@@ -5159,11 +5175,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+@@ -5159,11 +5183,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
* till we reach stop. In case of right shift, iterator points to stop
* and it is decreased till we reach start.
*/
@@ -124294,7 +186910,7 @@ index 0e02571f2f828..b81c008e66755 100644
/*
* Its safe to start updating extents. Start and stop are unsigned, so
* in case of right shift if extent with 0 block is reached, iterator
-@@ -5192,6 +5212,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+@@ -5192,6 +5220,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
}
}
@@ -124302,7 +186918,7 @@ index 0e02571f2f828..b81c008e66755 100644
if (SHIFT == SHIFT_LEFT) {
extent = EXT_LAST_EXTENT(path[depth].p_hdr);
*iterator = le32_to_cpu(extent->ee_block) +
-@@ -5210,6 +5231,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+@@ -5210,6 +5239,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
}
ret = ext4_ext_shift_path_extents(path, shift, inode,
handle, SHIFT);
@@ -124312,7 +186928,29 @@ index 0e02571f2f828..b81c008e66755 100644
if (ret)
break;
}
-@@ -5316,7 +5340,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
+@@ -5224,8 +5256,9 @@ out:
+ * This implements the fallocate's collapse range functionality for ext4
+ * Returns: 0 and non-zero on error.
+ */
+-static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
++static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
+ {
++ struct inode *inode = file_inode(file);
+ struct super_block *sb = inode->i_sb;
+ struct address_space *mapping = inode->i_mapping;
+ ext4_lblk_t punch_start, punch_stop;
+@@ -5277,6 +5310,10 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
+ /* Wait for existing dio to complete */
+ inode_dio_wait(inode);
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_mutex;
++
+ /*
+ * Prevent page faults from reinstantiating pages we have released from
+ * page cache.
+@@ -5316,7 +5353,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
ret = PTR_ERR(handle);
goto out_mmap;
}
@@ -124321,7 +186959,7 @@ index 0e02571f2f828..b81c008e66755 100644
down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode, 0);
-@@ -5355,7 +5379,6 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
+@@ -5355,7 +5392,6 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
out_stop:
ext4_journal_stop(handle);
@@ -124329,7 +186967,29 @@ index 0e02571f2f828..b81c008e66755 100644
out_mmap:
filemap_invalidate_unlock(mapping);
out_mutex:
-@@ -5457,7 +5480,7 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
+@@ -5371,8 +5407,9 @@ out_mutex:
+ * by len bytes.
+ * Returns 0 on success, error otherwise.
+ */
+-static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
++static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
+ {
++ struct inode *inode = file_inode(file);
+ struct super_block *sb = inode->i_sb;
+ struct address_space *mapping = inode->i_mapping;
+ handle_t *handle;
+@@ -5429,6 +5466,10 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
+ /* Wait for existing dio to complete */
+ inode_dio_wait(inode);
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_mutex;
++
+ /*
+ * Prevent page faults from reinstantiating pages we have released from
+ * page cache.
+@@ -5457,7 +5498,7 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
ret = PTR_ERR(handle);
goto out_mmap;
}
@@ -124338,7 +186998,7 @@ index 0e02571f2f828..b81c008e66755 100644
/* Expand file to avoid data loss if there is error while shifting */
inode->i_size += len;
-@@ -5532,7 +5555,6 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
+@@ -5532,7 +5573,6 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
out_stop:
ext4_journal_stop(handle);
@@ -124346,7 +187006,7 @@ index 0e02571f2f828..b81c008e66755 100644
out_mmap:
filemap_invalidate_unlock(mapping);
out_mutex:
-@@ -6072,11 +6094,15 @@ int ext4_ext_clear_bb(struct inode *inode)
+@@ -6072,11 +6112,15 @@ int ext4_ext_clear_bb(struct inode *inode)
ext4_mb_mark_bb(inode->i_sb,
path[j].p_block, 1, 0);
@@ -124990,8 +187650,31 @@ index 937c381b4c85e..083ad1cb705a7 100644
};
#define EXT4_FC_REPLAY_REALLOC_INCREMENT 4
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index ac0e11bbb4450..b25c1f8f7c4f1 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -74,7 +74,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ return generic_file_read_iter(iocb, to);
+ }
+
+- ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL, 0);
++ ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL, 0, 0);
+ inode_unlock_shared(inode);
+
+ file_accessed(iocb->ki_filp);
+@@ -566,7 +566,8 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ if (ilock_shared)
+ iomap_ops = &ext4_iomap_overwrite_ops;
+ ret = iomap_dio_rw(iocb, from, iomap_ops, &ext4_dio_write_ops,
+- (unaligned_io || extend) ? IOMAP_DIO_FORCE_WAIT : 0);
++ (unaligned_io || extend) ? IOMAP_DIO_FORCE_WAIT : 0,
++ 0);
+ if (ret == -ENOTBLK)
+ ret = 0;
+
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
-index 39a1ab129fdc9..d091133a4b460 100644
+index 39a1ab129fdc9..46fdb40c3962c 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1133,7 +1133,15 @@ static void ext4_restore_inline_data(handle_t *handle, struct inode *inode,
@@ -125011,8 +187694,57 @@ index 39a1ab129fdc9..d091133a4b460 100644
ext4_write_inline_data(inode, iloc, buf, 0, inline_size);
ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
}
+@@ -1780,19 +1788,20 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ void *inline_pos;
+ unsigned int offset;
+ struct ext4_dir_entry_2 *de;
+- bool ret = true;
++ bool ret = false;
+
+ err = ext4_get_inode_loc(dir, &iloc);
+ if (err) {
+ EXT4_ERROR_INODE_ERR(dir, -err,
+ "error %d getting inode %lu block",
+ err, dir->i_ino);
+- return true;
++ return false;
+ }
+
+ down_read(&EXT4_I(dir)->xattr_sem);
+ if (!ext4_has_inline_data(dir)) {
+ *has_inline_data = 0;
++ ret = true;
+ goto out;
+ }
+
+@@ -1801,7 +1810,6 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ ext4_warning(dir->i_sb,
+ "bad inline directory (dir #%lu) - no `..'",
+ dir->i_ino);
+- ret = true;
+ goto out;
+ }
+
+@@ -1820,16 +1828,15 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ dir->i_ino, le32_to_cpu(de->inode),
+ le16_to_cpu(de->rec_len), de->name_len,
+ inline_size);
+- ret = true;
+ goto out;
+ }
+ if (le32_to_cpu(de->inode)) {
+- ret = false;
+ goto out;
+ }
+ offset += ext4_rec_len_from_disk(de->rec_len, inline_size);
+ }
+
++ ret = true;
+ out:
+ up_read(&EXT4_I(dir)->xattr_sem);
+ brelse(iloc.bh);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
-index 0f06305167d5a..22a5140546fb6 100644
+index 0f06305167d5a..db73b49bd9795 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -337,7 +337,7 @@ stop_handle:
@@ -125143,7 +187875,89 @@ index 0f06305167d5a..22a5140546fb6 100644
brelse(inode_bh);
return ret;
}
-@@ -4374,7 +4355,7 @@ has_buffer:
+@@ -2011,6 +1992,15 @@ static int ext4_writepage(struct page *page,
+ else
+ len = PAGE_SIZE;
+
++ /* Should never happen but for bugs in other kernel subsystems */
++ if (!page_has_buffers(page)) {
++ ext4_warning_inode(inode,
++ "page %lu does not have buffers attached", page->index);
++ ClearPageDirty(page);
++ unlock_page(page);
++ return 0;
++ }
++
+ page_bufs = page_buffers(page);
+ /*
+ * We cannot do block allocation or other extent handling in this
+@@ -2614,6 +2604,22 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
+ wait_on_page_writeback(page);
+ BUG_ON(PageWriteback(page));
+
++ /*
++ * Should never happen but for buggy code in
++ * other subsystems that call
++ * set_page_dirty() without properly warning
++ * the file system first. See [1] for more
++ * information.
++ *
++ * [1] https://lore.kernel.org/linux-mm/20180103100430.GE4911@quack2.suse.cz
++ */
++ if (!page_has_buffers(page)) {
++ ext4_warning_inode(mpd->inode, "page %lu does not have buffers attached", page->index);
++ ClearPageDirty(page);
++ unlock_page(page);
++ continue;
++ }
++
+ if (mpd->map.m_len == 0)
+ mpd->first_page = page->index;
+ mpd->next_page = page->index + 1;
+@@ -3933,12 +3939,14 @@ int ext4_break_layouts(struct inode *inode)
+ * Returns: 0 on success or negative on failure
+ */
+
+-int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
++int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+ {
++ struct inode *inode = file_inode(file);
+ struct super_block *sb = inode->i_sb;
+ ext4_lblk_t first_block, stop_block;
+ struct address_space *mapping = inode->i_mapping;
+- loff_t first_block_offset, last_block_offset;
++ loff_t first_block_offset, last_block_offset, max_length;
++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ handle_t *handle;
+ unsigned int credits;
+ int ret = 0, ret2 = 0;
+@@ -3981,6 +3989,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
+ offset;
+ }
+
++ /*
++ * For punch hole the length + offset needs to be within one block
++ * before last range. Adjust the length if it goes beyond that limit.
++ */
++ max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
++ if (offset + length > max_length)
++ length = max_length - offset;
++
+ if (offset & (sb->s_blocksize - 1) ||
+ (offset + length) & (sb->s_blocksize - 1)) {
+ /*
+@@ -3996,6 +4012,10 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ inode_dio_wait(inode);
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_mutex;
++
+ /*
+ * Prevent page faults from reinstantiating pages we have released from
+ * page cache.
+@@ -4374,7 +4394,7 @@ has_buffer:
static int __ext4_get_inode_loc_noinmem(struct inode *inode,
struct ext4_iloc *iloc)
{
@@ -125152,7 +187966,7 @@ index 0f06305167d5a..22a5140546fb6 100644
int ret;
ret = __ext4_get_inode_loc(inode->i_sb, inode->i_ino, iloc, 0,
-@@ -4389,7 +4370,7 @@ static int __ext4_get_inode_loc_noinmem(struct inode *inode,
+@@ -4389,7 +4409,7 @@ static int __ext4_get_inode_loc_noinmem(struct inode *inode,
int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
{
@@ -125161,7 +187975,7 @@ index 0f06305167d5a..22a5140546fb6 100644
int ret;
/* We have all inode data except xattrs in memory here. */
-@@ -5416,8 +5397,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
+@@ -5416,8 +5436,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
ext4_fc_track_range(handle, inode,
(attr->ia_size > 0 ? attr->ia_size - 1 : 0) >>
inode->i_sb->s_blocksize_bits,
@@ -125171,7 +187985,7 @@ index 0f06305167d5a..22a5140546fb6 100644
else
ext4_fc_track_range(
handle, inode,
-@@ -5989,7 +5969,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
+@@ -5989,7 +6008,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
return PTR_ERR(handle);
ext4_fc_mark_ineligible(inode->i_sb,
@@ -125220,10 +188034,165 @@ index 606dee9e08a32..f61b59045c6d3 100644
if (ret < 0)
return ret;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 72bfac2d6dce9..74e3286d0e262 100644
+index 72bfac2d6dce9..46608723b6ed7 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
-@@ -4814,7 +4814,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+@@ -1000,7 +1000,7 @@ static inline int should_optimize_scan(struct ext4_allocation_context *ac)
+ return 0;
+ if (ac->ac_criteria >= 2)
+ return 0;
+- if (ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))
++ if (!ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))
+ return 0;
+ return 1;
+ }
+@@ -3899,69 +3899,95 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ ext4_group_t group;
+ ext4_grpblk_t blkoff;
+- int i, clen, err;
++ int i, err;
+ int already;
++ unsigned int clen, clen_changed, thisgrp_len;
+
+- clen = EXT4_B2C(sbi, len);
++ while (len > 0) {
++ ext4_get_group_no_and_offset(sb, block, &group, &blkoff);
+
+- ext4_get_group_no_and_offset(sb, block, &group, &blkoff);
+- bitmap_bh = ext4_read_block_bitmap(sb, group);
+- if (IS_ERR(bitmap_bh)) {
+- err = PTR_ERR(bitmap_bh);
+- bitmap_bh = NULL;
+- goto out_err;
+- }
++ /*
++ * Check to see if we are freeing blocks across a group
++ * boundary.
++ * In case of flex_bg, this can happen that (block, len) may
++ * span across more than one group. In that case we need to
++ * get the corresponding group metadata to work with.
++ * For this we have goto again loop.
++ */
++ thisgrp_len = min_t(unsigned int, (unsigned int)len,
++ EXT4_BLOCKS_PER_GROUP(sb) - EXT4_C2B(sbi, blkoff));
++ clen = EXT4_NUM_B2C(sbi, thisgrp_len);
+
+- err = -EIO;
+- gdp = ext4_get_group_desc(sb, group, &gdp_bh);
+- if (!gdp)
+- goto out_err;
++ bitmap_bh = ext4_read_block_bitmap(sb, group);
++ if (IS_ERR(bitmap_bh)) {
++ err = PTR_ERR(bitmap_bh);
++ bitmap_bh = NULL;
++ break;
++ }
+
+- ext4_lock_group(sb, group);
+- already = 0;
+- for (i = 0; i < clen; i++)
+- if (!mb_test_bit(blkoff + i, bitmap_bh->b_data) == !state)
+- already++;
++ err = -EIO;
++ gdp = ext4_get_group_desc(sb, group, &gdp_bh);
++ if (!gdp)
++ break;
+
+- if (state)
+- ext4_set_bits(bitmap_bh->b_data, blkoff, clen);
+- else
+- mb_test_and_clear_bits(bitmap_bh->b_data, blkoff, clen);
+- if (ext4_has_group_desc_csum(sb) &&
+- (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
+- gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+- ext4_free_group_clusters_set(sb, gdp,
+- ext4_free_clusters_after_init(sb,
+- group, gdp));
+- }
+- if (state)
+- clen = ext4_free_group_clusters(sb, gdp) - clen + already;
+- else
+- clen = ext4_free_group_clusters(sb, gdp) + clen - already;
++ ext4_lock_group(sb, group);
++ already = 0;
++ for (i = 0; i < clen; i++)
++ if (!mb_test_bit(blkoff + i, bitmap_bh->b_data) ==
++ !state)
++ already++;
++
++ clen_changed = clen - already;
++ if (state)
++ ext4_set_bits(bitmap_bh->b_data, blkoff, clen);
++ else
++ mb_test_and_clear_bits(bitmap_bh->b_data, blkoff, clen);
++ if (ext4_has_group_desc_csum(sb) &&
++ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
++ gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
++ ext4_free_group_clusters_set(sb, gdp,
++ ext4_free_clusters_after_init(sb, group, gdp));
++ }
++ if (state)
++ clen = ext4_free_group_clusters(sb, gdp) - clen_changed;
++ else
++ clen = ext4_free_group_clusters(sb, gdp) + clen_changed;
+
+- ext4_free_group_clusters_set(sb, gdp, clen);
+- ext4_block_bitmap_csum_set(sb, group, gdp, bitmap_bh);
+- ext4_group_desc_csum_set(sb, group, gdp);
++ ext4_free_group_clusters_set(sb, gdp, clen);
++ ext4_block_bitmap_csum_set(sb, group, gdp, bitmap_bh);
++ ext4_group_desc_csum_set(sb, group, gdp);
+
+- ext4_unlock_group(sb, group);
++ ext4_unlock_group(sb, group);
+
+- if (sbi->s_log_groups_per_flex) {
+- ext4_group_t flex_group = ext4_flex_group(sbi, group);
++ if (sbi->s_log_groups_per_flex) {
++ ext4_group_t flex_group = ext4_flex_group(sbi, group);
++ struct flex_groups *fg = sbi_array_rcu_deref(sbi,
++ s_flex_groups, flex_group);
+
+- atomic64_sub(len,
+- &sbi_array_rcu_deref(sbi, s_flex_groups,
+- flex_group)->free_clusters);
++ if (state)
++ atomic64_sub(clen_changed, &fg->free_clusters);
++ else
++ atomic64_add(clen_changed, &fg->free_clusters);
++
++ }
++
++ err = ext4_handle_dirty_metadata(NULL, NULL, bitmap_bh);
++ if (err)
++ break;
++ sync_dirty_buffer(bitmap_bh);
++ err = ext4_handle_dirty_metadata(NULL, NULL, gdp_bh);
++ sync_dirty_buffer(gdp_bh);
++ if (err)
++ break;
++
++ block += thisgrp_len;
++ len -= thisgrp_len;
++ brelse(bitmap_bh);
++ BUG_ON(len < 0);
+ }
+
+- err = ext4_handle_dirty_metadata(NULL, NULL, bitmap_bh);
+ if (err)
+- goto out_err;
+- sync_dirty_buffer(bitmap_bh);
+- err = ext4_handle_dirty_metadata(NULL, NULL, gdp_bh);
+- sync_dirty_buffer(gdp_bh);
+-
+-out_err:
+- brelse(bitmap_bh);
++ brelse(bitmap_bh);
+ }
+
+ /*
+@@ -4814,7 +4840,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
*/
static noinline_for_stack int
ext4_mb_discard_group_preallocations(struct super_block *sb,
@@ -125232,7 +188201,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
{
struct ext4_group_info *grp = ext4_get_group_info(sb, group);
struct buffer_head *bitmap_bh = NULL;
-@@ -4822,8 +4822,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+@@ -4822,8 +4848,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
struct list_head list;
struct ext4_buddy e4b;
int err;
@@ -125242,7 +188211,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
mb_debug(sb, "discard preallocation for group %u\n", group);
if (list_empty(&grp->bb_prealloc_list))
-@@ -4846,19 +4845,14 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+@@ -4846,19 +4871,14 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
goto out_dbg;
}
@@ -125263,7 +188232,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
continue;
}
if (pa->pa_deleted) {
-@@ -4898,22 +4892,13 @@ repeat:
+@@ -4898,22 +4918,13 @@ repeat:
call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
}
@@ -125288,7 +188257,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
}
/*
-@@ -5455,13 +5440,24 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
+@@ -5455,13 +5466,24 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
{
ext4_group_t i, ngroups = ext4_get_groups_count(sb);
int ret;
@@ -125315,7 +188284,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
}
return freed;
-@@ -5757,7 +5753,8 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle,
+@@ -5757,7 +5779,8 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle,
struct super_block *sb = ar->inode->i_sb;
ext4_group_t group;
ext4_grpblk_t blkoff;
@@ -125325,7 +188294,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
ext4_fsblk_t goal, block;
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
-@@ -5779,19 +5776,26 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle,
+@@ -5779,19 +5802,26 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle,
ext4_get_group_no_and_offset(sb,
max(ext4_group_first_block_no(sb, group), goal),
NULL, &blkoff);
@@ -125360,7 +188329,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
block = ext4_group_first_block_no(sb, group) + i;
ext4_mb_mark_bb(sb, block, 1, 1);
-@@ -6405,6 +6409,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+@@ -6405,6 +6435,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
*/
int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
{
@@ -125368,7 +188337,7 @@ index 72bfac2d6dce9..74e3286d0e262 100644
struct ext4_group_info *grp;
ext4_group_t group, first_group, last_group;
ext4_grpblk_t cnt = 0, first_cluster, last_cluster;
-@@ -6423,6 +6428,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+@@ -6423,6 +6454,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
start >= max_blks ||
range->len < sb->s_blocksize)
return -EINVAL;
@@ -125444,9 +188413,66 @@ index 7e0b4f81c6c06..ff8916e1d38e9 100644
memset(&lb, 0, sizeof(lb));
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
-index da7698341d7d3..192ea90e757cc 100644
+index da7698341d7d3..19c620118e628 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
+@@ -1466,10 +1466,10 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+
+ de = (struct ext4_dir_entry_2 *)search_buf;
+ dlimit = search_buf + buf_size;
+- while ((char *) de < dlimit) {
++ while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) {
+ /* this code is executed quadratically often */
+ /* do minimal checking `by hand' */
+- if ((char *) de + de->name_len <= dlimit &&
++ if (de->name + de->name_len <= dlimit &&
+ ext4_match(dir, fname, de)) {
+ /* found a match - just to be sure, do
+ * a full check */
+@@ -2997,14 +2997,14 @@ bool ext4_empty_dir(struct inode *inode)
+ if (inode->i_size < ext4_dir_rec_len(1, NULL) +
+ ext4_dir_rec_len(2, NULL)) {
+ EXT4_ERROR_INODE(inode, "invalid size");
+- return true;
++ return false;
+ }
+ /* The first directory block must not be a hole,
+ * so treat it as DIRENT_HTREE
+ */
+ bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
+ if (IS_ERR(bh))
+- return true;
++ return false;
+
+ de = (struct ext4_dir_entry_2 *) bh->b_data;
+ if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
+@@ -3012,7 +3012,7 @@ bool ext4_empty_dir(struct inode *inode)
+ le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
+ ext4_warning_inode(inode, "directory missing '.'");
+ brelse(bh);
+- return true;
++ return false;
+ }
+ offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
+ de = ext4_next_entry(de, sb->s_blocksize);
+@@ -3021,7 +3021,7 @@ bool ext4_empty_dir(struct inode *inode)
+ le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
+ ext4_warning_inode(inode, "directory missing '..'");
+ brelse(bh);
+- return true;
++ return false;
+ }
+ offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
+ while (offset < inode->i_size) {
+@@ -3035,7 +3035,7 @@ bool ext4_empty_dir(struct inode *inode)
+ continue;
+ }
+ if (IS_ERR(bh))
+- return true;
++ return false;
+ }
+ de = (struct ext4_dir_entry_2 *) (bh->b_data +
+ (offset & (sb->s_blocksize - 1)));
@@ -3889,7 +3889,7 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
* dirents in directories.
*/
@@ -125465,11 +188491,60 @@ index da7698341d7d3..192ea90e757cc 100644
if (old.dir_bh) {
retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino);
if (retval)
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index f038d578d8d8f..18977ff8e4939 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -134,8 +134,10 @@ static void ext4_finish_bio(struct bio *bio)
+ continue;
+ }
+ clear_buffer_async_write(bh);
+- if (bio->bi_status)
++ if (bio->bi_status) {
++ set_buffer_write_io_error(bh);
+ buffer_io_error(bh);
++ }
+ } while ((bh = bh->b_this_page) != head);
+ spin_unlock_irqrestore(&head->b_uptodate_lock, flags);
+ if (!under_io) {
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
-index 88d5d274a8684..fd4d34deb9fc6 100644
+index 88d5d274a8684..d12f11c6fbf25 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
-@@ -3263,9 +3263,9 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+@@ -1167,20 +1167,25 @@ static void ext4_put_super(struct super_block *sb)
+ int aborted = 0;
+ int i, err;
+
+- ext4_unregister_li_request(sb);
+- ext4_quota_off_umount(sb);
+-
+- flush_work(&sbi->s_error_work);
+- destroy_workqueue(sbi->rsv_conversion_wq);
+- ext4_release_orphan_info(sb);
+-
+ /*
+ * Unregister sysfs before destroying jbd2 journal.
+ * Since we could still access attr_journal_task attribute via sysfs
+ * path which could have sbi->s_journal->j_task as NULL
++ * Unregister sysfs before flush sbi->s_error_work.
++ * Since user may read /proc/fs/ext4/xx/mb_groups during umount, If
++ * read metadata verify failed then will queue error work.
++ * flush_stashed_error_work will call start_this_handle may trigger
++ * BUG_ON.
+ */
+ ext4_unregister_sysfs(sb);
+
++ ext4_unregister_li_request(sb);
++ ext4_quota_off_umount(sb);
++
++ flush_work(&sbi->s_error_work);
++ destroy_workqueue(sbi->rsv_conversion_wq);
++ ext4_release_orphan_info(sb);
++
+ if (sbi->s_journal) {
+ aborted = is_journal_aborted(sbi->s_journal);
+ err = jbd2_journal_destroy(sbi->s_journal);
+@@ -3263,9 +3268,9 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
struct super_block *sb = elr->lr_super;
ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
ext4_group_t group = elr->lr_next_group;
@@ -125480,7 +188555,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) {
elr->lr_next_group = ext4_mb_prefetch(sb, group,
-@@ -3302,14 +3302,13 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+@@ -3302,14 +3307,13 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
ret = 1;
if (!ret) {
@@ -125498,7 +188573,20 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
}
elr->lr_next_sched = jiffies + elr->lr_timeout;
elr->lr_next_group = group + 1;
-@@ -4614,14 +4613,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+@@ -3698,9 +3702,11 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
+ ext4_fsblk_t first_block, last_block, b;
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ int s, j, count = 0;
++ int has_super = ext4_bg_has_super(sb, grp);
+
+ if (!ext4_has_feature_bigalloc(sb))
+- return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
++ return (has_super + ext4_bg_num_gdb(sb, grp) +
++ (has_super ? le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0) +
+ sbi->s_itb_per_group + 2);
+
+ first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
+@@ -4614,14 +4620,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
/* Initialize fast commit stuff */
atomic_set(&sbi->s_fc_subtid, 0);
@@ -125514,7 +188602,29 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
spin_lock_init(&sbi->s_fc_lock);
memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats));
sbi->s_fc_replay_state.fc_regions = NULL;
-@@ -6267,10 +6265,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+@@ -4788,9 +4793,18 @@ no_journal:
+ * Get the # of file system overhead blocks from the
+ * superblock if present.
+ */
+- if (es->s_overhead_clusters)
+- sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
+- else {
++ sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
++ /* ignore the precalculated value if it is ridiculous */
++ if (sbi->s_overhead > ext4_blocks_count(es))
++ sbi->s_overhead = 0;
++ /*
++ * If the bigalloc feature is not enabled recalculating the
++ * overhead doesn't take long, so we might as well just redo
++ * it to make sure we are using the correct value.
++ */
++ if (!ext4_has_feature_bigalloc(sb))
++ sbi->s_overhead = 0;
++ if (sbi->s_overhead == 0) {
+ err = ext4_calculate_overhead(sb);
+ if (err)
+ goto failed_mount_wq;
+@@ -6267,10 +6281,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA);
err = dquot_quota_on(sb, type, format_id, path);
@@ -125526,7 +188636,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
struct inode *inode = d_inode(path->dentry);
handle_t *handle;
-@@ -6290,7 +6285,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+@@ -6290,7 +6301,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
ext4_journal_stop(handle);
unlock_inode:
inode_unlock(inode);
@@ -125539,7 +188649,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
return err;
}
-@@ -6353,8 +6353,19 @@ int ext4_enable_quotas(struct super_block *sb)
+@@ -6353,8 +6369,19 @@ int ext4_enable_quotas(struct super_block *sb)
"Failed to enable quota tracking "
"(type=%d, err=%d). Please run "
"e2fsck to fix.", type, err);
@@ -125560,7 +188670,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
return err;
}
-@@ -6458,7 +6469,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+@@ -6458,7 +6485,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
struct buffer_head *bh;
handle_t *handle = journal_current_handle();
@@ -125569,7 +188679,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
" cancelled because transaction is not started",
(unsigned long long)off, (unsigned long long)len);
-@@ -6641,6 +6652,7 @@ static int __init ext4_init_fs(void)
+@@ -6641,6 +6668,7 @@ static int __init ext4_init_fs(void)
out:
unregister_as_ext2();
unregister_as_ext3();
@@ -125577,7 +188687,7 @@ index 88d5d274a8684..fd4d34deb9fc6 100644
out05:
destroy_inodecache();
out1:
-@@ -6667,6 +6679,7 @@ static void __exit ext4_exit_fs(void)
+@@ -6667,6 +6695,7 @@ static void __exit ext4_exit_fs(void)
unregister_as_ext2();
unregister_as_ext3();
unregister_filesystem(&ext4_fs_type);
@@ -125617,10 +188727,38 @@ index 1e0fc1ed845bf..0423253490986 100644
error = 0;
cleanup:
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
-index 83e9bc0f91ffd..99fced979718e 100644
+index 83e9bc0f91ffd..1ff32926e1999 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
-@@ -1162,7 +1162,8 @@ static bool __need_flush_quota(struct f2fs_sb_info *sbi)
+@@ -867,6 +867,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
+ struct page *cp_page_1 = NULL, *cp_page_2 = NULL;
+ struct f2fs_checkpoint *cp_block = NULL;
+ unsigned long long cur_version = 0, pre_version = 0;
++ unsigned int cp_blocks;
+ int err;
+
+ err = get_checkpoint_version(sbi, cp_addr, &cp_block,
+@@ -874,15 +875,16 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
+ if (err)
+ return NULL;
+
+- if (le32_to_cpu(cp_block->cp_pack_total_block_count) >
+- sbi->blocks_per_seg) {
++ cp_blocks = le32_to_cpu(cp_block->cp_pack_total_block_count);
++
++ if (cp_blocks > sbi->blocks_per_seg || cp_blocks <= F2FS_CP_PACKS) {
+ f2fs_warn(sbi, "invalid cp_pack_total_block_count:%u",
+ le32_to_cpu(cp_block->cp_pack_total_block_count));
+ goto invalid_cp;
+ }
+ pre_version = *version;
+
+- cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
++ cp_addr += cp_blocks - 1;
+ err = get_checkpoint_version(sbi, cp_addr, &cp_block,
+ &cp_page_2, version);
+ if (err)
+@@ -1162,7 +1164,8 @@ static bool __need_flush_quota(struct f2fs_sb_info *sbi)
if (!is_journalled_quota(sbi))
return false;
@@ -125630,7 +188768,7 @@ index 83e9bc0f91ffd..99fced979718e 100644
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) {
ret = false;
} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) {
-@@ -1304,8 +1305,8 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+@@ -1304,8 +1307,8 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
unsigned long flags;
if (cpc->reason & CP_UMOUNT) {
@@ -125642,10 +188780,23 @@ index 83e9bc0f91ffd..99fced979718e 100644
f2fs_notice(sbi, "Disable nat_bits due to no space");
} else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
-index c1bf9ad4c2207..58d255d3a518a 100644
+index c1bf9ad4c2207..6adf047259546 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
-@@ -1448,25 +1448,38 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
+@@ -312,10 +312,9 @@ static int lz4_decompress_pages(struct decompress_io_ctx *dic)
+ }
+
+ if (ret != PAGE_SIZE << dic->log_cluster_size) {
+- printk_ratelimited("%sF2FS-fs (%s): lz4 invalid rlen:%zu, "
++ printk_ratelimited("%sF2FS-fs (%s): lz4 invalid ret:%d, "
+ "expected:%lu\n", KERN_ERR,
+- F2FS_I_SB(dic->inode)->sb->s_id,
+- dic->rlen,
++ F2FS_I_SB(dic->inode)->sb->s_id, ret,
+ PAGE_SIZE << dic->log_cluster_size);
+ return -EIO;
+ }
+@@ -1448,25 +1447,38 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
enum iostat_type io_type)
{
struct address_space *mapping = cc->inode->i_mapping;
@@ -125690,7 +188841,7 @@ index c1bf9ad4c2207..58d255d3a518a 100644
ret = f2fs_write_single_data_page(cc->rpages[i], &_submitted,
NULL, NULL, wbc, io_type,
-@@ -1481,26 +1494,15 @@ retry_write:
+@@ -1481,26 +1493,15 @@ retry_write:
* avoid deadlock caused by cluster update race
* from foreground operation.
*/
@@ -125720,7 +188871,7 @@ index c1bf9ad4c2207..58d255d3a518a 100644
}
*submitted += _submitted;
-@@ -1509,14 +1511,6 @@ retry_write:
+@@ -1509,14 +1510,6 @@ retry_write:
f2fs_balance_fs(F2FS_M_SB(mapping), true);
return 0;
@@ -125735,7 +188886,7 @@ index c1bf9ad4c2207..58d255d3a518a 100644
}
int f2fs_write_multi_pages(struct compress_ctx *cc,
-@@ -1530,6 +1524,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
+@@ -1530,6 +1523,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
if (cluster_may_compress(cc)) {
err = f2fs_compress_pages(cc);
if (err == -EAGAIN) {
@@ -125744,7 +188895,7 @@ index c1bf9ad4c2207..58d255d3a518a 100644
} else if (err) {
f2fs_put_rpages_wbc(cc, wbc, true, 1);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
-index f4fd6c246c9a9..e662355cf8c9b 100644
+index f4fd6c246c9a9..4cf522120cb1a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2564,6 +2564,11 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
@@ -125768,8 +188919,105 @@ index f4fd6c246c9a9..e662355cf8c9b 100644
/* swap file is migrating in aligned write mode */
if (is_inode_flag_set(inode, FI_ALIGNED_WRITE))
+@@ -3211,8 +3214,12 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
+ /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ atomic_inc(&sbi->wb_sync_req[DATA]);
+- else if (atomic_read(&sbi->wb_sync_req[DATA]))
++ else if (atomic_read(&sbi->wb_sync_req[DATA])) {
++ /* to avoid potential deadlock */
++ if (current->plug)
++ blk_finish_plug(current->plug);
+ goto skip_write;
++ }
+
+ if (__should_serialize_io(inode, wbc)) {
+ mutex_lock(&sbi->writepages);
+@@ -3403,7 +3410,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
+
+ *fsdata = NULL;
+
+- if (len == PAGE_SIZE)
++ if (len == PAGE_SIZE && !(f2fs_is_atomic_file(inode)))
+ goto repeat;
+
+ ret = f2fs_prepare_compress_overwrite(inode, pagep,
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+index 8c50518475a99..b449c7a372a4b 100644
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -21,7 +21,7 @@
+ #include "gc.h"
+
+ static LIST_HEAD(f2fs_stat_list);
+-static DEFINE_MUTEX(f2fs_stat_mutex);
++static DEFINE_RAW_SPINLOCK(f2fs_stat_lock);
+ #ifdef CONFIG_DEBUG_FS
+ static struct dentry *f2fs_debugfs_root;
+ #endif
+@@ -338,14 +338,16 @@ static char *s_flag[] = {
+ [SBI_QUOTA_SKIP_FLUSH] = " quota_skip_flush",
+ [SBI_QUOTA_NEED_REPAIR] = " quota_need_repair",
+ [SBI_IS_RESIZEFS] = " resizefs",
++ [SBI_IS_FREEZING] = " freezefs",
+ };
+
+ static int stat_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_stat_info *si;
+ int i = 0, j = 0;
++ unsigned long flags;
+
+- mutex_lock(&f2fs_stat_mutex);
++ raw_spin_lock_irqsave(&f2fs_stat_lock, flags);
+ list_for_each_entry(si, &f2fs_stat_list, stat_list) {
+ update_general_status(si->sbi);
+
+@@ -573,7 +575,7 @@ static int stat_show(struct seq_file *s, void *v)
+ seq_printf(s, " - paged : %llu KB\n",
+ si->page_mem >> 10);
+ }
+- mutex_unlock(&f2fs_stat_mutex);
++ raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags);
+ return 0;
+ }
+
+@@ -584,6 +586,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+ struct f2fs_stat_info *si;
++ unsigned long flags;
+ int i;
+
+ si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL);
+@@ -619,9 +622,9 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
+ atomic_set(&sbi->max_aw_cnt, 0);
+ atomic_set(&sbi->max_vw_cnt, 0);
+
+- mutex_lock(&f2fs_stat_mutex);
++ raw_spin_lock_irqsave(&f2fs_stat_lock, flags);
+ list_add_tail(&si->stat_list, &f2fs_stat_list);
+- mutex_unlock(&f2fs_stat_mutex);
++ raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags);
+
+ return 0;
+ }
+@@ -629,10 +632,11 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
+ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_stat_info *si = F2FS_STAT(sbi);
++ unsigned long flags;
+
+- mutex_lock(&f2fs_stat_mutex);
++ raw_spin_lock_irqsave(&f2fs_stat_lock, flags);
+ list_del(&si->stat_list);
+- mutex_unlock(&f2fs_stat_mutex);
++ raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags);
+
+ kfree(si);
+ }
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
-index b339ae89c1ad1..c68817d83a53b 100644
+index b339ae89c1ad1..0a0fa1a64d06e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1012,6 +1012,7 @@ struct f2fs_sm_info {
@@ -125780,7 +189028,15 @@ index b339ae89c1ad1..c68817d83a53b 100644
unsigned int ovp_segments; /* # of overprovision segments */
/* a threshold to reclaim prefree segments */
-@@ -2184,6 +2185,11 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+@@ -1252,6 +1253,7 @@ enum {
+ SBI_QUOTA_SKIP_FLUSH, /* skip flushing quota in current CP */
+ SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */
+ SBI_IS_RESIZEFS, /* resizefs is in process */
++ SBI_IS_FREEZING, /* freezefs is in process */
+ };
+
+ enum {
+@@ -2184,6 +2186,11 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
if (!__allow_reserved_blocks(sbi, inode, true))
avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
@@ -125792,7 +189048,7 @@ index b339ae89c1ad1..c68817d83a53b 100644
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
if (avail_user_block_count > sbi->unusable_block_count)
avail_user_block_count -= sbi->unusable_block_count;
-@@ -2430,6 +2436,11 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
+@@ -2430,6 +2437,11 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
if (!__allow_reserved_blocks(sbi, inode, false))
valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks;
@@ -125804,7 +189060,7 @@ index b339ae89c1ad1..c68817d83a53b 100644
user_block_count = sbi->user_block_count;
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
user_block_count -= sbi->unusable_block_count;
-@@ -4152,8 +4163,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
+@@ -4152,8 +4164,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
if (!f2fs_compressed_file(inode))
return true;
@@ -125815,10 +189071,22 @@ index b339ae89c1ad1..c68817d83a53b 100644
fi->i_flags &= ~F2FS_COMPR_FL;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
-index 9c8ef33bd8d32..7ed44752c7580 100644
+index 9c8ef33bd8d32..8ef92719c6799 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
-@@ -3143,17 +3143,17 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
+@@ -2002,7 +2002,10 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
+
+ inode_lock(inode);
+
+- f2fs_disable_compressed_file(inode);
++ if (!f2fs_disable_compressed_file(inode)) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ if (f2fs_is_atomic_file(inode)) {
+ if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST))
+@@ -3143,17 +3146,17 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
inode_lock(inode);
@@ -125841,21 +189109,32 @@ index 9c8ef33bd8d32..7ed44752c7580 100644
if (f2fs_pin_file_control(inode, false)) {
ret = -EAGAIN;
goto out;
+@@ -4276,7 +4279,7 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ size_t target_size = 0;
+ int err;
+
+- if (iov_iter_fault_in_readable(from, iov_iter_count(from)))
++ if (fault_in_iov_iter_readable(from, iov_iter_count(from)))
+ set_inode_flag(inode, FI_NO_PREALLOC);
+
+ if ((iocb->ki_flags & IOCB_NOWAIT)) {
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
-index 77391e3b7d68f..264821df0add1 100644
+index 77391e3b7d68f..ceb5fc6b40398 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
-@@ -1023,6 +1023,9 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+@@ -1023,6 +1023,11 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
set_sbi_flag(sbi, SBI_NEED_FSCK);
}
-+ if (f2fs_check_nid_range(sbi, dni->ino))
++ if (f2fs_check_nid_range(sbi, dni->ino)) {
++ f2fs_put_page(node_page, 1);
+ return false;
++ }
+
*nofs = ofs_of_node(node_page);
source_blkaddr = data_blkaddr(NULL, node_page, ofs_in_node);
f2fs_put_page(node_page, 1);
-@@ -1036,7 +1039,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+@@ -1036,7 +1041,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
if (!test_and_set_bit(segno, SIT_I(sbi)->invalid_segmap)) {
f2fs_err(sbi, "mismatched blkaddr %u (source_blkaddr %u) in seg %u",
blkaddr, source_blkaddr, segno);
@@ -125864,7 +189143,7 @@ index 77391e3b7d68f..264821df0add1 100644
}
}
#endif
-@@ -1454,7 +1457,8 @@ next_step:
+@@ -1454,7 +1459,8 @@ next_step:
if (phase == 3) {
inode = f2fs_iget(sb, dni.ino);
@@ -125875,7 +189154,7 @@ index 77391e3b7d68f..264821df0add1 100644
if (!down_write_trylock(
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
-index 9141147b5bb00..4557de37a9119 100644
+index 9141147b5bb00..2272000fb10b5 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -516,6 +516,11 @@ make_now:
@@ -125899,6 +189178,34 @@ index 9141147b5bb00..4557de37a9119 100644
} else if (S_ISLNK(inode->i_mode)) {
if (file_is_encrypt(inode))
inode->i_op = &f2fs_encrypted_symlink_inode_operations;
+@@ -764,7 +769,8 @@ void f2fs_evict_inode(struct inode *inode)
+ f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
+ f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
+
+- sb_start_intwrite(inode->i_sb);
++ if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
++ sb_start_intwrite(inode->i_sb);
+ set_inode_flag(inode, FI_NO_ALLOC);
+ i_size_write(inode, 0);
+ retry:
+@@ -795,7 +801,8 @@ retry:
+ if (dquot_initialize_needed(inode))
+ set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
+ }
+- sb_end_intwrite(inode->i_sb);
++ if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
++ sb_end_intwrite(inode->i_sb);
+ no_delete:
+ dquot_drop(inode);
+
+@@ -871,6 +878,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
+ err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
+ if (err) {
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
++ set_inode_flag(inode, FI_FREE_NID);
+ f2fs_warn(sbi, "May loss orphan inode, run fsck to fix.");
+ goto out;
+ }
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 9c528e583c9d5..ae0838001480a 100644
--- a/fs/f2fs/namei.c
@@ -125913,7 +189220,7 @@ index 9c528e583c9d5..ae0838001480a 100644
set_inode_flag(inode, FI_INC_LINK);
f2fs_lock_op(sbi);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
-index e863136081b47..556fcd8457f3f 100644
+index e863136081b47..69c6bcaf5aae8 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1443,6 +1443,7 @@ page_hit:
@@ -125924,8 +189231,22 @@ index e863136081b47..556fcd8457f3f 100644
err = -EINVAL;
out_err:
ClearPageUptodate(page);
+@@ -2105,8 +2106,12 @@ static int f2fs_write_node_pages(struct address_space *mapping,
+
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ atomic_inc(&sbi->wb_sync_req[NODE]);
+- else if (atomic_read(&sbi->wb_sync_req[NODE]))
++ else if (atomic_read(&sbi->wb_sync_req[NODE])) {
++ /* to avoid potential deadlock */
++ if (current->plug)
++ blk_finish_plug(current->plug);
+ goto skip_write;
++ }
+
+ trace_f2fs_writepages(mapping->host, wbc, NODE);
+
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
-index a135d22474154..d716553bdc025 100644
+index a135d22474154..338a57360bb8c 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -561,7 +561,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
@@ -125937,6 +189258,20 @@ index a135d22474154..d716553bdc025 100644
f2fs_available_free_memory(sbi, INO_ENTRIES))
return;
+@@ -4747,6 +4747,13 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
+
+ sanity_check_seg_type(sbi, curseg->seg_type);
+
++ if (curseg->alloc_type != LFS && curseg->alloc_type != SSR) {
++ f2fs_err(sbi,
++ "Current segment has invalid alloc_type:%d",
++ curseg->alloc_type);
++ return -EFSCORRUPTED;
++ }
++
+ if (f2fs_test_bit(blkofs, se->cur_valid_map))
+ goto out;
+
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 89fff258727d1..b2d82c9f5a16d 100644
--- a/fs/f2fs/segment.h
@@ -125952,7 +189287,7 @@ index 89fff258727d1..b2d82c9f5a16d 100644
static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
-index 78ebc306ee2b5..6174c4f4cee7f 100644
+index 78ebc306ee2b5..6dc66b7bc1f58 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -327,6 +327,46 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
@@ -126011,7 +189346,43 @@ index 78ebc306ee2b5..6174c4f4cee7f 100644
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) {
-@@ -3487,7 +3527,7 @@ skip_cross:
+@@ -1623,11 +1663,15 @@ static int f2fs_freeze(struct super_block *sb)
+ /* ensure no checkpoint required */
+ if (!llist_empty(&F2FS_SB(sb)->cprc_info.issue_list))
+ return -EINVAL;
++
++ /* to avoid deadlock on f2fs_evict_inode->SB_FREEZE_FS */
++ set_sbi_flag(F2FS_SB(sb), SBI_IS_FREEZING);
+ return 0;
+ }
+
+ static int f2fs_unfreeze(struct super_block *sb)
+ {
++ clear_sbi_flag(F2FS_SB(sb), SBI_IS_FREEZING);
+ return 0;
+ }
+
+@@ -2636,7 +2680,7 @@ int f2fs_quota_sync(struct super_block *sb, int type)
+ struct f2fs_sb_info *sbi = F2FS_SB(sb);
+ struct quota_info *dqopt = sb_dqopt(sb);
+ int cnt;
+- int ret;
++ int ret = 0;
+
+ /*
+ * Now when everything is written we can discard the pagecache so
+@@ -2647,8 +2691,8 @@ int f2fs_quota_sync(struct super_block *sb, int type)
+ if (type != -1 && cnt != type)
+ continue;
+
+- if (!sb_has_quota_active(sb, type))
+- return 0;
++ if (!sb_has_quota_active(sb, cnt))
++ continue;
+
+ inode_lock(dqopt->files[cnt]);
+
+@@ -3487,7 +3531,7 @@ skip_cross:
NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) {
f2fs_warn(sbi, "Insane cp_payload: %u, nat_bits_blocks: %u)",
cp_payload, nat_bits_blocks);
@@ -126020,7 +189391,7 @@ index 78ebc306ee2b5..6174c4f4cee7f 100644
}
if (unlikely(f2fs_cp_error(sbi))) {
-@@ -4148,6 +4188,10 @@ try_onemore:
+@@ -4148,6 +4192,10 @@ try_onemore:
goto free_nm;
}
@@ -126031,7 +189402,7 @@ index 78ebc306ee2b5..6174c4f4cee7f 100644
/* For write statistics */
sbi->sectors_written_start = f2fs_get_sectors_written(sbi);
-@@ -4352,6 +4396,8 @@ free_node_inode:
+@@ -4352,6 +4400,8 @@ free_node_inode:
free_stats:
f2fs_destroy_stats(sbi);
free_nm:
@@ -126041,7 +189412,7 @@ index 78ebc306ee2b5..6174c4f4cee7f 100644
free_sm:
f2fs_destroy_segment_manager(sbi);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
-index a32fe31c33b8e..abc4344fba394 100644
+index a32fe31c33b8e..8b36e61fe7edb 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -415,7 +415,9 @@ out:
@@ -126055,6 +189426,15 @@ index a32fe31c33b8e..abc4344fba394 100644
spin_unlock(&sbi->stat_lock);
return -EINVAL;
}
+@@ -471,7 +473,7 @@ out:
+ } else if (t == GC_IDLE_AT) {
+ if (!sbi->am.atgc_enabled)
+ return -EINVAL;
+- sbi->gc_mode = GC_AT;
++ sbi->gc_mode = GC_IDLE_AT;
+ } else {
+ sbi->gc_mode = GC_NORMAL;
+ }
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1d2d29dcd41ce..6a3b3bec7989d 100644
--- a/fs/f2fs/xattr.c
@@ -126079,10 +189459,69 @@ index 1d2d29dcd41ce..6a3b3bec7989d 100644
newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);
diff --git a/fs/file.c b/fs/file.c
-index 8627dacfc4246..97d212a9b8144 100644
+index 8627dacfc4246..ee93173467025 100644
--- a/fs/file.c
+++ b/fs/file.c
-@@ -841,24 +841,68 @@ void do_close_on_exec(struct files_struct *files)
+@@ -87,6 +87,21 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+ copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
+ }
+
++/*
++ * Note how the fdtable bitmap allocations very much have to be a multiple of
++ * BITS_PER_LONG. This is not only because we walk those things in chunks of
++ * 'unsigned long' in some places, but simply because that is how the Linux
++ * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
++ * they are very much "bits in an array of unsigned long".
++ *
++ * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
++ * by that "1024/sizeof(ptr)" before, we already know there are sufficient
++ * clear low bits. Clang seems to realize that, gcc ends up being confused.
++ *
++ * On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
++ * let's consider it documentation (and maybe a test-case for gcc to improve
++ * its code generation ;)
++ */
+ static struct fdtable * alloc_fdtable(unsigned int nr)
+ {
+ struct fdtable *fdt;
+@@ -102,6 +117,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ nr /= (1024 / sizeof(struct file *));
+ nr = roundup_pow_of_two(nr + 1);
+ nr *= (1024 / sizeof(struct file *));
++ nr = ALIGN(nr, BITS_PER_LONG);
+ /*
+ * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+ * had been set lower between the check in expand_files() and here. Deal
+@@ -269,6 +285,19 @@ static unsigned int count_open_files(struct fdtable *fdt)
+ return i;
+ }
+
++/*
++ * Note that a sane fdtable size always has to be a multiple of
++ * BITS_PER_LONG, since we have bitmaps that are sized by this.
++ *
++ * 'max_fds' will normally already be properly aligned, but it
++ * turns out that in the close_range() -> __close_range() ->
++ * unshare_fd() -> dup_fd() -> sane_fdtable_size() we can end
++ * up having a 'max_fds' value that isn't already aligned.
++ *
++ * Rather than make close_range() have to worry about this,
++ * just make that BITS_PER_LONG alignment be part of a sane
++ * fdtable size. Becuase that's really what it is.
++ */
+ static unsigned int sane_fdtable_size(struct fdtable *fdt, unsigned int max_fds)
+ {
+ unsigned int count;
+@@ -276,7 +305,7 @@ static unsigned int sane_fdtable_size(struct fdtable *fdt, unsigned int max_fds)
+ count = count_open_files(fdt);
+ if (max_fds < NR_OPEN_DEFAULT)
+ max_fds = NR_OPEN_DEFAULT;
+- return min(count, max_fds);
++ return ALIGN(min(count, max_fds), BITS_PER_LONG);
+ }
+
+ /*
+@@ -841,24 +870,68 @@ void do_close_on_exec(struct files_struct *files)
spin_unlock(&files->file_lock);
}
@@ -126163,6 +189602,33 @@ index 8627dacfc4246..97d212a9b8144 100644
rcu_read_unlock();
return file;
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 45437f8e1003e..e8c9016703ad6 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -375,6 +375,7 @@ void __fput_sync(struct file *file)
+ }
+
+ EXPORT_SYMBOL(fput);
++EXPORT_SYMBOL(__fput_sync);
+
+ void __init files_init(void)
+ {
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 81ec192ce0673..85b4259f104a2 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -1739,6 +1739,10 @@ static int writeback_single_inode(struct inode *inode,
+ */
+ if (!(inode->i_state & I_DIRTY_ALL))
+ inode_cgwb_move_to_attached(inode, wb);
++ else if (!(inode->i_state & I_SYNC_QUEUED) &&
++ (inode->i_state & I_DIRTY))
++ redirty_tail_locked(inode, wb);
++
+ spin_unlock(&wb->list_lock);
+ inode_sync_complete(inode);
+ out:
diff --git a/fs/fs_context.c b/fs/fs_context.c
index b7e43a780a625..24ce12f0db32e 100644
--- a/fs/fs_context.c
@@ -126177,7 +189643,7 @@ index b7e43a780a625..24ce12f0db32e 100644
if (strchr(param->key, ',') ||
(param->type == fs_value_is_string &&
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
-index dde341a6388a1..a9d21b33da9c4 100644
+index dde341a6388a1..d6b5339c56e2c 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -852,6 +852,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
@@ -126193,7 +189659,26 @@ index dde341a6388a1..a9d21b33da9c4 100644
err = 0;
spin_lock(&cs->req->waitq.lock);
if (test_bit(FR_ABORTED, &cs->req->flags))
-@@ -2031,8 +2037,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
+@@ -935,7 +941,17 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
+
+ while (count) {
+ if (cs->write && cs->pipebufs && page) {
+- return fuse_ref_page(cs, page, offset, count);
++ /*
++ * Can't control lifetime of pipe buffers, so always
++ * copy user pages.
++ */
++ if (cs->req->args->user_pages) {
++ err = fuse_copy_fill(cs);
++ if (err)
++ return err;
++ } else {
++ return fuse_ref_page(cs, page, offset, count);
++ }
+ } else if (!cs->len) {
+ if (cs->move_pages && page &&
+ offset == 0 && count == PAGE_SIZE) {
+@@ -2031,8 +2047,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
pipe_lock(pipe);
out_free:
@@ -126242,10 +189727,27 @@ index d9b977c0f38dc..80a2181b402b2 100644
goto unlock;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
-index 11404f8c21c75..2004d362361e1 100644
+index 11404f8c21c75..71e9e301e569d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
-@@ -1848,6 +1848,17 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
+@@ -1164,7 +1164,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
+
+ again:
+ err = -EFAULT;
+- if (iov_iter_fault_in_readable(ii, bytes))
++ if (fault_in_iov_iter_readable(ii, bytes))
+ break;
+
+ err = -ENOMEM;
+@@ -1417,6 +1417,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
+ (PAGE_SIZE - ret) & (PAGE_SIZE - 1);
+ }
+
++ ap->args.user_pages = true;
+ if (write)
+ ap->args.in_pages = true;
+ else
+@@ -1848,6 +1849,17 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
struct fuse_file *ff;
int err;
@@ -126263,7 +189765,7 @@ index 11404f8c21c75..2004d362361e1 100644
ff = __fuse_write_file_get(fi);
err = fuse_flush_times(inode, ff);
if (ff)
-@@ -2902,7 +2913,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+@@ -2902,7 +2914,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
{
@@ -126272,7 +189774,7 @@ index 11404f8c21c75..2004d362361e1 100644
if (!err)
fuse_sync_writes(inode);
-@@ -3002,6 +3013,8 @@ out:
+@@ -3002,6 +3014,8 @@ out:
if (lock_inode)
inode_unlock(inode);
@@ -126281,7 +189783,7 @@ index 11404f8c21c75..2004d362361e1 100644
return err;
}
-@@ -3111,6 +3124,8 @@ out:
+@@ -3111,6 +3125,8 @@ out:
inode_unlock(inode_out);
file_accessed(file_in);
@@ -126291,10 +189793,18 @@ index 11404f8c21c75..2004d362361e1 100644
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
-index f55f9f94b1a4f..a59e36c7deaea 100644
+index f55f9f94b1a4f..c3a87586a15fa 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
-@@ -1148,6 +1148,7 @@ int fuse_allow_current_process(struct fuse_conn *fc);
+@@ -256,6 +256,7 @@ struct fuse_args {
+ bool nocreds:1;
+ bool in_pages:1;
+ bool out_pages:1;
++ bool user_pages:1;
+ bool out_argvar:1;
+ bool page_zeroing:1;
+ bool page_replace:1;
+@@ -1148,6 +1149,7 @@ int fuse_allow_current_process(struct fuse_conn *fc);
u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
@@ -126316,8 +189826,28 @@ index 12d49a1914e84..2f999d38c9b4a 100644
truncate_inode_pages_final(&inode->i_data);
clear_inode(inode);
if (inode->i_sb->s_flags & SB_ACTIVE) {
+diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c
+index 546ea3d58fb47..fc69e1797a331 100644
+--- a/fs/fuse/ioctl.c
++++ b/fs/fuse/ioctl.c
+@@ -394,9 +394,12 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff,
+ args.out_args[1].value = ptr;
+
+ err = fuse_simple_request(fm, &args);
+- if (!err && outarg.flags & FUSE_IOCTL_RETRY)
+- err = -EIO;
+-
++ if (!err) {
++ if (outarg.result < 0)
++ err = outarg.result;
++ else if (outarg.flags & FUSE_IOCTL_RETRY)
++ err = -EIO;
++ }
+ return err;
+ }
+
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
-index 5414c2c335809..fba32141a651b 100644
+index 5414c2c335809..f785af2aa23cf 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -940,7 +940,7 @@ do_alloc:
@@ -126329,8 +189859,133 @@ index 5414c2c335809..fba32141a651b 100644
} else if (flags & IOMAP_WRITE) {
u64 alloc_size;
+@@ -961,46 +961,6 @@ hole_found:
+ goto out;
+ }
+
+-static int gfs2_write_lock(struct inode *inode)
+-{
+- struct gfs2_inode *ip = GFS2_I(inode);
+- struct gfs2_sbd *sdp = GFS2_SB(inode);
+- int error;
+-
+- gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
+- error = gfs2_glock_nq(&ip->i_gh);
+- if (error)
+- goto out_uninit;
+- if (&ip->i_inode == sdp->sd_rindex) {
+- struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
+-
+- error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
+- GL_NOCACHE, &m_ip->i_gh);
+- if (error)
+- goto out_unlock;
+- }
+- return 0;
+-
+-out_unlock:
+- gfs2_glock_dq(&ip->i_gh);
+-out_uninit:
+- gfs2_holder_uninit(&ip->i_gh);
+- return error;
+-}
+-
+-static void gfs2_write_unlock(struct inode *inode)
+-{
+- struct gfs2_inode *ip = GFS2_I(inode);
+- struct gfs2_sbd *sdp = GFS2_SB(inode);
+-
+- if (&ip->i_inode == sdp->sd_rindex) {
+- struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
+-
+- gfs2_glock_dq_uninit(&m_ip->i_gh);
+- }
+- gfs2_glock_dq_uninit(&ip->i_gh);
+-}
+-
+ static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos,
+ unsigned len)
+ {
+@@ -1118,11 +1078,6 @@ out_qunlock:
+ return ret;
+ }
+
+-static inline bool gfs2_iomap_need_write_lock(unsigned flags)
+-{
+- return (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT);
+-}
+-
+ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
+ unsigned flags, struct iomap *iomap,
+ struct iomap *srcmap)
+@@ -1135,12 +1090,6 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
+ iomap->flags |= IOMAP_F_BUFFER_HEAD;
+
+ trace_gfs2_iomap_start(ip, pos, length, flags);
+- if (gfs2_iomap_need_write_lock(flags)) {
+- ret = gfs2_write_lock(inode);
+- if (ret)
+- goto out;
+- }
+-
+ ret = __gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
+ if (ret)
+ goto out_unlock;
+@@ -1168,10 +1117,7 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
+ ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);
+
+ out_unlock:
+- if (ret && gfs2_iomap_need_write_lock(flags))
+- gfs2_write_unlock(inode);
+ release_metapath(&mp);
+-out:
+ trace_gfs2_iomap_end(ip, iomap, ret);
+ return ret;
+ }
+@@ -1208,26 +1154,21 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
+
+ if (length != written && (iomap->flags & IOMAP_F_NEW)) {
+ /* Deallocate blocks that were just allocated. */
+- loff_t blockmask = i_blocksize(inode) - 1;
+- loff_t end = (pos + length) & ~blockmask;
++ loff_t hstart = round_up(pos + written, i_blocksize(inode));
++ loff_t hend = iomap->offset + iomap->length;
+
+- pos = (pos + written + blockmask) & ~blockmask;
+- if (pos < end) {
+- truncate_pagecache_range(inode, pos, end - 1);
+- punch_hole(ip, pos, end - pos);
++ if (hstart < hend) {
++ truncate_pagecache_range(inode, hstart, hend - 1);
++ punch_hole(ip, hstart, hend - hstart);
+ }
+ }
+
+ if (unlikely(!written))
+- goto out_unlock;
++ return 0;
+
+ if (iomap->flags & IOMAP_F_SIZE_CHANGED)
+ mark_inode_dirty(inode);
+ set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
+-
+-out_unlock:
+- if (gfs2_iomap_need_write_lock(flags))
+- gfs2_write_unlock(inode);
+ return 0;
+ }
+
+@@ -2204,7 +2145,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
+
+ ret = do_shrink(inode, newsize);
+ out:
+- gfs2_rs_delete(ip, NULL);
++ gfs2_rs_delete(ip);
+ gfs2_qa_put(ip);
+ return ret;
+ }
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
-index c559827cb6f91..f6d3b3e13d72f 100644
+index c559827cb6f91..60390f9dc31f4 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -711,10 +711,11 @@ static int gfs2_release(struct inode *inode, struct file *file)
@@ -126342,17 +189997,837 @@ index c559827cb6f91..f6d3b3e13d72f 100644
- if (file->f_mode & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE) {
+ if (gfs2_rs_active(&ip->i_res))
-+ gfs2_rs_delete(ip, &inode->i_writecount);
++ gfs2_rs_delete(ip);
gfs2_qa_put(ip);
+ }
return 0;
}
+@@ -776,27 +777,99 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
+ return ret ? ret : ret1;
+ }
+
++static inline bool should_fault_in_pages(ssize_t ret, struct iov_iter *i,
++ size_t *prev_count,
++ size_t *window_size)
++{
++ char __user *p = i->iov[0].iov_base + i->iov_offset;
++ size_t count = iov_iter_count(i);
++ int pages = 1;
++
++ if (likely(!count))
++ return false;
++ if (ret <= 0 && ret != -EFAULT)
++ return false;
++ if (!iter_is_iovec(i))
++ return false;
++
++ if (*prev_count != count || !*window_size) {
++ int pages, nr_dirtied;
++
++ pages = min_t(int, BIO_MAX_VECS,
++ DIV_ROUND_UP(iov_iter_count(i), PAGE_SIZE));
++ nr_dirtied = max(current->nr_dirtied_pause -
++ current->nr_dirtied, 1);
++ pages = min(pages, nr_dirtied);
++ }
++
++ *prev_count = count;
++ *window_size = (size_t)PAGE_SIZE * pages - offset_in_page(p);
++ return true;
++}
++
+ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
+ struct gfs2_holder *gh)
+ {
+ struct file *file = iocb->ki_filp;
+ struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+- size_t count = iov_iter_count(to);
++ size_t prev_count = 0, window_size = 0;
++ size_t written = 0;
+ ssize_t ret;
+
+- if (!count)
++ /*
++ * In this function, we disable page faults when we're holding the
++ * inode glock while doing I/O. If a page fault occurs, we indicate
++ * that the inode glock may be dropped, fault in the pages manually,
++ * and retry.
++ *
++ * Unlike generic_file_read_iter, for reads, iomap_dio_rw can trigger
++ * physical as well as manual page faults, and we need to disable both
++ * kinds.
++ *
++ * For direct I/O, gfs2 takes the inode glock in deferred mode. This
++ * locking mode is compatible with other deferred holders, so multiple
++ * processes and nodes can do direct I/O to a file at the same time.
++ * There's no guarantee that reads or writes will be atomic. Any
++ * coordination among readers and writers needs to happen externally.
++ */
++
++ if (!iov_iter_count(to))
+ return 0; /* skip atime */
+
+ gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh);
++retry:
+ ret = gfs2_glock_nq(gh);
+ if (ret)
+ goto out_uninit;
++retry_under_glock:
++ pagefault_disable();
++ to->nofault = true;
++ ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL,
++ IOMAP_DIO_PARTIAL, written);
++ to->nofault = false;
++ pagefault_enable();
++ if (ret > 0)
++ written = ret;
+
+- ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL, 0);
+- gfs2_glock_dq(gh);
++ if (should_fault_in_pages(ret, to, &prev_count, &window_size)) {
++ size_t leftover;
++
++ gfs2_holder_allow_demote(gh);
++ leftover = fault_in_iov_iter_writeable(to, window_size);
++ gfs2_holder_disallow_demote(gh);
++ if (leftover != window_size) {
++ if (gfs2_holder_queued(gh))
++ goto retry_under_glock;
++ goto retry;
++ }
++ }
++ if (gfs2_holder_queued(gh))
++ gfs2_glock_dq(gh);
+ out_uninit:
+ gfs2_holder_uninit(gh);
+- return ret;
++ if (ret < 0)
++ return ret;
++ return written;
+ }
+
+ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
+@@ -805,10 +878,20 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ struct gfs2_inode *ip = GFS2_I(inode);
+- size_t len = iov_iter_count(from);
+- loff_t offset = iocb->ki_pos;
++ size_t prev_count = 0, window_size = 0;
++ size_t read = 0;
+ ssize_t ret;
+
++ /*
++ * In this function, we disable page faults when we're holding the
++ * inode glock while doing I/O. If a page fault occurs, we indicate
++ * that the inode glock may be dropped, fault in the pages manually,
++ * and retry.
++ *
++ * For writes, iomap_dio_rw only triggers manual page faults, so we
++ * don't need to disable physical ones.
++ */
++
+ /*
+ * Deferred lock, even if its a write, since we do no allocation on
+ * this path. All we need to change is the atime, and this lock mode
+@@ -818,45 +901,78 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
+ * VFS does.
+ */
+ gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh);
++retry:
+ ret = gfs2_glock_nq(gh);
+ if (ret)
+ goto out_uninit;
+-
++retry_under_glock:
+ /* Silently fall back to buffered I/O when writing beyond EOF */
+- if (offset + len > i_size_read(&ip->i_inode))
++ if (iocb->ki_pos + iov_iter_count(from) > i_size_read(&ip->i_inode))
+ goto out;
+
+- ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL, 0);
++ from->nofault = true;
++ ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL,
++ IOMAP_DIO_PARTIAL, read);
++ from->nofault = false;
++
+ if (ret == -ENOTBLK)
+ ret = 0;
++ if (ret > 0)
++ read = ret;
++
++ if (should_fault_in_pages(ret, from, &prev_count, &window_size)) {
++ size_t leftover;
++
++ gfs2_holder_allow_demote(gh);
++ leftover = fault_in_iov_iter_readable(from, window_size);
++ gfs2_holder_disallow_demote(gh);
++ if (leftover != window_size) {
++ if (gfs2_holder_queued(gh))
++ goto retry_under_glock;
++ goto retry;
++ }
++ }
+ out:
+- gfs2_glock_dq(gh);
++ if (gfs2_holder_queued(gh))
++ gfs2_glock_dq(gh);
+ out_uninit:
+ gfs2_holder_uninit(gh);
+- return ret;
++ if (ret < 0)
++ return ret;
++ return read;
+ }
+
+ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ {
+ struct gfs2_inode *ip;
+ struct gfs2_holder gh;
++ size_t prev_count = 0, window_size = 0;
+ size_t written = 0;
+ ssize_t ret;
+
++ /*
++ * In this function, we disable page faults when we're holding the
++ * inode glock while doing I/O. If a page fault occurs, we indicate
++ * that the inode glock may be dropped, fault in the pages manually,
++ * and retry.
++ */
++
+ if (iocb->ki_flags & IOCB_DIRECT) {
+ ret = gfs2_file_direct_read(iocb, to, &gh);
+ if (likely(ret != -ENOTBLK))
+ return ret;
+ iocb->ki_flags &= ~IOCB_DIRECT;
+ }
++ pagefault_disable();
+ iocb->ki_flags |= IOCB_NOIO;
+ ret = generic_file_read_iter(iocb, to);
+ iocb->ki_flags &= ~IOCB_NOIO;
++ pagefault_enable();
+ if (ret >= 0) {
+ if (!iov_iter_count(to))
+ return ret;
+ written = ret;
+- } else {
++ } else if (ret != -EFAULT) {
+ if (ret != -EAGAIN)
+ return ret;
+ if (iocb->ki_flags & IOCB_NOWAIT)
+@@ -864,18 +980,115 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ }
+ ip = GFS2_I(iocb->ki_filp->f_mapping->host);
+ gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
++retry:
+ ret = gfs2_glock_nq(&gh);
+ if (ret)
+ goto out_uninit;
++retry_under_glock:
++ pagefault_disable();
+ ret = generic_file_read_iter(iocb, to);
++ pagefault_enable();
+ if (ret > 0)
+ written += ret;
+- gfs2_glock_dq(&gh);
++
++ if (should_fault_in_pages(ret, to, &prev_count, &window_size)) {
++ size_t leftover;
++
++ gfs2_holder_allow_demote(&gh);
++ leftover = fault_in_iov_iter_writeable(to, window_size);
++ gfs2_holder_disallow_demote(&gh);
++ if (leftover != window_size) {
++ if (gfs2_holder_queued(&gh))
++ goto retry_under_glock;
++ goto retry;
++ }
++ }
++ if (gfs2_holder_queued(&gh))
++ gfs2_glock_dq(&gh);
+ out_uninit:
+ gfs2_holder_uninit(&gh);
+ return written ? written : ret;
+ }
+
++static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
++ struct iov_iter *from,
++ struct gfs2_holder *gh)
++{
++ struct file *file = iocb->ki_filp;
++ struct inode *inode = file_inode(file);
++ struct gfs2_inode *ip = GFS2_I(inode);
++ struct gfs2_sbd *sdp = GFS2_SB(inode);
++ struct gfs2_holder *statfs_gh = NULL;
++ size_t prev_count = 0, window_size = 0;
++ size_t orig_count = iov_iter_count(from);
++ size_t read = 0;
++ ssize_t ret;
++
++ /*
++ * In this function, we disable page faults when we're holding the
++ * inode glock while doing I/O. If a page fault occurs, we indicate
++ * that the inode glock may be dropped, fault in the pages manually,
++ * and retry.
++ */
++
++ if (inode == sdp->sd_rindex) {
++ statfs_gh = kmalloc(sizeof(*statfs_gh), GFP_NOFS);
++ if (!statfs_gh)
++ return -ENOMEM;
++ }
++
++ gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, gh);
++retry:
++ ret = gfs2_glock_nq(gh);
++ if (ret)
++ goto out_uninit;
++retry_under_glock:
++ if (inode == sdp->sd_rindex) {
++ struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
++
++ ret = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
++ GL_NOCACHE, statfs_gh);
++ if (ret)
++ goto out_unlock;
++ }
++
++ current->backing_dev_info = inode_to_bdi(inode);
++ pagefault_disable();
++ ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
++ pagefault_enable();
++ current->backing_dev_info = NULL;
++ if (ret > 0) {
++ iocb->ki_pos += ret;
++ read += ret;
++ }
++
++ if (inode == sdp->sd_rindex)
++ gfs2_glock_dq_uninit(statfs_gh);
++
++ from->count = orig_count - read;
++ if (should_fault_in_pages(ret, from, &prev_count, &window_size)) {
++ size_t leftover;
++
++ gfs2_holder_allow_demote(gh);
++ leftover = fault_in_iov_iter_readable(from, window_size);
++ gfs2_holder_disallow_demote(gh);
++ if (leftover != window_size) {
++ from->count = min(from->count, window_size - leftover);
++ if (gfs2_holder_queued(gh))
++ goto retry_under_glock;
++ goto retry;
++ }
++ }
++out_unlock:
++ if (gfs2_holder_queued(gh))
++ gfs2_glock_dq(gh);
++out_uninit:
++ gfs2_holder_uninit(gh);
++ if (statfs_gh)
++ kfree(statfs_gh);
++ return read ? read : ret;
++}
++
+ /**
+ * gfs2_file_write_iter - Perform a write to a file
+ * @iocb: The io context
+@@ -927,9 +1140,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ goto out_unlock;
+
+ iocb->ki_flags |= IOCB_DSYNC;
+- current->backing_dev_info = inode_to_bdi(inode);
+- buffered = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
+- current->backing_dev_info = NULL;
++ buffered = gfs2_file_buffered_write(iocb, from, &gh);
+ if (unlikely(buffered <= 0)) {
+ if (!ret)
+ ret = buffered;
+@@ -943,7 +1154,6 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ * the direct I/O range as we don't know if the buffered pages
+ * made it to disk.
+ */
+- iocb->ki_pos += buffered;
+ ret2 = generic_write_sync(iocb, buffered);
+ invalidate_mapping_pages(mapping,
+ (iocb->ki_pos - buffered) >> PAGE_SHIFT,
+@@ -951,13 +1161,9 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ if (!ret || ret2 > 0)
+ ret += ret2;
+ } else {
+- current->backing_dev_info = inode_to_bdi(inode);
+- ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
+- current->backing_dev_info = NULL;
+- if (likely(ret > 0)) {
+- iocb->ki_pos += ret;
++ ret = gfs2_file_buffered_write(iocb, from, &gh);
++ if (likely(ret > 0))
+ ret = generic_write_sync(iocb, ret);
+- }
+ }
+
+ out_unlock:
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
-index e0eaa9cf9fb6f..02cd0ae98208d 100644
+index e0eaa9cf9fb6f..e85ef6b14777d 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
-@@ -1893,10 +1893,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
+@@ -58,6 +58,7 @@ struct gfs2_glock_iter {
+ typedef void (*glock_examiner) (struct gfs2_glock * gl);
+
+ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
++static void __gfs2_glock_dq(struct gfs2_holder *gh);
+
+ static struct dentry *gfs2_root;
+ static struct workqueue_struct *glock_workqueue;
+@@ -197,6 +198,12 @@ static int demote_ok(const struct gfs2_glock *gl)
+
+ if (gl->gl_state == LM_ST_UNLOCKED)
+ return 0;
++ /*
++ * Note that demote_ok is used for the lru process of disposing of
++ * glocks. For this purpose, we don't care if the glock's holders
++ * have the HIF_MAY_DEMOTE flag set or not. If someone is using
++ * them, don't demote.
++ */
+ if (!list_empty(&gl->gl_holders))
+ return 0;
+ if (glops->go_demote_ok)
+@@ -301,46 +308,59 @@ void gfs2_glock_put(struct gfs2_glock *gl)
+ }
+
+ /**
+- * may_grant - check if its ok to grant a new lock
++ * may_grant - check if it's ok to grant a new lock
+ * @gl: The glock
++ * @current_gh: One of the current holders of @gl
+ * @gh: The lock request which we wish to grant
+ *
+- * Returns: true if its ok to grant the lock
++ * With our current compatibility rules, if a glock has one or more active
++ * holders (HIF_HOLDER flag set), any of those holders can be passed in as
++ * @current_gh; they are all the same as far as compatibility with the new @gh
++ * goes.
++ *
++ * Returns true if it's ok to grant the lock.
+ */
+
+-static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holder *gh)
+-{
+- const struct gfs2_holder *gh_head = list_first_entry(&gl->gl_holders, const struct gfs2_holder, gh_list);
++static inline bool may_grant(struct gfs2_glock *gl,
++ struct gfs2_holder *current_gh,
++ struct gfs2_holder *gh)
++{
++ if (current_gh) {
++ GLOCK_BUG_ON(gl, !test_bit(HIF_HOLDER, &current_gh->gh_iflags));
++
++ switch(current_gh->gh_state) {
++ case LM_ST_EXCLUSIVE:
++ /*
++ * Here we make a special exception to grant holders
++ * who agree to share the EX lock with other holders
++ * who also have the bit set. If the original holder
++ * has the LM_FLAG_NODE_SCOPE bit set, we grant more
++ * holders with the bit set.
++ */
++ return gh->gh_state == LM_ST_EXCLUSIVE &&
++ (current_gh->gh_flags & LM_FLAG_NODE_SCOPE) &&
++ (gh->gh_flags & LM_FLAG_NODE_SCOPE);
+
+- if (gh != gh_head) {
+- /**
+- * Here we make a special exception to grant holders who agree
+- * to share the EX lock with other holders who also have the
+- * bit set. If the original holder has the LM_FLAG_NODE_SCOPE bit
+- * is set, we grant more holders with the bit set.
+- */
+- if (gh_head->gh_state == LM_ST_EXCLUSIVE &&
+- (gh_head->gh_flags & LM_FLAG_NODE_SCOPE) &&
+- gh->gh_state == LM_ST_EXCLUSIVE &&
+- (gh->gh_flags & LM_FLAG_NODE_SCOPE))
+- return 1;
+- if ((gh->gh_state == LM_ST_EXCLUSIVE ||
+- gh_head->gh_state == LM_ST_EXCLUSIVE))
+- return 0;
++ case LM_ST_SHARED:
++ case LM_ST_DEFERRED:
++ return gh->gh_state == current_gh->gh_state;
++
++ default:
++ return false;
++ }
+ }
++
+ if (gl->gl_state == gh->gh_state)
+- return 1;
++ return true;
+ if (gh->gh_flags & GL_EXACT)
+- return 0;
++ return false;
+ if (gl->gl_state == LM_ST_EXCLUSIVE) {
+- if (gh->gh_state == LM_ST_SHARED && gh_head->gh_state == LM_ST_SHARED)
+- return 1;
+- if (gh->gh_state == LM_ST_DEFERRED && gh_head->gh_state == LM_ST_DEFERRED)
+- return 1;
++ return gh->gh_state == LM_ST_SHARED ||
++ gh->gh_state == LM_ST_DEFERRED;
+ }
+- if (gl->gl_state != LM_ST_UNLOCKED && (gh->gh_flags & LM_FLAG_ANY))
+- return 1;
+- return 0;
++ if (gh->gh_flags & LM_FLAG_ANY)
++ return gl->gl_state != LM_ST_UNLOCKED;
++ return false;
+ }
+
+ static void gfs2_holder_wake(struct gfs2_holder *gh)
+@@ -366,7 +386,7 @@ static void do_error(struct gfs2_glock *gl, const int ret)
+ struct gfs2_holder *gh, *tmp;
+
+ list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
+- if (test_bit(HIF_HOLDER, &gh->gh_iflags))
++ if (!test_bit(HIF_WAIT, &gh->gh_iflags))
+ continue;
+ if (ret & LM_OUT_ERROR)
+ gh->gh_error = -EIO;
+@@ -380,6 +400,78 @@ static void do_error(struct gfs2_glock *gl, const int ret)
+ }
+ }
+
++/**
++ * demote_incompat_holders - demote incompatible demoteable holders
++ * @gl: the glock we want to promote
++ * @new_gh: the new holder to be promoted
++ */
++static void demote_incompat_holders(struct gfs2_glock *gl,
++ struct gfs2_holder *new_gh)
++{
++ struct gfs2_holder *gh;
++
++ /*
++ * Demote incompatible holders before we make ourselves eligible.
++ * (This holder may or may not allow auto-demoting, but we don't want
++ * to demote the new holder before it's even granted.)
++ */
++ list_for_each_entry(gh, &gl->gl_holders, gh_list) {
++ /*
++ * Since holders are at the front of the list, we stop when we
++ * find the first non-holder.
++ */
++ if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
++ return;
++ if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) &&
++ !may_grant(gl, new_gh, gh)) {
++ /*
++ * We should not recurse into do_promote because
++ * __gfs2_glock_dq only calls handle_callback,
++ * gfs2_glock_add_to_lru and __gfs2_glock_queue_work.
++ */
++ __gfs2_glock_dq(gh);
++ }
++ }
++}
++
++/**
++ * find_first_holder - find the first "holder" gh
++ * @gl: the glock
++ */
++
++static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
++{
++ struct gfs2_holder *gh;
++
++ if (!list_empty(&gl->gl_holders)) {
++ gh = list_first_entry(&gl->gl_holders, struct gfs2_holder,
++ gh_list);
++ if (test_bit(HIF_HOLDER, &gh->gh_iflags))
++ return gh;
++ }
++ return NULL;
++}
++
++/**
++ * find_first_strong_holder - find the first non-demoteable holder
++ * @gl: the glock
++ *
++ * Find the first holder that doesn't have the HIF_MAY_DEMOTE flag set.
++ */
++static inline struct gfs2_holder *
++find_first_strong_holder(struct gfs2_glock *gl)
++{
++ struct gfs2_holder *gh;
++
++ list_for_each_entry(gh, &gl->gl_holders, gh_list) {
++ if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
++ return NULL;
++ if (!test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
++ return gh;
++ }
++ return NULL;
++}
++
+ /**
+ * do_promote - promote as many requests as possible on the current queue
+ * @gl: The glock
+@@ -393,14 +485,21 @@ __releases(&gl->gl_lockref.lock)
+ __acquires(&gl->gl_lockref.lock)
+ {
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
+- struct gfs2_holder *gh, *tmp;
++ struct gfs2_holder *gh, *tmp, *first_gh;
++ bool incompat_holders_demoted = false;
+ int ret;
+
+ restart:
++ first_gh = find_first_strong_holder(gl);
+ list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
+- if (test_bit(HIF_HOLDER, &gh->gh_iflags))
++ if (!test_bit(HIF_WAIT, &gh->gh_iflags))
+ continue;
+- if (may_grant(gl, gh)) {
++ if (may_grant(gl, first_gh, gh)) {
++ if (!incompat_holders_demoted) {
++ demote_incompat_holders(gl, first_gh);
++ incompat_holders_demoted = true;
++ first_gh = gh;
++ }
+ if (gh->gh_list.prev == &gl->gl_holders &&
+ glops->go_lock) {
+ spin_unlock(&gl->gl_lockref.lock);
+@@ -426,6 +525,11 @@ restart:
+ gfs2_holder_wake(gh);
+ continue;
+ }
++ /*
++ * If we get here, it means we may not grant this holder for
++ * some reason. If this holder is the head of the list, it
++ * means we have a blocked holder at the head, so return 1.
++ */
+ if (gh->gh_list.prev == &gl->gl_holders)
+ return 1;
+ do_error(gl, 0);
+@@ -722,23 +826,6 @@ out:
+ spin_lock(&gl->gl_lockref.lock);
+ }
+
+-/**
+- * find_first_holder - find the first "holder" gh
+- * @gl: the glock
+- */
+-
+-static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
+-{
+- struct gfs2_holder *gh;
+-
+- if (!list_empty(&gl->gl_holders)) {
+- gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
+- if (test_bit(HIF_HOLDER, &gh->gh_iflags))
+- return gh;
+- }
+- return NULL;
+-}
+-
+ /**
+ * run_queue - do all outstanding tasks related to a glock
+ * @gl: The glock in question
+@@ -1354,15 +1441,20 @@ __acquires(&gl->gl_lockref.lock)
+ GLOCK_BUG_ON(gl, true);
+
+ if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
+- if (test_bit(GLF_LOCK, &gl->gl_flags))
+- try_futile = !may_grant(gl, gh);
++ if (test_bit(GLF_LOCK, &gl->gl_flags)) {
++ struct gfs2_holder *first_gh;
++
++ first_gh = find_first_strong_holder(gl);
++ try_futile = !may_grant(gl, first_gh, gh);
++ }
+ if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
+ goto fail;
+ }
+
+ list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
+ if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid &&
+- (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK)))
++ (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK) &&
++ !test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags)))
+ goto trap_recursive;
+ if (try_futile &&
+ !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) {
+@@ -1458,51 +1550,83 @@ int gfs2_glock_poll(struct gfs2_holder *gh)
+ return test_bit(HIF_WAIT, &gh->gh_iflags) ? 0 : 1;
+ }
+
+-/**
+- * gfs2_glock_dq - dequeue a struct gfs2_holder from a glock (release a glock)
+- * @gh: the glock holder
+- *
+- */
++static inline bool needs_demote(struct gfs2_glock *gl)
++{
++ return (test_bit(GLF_DEMOTE, &gl->gl_flags) ||
++ test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags));
++}
+
+-void gfs2_glock_dq(struct gfs2_holder *gh)
++static void __gfs2_glock_dq(struct gfs2_holder *gh)
+ {
+ struct gfs2_glock *gl = gh->gh_gl;
+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+ unsigned delay = 0;
+ int fast_path = 0;
+
+- spin_lock(&gl->gl_lockref.lock);
+ /*
+- * If we're in the process of file system withdraw, we cannot just
+- * dequeue any glocks until our journal is recovered, lest we
+- * introduce file system corruption. We need two exceptions to this
+- * rule: We need to allow unlocking of nondisk glocks and the glock
+- * for our own journal that needs recovery.
++ * This while loop is similar to function demote_incompat_holders:
++ * If the glock is due to be demoted (which may be from another node
++ * or even if this holder is GL_NOCACHE), the weak holders are
++ * demoted as well, allowing the glock to be demoted.
+ */
+- if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
+- glock_blocked_by_withdraw(gl) &&
+- gh->gh_gl != sdp->sd_jinode_gl) {
+- sdp->sd_glock_dqs_held++;
+- spin_unlock(&gl->gl_lockref.lock);
+- might_sleep();
+- wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
+- TASK_UNINTERRUPTIBLE);
+- spin_lock(&gl->gl_lockref.lock);
+- }
+- if (gh->gh_flags & GL_NOCACHE)
+- handle_callback(gl, LM_ST_UNLOCKED, 0, false);
++ while (gh) {
++ /*
++ * If we're in the process of file system withdraw, we cannot
++ * just dequeue any glocks until our journal is recovered, lest
++ * we introduce file system corruption. We need two exceptions
++ * to this rule: We need to allow unlocking of nondisk glocks
++ * and the glock for our own journal that needs recovery.
++ */
++ if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
++ glock_blocked_by_withdraw(gl) &&
++ gh->gh_gl != sdp->sd_jinode_gl) {
++ sdp->sd_glock_dqs_held++;
++ spin_unlock(&gl->gl_lockref.lock);
++ might_sleep();
++ wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
++ TASK_UNINTERRUPTIBLE);
++ spin_lock(&gl->gl_lockref.lock);
++ }
+
+- list_del_init(&gh->gh_list);
+- clear_bit(HIF_HOLDER, &gh->gh_iflags);
+- if (list_empty(&gl->gl_holders) &&
+- !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
+- !test_bit(GLF_DEMOTE, &gl->gl_flags))
+- fast_path = 1;
++ /*
++ * This holder should not be cached, so mark it for demote.
++ * Note: this should be done before the check for needs_demote
++ * below.
++ */
++ if (gh->gh_flags & GL_NOCACHE)
++ handle_callback(gl, LM_ST_UNLOCKED, 0, false);
++
++ list_del_init(&gh->gh_list);
++ clear_bit(HIF_HOLDER, &gh->gh_iflags);
++ trace_gfs2_glock_queue(gh, 0);
++
++ /*
++ * If there hasn't been a demote request we are done.
++ * (Let the remaining holders, if any, keep holding it.)
++ */
++ if (!needs_demote(gl)) {
++ if (list_empty(&gl->gl_holders))
++ fast_path = 1;
++ break;
++ }
++ /*
++ * If we have another strong holder (we cannot auto-demote)
++ * we are done. It keeps holding it until it is done.
++ */
++ if (find_first_strong_holder(gl))
++ break;
++
++ /*
++ * If we have a weak holder at the head of the list, it
++ * (and all others like it) must be auto-demoted. If there
++ * are no more weak holders, we exit the while loop.
++ */
++ gh = find_first_holder(gl);
++ }
+
+ if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl))
+ gfs2_glock_add_to_lru(gl);
+
+- trace_gfs2_glock_queue(gh, 0);
+ if (unlikely(!fast_path)) {
+ gl->gl_lockref.count++;
+ if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
+@@ -1511,6 +1635,19 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
+ delay = gl->gl_hold_time;
+ __gfs2_glock_queue_work(gl, delay);
+ }
++}
++
++/**
++ * gfs2_glock_dq - dequeue a struct gfs2_holder from a glock (release a glock)
++ * @gh: the glock holder
++ *
++ */
++void gfs2_glock_dq(struct gfs2_holder *gh)
++{
++ struct gfs2_glock *gl = gh->gh_gl;
++
++ spin_lock(&gl->gl_lockref.lock);
++ __gfs2_glock_dq(gh);
+ spin_unlock(&gl->gl_lockref.lock);
+ }
+
+@@ -1673,6 +1810,7 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs)
+
+ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
+ {
++ struct gfs2_holder mock_gh = { .gh_gl = gl, .gh_state = state, };
+ unsigned long delay = 0;
+ unsigned long holdtime;
+ unsigned long now = jiffies;
+@@ -1687,6 +1825,28 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
+ if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
+ delay = gl->gl_hold_time;
+ }
++ /*
++ * Note 1: We cannot call demote_incompat_holders from handle_callback
++ * or gfs2_set_demote due to recursion problems like: gfs2_glock_dq ->
++ * handle_callback -> demote_incompat_holders -> gfs2_glock_dq
++ * Plus, we only want to demote the holders if the request comes from
++ * a remote cluster node because local holder conflicts are resolved
++ * elsewhere.
++ *
++ * Note 2: if a remote node wants this glock in EX mode, lock_dlm will
++ * request that we set our state to UNLOCKED. Here we mock up a holder
++ * to make it look like someone wants the lock EX locally. Any SH
++ * and DF requests should be able to share the lock without demoting.
++ *
++ * Note 3: We only want to demote the demoteable holders when there
++ * are no more strong holders. The demoteable holders might as well
++ * keep the glock until the last strong holder is done with it.
++ */
++ if (!find_first_strong_holder(gl)) {
++ if (state == LM_ST_UNLOCKED)
++ mock_gh.gh_state = LM_ST_EXCLUSIVE;
++ demote_incompat_holders(gl, &mock_gh);
++ }
+ handle_callback(gl, state, delay, true);
+ __gfs2_glock_queue_work(gl, delay);
+ spin_unlock(&gl->gl_lockref.lock);
+@@ -1893,10 +2053,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
do {
rhashtable_walk_start(&iter);
@@ -126366,7 +190841,7 @@ index e0eaa9cf9fb6f..02cd0ae98208d 100644
rhashtable_walk_stop(&iter);
} while (cond_resched(), gl == ERR_PTR(-EAGAIN));
-@@ -1919,7 +1919,7 @@ bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay)
+@@ -1919,7 +2079,7 @@ bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay)
void gfs2_cancel_delete_work(struct gfs2_glock *gl)
{
@@ -126375,7 +190850,7 @@ index e0eaa9cf9fb6f..02cd0ae98208d 100644
clear_bit(GLF_PENDING_DELETE, &gl->gl_flags);
gfs2_glock_put(gl);
}
-@@ -1938,7 +1938,6 @@ static void flush_delete_work(struct gfs2_glock *gl)
+@@ -1938,7 +2098,6 @@ static void flush_delete_work(struct gfs2_glock *gl)
&gl->gl_delete, 0);
}
}
@@ -126383,7 +190858,7 @@ index e0eaa9cf9fb6f..02cd0ae98208d 100644
}
void gfs2_flush_delete_work(struct gfs2_sbd *sdp)
-@@ -1955,10 +1954,10 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp)
+@@ -1955,10 +2114,10 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp)
static void thaw_glock(struct gfs2_glock *gl)
{
@@ -126397,7 +190872,7 @@ index e0eaa9cf9fb6f..02cd0ae98208d 100644
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
gfs2_glock_queue_work(gl, 0);
}
-@@ -1974,9 +1973,12 @@ static void clear_glock(struct gfs2_glock *gl)
+@@ -1974,9 +2133,12 @@ static void clear_glock(struct gfs2_glock *gl)
gfs2_glock_remove_from_lru(gl);
spin_lock(&gl->gl_lockref.lock);
@@ -126413,11 +190888,172 @@ index e0eaa9cf9fb6f..02cd0ae98208d 100644
spin_unlock(&gl->gl_lockref.lock);
}
+@@ -2076,6 +2238,8 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
+ *p++ = 'H';
+ if (test_bit(HIF_WAIT, &iflags))
+ *p++ = 'W';
++ if (test_bit(HIF_MAY_DEMOTE, &iflags))
++ *p++ = 'D';
+ *p = 0;
+ return buf;
+ }
+diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
+index 31a8f2f649b52..9012487da4c69 100644
+--- a/fs/gfs2/glock.h
++++ b/fs/gfs2/glock.h
+@@ -150,6 +150,8 @@ static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *
+ list_for_each_entry(gh, &gl->gl_holders, gh_list) {
+ if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
+ break;
++ if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
++ continue;
+ if (gh->gh_owner_pid == pid)
+ goto out;
+ }
+@@ -325,6 +327,24 @@ static inline void glock_clear_object(struct gfs2_glock *gl, void *object)
+ spin_unlock(&gl->gl_lockref.lock);
+ }
+
++static inline void gfs2_holder_allow_demote(struct gfs2_holder *gh)
++{
++ struct gfs2_glock *gl = gh->gh_gl;
++
++ spin_lock(&gl->gl_lockref.lock);
++ set_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
++ spin_unlock(&gl->gl_lockref.lock);
++}
++
++static inline void gfs2_holder_disallow_demote(struct gfs2_holder *gh)
++{
++ struct gfs2_glock *gl = gh->gh_gl;
++
++ spin_lock(&gl->gl_lockref.lock);
++ clear_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
++ spin_unlock(&gl->gl_lockref.lock);
++}
++
+ extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation);
+ extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation);
+
+diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
+index 0fe49770166ea..ca42d310fd4d6 100644
+--- a/fs/gfs2/incore.h
++++ b/fs/gfs2/incore.h
+@@ -252,6 +252,7 @@ struct gfs2_lkstats {
+
+ enum {
+ /* States */
++ HIF_MAY_DEMOTE = 1,
+ HIF_HOLDER = 6, /* Set for gh that "holds" the glock */
+ HIF_WAIT = 10,
+ };
+@@ -386,9 +387,8 @@ struct gfs2_inode {
+ u64 i_generation;
+ u64 i_eattr;
+ unsigned long i_flags; /* GIF_... */
+- struct gfs2_glock *i_gl; /* Move into i_gh? */
++ struct gfs2_glock *i_gl;
+ struct gfs2_holder i_iopen_gh;
+- struct gfs2_holder i_gh; /* for prepare/commit_write only */
+ struct gfs2_qadata *i_qadata; /* quota allocation data */
+ struct gfs2_holder i_rgd_gh;
+ struct gfs2_blkreserv i_res; /* rgrp multi-block reservation */
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index 3130f85d2b3f4..97ee17843b4d0 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -811,7 +811,7 @@ fail_free_inode:
+ if (free_vfs_inode) /* else evict will do the put for us */
+ gfs2_glock_put(ip->i_gl);
+ }
+- gfs2_rs_delete(ip, NULL);
++ gfs2_rs_deltree(&ip->i_res);
+ gfs2_qa_put(ip);
+ fail_free_acls:
+ posix_acl_release(default_acl);
+diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
+index c3b00ba92ed2e..6901cd85f1df7 100644
+--- a/fs/gfs2/rgrp.c
++++ b/fs/gfs2/rgrp.c
+@@ -680,13 +680,14 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
+ /**
+ * gfs2_rs_delete - delete a multi-block reservation
+ * @ip: The inode for this reservation
+- * @wcount: The inode's write count, or NULL
+ *
+ */
+-void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount)
++void gfs2_rs_delete(struct gfs2_inode *ip)
+ {
++ struct inode *inode = &ip->i_inode;
++
+ down_write(&ip->i_rw_mutex);
+- if ((wcount == NULL) || (atomic_read(wcount) <= 1))
++ if (atomic_read(&inode->i_writecount) <= 1)
+ gfs2_rs_deltree(&ip->i_res);
+ up_write(&ip->i_rw_mutex);
+ }
+@@ -922,15 +923,15 @@ static int read_rindex_entry(struct gfs2_inode *ip)
+ spin_lock_init(&rgd->rd_rsspin);
+ mutex_init(&rgd->rd_mutex);
+
+- error = compute_bitstructs(rgd);
+- if (error)
+- goto fail;
+-
+ error = gfs2_glock_get(sdp, rgd->rd_addr,
+ &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+ if (error)
+ goto fail;
+
++ error = compute_bitstructs(rgd);
++ if (error)
++ goto fail_glock;
++
+ rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr;
+ rgd->rd_flags &= ~(GFS2_RDF_UPTODATE | GFS2_RDF_PREFERRED);
+ if (rgd->rd_data > sdp->sd_max_rg_data)
+@@ -944,6 +945,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
+ }
+
+ error = 0; /* someone else read in the rgrp; free it and ignore it */
++fail_glock:
+ gfs2_glock_put(rgd->rd_gl);
+
+ fail:
+@@ -1427,7 +1429,8 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
+
+ start = r.start >> bs_shift;
+ end = start + (r.len >> bs_shift);
+- minlen = max_t(u64, r.minlen,
++ minlen = max_t(u64, r.minlen, sdp->sd_sb.sb_bsize);
++ minlen = max_t(u64, minlen,
+ q->limits.discard_granularity) >> bs_shift;
+
+ if (end <= start || minlen > sdp->sd_max_rg_data)
+diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
+index a6855fd796e03..2f80f3bbf8767 100644
+--- a/fs/gfs2/rgrp.h
++++ b/fs/gfs2/rgrp.h
+@@ -45,7 +45,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
+ bool dinode, u64 *generation);
+
+ extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
+-extern void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount);
++extern void gfs2_rs_delete(struct gfs2_inode *ip);
+ extern void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
+ u64 bstart, u32 blen, int meta);
+ extern void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
-index 6e00d15ef0a82..cc51b5f5f52d8 100644
+index 6e00d15ef0a82..0f2e0530dd433 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
-@@ -1402,13 +1402,6 @@ out:
+@@ -1398,17 +1398,10 @@ out:
+ truncate_inode_pages_final(&inode->i_data);
+ if (ip->i_qadata)
+ gfs2_assert_warn(sdp, ip->i_qadata->qa_ref == 0);
+- gfs2_rs_delete(ip, NULL);
++ gfs2_rs_deltree(&ip->i_res);
gfs2_ordered_del_inode(ip);
clear_inode(inode);
gfs2_dir_hash_inval(ip);
@@ -126446,10 +191082,54 @@ index 6e00d15ef0a82..cc51b5f5f52d8 100644
static struct inode *gfs2_alloc_inode(struct super_block *sb)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
-index cdfb1ae78a3f8..54c4e0b0dda4a 100644
+index cdfb1ae78a3f8..bb0651a4a1287 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
-@@ -409,10 +409,11 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
+@@ -206,7 +206,7 @@ hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
+ info.flags = 0;
+ info.length = len;
+ info.low_limit = current->mm->mmap_base;
+- info.high_limit = TASK_SIZE;
++ info.high_limit = arch_get_mmap_end(addr);
+ info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+ info.align_offset = 0;
+ return vm_unmapped_area(&info);
+@@ -222,7 +222,7 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
+ info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+ info.length = len;
+ info.low_limit = max(PAGE_SIZE, mmap_min_addr);
+- info.high_limit = current->mm->mmap_base;
++ info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
+ info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+ info.align_offset = 0;
+ addr = vm_unmapped_area(&info);
+@@ -237,7 +237,7 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
+ VM_BUG_ON(addr != -ENOMEM);
+ info.flags = 0;
+ info.low_limit = current->mm->mmap_base;
+- info.high_limit = TASK_SIZE;
++ info.high_limit = arch_get_mmap_end(addr);
+ addr = vm_unmapped_area(&info);
+ }
+
+@@ -251,6 +251,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ struct hstate *h = hstate_file(file);
++ const unsigned long mmap_end = arch_get_mmap_end(addr);
+
+ if (len & ~huge_page_mask(h))
+ return -EINVAL;
+@@ -266,7 +267,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ if (addr) {
+ addr = ALIGN(addr, huge_page_size(h));
+ vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
++ if (mmap_end - len >= addr &&
+ (!vma || addr + len <= vm_start_gap(vma)))
+ return addr;
+ }
+@@ -409,10 +410,11 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
struct vm_area_struct *vma;
/*
@@ -126501,6 +191181,33 @@ index ed0cab8a32db1..9abc88d7959cb 100644
__mnt_drop_write_file(file);
return ret;
+diff --git a/fs/internal.h b/fs/internal.h
+index 3cd065c8a66b4..cdd83d4899bb3 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -23,22 +23,11 @@ struct pipe_inode_info;
+ #ifdef CONFIG_BLOCK
+ extern void __init bdev_cache_init(void);
+
+-extern int __sync_blockdev(struct block_device *bdev, int wait);
+-void iterate_bdevs(void (*)(struct block_device *, void *), void *);
+ void emergency_thaw_bdev(struct super_block *sb);
+ #else
+ static inline void bdev_cache_init(void)
+ {
+ }
+-
+-static inline int __sync_blockdev(struct block_device *bdev, int wait)
+-{
+- return 0;
+-}
+-static inline void iterate_bdevs(void (*f)(struct block_device *, void *),
+- void *arg)
+-{
+-}
+ static inline int emergency_thaw_bdev(struct super_block *sb)
+ {
+ return 0;
diff --git a/fs/io-wq.c b/fs/io-wq.c
index 422a7ed6a9bdb..01d4e3ff3170d 100644
--- a/fs/io-wq.c
@@ -126764,9 +191471,21 @@ index 422a7ed6a9bdb..01d4e3ff3170d 100644
}
diff --git a/fs/io_uring.c b/fs/io_uring.c
-index bc18af5e0a934..156c54ebb62b7 100644
+index bc18af5e0a934..b8e6398d94307 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
+@@ -623,10 +623,10 @@ struct io_epoll {
+
+ struct io_splice {
+ struct file *file_out;
+- struct file *file_in;
+ loff_t off_out;
+ loff_t off_in;
+ u64 len;
++ int splice_fd_in;
+ unsigned int flags;
+ };
+
@@ -1204,6 +1204,7 @@ static void io_refs_resurrect(struct percpu_ref *ref, struct completion *compl)
static bool io_match_task(struct io_kiocb *head, struct task_struct *task,
@@ -126820,7 +191539,22 @@ index bc18af5e0a934..156c54ebb62b7 100644
static inline void req_set_fail(struct io_kiocb *req)
{
req->flags |= REQ_F_FAIL;
-@@ -1430,10 +1469,10 @@ static void io_prep_async_link(struct io_kiocb *req)
+@@ -1413,14 +1452,6 @@ static void io_prep_async_work(struct io_kiocb *req)
+ if (def->unbound_nonreg_file)
+ req->work.flags |= IO_WQ_WORK_UNBOUND;
+ }
+-
+- switch (req->opcode) {
+- case IORING_OP_SPLICE:
+- case IORING_OP_TEE:
+- if (!S_ISREG(file_inode(req->splice.file_in)->i_mode))
+- req->work.flags |= IO_WQ_WORK_UNBOUND;
+- break;
+- }
+ }
+
+ static void io_prep_async_link(struct io_kiocb *req)
+@@ -1430,10 +1461,10 @@ static void io_prep_async_link(struct io_kiocb *req)
if (req->flags & REQ_F_LINK_TIMEOUT) {
struct io_ring_ctx *ctx = req->ctx;
@@ -126833,7 +191567,30 @@ index bc18af5e0a934..156c54ebb62b7 100644
} else {
io_for_each_link(cur, req)
io_prep_async_work(cur);
-@@ -1721,6 +1760,18 @@ static inline void io_get_task_refs(int nr)
+@@ -1507,12 +1538,11 @@ static void io_flush_timeouts(struct io_ring_ctx *ctx)
+ __must_hold(&ctx->completion_lock)
+ {
+ u32 seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts);
++ struct io_kiocb *req, *tmp;
+
+ spin_lock_irq(&ctx->timeout_lock);
+- while (!list_empty(&ctx->timeout_list)) {
++ list_for_each_entry_safe(req, tmp, &ctx->timeout_list, timeout.list) {
+ u32 events_needed, events_got;
+- struct io_kiocb *req = list_first_entry(&ctx->timeout_list,
+- struct io_kiocb, timeout.list);
+
+ if (io_is_timeout_noseq(req))
+ break;
+@@ -1529,7 +1559,6 @@ static void io_flush_timeouts(struct io_ring_ctx *ctx)
+ if (events_got < events_needed)
+ break;
+
+- list_del_init(&req->timeout.list);
+ io_kill_timeout(req, 0);
+ }
+ ctx->cq_last_tm_flush = seq;
+@@ -1721,6 +1750,18 @@ static inline void io_get_task_refs(int nr)
io_task_refs_refill(tctx);
}
@@ -126852,7 +191609,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data,
long res, unsigned int cflags)
{
-@@ -2161,6 +2212,10 @@ static void tctx_task_work(struct callback_head *cb)
+@@ -2161,6 +2202,10 @@ static void tctx_task_work(struct callback_head *cb)
}
ctx_flush_and_put(ctx, &locked);
@@ -126863,7 +191620,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
static void io_req_task_work_add(struct io_kiocb *req)
-@@ -2840,9 +2895,13 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+@@ -2840,9 +2885,13 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
req->flags |= REQ_F_ISREG;
kiocb->ki_pos = READ_ONCE(sqe->off);
@@ -126880,7 +191637,120 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
kiocb->ki_hint = ki_hint_validate(file_write_hint(kiocb->ki_filp));
kiocb->ki_flags = iocb_flags(kiocb->ki_filp);
-@@ -4304,6 +4363,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf,
+@@ -3260,13 +3309,15 @@ static ssize_t loop_rw_iter(int rw, struct io_kiocb *req, struct iov_iter *iter)
+ ret = nr;
+ break;
+ }
++ ret += nr;
+ if (!iov_iter_is_bvec(iter)) {
+ iov_iter_advance(iter, nr);
+ } else {
+- req->rw.len -= nr;
+ req->rw.addr += nr;
++ req->rw.len -= nr;
++ if (!req->rw.len)
++ break;
+ }
+- ret += nr;
+ if (nr != iovec.iov_len)
+ break;
+ }
+@@ -3966,18 +4017,11 @@ static int __io_splice_prep(struct io_kiocb *req,
+ if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+ return -EINVAL;
+
+- sp->file_in = NULL;
+ sp->len = READ_ONCE(sqe->len);
+ sp->flags = READ_ONCE(sqe->splice_flags);
+-
+ if (unlikely(sp->flags & ~valid_flags))
+ return -EINVAL;
+-
+- sp->file_in = io_file_get(req->ctx, req, READ_ONCE(sqe->splice_fd_in),
+- (sp->flags & SPLICE_F_FD_IN_FIXED));
+- if (!sp->file_in)
+- return -EBADF;
+- req->flags |= REQ_F_NEED_CLEANUP;
++ sp->splice_fd_in = READ_ONCE(sqe->splice_fd_in);
+ return 0;
+ }
+
+@@ -3992,20 +4036,27 @@ static int io_tee_prep(struct io_kiocb *req,
+ static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
+ {
+ struct io_splice *sp = &req->splice;
+- struct file *in = sp->file_in;
+ struct file *out = sp->file_out;
+ unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
++ struct file *in;
+ long ret = 0;
+
+ if (issue_flags & IO_URING_F_NONBLOCK)
+ return -EAGAIN;
++
++ in = io_file_get(req->ctx, req, sp->splice_fd_in,
++ (sp->flags & SPLICE_F_FD_IN_FIXED));
++ if (!in) {
++ ret = -EBADF;
++ goto done;
++ }
++
+ if (sp->len)
+ ret = do_tee(in, out, sp->len, flags);
+
+ if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
+ io_put_file(in);
+- req->flags &= ~REQ_F_NEED_CLEANUP;
+-
++done:
+ if (ret != sp->len)
+ req_set_fail(req);
+ io_req_complete(req, ret);
+@@ -4024,15 +4075,22 @@ static int io_splice_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
+ {
+ struct io_splice *sp = &req->splice;
+- struct file *in = sp->file_in;
+ struct file *out = sp->file_out;
+ unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
+ loff_t *poff_in, *poff_out;
++ struct file *in;
+ long ret = 0;
+
+ if (issue_flags & IO_URING_F_NONBLOCK)
+ return -EAGAIN;
+
++ in = io_file_get(req->ctx, req, sp->splice_fd_in,
++ (sp->flags & SPLICE_F_FD_IN_FIXED));
++ if (!in) {
++ ret = -EBADF;
++ goto done;
++ }
++
+ poff_in = (sp->off_in == -1) ? NULL : &sp->off_in;
+ poff_out = (sp->off_out == -1) ? NULL : &sp->off_out;
+
+@@ -4041,8 +4099,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
+
+ if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
+ io_put_file(in);
+- req->flags &= ~REQ_F_NEED_CLEANUP;
+-
++done:
+ if (ret != sp->len)
+ req_set_fail(req);
+ io_req_complete(req, ret);
+@@ -4067,9 +4124,6 @@ static int io_fsync_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
+ struct io_ring_ctx *ctx = req->ctx;
+
+- if (!req->file)
+- return -EBADF;
+-
+ if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
+ return -EINVAL;
+ if (unlikely(sqe->addr || sqe->ioprio || sqe->buf_index ||
+@@ -4304,6 +4358,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf,
kfree(nxt);
if (++i == nbufs)
return i;
@@ -126888,7 +191758,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
i++;
kfree(buf);
-@@ -4394,6 +4454,7 @@ static int io_add_buffers(struct io_provide_buf *pbuf, struct io_buffer **head)
+@@ -4394,6 +4449,7 @@ static int io_add_buffers(struct io_provide_buf *pbuf, struct io_buffer **head)
} else {
list_add_tail(&buf->list, &(*head)->list);
}
@@ -126896,7 +191766,66 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
return i ? i : -ENOMEM;
-@@ -5702,7 +5763,7 @@ static bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk,
+@@ -4730,6 +4786,8 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+
+ if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+ return -EINVAL;
++ if (unlikely(sqe->addr2 || sqe->file_index))
++ return -EINVAL;
+
+ sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
+ sr->len = READ_ONCE(sqe->len);
+@@ -4951,6 +5009,8 @@ static int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+
+ if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+ return -EINVAL;
++ if (unlikely(sqe->addr2 || sqe->file_index))
++ return -EINVAL;
+
+ sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
+ sr->len = READ_ONCE(sqe->len);
+@@ -5093,8 +5153,7 @@ static int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ accept->nofile = rlimit(RLIMIT_NOFILE);
+
+ accept->file_slot = READ_ONCE(sqe->file_index);
+- if (accept->file_slot && ((req->open.how.flags & O_CLOEXEC) ||
+- (accept->flags & SOCK_CLOEXEC)))
++ if (accept->file_slot && (accept->flags & SOCK_CLOEXEC))
+ return -EINVAL;
+ if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+ return -EINVAL;
+@@ -5603,7 +5662,6 @@ static int io_arm_poll_handler(struct io_kiocb *req)
+ struct async_poll *apoll;
+ struct io_poll_table ipt;
+ __poll_t ret, mask = EPOLLONESHOT | POLLERR | POLLPRI;
+- int rw;
+
+ if (!req->file || !file_can_poll(req->file))
+ return IO_APOLL_ABORTED;
+@@ -5613,7 +5671,6 @@ static int io_arm_poll_handler(struct io_kiocb *req)
+ return IO_APOLL_ABORTED;
+
+ if (def->pollin) {
+- rw = READ;
+ mask |= POLLIN | POLLRDNORM;
+
+ /* If reading from MSG_ERRQUEUE using recvmsg, ignore POLLIN */
+@@ -5621,14 +5678,9 @@ static int io_arm_poll_handler(struct io_kiocb *req)
+ (req->sr_msg.msg_flags & MSG_ERRQUEUE))
+ mask &= ~POLLIN;
+ } else {
+- rw = WRITE;
+ mask |= POLLOUT | POLLWRNORM;
+ }
+
+- /* if we can't nonblock try, then no point in arming a poll handler */
+- if (!io_file_supports_nowait(req, rw))
+- return IO_APOLL_ABORTED;
+-
+ apoll = kmalloc(sizeof(*apoll), GFP_ATOMIC);
+ if (unlikely(!apoll))
+ return IO_APOLL_ABORTED;
+@@ -5702,7 +5754,7 @@ static bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk,
list = &ctx->cancel_hash[i];
hlist_for_each_entry_safe(req, tmp, list, hash_node) {
@@ -126905,7 +191834,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
posted += io_poll_remove_one(req);
}
}
-@@ -5881,6 +5942,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
+@@ -5881,6 +5933,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
* update those. For multishot, if we're racing with completion, just
* let completion re-add it.
*/
@@ -126913,7 +191842,23 @@ index bc18af5e0a934..156c54ebb62b7 100644
completing = !__io_poll_remove_one(preq, &preq->poll, false);
if (completing && (preq->poll.events & EPOLLONESHOT)) {
ret = -EALREADY;
-@@ -6511,11 +6573,14 @@ static bool io_drain_req(struct io_kiocb *req)
+@@ -6147,6 +6200,7 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+ if (get_timespec64(&data->ts, u64_to_user_ptr(sqe->addr)))
+ return -EFAULT;
+
++ INIT_LIST_HEAD(&req->timeout.list);
+ data->mode = io_translate_timeout_mode(flags);
+ hrtimer_init(&data->timer, io_timeout_get_clock(data), data->mode);
+
+@@ -6346,6 +6400,7 @@ static int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
+ up.nr = 0;
+ up.tags = 0;
+ up.resv = 0;
++ up.resv2 = 0;
+
+ io_ring_submit_lock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
+ ret = __io_register_rsrc_update(ctx, IORING_RSRC_FILE,
+@@ -6511,11 +6566,14 @@ static bool io_drain_req(struct io_kiocb *req)
}
/* Still need defer if there is pending req in defer list. */
@@ -126928,7 +191873,19 @@ index bc18af5e0a934..156c54ebb62b7 100644
seq = io_get_sequence(req);
/* Still a chance to pass the sequence check */
-@@ -6884,10 +6949,11 @@ static inline struct file *io_file_get(struct io_ring_ctx *ctx,
+@@ -6586,11 +6644,6 @@ static void io_clean_op(struct io_kiocb *req)
+ kfree(io->free_iov);
+ break;
+ }
+- case IORING_OP_SPLICE:
+- case IORING_OP_TEE:
+- if (!(req->splice.flags & SPLICE_F_FD_IN_FIXED))
+- io_put_file(req->splice.file_in);
+- break;
+ case IORING_OP_OPENAT:
+ case IORING_OP_OPENAT2:
+ if (req->open.filename)
+@@ -6884,10 +6937,11 @@ static inline struct file *io_file_get(struct io_ring_ctx *ctx,
static void io_req_task_link_timeout(struct io_kiocb *req, bool *locked)
{
struct io_kiocb *prev = req->timeout.prev;
@@ -126942,7 +191899,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
io_req_complete_post(req, ret ?: -ETIME, 0);
io_put_req(prev);
} else {
-@@ -7528,7 +7594,7 @@ static int io_run_task_work_sig(void)
+@@ -7528,7 +7582,7 @@ static int io_run_task_work_sig(void)
/* when returns >0, the caller should retry */
static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
struct io_wait_queue *iowq,
@@ -126951,7 +191908,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
{
int ret;
-@@ -7540,8 +7606,9 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
+@@ -7540,8 +7594,9 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
if (test_bit(0, &ctx->check_cq_overflow))
return 1;
@@ -126963,7 +191920,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
/*
-@@ -7554,7 +7621,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+@@ -7554,7 +7609,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
{
struct io_wait_queue iowq;
struct io_rings *rings = ctx->rings;
@@ -126972,7 +191929,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
int ret;
do {
-@@ -7570,7 +7637,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+@@ -7570,7 +7625,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
if (get_timespec64(&ts, uts))
return -EFAULT;
@@ -126981,7 +191938,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
if (sig) {
-@@ -7602,7 +7669,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+@@ -7602,7 +7657,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
}
prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq,
TASK_INTERRUPTIBLE);
@@ -126990,7 +191947,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
finish_wait(&ctx->cq_wait, &iowq.wq);
cond_resched();
} while (ret > 0);
-@@ -7656,10 +7723,15 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
+@@ -7656,10 +7711,15 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
struct io_ring_ctx *ctx = node->rsrc_data->ctx;
unsigned long flags;
bool first_add = false;
@@ -127006,7 +191963,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
while (!list_empty(&ctx->rsrc_ref_list)) {
node = list_first_entry(&ctx->rsrc_ref_list,
struct io_rsrc_node, node);
-@@ -7672,7 +7744,7 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
+@@ -7672,7 +7732,7 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
spin_unlock_irqrestore(&ctx->rsrc_ref_lock, flags);
if (first_add)
@@ -127015,7 +191972,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
static struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx)
-@@ -7750,7 +7822,15 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct
+@@ -7750,7 +7810,15 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct
ret = wait_for_completion_interruptible(&data->done);
if (!ret) {
mutex_lock(&ctx->uring_lock);
@@ -127032,7 +191989,81 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
atomic_inc(&data->refs);
-@@ -8753,10 +8833,9 @@ static void io_mem_free(void *ptr)
+@@ -8045,10 +8113,15 @@ static int __io_sqe_files_scm(struct io_ring_ctx *ctx, int nr, int offset)
+ refcount_add(skb->truesize, &sk->sk_wmem_alloc);
+ skb_queue_head(&sk->sk_receive_queue, skb);
+
+- for (i = 0; i < nr_files; i++)
+- fput(fpl->fp[i]);
++ for (i = 0; i < nr; i++) {
++ struct file *file = io_file_from_index(ctx, i + offset);
++
++ if (file)
++ fput(file);
++ }
+ } else {
+ kfree_skb(skb);
++ free_uid(fpl->user);
+ kfree(fpl);
+ }
+
+@@ -8337,13 +8410,15 @@ static int io_sqe_file_register(struct io_ring_ctx *ctx, struct file *file,
+ static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
+ struct io_rsrc_node *node, void *rsrc)
+ {
++ u64 *tag_slot = io_get_tag_slot(data, idx);
+ struct io_rsrc_put *prsrc;
+
+ prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL);
+ if (!prsrc)
+ return -ENOMEM;
+
+- prsrc->tag = *io_get_tag_slot(data, idx);
++ prsrc->tag = *tag_slot;
++ *tag_slot = 0;
+ prsrc->rsrc = rsrc;
+ list_add(&prsrc->list, &node->rsrc_list);
+ return 0;
+@@ -8411,7 +8486,7 @@ static int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags)
+ struct io_ring_ctx *ctx = req->ctx;
+ struct io_fixed_file *file_slot;
+ struct file *file;
+- int ret, i;
++ int ret;
+
+ io_ring_submit_lock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
+ ret = -ENXIO;
+@@ -8424,8 +8499,8 @@ static int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags)
+ if (ret)
+ goto out;
+
+- i = array_index_nospec(offset, ctx->nr_user_files);
+- file_slot = io_fixed_file_slot(&ctx->file_table, i);
++ offset = array_index_nospec(offset, ctx->nr_user_files);
++ file_slot = io_fixed_file_slot(&ctx->file_table, offset);
+ ret = -EBADF;
+ if (!file_slot->file_ptr)
+ goto out;
+@@ -8481,8 +8556,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
+
+ if (file_slot->file_ptr) {
+ file = (struct file *)(file_slot->file_ptr & FFS_MASK);
+- err = io_queue_rsrc_removal(data, up->offset + done,
+- ctx->rsrc_node, file);
++ err = io_queue_rsrc_removal(data, i, ctx->rsrc_node, file);
+ if (err)
+ break;
+ file_slot->file_ptr = 0;
+@@ -8507,7 +8581,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
+ err = -EBADF;
+ break;
+ }
+- *io_get_tag_slot(data, up->offset + done) = tag;
++ *io_get_tag_slot(data, i) = tag;
+ io_fixed_file_set(file_slot, file);
+ err = io_sqe_file_register(ctx, file, i);
+ if (err) {
+@@ -8753,10 +8827,9 @@ static void io_mem_free(void *ptr)
static void *io_mem_alloc(size_t size)
{
@@ -127045,7 +192076,16 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
static unsigned long rings_size(unsigned sq_entries, unsigned cq_entries,
-@@ -9209,10 +9288,8 @@ static void io_destroy_buffers(struct io_ring_ctx *ctx)
+@@ -9152,7 +9225,7 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
+
+ i = array_index_nospec(offset, ctx->nr_user_bufs);
+ if (ctx->user_bufs[i] != ctx->dummy_ubuf) {
+- err = io_queue_rsrc_removal(ctx->buf_data, offset,
++ err = io_queue_rsrc_removal(ctx->buf_data, i,
+ ctx->rsrc_node, ctx->user_bufs[i]);
+ if (unlikely(err)) {
+ io_buffer_unmap(ctx, &imu);
+@@ -9209,10 +9282,8 @@ static void io_destroy_buffers(struct io_ring_ctx *ctx)
struct io_buffer *buf;
unsigned long index;
@@ -127057,7 +192097,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
static void io_req_cache_free(struct list_head *list)
-@@ -9517,19 +9594,8 @@ static bool io_cancel_task_cb(struct io_wq_work *work, void *data)
+@@ -9517,19 +9588,8 @@ static bool io_cancel_task_cb(struct io_wq_work *work, void *data)
{
struct io_kiocb *req = container_of(work, struct io_kiocb, work);
struct io_task_cancel *cancel = data;
@@ -127078,7 +192118,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
}
static bool io_cancel_defer_files(struct io_ring_ctx *ctx,
-@@ -9540,7 +9606,7 @@ static bool io_cancel_defer_files(struct io_ring_ctx *ctx,
+@@ -9540,7 +9600,7 @@ static bool io_cancel_defer_files(struct io_ring_ctx *ctx,
spin_lock(&ctx->completion_lock);
list_for_each_entry_reverse(de, &ctx->defer_list, list) {
@@ -127087,7 +192127,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
list_cut_position(&list, &ctx->defer_list, &de->list);
break;
}
-@@ -9733,21 +9799,9 @@ static s64 tctx_inflight(struct io_uring_task *tctx, bool tracked)
+@@ -9733,21 +9793,9 @@ static s64 tctx_inflight(struct io_uring_task *tctx, bool tracked)
return percpu_counter_sum(&tctx->inflight);
}
@@ -127110,7 +192150,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
*/
static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
{
-@@ -9788,8 +9842,10 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
+@@ -9788,8 +9836,10 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
cancel_all);
}
@@ -127122,7 +192162,7 @@ index bc18af5e0a934..156c54ebb62b7 100644
/*
* If we've seen completions, retry without waiting. This
* avoids a race where a completion comes in before we did
-@@ -9799,10 +9855,14 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
+@@ -9799,10 +9849,14 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
schedule();
finish_wait(&tctx->wait, &wait);
} while (1);
@@ -127138,7 +192178,60 @@ index bc18af5e0a934..156c54ebb62b7 100644
/* for exec all current's requests should be gone, kill tctx */
__io_uring_free(current);
}
-@@ -10684,7 +10744,9 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
+@@ -9925,6 +9979,8 @@ static int io_get_ext_arg(unsigned flags, const void __user *argp, size_t *argsz
+ return -EINVAL;
+ if (copy_from_user(&arg, argp, sizeof(arg)))
+ return -EFAULT;
++ if (arg.pad)
++ return -EINVAL;
+ *sig = u64_to_user_ptr(arg.sigmask);
+ *argsz = arg.sigmask_sz;
+ *ts = u64_to_user_ptr(arg.ts);
+@@ -10540,8 +10596,6 @@ static int __io_register_rsrc_update(struct io_ring_ctx *ctx, unsigned type,
+ __u32 tmp;
+ int err;
+
+- if (up->resv)
+- return -EINVAL;
+ if (check_add_overflow(up->offset, nr_args, &tmp))
+ return -EOVERFLOW;
+ err = io_rsrc_node_switch_start(ctx);
+@@ -10567,6 +10621,8 @@ static int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
+ memset(&up, 0, sizeof(up));
+ if (copy_from_user(&up, arg, sizeof(struct io_uring_rsrc_update)))
+ return -EFAULT;
++ if (up.resv || up.resv2)
++ return -EINVAL;
+ return __io_register_rsrc_update(ctx, IORING_RSRC_FILE, &up, nr_args);
+ }
+
+@@ -10579,7 +10635,7 @@ static int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
+ return -EINVAL;
+ if (copy_from_user(&up, arg, sizeof(up)))
+ return -EFAULT;
+- if (!up.nr || up.resv)
++ if (!up.nr || up.resv || up.resv2)
+ return -EINVAL;
+ return __io_register_rsrc_update(ctx, type, &up, up.nr);
+ }
+@@ -10627,7 +10683,15 @@ static int io_register_iowq_aff(struct io_ring_ctx *ctx, void __user *arg,
+ if (len > cpumask_size())
+ len = cpumask_size();
+
+- if (copy_from_user(new_mask, arg, len)) {
++ if (in_compat_syscall()) {
++ ret = compat_get_bitmap(cpumask_bits(new_mask),
++ (const compat_ulong_t __user *)arg,
++ len * 8 /* CHAR_BIT */);
++ } else {
++ ret = copy_from_user(new_mask, arg, len);
++ }
++
++ if (ret) {
+ free_cpumask_var(new_mask);
+ return -EFAULT;
+ }
+@@ -10684,7 +10748,9 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
BUILD_BUG_ON(sizeof(new_count) != sizeof(ctx->iowq_limits));
@@ -127149,8 +192242,21 @@ index bc18af5e0a934..156c54ebb62b7 100644
ctx->iowq_limits_set = true;
ret = -EINVAL;
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index 504e695781124..e0a3455f9a0f6 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -173,7 +173,7 @@ int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
+
+ if (*len == 0)
+ return -EINVAL;
+- if (start > maxbytes)
++ if (start >= maxbytes)
+ return -EFBIG;
+
+ /*
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
-index 9cc5798423d12..97119ec3b8503 100644
+index 9cc5798423d12..fe10d8a30f6bd 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -256,8 +256,13 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
@@ -127178,6 +192284,113 @@ index 9cc5798423d12..97119ec3b8503 100644
}
return done;
+@@ -750,7 +757,7 @@ again:
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ */
+- if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
++ if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
+ status = -EFAULT;
+ break;
+ }
+diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
+index 4ecd255e0511c..468dcbba45bcb 100644
+--- a/fs/iomap/direct-io.c
++++ b/fs/iomap/direct-io.c
+@@ -31,6 +31,7 @@ struct iomap_dio {
+ atomic_t ref;
+ unsigned flags;
+ int error;
++ size_t done_before;
+ bool wait_for_completion;
+
+ union {
+@@ -124,6 +125,9 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
+ if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC))
+ ret = generic_write_sync(iocb, ret);
+
++ if (ret > 0)
++ ret += dio->done_before;
++
+ kfree(dio);
+
+ return ret;
+@@ -371,6 +375,8 @@ static loff_t iomap_dio_hole_iter(const struct iomap_iter *iter,
+ loff_t length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
+
+ dio->size += length;
++ if (!length)
++ return -EFAULT;
+ return length;
+ }
+
+@@ -402,6 +408,8 @@ static loff_t iomap_dio_inline_iter(const struct iomap_iter *iomi,
+ copied = copy_to_iter(inline_data, length, iter);
+ }
+ dio->size += copied;
++ if (!copied)
++ return -EFAULT;
+ return copied;
+ }
+
+@@ -446,13 +454,21 @@ static loff_t iomap_dio_iter(const struct iomap_iter *iter,
+ * may be pure data writes. In that case, we still need to do a full data sync
+ * completion.
+ *
++ * When page faults are disabled and @dio_flags includes IOMAP_DIO_PARTIAL,
++ * __iomap_dio_rw can return a partial result if it encounters a non-resident
++ * page in @iter after preparing a transfer. In that case, the non-resident
++ * pages can be faulted in and the request resumed with @done_before set to the
++ * number of bytes previously transferred. The request will then complete with
++ * the correct total number of bytes transferred; this is essential for
++ * completing partial requests asynchronously.
++ *
+ * Returns -ENOTBLK In case of a page invalidation invalidation failure for
+ * writes. The callers needs to fall back to buffered I/O in this case.
+ */
+ struct iomap_dio *
+ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
+- unsigned int dio_flags)
++ unsigned int dio_flags, size_t done_before)
+ {
+ struct address_space *mapping = iocb->ki_filp->f_mapping;
+ struct inode *inode = file_inode(iocb->ki_filp);
+@@ -482,6 +498,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ dio->dops = dops;
+ dio->error = 0;
+ dio->flags = 0;
++ dio->done_before = done_before;
+
+ dio->submit.iter = iter;
+ dio->submit.waiter = current;
+@@ -577,6 +594,12 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ if (iov_iter_rw(iter) == READ && iomi.pos >= dio->i_size)
+ iov_iter_revert(iter, iomi.pos - dio->i_size);
+
++ if (ret == -EFAULT && dio->size && (dio_flags & IOMAP_DIO_PARTIAL)) {
++ if (!(iocb->ki_flags & IOCB_NOWAIT))
++ wait_for_completion = true;
++ ret = 0;
++ }
++
+ /* magic error code to fall back to buffered I/O */
+ if (ret == -ENOTBLK) {
+ wait_for_completion = true;
+@@ -642,11 +665,11 @@ EXPORT_SYMBOL_GPL(__iomap_dio_rw);
+ ssize_t
+ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
+- unsigned int dio_flags)
++ unsigned int dio_flags, size_t done_before)
+ {
+ struct iomap_dio *dio;
+
+- dio = __iomap_dio_rw(iocb, iter, ops, dops, dio_flags);
++ dio = __iomap_dio_rw(iocb, iter, ops, dops, dio_flags, done_before);
+ if (IS_ERR_OR_NULL(dio))
+ return PTR_ERR_OR_ZERO(dio);
+ return iomap_dio_complete(dio);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 678e2c51b855c..0c6eacfcbeef1 100644
--- a/fs/isofs/inode.c
@@ -127192,10 +192405,35 @@ index 678e2c51b855c..0c6eacfcbeef1 100644
if (offset + de_len > bufsize) {
int frag1 = bufsize - offset;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
-index 3cc4ab2ba7f4f..d188fa913a075 100644
+index 3cc4ab2ba7f4f..34b1406c06fde 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
-@@ -1170,7 +1170,7 @@ restart_loop:
+@@ -501,7 +501,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ }
+ spin_unlock(&commit_transaction->t_handle_lock);
+ commit_transaction->t_state = T_SWITCH;
+- write_unlock(&journal->j_state_lock);
+
+ J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <=
+ journal->j_max_transaction_buffers);
+@@ -521,6 +520,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ * has reserved. This is consistent with the existing behaviour
+ * that multiple jbd2_journal_get_write_access() calls to the same
+ * buffer are perfectly permissible.
++ * We use journal->j_state_lock here to serialize processing of
++ * t_reserved_list with eviction of buffers from journal_unmap_buffer().
+ */
+ while (commit_transaction->t_reserved_list) {
+ jh = commit_transaction->t_reserved_list;
+@@ -540,6 +541,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ jbd2_journal_refile_buffer(journal, jh);
+ }
+
++ write_unlock(&journal->j_state_lock);
+ /*
+ * Now try to drop any written-back buffers from the journal's
+ * checkpoint lists. We do this *before* commit because it potentially
+@@ -1170,7 +1172,7 @@ restart_loop:
if (journal->j_commit_callback)
journal->j_commit_callback(journal, commit_transaction);
if (journal->j_fc_cleanup_callback)
@@ -127233,6 +192471,27 @@ index 35302bc192eb9..1f8493ef181d6 100644
/*
* Initialize jbd inode head
+diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
+index b288c8ae1236b..837cd55fd4c5e 100644
+--- a/fs/jffs2/build.c
++++ b/fs/jffs2/build.c
+@@ -415,13 +415,15 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
+ jffs2_free_ino_caches(c);
+ jffs2_free_raw_node_refs(c);
+ ret = -EIO;
+- goto out_free;
++ goto out_sum_exit;
+ }
+
+ jffs2_calc_trigger_levels(c);
+
+ return 0;
+
++ out_sum_exit:
++ jffs2_sum_exit(c);
+ out_free:
+ kvfree(c->blocks);
+
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 4fc8cd698d1a4..bd7d58d27bfc6 100644
--- a/fs/jffs2/file.c
@@ -127329,6 +192588,94 @@ index 4fc8cd698d1a4..bd7d58d27bfc6 100644
return ret;
}
+diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
+index 2ac410477c4f4..71f03a5d36ed2 100644
+--- a/fs/jffs2/fs.c
++++ b/fs/jffs2/fs.c
+@@ -603,8 +603,8 @@ out_root:
+ jffs2_free_ino_caches(c);
+ jffs2_free_raw_node_refs(c);
+ kvfree(c->blocks);
+- out_inohash:
+ jffs2_clear_xattr_subsystem(c);
++ out_inohash:
+ kfree(c->inocache_list);
+ out_wbuf:
+ jffs2_flash_cleanup(c);
+diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
+index b676056826beb..29671e33a1714 100644
+--- a/fs/jffs2/scan.c
++++ b/fs/jffs2/scan.c
+@@ -136,7 +136,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
+ if (!s) {
+ JFFS2_WARNING("Can't allocate memory for summary\n");
+ ret = -ENOMEM;
+- goto out;
++ goto out_buf;
+ }
+ }
+
+@@ -275,13 +275,15 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
+ }
+ ret = 0;
+ out:
++ jffs2_sum_reset_collected(s);
++ kfree(s);
++ out_buf:
+ if (buf_size)
+ kfree(flashbuf);
+ #ifndef __ECOS
+ else
+ mtd_unpoint(c->mtd, 0, c->mtd->size);
+ #endif
+- kfree(s);
+ return ret;
+ }
+
+diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
+index 57ab424c05ff0..072821b50ab91 100644
+--- a/fs/jfs/inode.c
++++ b/fs/jfs/inode.c
+@@ -146,12 +146,13 @@ void jfs_evict_inode(struct inode *inode)
+ dquot_initialize(inode);
+
+ if (JFS_IP(inode)->fileset == FILESYSTEM_I) {
++ struct inode *ipimap = JFS_SBI(inode->i_sb)->ipimap;
+ truncate_inode_pages_final(&inode->i_data);
+
+ if (test_cflag(COMMIT_Freewmap, inode))
+ jfs_free_zero_link(inode);
+
+- if (JFS_SBI(inode->i_sb)->ipimap)
++ if (ipimap && JFS_IP(ipimap)->i_imap)
+ diFree(inode);
+
+ /*
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 91f4ec93dab1f..d8502f4989d9d 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -148,6 +148,7 @@ static const s8 budtab[256] = {
+ * 0 - success
+ * -ENOMEM - insufficient memory
+ * -EIO - i/o error
++ * -EINVAL - wrong bmap data
+ */
+ int dbMount(struct inode *ipbmap)
+ {
+@@ -179,6 +180,12 @@ int dbMount(struct inode *ipbmap)
+ bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
+ bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
+ bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
++ if (!bmp->db_numag) {
++ release_metapage(mp);
++ kfree(bmp);
++ return -EINVAL;
++ }
++
+ bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
+ bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
+ bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 5d7d7170c03c0..aa4ff7bcaff23 100644
--- a/fs/jfs/jfs_mount.c
@@ -127759,10 +193106,18 @@ index fb6a65d231391..f0a5b704f301c 100644
+ smb311_server_values.max_credits = sz;
+}
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
-index 7e448df3f8474..192d8308afc27 100644
+index 7e448df3f8474..1ed3046dd5b3f 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
-@@ -301,16 +301,15 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
+@@ -11,6 +11,7 @@
+ #include <linux/statfs.h>
+ #include <linux/ethtool.h>
+ #include <linux/falloc.h>
++#include <linux/mount.h>
+
+ #include "glob.h"
+ #include "smb2pdu.h"
+@@ -301,16 +302,15 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
struct smb2_hdr *hdr = ksmbd_resp_buf_next(work);
struct ksmbd_conn *conn = work->conn;
@@ -127781,7 +193136,7 @@ index 7e448df3f8474..192d8308afc27 100644
hdr->CreditRequest = 0;
pr_err("Total credits overflow: %d\n", conn->total_credits);
return -EINVAL;
-@@ -318,6 +317,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
+@@ -318,6 +318,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
credit_charge = max_t(unsigned short,
le16_to_cpu(req_hdr->CreditCharge), 1);
@@ -127796,7 +193151,7 @@ index 7e448df3f8474..192d8308afc27 100644
credits_requested = max_t(unsigned short,
le16_to_cpu(req_hdr->CreditRequest), 1);
-@@ -327,16 +334,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
+@@ -327,16 +335,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
* TODO: Need to adjuct CreditRequest value according to
* current cpu load
*/
@@ -127818,7 +193173,7 @@ index 7e448df3f8474..192d8308afc27 100644
conn->total_credits;
conn->total_credits += credits_granted;
-@@ -917,6 +922,25 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
+@@ -917,6 +923,25 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
}
}
@@ -127844,7 +193199,7 @@ index 7e448df3f8474..192d8308afc27 100644
static void decode_compress_ctxt(struct ksmbd_conn *conn,
struct smb2_compression_ctx *pneg_ctxt)
{
-@@ -1438,11 +1462,6 @@ static int ntlm_authenticate(struct ksmbd_work *work)
+@@ -1438,11 +1463,6 @@ static int ntlm_authenticate(struct ksmbd_work *work)
sess->user = user;
if (user_guest(sess->user)) {
@@ -127856,7 +193211,7 @@ index 7e448df3f8474..192d8308afc27 100644
rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE;
} else {
struct authenticate_message *authblob;
-@@ -1455,39 +1474,39 @@ static int ntlm_authenticate(struct ksmbd_work *work)
+@@ -1455,39 +1475,39 @@ static int ntlm_authenticate(struct ksmbd_work *work)
ksmbd_debug(SMB, "authentication failed\n");
return -EPERM;
}
@@ -127925,7 +193280,7 @@ index 7e448df3f8474..192d8308afc27 100644
}
binding_session:
-@@ -1562,8 +1581,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
+@@ -1562,8 +1582,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
sess->sign = true;
@@ -127935,7 +193290,7 @@ index 7e448df3f8474..192d8308afc27 100644
retval = conn->ops->generate_encryptionkey(sess);
if (retval) {
ksmbd_debug(SMB,
-@@ -1700,8 +1718,10 @@ int smb2_sess_setup(struct ksmbd_work *work)
+@@ -1700,8 +1719,10 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off = le16_to_cpu(req->SecurityBufferOffset);
negblob_len = le16_to_cpu(req->SecurityBufferLength);
if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) ||
@@ -127948,7 +193303,7 @@ index 7e448df3f8474..192d8308afc27 100644
negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId +
negblob_off);
-@@ -2670,7 +2690,7 @@ int smb2_open(struct ksmbd_work *work)
+@@ -2670,7 +2691,7 @@ int smb2_open(struct ksmbd_work *work)
(struct create_posix *)context;
if (le16_to_cpu(context->DataOffset) +
le32_to_cpu(context->DataLength) <
@@ -127957,7 +193312,7 @@ index 7e448df3f8474..192d8308afc27 100644
rc = -EINVAL;
goto err_out1;
}
-@@ -2962,6 +2982,10 @@ int smb2_open(struct ksmbd_work *work)
+@@ -2962,6 +2983,10 @@ int smb2_open(struct ksmbd_work *work)
&pntsd_size, &fattr);
posix_acl_release(fattr.cf_acls);
posix_acl_release(fattr.cf_dacls);
@@ -127968,7 +193323,7 @@ index 7e448df3f8474..192d8308afc27 100644
rc = ksmbd_vfs_set_sd_xattr(conn,
user_ns,
-@@ -3398,9 +3422,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
+@@ -3398,9 +3423,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
goto free_conv_name;
}
@@ -127981,7 +193336,7 @@ index 7e448df3f8474..192d8308afc27 100644
if (next_entry_offset > d_info->out_buf_len) {
d_info->out_buf_len = 0;
-@@ -3952,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work)
+@@ -3952,6 +3977,7 @@ int smb2_query_dir(struct ksmbd_work *work)
((struct file_directory_info *)
((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0;
@@ -127989,7 +193344,7 @@ index 7e448df3f8474..192d8308afc27 100644
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
-@@ -4450,6 +4475,12 @@ static void get_file_stream_info(struct ksmbd_work *work,
+@@ -4450,6 +4476,12 @@ static void get_file_stream_info(struct ksmbd_work *work,
&stat);
file_info = (struct smb2_file_stream_info *)rsp->Buffer;
@@ -128002,7 +193357,7 @@ index 7e448df3f8474..192d8308afc27 100644
xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
-@@ -4458,12 +4489,6 @@ static void get_file_stream_info(struct ksmbd_work *work,
+@@ -4458,12 +4490,6 @@ static void get_file_stream_info(struct ksmbd_work *work,
goto out;
}
@@ -128015,7 +193370,7 @@ index 7e448df3f8474..192d8308afc27 100644
while (idx < xattr_list_len) {
stream_name = xattr_list + idx;
streamlen = strlen(stream_name);
-@@ -4489,8 +4514,10 @@ static void get_file_stream_info(struct ksmbd_work *work,
+@@ -4489,8 +4515,10 @@ static void get_file_stream_info(struct ksmbd_work *work,
":%s", &stream_name[XATTR_NAME_STREAM_LEN]);
next = sizeof(struct smb2_file_stream_info) + streamlen * 2;
@@ -128027,7 +193382,7 @@ index 7e448df3f8474..192d8308afc27 100644
file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes];
streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
-@@ -4507,6 +4534,7 @@ static void get_file_stream_info(struct ksmbd_work *work,
+@@ -4507,6 +4535,7 @@ static void get_file_stream_info(struct ksmbd_work *work,
file_info->NextEntryOffset = cpu_to_le32(next);
}
@@ -128035,7 +193390,7 @@ index 7e448df3f8474..192d8308afc27 100644
if (!S_ISDIR(stat.mode) &&
buf_free_len >= sizeof(struct smb2_file_stream_info) + 7 * 2) {
file_info = (struct smb2_file_stream_info *)
-@@ -4515,14 +4543,13 @@ static void get_file_stream_info(struct ksmbd_work *work,
+@@ -4515,14 +4544,13 @@ static void get_file_stream_info(struct ksmbd_work *work,
"::$DATA", 7, conn->local_nls, 0);
streamlen *= 2;
file_info->StreamNameLength = cpu_to_le32(streamlen);
@@ -128052,7 +193407,7 @@ index 7e448df3f8474..192d8308afc27 100644
kvfree(xattr_list);
rsp->OutputBufferLength = cpu_to_le32(nbytes);
-@@ -4891,11 +4918,18 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
+@@ -4891,11 +4919,18 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
{
struct filesystem_vol_info *info;
size_t sz;
@@ -128072,7 +193427,29 @@ index 7e448df3f8474..192d8308afc27 100644
len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
share->name, PATH_MAX,
conn->local_nls, 0);
-@@ -5053,7 +5087,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
+@@ -4963,15 +4998,17 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
+ case FS_SECTOR_SIZE_INFORMATION:
+ {
+ struct smb3_fs_ss_info *info;
++ unsigned int sector_size =
++ min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096);
+
+ info = (struct smb3_fs_ss_info *)(rsp->Buffer);
+
+- info->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize);
++ info->LogicalBytesPerSector = cpu_to_le32(sector_size);
+ info->PhysicalBytesPerSectorForAtomicity =
+- cpu_to_le32(stfs.f_bsize);
+- info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize);
++ cpu_to_le32(sector_size);
++ info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size);
+ info->FSEffPhysicalBytesPerSectorForAtomicity =
+- cpu_to_le32(stfs.f_bsize);
++ cpu_to_le32(sector_size);
+ info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
+ SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
+ info->ByteOffsetForSectorAlignment = 0;
+@@ -5053,7 +5090,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
PROTECTED_DACL_SECINFO |
UNPROTECTED_DACL_SECINFO)) {
@@ -128081,7 +193458,18 @@ index 7e448df3f8474..192d8308afc27 100644
addition_info);
pntsd->revision = cpu_to_le16(1);
-@@ -7312,7 +7346,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
+@@ -5734,8 +5771,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
+ if (parent_fp) {
+ if (parent_fp->daccess & FILE_DELETE_LE) {
+ pr_err("parent dir is opened with delete access\n");
++ ksmbd_fd_put(work, parent_fp);
+ return -ESHARE;
+ }
++ ksmbd_fd_put(work, parent_fp);
+ }
+ next:
+ return smb2_rename(work, fp, user_ns, rename_info,
+@@ -7312,7 +7351,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
int ret = 0;
int dialect;
@@ -128191,6 +193579,18 @@ index b0d5b8feb4a36..432c947731779 100644
};
struct ksmbd_readdir_data {
+diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
+index 29c1db66bd0f7..8b873d92d7854 100644
+--- a/fs/ksmbd/vfs_cache.c
++++ b/fs/ksmbd/vfs_cache.c
+@@ -497,6 +497,7 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
+ list_for_each_entry(lfp, &ci->m_fp_list, node) {
+ if (inode == file_inode(lfp->filp)) {
+ atomic_dec(&ci->m_count);
++ lfp = ksmbd_fp_get(lfp);
+ read_unlock(&ci->m_lock);
+ return lfp;
+ }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index cb3a7512c33ec..0a22a2faf5522 100644
--- a/fs/lockd/svcsubs.c
@@ -128225,11 +193625,74 @@ index cb3a7512c33ec..0a22a2faf5522 100644
}
/*
+diff --git a/fs/minix/inode.c b/fs/minix/inode.c
+index a71f1cf894b9f..d4bd94234ef73 100644
+--- a/fs/minix/inode.c
++++ b/fs/minix/inode.c
+@@ -447,7 +447,8 @@ static const struct address_space_operations minix_aops = {
+ .writepage = minix_writepage,
+ .write_begin = minix_write_begin,
+ .write_end = generic_write_end,
+- .bmap = minix_bmap
++ .bmap = minix_bmap,
++ .direct_IO = noop_direct_IO
+ };
+
+ static const struct inode_operations minix_symlink_inode_operations = {
diff --git a/fs/namei.c b/fs/namei.c
-index 1946d96677908..3bb65f48fe1da 100644
+index 1946d96677908..8882a70dc1192 100644
--- a/fs/namei.c
+++ b/fs/namei.c
-@@ -3975,13 +3975,12 @@ int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir,
+@@ -3625,18 +3625,14 @@ static struct dentry *filename_create(int dfd, struct filename *name,
+ {
+ struct dentry *dentry = ERR_PTR(-EEXIST);
+ struct qstr last;
++ bool want_dir = lookup_flags & LOOKUP_DIRECTORY;
++ unsigned int reval_flag = lookup_flags & LOOKUP_REVAL;
++ unsigned int create_flags = LOOKUP_CREATE | LOOKUP_EXCL;
+ int type;
+ int err2;
+ int error;
+- bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
+
+- /*
+- * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
+- * other flags passed in are ignored!
+- */
+- lookup_flags &= LOOKUP_REVAL;
+-
+- error = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
++ error = filename_parentat(dfd, name, reval_flag, path, &last, &type);
+ if (error)
+ return ERR_PTR(error);
+
+@@ -3650,11 +3646,13 @@ static struct dentry *filename_create(int dfd, struct filename *name,
+ /* don't fail immediately if it's r/o, at least try to report other errors */
+ err2 = mnt_want_write(path->mnt);
+ /*
+- * Do the final lookup.
++ * Do the final lookup. Suppress 'create' if there is a trailing
++ * '/', and a directory wasn't requested.
+ */
+- lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
++ if (last.name[last.len] && !want_dir)
++ create_flags = 0;
+ inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
+- dentry = __lookup_hash(&last, path->dentry, lookup_flags);
++ dentry = __lookup_hash(&last, path->dentry, reval_flag | create_flags);
+ if (IS_ERR(dentry))
+ goto unlock;
+
+@@ -3668,7 +3666,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
+ * all is fine. Let's be bastards - you had / on the end, you've
+ * been asking for (non-existent) directory. -ENOENT for you.
+ */
+- if (unlikely(!is_dir && last.name[last.len])) {
++ if (unlikely(!create_flags)) {
+ error = -ENOENT;
+ goto fail;
+ }
+@@ -3975,13 +3973,12 @@ int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir,
dentry->d_inode->i_flags |= S_DEAD;
dont_mount(dentry);
detach_mounts(dentry);
@@ -128244,7 +193707,7 @@ index 1946d96677908..3bb65f48fe1da 100644
return error;
}
EXPORT_SYMBOL(vfs_rmdir);
-@@ -4103,7 +4102,6 @@ int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
+@@ -4103,7 +4100,6 @@ int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
if (!error) {
dont_mount(dentry);
detach_mounts(dentry);
@@ -128252,7 +193715,7 @@ index 1946d96677908..3bb65f48fe1da 100644
}
}
}
-@@ -4111,9 +4109,11 @@ out:
+@@ -4111,9 +4107,11 @@ out:
inode_unlock(target);
/* We don't d_delete() NFS sillyrenamed files--they still exist. */
@@ -128362,20 +193825,58 @@ index 6a2033131c068..ccd4f245cae24 100644
};
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
-index ed9d580826f5a..f2bc5b5b764b7 100644
+index ed9d580826f5a..a30dd35ec1c26 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
-@@ -358,7 +358,7 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
+@@ -358,12 +358,11 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
struct cb_process_state *cps)
{
struct cb_devicenotifyargs *args = argp;
- int i;
++ const struct pnfs_layoutdriver_type *ld = NULL;
+ uint32_t i;
__be32 res = 0;
- struct nfs_client *clp = cps->clp;
- struct nfs_server *server = NULL;
+- struct nfs_client *clp = cps->clp;
+- struct nfs_server *server = NULL;
+
+- if (!clp) {
++ if (!cps->clp) {
+ res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
+ goto out;
+ }
+@@ -371,23 +370,15 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
+ for (i = 0; i < args->ndevs; i++) {
+ struct cb_devicenotifyitem *dev = &args->devs[i];
+
+- if (!server ||
+- server->pnfs_curr_ld->id != dev->cbd_layout_type) {
+- rcu_read_lock();
+- list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
+- if (server->pnfs_curr_ld &&
+- server->pnfs_curr_ld->id == dev->cbd_layout_type) {
+- rcu_read_unlock();
+- goto found;
+- }
+- rcu_read_unlock();
+- continue;
++ if (!ld || ld->id != dev->cbd_layout_type) {
++ pnfs_put_layoutdriver(ld);
++ ld = pnfs_find_layoutdriver(dev->cbd_layout_type);
++ if (!ld)
++ continue;
+ }
+-
+- found:
+- nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
++ nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id);
+ }
+-
++ pnfs_put_layoutdriver(ld);
+ out:
+ kfree(args->devs);
+ return res;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
-index 4c48d85f65170..ce3d1d5b1291f 100644
+index 4c48d85f65170..ea17085ef884b 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -258,11 +258,9 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
@@ -128391,16 +193892,21 @@ index 4c48d85f65170..ce3d1d5b1291f 100644
/* Num of device notifications */
p = xdr_inline_decode(xdr, sizeof(uint32_t));
-@@ -271,7 +269,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
+@@ -271,12 +269,8 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
goto out;
}
n = ntohl(*p++);
- if (n <= 0)
+- goto out;
+- if (n > ULONG_MAX / sizeof(*args->devs)) {
+- status = htonl(NFS4ERR_BADXDR);
+ if (n == 0)
goto out;
- if (n > ULONG_MAX / sizeof(*args->devs)) {
- status = htonl(NFS4ERR_BADXDR);
-@@ -330,19 +328,21 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
+- }
+
+ args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
+ if (!args->devs) {
+@@ -330,19 +324,21 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
dev->cbd_immediate = 0;
}
@@ -128462,7 +193968,7 @@ index 23e165d5ec9ca..090b16890e3d6 100644
}
EXPORT_SYMBOL_GPL(nfs_probe_fsinfo);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
-index 1a6d2867fba4f..9adc6f57a0083 100644
+index 1a6d2867fba4f..78219396788b4 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -870,7 +870,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
@@ -128509,7 +194015,24 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
spin_unlock(&inode->i_lock);
}
-@@ -1983,6 +1984,24 @@ out:
+@@ -1834,16 +1835,6 @@ const struct dentry_operations nfs4_dentry_operations = {
+ };
+ EXPORT_SYMBOL_GPL(nfs4_dentry_operations);
+
+-static fmode_t flags_to_mode(int flags)
+-{
+- fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
+- if ((flags & O_ACCMODE) != O_WRONLY)
+- res |= FMODE_READ;
+- if ((flags & O_ACCMODE) != O_RDONLY)
+- res |= FMODE_WRITE;
+- return res;
+-}
+-
+ static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags, struct file *filp)
+ {
+ return alloc_nfs_open_context(dentry, flags_to_mode(open_flags), filp);
+@@ -1983,6 +1974,24 @@ out:
no_open:
res = nfs_lookup(dir, dentry, lookup_flags);
@@ -128534,7 +194057,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
if (switched) {
d_lookup_done(dentry);
if (!res)
-@@ -2383,6 +2402,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+@@ -2383,6 +2392,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
trace_nfs_link_enter(inode, dir, dentry);
d_drop(dentry);
@@ -128543,7 +194066,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
if (error == 0) {
ihold(inode);
-@@ -2471,6 +2492,8 @@ int nfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
+@@ -2471,6 +2482,8 @@ int nfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
}
}
@@ -128552,7 +194075,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
if (IS_ERR(task)) {
error = PTR_ERR(task);
-@@ -2676,7 +2699,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
+@@ -2676,7 +2689,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
return NULL;
}
@@ -128561,7 +194084,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_access_entry *cache;
-@@ -2706,8 +2729,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
+@@ -2706,8 +2719,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
spin_lock(&inode->i_lock);
retry = false;
}
@@ -128571,7 +194094,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
err = 0;
out:
-@@ -2719,7 +2741,7 @@ out_zap:
+@@ -2719,7 +2731,7 @@ out_zap:
return -ENOENT;
}
@@ -128580,7 +194103,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
{
/* Only check the most recently returned cache entry,
* but do it without locking.
-@@ -2741,22 +2763,21 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
+@@ -2741,22 +2753,21 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
goto out;
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
goto out;
@@ -128608,7 +194131,7 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
may_block);
return status;
-@@ -2877,7 +2898,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
+@@ -2877,7 +2888,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
trace_nfs_access_enter(inode);
@@ -128618,10 +194141,56 @@ index 1a6d2867fba4f..9adc6f57a0083 100644
goto out_cached;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
-index 2e894fec036b0..3c0335c15a730 100644
+index 2e894fec036b0..c220810c61d14 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
-@@ -620,7 +620,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
+@@ -172,8 +172,8 @@ ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+ VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
+
+ if (iov_iter_rw(iter) == READ)
+- return nfs_file_direct_read(iocb, iter);
+- return nfs_file_direct_write(iocb, iter);
++ return nfs_file_direct_read(iocb, iter, true);
++ return nfs_file_direct_write(iocb, iter, true);
+ }
+
+ static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
+@@ -424,6 +424,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
+ * nfs_file_direct_read - file direct read operation for NFS files
+ * @iocb: target I/O control block
+ * @iter: vector of user buffers into which to read data
++ * @swap: flag indicating this is swap IO, not O_DIRECT IO
+ *
+ * We use this function for direct reads instead of calling
+ * generic_file_aio_read() in order to avoid gfar's check to see if
+@@ -439,7 +440,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
+ * client must read the updated atime from the server back into its
+ * cache.
+ */
+-ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
++ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
++ bool swap)
+ {
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+@@ -481,12 +483,14 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
+ if (iter_is_iovec(iter))
+ dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
+
+- nfs_start_io_direct(inode);
++ if (!swap)
++ nfs_start_io_direct(inode);
+
+ NFS_I(inode)->read_io += count;
+ requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos);
+
+- nfs_end_io_direct(inode);
++ if (!swap)
++ nfs_end_io_direct(inode);
+
+ if (requested > 0) {
+ result = nfs_direct_wait(dreq);
+@@ -620,7 +624,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
nfs_unlock_and_release_request(req);
}
@@ -128630,6 +194199,107 @@ index 2e894fec036b0..3c0335c15a730 100644
nfs_direct_write_complete(dreq);
}
+@@ -789,7 +793,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
+ */
+ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
+ struct iov_iter *iter,
+- loff_t pos)
++ loff_t pos, int ioflags)
+ {
+ struct nfs_pageio_descriptor desc;
+ struct inode *inode = dreq->inode;
+@@ -797,7 +801,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
+ size_t requested_bytes = 0;
+ size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
+
+- nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, false,
++ nfs_pageio_init_write(&desc, inode, ioflags, false,
+ &nfs_direct_write_completion_ops);
+ desc.pg_dreq = dreq;
+ get_dreq(dreq);
+@@ -875,6 +879,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
+ * nfs_file_direct_write - file direct write operation for NFS files
+ * @iocb: target I/O control block
+ * @iter: vector of user buffers from which to write data
++ * @swap: flag indicating this is swap IO, not O_DIRECT IO
+ *
+ * We use this function for direct writes instead of calling
+ * generic_file_aio_write() in order to avoid taking the inode
+@@ -891,7 +896,8 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
+ * Note that O_APPEND is not supported for NFS direct writes, as there
+ * is no atomic O_APPEND write facility in the NFS protocol.
+ */
+-ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
++ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
++ bool swap)
+ {
+ ssize_t result, requested;
+ size_t count;
+@@ -905,7 +911,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
+ dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
+ file, iov_iter_count(iter), (long long) iocb->ki_pos);
+
+- result = generic_write_checks(iocb, iter);
++ if (swap)
++ /* bypass generic checks */
++ result = iov_iter_count(iter);
++ else
++ result = generic_write_checks(iocb, iter);
+ if (result <= 0)
+ return result;
+ count = result;
+@@ -936,16 +946,22 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
+ dreq->iocb = iocb;
+ pnfs_init_ds_commit_info_ops(&dreq->ds_cinfo, inode);
+
+- nfs_start_io_direct(inode);
++ if (swap) {
++ requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
++ FLUSH_STABLE);
++ } else {
++ nfs_start_io_direct(inode);
+
+- requested = nfs_direct_write_schedule_iovec(dreq, iter, pos);
++ requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
++ FLUSH_COND_STABLE);
+
+- if (mapping->nrpages) {
+- invalidate_inode_pages2_range(mapping,
+- pos >> PAGE_SHIFT, end);
+- }
++ if (mapping->nrpages) {
++ invalidate_inode_pages2_range(mapping,
++ pos >> PAGE_SHIFT, end);
++ }
+
+- nfs_end_io_direct(inode);
++ nfs_end_io_direct(inode);
++ }
+
+ if (requested > 0) {
+ result = nfs_direct_wait(dreq);
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index aa353fd582404..42a16993913a8 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -161,7 +161,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
+ ssize_t result;
+
+ if (iocb->ki_flags & IOCB_DIRECT)
+- return nfs_file_direct_read(iocb, to);
++ return nfs_file_direct_read(iocb, to, false);
+
+ dprintk("NFS: read(%pD2, %zu@%lu)\n",
+ iocb->ki_filp,
+@@ -616,7 +616,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
+ return result;
+
+ if (iocb->ki_flags & IOCB_DIRECT)
+- return nfs_file_direct_write(iocb, from);
++ return nfs_file_direct_write(iocb, from, false);
+
+ dprintk("NFS: write(%pD2, %zu@%Ld)\n",
+ file, iov_iter_count(from), (long long) iocb->ki_pos);
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index c9b61b818ec11..bfa7202ca7be1 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -128647,8 +194317,21 @@ index c9b61b818ec11..bfa7202ca7be1 100644
/* FIXME: For now we assume the server sent only one version of NFS
* to use for the DS.
+diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
+index 0d444a90f513a..fb3cad38b1497 100644
+--- a/fs/nfs/fs_context.c
++++ b/fs/nfs/fs_context.c
+@@ -514,7 +514,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
+ if (result.negated)
+ ctx->flags &= ~NFS_MOUNT_SOFTREVAL;
+ else
+- ctx->flags &= NFS_MOUNT_SOFTREVAL;
++ ctx->flags |= NFS_MOUNT_SOFTREVAL;
+ break;
+ case Opt_posix:
+ if (result.negated)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
-index 853213b3a2095..410f87bc48cca 100644
+index 853213b3a2095..f4f75db7a8258 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -210,10 +210,15 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
@@ -128685,7 +194368,15 @@ index 853213b3a2095..410f87bc48cca 100644
/*
* We may force a getattr if the user cares about atime.
-@@ -1777,8 +1779,10 @@ static int nfs_inode_finish_partial_attr_update(const struct nfs_fattr *fattr,
+@@ -1165,7 +1167,6 @@ int nfs_open(struct inode *inode, struct file *filp)
+ nfs_fscache_open_file(inode, filp);
+ return 0;
+ }
+-EXPORT_SYMBOL_GPL(nfs_open);
+
+ /*
+ * This function is called whenever some part of NFS notices that
+@@ -1777,8 +1778,10 @@ static int nfs_inode_finish_partial_attr_update(const struct nfs_fattr *fattr,
NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_OTHER |
NFS_INO_INVALID_NLINK;
unsigned long cache_validity = NFS_I(inode)->cache_validity;
@@ -128697,21 +194388,132 @@ index 853213b3a2095..410f87bc48cca 100644
(cache_validity & check_valid) != 0 &&
(fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 &&
nfs_inode_attrs_cmp_monotonic(fattr, inode) == 0)
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 66fc936834f23..c8845242d4225 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -42,6 +42,16 @@ static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry)
+ return true;
+ }
+
++static inline fmode_t flags_to_mode(int flags)
++{
++ fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
++ if ((flags & O_ACCMODE) != O_WRONLY)
++ res |= FMODE_READ;
++ if ((flags & O_ACCMODE) != O_RDONLY)
++ res |= FMODE_WRITE;
++ return res;
++}
++
+ /*
+ * Note: RFC 1813 doesn't limit the number of auth flavors that
+ * a server can return, so make something up.
+@@ -580,6 +590,13 @@ nfs_write_match_verf(const struct nfs_writeverf *verf,
+ !nfs_write_verifier_cmp(&req->wb_verf, &verf->verifier);
+ }
+
++static inline gfp_t nfs_io_gfp_mask(void)
++{
++ if (current->flags & PF_WQ_WORKER)
++ return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
++ return GFP_KERNEL;
++}
++
+ /* unlink.c */
+ extern struct rpc_task *
+ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
+diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
+index 7fba7711e6b3a..3d5ba43f44bb6 100644
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -949,7 +949,7 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+
+ error = decode_filename_inline(xdr, &entry->name, &entry->len);
+ if (unlikely(error))
+- return error;
++ return -EAGAIN;
+
+ /*
+ * The type (size and byte order) of nfscookie isn't defined in
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
-index e6eca1d7481b8..9274c9c5efea6 100644
+index e6eca1d7481b8..7ab60ad98776f 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
-@@ -2227,7 +2227,7 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
+@@ -1967,7 +1967,6 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+ bool plus)
+ {
+ struct user_namespace *userns = rpc_userns(entry->server->client);
+- struct nfs_entry old = *entry;
+ __be32 *p;
+ int error;
+ u64 new_cookie;
+@@ -1987,15 +1986,15 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+
+ error = decode_fileid3(xdr, &entry->ino);
+ if (unlikely(error))
+- return error;
++ return -EAGAIN;
+
+ error = decode_inline_filename3(xdr, &entry->name, &entry->len);
+ if (unlikely(error))
+- return error;
++ return -EAGAIN;
+
+ error = decode_cookie3(xdr, &new_cookie);
+ if (unlikely(error))
+- return error;
++ return -EAGAIN;
+
+ entry->d_type = DT_UNKNOWN;
+
+@@ -2003,7 +2002,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+ entry->fattr->valid = 0;
+ error = decode_post_op_attr(xdr, entry->fattr, userns);
+ if (unlikely(error))
+- return error;
++ return -EAGAIN;
+ if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
+ entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
+
+@@ -2018,11 +2017,8 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+ return -EAGAIN;
+ if (*p != xdr_zero) {
+ error = decode_nfs_fh3(xdr, entry->fh);
+- if (unlikely(error)) {
+- if (error == -E2BIG)
+- goto out_truncated;
+- return error;
+- }
++ if (unlikely(error))
++ return -EAGAIN;
+ } else
+ zero_nfs_fh3(entry->fh);
+ }
+@@ -2031,11 +2027,6 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+ entry->cookie = new_cookie;
+
+ return 0;
+-
+-out_truncated:
+- dprintk("NFS: directory entry contains invalid file handle\n");
+- *entry = old;
+- return -EAGAIN;
+ }
+
+ /*
+@@ -2227,7 +2218,8 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
/* ignore properties */
result->lease_time = 0;
- result->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA;
+ result->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
++ result->xattr_support = 0;
return 0;
}
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
-index a24349512ffe9..9865b5c37d889 100644
+index a24349512ffe9..93f4d8257525b 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -285,7 +285,9 @@ static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len)
@@ -128725,6 +194527,36 @@ index a24349512ffe9..9865b5c37d889 100644
spin_lock(&inode->i_lock);
if (newsize > i_size_read(inode))
i_size_write(inode, newsize);
+@@ -584,8 +586,10 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
+
+ ctx = get_nfs_open_context(nfs_file_open_context(src));
+ l_ctx = nfs_get_lock_context(ctx);
+- if (IS_ERR(l_ctx))
+- return PTR_ERR(l_ctx);
++ if (IS_ERR(l_ctx)) {
++ status = PTR_ERR(l_ctx);
++ goto out;
++ }
+
+ status = nfs4_set_rw_stateid(&args->cna_src_stateid, ctx, l_ctx,
+ FMODE_READ);
+@@ -593,7 +597,7 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
+ if (status) {
+ if (status == -EAGAIN)
+ status = -NFS4ERR_BAD_STATEID;
+- return status;
++ goto out;
+ }
+
+ status = nfs4_call_sync(src_server->client, src_server, &msg,
+@@ -601,6 +605,7 @@ static int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
+ if (status == -ENOTSUPP)
+ src_server->caps &= ~NFS_CAP_COPY_NOTIFY;
+
++out:
+ put_nfs_open_context(nfs_file_open_context(src));
+ return status;
+ }
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c
index c8bad735e4c19..271e5f92ed019 100644
--- a/fs/nfs/nfs42xdr.c
@@ -128793,6 +194625,38 @@ index af57332503bed..ed06b68b2b4e9 100644
nfs_server_insert_lists(server);
return nfs_probe_destination(server);
+diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
+index c91565227ea2a..4120e1cb3feef 100644
+--- a/fs/nfs/nfs4file.c
++++ b/fs/nfs/nfs4file.c
+@@ -32,6 +32,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
+ struct dentry *parent = NULL;
+ struct inode *dir;
+ unsigned openflags = filp->f_flags;
++ fmode_t f_mode;
+ struct iattr attr;
+ int err;
+
+@@ -50,8 +51,9 @@ nfs4_file_open(struct inode *inode, struct file *filp)
+ if (err)
+ return err;
+
++ f_mode = filp->f_mode;
+ if ((openflags & O_ACCMODE) == 3)
+- return nfs_open(inode, filp);
++ f_mode |= flags_to_mode(openflags);
+
+ /* We can't create new files here */
+ openflags &= ~(O_CREAT|O_EXCL);
+@@ -59,7 +61,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
+ parent = dget_parent(dentry);
+ dir = d_inode(parent);
+
+- ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp);
++ ctx = alloc_nfs_open_context(file_dentry(filp), f_mode, filp);
+ err = PTR_ERR(ctx);
+ if (IS_ERR(ctx))
+ goto out;
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index 8d8aba305ecca..f331866dd4182 100644
--- a/fs/nfs/nfs4idmap.c
@@ -128856,10 +194720,25 @@ index 873342308dc0d..3680c8da510c9 100644
continue;
rpc_set_port(sap, NFS_PORT);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
-index e1214bb6b7ee5..53be03681f69e 100644
+index e1214bb6b7ee5..ae6b3600ed11b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
-@@ -1232,8 +1232,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
+@@ -366,6 +366,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
+ kunmap_atomic(start);
+ }
+
++static void nfs4_fattr_set_prechange(struct nfs_fattr *fattr, u64 version)
++{
++ if (!(fattr->valid & NFS_ATTR_FATTR_PRECHANGE)) {
++ fattr->pre_change_attr = version;
++ fattr->valid |= NFS_ATTR_FATTR_PRECHANGE;
++ }
++}
++
+ static void nfs4_test_and_free_stateid(struct nfs_server *server,
+ nfs4_stateid *stateid,
+ const struct cred *cred)
+@@ -1232,8 +1240,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER |
NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
@@ -128869,7 +194748,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
}
nfsi->attrtimeo_timestamp = jiffies;
-@@ -1609,15 +1608,16 @@ static bool nfs_stateid_is_sequential(struct nfs4_state *state,
+@@ -1609,15 +1616,16 @@ static bool nfs_stateid_is_sequential(struct nfs4_state *state,
{
if (test_bit(NFS_OPEN_STATE, &state->flags)) {
/* The common case - we're updating to a new sequence number */
@@ -128893,7 +194772,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
return false;
}
-@@ -3893,6 +3893,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
+@@ -3893,6 +3901,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
server->caps |= NFS_CAP_SECURITY_LABEL;
#endif
@@ -128902,7 +194781,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE))
-@@ -3949,6 +3951,60 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+@@ -3949,6 +3959,60 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
return err;
}
@@ -128963,7 +194842,18 @@ index e1214bb6b7ee5..53be03681f69e 100644
static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
-@@ -7676,7 +7732,7 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
+@@ -6502,7 +6566,9 @@ static void nfs4_delegreturn_release(void *calldata)
+ pnfs_roc_release(&data->lr.arg, &data->lr.res,
+ data->res.lr_ret);
+ if (inode) {
+- nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
++ nfs4_fattr_set_prechange(&data->fattr,
++ inode_peek_iversion_raw(inode));
++ nfs_refresh_inode(inode, &data->fattr);
+ nfs_iput_and_deactive(inode);
+ }
+ kfree(calldata);
+@@ -7676,7 +7742,7 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
const char *key, const void *buf,
size_t buflen, int flags)
{
@@ -128972,7 +194862,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
int ret;
if (!nfs_server_capable(inode, NFS_CAP_XATTR))
-@@ -7691,8 +7747,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
+@@ -7691,8 +7757,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
* do a cached access check for the XA* flags to possibly avoid
* doing an RPC and getting EACCES back.
*/
@@ -128983,7 +194873,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
return -EACCES;
}
-@@ -7713,14 +7769,14 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
+@@ -7713,14 +7779,14 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen)
{
@@ -129001,7 +194891,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
return -EACCES;
}
-@@ -7745,13 +7801,13 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
+@@ -7745,13 +7811,13 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
ssize_t ret, size;
char *buf;
size_t buflen;
@@ -129018,7 +194908,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
return 0;
}
-@@ -7883,18 +7939,18 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
+@@ -7883,18 +7949,18 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
* appended to this compound to identify the client ID which is
* performing recovery.
*/
@@ -129040,7 +194930,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
.page = page,
.bitmask = bitmask,
.migration = 1, /* skip LOOKUP */
-@@ -7940,17 +7996,17 @@ static int _nfs40_proc_get_locations(struct inode *inode,
+@@ -7940,17 +8006,17 @@ static int _nfs40_proc_get_locations(struct inode *inode,
* When the client supports GETATTR(fs_locations_info), it can
* be plumbed in here.
*/
@@ -129061,7 +194951,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
.page = page,
.bitmask = bitmask,
.migration = 1, /* skip LOOKUP */
-@@ -7999,11 +8055,11 @@ static int _nfs41_proc_get_locations(struct inode *inode,
+@@ -7999,11 +8065,11 @@ static int _nfs41_proc_get_locations(struct inode *inode,
* -NFS4ERR_LEASE_MOVED is returned if the server still has leases
* from this client that require migration recovery.
*/
@@ -129075,7 +194965,7 @@ index e1214bb6b7ee5..53be03681f69e 100644
struct nfs_client *clp = server->nfs_client;
const struct nfs4_mig_recovery_ops *ops =
clp->cl_mvops->mig_recovery_ops;
-@@ -8016,10 +8072,11 @@ int nfs4_proc_get_locations(struct inode *inode,
+@@ -8016,10 +8082,11 @@ int nfs4_proc_get_locations(struct inode *inode,
(unsigned long long)server->fsid.major,
(unsigned long long)server->fsid.minor,
clp->cl_hostname);
@@ -129089,7 +194979,15 @@ index e1214bb6b7ee5..53be03681f69e 100644
if (status != -NFS4ERR_DELAY)
break;
nfs4_handle_exception(server, status, &exception);
-@@ -10513,6 +10570,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
+@@ -8284,6 +8351,7 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
+ case -NFS4ERR_DEADSESSION:
+ nfs4_schedule_session_recovery(clp->cl_session,
+ task->tk_status);
++ return;
+ }
+ if (args->dir == NFS4_CDFC4_FORE_OR_BOTH &&
+ res->dir != NFS4_CDFS4_BOTH) {
+@@ -10513,6 +10581,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.free_client = nfs4_free_client,
.create_server = nfs4_create_server,
.clone_server = nfs_clone_server,
@@ -129098,10 +194996,18 @@ index e1214bb6b7ee5..53be03681f69e 100644
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
-index f22818a80c2c7..51f5cb41e87a4 100644
+index f22818a80c2c7..57ea63e2cdb41 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
-@@ -2097,7 +2097,8 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
+@@ -49,6 +49,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/bitops.h>
+ #include <linux/jiffies.h>
++#include <linux/sched/mm.h>
+
+ #include <linux/sunrpc/clnt.h>
+
+@@ -2097,7 +2098,8 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
}
inode = d_inode(server->super->s_root);
@@ -129111,7 +195017,7 @@ index f22818a80c2c7..51f5cb41e87a4 100644
if (result) {
dprintk("<-- %s: failed to retrieve fs_locations: %d\n",
__func__, result);
-@@ -2105,6 +2106,9 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
+@@ -2105,6 +2107,9 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
}
result = -NFS4ERR_NXIO;
@@ -129121,6 +195027,48 @@ index f22818a80c2c7..51f5cb41e87a4 100644
if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) {
dprintk("<-- %s: No fs_locations data, migration skipped\n",
__func__);
+@@ -2555,9 +2560,17 @@ static void nfs4_layoutreturn_any_run(struct nfs_client *clp)
+
+ static void nfs4_state_manager(struct nfs_client *clp)
+ {
++ unsigned int memflags;
+ int status = 0;
+ const char *section = "", *section_sep = "";
+
++ /*
++ * State recovery can deadlock if the direct reclaim code tries
++ * start NFS writeback. So ensure memory allocations are all
++ * GFP_NOFS.
++ */
++ memflags = memalloc_nofs_save();
++
+ /* Ensure exclusive access to NFSv4 state */
+ do {
+ trace_nfs4_state_mgr(clp);
+@@ -2652,6 +2665,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
+ clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
+ }
+
++ memalloc_nofs_restore(memflags);
+ nfs4_end_drain_session(clp);
+ nfs4_clear_state_manager_bit(clp);
+
+@@ -2669,6 +2683,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
+ return;
+ if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
+ return;
++ memflags = memalloc_nofs_save();
+ } while (refcount_read(&clp->cl_count) > 1 && !signalled());
+ goto out_drain;
+
+@@ -2681,6 +2696,7 @@ out_error:
+ clp->cl_hostname, -status);
+ ssleep(1);
+ out_drain:
++ memalloc_nofs_restore(memflags);
+ nfs4_end_drain_session(clp);
+ nfs4_clear_state_manager_bit(clp);
+ }
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index a8cff19c6f00c..2a1bf0a72d5bf 100644
--- a/fs/nfs/nfs4xdr.c
@@ -129149,11 +195097,86 @@ index a8cff19c6f00c..2a1bf0a72d5bf 100644
return status;
}
+diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
+index cc232d1f16f2f..f2fe23e6c51f4 100644
+--- a/fs/nfs/pagelist.c
++++ b/fs/nfs/pagelist.c
+@@ -90,10 +90,10 @@ void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos)
+ }
+ }
+
+-static inline struct nfs_page *
+-nfs_page_alloc(void)
++static inline struct nfs_page *nfs_page_alloc(void)
+ {
+- struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL);
++ struct nfs_page *p =
++ kmem_cache_zalloc(nfs_page_cachep, nfs_io_gfp_mask());
+ if (p)
+ INIT_LIST_HEAD(&p->wb_list);
+ return p;
+@@ -901,7 +901,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
+ struct nfs_commit_info cinfo;
+ struct nfs_page_array *pg_array = &hdr->page_array;
+ unsigned int pagecount, pageused;
+- gfp_t gfp_flags = GFP_KERNEL;
++ gfp_t gfp_flags = nfs_io_gfp_mask();
+
+ pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
+ pg_array->npages = pagecount;
+@@ -988,7 +988,7 @@ nfs_pageio_alloc_mirrors(struct nfs_pageio_descriptor *desc,
+ desc->pg_mirrors_dynamic = NULL;
+ if (mirror_count == 1)
+ return desc->pg_mirrors_static;
+- ret = kmalloc_array(mirror_count, sizeof(*ret), GFP_KERNEL);
++ ret = kmalloc_array(mirror_count, sizeof(*ret), nfs_io_gfp_mask());
+ if (ret != NULL) {
+ for (i = 0; i < mirror_count; i++)
+ nfs_pageio_mirror_init(&ret[i], desc->pg_bsize);
+@@ -1227,6 +1227,7 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
+
+ do {
+ list_splice_init(&mirror->pg_list, &head);
++ mirror->pg_recoalesce = 0;
+
+ while (!list_empty(&head)) {
+ struct nfs_page *req;
+diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
+index 7c9090a28e5c3..7ddd003ab8b1a 100644
+--- a/fs/nfs/pnfs.c
++++ b/fs/nfs/pnfs.c
+@@ -92,6 +92,17 @@ find_pnfs_driver(u32 id)
+ return local;
+ }
+
++const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id)
++{
++ return find_pnfs_driver(id);
++}
++
++void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld)
++{
++ if (ld)
++ module_put(ld->owner);
++}
++
+ void
+ unset_pnfs_layoutdriver(struct nfs_server *nfss)
+ {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
-index d810ae674f4e8..a0f6ff094b3a4 100644
+index d810ae674f4e8..5a54cf8ac6f3d 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
-@@ -517,7 +517,7 @@ pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
+@@ -238,6 +238,8 @@ struct pnfs_devicelist {
+
+ extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
+ extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
++extern const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id);
++extern void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld);
+
+ /* nfs4proc.c */
+ extern size_t max_response_pages(struct nfs_server *server);
+@@ -517,7 +519,7 @@ pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
{
struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
@@ -129163,9 +195186,18 @@ index d810ae674f4e8..a0f6ff094b3a4 100644
fl_cinfo->ops->mark_request_commit(req, lseg, cinfo, ds_commit_idx);
return true;
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
-index cf19914fec817..316f68f96e573 100644
+index cf19914fec817..657c242a18ff1 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
+@@ -419,7 +419,7 @@ static struct nfs_commit_data *
+ pnfs_bucket_fetch_commitdata(struct pnfs_commit_bucket *bucket,
+ struct nfs_commit_info *cinfo)
+ {
+- struct nfs_commit_data *data = nfs_commitdata_alloc(false);
++ struct nfs_commit_data *data = nfs_commitdata_alloc();
+
+ if (!data)
+ return NULL;
@@ -468,7 +468,6 @@ pnfs_bucket_alloc_ds_commits(struct list_head *list,
goto out_error;
data->ds_commit_index = i;
@@ -129174,7 +195206,16 @@ index cf19914fec817..316f68f96e573 100644
nreq++;
}
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
-@@ -520,7 +519,6 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
+@@ -516,11 +515,14 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
+ unsigned int nreq = 0;
+
+ if (!list_empty(mds_pages)) {
+- data = nfs_commitdata_alloc(true);
++ data = nfs_commitdata_alloc();
++ if (!data) {
++ nfs_retry_commit(mds_pages, NULL, cinfo, -1);
++ return -ENOMEM;
++ }
data->ds_commit_index = -1;
list_splice_init(mds_pages, &data->pages);
list_add_tail(&data->list, &list);
@@ -129182,7 +195223,7 @@ index cf19914fec817..316f68f96e573 100644
nreq++;
}
-@@ -895,7 +893,7 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
+@@ -895,7 +897,7 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
}
smp_wmb();
@@ -129191,7 +195232,7 @@ index cf19914fec817..316f68f96e573 100644
dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
out:
return status;
-@@ -973,7 +971,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
+@@ -973,7 +975,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
}
smp_wmb();
@@ -129201,23 +195242,86 @@ index cf19914fec817..316f68f96e573 100644
out:
return status;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
-index ea19dbf123014..ecc4e717808c4 100644
+index ea19dbf123014..a5b0bdcb53963 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
-@@ -91,7 +91,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+@@ -91,7 +91,8 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
info->dtpref = fsinfo.tsize;
info->maxfilesize = 0x7FFFFFFF;
info->lease_time = 0;
- info->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA;
+ info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
++ info->xattr_support = 0;
return 0;
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
-index eae9bf1140417..7dce3e735fc53 100644
+index eae9bf1140417..d21b255114993 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
-@@ -1038,25 +1038,11 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
+@@ -70,27 +70,17 @@ static mempool_t *nfs_wdata_mempool;
+ static struct kmem_cache *nfs_cdata_cachep;
+ static mempool_t *nfs_commit_mempool;
+
+-struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail)
++struct nfs_commit_data *nfs_commitdata_alloc(void)
+ {
+ struct nfs_commit_data *p;
+
+- if (never_fail)
+- p = mempool_alloc(nfs_commit_mempool, GFP_NOIO);
+- else {
+- /* It is OK to do some reclaim, not no safe to wait
+- * for anything to be returned to the pool.
+- * mempool_alloc() cannot handle that particular combination,
+- * so we need two separate attempts.
+- */
++ p = kmem_cache_zalloc(nfs_cdata_cachep, nfs_io_gfp_mask());
++ if (!p) {
+ p = mempool_alloc(nfs_commit_mempool, GFP_NOWAIT);
+- if (!p)
+- p = kmem_cache_alloc(nfs_cdata_cachep, GFP_NOIO |
+- __GFP_NOWARN | __GFP_NORETRY);
+ if (!p)
+ return NULL;
++ memset(p, 0, sizeof(*p));
+ }
+-
+- memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ return p;
+ }
+@@ -104,9 +94,15 @@ EXPORT_SYMBOL_GPL(nfs_commit_free);
+
+ static struct nfs_pgio_header *nfs_writehdr_alloc(void)
+ {
+- struct nfs_pgio_header *p = mempool_alloc(nfs_wdata_mempool, GFP_KERNEL);
++ struct nfs_pgio_header *p;
+
+- memset(p, 0, sizeof(*p));
++ p = kmem_cache_zalloc(nfs_wdata_cachep, nfs_io_gfp_mask());
++ if (!p) {
++ p = mempool_alloc(nfs_wdata_mempool, GFP_NOWAIT);
++ if (!p)
++ return NULL;
++ memset(p, 0, sizeof(*p));
++ }
+ p->rw_mode = FMODE_WRITE;
+ return p;
+ }
+@@ -314,7 +310,10 @@ static void nfs_mapping_set_error(struct page *page, int error)
+ struct address_space *mapping = page_file_mapping(page);
+
+ SetPageError(page);
+- mapping_set_error(mapping, error);
++ filemap_set_wb_err(mapping, error);
++ if (mapping->host)
++ errseq_set(&mapping->host->i_sb->s_wb_err,
++ error == -ENOSPC ? -ENOSPC : -EIO);
+ nfs_set_pageerror(mapping);
+ }
+
+@@ -1038,25 +1037,11 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
struct nfs_page *req, *tmp;
int ret = 0;
@@ -129244,7 +195348,7 @@ index eae9bf1140417..7dce3e735fc53 100644
}
nfs_request_remove_commit_list(req, cinfo);
clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
-@@ -1671,10 +1657,13 @@ static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
+@@ -1671,10 +1656,13 @@ static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
atomic_inc(&cinfo->rpcs_out);
}
@@ -129260,7 +195364,7 @@ index eae9bf1140417..7dce3e735fc53 100644
}
void nfs_commitdata_release(struct nfs_commit_data *data)
-@@ -1774,6 +1763,7 @@ void nfs_init_commit(struct nfs_commit_data *data,
+@@ -1774,6 +1762,7 @@ void nfs_init_commit(struct nfs_commit_data *data,
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
nfs_fattr_init(&data->fattr);
@@ -129268,7 +195372,16 @@ index eae9bf1140417..7dce3e735fc53 100644
}
EXPORT_SYMBOL_GPL(nfs_init_commit);
-@@ -1820,7 +1810,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
+@@ -1816,11 +1805,14 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
+ if (list_empty(head))
+ return 0;
+
+- data = nfs_commitdata_alloc(true);
++ data = nfs_commitdata_alloc();
++ if (!data) {
++ nfs_retry_commit(head, NULL, cinfo, -1);
++ return -ENOMEM;
++ }
/* Set up the argument struct */
nfs_init_commit(data, head, NULL, cinfo);
@@ -129276,7 +195389,7 @@ index eae9bf1140417..7dce3e735fc53 100644
if (NFS_SERVER(inode)->nfs_client->cl_minorversion)
task_flags = RPC_TASK_MOVEABLE;
return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
-@@ -1936,6 +1925,7 @@ static int __nfs_commit_inode(struct inode *inode, int how,
+@@ -1936,6 +1928,7 @@ static int __nfs_commit_inode(struct inode *inode, int how,
int may_wait = how & FLUSH_SYNC;
int ret, nscan;
@@ -129284,6 +195397,37 @@ index eae9bf1140417..7dce3e735fc53 100644
nfs_init_cinfo_from_inode(&cinfo, inode);
nfs_commit_begin(cinfo.mds);
for (;;) {
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index be3c1aad50ea3..7e23c588f4842 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -641,7 +641,7 @@ nfsd_file_cache_init(void)
+ if (!nfsd_filecache_wq)
+ goto out;
+
+- nfsd_file_hashtbl = kcalloc(NFSD_FILE_HASH_SIZE,
++ nfsd_file_hashtbl = kvcalloc(NFSD_FILE_HASH_SIZE,
+ sizeof(*nfsd_file_hashtbl), GFP_KERNEL);
+ if (!nfsd_file_hashtbl) {
+ pr_err("nfsd: unable to allocate nfsd_file_hashtbl\n");
+@@ -709,7 +709,7 @@ out_err:
+ nfsd_file_slab = NULL;
+ kmem_cache_destroy(nfsd_file_mark_slab);
+ nfsd_file_mark_slab = NULL;
+- kfree(nfsd_file_hashtbl);
++ kvfree(nfsd_file_hashtbl);
+ nfsd_file_hashtbl = NULL;
+ destroy_workqueue(nfsd_filecache_wq);
+ nfsd_filecache_wq = NULL;
+@@ -855,7 +855,7 @@ nfsd_file_cache_shutdown(void)
+ fsnotify_wait_marks_destroyed();
+ kmem_cache_destroy(nfsd_file_mark_slab);
+ nfsd_file_mark_slab = NULL;
+- kfree(nfsd_file_hashtbl);
++ kvfree(nfsd_file_hashtbl);
+ nfsd_file_hashtbl = NULL;
+ destroy_workqueue(nfsd_filecache_wq);
+ nfsd_filecache_wq = NULL;
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 17715a6c7a409..b540489ea240d 100644
--- a/fs/nfsd/nfs3proc.c
@@ -129551,7 +195695,7 @@ index 6fedc49726bf7..c634483d85d2a 100644
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
-index 3f4027a5de883..db4a47a280dc5 100644
+index 3f4027a5de883..181bc3d9f5663 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1207,6 +1207,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
@@ -129596,7 +195740,36 @@ index 3f4027a5de883..db4a47a280dc5 100644
dp->dl_time = ktime_get_boottime_seconds();
list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
}
-@@ -6035,7 +6042,11 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
+@@ -4686,6 +4693,14 @@ nfsd_break_deleg_cb(struct file_lock *fl)
+ return ret;
+ }
+
++/**
++ * nfsd_breaker_owns_lease - Check if lease conflict was resolved
++ * @fl: Lock state to check
++ *
++ * Return values:
++ * %true: Lease conflict was resolved
++ * %false: Lease conflict was not resolved.
++ */
+ static bool nfsd_breaker_owns_lease(struct file_lock *fl)
+ {
+ struct nfs4_delegation *dl = fl->fl_owner;
+@@ -4693,11 +4708,11 @@ static bool nfsd_breaker_owns_lease(struct file_lock *fl)
+ struct nfs4_client *clp;
+
+ if (!i_am_nfsd())
+- return NULL;
++ return false;
+ rqst = kthread_data(current);
+ /* Note rq_prog == NFS_ACL_PROGRAM is also possible: */
+ if (rqst->rq_prog != NFS_PROGRAM || rqst->rq_vers < 4)
+- return NULL;
++ return false;
+ clp = *(rqst->rq_lease_breaker);
+ return dl->dl_stid.sc_client == clp;
+ }
+@@ -6035,7 +6050,11 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
*nfp = NULL;
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
@@ -129728,10 +195901,15 @@ index 070e5dd03e26f..cb73c12925629 100644
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
-index 90fcd6178823b..312fd289be583 100644
+index 90fcd6178823b..9700ad433b498 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
-@@ -234,12 +234,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+@@ -230,16 +230,11 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+ unsigned long cnt = argp->len;
+ unsigned int nvecs;
+
+- dprintk("nfsd: WRITE %s %d bytes at %d\n",
++ dprintk("nfsd: WRITE %s %u bytes at %d\n",
SVCFH_fmt(&argp->fh),
argp->len, argp->offset);
@@ -129882,14 +196060,16 @@ index 738d564ca4ce3..271f7c15d6e52 100644
if (host_err < 0)
nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
-index f45b4bc93f527..80fd6d7f3404a 100644
+index f45b4bc93f527..863a35f24910a 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
-@@ -33,7 +33,7 @@ struct nfsd_writeargs {
+@@ -32,8 +32,8 @@ struct nfsd_readargs {
+ struct nfsd_writeargs {
svc_fh fh;
__u32 offset;
- int len;
+- int len;
- struct kvec first;
++ __u32 len;
+ struct xdr_buf payload;
};
@@ -129907,6 +196087,712 @@ index 933008382bbeb..712c117300cb7 100644
};
struct nfsd3_createargs {
+diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
+index 4391fd3abd8f8..e00e184b12615 100644
+--- a/fs/nilfs2/btnode.c
++++ b/fs/nilfs2/btnode.c
+@@ -20,6 +20,23 @@
+ #include "page.h"
+ #include "btnode.h"
+
++
++/**
++ * nilfs_init_btnc_inode - initialize B-tree node cache inode
++ * @btnc_inode: inode to be initialized
++ *
++ * nilfs_init_btnc_inode() sets up an inode for B-tree node cache.
++ */
++void nilfs_init_btnc_inode(struct inode *btnc_inode)
++{
++ struct nilfs_inode_info *ii = NILFS_I(btnc_inode);
++
++ btnc_inode->i_mode = S_IFREG;
++ ii->i_flags = 0;
++ memset(&ii->i_bmap_data, 0, sizeof(struct nilfs_bmap));
++ mapping_set_gfp_mask(btnc_inode->i_mapping, GFP_NOFS);
++}
++
+ void nilfs_btnode_cache_clear(struct address_space *btnc)
+ {
+ invalidate_mapping_pages(btnc, 0, -1);
+@@ -29,7 +46,7 @@ void nilfs_btnode_cache_clear(struct address_space *btnc)
+ struct buffer_head *
+ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
+ {
+- struct inode *inode = NILFS_BTNC_I(btnc);
++ struct inode *inode = btnc->host;
+ struct buffer_head *bh;
+
+ bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
+@@ -57,7 +74,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
+ struct buffer_head **pbh, sector_t *submit_ptr)
+ {
+ struct buffer_head *bh;
+- struct inode *inode = NILFS_BTNC_I(btnc);
++ struct inode *inode = btnc->host;
+ struct page *page;
+ int err;
+
+@@ -157,7 +174,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
+ struct nilfs_btnode_chkey_ctxt *ctxt)
+ {
+ struct buffer_head *obh, *nbh;
+- struct inode *inode = NILFS_BTNC_I(btnc);
++ struct inode *inode = btnc->host;
+ __u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
+ int err;
+
+diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h
+index 0f88dbc9bcb3e..05ab64d354dc9 100644
+--- a/fs/nilfs2/btnode.h
++++ b/fs/nilfs2/btnode.h
+@@ -30,6 +30,7 @@ struct nilfs_btnode_chkey_ctxt {
+ struct buffer_head *newbh;
+ };
+
++void nilfs_init_btnc_inode(struct inode *btnc_inode);
+ void nilfs_btnode_cache_clear(struct address_space *);
+ struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc,
+ __u64 blocknr);
+diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
+index ab9ec073330f1..2301b57ca17ff 100644
+--- a/fs/nilfs2/btree.c
++++ b/fs/nilfs2/btree.c
+@@ -58,7 +58,8 @@ static void nilfs_btree_free_path(struct nilfs_btree_path *path)
+ static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
+ __u64 ptr, struct buffer_head **bhp)
+ {
+- struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
++ struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
++ struct address_space *btnc = btnc_inode->i_mapping;
+ struct buffer_head *bh;
+
+ bh = nilfs_btnode_create_block(btnc, ptr);
+@@ -470,7 +471,8 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
+ struct buffer_head **bhp,
+ const struct nilfs_btree_readahead_info *ra)
+ {
+- struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
++ struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
++ struct address_space *btnc = btnc_inode->i_mapping;
+ struct buffer_head *bh, *ra_bh;
+ sector_t submit_ptr = 0;
+ int ret;
+@@ -1741,6 +1743,10 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key,
+ dat = nilfs_bmap_get_dat(btree);
+ }
+
++ ret = nilfs_attach_btree_node_cache(&NILFS_BMAP_I(btree)->vfs_inode);
++ if (ret < 0)
++ return ret;
++
+ ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat);
+ if (ret < 0)
+ return ret;
+@@ -1913,7 +1919,7 @@ static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree,
+ path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
+ path[level].bp_ctxt.bh = path[level].bp_bh;
+ ret = nilfs_btnode_prepare_change_key(
+- &NILFS_BMAP_I(btree)->i_btnode_cache,
++ NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
+ &path[level].bp_ctxt);
+ if (ret < 0) {
+ nilfs_dat_abort_update(dat,
+@@ -1939,7 +1945,7 @@ static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree,
+
+ if (buffer_nilfs_node(path[level].bp_bh)) {
+ nilfs_btnode_commit_change_key(
+- &NILFS_BMAP_I(btree)->i_btnode_cache,
++ NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
+ &path[level].bp_ctxt);
+ path[level].bp_bh = path[level].bp_ctxt.bh;
+ }
+@@ -1958,7 +1964,7 @@ static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree,
+ &path[level].bp_newreq.bpr_req);
+ if (buffer_nilfs_node(path[level].bp_bh))
+ nilfs_btnode_abort_change_key(
+- &NILFS_BMAP_I(btree)->i_btnode_cache,
++ NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
+ &path[level].bp_ctxt);
+ }
+
+@@ -2134,7 +2140,8 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree,
+ static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree,
+ struct list_head *listp)
+ {
+- struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache;
++ struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
++ struct address_space *btcache = btnc_inode->i_mapping;
+ struct list_head lists[NILFS_BTREE_LEVEL_MAX];
+ struct pagevec pvec;
+ struct buffer_head *bh, *head;
+@@ -2188,12 +2195,12 @@ static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
+ path[level].bp_ctxt.newkey = blocknr;
+ path[level].bp_ctxt.bh = *bh;
+ ret = nilfs_btnode_prepare_change_key(
+- &NILFS_BMAP_I(btree)->i_btnode_cache,
++ NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
+ &path[level].bp_ctxt);
+ if (ret < 0)
+ return ret;
+ nilfs_btnode_commit_change_key(
+- &NILFS_BMAP_I(btree)->i_btnode_cache,
++ NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
+ &path[level].bp_ctxt);
+ *bh = path[level].bp_ctxt.bh;
+ }
+@@ -2398,6 +2405,10 @@ int nilfs_btree_init(struct nilfs_bmap *bmap)
+
+ if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), bmap->b_inode))
+ ret = -EIO;
++ else
++ ret = nilfs_attach_btree_node_cache(
++ &NILFS_BMAP_I(bmap)->vfs_inode);
++
+ return ret;
+ }
+
+diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
+index 8bccdf1158fce..1a3d183027b9e 100644
+--- a/fs/nilfs2/dat.c
++++ b/fs/nilfs2/dat.c
+@@ -497,7 +497,9 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
+ di = NILFS_DAT_I(dat);
+ lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
+ nilfs_palloc_setup_cache(dat, &di->palloc_cache);
+- nilfs_mdt_setup_shadow_map(dat, &di->shadow);
++ err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
++ if (err)
++ goto failed;
+
+ err = nilfs_read_inode_common(dat, raw_inode);
+ if (err)
+diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
+index 4483204968568..aadea660c66c9 100644
+--- a/fs/nilfs2/gcinode.c
++++ b/fs/nilfs2/gcinode.c
+@@ -126,9 +126,10 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff,
+ int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn,
+ __u64 vbn, struct buffer_head **out_bh)
+ {
++ struct inode *btnc_inode = NILFS_I(inode)->i_assoc_inode;
+ int ret;
+
+- ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache,
++ ret = nilfs_btnode_submit_block(btnc_inode->i_mapping,
+ vbn ? : pbn, pbn, REQ_OP_READ, 0,
+ out_bh, &pbn);
+ if (ret == -EEXIST) /* internal code (cache hit) */
+@@ -170,7 +171,7 @@ int nilfs_init_gcinode(struct inode *inode)
+ ii->i_flags = 0;
+ nilfs_bmap_init_gc(ii->i_bmap);
+
+- return 0;
++ return nilfs_attach_btree_node_cache(inode);
+ }
+
+ /**
+@@ -185,7 +186,7 @@ void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)
+ ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
+ list_del_init(&ii->i_dirty);
+ truncate_inode_pages(&ii->vfs_inode.i_data, 0);
+- nilfs_btnode_cache_clear(&ii->i_btnode_cache);
++ nilfs_btnode_cache_clear(ii->i_assoc_inode->i_mapping);
+ iput(&ii->vfs_inode);
+ }
+ }
+diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
+index 2e8eb263cf0f6..2466f8b8be95c 100644
+--- a/fs/nilfs2/inode.c
++++ b/fs/nilfs2/inode.c
+@@ -29,12 +29,16 @@
+ * @cno: checkpoint number
+ * @root: pointer on NILFS root object (mounted checkpoint)
+ * @for_gc: inode for GC flag
++ * @for_btnc: inode for B-tree node cache flag
++ * @for_shadow: inode for shadowed page cache flag
+ */
+ struct nilfs_iget_args {
+ u64 ino;
+ __u64 cno;
+ struct nilfs_root *root;
+- int for_gc;
++ bool for_gc;
++ bool for_btnc;
++ bool for_shadow;
+ };
+
+ static int nilfs_iget_test(struct inode *inode, void *opaque);
+@@ -314,7 +318,8 @@ static int nilfs_insert_inode_locked(struct inode *inode,
+ unsigned long ino)
+ {
+ struct nilfs_iget_args args = {
+- .ino = ino, .root = root, .cno = 0, .for_gc = 0
++ .ino = ino, .root = root, .cno = 0, .for_gc = false,
++ .for_btnc = false, .for_shadow = false
+ };
+
+ return insert_inode_locked4(inode, ino, nilfs_iget_test, &args);
+@@ -527,6 +532,19 @@ static int nilfs_iget_test(struct inode *inode, void *opaque)
+ return 0;
+
+ ii = NILFS_I(inode);
++ if (test_bit(NILFS_I_BTNC, &ii->i_state)) {
++ if (!args->for_btnc)
++ return 0;
++ } else if (args->for_btnc) {
++ return 0;
++ }
++ if (test_bit(NILFS_I_SHADOW, &ii->i_state)) {
++ if (!args->for_shadow)
++ return 0;
++ } else if (args->for_shadow) {
++ return 0;
++ }
++
+ if (!test_bit(NILFS_I_GCINODE, &ii->i_state))
+ return !args->for_gc;
+
+@@ -538,15 +556,17 @@ static int nilfs_iget_set(struct inode *inode, void *opaque)
+ struct nilfs_iget_args *args = opaque;
+
+ inode->i_ino = args->ino;
+- if (args->for_gc) {
++ NILFS_I(inode)->i_cno = args->cno;
++ NILFS_I(inode)->i_root = args->root;
++ if (args->root && args->ino == NILFS_ROOT_INO)
++ nilfs_get_root(args->root);
++
++ if (args->for_gc)
+ NILFS_I(inode)->i_state = BIT(NILFS_I_GCINODE);
+- NILFS_I(inode)->i_cno = args->cno;
+- NILFS_I(inode)->i_root = NULL;
+- } else {
+- if (args->root && args->ino == NILFS_ROOT_INO)
+- nilfs_get_root(args->root);
+- NILFS_I(inode)->i_root = args->root;
+- }
++ if (args->for_btnc)
++ NILFS_I(inode)->i_state |= BIT(NILFS_I_BTNC);
++ if (args->for_shadow)
++ NILFS_I(inode)->i_state |= BIT(NILFS_I_SHADOW);
+ return 0;
+ }
+
+@@ -554,7 +574,8 @@ struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
+ unsigned long ino)
+ {
+ struct nilfs_iget_args args = {
+- .ino = ino, .root = root, .cno = 0, .for_gc = 0
++ .ino = ino, .root = root, .cno = 0, .for_gc = false,
++ .for_btnc = false, .for_shadow = false
+ };
+
+ return ilookup5(sb, ino, nilfs_iget_test, &args);
+@@ -564,7 +585,8 @@ struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
+ unsigned long ino)
+ {
+ struct nilfs_iget_args args = {
+- .ino = ino, .root = root, .cno = 0, .for_gc = 0
++ .ino = ino, .root = root, .cno = 0, .for_gc = false,
++ .for_btnc = false, .for_shadow = false
+ };
+
+ return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
+@@ -595,7 +617,8 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino,
+ __u64 cno)
+ {
+ struct nilfs_iget_args args = {
+- .ino = ino, .root = NULL, .cno = cno, .for_gc = 1
++ .ino = ino, .root = NULL, .cno = cno, .for_gc = true,
++ .for_btnc = false, .for_shadow = false
+ };
+ struct inode *inode;
+ int err;
+@@ -615,6 +638,113 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino,
+ return inode;
+ }
+
++/**
++ * nilfs_attach_btree_node_cache - attach a B-tree node cache to the inode
++ * @inode: inode object
++ *
++ * nilfs_attach_btree_node_cache() attaches a B-tree node cache to @inode,
++ * or does nothing if the inode already has it. This function allocates
++ * an additional inode to maintain page cache of B-tree nodes one-on-one.
++ *
++ * Return Value: On success, 0 is returned. On errors, one of the following
++ * negative error code is returned.
++ *
++ * %-ENOMEM - Insufficient memory available.
++ */
++int nilfs_attach_btree_node_cache(struct inode *inode)
++{
++ struct nilfs_inode_info *ii = NILFS_I(inode);
++ struct inode *btnc_inode;
++ struct nilfs_iget_args args;
++
++ if (ii->i_assoc_inode)
++ return 0;
++
++ args.ino = inode->i_ino;
++ args.root = ii->i_root;
++ args.cno = ii->i_cno;
++ args.for_gc = test_bit(NILFS_I_GCINODE, &ii->i_state) != 0;
++ args.for_btnc = true;
++ args.for_shadow = test_bit(NILFS_I_SHADOW, &ii->i_state) != 0;
++
++ btnc_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
++ nilfs_iget_set, &args);
++ if (unlikely(!btnc_inode))
++ return -ENOMEM;
++ if (btnc_inode->i_state & I_NEW) {
++ nilfs_init_btnc_inode(btnc_inode);
++ unlock_new_inode(btnc_inode);
++ }
++ NILFS_I(btnc_inode)->i_assoc_inode = inode;
++ NILFS_I(btnc_inode)->i_bmap = ii->i_bmap;
++ ii->i_assoc_inode = btnc_inode;
++
++ return 0;
++}
++
++/**
++ * nilfs_detach_btree_node_cache - detach the B-tree node cache from the inode
++ * @inode: inode object
++ *
++ * nilfs_detach_btree_node_cache() detaches the B-tree node cache and its
++ * holder inode bound to @inode, or does nothing if @inode doesn't have it.
++ */
++void nilfs_detach_btree_node_cache(struct inode *inode)
++{
++ struct nilfs_inode_info *ii = NILFS_I(inode);
++ struct inode *btnc_inode = ii->i_assoc_inode;
++
++ if (btnc_inode) {
++ NILFS_I(btnc_inode)->i_assoc_inode = NULL;
++ ii->i_assoc_inode = NULL;
++ iput(btnc_inode);
++ }
++}
++
++/**
++ * nilfs_iget_for_shadow - obtain inode for shadow mapping
++ * @inode: inode object that uses shadow mapping
++ *
++ * nilfs_iget_for_shadow() allocates a pair of inodes that holds page
++ * caches for shadow mapping. The page cache for data pages is set up
++ * in one inode and the one for b-tree node pages is set up in the
++ * other inode, which is attached to the former inode.
++ *
++ * Return Value: On success, a pointer to the inode for data pages is
++ * returned. On errors, one of the following negative error code is returned
++ * in a pointer type.
++ *
++ * %-ENOMEM - Insufficient memory available.
++ */
++struct inode *nilfs_iget_for_shadow(struct inode *inode)
++{
++ struct nilfs_iget_args args = {
++ .ino = inode->i_ino, .root = NULL, .cno = 0, .for_gc = false,
++ .for_btnc = false, .for_shadow = true
++ };
++ struct inode *s_inode;
++ int err;
++
++ s_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
++ nilfs_iget_set, &args);
++ if (unlikely(!s_inode))
++ return ERR_PTR(-ENOMEM);
++ if (!(s_inode->i_state & I_NEW))
++ return inode;
++
++ NILFS_I(s_inode)->i_flags = 0;
++ memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap));
++ mapping_set_gfp_mask(s_inode->i_mapping, GFP_NOFS);
++
++ err = nilfs_attach_btree_node_cache(s_inode);
++ if (unlikely(err)) {
++ iget_failed(s_inode);
++ return ERR_PTR(err);
++ }
++ unlock_new_inode(s_inode);
++ return s_inode;
++}
++
+ void nilfs_write_inode_common(struct inode *inode,
+ struct nilfs_inode *raw_inode, int has_bmap)
+ {
+@@ -762,7 +892,8 @@ static void nilfs_clear_inode(struct inode *inode)
+ if (test_bit(NILFS_I_BMAP, &ii->i_state))
+ nilfs_bmap_clear(ii->i_bmap);
+
+- nilfs_btnode_cache_clear(&ii->i_btnode_cache);
++ if (!test_bit(NILFS_I_BTNC, &ii->i_state))
++ nilfs_detach_btree_node_cache(inode);
+
+ if (ii->i_root && inode->i_ino == NILFS_ROOT_INO)
+ nilfs_put_root(ii->i_root);
+diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
+index 97769fe4d5885..131b5add32eeb 100644
+--- a/fs/nilfs2/mdt.c
++++ b/fs/nilfs2/mdt.c
+@@ -470,9 +470,18 @@ int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz)
+ void nilfs_mdt_clear(struct inode *inode)
+ {
+ struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
++ struct nilfs_shadow_map *shadow = mdi->mi_shadow;
+
+ if (mdi->mi_palloc_cache)
+ nilfs_palloc_destroy_cache(inode);
++
++ if (shadow) {
++ struct inode *s_inode = shadow->inode;
++
++ shadow->inode = NULL;
++ iput(s_inode);
++ mdi->mi_shadow = NULL;
++ }
+ }
+
+ /**
+@@ -506,12 +515,15 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode,
+ struct nilfs_shadow_map *shadow)
+ {
+ struct nilfs_mdt_info *mi = NILFS_MDT(inode);
++ struct inode *s_inode;
+
+ INIT_LIST_HEAD(&shadow->frozen_buffers);
+- address_space_init_once(&shadow->frozen_data);
+- nilfs_mapping_init(&shadow->frozen_data, inode);
+- address_space_init_once(&shadow->frozen_btnodes);
+- nilfs_mapping_init(&shadow->frozen_btnodes, inode);
++
++ s_inode = nilfs_iget_for_shadow(inode);
++ if (IS_ERR(s_inode))
++ return PTR_ERR(s_inode);
++
++ shadow->inode = s_inode;
+ mi->mi_shadow = shadow;
+ return 0;
+ }
+@@ -525,14 +537,15 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode)
+ struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+ struct nilfs_inode_info *ii = NILFS_I(inode);
+ struct nilfs_shadow_map *shadow = mi->mi_shadow;
++ struct inode *s_inode = shadow->inode;
+ int ret;
+
+- ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping);
++ ret = nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping);
+ if (ret)
+ goto out;
+
+- ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes,
+- &ii->i_btnode_cache);
++ ret = nilfs_copy_dirty_pages(NILFS_I(s_inode)->i_assoc_inode->i_mapping,
++ ii->i_assoc_inode->i_mapping);
+ if (ret)
+ goto out;
+
+@@ -548,7 +561,7 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
+ struct page *page;
+ int blkbits = inode->i_blkbits;
+
+- page = grab_cache_page(&shadow->frozen_data, bh->b_page->index);
++ page = grab_cache_page(shadow->inode->i_mapping, bh->b_page->index);
+ if (!page)
+ return -ENOMEM;
+
+@@ -580,7 +593,7 @@ nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh)
+ struct page *page;
+ int n;
+
+- page = find_lock_page(&shadow->frozen_data, bh->b_page->index);
++ page = find_lock_page(shadow->inode->i_mapping, bh->b_page->index);
+ if (page) {
+ if (page_has_buffers(page)) {
+ n = bh_offset(bh) >> inode->i_blkbits;
+@@ -621,10 +634,11 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
+ nilfs_palloc_clear_cache(inode);
+
+ nilfs_clear_dirty_pages(inode->i_mapping, true);
+- nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data);
++ nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);
+
+- nilfs_clear_dirty_pages(&ii->i_btnode_cache, true);
+- nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes);
++ nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true);
++ nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,
++ NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);
+
+ nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);
+
+@@ -639,10 +653,11 @@ void nilfs_mdt_clear_shadow_map(struct inode *inode)
+ {
+ struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+ struct nilfs_shadow_map *shadow = mi->mi_shadow;
++ struct inode *shadow_btnc_inode = NILFS_I(shadow->inode)->i_assoc_inode;
+
+ down_write(&mi->mi_sem);
+ nilfs_release_frozen_buffers(shadow);
+- truncate_inode_pages(&shadow->frozen_data, 0);
+- truncate_inode_pages(&shadow->frozen_btnodes, 0);
++ truncate_inode_pages(shadow->inode->i_mapping, 0);
++ truncate_inode_pages(shadow_btnc_inode->i_mapping, 0);
+ up_write(&mi->mi_sem);
+ }
+diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h
+index e77aea4bb921c..9d8ac0d27c16e 100644
+--- a/fs/nilfs2/mdt.h
++++ b/fs/nilfs2/mdt.h
+@@ -18,14 +18,12 @@
+ /**
+ * struct nilfs_shadow_map - shadow mapping of meta data file
+ * @bmap_store: shadow copy of bmap state
+- * @frozen_data: shadowed dirty data pages
+- * @frozen_btnodes: shadowed dirty b-tree nodes' pages
++ * @inode: holder of page caches used in shadow mapping
+ * @frozen_buffers: list of frozen buffers
+ */
+ struct nilfs_shadow_map {
+ struct nilfs_bmap_store bmap_store;
+- struct address_space frozen_data;
+- struct address_space frozen_btnodes;
++ struct inode *inode;
+ struct list_head frozen_buffers;
+ };
+
+diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
+index 60b21b6eeac06..7dcb77d387593 100644
+--- a/fs/nilfs2/nilfs.h
++++ b/fs/nilfs2/nilfs.h
+@@ -28,7 +28,7 @@
+ * @i_xattr: <TODO>
+ * @i_dir_start_lookup: page index of last successful search
+ * @i_cno: checkpoint number for GC inode
+- * @i_btnode_cache: cached pages of b-tree nodes
++ * @i_assoc_inode: associated inode (B-tree node cache holder or back pointer)
+ * @i_dirty: list for connecting dirty files
+ * @xattr_sem: semaphore for extended attributes processing
+ * @i_bh: buffer contains disk inode
+@@ -43,7 +43,7 @@ struct nilfs_inode_info {
+ __u64 i_xattr; /* sector_t ??? */
+ __u32 i_dir_start_lookup;
+ __u64 i_cno; /* check point number for GC inode */
+- struct address_space i_btnode_cache;
++ struct inode *i_assoc_inode;
+ struct list_head i_dirty; /* List for connecting dirty files */
+
+ #ifdef CONFIG_NILFS_XATTR
+@@ -75,13 +75,6 @@ NILFS_BMAP_I(const struct nilfs_bmap *bmap)
+ return container_of(bmap, struct nilfs_inode_info, i_bmap_data);
+ }
+
+-static inline struct inode *NILFS_BTNC_I(struct address_space *btnc)
+-{
+- struct nilfs_inode_info *ii =
+- container_of(btnc, struct nilfs_inode_info, i_btnode_cache);
+- return &ii->vfs_inode;
+-}
+-
+ /*
+ * Dynamic state flags of NILFS on-memory inode (i_state)
+ */
+@@ -98,6 +91,8 @@ enum {
+ NILFS_I_INODE_SYNC, /* dsync is not allowed for inode */
+ NILFS_I_BMAP, /* has bmap and btnode_cache */
+ NILFS_I_GCINODE, /* inode for GC, on memory only */
++ NILFS_I_BTNC, /* inode for btree node cache */
++ NILFS_I_SHADOW, /* inode for shadowed page cache */
+ };
+
+ /*
+@@ -267,6 +262,9 @@ struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
+ unsigned long ino);
+ extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
+ unsigned long ino, __u64 cno);
++int nilfs_attach_btree_node_cache(struct inode *inode);
++void nilfs_detach_btree_node_cache(struct inode *inode);
++struct inode *nilfs_iget_for_shadow(struct inode *inode);
+ extern void nilfs_update_inode(struct inode *, struct buffer_head *, int);
+ extern void nilfs_truncate(struct inode *);
+ extern void nilfs_evict_inode(struct inode *);
+diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
+index 171fb5cd427fd..d1a148f0cae33 100644
+--- a/fs/nilfs2/page.c
++++ b/fs/nilfs2/page.c
+@@ -448,10 +448,9 @@ void nilfs_mapping_init(struct address_space *mapping, struct inode *inode)
+ /*
+ * NILFS2 needs clear_page_dirty() in the following two cases:
+ *
+- * 1) For B-tree node pages and data pages of the dat/gcdat, NILFS2 clears
+- * page dirty flags when it copies back pages from the shadow cache
+- * (gcdat->{i_mapping,i_btnode_cache}) to its original cache
+- * (dat->{i_mapping,i_btnode_cache}).
++ * 1) For B-tree node pages and data pages of DAT file, NILFS2 clears dirty
++ * flag of pages when it copies back pages from shadow cache to the
++ * original cache.
+ *
+ * 2) Some B-tree operations like insertion or deletion may dispose buffers
+ * in dirty state, and this needs to cancel the dirty state of their pages.
+diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
+index 686c8ee7b29ce..314a23a166893 100644
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -733,15 +733,18 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,
+ struct list_head *listp)
+ {
+ struct nilfs_inode_info *ii = NILFS_I(inode);
+- struct address_space *mapping = &ii->i_btnode_cache;
++ struct inode *btnc_inode = ii->i_assoc_inode;
+ struct pagevec pvec;
+ struct buffer_head *bh, *head;
+ unsigned int i;
+ pgoff_t index = 0;
+
++ if (!btnc_inode)
++ return;
++
+ pagevec_init(&pvec);
+
+- while (pagevec_lookup_tag(&pvec, mapping, &index,
++ while (pagevec_lookup_tag(&pvec, btnc_inode->i_mapping, &index,
+ PAGECACHE_TAG_DIRTY)) {
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ bh = head = page_buffers(pvec.pages[i]);
+@@ -2410,7 +2413,7 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
+ continue;
+ list_del_init(&ii->i_dirty);
+ truncate_inode_pages(&ii->vfs_inode.i_data, 0);
+- nilfs_btnode_cache_clear(&ii->i_btnode_cache);
++ nilfs_btnode_cache_clear(ii->i_assoc_inode->i_mapping);
+ iput(&ii->vfs_inode);
+ }
+ }
+diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
+index f6b2d280aab5a..2883ab625f61f 100644
+--- a/fs/nilfs2/super.c
++++ b/fs/nilfs2/super.c
+@@ -157,7 +157,8 @@ struct inode *nilfs_alloc_inode(struct super_block *sb)
+ ii->i_bh = NULL;
+ ii->i_state = 0;
+ ii->i_cno = 0;
+- nilfs_mapping_init(&ii->i_btnode_cache, &ii->vfs_inode);
++ ii->i_assoc_inode = NULL;
++ ii->i_bmap = &ii->i_bmap_data;
+ return &ii->vfs_inode;
+ }
+
+@@ -1377,8 +1378,6 @@ static void nilfs_inode_init_once(void *obj)
+ #ifdef CONFIG_NILFS_XATTR
+ init_rwsem(&ii->xattr_sem);
+ #endif
+- address_space_init_once(&ii->i_btnode_cache);
+- ii->i_bmap = &ii->i_bmap_data;
+ inode_init_once(&ii->vfs_inode);
+ }
+
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 6facdf476255d..84ec851211d91 100644
--- a/fs/notify/fanotify/fanotify_user.c
@@ -129931,6 +196817,47 @@ index 6facdf476255d..84ec851211d91 100644
return metadata.event_len;
out_close_fd:
+diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
+index ab4f3362466d0..a43adeacd930c 100644
+--- a/fs/ntfs/file.c
++++ b/fs/ntfs/file.c
+@@ -1829,7 +1829,7 @@ again:
+ * pages being swapped out between us bringing them into memory
+ * and doing the actual copying.
+ */
+- if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
++ if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
+ status = -EFAULT;
+ break;
+ }
+diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
+index 4474adb393ca8..517b71c73aa96 100644
+--- a/fs/ntfs/inode.c
++++ b/fs/ntfs/inode.c
+@@ -1881,6 +1881,10 @@ int ntfs_read_inode_mount(struct inode *vi)
+ }
+ /* Now allocate memory for the attribute list. */
+ ni->attr_list_size = (u32)ntfs_attr_size(a);
++ if (!ni->attr_list_size) {
++ ntfs_error(sb, "Attr_list_size is zero");
++ goto put_err_out;
++ }
+ ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);
+ if (!ni->attr_list) {
+ ntfs_error(sb, "Not enough memory to allocate buffer "
+diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
+index 43b1451bff539..54b9599640ef4 100644
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -989,7 +989,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
+ frame_vbo = pos & ~(frame_size - 1);
+ index = frame_vbo >> PAGE_SHIFT;
+
+- if (unlikely(iov_iter_fault_in_readable(from, bytes))) {
++ if (unlikely(fault_in_iov_iter_readable(from, bytes))) {
+ err = -EFAULT;
+ goto out;
+ }
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 54d7843c02114..fc5f780fa2355 100644
--- a/fs/ocfs2/file.c
@@ -129959,6 +196886,73 @@ index 54d7843c02114..fc5f780fa2355 100644
status = ocfs2_commit_truncate(osb, inode, di_bh);
if (status < 0) {
mlog_errno(status);
+diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
+index f033de733adb3..effe92c7d6937 100644
+--- a/fs/ocfs2/quota_global.c
++++ b/fs/ocfs2/quota_global.c
+@@ -337,7 +337,6 @@ void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
+ /* Read information header from global quota file */
+ int ocfs2_global_read_info(struct super_block *sb, int type)
+ {
+- struct inode *gqinode = NULL;
+ unsigned int ino[OCFS2_MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
+ GROUP_QUOTA_SYSTEM_INODE };
+ struct ocfs2_global_disk_dqinfo dinfo;
+@@ -346,29 +345,31 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
+ u64 pcount;
+ int status;
+
++ oinfo->dqi_gi.dqi_sb = sb;
++ oinfo->dqi_gi.dqi_type = type;
++ ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
++ oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
++ oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
++ oinfo->dqi_gqi_bh = NULL;
++ oinfo->dqi_gqi_count = 0;
++
+ /* Read global header */
+- gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
++ oinfo->dqi_gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
+ OCFS2_INVALID_SLOT);
+- if (!gqinode) {
++ if (!oinfo->dqi_gqinode) {
+ mlog(ML_ERROR, "failed to get global quota inode (type=%d)\n",
+ type);
+ status = -EINVAL;
+ goto out_err;
+ }
+- oinfo->dqi_gi.dqi_sb = sb;
+- oinfo->dqi_gi.dqi_type = type;
+- oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
+- oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
+- oinfo->dqi_gqi_bh = NULL;
+- oinfo->dqi_gqi_count = 0;
+- oinfo->dqi_gqinode = gqinode;
++
+ status = ocfs2_lock_global_qf(oinfo, 0);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_err;
+ }
+
+- status = ocfs2_extent_map_get_blocks(gqinode, 0, &oinfo->dqi_giblk,
++ status = ocfs2_extent_map_get_blocks(oinfo->dqi_gqinode, 0, &oinfo->dqi_giblk,
+ &pcount, NULL);
+ if (status < 0)
+ goto out_unlock;
+diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
+index 0e4b16d4c037f..b1a8b046f4c22 100644
+--- a/fs/ocfs2/quota_local.c
++++ b/fs/ocfs2/quota_local.c
+@@ -702,8 +702,6 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
+ info->dqi_priv = oinfo;
+ oinfo->dqi_type = type;
+ INIT_LIST_HEAD(&oinfo->dqi_chunk);
+- oinfo->dqi_gqinode = NULL;
+- ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
+ oinfo->dqi_rec = NULL;
+ oinfo->dqi_lqi_bh = NULL;
+ oinfo->dqi_libh = NULL;
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 481017e1dac5a..166c8918c825a 100644
--- a/fs/ocfs2/suballoc.c
@@ -130001,6 +196995,46 @@ index 481017e1dac5a..166c8918c825a 100644
return ret;
}
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index 5c914ce9b3ac9..7ba3dabe16f09 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -1106,17 +1106,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ goto read_super_error;
+ }
+
+- root = d_make_root(inode);
+- if (!root) {
+- status = -ENOMEM;
+- mlog_errno(status);
+- goto read_super_error;
+- }
+-
+- sb->s_root = root;
+-
+- ocfs2_complete_mount_recovery(osb);
+-
+ osb->osb_dev_kset = kset_create_and_add(sb->s_id, NULL,
+ &ocfs2_kset->kobj);
+ if (!osb->osb_dev_kset) {
+@@ -1134,6 +1123,17 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ goto read_super_error;
+ }
+
++ root = d_make_root(inode);
++ if (!root) {
++ status = -ENOMEM;
++ mlog_errno(status);
++ goto read_super_error;
++ }
++
++ sb->s_root = root;
++
++ ocfs2_complete_mount_recovery(osb);
++
+ if (ocfs2_mount_local(osb))
+ snprintf(nodestr, sizeof(nodestr), "local");
+ else
diff --git a/fs/open.c b/fs/open.c
index daa324606a41f..e0df1536eb69f 100644
--- a/fs/open.c
@@ -130255,6 +197289,43 @@ index 178daa5e82c9d..265181c110ae2 100644
/*
* Try to remove POSIX ACL xattrs from workdir. We are good if:
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 6d4342bad9f15..751d5b36c84bb 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -252,7 +252,8 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
+ */
+ was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
+ for (;;) {
+- unsigned int head = pipe->head;
++ /* Read ->head with a barrier vs post_one_notification() */
++ unsigned int head = smp_load_acquire(&pipe->head);
+ unsigned int tail = pipe->tail;
+ unsigned int mask = pipe->ring_size - 1;
+
+@@ -830,10 +831,8 @@ void free_pipe_info(struct pipe_inode_info *pipe)
+ int i;
+
+ #ifdef CONFIG_WATCH_QUEUE
+- if (pipe->watch_queue) {
++ if (pipe->watch_queue)
+ watch_queue_clear(pipe->watch_queue);
+- put_watch_queue(pipe->watch_queue);
+- }
+ #endif
+
+ (void) account_pipe_buffers(pipe->user, pipe->nr_accounted, 0);
+@@ -843,6 +842,10 @@ void free_pipe_info(struct pipe_inode_info *pipe)
+ if (buf->ops)
+ pipe_buf_release(pipe, buf);
+ }
++#ifdef CONFIG_WATCH_QUEUE
++ if (pipe->watch_queue)
++ put_watch_queue(pipe->watch_queue);
++#endif
+ if (pipe->tmp_page)
+ __free_page(pipe->tmp_page);
+ kfree(pipe->bufs);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 533d5836eb9a4..1f394095eb880 100644
--- a/fs/proc/base.c
@@ -130295,6 +197366,73 @@ index 533d5836eb9a4..1f394095eb880 100644
return 0;
}
#endif /* CONFIG_KALLSYMS */
+diff --git a/fs/proc/bootconfig.c b/fs/proc/bootconfig.c
+index 6d8d4bf208377..2e244ada1f970 100644
+--- a/fs/proc/bootconfig.c
++++ b/fs/proc/bootconfig.c
+@@ -32,6 +32,8 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size)
+ int ret = 0;
+
+ key = kzalloc(XBC_KEYLEN_MAX, GFP_KERNEL);
++ if (!key)
++ return -ENOMEM;
+
+ xbc_for_each_key_value(leaf, val) {
+ ret = xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX);
+diff --git a/fs/proc/fd.c b/fs/proc/fd.c
+index 172c86270b312..913bef0d2a36c 100644
+--- a/fs/proc/fd.c
++++ b/fs/proc/fd.c
+@@ -72,7 +72,7 @@ out:
+ return 0;
+ }
+
+-static int seq_fdinfo_open(struct inode *inode, struct file *file)
++static int proc_fdinfo_access_allowed(struct inode *inode)
+ {
+ bool allowed = false;
+ struct task_struct *task = get_proc_task(inode);
+@@ -86,6 +86,16 @@ static int seq_fdinfo_open(struct inode *inode, struct file *file)
+ if (!allowed)
+ return -EACCES;
+
++ return 0;
++}
++
++static int seq_fdinfo_open(struct inode *inode, struct file *file)
++{
++ int ret = proc_fdinfo_access_allowed(inode);
++
++ if (ret)
++ return ret;
++
+ return single_open(file, seq_show, inode);
+ }
+
+@@ -348,12 +358,23 @@ static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
+ proc_fdinfo_instantiate);
+ }
+
++static int proc_open_fdinfo(struct inode *inode, struct file *file)
++{
++ int ret = proc_fdinfo_access_allowed(inode);
++
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
+ const struct inode_operations proc_fdinfo_inode_operations = {
+ .lookup = proc_lookupfdinfo,
+ .setattr = proc_setattr,
+ };
+
+ const struct file_operations proc_fdinfo_operations = {
++ .open = proc_open_fdinfo,
+ .read = generic_read_dir,
+ .iterate_shared = proc_readfdinfo,
+ .llseek = generic_file_llseek,
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index 6561a06ef9059..4fb8729a68d4e 100644
--- a/fs/proc/stat.c
@@ -130561,6 +197699,89 @@ index 04ce58c939a0b..6093088de49fd 100644
blkdev, best_effort_dev->zone.total_size);
return ret;
+diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
+index b9614db48b1de..ad96ba97d8f97 100644
+--- a/fs/pstore/platform.c
++++ b/fs/pstore/platform.c
+@@ -143,21 +143,22 @@ static void pstore_timer_kick(void)
+ mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));
+ }
+
+-/*
+- * Should pstore_dump() wait for a concurrent pstore_dump()? If
+- * not, the current pstore_dump() will report a failure to dump
+- * and return.
+- */
+-static bool pstore_cannot_wait(enum kmsg_dump_reason reason)
++static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+ {
+- /* In NMI path, pstore shouldn't block regardless of reason. */
++ /*
++ * In case of NMI path, pstore shouldn't be blocked
++ * regardless of reason.
++ */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+- /* Emergency restart shouldn't be blocked. */
++ /*
++ * Emergency restart shouldn't be blocked by spinning on
++ * pstore_info::buf_lock.
++ */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+@@ -389,21 +390,19 @@ static void pstore_dump(struct kmsg_dumper *dumper,
+ unsigned long total = 0;
+ const char *why;
+ unsigned int part = 1;
++ unsigned long flags = 0;
+ int ret;
+
+ why = kmsg_dump_reason_str(reason);
+
+- if (down_trylock(&psinfo->buf_lock)) {
+- /* Failed to acquire lock: give up if we cannot wait. */
+- if (pstore_cannot_wait(reason)) {
+- pr_err("dump skipped in %s path: may corrupt error record\n",
+- in_nmi() ? "NMI" : why);
+- return;
+- }
+- if (down_interruptible(&psinfo->buf_lock)) {
+- pr_err("could not grab semaphore?!\n");
++ if (pstore_cannot_block_path(reason)) {
++ if (!spin_trylock_irqsave(&psinfo->buf_lock, flags)) {
++ pr_err("dump skipped in %s path because of concurrent dump\n",
++ in_nmi() ? "NMI" : why);
+ return;
+ }
++ } else {
++ spin_lock_irqsave(&psinfo->buf_lock, flags);
+ }
+
+ kmsg_dump_rewind(&iter);
+@@ -467,8 +466,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
+ total += record.size;
+ part++;
+ }
+-
+- up(&psinfo->buf_lock);
++ spin_unlock_irqrestore(&psinfo->buf_lock, flags);
+ }
+
+ static struct kmsg_dumper pstore_dumper = {
+@@ -594,7 +592,7 @@ int pstore_register(struct pstore_info *psi)
+ psi->write_user = pstore_write_user_compat;
+ psinfo = psi;
+ mutex_init(&psinfo->read_mutex);
+- sema_init(&psinfo->buf_lock, 1);
++ spin_lock_init(&psinfo->buf_lock);
+
+ if (psi->flags & PSTORE_FLAGS_DMESG)
+ allocate_buf_for_compression();
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 22d904bde6ab9..a74aef99bd3d6 100644
--- a/fs/quota/dquot.c
@@ -130756,6 +197977,74 @@ index 85ba15a60b13b..043e4cb839fa2 100644
-
-module_init(init_smbfs_common)
-module_exit(exit_smbfs_common)
+diff --git a/fs/stat.c b/fs/stat.c
+index 28d2020ba1f42..246d138ec0669 100644
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -334,9 +334,6 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
+ # define choose_32_64(a,b) b
+ #endif
+
+-#define valid_dev(x) choose_32_64(old_valid_dev(x),true)
+-#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
+-
+ #ifndef INIT_STRUCT_STAT_PADDING
+ # define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
+ #endif
+@@ -345,7 +342,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
+ {
+ struct stat tmp;
+
+- if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
++ if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
++ return -EOVERFLOW;
++ if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+ #if BITS_PER_LONG == 32
+ if (stat->size > MAX_NON_LFS)
+@@ -353,7 +352,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
+ #endif
+
+ INIT_STRUCT_STAT_PADDING(tmp);
+- tmp.st_dev = encode_dev(stat->dev);
++ tmp.st_dev = new_encode_dev(stat->dev);
+ tmp.st_ino = stat->ino;
+ if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
+ return -EOVERFLOW;
+@@ -363,7 +362,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
+ return -EOVERFLOW;
+ SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+ SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
+- tmp.st_rdev = encode_dev(stat->rdev);
++ tmp.st_rdev = new_encode_dev(stat->rdev);
+ tmp.st_size = stat->size;
+ tmp.st_atime = stat->atime.tv_sec;
+ tmp.st_mtime = stat->mtime.tv_sec;
+@@ -644,11 +643,13 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+ {
+ struct compat_stat tmp;
+
+- if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
++ if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
++ return -EOVERFLOW;
++ if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+
+ memset(&tmp, 0, sizeof(tmp));
+- tmp.st_dev = old_encode_dev(stat->dev);
++ tmp.st_dev = new_encode_dev(stat->dev);
+ tmp.st_ino = stat->ino;
+ if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
+ return -EOVERFLOW;
+@@ -658,7 +659,7 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+ return -EOVERFLOW;
+ SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+ SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
+- tmp.st_rdev = old_encode_dev(stat->rdev);
++ tmp.st_rdev = new_encode_dev(stat->rdev);
+ if ((u64) stat->size > MAX_NON_LFS)
+ return -EOVERFLOW;
+ tmp.st_size = stat->size;
diff --git a/fs/super.c b/fs/super.c
index bcef3a6f4c4b5..87379bb1f7a30 100644
--- a/fs/super.c
@@ -130819,6 +198108,134 @@ index bcef3a6f4c4b5..87379bb1f7a30 100644
out:
wake_up(&sb->s_writers.wait_unfrozen);
deactivate_locked_super(sb);
+diff --git a/fs/sync.c b/fs/sync.c
+index 1373a610dc784..c7690016453e4 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -3,6 +3,7 @@
+ * High-level sync()-related operations
+ */
+
++#include <linux/blkdev.h>
+ #include <linux/kernel.h>
+ #include <linux/file.h>
+ #include <linux/fs.h>
+@@ -21,25 +22,6 @@
+ #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
+ SYNC_FILE_RANGE_WAIT_AFTER)
+
+-/*
+- * Do the filesystem syncing work. For simple filesystems
+- * writeback_inodes_sb(sb) just dirties buffers with inodes so we have to
+- * submit IO for these buffers via __sync_blockdev(). This also speeds up the
+- * wait == 1 case since in that case write_inode() functions do
+- * sync_dirty_buffer() and thus effectively write one block at a time.
+- */
+-static int __sync_filesystem(struct super_block *sb, int wait)
+-{
+- if (wait)
+- sync_inodes_sb(sb);
+- else
+- writeback_inodes_sb(sb, WB_REASON_SYNC);
+-
+- if (sb->s_op->sync_fs)
+- sb->s_op->sync_fs(sb, wait);
+- return __sync_blockdev(sb->s_bdev, wait);
+-}
+-
+ /*
+ * Write out and wait upon all dirty data associated with this
+ * superblock. Filesystem data as well as the underlying block
+@@ -47,7 +29,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
+ */
+ int sync_filesystem(struct super_block *sb)
+ {
+- int ret;
++ int ret = 0;
+
+ /*
+ * We need to be protected against the filesystem going from
+@@ -61,10 +43,31 @@ int sync_filesystem(struct super_block *sb)
+ if (sb_rdonly(sb))
+ return 0;
+
+- ret = __sync_filesystem(sb, 0);
+- if (ret < 0)
++ /*
++ * Do the filesystem syncing work. For simple filesystems
++ * writeback_inodes_sb(sb) just dirties buffers with inodes so we have
++ * to submit I/O for these buffers via sync_blockdev(). This also
++ * speeds up the wait == 1 case since in that case write_inode()
++ * methods call sync_dirty_buffer() and thus effectively write one block
++ * at a time.
++ */
++ writeback_inodes_sb(sb, WB_REASON_SYNC);
++ if (sb->s_op->sync_fs) {
++ ret = sb->s_op->sync_fs(sb, 0);
++ if (ret)
++ return ret;
++ }
++ ret = sync_blockdev_nowait(sb->s_bdev);
++ if (ret)
+ return ret;
+- return __sync_filesystem(sb, 1);
++
++ sync_inodes_sb(sb);
++ if (sb->s_op->sync_fs) {
++ ret = sb->s_op->sync_fs(sb, 1);
++ if (ret)
++ return ret;
++ }
++ return sync_blockdev(sb->s_bdev);
+ }
+ EXPORT_SYMBOL(sync_filesystem);
+
+@@ -81,21 +84,6 @@ static void sync_fs_one_sb(struct super_block *sb, void *arg)
+ sb->s_op->sync_fs(sb, *(int *)arg);
+ }
+
+-static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
+-{
+- filemap_fdatawrite(bdev->bd_inode->i_mapping);
+-}
+-
+-static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
+-{
+- /*
+- * We keep the error status of individual mapping so that
+- * applications can catch the writeback error using fsync(2).
+- * See filemap_fdatawait_keep_errors() for details.
+- */
+- filemap_fdatawait_keep_errors(bdev->bd_inode->i_mapping);
+-}
+-
+ /*
+ * Sync everything. We start by waking flusher threads so that most of
+ * writeback runs on all devices in parallel. Then we sync all inodes reliably
+@@ -114,8 +102,8 @@ void ksys_sync(void)
+ iterate_supers(sync_inodes_one_sb, NULL);
+ iterate_supers(sync_fs_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &wait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
+- iterate_bdevs(fdatawait_one_bdev, NULL);
++ sync_bdevs(false);
++ sync_bdevs(true);
+ if (unlikely(laptop_mode))
+ laptop_sync_completion();
+ }
+@@ -136,10 +124,10 @@ static void do_sync_work(struct work_struct *work)
+ */
+ iterate_supers(sync_inodes_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &nowait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
++ sync_bdevs(false);
+ iterate_supers(sync_inodes_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &nowait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
++ sync_bdevs(false);
+ printk("Emergency Sync complete\n");
+ kfree(work);
+ }
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 1261e8b41edb4..f2625a372a3ae 100644
--- a/fs/tracefs/inode.c
@@ -130935,6 +198352,617 @@ index 1261e8b41edb4..f2625a372a3ae 100644
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
+diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
+index 7c61d0ec0159e..79e371bc15e1e 100644
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -349,20 +349,97 @@ out_budg:
+ return err;
+ }
+
+-static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+- umode_t mode, struct inode **whiteout)
++static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry)
++{
++ int err;
++ umode_t mode = S_IFCHR | WHITEOUT_MODE;
++ struct inode *inode;
++ struct ubifs_info *c = dir->i_sb->s_fs_info;
++ struct fscrypt_name nm;
++
++ /*
++ * Create an inode('nlink = 1') for whiteout without updating journal,
++ * let ubifs_jnl_rename() store it on flash to complete rename whiteout
++ * atomically.
++ */
++
++ dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
++ dentry, mode, dir->i_ino);
++
++ err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
++ if (err)
++ return ERR_PTR(err);
++
++ inode = ubifs_new_inode(c, dir, mode);
++ if (IS_ERR(inode)) {
++ err = PTR_ERR(inode);
++ goto out_free;
++ }
++
++ init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
++ ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
++
++ err = ubifs_init_security(dir, inode, &dentry->d_name);
++ if (err)
++ goto out_inode;
++
++ /* The dir size is updated by do_rename. */
++ insert_inode_hash(inode);
++
++ return inode;
++
++out_inode:
++ make_bad_inode(inode);
++ iput(inode);
++out_free:
++ fscrypt_free_filename(&nm);
++ ubifs_err(c, "cannot create whiteout file, error %d", err);
++ return ERR_PTR(err);
++}
++
++/**
++ * lock_2_inodes - a wrapper for locking two UBIFS inodes.
++ * @inode1: first inode
++ * @inode2: second inode
++ *
++ * We do not implement any tricks to guarantee strict lock ordering, because
++ * VFS has already done it for us on the @i_mutex. So this is just a simple
++ * wrapper function.
++ */
++static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
++{
++ mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
++ mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
++}
++
++/**
++ * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
++ * @inode1: first inode
++ * @inode2: second inode
++ */
++static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
++{
++ mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
++ mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
++}
++
++static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, umode_t mode)
+ {
+ struct inode *inode;
+ struct ubifs_info *c = dir->i_sb->s_fs_info;
+- struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
++ .dirtied_ino = 1};
+ struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
+- struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir);
++ struct ubifs_inode *ui;
+ int err, instantiated = 0;
+ struct fscrypt_name nm;
+
+ /*
+- * Budget request settings: new dirty inode, new direntry,
+- * budget for dirtied inode will be released via writeback.
++ * Budget request settings: new inode, new direntry, changing the
++ * parent directory inode.
++ * Allocate budget separately for new dirtied inode, the budget will
++ * be released via writeback.
+ */
+
+ dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
+@@ -392,42 +469,30 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+ }
+ ui = ubifs_inode(inode);
+
+- if (whiteout) {
+- init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
+- ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
+- }
+-
+ err = ubifs_init_security(dir, inode, &dentry->d_name);
+ if (err)
+ goto out_inode;
+
+ mutex_lock(&ui->ui_mutex);
+ insert_inode_hash(inode);
+-
+- if (whiteout) {
+- mark_inode_dirty(inode);
+- drop_nlink(inode);
+- *whiteout = inode;
+- } else {
+- d_tmpfile(dentry, inode);
+- }
++ d_tmpfile(dentry, inode);
+ ubifs_assert(c, ui->dirty);
+
+ instantiated = 1;
+ mutex_unlock(&ui->ui_mutex);
+
+- mutex_lock(&dir_ui->ui_mutex);
++ lock_2_inodes(dir, inode);
+ err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0);
+ if (err)
+ goto out_cancel;
+- mutex_unlock(&dir_ui->ui_mutex);
++ unlock_2_inodes(dir, inode);
+
+ ubifs_release_budget(c, &req);
+
+ return 0;
+
+ out_cancel:
+- mutex_unlock(&dir_ui->ui_mutex);
++ unlock_2_inodes(dir, inode);
+ out_inode:
+ make_bad_inode(inode);
+ if (!instantiated)
+@@ -441,12 +506,6 @@ out_budg:
+ return err;
+ }
+
+-static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
+- struct dentry *dentry, umode_t mode)
+-{
+- return do_tmpfile(dir, dentry, mode, NULL);
+-}
+-
+ /**
+ * vfs_dent_type - get VFS directory entry type.
+ * @type: UBIFS directory entry type
+@@ -660,32 +719,6 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
+ return 0;
+ }
+
+-/**
+- * lock_2_inodes - a wrapper for locking two UBIFS inodes.
+- * @inode1: first inode
+- * @inode2: second inode
+- *
+- * We do not implement any tricks to guarantee strict lock ordering, because
+- * VFS has already done it for us on the @i_mutex. So this is just a simple
+- * wrapper function.
+- */
+-static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
+-{
+- mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
+- mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
+-}
+-
+-/**
+- * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
+- * @inode1: first inode
+- * @inode2: second inode
+- */
+-static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
+-{
+- mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
+- mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
+-}
+-
+ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+ {
+@@ -949,7 +982,8 @@ static int ubifs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
+ struct ubifs_inode *dir_ui = ubifs_inode(dir);
+ struct ubifs_info *c = dir->i_sb->s_fs_info;
+ int err, sz_change;
+- struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
++ .dirtied_ino = 1};
+ struct fscrypt_name nm;
+
+ /*
+@@ -1264,17 +1298,19 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ .dirtied_ino = 3 };
+ struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
+ .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
++ struct ubifs_budget_req wht_req;
+ struct timespec64 time;
+ unsigned int saved_nlink;
+ struct fscrypt_name old_nm, new_nm;
+
+ /*
+- * Budget request settings: deletion direntry, new direntry, removing
+- * the old inode, and changing old and new parent directory inodes.
++ * Budget request settings:
++ * req: deletion direntry, new direntry, removing the old inode,
++ * and changing old and new parent directory inodes.
++ *
++ * wht_req: new whiteout inode for RENAME_WHITEOUT.
+ *
+- * However, this operation also marks the target inode as dirty and
+- * does not write it, so we allocate budget for the target inode
+- * separately.
++ * ino_req: marks the target inode as dirty and does not write it.
+ */
+
+ dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x",
+@@ -1331,20 +1367,44 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ goto out_release;
+ }
+
+- err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
+- if (err) {
++ /*
++ * The whiteout inode without dentry is pinned in memory,
++ * umount won't happen during rename process because we
++ * got parent dentry.
++ */
++ whiteout = create_whiteout(old_dir, old_dentry);
++ if (IS_ERR(whiteout)) {
++ err = PTR_ERR(whiteout);
+ kfree(dev);
+ goto out_release;
+ }
+
+- spin_lock(&whiteout->i_lock);
+- whiteout->i_state |= I_LINKABLE;
+- spin_unlock(&whiteout->i_lock);
+-
+ whiteout_ui = ubifs_inode(whiteout);
+ whiteout_ui->data = dev;
+ whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
+ ubifs_assert(c, !whiteout_ui->dirty);
++
++ memset(&wht_req, 0, sizeof(struct ubifs_budget_req));
++ wht_req.new_ino = 1;
++ wht_req.new_ino_d = ALIGN(whiteout_ui->data_len, 8);
++ /*
++ * To avoid deadlock between space budget (holds ui_mutex and
++ * waits wb work) and writeback work(waits ui_mutex), do space
++ * budget before ubifs inodes locked.
++ */
++ err = ubifs_budget_space(c, &wht_req);
++ if (err) {
++ /*
++ * Whiteout inode can not be written on flash by
++ * ubifs_jnl_write_inode(), because it's neither
++ * dirty nor zero-nlink.
++ */
++ iput(whiteout);
++ goto out_release;
++ }
++
++ /* Add the old_dentry size to the old_dir size. */
++ old_sz -= CALC_DENT_SIZE(fname_len(&old_nm));
+ }
+
+ lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
+@@ -1416,29 +1476,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
+ if (unlink && IS_SYNC(new_inode))
+ sync = 1;
+- }
+-
+- if (whiteout) {
+- struct ubifs_budget_req wht_req = { .dirtied_ino = 1,
+- .dirtied_ino_d = \
+- ALIGN(ubifs_inode(whiteout)->data_len, 8) };
+-
+- err = ubifs_budget_space(c, &wht_req);
+- if (err) {
+- kfree(whiteout_ui->data);
+- whiteout_ui->data_len = 0;
+- iput(whiteout);
+- goto out_release;
+- }
+-
+- inc_nlink(whiteout);
+- mark_inode_dirty(whiteout);
+-
+- spin_lock(&whiteout->i_lock);
+- whiteout->i_state &= ~I_LINKABLE;
+- spin_unlock(&whiteout->i_lock);
+-
+- iput(whiteout);
++ /*
++ * S_SYNC flag of whiteout inherits from the old_dir, and we
++ * have already checked the old dir inode. So there is no need
++ * to check whiteout.
++ */
+ }
+
+ err = ubifs_jnl_rename(c, old_dir, old_inode, &old_nm, new_dir,
+@@ -1449,6 +1491,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
+ ubifs_release_budget(c, &req);
+
++ if (whiteout) {
++ ubifs_release_budget(c, &wht_req);
++ iput(whiteout);
++ }
++
+ mutex_lock(&old_inode_ui->ui_mutex);
+ release = old_inode_ui->dirty;
+ mark_inode_dirty_sync(old_inode);
+@@ -1457,11 +1504,16 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ if (release)
+ ubifs_release_budget(c, &ino_req);
+ if (IS_SYNC(old_inode))
+- err = old_inode->i_sb->s_op->write_inode(old_inode, NULL);
++ /*
++ * Rename finished here. Although old inode cannot be updated
++ * on flash, old ctime is not a big problem, don't return err
++ * code to userspace.
++ */
++ old_inode->i_sb->s_op->write_inode(old_inode, NULL);
+
+ fscrypt_free_filename(&old_nm);
+ fscrypt_free_filename(&new_nm);
+- return err;
++ return 0;
+
+ out_cancel:
+ if (unlink) {
+@@ -1482,11 +1534,11 @@ out_cancel:
+ inc_nlink(old_dir);
+ }
+ }
++ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
+ if (whiteout) {
+- drop_nlink(whiteout);
++ ubifs_release_budget(c, &wht_req);
+ iput(whiteout);
+ }
+- unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
+ out_release:
+ ubifs_release_budget(c, &ino_req);
+ ubifs_release_budget(c, &req);
+diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
+index 5cfa28cd00cdc..6b45a037a0471 100644
+--- a/fs/ubifs/file.c
++++ b/fs/ubifs/file.c
+@@ -570,7 +570,7 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping,
+ }
+
+ if (!PagePrivate(page)) {
+- SetPagePrivate(page);
++ attach_page_private(page, (void *)1);
+ atomic_long_inc(&c->dirty_pg_cnt);
+ __set_page_dirty_nobuffers(page);
+ }
+@@ -947,7 +947,7 @@ static int do_writepage(struct page *page, int len)
+ release_existing_page_budget(c);
+
+ atomic_long_dec(&c->dirty_pg_cnt);
+- ClearPagePrivate(page);
++ detach_page_private(page);
+ ClearPageChecked(page);
+
+ kunmap(page);
+@@ -1304,7 +1304,7 @@ static void ubifs_invalidatepage(struct page *page, unsigned int offset,
+ release_existing_page_budget(c);
+
+ atomic_long_dec(&c->dirty_pg_cnt);
+- ClearPagePrivate(page);
++ detach_page_private(page);
+ ClearPageChecked(page);
+ }
+
+@@ -1471,8 +1471,8 @@ static int ubifs_migrate_page(struct address_space *mapping,
+ return rc;
+
+ if (PagePrivate(page)) {
+- ClearPagePrivate(page);
+- SetPagePrivate(newpage);
++ detach_page_private(page);
++ attach_page_private(newpage, (void *)1);
+ }
+
+ if (mode != MIGRATE_SYNC_NO_COPY)
+@@ -1496,7 +1496,7 @@ static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
+ return 0;
+ ubifs_assert(c, PagePrivate(page));
+ ubifs_assert(c, 0);
+- ClearPagePrivate(page);
++ detach_page_private(page);
+ ClearPageChecked(page);
+ return 1;
+ }
+@@ -1567,7 +1567,7 @@ static vm_fault_t ubifs_vm_page_mkwrite(struct vm_fault *vmf)
+ else {
+ if (!PageChecked(page))
+ ubifs_convert_page_budget(c);
+- SetPagePrivate(page);
++ attach_page_private(page, (void *)1);
+ atomic_long_inc(&c->dirty_pg_cnt);
+ __set_page_dirty_nobuffers(page);
+ }
+diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
+index 00b61dba62b70..b019dd6f7fa06 100644
+--- a/fs/ubifs/io.c
++++ b/fs/ubifs/io.c
+@@ -833,16 +833,42 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
+ */
+ n = aligned_len >> c->max_write_shift;
+ if (n) {
+- n <<= c->max_write_shift;
++ int m = n - 1;
++
+ dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
+ wbuf->offs);
+- err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+- wbuf->offs, n);
++
++ if (m) {
++ /* '(n-1)<<c->max_write_shift < len' is always true. */
++ m <<= c->max_write_shift;
++ err = ubifs_leb_write(c, wbuf->lnum, buf + written,
++ wbuf->offs, m);
++ if (err)
++ goto out;
++ wbuf->offs += m;
++ aligned_len -= m;
++ len -= m;
++ written += m;
++ }
++
++ /*
++ * The non-written len of buf may be less than 'n' because
++ * parameter 'len' is not 8 bytes aligned, so here we read
++ * min(len, n) bytes from buf.
++ */
++ n = 1 << c->max_write_shift;
++ memcpy(wbuf->buf, buf + written, min(len, n));
++ if (n > len) {
++ ubifs_assert(c, n - len < 8);
++ ubifs_pad(c, wbuf->buf + len, n - len);
++ }
++
++ err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, n);
+ if (err)
+ goto out;
+ wbuf->offs += n;
+ aligned_len -= n;
+- len -= n;
++ len -= min(len, n);
+ written += n;
+ }
+
+diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
+index c6a8634877803..71bcebe45f9c5 100644
+--- a/fs/ubifs/ioctl.c
++++ b/fs/ubifs/ioctl.c
+@@ -108,7 +108,7 @@ static int setflags(struct inode *inode, int flags)
+ struct ubifs_inode *ui = ubifs_inode(inode);
+ struct ubifs_info *c = inode->i_sb->s_fs_info;
+ struct ubifs_budget_req req = { .dirtied_ino = 1,
+- .dirtied_ino_d = ui->data_len };
++ .dirtied_ino_d = ALIGN(ui->data_len, 8) };
+
+ err = ubifs_budget_space(c, &req);
+ if (err)
+diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
+index 8ea680dba61e3..75dab0ae3939d 100644
+--- a/fs/ubifs/journal.c
++++ b/fs/ubifs/journal.c
+@@ -1207,9 +1207,9 @@ out_free:
+ * @sync: non-zero if the write-buffer has to be synchronized
+ *
+ * This function implements the re-name operation which may involve writing up
+- * to 4 inodes and 2 directory entries. It marks the written inodes as clean
+- * and returns zero on success. In case of failure, a negative error code is
+- * returned.
++ * to 4 inodes(new inode, whiteout inode, old and new parent directory inodes)
++ * and 2 directory entries. It marks the written inodes as clean and returns
++ * zero on success. In case of failure, a negative error code is returned.
+ */
+ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ const struct inode *old_inode,
+@@ -1222,14 +1222,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ void *p;
+ union ubifs_key key;
+ struct ubifs_dent_node *dent, *dent2;
+- int err, dlen1, dlen2, ilen, lnum, offs, len, orphan_added = 0;
++ int err, dlen1, dlen2, ilen, wlen, lnum, offs, len, orphan_added = 0;
+ int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
+ int last_reference = !!(new_inode && new_inode->i_nlink == 0);
+ int move = (old_dir != new_dir);
+- struct ubifs_inode *new_ui;
++ struct ubifs_inode *new_ui, *whiteout_ui;
+ u8 hash_old_dir[UBIFS_HASH_ARR_SZ];
+ u8 hash_new_dir[UBIFS_HASH_ARR_SZ];
+ u8 hash_new_inode[UBIFS_HASH_ARR_SZ];
++ u8 hash_whiteout_inode[UBIFS_HASH_ARR_SZ];
+ u8 hash_dent1[UBIFS_HASH_ARR_SZ];
+ u8 hash_dent2[UBIFS_HASH_ARR_SZ];
+
+@@ -1249,9 +1250,20 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ } else
+ ilen = 0;
+
++ if (whiteout) {
++ whiteout_ui = ubifs_inode(whiteout);
++ ubifs_assert(c, mutex_is_locked(&whiteout_ui->ui_mutex));
++ ubifs_assert(c, whiteout->i_nlink == 1);
++ ubifs_assert(c, !whiteout_ui->dirty);
++ wlen = UBIFS_INO_NODE_SZ;
++ wlen += whiteout_ui->data_len;
++ } else
++ wlen = 0;
++
+ aligned_dlen1 = ALIGN(dlen1, 8);
+ aligned_dlen2 = ALIGN(dlen2, 8);
+- len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
++ len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) +
++ ALIGN(wlen, 8) + ALIGN(plen, 8);
+ if (move)
+ len += plen;
+
+@@ -1313,6 +1325,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ p += ALIGN(ilen, 8);
+ }
+
++ if (whiteout) {
++ pack_inode(c, p, whiteout, 0);
++ err = ubifs_node_calc_hash(c, p, hash_whiteout_inode);
++ if (err)
++ goto out_release;
++
++ p += ALIGN(wlen, 8);
++ }
++
+ if (!move) {
+ pack_inode(c, p, old_dir, 1);
+ err = ubifs_node_calc_hash(c, p, hash_old_dir);
+@@ -1352,6 +1373,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ if (new_inode)
+ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
+ new_inode->i_ino);
++ if (whiteout)
++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
++ whiteout->i_ino);
+ }
+ release_head(c, BASEHD);
+
+@@ -1368,8 +1392,6 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, hash_dent2, old_nm);
+ if (err)
+ goto out_ro;
+-
+- ubifs_delete_orphan(c, whiteout->i_ino);
+ } else {
+ err = ubifs_add_dirt(c, lnum, dlen2);
+ if (err)
+@@ -1390,6 +1412,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ offs += ALIGN(ilen, 8);
+ }
+
++ if (whiteout) {
++ ino_key_init(c, &key, whiteout->i_ino);
++ err = ubifs_tnc_add(c, &key, lnum, offs, wlen,
++ hash_whiteout_inode);
++ if (err)
++ goto out_ro;
++ offs += ALIGN(wlen, 8);
++ }
++
+ ino_key_init(c, &key, old_dir->i_ino);
+ err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_old_dir);
+ if (err)
+@@ -1410,6 +1441,11 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
+ new_ui->synced_i_size = new_ui->ui_size;
+ spin_unlock(&new_ui->ui_lock);
+ }
++ /*
++ * No need to mark whiteout inode clean.
++ * Whiteout doesn't have non-zero size, no need to update
++ * synced_i_size for whiteout_ui.
++ */
+ mark_inode_clean(c, ubifs_inode(old_dir));
+ if (move)
+ mark_inode_clean(c, ubifs_inode(new_dir));
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f0fb25727d961..eb05038b71911 100644
--- a/fs/ubifs/super.c
@@ -131089,7 +199117,7 @@ index 1d6b7a50736ba..ea8f6cd01f501 100644
}
put_page(page);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
-index caeef08efed23..0ed4861b038f6 100644
+index caeef08efed23..b3d5f97f16cdb 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -30,6 +30,7 @@
@@ -131100,6 +199128,34 @@ index caeef08efed23..0ed4861b038f6 100644
static inline int udf_match(int len1, const unsigned char *name1, int len2,
const unsigned char *name2)
+@@ -74,11 +75,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
+
+ if (fileident) {
+ if (adinicb || (offset + lfi < 0)) {
+- memcpy(udf_get_fi_ident(sfi), fileident, lfi);
++ memcpy(sfi->impUse + liu, fileident, lfi);
+ } else if (offset >= 0) {
+ memcpy(fibh->ebh->b_data + offset, fileident, lfi);
+ } else {
+- memcpy(udf_get_fi_ident(sfi), fileident, -offset);
++ memcpy(sfi->impUse + liu, fileident, -offset);
+ memcpy(fibh->ebh->b_data, fileident - offset,
+ lfi + offset);
+ }
+@@ -87,11 +88,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
+ offset += lfi;
+
+ if (adinicb || (offset + padlen < 0)) {
+- memset(udf_get_fi_ident(sfi) + lfi, 0x00, padlen);
++ memset(sfi->impUse + liu + lfi, 0x00, padlen);
+ } else if (offset >= 0) {
+ memset(fibh->ebh->b_data + offset, 0x00, padlen);
+ } else {
+- memset(udf_get_fi_ident(sfi) + lfi, 0x00, -offset);
++ memset(sfi->impUse + liu + lfi, 0x00, -offset);
+ memset(fibh->ebh->b_data, 0x00, padlen + offset);
+ }
+
@@ -134,6 +135,8 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
mark_buffer_dirty_inode(fibh->ebh, inode);
mark_buffer_dirty_inode(fibh->sbh, inode);
@@ -131129,6 +199185,37 @@ index b2d7c57d06881..aa2f6093d3f6f 100644
return &ei->vfs_inode;
}
+diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
+index 7aa943edfc02f..240eb932c014b 100644
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -259,7 +259,7 @@ xfs_file_dio_read(
+ ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED);
+ if (ret)
+ return ret;
+- ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0);
++ ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, 0);
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+
+ return ret;
+@@ -569,7 +569,7 @@ xfs_file_dio_write_aligned(
+ }
+ trace_xfs_file_direct_write(iocb, from);
+ ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
+- &xfs_dio_write_ops, 0);
++ &xfs_dio_write_ops, 0, 0);
+ out_unlock:
+ if (iolock)
+ xfs_iunlock(ip, iolock);
+@@ -647,7 +647,7 @@ retry_exclusive:
+
+ trace_xfs_file_direct_write(iocb, from);
+ ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
+- &xfs_dio_write_ops, flags);
++ &xfs_dio_write_ops, flags, 0);
+
+ /*
+ * Retry unaligned I/O with exclusive blocking semantics if the DIO
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 0c795dc093efa..09269f478df9c 100644
--- a/fs/xfs/xfs_ioctl.c
@@ -131143,11 +199230,146 @@ index 0c795dc093efa..09269f478df9c 100644
if (error)
goto out_unlock;
}
+diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
+index c4e0cd1c1c8ca..170fee98c45c7 100644
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -729,6 +729,7 @@ xfs_fs_sync_fs(
+ int wait)
+ {
+ struct xfs_mount *mp = XFS_M(sb);
++ int error;
+
+ trace_xfs_fs_sync_fs(mp, __return_address);
+
+@@ -738,7 +739,10 @@ xfs_fs_sync_fs(
+ if (!wait)
+ return 0;
+
+- xfs_log_force(mp, XFS_LOG_SYNC);
++ error = xfs_log_force(mp, XFS_LOG_SYNC);
++ if (error)
++ return error;
++
+ if (laptop_mode) {
+ /*
+ * The disk must be active because we're syncing.
diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c
-index ddc346a9df9ba..807f33553a8eb 100644
+index ddc346a9df9ba..b34ccfd71b0ff 100644
--- a/fs/zonefs/super.c
+++ b/fs/zonefs/super.c
-@@ -1787,5 +1787,6 @@ static void __exit zonefs_exit(void)
+@@ -35,6 +35,17 @@ static inline int zonefs_zone_mgmt(struct inode *inode,
+
+ lockdep_assert_held(&zi->i_truncate_mutex);
+
++ /*
++ * With ZNS drives, closing an explicitly open zone that has not been
++ * written will change the zone state to "closed", that is, the zone
++ * will remain active. Since this can then cause failure of explicit
++ * open operation on other zones if the drive active zone resources
++ * are exceeded, make sure that the zone does not remain active by
++ * resetting it.
++ */
++ if (op == REQ_OP_ZONE_CLOSE && !zi->i_wpoffset)
++ op = REQ_OP_ZONE_RESET;
++
+ trace_zonefs_zone_mgmt(inode, op);
+ ret = blkdev_zone_mgmt(inode->i_sb->s_bdev, op, zi->i_zsector,
+ zi->i_zone_size >> SECTOR_SHIFT, GFP_NOFS);
+@@ -852,7 +863,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
+ ret = zonefs_file_dio_append(iocb, from);
+ else
+ ret = iomap_dio_rw(iocb, from, &zonefs_iomap_ops,
+- &zonefs_write_dio_ops, 0);
++ &zonefs_write_dio_ops, 0, 0);
+ if (zi->i_ztype == ZONEFS_ZTYPE_SEQ &&
+ (ret > 0 || ret == -EIOCBQUEUED)) {
+ if (ret > 0)
+@@ -987,7 +998,7 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ }
+ file_accessed(iocb->ki_filp);
+ ret = iomap_dio_rw(iocb, to, &zonefs_iomap_ops,
+- &zonefs_read_dio_ops, 0);
++ &zonefs_read_dio_ops, 0, 0);
+ } else {
+ ret = generic_file_read_iter(iocb, to);
+ if (ret == -EIO)
+@@ -1144,6 +1155,7 @@ static struct inode *zonefs_alloc_inode(struct super_block *sb)
+ inode_init_once(&zi->i_vnode);
+ mutex_init(&zi->i_truncate_mutex);
+ zi->i_wr_refcnt = 0;
++ zi->i_flags = 0;
+
+ return &zi->i_vnode;
+ }
+@@ -1295,12 +1307,13 @@ static void zonefs_init_dir_inode(struct inode *parent, struct inode *inode,
+ inc_nlink(parent);
+ }
+
+-static void zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
+- enum zonefs_ztype type)
++static int zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
++ enum zonefs_ztype type)
+ {
+ struct super_block *sb = inode->i_sb;
+ struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
+ struct zonefs_inode_info *zi = ZONEFS_I(inode);
++ int ret = 0;
+
+ inode->i_ino = zone->start >> sbi->s_zone_sectors_shift;
+ inode->i_mode = S_IFREG | sbi->s_perm;
+@@ -1325,6 +1338,22 @@ static void zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
+ sb->s_maxbytes = max(zi->i_max_size, sb->s_maxbytes);
+ sbi->s_blocks += zi->i_max_size >> sb->s_blocksize_bits;
+ sbi->s_used_blocks += zi->i_wpoffset >> sb->s_blocksize_bits;
++
++ /*
++ * For sequential zones, make sure that any open zone is closed first
++ * to ensure that the initial number of open zones is 0, in sync with
++ * the open zone accounting done when the mount option
++ * ZONEFS_MNTOPT_EXPLICIT_OPEN is used.
++ */
++ if (type == ZONEFS_ZTYPE_SEQ &&
++ (zone->cond == BLK_ZONE_COND_IMP_OPEN ||
++ zone->cond == BLK_ZONE_COND_EXP_OPEN)) {
++ mutex_lock(&zi->i_truncate_mutex);
++ ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
++ mutex_unlock(&zi->i_truncate_mutex);
++ }
++
++ return ret;
+ }
+
+ static struct dentry *zonefs_create_inode(struct dentry *parent,
+@@ -1334,6 +1363,7 @@ static struct dentry *zonefs_create_inode(struct dentry *parent,
+ struct inode *dir = d_inode(parent);
+ struct dentry *dentry;
+ struct inode *inode;
++ int ret;
+
+ dentry = d_alloc_name(parent, name);
+ if (!dentry)
+@@ -1344,10 +1374,16 @@ static struct dentry *zonefs_create_inode(struct dentry *parent,
+ goto dput;
+
+ inode->i_ctime = inode->i_mtime = inode->i_atime = dir->i_ctime;
+- if (zone)
+- zonefs_init_file_inode(inode, zone, type);
+- else
++ if (zone) {
++ ret = zonefs_init_file_inode(inode, zone, type);
++ if (ret) {
++ iput(inode);
++ goto dput;
++ }
++ } else {
+ zonefs_init_dir_inode(dir, inode, type);
++ }
++
+ d_add(dentry, inode);
+ dir->i_size++;
+
+@@ -1787,5 +1823,6 @@ static void __exit zonefs_exit(void)
MODULE_AUTHOR("Damien Le Moal");
MODULE_DESCRIPTION("Zone file system for zoned block devices");
MODULE_LICENSE("GPL");
@@ -131223,6 +199445,228 @@ index 0d132ee2a2913..835f959a25f25 100644
#else /* CONFIG_GENERIC_FIND_FIRST_BIT */
#ifndef find_first_bit
+diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
+index 2c68a545ffa7d..71942a1c642d4 100644
+--- a/include/asm-generic/tlb.h
++++ b/include/asm-generic/tlb.h
+@@ -565,10 +565,14 @@ static inline void tlb_flush_p4d_range(struct mmu_gather *tlb,
+ #define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ do { \
+ unsigned long _sz = huge_page_size(h); \
+- if (_sz == PMD_SIZE) \
+- tlb_flush_pmd_range(tlb, address, _sz); \
+- else if (_sz == PUD_SIZE) \
++ if (_sz >= P4D_SIZE) \
++ tlb_flush_p4d_range(tlb, address, _sz); \
++ else if (_sz >= PUD_SIZE) \
+ tlb_flush_pud_range(tlb, address, _sz); \
++ else if (_sz >= PMD_SIZE) \
++ tlb_flush_pmd_range(tlb, address, _sz); \
++ else \
++ tlb_flush_pte_range(tlb, address, _sz); \
+ __tlb_remove_tlb_entry(tlb, ptep, address); \
+ } while (0)
+
+diff --git a/include/crypto/blake2s.h b/include/crypto/blake2s.h
+index bc3fb59442ce5..4e30e1799e614 100644
+--- a/include/crypto/blake2s.h
++++ b/include/crypto/blake2s.h
+@@ -101,7 +101,4 @@ static inline void blake2s(u8 *out, const u8 *in, const u8 *key,
+ blake2s_final(&state, out);
+ }
+
+-void blake2s256_hmac(u8 *out, const u8 *in, const u8 *key, const size_t inlen,
+- const size_t keylen);
+-
+ #endif /* _CRYPTO_BLAKE2S_H */
+diff --git a/include/crypto/chacha.h b/include/crypto/chacha.h
+index dabaee6987186..b3ea73b819443 100644
+--- a/include/crypto/chacha.h
++++ b/include/crypto/chacha.h
+@@ -47,12 +47,19 @@ static inline void hchacha_block(const u32 *state, u32 *out, int nrounds)
+ hchacha_block_generic(state, out, nrounds);
+ }
+
++enum chacha_constants { /* expand 32-byte k */
++ CHACHA_CONSTANT_EXPA = 0x61707865U,
++ CHACHA_CONSTANT_ND_3 = 0x3320646eU,
++ CHACHA_CONSTANT_2_BY = 0x79622d32U,
++ CHACHA_CONSTANT_TE_K = 0x6b206574U
++};
++
+ static inline void chacha_init_consts(u32 *state)
+ {
+- state[0] = 0x61707865; /* "expa" */
+- state[1] = 0x3320646e; /* "nd 3" */
+- state[2] = 0x79622d32; /* "2-by" */
+- state[3] = 0x6b206574; /* "te k" */
++ state[0] = CHACHA_CONSTANT_EXPA;
++ state[1] = CHACHA_CONSTANT_ND_3;
++ state[2] = CHACHA_CONSTANT_2_BY;
++ state[3] = CHACHA_CONSTANT_TE_K;
+ }
+
+ void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv);
+diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
+index c4165126937e4..88e4d145f7cda 100644
+--- a/include/crypto/drbg.h
++++ b/include/crypto/drbg.h
+@@ -136,7 +136,7 @@ struct drbg_state {
+ const struct drbg_state_ops *d_ops;
+ const struct drbg_core *core;
+ struct drbg_string test_data;
+- struct random_ready_callback random_ready;
++ struct notifier_block random_ready;
+ };
+
+ static inline __u8 drbg_statelen(struct drbg_state *drbg)
+diff --git a/include/crypto/internal/blake2s.h b/include/crypto/internal/blake2s.h
+index 8e50d487500f2..52363eee2b20e 100644
+--- a/include/crypto/internal/blake2s.h
++++ b/include/crypto/internal/blake2s.h
+@@ -11,11 +11,11 @@
+ #include <crypto/internal/hash.h>
+ #include <linux/string.h>
+
+-void blake2s_compress_generic(struct blake2s_state *state,const u8 *block,
++void blake2s_compress_generic(struct blake2s_state *state, const u8 *block,
+ size_t nblocks, const u32 inc);
+
+-void blake2s_compress_arch(struct blake2s_state *state,const u8 *block,
+- size_t nblocks, const u32 inc);
++void blake2s_compress(struct blake2s_state *state, const u8 *block,
++ size_t nblocks, const u32 inc);
+
+ bool blake2s_selftest(void);
+
+@@ -24,14 +24,11 @@ static inline void blake2s_set_lastblock(struct blake2s_state *state)
+ state->f[0] = -1;
+ }
+
+-typedef void (*blake2s_compress_t)(struct blake2s_state *state,
+- const u8 *block, size_t nblocks, u32 inc);
+-
+ /* Helper functions for BLAKE2s shared by the library and shash APIs */
+
+-static inline void __blake2s_update(struct blake2s_state *state,
+- const u8 *in, size_t inlen,
+- blake2s_compress_t compress)
++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;
+
+@@ -39,7 +36,12 @@ static inline void __blake2s_update(struct blake2s_state *state,
+ return;
+ if (inlen > fill) {
+ memcpy(state->buf + state->buflen, in, fill);
+- (*compress)(state, state->buf, 1, BLAKE2S_BLOCK_SIZE);
++ 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;
+@@ -47,7 +49,12 @@ static inline void __blake2s_update(struct blake2s_state *state,
+ if (inlen > BLAKE2S_BLOCK_SIZE) {
+ const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
+ /* Hash one less (full) block than strictly possible */
+- (*compress)(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE);
++ 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);
+ }
+@@ -55,13 +62,16 @@ static inline void __blake2s_update(struct blake2s_state *state,
+ state->buflen += inlen;
+ }
+
+-static inline void __blake2s_final(struct blake2s_state *state, u8 *out,
+- blake2s_compress_t compress)
++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 */
+- (*compress)(state, state->buf, 1, state->buflen);
++ 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);
+ }
+@@ -99,20 +109,20 @@ static inline int crypto_blake2s_init(struct shash_desc *desc)
+
+ static inline int crypto_blake2s_update(struct shash_desc *desc,
+ const u8 *in, unsigned int inlen,
+- blake2s_compress_t compress)
++ bool force_generic)
+ {
+ struct blake2s_state *state = shash_desc_ctx(desc);
+
+- __blake2s_update(state, in, inlen, compress);
++ __blake2s_update(state, in, inlen, force_generic);
+ return 0;
+ }
+
+ static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out,
+- blake2s_compress_t compress)
++ bool force_generic)
+ {
+ struct blake2s_state *state = shash_desc_ctx(desc);
+
+- __blake2s_final(state, out, compress);
++ __blake2s_final(state, out, force_generic);
+ return 0;
+ }
+
+diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
+index 1647960c9e506..1f43d7c6724aa 100644
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -566,10 +566,16 @@ struct drm_display_info {
+ bool rgb_quant_range_selectable;
+
+ /**
+- * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
+- * more stuff redundant with @bus_formats.
++ * @edid_hdmi_rgb444_dc_modes: Mask of supported hdmi deep color modes
++ * in RGB 4:4:4. Even more stuff redundant with @bus_formats.
+ */
+- u8 edid_hdmi_dc_modes;
++ u8 edid_hdmi_rgb444_dc_modes;
++
++ /**
++ * @edid_hdmi_ycbcr444_dc_modes: Mask of supported hdmi deep color
++ * modes in YCbCr 4:4:4. Even more stuff redundant with @bus_formats.
++ */
++ u8 edid_hdmi_ycbcr444_dc_modes;
+
+ /**
+ * @cea_rev: CEA revision of the HDMI sink.
+diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
+index 1d5b3dbb6e563..dfb46915015b1 100644
+--- a/include/drm/drm_dp_helper.h
++++ b/include/drm/drm_dp_helper.h
+@@ -455,7 +455,7 @@ struct drm_panel;
+ # define DP_FEC_BIT_ERROR_COUNT_CAP (1 << 3)
+
+ /* DP-HDMI2.1 PCON DSC ENCODER SUPPORT */
+-#define DP_PCON_DSC_ENCODER_CAP_SIZE 0xC /* 0x9E - 0x92 */
++#define DP_PCON_DSC_ENCODER_CAP_SIZE 0xD /* 0x92 through 0x9E */
+ #define DP_PCON_DSC_ENCODER 0x092
+ # define DP_PCON_DSC_ENCODER_SUPPORTED (1 << 0)
+ # define DP_PCON_DSC_PPS_ENC_OVERRIDE (1 << 1)
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index f681bbdbc6982..36f7eb9d06639 100644
--- a/include/drm/ttm/ttm_bo_api.h
@@ -131273,6 +199717,136 @@ index 63ccb52521902..220c8c60e021a 100644
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
+diff --git a/include/linux/atomic/atomic-arch-fallback.h b/include/linux/atomic/atomic-arch-fallback.h
+index a3dba31df01e9..6db58d1808665 100644
+--- a/include/linux/atomic/atomic-arch-fallback.h
++++ b/include/linux/atomic/atomic-arch-fallback.h
+@@ -151,7 +151,16 @@
+ static __always_inline int
+ arch_atomic_read_acquire(const atomic_t *v)
+ {
+- return smp_load_acquire(&(v)->counter);
++ int ret;
++
++ if (__native_word(atomic_t)) {
++ ret = smp_load_acquire(&(v)->counter);
++ } else {
++ ret = arch_atomic_read(v);
++ __atomic_acquire_fence();
++ }
++
++ return ret;
+ }
+ #define arch_atomic_read_acquire arch_atomic_read_acquire
+ #endif
+@@ -160,7 +169,12 @@ arch_atomic_read_acquire(const atomic_t *v)
+ static __always_inline void
+ arch_atomic_set_release(atomic_t *v, int i)
+ {
+- smp_store_release(&(v)->counter, i);
++ if (__native_word(atomic_t)) {
++ smp_store_release(&(v)->counter, i);
++ } else {
++ __atomic_release_fence();
++ arch_atomic_set(v, i);
++ }
+ }
+ #define arch_atomic_set_release arch_atomic_set_release
+ #endif
+@@ -1258,7 +1272,16 @@ arch_atomic_dec_if_positive(atomic_t *v)
+ static __always_inline s64
+ arch_atomic64_read_acquire(const atomic64_t *v)
+ {
+- return smp_load_acquire(&(v)->counter);
++ s64 ret;
++
++ if (__native_word(atomic64_t)) {
++ ret = smp_load_acquire(&(v)->counter);
++ } else {
++ ret = arch_atomic64_read(v);
++ __atomic_acquire_fence();
++ }
++
++ return ret;
+ }
+ #define arch_atomic64_read_acquire arch_atomic64_read_acquire
+ #endif
+@@ -1267,7 +1290,12 @@ arch_atomic64_read_acquire(const atomic64_t *v)
+ static __always_inline void
+ arch_atomic64_set_release(atomic64_t *v, s64 i)
+ {
+- smp_store_release(&(v)->counter, i);
++ if (__native_word(atomic64_t)) {
++ smp_store_release(&(v)->counter, i);
++ } else {
++ __atomic_release_fence();
++ arch_atomic64_set(v, i);
++ }
+ }
+ #define arch_atomic64_set_release arch_atomic64_set_release
+ #endif
+@@ -2358,4 +2386,4 @@ arch_atomic64_dec_if_positive(atomic64_t *v)
+ #endif
+
+ #endif /* _LINUX_ATOMIC_FALLBACK_H */
+-// cca554917d7ea73d5e3e7397dd70c484cad9b2c4
++// 8e2cc06bc0d2c0967d2f8424762bd48555ee40ae
+diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
+index 049cf9421d831..f821b72433613 100644
+--- a/include/linux/binfmts.h
++++ b/include/linux/binfmts.h
+@@ -87,6 +87,9 @@ struct coredump_params {
+ loff_t written;
+ loff_t pos;
+ loff_t to_skip;
++ int vma_count;
++ size_t vma_data_size;
++ struct core_vma_metadata *vma_meta;
+ };
+
+ /*
+diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
+index b4de2010fba55..bc5c04d711bbc 100644
+--- a/include/linux/blk-cgroup.h
++++ b/include/linux/blk-cgroup.h
+@@ -24,6 +24,7 @@
+ #include <linux/atomic.h>
+ #include <linux/kthread.h>
+ #include <linux/fs.h>
++#include <linux/blk-mq.h>
+
+ /* percpu_counter batch for blkg_[rw]stats, per-cpu drift doesn't matter */
+ #define BLKG_STAT_CPU_BATCH (INT_MAX / 2)
+@@ -604,6 +605,21 @@ static inline void blkcg_clear_delay(struct blkcg_gq *blkg)
+ atomic_dec(&blkg->blkcg->css.cgroup->congestion_count);
+ }
+
++/**
++ * blk_cgroup_mergeable - Determine whether to allow or disallow merges
++ * @rq: request to merge into
++ * @bio: bio to merge
++ *
++ * @bio and @rq should belong to the same cgroup and their issue_as_root should
++ * match. The latter is necessary as we don't want to throttle e.g. a metadata
++ * update because it happens to be next to a regular IO.
++ */
++static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio)
++{
++ return rq->bio->bi_blkg == bio->bi_blkg &&
++ bio_issue_as_root_blkg(rq->bio) == bio_issue_as_root_blkg(bio);
++}
++
+ void blk_cgroup_bio_start(struct bio *bio);
+ void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta);
+ void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay);
+@@ -659,6 +675,7 @@ static inline void blkg_put(struct blkcg_gq *blkg) { }
+ static inline bool blkcg_punt_bio_submit(struct bio *bio) { return false; }
+ static inline void blkcg_bio_issue_init(struct bio *bio) { }
+ static inline void blk_cgroup_bio_start(struct bio *bio) { }
++static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) { return true; }
+
+ #define blk_queue_for_each_rl(rl, q) \
+ for ((rl) = &(q)->root_rl; (rl); (rl) = NULL)
diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h
index b80c65aba2493..2580e05a8ab67 100644
--- a/include/linux/blk-pm.h
@@ -131287,7 +199861,7 @@ index b80c65aba2493..2580e05a8ab67 100644
#else
static inline void blk_pm_runtime_init(struct request_queue *q,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
-index 12b9dbcc980ee..413c0148c0ce5 100644
+index 12b9dbcc980ee..aebe67ed7a73e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -235,6 +235,14 @@ struct request {
@@ -131332,6 +199906,29 @@ index 12b9dbcc980ee..413c0148c0ce5 100644
unsigned long bio_start_io_acct(struct bio *bio);
void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time,
struct block_device *orig_bdev);
+@@ -1991,6 +1999,8 @@ int truncate_bdev_range(struct block_device *bdev, fmode_t mode, loff_t lstart,
+ #ifdef CONFIG_BLOCK
+ void invalidate_bdev(struct block_device *bdev);
+ int sync_blockdev(struct block_device *bdev);
++int sync_blockdev_nowait(struct block_device *bdev);
++void sync_bdevs(bool wait);
+ #else
+ static inline void invalidate_bdev(struct block_device *bdev)
+ {
+@@ -1999,6 +2009,13 @@ static inline int sync_blockdev(struct block_device *bdev)
+ {
+ return 0;
+ }
++static inline int sync_blockdev_nowait(struct block_device *bdev)
++{
++ return 0;
++}
++static inline void sync_bdevs(bool wait)
++{
++}
+ #endif
+ int fsync_bdev(struct block_device *bdev);
+
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 2746fd8042162..3536ab432b30c 100644
--- a/include/linux/bpf-cgroup.h
@@ -131345,7 +199942,7 @@ index 2746fd8042162..3536ab432b30c 100644
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
-index 3db6f6c95489e..15b690a0cecb0 100644
+index 3db6f6c95489e..c5c4b6f09e230 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -190,7 +190,7 @@ struct bpf_map {
@@ -131381,7 +199978,186 @@ index 3db6f6c95489e..15b690a0cecb0 100644
t_off = map->timer_off;
t_sz = sizeof(struct bpf_timer);
}
-@@ -723,6 +722,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr)
+@@ -294,6 +293,34 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0,
+
+ extern const struct bpf_map_ops bpf_map_offload_ops;
+
++/* bpf_type_flag contains a set of flags that are applicable to the values of
++ * arg_type, ret_type and reg_type. For example, a pointer value may be null,
++ * or a memory is read-only. We classify types into two categories: base types
++ * and extended types. Extended types are base types combined with a type flag.
++ *
++ * Currently there are no more than 32 base types in arg_type, ret_type and
++ * reg_types.
++ */
++#define BPF_BASE_TYPE_BITS 8
++
++enum bpf_type_flag {
++ /* PTR may be NULL. */
++ PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS),
++
++ /* MEM is read-only. When applied on bpf_arg, it indicates the arg is
++ * compatible with both mutable and immutable memory.
++ */
++ MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS),
++
++ __BPF_TYPE_LAST_FLAG = MEM_RDONLY,
++};
++
++/* Max number of base types. */
++#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS)
++
++/* Max number of all types. */
++#define BPF_TYPE_LIMIT (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1))
++
+ /* function argument constraints */
+ enum bpf_arg_type {
+ ARG_DONTCARE = 0, /* unused argument in helper function */
+@@ -305,13 +332,11 @@ enum bpf_arg_type {
+ ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
+ ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */
+ ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */
+- ARG_PTR_TO_MAP_VALUE_OR_NULL, /* pointer to stack used as map value or NULL */
+
+ /* the following constraints used to prototype bpf_memcmp() and other
+ * functions that access data on eBPF program stack
+ */
+ ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */
+- ARG_PTR_TO_MEM_OR_NULL, /* pointer to valid memory or NULL */
+ ARG_PTR_TO_UNINIT_MEM, /* pointer to memory does not need to be initialized,
+ * helper function must fill all bytes or clear
+ * them in error case.
+@@ -321,42 +346,65 @@ enum bpf_arg_type {
+ ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */
+
+ ARG_PTR_TO_CTX, /* pointer to context */
+- ARG_PTR_TO_CTX_OR_NULL, /* pointer to context or NULL */
+ ARG_ANYTHING, /* any (initialized) argument is ok */
+ ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */
+ ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */
+ ARG_PTR_TO_INT, /* pointer to int */
+ ARG_PTR_TO_LONG, /* pointer to long */
+ ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */
+- ARG_PTR_TO_SOCKET_OR_NULL, /* pointer to bpf_sock (fullsock) or NULL */
+ ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */
+ ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */
+- ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */
+ ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
+ ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */
+ ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */
+ ARG_PTR_TO_FUNC, /* pointer to a bpf program function */
+- ARG_PTR_TO_STACK_OR_NULL, /* pointer to stack or NULL */
++ ARG_PTR_TO_STACK, /* pointer to stack */
+ ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */
+ ARG_PTR_TO_TIMER, /* pointer to bpf_timer */
+ __BPF_ARG_TYPE_MAX,
++
++ /* Extended arg_types. */
++ ARG_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MAP_VALUE,
++ ARG_PTR_TO_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MEM,
++ ARG_PTR_TO_CTX_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_CTX,
++ ARG_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET,
++ ARG_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_ALLOC_MEM,
++ ARG_PTR_TO_STACK_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_STACK,
++
++ /* This must be the last entry. Its purpose is to ensure the enum is
++ * wide enough to hold the higher bits reserved for bpf_type_flag.
++ */
++ __BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT,
+ };
++static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
+
+ /* type of values returned from helper functions */
+ enum bpf_return_type {
+ RET_INTEGER, /* function returns integer */
+ RET_VOID, /* function doesn't return anything */
+ RET_PTR_TO_MAP_VALUE, /* returns a pointer to map elem value */
+- RET_PTR_TO_MAP_VALUE_OR_NULL, /* returns a pointer to map elem value or NULL */
+- RET_PTR_TO_SOCKET_OR_NULL, /* returns a pointer to a socket or NULL */
+- RET_PTR_TO_TCP_SOCK_OR_NULL, /* returns a pointer to a tcp_sock or NULL */
+- RET_PTR_TO_SOCK_COMMON_OR_NULL, /* returns a pointer to a sock_common or NULL */
+- RET_PTR_TO_ALLOC_MEM_OR_NULL, /* returns a pointer to dynamically allocated memory or NULL */
+- RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */
+- RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */
++ RET_PTR_TO_SOCKET, /* returns a pointer to a socket */
++ RET_PTR_TO_TCP_SOCK, /* returns a pointer to a tcp_sock */
++ RET_PTR_TO_SOCK_COMMON, /* returns a pointer to a sock_common */
++ RET_PTR_TO_ALLOC_MEM, /* returns a pointer to dynamically allocated memory */
+ RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */
+ RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */
++ __BPF_RET_TYPE_MAX,
++
++ /* Extended ret_types. */
++ RET_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MAP_VALUE,
++ RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET,
++ RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK,
++ RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON,
++ RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_ALLOC_MEM,
++ RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID,
++
++ /* This must be the last entry. Its purpose is to ensure the enum is
++ * wide enough to hold the higher bits reserved for bpf_type_flag.
++ */
++ __BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT,
+ };
++static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
+
+ /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
+ * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
+@@ -418,18 +466,15 @@ enum bpf_reg_type {
+ PTR_TO_CTX, /* reg points to bpf_context */
+ CONST_PTR_TO_MAP, /* reg points to struct bpf_map */
+ PTR_TO_MAP_VALUE, /* reg points to map element value */
+- PTR_TO_MAP_VALUE_OR_NULL,/* points to map elem value or NULL */
++ PTR_TO_MAP_KEY, /* reg points to a map element key */
+ PTR_TO_STACK, /* reg == frame_pointer + offset */
+ PTR_TO_PACKET_META, /* skb->data - meta_len */
+ PTR_TO_PACKET, /* reg points to skb->data */
+ PTR_TO_PACKET_END, /* skb->data + headlen */
+ PTR_TO_FLOW_KEYS, /* reg points to bpf_flow_keys */
+ PTR_TO_SOCKET, /* reg points to struct bpf_sock */
+- PTR_TO_SOCKET_OR_NULL, /* reg points to struct bpf_sock or NULL */
+ PTR_TO_SOCK_COMMON, /* reg points to sock_common */
+- PTR_TO_SOCK_COMMON_OR_NULL, /* reg points to sock_common or NULL */
+ PTR_TO_TCP_SOCK, /* reg points to struct tcp_sock */
+- PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */
+ PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */
+ PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */
+ /* PTR_TO_BTF_ID points to a kernel struct that does not need
+@@ -447,18 +492,25 @@ enum bpf_reg_type {
+ * been checked for null. Used primarily to inform the verifier
+ * an explicit null check is required for this struct.
+ */
+- PTR_TO_BTF_ID_OR_NULL,
+ PTR_TO_MEM, /* reg points to valid memory region */
+- PTR_TO_MEM_OR_NULL, /* reg points to valid memory region or NULL */
+- PTR_TO_RDONLY_BUF, /* reg points to a readonly buffer */
+- PTR_TO_RDONLY_BUF_OR_NULL, /* reg points to a readonly buffer or NULL */
+- PTR_TO_RDWR_BUF, /* reg points to a read/write buffer */
+- PTR_TO_RDWR_BUF_OR_NULL, /* reg points to a read/write buffer or NULL */
++ PTR_TO_BUF, /* reg points to a read/write buffer */
+ PTR_TO_PERCPU_BTF_ID, /* reg points to a percpu kernel variable */
+ PTR_TO_FUNC, /* reg points to a bpf program function */
+- PTR_TO_MAP_KEY, /* reg points to a map element key */
+ __BPF_REG_TYPE_MAX,
++
++ /* Extended reg_types. */
++ PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | PTR_TO_MAP_VALUE,
++ PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCKET,
++ PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCK_COMMON,
++ PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | PTR_TO_TCP_SOCK,
++ PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | PTR_TO_BTF_ID,
++
++ /* This must be the last entry. Its purpose is to ensure the enum is
++ * wide enough to hold the higher bits reserved for bpf_type_flag.
++ */
++ __BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT,
+ };
++static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
+
+ /* The information passed from prog-specific *_is_valid_access
+ * back to the verifier.
+@@ -723,6 +775,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr)
struct bpf_trampoline *bpf_trampoline_get(u64 key,
struct bpf_attach_target_info *tgt_info);
void bpf_trampoline_put(struct bpf_trampoline *tr);
@@ -131389,7 +200165,7 @@ index 3db6f6c95489e..15b690a0cecb0 100644
#define BPF_DISPATCHER_INIT(_name) { \
.mutex = __MUTEX_INITIALIZER(_name.mutex), \
.func = &_name##_func, \
-@@ -1320,28 +1320,16 @@ extern struct mutex bpf_stats_enabled_mutex;
+@@ -1320,28 +1373,16 @@ extern struct mutex bpf_stats_enabled_mutex;
* kprobes, tracepoints) to prevent deadlocks on map operations as any of
* these events can happen inside a region which holds a map bucket lock
* and can deadlock on it.
@@ -131420,7 +200196,7 @@ index 3db6f6c95489e..15b690a0cecb0 100644
migrate_enable();
}
-@@ -1387,6 +1375,7 @@ void bpf_map_put(struct bpf_map *map);
+@@ -1387,6 +1428,7 @@ void bpf_map_put(struct bpf_map *map);
void *bpf_map_area_alloc(u64 size, int numa_node);
void *bpf_map_area_mmapable_alloc(u64 size, int numa_node);
void bpf_map_area_free(void *base);
@@ -131428,7 +200204,7 @@ index 3db6f6c95489e..15b690a0cecb0 100644
void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
int generic_map_lookup_batch(struct bpf_map *map,
const union bpf_attr *attr,
-@@ -1677,6 +1666,12 @@ bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog);
+@@ -1677,6 +1719,12 @@ bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog);
const struct btf_func_model *
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
const struct bpf_insn *insn);
@@ -131441,7 +200217,7 @@ index 3db6f6c95489e..15b690a0cecb0 100644
#else /* !CONFIG_BPF_SYSCALL */
static inline struct bpf_prog *bpf_prog_get(u32 ufd)
{
-@@ -1895,6 +1890,12 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
+@@ -1895,6 +1943,12 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
{
return NULL;
}
@@ -131455,10 +200231,19 @@ index 3db6f6c95489e..15b690a0cecb0 100644
void __bpf_free_used_btfs(struct bpf_prog_aux *aux,
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
-index 5424124dbe365..364550dd19c4a 100644
+index 5424124dbe365..bb1cc3fbc4bab 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
-@@ -396,6 +396,13 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
+@@ -18,6 +18,8 @@
+ * that converting umax_value to int cannot overflow.
+ */
+ #define BPF_MAX_VAR_SIZ (1 << 29)
++/* size of type_str_buf in bpf_verifier. */
++#define TYPE_STR_BUF_LEN 64
+
+ /* Liveness marks, used for registers and spilled-regs (in stack slots).
+ * Read marks propagate upwards until they find a write mark; they record that
+@@ -396,6 +398,13 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
log->level == BPF_LOG_KERNEL);
}
@@ -131472,6 +200257,34 @@ index 5424124dbe365..364550dd19c4a 100644
#define BPF_MAX_SUBPROGS 256
struct bpf_subprog_info {
+@@ -467,6 +476,8 @@ struct bpf_verifier_env {
+ /* longest register parentage chain walked for liveness marking */
+ u32 longest_mark_read_walk;
+ bpfptr_t fd_array;
++ /* buffer used in reg_type_str() to generate reg_type string */
++ char type_str_buf[TYPE_STR_BUF_LEN];
+ };
+
+ __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
+@@ -528,4 +539,18 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
+ u32 btf_id,
+ struct bpf_attach_target_info *tgt_info);
+
++#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0)
++
++/* extract base type from bpf_{arg, return, reg}_type. */
++static inline u32 base_type(u32 type)
++{
++ return type & BPF_BASE_TYPE_MASK;
++}
++
++/* extract flags from an extended type. See bpf_type_flag in bpf.h. */
++static inline u32 type_flag(u32 type)
++{
++ return type & ~BPF_BASE_TYPE_MASK;
++}
++
+ #endif /* _LINUX_BPF_VERIFIER_H */
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
new file mode 100644
index 0000000000000..a075b70b9a70c
@@ -131566,6 +200379,20 @@ index 0000000000000..a075b70b9a70c
+#endif /* CONFIG_ARCH_HAS_CC_PLATFORM */
+
+#endif /* _LINUX_CC_PLATFORM_H */
+diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
+index 83fa08a065071..787fff5ec7f58 100644
+--- a/include/linux/ceph/osd_client.h
++++ b/include/linux/ceph/osd_client.h
+@@ -287,6 +287,9 @@ struct ceph_osd_linger_request {
+ rados_watcherrcb_t errcb;
+ void *data;
+
++ struct ceph_pagelist *request_pl;
++ struct page **notify_id_pages;
++
+ struct page ***preply_pages;
+ size_t *preply_len;
+ };
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 3d5af56337bdb..0f7fd205ab7ea 100644
--- a/include/linux/compiler.h
@@ -131630,6 +200457,29 @@ index 20874db50bc8a..a97f277cfdfa3 100644
void *data;
struct console *next;
};
+diff --git a/include/linux/coredump.h b/include/linux/coredump.h
+index 78fcd776b185a..4b95e46d215f1 100644
+--- a/include/linux/coredump.h
++++ b/include/linux/coredump.h
+@@ -12,6 +12,8 @@ struct core_vma_metadata {
+ unsigned long start, end;
+ unsigned long flags;
+ unsigned long dump_size;
++ unsigned long pgoff;
++ struct file *file;
+ };
+
+ extern int core_uses_pid;
+@@ -29,9 +31,6 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
+ extern int dump_align(struct coredump_params *cprm, int align);
+ int dump_user_range(struct coredump_params *cprm, unsigned long start,
+ unsigned long len);
+-int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
+- struct core_vma_metadata **vma_meta,
+- size_t *vma_data_size_ptr);
+ extern void do_coredump(const kernel_siginfo_t *siginfo);
+ #else
+ static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ff88bb3e44fca..66a1f495f01a6 100644
--- a/include/linux/cpufreq.h
@@ -131643,6 +200493,26 @@ index ff88bb3e44fca..66a1f495f01a6 100644
if (ret < 0)
continue;
+diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
+index 991911048857a..c88ccc48877d6 100644
+--- a/include/linux/cpuhotplug.h
++++ b/include/linux/cpuhotplug.h
+@@ -99,6 +99,7 @@ enum cpuhp_state {
+ CPUHP_LUSTRE_CFS_DEAD,
+ CPUHP_AP_ARM_CACHE_B15_RAC_DEAD,
+ CPUHP_PADATA_DEAD,
++ CPUHP_RANDOM_PREPARE,
+ CPUHP_WORKQUEUE_PREP,
+ CPUHP_POWER_NUMA_PREPARE,
+ CPUHP_HRTIMERS_PREPARE,
+@@ -238,6 +239,7 @@ enum cpuhp_state {
+ CPUHP_AP_PERF_CSKY_ONLINE,
+ CPUHP_AP_WATCHDOG_ONLINE,
+ CPUHP_AP_WORKQUEUE_ONLINE,
++ CPUHP_AP_RANDOM_ONLINE,
+ CPUHP_AP_RCUTREE_ONLINE,
+ CPUHP_AP_BASE_CACHEINFO_ONLINE,
+ CPUHP_AP_ONLINE_DYN,
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 1d0e2ce6b6d9f..e8607992c68a5 100644
--- a/include/linux/delay.h
@@ -131730,6 +200600,29 @@ index 6b5d36babfcc4..3d8ddc5eca8ca 100644
+#endif
+
#endif /* _LINUX_EFI_H */
+diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
+index c58d504514854..7f28fa702bb72 100644
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -127,7 +127,7 @@ static inline bool is_multicast_ether_addr(const u8 *addr)
+ #endif
+ }
+
+-static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2])
++static inline bool is_multicast_ether_addr_64bits(const u8 *addr)
+ {
+ #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ #ifdef __BIG_ENDIAN
+@@ -364,8 +364,7 @@ static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
+ * Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits.
+ */
+
+-static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
+- const u8 addr2[6+2])
++static inline bool ether_addr_equal_64bits(const u8 *addr1, const u8 *addr2)
+ {
+ #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 849524b55d89a..3fad741df53ef 100644
--- a/include/linux/ethtool.h
@@ -131758,10 +200651,18 @@ index 1e7bf78cb3829..aba348d58ff61 100644
ETHNL_MCGRP_MONITOR,
};
diff --git a/include/linux/fb.h b/include/linux/fb.h
-index 5950f8f5dc74d..02f362c661c80 100644
+index 5950f8f5dc74d..3d7306c9a7065 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
-@@ -610,6 +610,7 @@ extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
+@@ -502,6 +502,7 @@ struct fb_info {
+ } *apertures;
+
+ bool skip_vt_switch; /* no VT switch on suspend/resume required */
++ bool forced_out; /* set when being removed by another driver */
+ };
+
+ static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
+@@ -610,6 +611,7 @@ extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
const char *name);
extern int remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
@@ -131945,6 +200846,60 @@ index 12d3a7d308ab9..a9477c14fad5c 100644
}
/*
+diff --git a/include/linux/genhd.h b/include/linux/genhd.h
+index 0f5315c2b5a34..0b48a0cf42624 100644
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -12,12 +12,10 @@
+
+ #include <linux/types.h>
+ #include <linux/kdev_t.h>
+-#include <linux/rcupdate.h>
+-#include <linux/slab.h>
+-#include <linux/percpu-refcount.h>
+ #include <linux/uuid.h>
+ #include <linux/blk_types.h>
+-#include <asm/local.h>
++#include <linux/device.h>
++#include <linux/xarray.h>
+
+ extern const struct device_type disk_type;
+ extern struct device_type part_type;
+@@ -26,14 +24,6 @@ extern struct class block_class;
+ #define DISK_MAX_PARTS 256
+ #define DISK_NAME_LEN 32
+
+-#include <linux/major.h>
+-#include <linux/device.h>
+-#include <linux/smp.h>
+-#include <linux/string.h>
+-#include <linux/fs.h>
+-#include <linux/workqueue.h>
+-#include <linux/xarray.h>
+-
+ #define PARTITION_META_INFO_VOLNAMELTH 64
+ /*
+ * Enough for the string representation of any kind of UUID plus NULL.
+diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
+index a0f9901dcae60..e3c29d2e68263 100644
+--- a/include/linux/gpio/driver.h
++++ b/include/linux/gpio/driver.h
+@@ -224,6 +224,15 @@ struct gpio_irq_chip {
+ unsigned long *valid_mask,
+ unsigned int ngpios);
+
++ /**
++ * @initialized:
++ *
++ * Flag to track GPIO chip irq member's initialization.
++ * This flag will make sure GPIO chip irq members are not used
++ * before they are initialized.
++ */
++ bool initialized;
++
+ /**
+ * @valid_mask:
+ *
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 9e067f937dbc2..26742ca14609a 100644
--- a/include/linux/hid.h
@@ -131970,6 +200925,30 @@ index 9e067f937dbc2..26742ca14609a 100644
#define PM_HINT_FULLON 1<<5
#define PM_HINT_NORMAL 1<<1
+diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
+index 8e6dd908da216..aa1d4da03538b 100644
+--- a/include/linux/hw_random.h
++++ b/include/linux/hw_random.h
+@@ -60,7 +60,5 @@ extern int devm_hwrng_register(struct device *dev, struct hwrng *rng);
+ /** Unregister a Hardware Random Number Generator driver. */
+ extern void hwrng_unregister(struct hwrng *rng);
+ extern void devm_hwrng_unregister(struct device *dve, struct hwrng *rng);
+-/** Feed random bits into the pool. */
+-extern void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy);
+
+ #endif /* LINUX_HWRANDOM_H_ */
+diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
+index b712217f70304..1ed52441972f9 100644
+--- a/include/linux/if_arp.h
++++ b/include/linux/if_arp.h
+@@ -52,6 +52,7 @@ static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
+ case ARPHRD_VOID:
+ case ARPHRD_NONE:
+ case ARPHRD_RAWIP:
++ case ARPHRD_PIMREG:
+ return false;
+ default:
+ return true;
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h
index 096f68dd2e0ca..4c69b144677b1 100644
--- a/include/linux/iio/trigger.h
@@ -132012,6 +200991,45 @@ index fa2cd8c63dcc9..24359b4a96053 100644
})
#define instrumentation_end() __instrumentation_end(__COUNTER__)
#else
+diff --git a/include/linux/iomap.h b/include/linux/iomap.h
+index 24f8489583ca7..829f2325ecbab 100644
+--- a/include/linux/iomap.h
++++ b/include/linux/iomap.h
+@@ -330,12 +330,19 @@ struct iomap_dio_ops {
+ */
+ #define IOMAP_DIO_OVERWRITE_ONLY (1 << 1)
+
++/*
++ * When a page fault occurs, return a partial synchronous result and allow
++ * the caller to retry the rest of the operation after dealing with the page
++ * fault.
++ */
++#define IOMAP_DIO_PARTIAL (1 << 2)
++
+ ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
+- unsigned int dio_flags);
++ unsigned int dio_flags, size_t done_before);
+ struct iomap_dio *__iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
+- unsigned int dio_flags);
++ unsigned int dio_flags, size_t done_before);
+ ssize_t iomap_dio_complete(struct iomap_dio *dio);
+ int iomap_dio_iopoll(struct kiocb *kiocb, bool spin);
+
+diff --git a/include/linux/ioport.h b/include/linux/ioport.h
+index 8359c50f99884..ec5f71f7135b0 100644
+--- a/include/linux/ioport.h
++++ b/include/linux/ioport.h
+@@ -262,6 +262,8 @@ resource_union(struct resource *r1, struct resource *r2, struct resource *r)
+ #define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED)
+ #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl)
+ #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
++#define request_mem_region_muxed(start, n, name) \
++ __request_region(&iomem_resource, (start), (n), (name), IORESOURCE_MUXED)
+ #define request_mem_region_exclusive(start,n,name) \
+ __request_region(&iomem_resource, (start), (n), (name), IORESOURCE_EXCLUSIVE)
+ #define rename_region(region, newname) do { (region)->name = (newname); } while (0)
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 05e22770af517..b75395ec8d521 100644
--- a/include/linux/ipc_namespace.h
@@ -132046,9 +201064,18 @@ index 05e22770af517..b75395ec8d521 100644
{
}
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
-index ef4a69865737c..07cba0b3496d5 100644
+index ef4a69865737c..d1f3864307959 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
+@@ -51,7 +51,7 @@ struct ipv6_devconf {
+ __s32 use_optimistic;
+ #endif
+ #ifdef CONFIG_IPV6_MROUTE
+- __s32 mc_forwarding;
++ atomic_t mc_forwarding;
+ #endif
+ __s32 disable_ipv6;
+ __s32 drop_unicast_in_l2_multicast;
@@ -132,6 +132,7 @@ struct inet6_skb_parm {
__u16 dsthao;
#endif
@@ -132105,6 +201132,19 @@ index dd874a1ee862a..f407e937241af 100644
static inline void kasan_free_shadow(const struct vm_struct *vm) {}
#endif /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 2776423a587e4..f56cd8879a594 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -277,7 +277,7 @@ static inline char *hex_byte_pack_upper(char *buf, u8 byte)
+ return buf;
+ }
+
+-extern int hex_to_bin(char ch);
++extern int hex_to_bin(unsigned char ch);
+ extern int __must_check hex2bin(u8 *dst, const char *src, size_t count);
+ extern char *bin2hex(char *dst, const void *src, size_t count);
+
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 44ae1a7eb9e39..69ae6b2784645 100644
--- a/include/linux/kernel_stat.h
@@ -132118,7 +201158,7 @@ index 44ae1a7eb9e39..69ae6b2784645 100644
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
static inline void account_process_tick(struct task_struct *tsk, int user)
diff --git a/include/linux/kfence.h b/include/linux/kfence.h
-index 3fe6dd8a18c19..4b5e3679a72c7 100644
+index 3fe6dd8a18c19..3c75209a545e1 100644
--- a/include/linux/kfence.h
+++ b/include/linux/kfence.h
@@ -14,6 +14,9 @@
@@ -132167,6 +201207,44 @@ index 3fe6dd8a18c19..4b5e3679a72c7 100644
}
/**
+@@ -201,6 +202,22 @@ static __always_inline __must_check bool kfence_free(void *addr)
+ */
+ bool __must_check kfence_handle_page_fault(unsigned long addr, bool is_write, struct pt_regs *regs);
+
++#ifdef CONFIG_PRINTK
++struct kmem_obj_info;
++/**
++ * __kfence_obj_info() - fill kmem_obj_info struct
++ * @kpp: kmem_obj_info to be filled
++ * @object: the object
++ *
++ * Return:
++ * * false - not a KFENCE object
++ * * true - a KFENCE object, filled @kpp
++ *
++ * Copies information to @kpp for KFENCE objects.
++ */
++bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page);
++#endif
++
+ #else /* CONFIG_KFENCE */
+
+ static inline bool is_kfence_address(const void *addr) { return false; }
+@@ -218,6 +235,14 @@ static inline bool __must_check kfence_handle_page_fault(unsigned long addr, boo
+ return false;
+ }
+
++#ifdef CONFIG_PRINTK
++struct kmem_obj_info;
++static inline bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++{
++ return false;
++}
++#endif
++
+ #endif
+
+ #endif /* _LINUX_KFENCE_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index e4f3bfe087570..ef8c7accbc689 100644
--- a/include/linux/kprobes.h
@@ -132413,6 +201491,29 @@ index 5c4c5c0602cb7..59024618554e2 100644
*
* @ptrace_access_check:
* Check permission before allowing the current process to trace the
+diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
+index 0661af17a7584..3038124c61154 100644
+--- a/include/linux/mc146818rtc.h
++++ b/include/linux/mc146818rtc.h
+@@ -86,6 +86,8 @@ struct cmos_rtc_board_info {
+ /* 2 values for divider stage reset, others for "testing purposes only" */
+ # define RTC_DIV_RESET1 0x60
+ # define RTC_DIV_RESET2 0x70
++ /* In AMD BKDG bit 5 and 6 are reserved, bit 4 is for select dv0 bank */
++# define RTC_AMD_BANK_SELECT 0x10
+ /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
+ # define RTC_RATE_SELECT 0x0F
+
+@@ -123,7 +125,8 @@ struct cmos_rtc_board_info {
+ #define RTC_IO_EXTENT_USED RTC_IO_EXTENT
+ #endif /* ARCH_RTC_LOCATION */
+
+-unsigned int mc146818_get_time(struct rtc_time *time);
++bool mc146818_does_rtc_work(void);
++int mc146818_get_time(struct rtc_time *time);
+ int mc146818_set_time(struct rtc_time *time);
+
+ #endif /* _MC146818RTC_H */
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 34de69b3b8bad..5df38332e4139 100644
--- a/include/linux/memblock.h
@@ -132429,7 +201530,7 @@ index 34de69b3b8bad..5df38332e4139 100644
return memblock_phys_alloc_range(size, align, 0,
MEMBLOCK_ALLOC_ACCESSIBLE);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
-index 3096c9a0ee014..d9b8df5ef212f 100644
+index 3096c9a0ee014..d35439db047cb 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -223,7 +223,7 @@ struct obj_cgroup {
@@ -132451,6 +201552,25 @@ index 3096c9a0ee014..d9b8df5ef212f 100644
#endif
MEMCG_PADDING(_pad2_);
+@@ -1001,6 +1002,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
+ }
+
+ void mem_cgroup_flush_stats(void);
++void mem_cgroup_flush_stats_delayed(void);
+
+ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
+ int val);
+@@ -1421,6 +1423,10 @@ static inline void mem_cgroup_flush_stats(void)
+ {
+ }
+
++static inline void mem_cgroup_flush_stats_delayed(void)
++{
++}
++
+ static inline void __mod_memcg_lruvec_state(struct lruvec *lruvec,
+ enum node_stat_item idx, int val)
+ {
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 7239858790353..a5cc4cdf9cc86 100644
--- a/include/linux/mhi.h
@@ -132496,7 +201616,7 @@ index 4ab5c1fc1270d..a09ed4c8361b6 100644
return MLX5_ESWITCH_NONE;
}
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
-index 993204a6c1a13..25d775764a5ac 100644
+index 993204a6c1a13..fdf4589ab4d48 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -3309,8 +3309,8 @@ enum {
@@ -132528,8 +201648,19 @@ index 993204a6c1a13..25d775764a5ac 100644
};
struct mlx5_ifc_modify_tir_out_bits {
+@@ -9508,8 +9508,8 @@ struct mlx5_ifc_bufferx_reg_bits {
+ u8 reserved_at_0[0x6];
+ u8 lossy[0x1];
+ u8 epsb[0x1];
+- u8 reserved_at_8[0xc];
+- u8 size[0xc];
++ u8 reserved_at_8[0x8];
++ u8 size[0x10];
+
+ u8 xoff_threshold[0x10];
+ u8 xon_threshold[0x10];
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 73a52aba448f9..90c2d7f3c7a88 100644
+index 73a52aba448f9..85205adcdd0d1 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1511,11 +1511,18 @@ static inline u8 page_kasan_tag(const struct page *page)
@@ -132556,8 +201687,26 @@ index 73a52aba448f9..90c2d7f3c7a88 100644
}
static inline void page_kasan_tag_reset(struct page *page)
+@@ -2600,6 +2607,7 @@ extern int install_special_mapping(struct mm_struct *mm,
+ unsigned long flags, struct page **pages);
+
+ unsigned long randomize_stack_top(unsigned long stack_top);
++unsigned long randomize_page(unsigned long start, unsigned long range);
+
+ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+
+@@ -2851,7 +2859,8 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
+ #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */
+ #define FOLL_NOWAIT 0x20 /* if a disk transfer is needed, start the IO
+ * and return without waiting upon it */
+-#define FOLL_POPULATE 0x40 /* fault in page */
++#define FOLL_POPULATE 0x40 /* fault in pages (with FOLL_MLOCK) */
++#define FOLL_NOFAULT 0x80 /* do not fault in pages */
+ #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */
+ #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */
+ #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
-index 6a1d79d84675a..fa1ef98614bcb 100644
+index 6a1d79d84675a..6ba1002165302 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1031,6 +1031,15 @@ static inline int is_highmem_idx(enum zone_type idx)
@@ -132576,6 +201725,27 @@ index 6a1d79d84675a..fa1ef98614bcb 100644
/**
* is_highmem - helper function to quickly check if a struct zone is a
* highmem zone or not. This is an attempt to keep references
+@@ -1342,13 +1351,16 @@ static inline unsigned long *section_to_usemap(struct mem_section *ms)
+
+ static inline struct mem_section *__nr_to_section(unsigned long nr)
+ {
++ unsigned long root = SECTION_NR_TO_ROOT(nr);
++
++ if (unlikely(root >= NR_SECTION_ROOTS))
++ return NULL;
++
+ #ifdef CONFIG_SPARSEMEM_EXTREME
+- if (!mem_section)
++ if (!mem_section || !mem_section[root])
+ return NULL;
+ #endif
+- if (!mem_section[SECTION_NR_TO_ROOT(nr)])
+- return NULL;
+- return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
++ return &mem_section[root][nr & SECTION_ROOT_MASK];
+ }
+ extern size_t mem_section_usage_size(void);
+
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 49cf6eb222e76..e616f94c7c585 100644
--- a/include/linux/msi.h
@@ -132589,11 +201759,44 @@ index 49cf6eb222e76..e616f94c7c585 100644
u8 is_64 : 1;
u8 is_virtual : 1;
u16 entry_nr;
+diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
+index 88227044fc86c..8a2c60235ebb8 100644
+--- a/include/linux/mtd/mtd.h
++++ b/include/linux/mtd/mtd.h
+@@ -394,10 +394,8 @@ struct mtd_info {
+ /* List of partitions attached to this MTD device */
+ struct list_head partitions;
+
+- union {
+- struct mtd_part part;
+- struct mtd_master master;
+- };
++ struct mtd_part part;
++ struct mtd_master master;
+ };
+
+ static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
-index b2f9dd3cbd695..5b88cd51fadb5 100644
+index b2f9dd3cbd695..dcf90144d70b7 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
-@@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
+@@ -1240,6 +1240,7 @@ struct nand_secure_region {
+ * @lock: Lock protecting the suspended field. Also used to serialize accesses
+ * to the NAND device
+ * @suspended: Set to 1 when the device is suspended, 0 when it's not
++ * @resume_wq: wait queue to sleep if rawnand is in suspended state.
+ * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
+ * should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
+ * NAND Controller drivers should not modify this value, but they're
+@@ -1294,6 +1295,7 @@ struct nand_chip {
+ /* Internals */
+ struct mutex lock;
+ unsigned int suspended : 1;
++ wait_queue_head_t resume_wq;
+ int cur_cs;
+ int read_retries;
+ struct nand_secure_region *secure_regions;
+@@ -1539,6 +1541,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
bool force_8bit, bool check_only);
int nand_write_data_op(struct nand_chip *chip, const void *buf,
unsigned int len, bool force_8bit);
@@ -132602,10 +201805,41 @@ index b2f9dd3cbd695..5b88cd51fadb5 100644
/* Scan and identify a NAND device */
int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,
+diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
+index 2c6b9e4162254..7c2d77d75a888 100644
+--- a/include/linux/netdev_features.h
++++ b/include/linux/netdev_features.h
+@@ -169,7 +169,7 @@ enum {
+ #define NETIF_F_HW_HSR_FWD __NETIF_F(HW_HSR_FWD)
+ #define NETIF_F_HW_HSR_DUP __NETIF_F(HW_HSR_DUP)
+
+-/* Finds the next feature with the highest number of the range of start till 0.
++/* Finds the next feature with the highest number of the range of start-1 till 0.
+ */
+ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
+ {
+@@ -188,7 +188,7 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
+ for ((bit) = find_next_netdev_feature((mask_addr), \
+ NETDEV_FEATURE_COUNT); \
+ (bit) >= 0; \
+- (bit) = find_next_netdev_feature((mask_addr), (bit) - 1))
++ (bit) = find_next_netdev_feature((mask_addr), (bit)))
+
+ /* Features valid for ethtool to change */
+ /* = all defined minus driver/device-class-related */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index d79163208dfdb..62ff094677762 100644
+index d79163208dfdb..39f1893ecac03 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
+@@ -887,7 +887,7 @@ struct net_device_path_stack {
+
+ struct net_device_path_ctx {
+ const struct net_device *dev;
+- const u8 *daddr;
++ u8 daddr[ETH_ALEN];
+
+ int num_vlans;
+ struct {
@@ -2149,7 +2149,7 @@ struct net_device {
struct netdev_queue *_tx ____cacheline_aligned_in_smp;
unsigned int num_tx_queues;
@@ -132671,10 +201905,63 @@ index d79163208dfdb..62ff094677762 100644
spin_unlock_bh(&txq->_xmit_lock);
}
+diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
+index 700ea077ce2d6..2770db2fa080d 100644
+--- a/include/linux/netfilter/nf_conntrack_common.h
++++ b/include/linux/netfilter/nf_conntrack_common.h
+@@ -2,7 +2,7 @@
+ #ifndef _NF_CONNTRACK_COMMON_H
+ #define _NF_CONNTRACK_COMMON_H
+
+-#include <linux/atomic.h>
++#include <linux/refcount.h>
+ #include <uapi/linux/netfilter/nf_conntrack_common.h>
+
+ struct ip_conntrack_stat {
+@@ -25,19 +25,21 @@ struct ip_conntrack_stat {
+ #define NFCT_PTRMASK ~(NFCT_INFOMASK)
+
+ struct nf_conntrack {
+- atomic_t use;
++ refcount_t use;
+ };
+
+ void nf_conntrack_destroy(struct nf_conntrack *nfct);
++
++/* like nf_ct_put, but without module dependency on nf_conntrack */
+ static inline void nf_conntrack_put(struct nf_conntrack *nfct)
+ {
+- if (nfct && atomic_dec_and_test(&nfct->use))
++ if (nfct && refcount_dec_and_test(&nfct->use))
+ nf_conntrack_destroy(nfct);
+ }
+ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
+ {
+ if (nfct)
+- atomic_inc(&nfct->use);
++ refcount_inc(&nfct->use);
+ }
+
+ #endif /* _NF_CONNTRACK_COMMON_H */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
-index b9a8b925db430..4a733f1409397 100644
+index b9a8b925db430..5ffcde9ac4130 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
+@@ -494,10 +494,10 @@ static inline const struct cred *nfs_file_cred(struct file *file)
+ * linux/fs/nfs/direct.c
+ */
+ extern ssize_t nfs_direct_IO(struct kiocb *, struct iov_iter *);
+-extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
+- struct iov_iter *iter);
+-extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
+- struct iov_iter *iter);
++ssize_t nfs_file_direct_read(struct kiocb *iocb,
++ struct iov_iter *iter, bool swap);
++ssize_t nfs_file_direct_write(struct kiocb *iocb,
++ struct iov_iter *iter, bool swap);
+
+ /*
+ * linux/fs/nfs/dir.c
@@ -517,8 +517,8 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh,
struct nfs_fattr *fattr, struct nfs4_label *label);
extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags);
@@ -132686,9 +201973,12 @@ index b9a8b925db430..4a733f1409397 100644
/*
* linux/fs/nfs/symlink.c
-@@ -569,6 +569,7 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
+@@ -567,8 +567,9 @@ extern int nfs_wb_all(struct inode *inode);
+ extern int nfs_wb_page(struct inode *inode, struct page *page);
+ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
extern int nfs_commit_inode(struct inode *, int);
- extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail);
+-extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail);
++extern struct nfs_commit_data *nfs_commitdata_alloc(void);
extern void nfs_commit_free(struct nfs_commit_data *data);
+bool nfs_commit_end(struct nfs_mds_commit_info *cinfo);
@@ -132717,6 +202007,18 @@ index e9698b6278a52..ecd74cc347974 100644
};
/*
+diff --git a/include/linux/nvme.h b/include/linux/nvme.h
+index b7c4c4130b65e..039f59ee8f435 100644
+--- a/include/linux/nvme.h
++++ b/include/linux/nvme.h
+@@ -322,6 +322,7 @@ enum {
+ NVME_CTRL_ONCS_TIMESTAMP = 1 << 6,
+ NVME_CTRL_VWC_PRESENT = 1 << 0,
+ NVME_CTRL_OACS_SEC_SUPP = 1 << 0,
++ NVME_CTRL_OACS_NS_MNGT_SUPP = 1 << 3,
+ NVME_CTRL_OACS_DIRECTIVES = 1 << 5,
+ NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8,
+ NVME_CTRL_LPA_CMD_EFFECTS_LOG = 1 << 1,
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 104505e9028f7..87932bdb25d7b 100644
--- a/include/linux/nvmem-provider.h
@@ -132772,8 +202074,90 @@ index daef3b0d9270d..55460ecfa50ad 100644
#include <linux/of.h>
struct net_device;
+diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
+index 62db6b0176b95..2f7dd14083d94 100644
+--- a/include/linux/pagemap.h
++++ b/include/linux/pagemap.h
+@@ -733,61 +733,11 @@ int wait_on_page_private_2_killable(struct page *page);
+ extern void add_page_wait_queue(struct page *page, wait_queue_entry_t *waiter);
+
+ /*
+- * Fault everything in given userspace address range in.
++ * Fault in userspace address range.
+ */
+-static inline int fault_in_pages_writeable(char __user *uaddr, size_t size)
+-{
+- char __user *end = uaddr + size - 1;
+-
+- if (unlikely(size == 0))
+- return 0;
+-
+- if (unlikely(uaddr > end))
+- return -EFAULT;
+- /*
+- * Writing zeroes into userspace here is OK, because we know that if
+- * the zero gets there, we'll be overwriting it.
+- */
+- do {
+- if (unlikely(__put_user(0, uaddr) != 0))
+- return -EFAULT;
+- uaddr += PAGE_SIZE;
+- } while (uaddr <= end);
+-
+- /* Check whether the range spilled into the next page. */
+- if (((unsigned long)uaddr & PAGE_MASK) ==
+- ((unsigned long)end & PAGE_MASK))
+- return __put_user(0, end);
+-
+- return 0;
+-}
+-
+-static inline int fault_in_pages_readable(const char __user *uaddr, size_t size)
+-{
+- volatile char c;
+- const char __user *end = uaddr + size - 1;
+-
+- if (unlikely(size == 0))
+- return 0;
+-
+- if (unlikely(uaddr > end))
+- return -EFAULT;
+-
+- do {
+- if (unlikely(__get_user(c, uaddr) != 0))
+- return -EFAULT;
+- uaddr += PAGE_SIZE;
+- } while (uaddr <= end);
+-
+- /* Check whether the range spilled into the next page. */
+- if (((unsigned long)uaddr & PAGE_MASK) ==
+- ((unsigned long)end & PAGE_MASK)) {
+- return __get_user(c, end);
+- }
+-
+- (void)c;
+- return 0;
+-}
++size_t fault_in_writeable(char __user *uaddr, size_t size);
++size_t fault_in_safe_writeable(const char __user *uaddr, size_t size);
++size_t fault_in_readable(const char __user *uaddr, size_t size);
+
+ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
+ pgoff_t index, gfp_t gfp_mask);
+diff --git a/include/linux/part_stat.h b/include/linux/part_stat.h
+index d2558121d48c0..6f7949b2fd8dc 100644
+--- a/include/linux/part_stat.h
++++ b/include/linux/part_stat.h
+@@ -3,6 +3,7 @@
+ #define _LINUX_PART_STAT_H
+
+ #include <linux/genhd.h>
++#include <asm/local.h>
+
+ struct disk_stats {
+ u64 nsecs[NR_STAT_GROUPS];
diff --git a/include/linux/pci.h b/include/linux/pci.h
-index cd8aa6fce2041..152a4d74f87f0 100644
+index cd8aa6fce2041..9d6e75222868f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -233,6 +233,8 @@ enum pci_dev_flags {
@@ -132785,6 +202169,14 @@ index cd8aa6fce2041..152a4d74f87f0 100644
};
enum pci_irq_reroute_variant {
+@@ -654,6 +656,7 @@ struct pci_bus {
+ struct bin_attribute *legacy_io; /* Legacy I/O for this bus */
+ struct bin_attribute *legacy_mem; /* Legacy mem */
+ unsigned int is_added:1;
++ unsigned int unsafe_warn:1; /* warned about RW1C config write */
+ };
+
+ #define to_pci_bus(n) container_of(n, struct pci_bus, dev)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 9b60bb89d86ab..6cce33e7e7acc 100644
--- a/include/linux/perf_event.h
@@ -132914,6 +202306,55 @@ index 00fef0064355f..5bbcd280bfd26 100644
static inline void posix_cputimers_init_work(void) { }
#endif
+diff --git a/include/linux/prandom.h b/include/linux/prandom.h
+index 056d31317e499..a4aadd2dc153e 100644
+--- a/include/linux/prandom.h
++++ b/include/linux/prandom.h
+@@ -10,6 +10,7 @@
+
+ #include <linux/types.h>
+ #include <linux/percpu.h>
++#include <linux/siphash.h>
+
+ u32 prandom_u32(void);
+ void prandom_bytes(void *buf, size_t nbytes);
+@@ -27,15 +28,10 @@ DECLARE_PER_CPU(unsigned long, net_rand_noise);
+ * The core SipHash round function. Each line can be executed in
+ * parallel given enough CPU resources.
+ */
+-#define PRND_SIPROUND(v0, v1, v2, v3) ( \
+- v0 += v1, v1 = rol64(v1, 13), v2 += v3, v3 = rol64(v3, 16), \
+- v1 ^= v0, v0 = rol64(v0, 32), v3 ^= v2, \
+- v0 += v3, v3 = rol64(v3, 21), v2 += v1, v1 = rol64(v1, 17), \
+- v3 ^= v0, v1 ^= v2, v2 = rol64(v2, 32) \
+-)
++#define PRND_SIPROUND(v0, v1, v2, v3) SIPHASH_PERMUTATION(v0, v1, v2, v3)
+
+-#define PRND_K0 (0x736f6d6570736575 ^ 0x6c7967656e657261)
+-#define PRND_K1 (0x646f72616e646f6d ^ 0x7465646279746573)
++#define PRND_K0 (SIPHASH_CONST_0 ^ SIPHASH_CONST_2)
++#define PRND_K1 (SIPHASH_CONST_1 ^ SIPHASH_CONST_3)
+
+ #elif BITS_PER_LONG == 32
+ /*
+@@ -43,14 +39,9 @@ DECLARE_PER_CPU(unsigned long, net_rand_noise);
+ * This is weaker, but 32-bit machines are not used for high-traffic
+ * applications, so there is less output for an attacker to analyze.
+ */
+-#define PRND_SIPROUND(v0, v1, v2, v3) ( \
+- v0 += v1, v1 = rol32(v1, 5), v2 += v3, v3 = rol32(v3, 8), \
+- v1 ^= v0, v0 = rol32(v0, 16), v3 ^= v2, \
+- v0 += v3, v3 = rol32(v3, 7), v2 += v1, v1 = rol32(v1, 13), \
+- v3 ^= v0, v1 ^= v2, v2 = rol32(v2, 16) \
+-)
+-#define PRND_K0 0x6c796765
+-#define PRND_K1 0x74656462
++#define PRND_SIPROUND(v0, v1, v2, v3) HSIPHASH_PERMUTATION(v0, v1, v2, v3)
++#define PRND_K0 (HSIPHASH_CONST_0 ^ HSIPHASH_CONST_2)
++#define PRND_K1 (HSIPHASH_CONST_1 ^ HSIPHASH_CONST_3)
+
+ #else
+ #error Unsupported BITS_PER_LONG
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 85b656f82d752..9497f6b983399 100644
--- a/include/linux/printk.h
@@ -133006,6 +202447,37 @@ index 0a23300d49af7..6f190002a2022 100644
};
struct psi_group {
+diff --git a/include/linux/pstore.h b/include/linux/pstore.h
+index eb93a54cff31f..e97a8188f0fd8 100644
+--- a/include/linux/pstore.h
++++ b/include/linux/pstore.h
+@@ -14,7 +14,7 @@
+ #include <linux/errno.h>
+ #include <linux/kmsg_dump.h>
+ #include <linux/mutex.h>
+-#include <linux/semaphore.h>
++#include <linux/spinlock.h>
+ #include <linux/time.h>
+ #include <linux/types.h>
+
+@@ -87,7 +87,7 @@ struct pstore_record {
+ * @owner: module which is responsible for this backend driver
+ * @name: name of the backend driver
+ *
+- * @buf_lock: semaphore to serialize access to @buf
++ * @buf_lock: spinlock to serialize access to @buf
+ * @buf: preallocated crash dump buffer
+ * @bufsize: size of @buf available for crash dump bytes (must match
+ * smallest number of bytes available for writing to a
+@@ -178,7 +178,7 @@ struct pstore_info {
+ struct module *owner;
+ const char *name;
+
+- struct semaphore buf_lock;
++ spinlock_t buf_lock;
+ char *buf;
+ size_t bufsize;
+
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 2e5565067355b..554454cb86931 100644
--- a/include/linux/ptp_clock_kernel.h
@@ -133033,6 +202505,202 @@ index 2e5565067355b..554454cb86931 100644
#endif
+diff --git a/include/linux/random.h b/include/linux/random.h
+index f45b8be3e3c4e..917470c4490ac 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -1,9 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * include/linux/random.h
+- *
+- * Include file for the random number generator.
+- */
++
+ #ifndef _LINUX_RANDOM_H
+ #define _LINUX_RANDOM_H
+
+@@ -14,41 +10,26 @@
+
+ #include <uapi/linux/random.h>
+
+-struct random_ready_callback {
+- struct list_head list;
+- void (*func)(struct random_ready_callback *rdy);
+- struct module *owner;
+-};
++struct notifier_block;
+
+-extern void add_device_randomness(const void *, unsigned int);
+-extern void add_bootloader_randomness(const void *, unsigned int);
++void add_device_randomness(const void *buf, size_t len);
++void add_bootloader_randomness(const void *buf, size_t len);
++void add_input_randomness(unsigned int type, unsigned int code,
++ unsigned int value) __latent_entropy;
++void add_interrupt_randomness(int irq) __latent_entropy;
++void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
+
+ #if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
+ static inline void add_latent_entropy(void)
+ {
+- add_device_randomness((const void *)&latent_entropy,
+- sizeof(latent_entropy));
++ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
+ }
+ #else
+-static inline void add_latent_entropy(void) {}
+-#endif
+-
+-extern void add_input_randomness(unsigned int type, unsigned int code,
+- unsigned int value) __latent_entropy;
+-extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
+-
+-extern void get_random_bytes(void *buf, int nbytes);
+-extern int wait_for_random_bytes(void);
+-extern int __init rand_initialize(void);
+-extern bool rng_is_initialized(void);
+-extern int add_random_ready_callback(struct random_ready_callback *rdy);
+-extern void del_random_ready_callback(struct random_ready_callback *rdy);
+-extern int __must_check get_random_bytes_arch(void *buf, int nbytes);
+-
+-#ifndef MODULE
+-extern const struct file_operations random_fops, urandom_fops;
++static inline void add_latent_entropy(void) { }
+ #endif
+
++void get_random_bytes(void *buf, size_t len);
++size_t __must_check get_random_bytes_arch(void *buf, size_t len);
+ u32 get_random_u32(void);
+ u64 get_random_u64(void);
+ static inline unsigned int get_random_int(void)
+@@ -80,36 +61,38 @@ static inline unsigned long get_random_long(void)
+
+ static inline unsigned long get_random_canary(void)
+ {
+- unsigned long val = get_random_long();
+-
+- return val & CANARY_MASK;
++ return get_random_long() & CANARY_MASK;
+ }
+
++int __init random_init(const char *command_line);
++bool rng_is_initialized(void);
++int wait_for_random_bytes(void);
++int register_random_ready_notifier(struct notifier_block *nb);
++int unregister_random_ready_notifier(struct notifier_block *nb);
++
+ /* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes).
+ * Returns the result of the call to wait_for_random_bytes. */
+-static inline int get_random_bytes_wait(void *buf, int nbytes)
++static inline int get_random_bytes_wait(void *buf, size_t nbytes)
+ {
+ int ret = wait_for_random_bytes();
+ get_random_bytes(buf, nbytes);
+ return ret;
+ }
+
+-#define declare_get_random_var_wait(var) \
+- static inline int get_random_ ## var ## _wait(var *out) { \
++#define declare_get_random_var_wait(name, ret_type) \
++ static inline int get_random_ ## name ## _wait(ret_type *out) { \
+ int ret = wait_for_random_bytes(); \
+ if (unlikely(ret)) \
+ return ret; \
+- *out = get_random_ ## var(); \
++ *out = get_random_ ## name(); \
+ return 0; \
+ }
+-declare_get_random_var_wait(u32)
+-declare_get_random_var_wait(u64)
+-declare_get_random_var_wait(int)
+-declare_get_random_var_wait(long)
++declare_get_random_var_wait(u32, u32)
++declare_get_random_var_wait(u64, u32)
++declare_get_random_var_wait(int, unsigned int)
++declare_get_random_var_wait(long, unsigned long)
+ #undef declare_get_random_var
+
+-unsigned long randomize_page(unsigned long start, unsigned long range);
+-
+ /*
+ * This is designed to be standalone for just prandom
+ * users, but for now we include it from <linux/random.h>
+@@ -120,22 +103,10 @@ unsigned long randomize_page(unsigned long start, unsigned long range);
+ #ifdef CONFIG_ARCH_RANDOM
+ # include <asm/archrandom.h>
+ #else
+-static inline bool __must_check arch_get_random_long(unsigned long *v)
+-{
+- return false;
+-}
+-static inline bool __must_check arch_get_random_int(unsigned int *v)
+-{
+- return false;
+-}
+-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;
+-}
++static inline bool __must_check arch_get_random_long(unsigned long *v) { return false; }
++static inline bool __must_check arch_get_random_int(unsigned int *v) { return false; }
++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
+
+ /*
+@@ -158,4 +129,13 @@ static inline bool __init arch_get_random_long_early(unsigned long *v)
+ }
+ #endif
+
++#ifdef CONFIG_SMP
++int random_prepare_cpu(unsigned int cpu);
++int random_online_cpu(unsigned int cpu);
++#endif
++
++#ifndef MODULE
++extern const struct file_operations random_fops, urandom_fops;
++#endif
++
+ #endif /* _LINUX_RANDOM_H */
+diff --git a/include/linux/randomize_kstack.h b/include/linux/randomize_kstack.h
+index bebc911161b6f..d373f1bcbf7ca 100644
+--- a/include/linux/randomize_kstack.h
++++ b/include/linux/randomize_kstack.h
+@@ -16,8 +16,20 @@ DECLARE_PER_CPU(u32, kstack_offset);
+ * alignment. Also, since this use is being explicitly masked to a max of
+ * 10 bits, stack-clash style attacks are unlikely. For more details see
+ * "VLAs" in Documentation/process/deprecated.rst
++ *
++ * The normal __builtin_alloca() is initialized with INIT_STACK_ALL (currently
++ * only with Clang and not GCC). Initializing the unused area on each syscall
++ * entry is expensive, and generating an implicit call to memset() may also be
++ * problematic (such as in noinstr functions). Therefore, if the compiler
++ * supports it (which it should if it initializes allocas), always use the
++ * "uninitialized" variant of the builtin.
+ */
+-void *__builtin_alloca(size_t size);
++#if __has_builtin(__builtin_alloca_uninitialized)
++#define __kstack_alloca __builtin_alloca_uninitialized
++#else
++#define __kstack_alloca __builtin_alloca
++#endif
++
+ /*
+ * Use, at most, 10 bits of entropy. We explicitly cap this to keep the
+ * "VLA" from being unbounded (see above). 10 bits leaves enough room for
+@@ -36,7 +48,7 @@ void *__builtin_alloca(size_t size);
+ if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
+ &randomize_kstack_offset)) { \
+ u32 offset = raw_cpu_read(kstack_offset); \
+- u8 *ptr = __builtin_alloca(KSTACK_OFFSET_MAX(offset)); \
++ u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \
+ /* Keep allocation even after "ptr" loses scope. */ \
+ asm volatile("" :: "r"(ptr) : "memory"); \
+ } \
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index d97dcd049f18f..a8dcf8a9ae885 100644
--- a/include/linux/rpmsg.h
@@ -133047,10 +202715,33 @@ index d97dcd049f18f..a8dcf8a9ae885 100644
static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
diff --git a/include/linux/sched.h b/include/linux/sched.h
-index c1a927ddec646..76e8695506465 100644
+index c1a927ddec646..ad7ff332a0ac8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -1675,7 +1675,6 @@ extern struct pid *cad_pid;
+@@ -1436,6 +1436,7 @@ struct task_struct {
+ int pagefault_disabled;
+ #ifdef CONFIG_MMU
+ struct task_struct *oom_reaper_list;
++ struct timer_list oom_reaper_timer;
+ #endif
+ #ifdef CONFIG_VMAP_STACK
+ struct vm_struct *stack_vm_area;
+@@ -1626,6 +1627,14 @@ static inline unsigned int task_state_index(struct task_struct *tsk)
+ if (tsk_state == TASK_IDLE)
+ state = TASK_REPORT_IDLE;
+
++ /*
++ * We're lying here, but rather than expose a completely new task state
++ * to userspace, we can make this appear as if the task has gone through
++ * a regular rt_mutex_lock() call.
++ */
++ if (tsk_state == TASK_RTLOCK_WAIT)
++ state = TASK_UNINTERRUPTIBLE;
++
+ return fls(state);
+ }
+
+@@ -1675,7 +1684,6 @@ extern struct pid *cad_pid;
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_NPROC_EXCEEDED 0x00001000 /* set_user() noticed that RLIMIT_NPROC was exceeded */
#define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */
@@ -133058,6 +202749,25 @@ index c1a927ddec646..76e8695506465 100644
#define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */
#define PF_FROZEN 0x00010000 /* Frozen for system suspend */
#define PF_KSWAPD 0x00020000 /* I am kswapd */
+diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
+index 5561486fddef7..95fb7aaaec8de 100644
+--- a/include/linux/sched/mm.h
++++ b/include/linux/sched/mm.h
+@@ -106,6 +106,14 @@ static inline void mm_update_next_owner(struct mm_struct *mm)
+ #endif /* CONFIG_MEMCG */
+
+ #ifdef CONFIG_MMU
++#ifndef arch_get_mmap_end
++#define arch_get_mmap_end(addr) (TASK_SIZE)
++#endif
++
++#ifndef arch_get_mmap_base
++#define arch_get_mmap_base(addr, base) (base)
++#endif
++
+ extern void arch_pick_mmap_layout(struct mm_struct *mm,
+ struct rlimit *rlim_stack);
+ extern unsigned long
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index e5f4ce622ee61..9a707b555b0a0 100644
--- a/include/linux/sched/signal.h
@@ -133109,10 +202819,23 @@ index 2413427e439c7..d10150587d819 100644
#elif !defined(__HAVE_THREAD_FUNCTIONS)
diff --git a/include/linux/security.h b/include/linux/security.h
-index 5b7288521300b..46a02ce34d00b 100644
+index 5b7288521300b..da184e7b361f4 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
-@@ -258,13 +258,13 @@ extern int security_init(void);
+@@ -121,10 +121,12 @@ enum lockdown_reason {
+ LOCKDOWN_DEBUGFS,
+ LOCKDOWN_XMON_WR,
+ LOCKDOWN_BPF_WRITE_USER,
++ LOCKDOWN_DBG_WRITE_KERNEL,
+ LOCKDOWN_INTEGRITY_MAX,
+ LOCKDOWN_KCORE,
+ LOCKDOWN_KPROBES,
+ LOCKDOWN_BPF_READ_KERNEL,
++ LOCKDOWN_DBG_READ_KERNEL,
+ LOCKDOWN_PERF,
+ LOCKDOWN_TRACEFS,
+ LOCKDOWN_XMON_RW,
+@@ -258,13 +260,13 @@ extern int security_init(void);
extern int early_security_init(void);
/* Security operations */
@@ -133133,7 +202856,7 @@ index 5b7288521300b..46a02ce34d00b 100644
int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
int security_ptrace_traceme(struct task_struct *parent);
int security_capget(struct task_struct *target,
-@@ -508,25 +508,25 @@ static inline int early_security_init(void)
+@@ -508,25 +510,25 @@ static inline int early_security_init(void)
return 0;
}
@@ -133166,7 +202889,7 @@ index 5b7288521300b..46a02ce34d00b 100644
struct file *file)
{
return 0;
-@@ -1041,6 +1041,11 @@ static inline void security_transfer_creds(struct cred *new,
+@@ -1041,6 +1043,11 @@ static inline void security_transfer_creds(struct cred *new,
{
}
@@ -133191,6 +202914,19 @@ index dd99569595fd3..5733890df64f5 100644
} \
\
static const struct proc_ops __name ## _proc_ops = { \
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index c58cc142d23f4..8c32935e1059d 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -458,6 +458,8 @@ extern void uart_handle_cts_change(struct uart_port *uport,
+ extern void uart_insert_char(struct uart_port *port, unsigned int status,
+ unsigned int overrun, unsigned int ch, unsigned int flag);
+
++void uart_xchar_out(struct uart_port *uport, int offset);
++
+ #ifdef CONFIG_MAGIC_SYSRQ_SERIAL
+ #define SYSRQ_TIMEOUT (HZ * 5)
+
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index 34cb28b8f16ca..a70b2bdbf4d96 100644
--- a/include/linux/signal_types.h
@@ -133206,7 +202942,7 @@ index 34cb28b8f16ca..a70b2bdbf4d96 100644
#ifdef SA_RESTORER
#define __ARCH_UAPI_SA_FLAGS SA_RESTORER
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
-index bf21591a9e5e6..0cda61855d907 100644
+index bf21591a9e5e6..0bb5ecd507bef 100644
--- a/include/linux/siphash.h
+++ b/include/linux/siphash.h
@@ -27,9 +27,7 @@ static inline bool siphash_key_is_zero(const siphash_key_t *key)
@@ -133243,7 +202979,7 @@ index bf21591a9e5e6..0cda61855d907 100644
u32 hsiphash_1u32(const u32 a, const hsiphash_key_t *key);
u32 hsiphash_2u32(const u32 a, const u32 b, const hsiphash_key_t *key);
-@@ -135,10 +130,9 @@ static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len,
+@@ -135,11 +130,38 @@ static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len,
static inline u32 hsiphash(const void *data, size_t len,
const hsiphash_key_t *key)
{
@@ -133256,8 +202992,37 @@ index bf21591a9e5e6..0cda61855d907 100644
return ___hsiphash_aligned(data, len, key);
}
++/*
++ * These macros expose the raw SipHash and HalfSipHash permutations.
++ * Do not use them directly! If you think you have a use for them,
++ * be sure to CC the maintainer of this file explaining why.
++ */
++
++#define SIPHASH_PERMUTATION(a, b, c, d) ( \
++ (a) += (b), (b) = rol64((b), 13), (b) ^= (a), (a) = rol64((a), 32), \
++ (c) += (d), (d) = rol64((d), 16), (d) ^= (c), \
++ (a) += (d), (d) = rol64((d), 21), (d) ^= (a), \
++ (c) += (b), (b) = rol64((b), 17), (b) ^= (c), (c) = rol64((c), 32))
++
++#define SIPHASH_CONST_0 0x736f6d6570736575ULL
++#define SIPHASH_CONST_1 0x646f72616e646f6dULL
++#define SIPHASH_CONST_2 0x6c7967656e657261ULL
++#define SIPHASH_CONST_3 0x7465646279746573ULL
++
++#define HSIPHASH_PERMUTATION(a, b, c, d) ( \
++ (a) += (b), (b) = rol32((b), 5), (b) ^= (a), (a) = rol32((a), 16), \
++ (c) += (d), (d) = rol32((d), 8), (d) ^= (c), \
++ (a) += (d), (d) = rol32((d), 7), (d) ^= (a), \
++ (c) += (b), (b) = rol32((b), 13), (b) ^= (c), (c) = rol32((c), 16))
++
++#define HSIPHASH_CONST_0 0U
++#define HSIPHASH_CONST_1 0U
++#define HSIPHASH_CONST_2 0x6c796765U
++#define HSIPHASH_CONST_3 0x74656462U
++
+ #endif /* _LINUX_SIPHASH_H */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index 841e2f0f5240b..532f5d402f060 100644
+index 841e2f0f5240b..e213acaa91ecc 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -286,7 +286,10 @@ struct nf_bridge_info {
@@ -133281,23 +203046,47 @@ index 841e2f0f5240b..532f5d402f060 100644
void
skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
-@@ -1671,6 +1674,22 @@ static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
+@@ -1433,6 +1436,11 @@ static inline unsigned int skb_end_offset(const struct sk_buff *skb)
+ {
+ return skb->end;
+ }
++
++static inline void skb_set_end_offset(struct sk_buff *skb, unsigned int offset)
++{
++ skb->end = offset;
++}
+ #else
+ static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
+ {
+@@ -1443,6 +1451,11 @@ static inline unsigned int skb_end_offset(const struct sk_buff *skb)
+ {
+ return skb->end - skb->head;
+ }
++
++static inline void skb_set_end_offset(struct sk_buff *skb, unsigned int offset)
++{
++ skb->end = skb->head + offset;
++}
+ #endif
+
+ /* Internal */
+@@ -1671,6 +1684,22 @@ static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
return 0;
}
-+/* This variant of skb_unclone() makes sure skb->truesize is not changed */
++/* This variant of skb_unclone() makes sure skb->truesize
++ * and skb_end_offset() are not changed, whenever a new skb->head is needed.
++ *
++ * Indeed there is no guarantee that ksize(kmalloc(X)) == ksize(kmalloc(X))
++ * when various debugging features are in place.
++ */
++int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri);
+static inline int skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri)
+{
+ might_sleep_if(gfpflags_allow_blocking(pri));
+
-+ if (skb_cloned(skb)) {
-+ unsigned int save = skb->truesize;
-+ int res;
-+
-+ res = pskb_expand_head(skb, 0, 0, pri);
-+ skb->truesize = save;
-+ return res;
-+ }
++ if (skb_cloned(skb))
++ return __skb_unclone_keeptruesize(skb, pri);
+ return 0;
+}
+
@@ -133305,10 +203094,36 @@ index 841e2f0f5240b..532f5d402f060 100644
* skb_header_cloned - is the header a clone
* @skb: buffer to check
diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
-index 1ce9a9eb223b6..b4256847c7079 100644
+index 1ce9a9eb223b6..73bedd128d529 100644
--- a/include/linux/skmsg.h
+++ b/include/linux/skmsg.h
-@@ -509,8 +509,22 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
+@@ -310,21 +310,16 @@ static inline void sock_drop(struct sock *sk, struct sk_buff *skb)
+ kfree_skb(skb);
+ }
+
+-static inline void drop_sk_msg(struct sk_psock *psock, struct sk_msg *msg)
+-{
+- if (msg->skb)
+- sock_drop(psock->sk, msg->skb);
+- kfree(msg);
+-}
+-
+ static inline void sk_psock_queue_msg(struct sk_psock *psock,
+ struct sk_msg *msg)
+ {
+ spin_lock_bh(&psock->ingress_lock);
+ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+ list_add_tail(&msg->list, &psock->ingress_msg);
+- else
+- drop_sk_msg(psock, msg);
++ else {
++ sk_msg_free(psock->sk, msg);
++ kfree(msg);
++ }
+ spin_unlock_bh(&psock->ingress_lock);
+ }
+
+@@ -509,8 +504,22 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
#if IS_ENABLED(CONFIG_NET_SOCK_MSG)
@@ -133333,8 +203148,106 @@ index 1ce9a9eb223b6..b4256847c7079 100644
static inline bool skb_bpf_ingress(const struct sk_buff *skb)
{
+diff --git a/include/linux/soc/qcom/qcom_aoss.h b/include/linux/soc/qcom/qcom_aoss.h
+new file mode 100644
+index 0000000000000..3c2a82e606f81
+--- /dev/null
++++ b/include/linux/soc/qcom/qcom_aoss.h
+@@ -0,0 +1,38 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
++ */
++
++#ifndef __QCOM_AOSS_H__
++#define __QCOM_AOSS_H__
++
++#include <linux/err.h>
++#include <linux/device.h>
++
++struct qmp;
++
++#if IS_ENABLED(CONFIG_QCOM_AOSS_QMP)
++
++int qmp_send(struct qmp *qmp, const void *data, size_t len);
++struct qmp *qmp_get(struct device *dev);
++void qmp_put(struct qmp *qmp);
++
++#else
++
++static inline int qmp_send(struct qmp *qmp, const void *data, size_t len)
++{
++ return -ENODEV;
++}
++
++static inline struct qmp *qmp_get(struct device *dev)
++{
++ return ERR_PTR(-ENODEV);
++}
++
++static inline void qmp_put(struct qmp *qmp)
++{
++}
++
++#endif
++
++#endif
+diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
+index 0aad7009b50e6..bd0d11af76c5e 100644
+--- a/include/linux/soc/ti/ti_sci_protocol.h
++++ b/include/linux/soc/ti/ti_sci_protocol.h
+@@ -645,7 +645,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
+
+ static inline struct ti_sci_resource *
+ devm_ti_sci_get_resource(const struct ti_sci_handle *handle, struct device *dev,
+- u32 dev_id, u32 sub_type);
++ u32 dev_id, u32 sub_type)
+ {
+ return ERR_PTR(-EINVAL);
+ }
+diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
+index 6bb4bc1a5f545..22919a94ca19d 100644
+--- a/include/linux/stackdepot.h
++++ b/include/linux/stackdepot.h
+@@ -19,8 +19,6 @@ depot_stack_handle_t stack_depot_save(unsigned long *entries,
+ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
+ unsigned long **entries);
+
+-unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries);
+-
+ #ifdef CONFIG_STACKDEPOT
+ int stack_depot_init(void);
+ #else
+diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
+index 9edecb494e9e2..bef158815e83d 100644
+--- a/include/linux/stacktrace.h
++++ b/include/linux/stacktrace.h
+@@ -21,6 +21,7 @@ unsigned int stack_trace_save_tsk(struct task_struct *task,
+ unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
+ unsigned int size, unsigned int skipnr);
+ unsigned int stack_trace_save_user(unsigned long *store, unsigned int size);
++unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries);
+
+ /* Internal interfaces. Do not use in generic code */
+ #ifdef CONFIG_ARCH_STACKWALK
+diff --git a/include/linux/static_call.h b/include/linux/static_call.h
+index 3e56a9751c062..fcc5b48989b3c 100644
+--- a/include/linux/static_call.h
++++ b/include/linux/static_call.h
+@@ -248,10 +248,7 @@ static inline int static_call_text_reserved(void *start, void *end)
+ return 0;
+ }
+
+-static inline long __static_call_return0(void)
+-{
+- return 0;
+-}
++extern long __static_call_return0(void);
+
+ #define EXPORT_STATIC_CALL(name) \
+ EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
-index a6f03b36fc4f7..1450397fc0bcd 100644
+index a6f03b36fc4f7..48d015ed21752 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -233,6 +233,7 @@ struct plat_stmmacenet_data {
@@ -133345,6 +203258,13 @@ index a6f03b36fc4f7..1450397fc0bcd 100644
void *bsp_priv;
struct clk *stmmac_clk;
struct clk *pclk;
+@@ -268,5 +269,6 @@ struct plat_stmmacenet_data {
+ int msi_rx_base_vec;
+ int msi_tx_base_vec;
+ bool use_phy_wol;
++ bool sph_disable;
+ };
+ #endif
diff --git a/include/linux/string.h b/include/linux/string.h
index 5e96d656be7ae..d68097b4f600b 100644
--- a/include/linux/string.h
@@ -133375,11 +203295,31 @@ index 5e96d656be7ae..d68097b4f600b 100644
/**
* str_has_prefix - Test if a string has a given prefix
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index a4661646adc9c..9fcf5ffc4f9ad 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -159,6 +159,7 @@ struct rpc_add_xprt_test {
+ #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
+ #define RPC_CLNT_CREATE_SOFTERR (1UL << 10)
+ #define RPC_CLNT_CREATE_REUSEPORT (1UL << 11)
++#define RPC_CLNT_CREATE_CONNECTED (1UL << 12)
+
+ struct rpc_clnt *rpc_create(struct rpc_create_args *args);
+ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
-index 064c96157d1f0..6263410c948a0 100644
+index 064c96157d1f0..01f09adccc63c 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
-@@ -532,8 +532,7 @@ int svc_encode_result_payload(struct svc_rqst *rqstp,
+@@ -384,6 +384,7 @@ struct svc_deferred_req {
+ size_t addrlen;
+ struct sockaddr_storage daddr; /* where reply must come from */
+ size_t daddrlen;
++ void *xprt_ctxt;
+ struct cache_deferred_req handle;
+ size_t xprt_hlen;
+ int argslen;
+@@ -532,8 +533,7 @@ int svc_encode_result_payload(struct svc_rqst *rqstp,
unsigned int offset,
unsigned int length);
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
@@ -133389,6 +203329,30 @@ index 064c96157d1f0..6263410c948a0 100644
char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
struct kvec *first, void *p,
size_t total);
+diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
+index b519609af1d02..4417f667c757e 100644
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -731,6 +731,8 @@ xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
+
+ if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
+ return -EBADMSG;
++ if (len > SIZE_MAX / sizeof(*p))
++ return -EBADMSG;
+ p = xdr_inline_decode(xdr, len * sizeof(*p));
+ if (unlikely(!p))
+ return -EBADMSG;
+diff --git a/include/linux/sunrpc/xprtsock.h b/include/linux/sunrpc/xprtsock.h
+index 8c2a712cb2420..689062afdd610 100644
+--- a/include/linux/sunrpc/xprtsock.h
++++ b/include/linux/sunrpc/xprtsock.h
+@@ -89,5 +89,6 @@ struct sock_xprt {
+ #define XPRT_SOCK_WAKE_WRITE (5)
+ #define XPRT_SOCK_WAKE_PENDING (6)
+ #define XPRT_SOCK_WAKE_DISCONNECT (7)
++#define XPRT_SOCK_CONNECT_SENT (8)
+
+ #endif /* _LINUX_SUNRPC_XPRTSOCK_H */
diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
index 068e1982ad371..74bfdffaf7b0e 100644
--- a/include/linux/surface_aggregator/controller.h
@@ -133450,6 +203414,20 @@ index 8af13ba60c7e4..4bcd65679cee0 100644
extern bool pm_get_wakeup_count(unsigned int *count, bool block);
extern bool pm_save_wakeup_count(unsigned int count);
extern void pm_wakep_autosleep_enabled(bool set);
+diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
+index b0cb2a9973f49..569272871375c 100644
+--- a/include/linux/swiotlb.h
++++ b/include/linux/swiotlb.h
+@@ -45,7 +45,8 @@ extern void __init swiotlb_update_mem_attributes(void);
+
+ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys,
+ size_t mapping_size, size_t alloc_size,
+- enum dma_data_direction dir, unsigned long attrs);
++ unsigned int alloc_aligned_mask, enum dma_data_direction dir,
++ unsigned long attrs);
+
+ extern void swiotlb_tbl_unmap_single(struct device *hwdev,
+ phys_addr_t tlb_addr,
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 3ebfea0781f10..38b701b7af4cf 100644
--- a/include/linux/tee_drv.h
@@ -133491,6 +203469,35 @@ index 3ebfea0781f10..38b701b7af4cf 100644
+void teedev_close_context(struct tee_context *ctx);
+
#endif /*__TEE_DRV_H*/
+diff --git a/include/linux/timex.h b/include/linux/timex.h
+index 059b18eb1f1fa..3871b06bd302c 100644
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -62,6 +62,8 @@
+ #include <linux/types.h>
+ #include <linux/param.h>
+
++unsigned long random_get_entropy_fallback(void);
++
+ #include <asm/timex.h>
+
+ #ifndef random_get_entropy
+@@ -74,8 +76,14 @@
+ *
+ * By default we use get_cycles() for this purpose, but individual
+ * architectures may override this in their asm/timex.h header file.
++ * If a given arch does not have get_cycles(), then we fallback to
++ * using random_get_entropy_fallback().
+ */
+-#define random_get_entropy() get_cycles()
++#ifdef get_cycles
++#define random_get_entropy() ((unsigned long)get_cycles())
++#else
++#define random_get_entropy() random_get_entropy_fallback()
++#endif
+ #endif
+
+ /*
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index aa11fe323c56b..12d827734686d 100644
--- a/include/linux/tpm.h
@@ -133516,6 +203523,28 @@ index 3e475eeb5a995..57113190448c6 100644
enum event_trigger_type {
ETT_NONE = (0),
+diff --git a/include/linux/uio.h b/include/linux/uio.h
+index 207101a9c5c32..6350354f97e90 100644
+--- a/include/linux/uio.h
++++ b/include/linux/uio.h
+@@ -35,6 +35,7 @@ struct iov_iter_state {
+
+ struct iov_iter {
+ u8 iter_type;
++ bool nofault;
+ bool data_source;
+ size_t iov_offset;
+ size_t count;
+@@ -133,7 +134,8 @@ size_t copy_page_from_iter_atomic(struct page *page, unsigned offset,
+ size_t bytes, struct iov_iter *i);
+ void iov_iter_advance(struct iov_iter *i, size_t bytes);
+ void iov_iter_revert(struct iov_iter *i, size_t bytes);
+-int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes);
++size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t bytes);
++size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t bytes);
+ size_t iov_iter_single_seg_count(const struct iov_iter *i);
+ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
+ struct iov_iter *i);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 2c1fc9212cf28..548a028f2dabb 100644
--- a/include/linux/usb/hcd.h
@@ -133553,6 +203582,64 @@ index 031f148ab3734..b5deafd91f67b 100644
static inline struct usb_role_switch *
usb_role_switch_register(struct device *parent,
const struct usb_role_switch_desc *desc)
+diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
+index ef9a44b6cf5d5..6e5db4edc3359 100644
+--- a/include/linux/vfio_pci_core.h
++++ b/include/linux/vfio_pci_core.h
+@@ -133,6 +133,8 @@ struct vfio_pci_core_device {
+ struct mutex ioeventfds_lock;
+ struct list_head ioeventfds_list;
+ struct vfio_pci_vf_token *vf_token;
++ struct list_head sriov_pfs_item;
++ struct vfio_pci_core_device *sriov_pf_core_dev;
+ struct notifier_block nb;
+ struct mutex vma_lock;
+ struct list_head vma_list;
+@@ -159,8 +161,17 @@ extern ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
+ extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite);
+
++#ifdef CONFIG_VFIO_PCI_VGA
+ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite);
++#else
++static inline ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev,
++ char __user *buf, size_t count,
++ loff_t *ppos, bool iswrite)
++{
++ return -EINVAL;
++}
++#endif
+
+ extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
+ uint64_t data, int count, int fd);
+diff --git a/include/linux/virtio.h b/include/linux/virtio.h
+index 41edbc01ffa40..1af8d65d4c8f7 100644
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -133,7 +133,6 @@ bool is_virtio_device(struct device *dev);
+ void virtio_break_device(struct virtio_device *dev);
+
+ void virtio_config_changed(struct virtio_device *dev);
+-int virtio_finalize_features(struct virtio_device *dev);
+ #ifdef CONFIG_PM_SLEEP
+ int virtio_device_freeze(struct virtio_device *dev);
+ int virtio_device_restore(struct virtio_device *dev);
+diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
+index 8519b3ae5d52e..b341dd62aa4da 100644
+--- a/include/linux/virtio_config.h
++++ b/include/linux/virtio_config.h
+@@ -62,8 +62,9 @@ struct virtio_shm_region {
+ * Returns the first 64 feature bits (all we currently need).
+ * @finalize_features: confirm what device features we'll be using.
+ * vdev: the virtio_device
+- * This gives the final feature bits for the device: it can change
++ * This sends the driver feature bits to the device: it can change
+ * the dev->feature bits if it wants.
++ * Note: despite the name this can be called any number of times.
+ * Returns 0 on success or error status
+ * @bus_name: return the bus name associated with the device (optional)
+ * vdev: the virtio_device
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index b465f8f3e554f..a960de68ac69e 100644
--- a/include/linux/virtio_net.h
@@ -133679,6 +203766,20 @@ index 93dab0e9580f8..d22cf2985b8fd 100644
#define ___wait_cond_timeout(condition) \
({ \
bool __cond = (condition); \
+diff --git a/include/linux/watch_queue.h b/include/linux/watch_queue.h
+index c994d1b2cdbaa..3b9a40ae8bdba 100644
+--- a/include/linux/watch_queue.h
++++ b/include/linux/watch_queue.h
+@@ -28,7 +28,8 @@ struct watch_type_filter {
+ struct watch_filter {
+ union {
+ struct rcu_head rcu;
+- unsigned long type_filter[2]; /* Bitmask of accepted types */
++ /* Bitmask of accepted types */
++ DECLARE_BITMAP(type_filter, WATCH_TYPE__NR);
+ };
+ u32 nr_filters; /* Number of filters */
+ struct watch_type_filter filters[];
diff --git a/include/media/cec.h b/include/media/cec.h
index 208c9613c07eb..77346f757036d 100644
--- a/include/media/cec.h
@@ -133791,10 +203892,10 @@ index 12955cb460d23..3b5986cee0739 100644
unsigned int (*num_users)(void *buf_priv);
diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h
-index e3e770f76f349..77c694a19149d 100644
+index e3e770f76f349..15dd0076c2936 100644
--- a/include/memory/renesas-rpc-if.h
+++ b/include/memory/renesas-rpc-if.h
-@@ -59,6 +59,7 @@ struct rpcif_op {
+@@ -59,12 +59,14 @@ struct rpcif_op {
struct rpcif {
struct device *dev;
@@ -133802,6 +203903,13 @@ index e3e770f76f349..77c694a19149d 100644
void __iomem *dirmap;
struct regmap *regmap;
struct reset_control *rstc;
+ size_t size;
+ enum rpcif_data_dir dir;
+ u8 bus_size;
++ u8 xfer_size;
+ void *buffer;
+ u32 xferlen;
+ u32 smcr;
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 78ea3e332688f..59940e230b782 100644
--- a/include/net/addrconf.h
@@ -133824,6 +203932,94 @@ index 78ea3e332688f..59940e230b782 100644
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
u32 banned_flags);
bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
+index ab207677e0a8b..f742e50207fbd 100644
+--- a/include/net/af_vsock.h
++++ b/include/net/af_vsock.h
+@@ -205,7 +205,8 @@ struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
+ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
+ struct sockaddr_vm *dst);
+ void vsock_remove_sock(struct vsock_sock *vsk);
+-void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
++void vsock_for_each_connected_socket(struct vsock_transport *transport,
++ void (*fn)(struct sock *sk));
+ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk);
+ bool vsock_find_cid(unsigned int cid);
+
+diff --git a/include/net/arp.h b/include/net/arp.h
+index 4950191f6b2bf..4a23a97195f33 100644
+--- a/include/net/arp.h
++++ b/include/net/arp.h
+@@ -71,6 +71,7 @@ void arp_send(int type, int ptype, __be32 dest_ip,
+ const unsigned char *src_hw, const unsigned char *th);
+ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
+ void arp_ifdown(struct net_device *dev);
++int arp_invalidate(struct net_device *dev, __be32 ip, bool force);
+
+ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+ struct net_device *dev, __be32 src_ip,
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 8b7eb46ad72d8..aadff553e4b73 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -236,6 +236,7 @@ typedef struct ax25_dev {
+ #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
+ ax25_dama_info dama;
+ #endif
++ refcount_t refcount;
+ } ax25_dev;
+
+ typedef struct ax25_cb {
+@@ -290,6 +291,17 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
+ }
+ }
+
++static inline void ax25_dev_hold(ax25_dev *ax25_dev)
++{
++ refcount_inc(&ax25_dev->refcount);
++}
++
++static inline void ax25_dev_put(ax25_dev *ax25_dev)
++{
++ if (refcount_dec_and_test(&ax25_dev->refcount)) {
++ kfree(ax25_dev);
++ }
++}
+ static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+ {
+ skb->dev = dev;
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 9125effbf4483..3fecc4a411a13 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -180,19 +180,21 @@ void bt_err_ratelimited(const char *fmt, ...);
+ #define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
+ #endif
+
++#define bt_dev_name(hdev) ((hdev) ? (hdev)->name : "null")
++
+ #define bt_dev_info(hdev, fmt, ...) \
+- BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ BT_INFO("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+ #define bt_dev_warn(hdev, fmt, ...) \
+- BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ BT_WARN("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+ #define bt_dev_err(hdev, fmt, ...) \
+- BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ BT_ERR("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+ #define bt_dev_dbg(hdev, fmt, ...) \
+- BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ BT_DBG("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+
+ #define bt_dev_warn_ratelimited(hdev, fmt, ...) \
+- bt_warn_ratelimited("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ bt_warn_ratelimited("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+ #define bt_dev_err_ratelimited(hdev, fmt, ...) \
+- bt_err_ratelimited("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
++ bt_err_ratelimited("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+
+ /* Connection and socket states */
+ enum {
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b80415011dcd5..9ce46cb8564d6 100644
--- a/include/net/bluetooth/hci.h
@@ -133844,6 +204040,20 @@ index b80415011dcd5..9ce46cb8564d6 100644
};
/* HCI device flags */
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index a7360c8c72f82..3da5cfcf84c1d 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -35,6 +35,9 @@
+ /* HCI priority */
+ #define HCI_PRIO_MAX 7
+
++/* HCI maximum id value */
++#define HCI_MAX_ID 10000
++
+ /* HCI Core structures */
+ struct inquiry_data {
+ bdaddr_t bdaddr;
diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h
index 38785d48baff9..184105d682942 100644
--- a/include/net/bond_3ad.h
@@ -134040,18 +204250,6 @@ index 5b96d5bd6e545..d3b5d368a0caa 100644
{
*psum = csum_fold(csum_sub(delta, (__force __wsum)*psum));
}
-diff --git a/include/net/dsa.h b/include/net/dsa.h
-index d784e76113b8d..49e5ece9361c6 100644
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -1056,6 +1056,7 @@ void dsa_unregister_switch(struct dsa_switch *ds);
- int dsa_register_switch(struct dsa_switch *ds);
- void dsa_switch_shutdown(struct dsa_switch *ds);
- struct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
-+void dsa_flush_workqueue(void);
- #ifdef CONFIG_PM_SLEEP
- int dsa_switch_suspend(struct dsa_switch *ds);
- int dsa_switch_resume(struct dsa_switch *ds);
diff --git a/include/net/dst_cache.h b/include/net/dst_cache.h
index 67634675e9197..df6622a5fe98f 100644
--- a/include/net/dst_cache.h
@@ -134123,6 +204321,19 @@ index 4b10676c69d19..bd07484ab9dd5 100644
+ int flags,
struct fib_lookup_arg *arg));
#endif
+diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
+index ffd386ea0dbb3..c8d1c5e187e4b 100644
+--- a/include/net/flow_dissector.h
++++ b/include/net/flow_dissector.h
+@@ -59,6 +59,8 @@ struct flow_dissector_key_vlan {
+ __be16 vlan_tci;
+ };
+ __be16 vlan_tpid;
++ __be16 vlan_eth_type;
++ u16 padding;
+ };
+
+ struct flow_dissector_mpls_lse {
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index b06c2d02ec84e..fa6a87246a7b8 100644
--- a/include/net/inet_connection_sock.h
@@ -134158,6 +204369,19 @@ index 48cc5795ceda6..63540be0fc34a 100644
}
void fqdir_exit(struct fqdir *fqdir);
+diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
+index f72ec113ae568..98e1ec1a14f03 100644
+--- a/include/net/inet_hashtables.h
++++ b/include/net/inet_hashtables.h
+@@ -425,7 +425,7 @@ static inline void sk_rcv_saddr_set(struct sock *sk, __be32 addr)
+ }
+
+ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+- struct sock *sk, u32 port_offset,
++ struct sock *sk, u64 port_offset,
+ int (*check_established)(struct inet_timewait_death_row *,
+ struct sock *, __u16,
+ struct inet_timewait_sock **));
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 89163ef8cf4be..9e1111f5915bd 100644
--- a/include/net/inet_sock.h
@@ -134176,10 +204400,18 @@ index 89163ef8cf4be..9e1111f5915bd 100644
__u8 min_ttl;
__u8 mc_ttl;
diff --git a/include/net/ip.h b/include/net/ip.h
-index 9192444f2964e..0106c6590ee7b 100644
+index 9192444f2964e..a77a9e1c6c047 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
-@@ -520,19 +520,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
+@@ -55,6 +55,7 @@ struct inet_skb_parm {
+ #define IPSKB_DOREDIRECT BIT(5)
+ #define IPSKB_FRAG_PMTU BIT(6)
+ #define IPSKB_L3SLAVE BIT(7)
++#define IPSKB_NOPOLICY BIT(8)
+
+ u16 frag_max_size;
+ };
+@@ -520,19 +521,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
{
struct iphdr *iph = ip_hdr(skb);
@@ -134251,6 +204483,19 @@ index c412dde4d67dc..bbb27639f2933 100644
int call_fib6_entry_notifiers(struct net *net,
enum fib_event_type event_type,
+diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
+index 028eaea1c8544..42d50856fcf24 100644
+--- a/include/net/ip6_tunnel.h
++++ b/include/net/ip6_tunnel.h
+@@ -57,7 +57,7 @@ struct ip6_tnl {
+
+ /* These fields used only by GRE */
+ __u32 i_seqno; /* The last seen seqno */
+- __u32 o_seqno; /* The last output seqno */
++ atomic_t o_seqno; /* The last output seqno */
+ int hlen; /* tun_hlen + encap_hlen */
+ int tun_hlen; /* Precalculated header length */
+ int encap_hlen; /* Encap header length (FOU,GUE) */
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index ab5348e57db1a..3417ba2d27ad6 100644
--- a/include/net/ip_fib.h
@@ -134264,6 +204509,19 @@ index ab5348e57db1a..3417ba2d27ad6 100644
}
#else
static inline int fib_num_tclassid_users(struct net *net)
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index bc3b13ec93c9d..37d5d4968e20a 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -113,7 +113,7 @@ struct ip_tunnel {
+
+ /* These four fields used only by GRE */
+ u32 i_seqno; /* The last seen seqno */
+- u32 o_seqno; /* The last output seqno */
++ atomic_t o_seqno; /* The last output seqno */
+ int tun_hlen; /* Precalculated header length */
+
+ /* These four fields used only by ERSPAN */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f2d0ecc257bb2..359540dfc0339 100644
--- a/include/net/ipv6.h
@@ -134378,11 +204636,51 @@ index 22ced1381ede5..d5767e25509cc 100644
}
static inline struct neighbour *
+diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
+index bb5fa59140321..2ba326f9e004d 100644
+--- a/include/net/net_namespace.h
++++ b/include/net/net_namespace.h
+@@ -479,4 +479,10 @@ static inline void fnhe_genid_bump(struct net *net)
+ atomic_inc(&net->fnhe_genid);
+ }
+
++#ifdef CONFIG_NET
++void net_ns_init(void);
++#else
++static inline void net_ns_init(void) {}
++#endif
++
+ #endif /* __NET_NET_NAMESPACE_H */
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
-index cc663c68ddc4b..d24b0a34c8f0c 100644
+index cc663c68ddc4b..34c266502a50e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
-@@ -276,14 +276,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
+@@ -76,6 +76,8 @@ struct nf_conn {
+ * Hint, SKB address this struct and refcnt via skb->_nfct and
+ * helpers nf_conntrack_get() and nf_conntrack_put().
+ * Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt,
++ * except that the latter uses internal indirection and does not
++ * result in a conntrack module dependency.
+ * beware nf_ct_get() is different and don't inc refcnt.
+ */
+ struct nf_conntrack ct_general;
+@@ -169,11 +171,13 @@ nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+ return (struct nf_conn *)(nfct & NFCT_PTRMASK);
+ }
+
++void nf_ct_destroy(struct nf_conntrack *nfct);
++
+ /* decrement reference count on a conntrack */
+ static inline void nf_ct_put(struct nf_conn *ct)
+ {
+- WARN_ON(!ct);
+- nf_conntrack_put(&ct->ct_general);
++ if (ct && refcount_dec_and_test(&ct->ct_general.use))
++ nf_ct_destroy(&ct->ct_general);
+ }
+
+ /* Protocol module loading */
+@@ -276,14 +280,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
/* jiffies until ct expires, 0 if already expired */
static inline unsigned long nf_ct_expires(const struct nf_conn *ct)
{
@@ -134399,7 +204697,7 @@ index cc663c68ddc4b..d24b0a34c8f0c 100644
}
/* use after obtaining a reference count */
-@@ -302,7 +302,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
+@@ -302,7 +306,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
static inline void nf_ct_offload_timeout(struct nf_conn *ct)
{
if (nf_ct_expires(ct) < NF_CT_DAY / 2)
@@ -134408,6 +204706,50 @@ index cc663c68ddc4b..d24b0a34c8f0c 100644
}
struct kernel_param;
+diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
+index 37f0fbefb060f..9939c366f720d 100644
+--- a/include/net/netfilter/nf_conntrack_helper.h
++++ b/include/net/netfilter/nf_conntrack_helper.h
+@@ -177,4 +177,5 @@ void nf_nat_helper_unregister(struct nf_conntrack_nat_helper *nat);
+ int nf_nat_helper_try_module_get(const char *name, u16 l3num,
+ u8 protonum);
+ void nf_nat_helper_put(struct nf_conntrack_helper *helper);
++void nf_ct_set_auto_assign_helper_warned(struct net *net);
+ #endif /*_NF_CONNTRACK_HELPER_H*/
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index a3647fadf1ccb..9f927c44087de 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -10,6 +10,8 @@
+ #include <linux/netfilter/nf_conntrack_tuple_common.h>
+ #include <net/flow_offload.h>
+ #include <net/dst.h>
++#include <linux/if_pppox.h>
++#include <linux/ppp_defs.h>
+
+ struct nf_flowtable;
+ struct nf_flow_rule;
+@@ -313,4 +315,20 @@ int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow,
+ int nf_flow_table_offload_init(void);
+ void nf_flow_table_offload_exit(void);
+
++static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
++{
++ __be16 proto;
++
++ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
++ sizeof(struct pppoe_hdr)));
++ switch (proto) {
++ case htons(PPP_IP):
++ return htons(ETH_P_IP);
++ case htons(PPP_IPV6):
++ return htons(ETH_P_IPV6);
++ }
++
++ return 0;
++}
++
+ #endif /* _NF_FLOW_TABLE_H */
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 9eed51e920e87..980daa6e1e3aa 100644
--- a/include/net/netfilter/nf_queue.h
@@ -134463,13 +204805,17 @@ index 2f65701a43c95..6c5b2efc4f17d 100644
struct hlist_head *fib_table_hash;
struct sock *fibnl;
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
-index a4b5503803165..6bd7e5a85ce76 100644
+index a4b5503803165..ff82983b7ab41 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
-@@ -77,9 +77,10 @@ struct netns_ipv6 {
+@@ -75,11 +75,12 @@ struct netns_ipv6 {
+ struct list_head fib6_walkers;
+ rwlock_t fib6_walker_lock;
spinlock_t fib6_gc_lock;
- unsigned int ip6_rt_gc_expire;
- unsigned long ip6_rt_last_gc;
+- unsigned int ip6_rt_gc_expire;
+- unsigned long ip6_rt_last_gc;
++ atomic_t ip6_rt_gc_expire;
++ unsigned long ip6_rt_last_gc;
+ unsigned char flowlabel_has_excl;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
- unsigned int fib6_rules_require_fldissect;
@@ -134478,6 +204824,23 @@ index a4b5503803165..6bd7e5a85ce76 100644
#ifdef CONFIG_IPV6_SUBTREES
unsigned int fib6_routes_require_src;
#endif
+diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
+index 947733a639a6f..bd7c3be4af5d7 100644
+--- a/include/net/netns/xfrm.h
++++ b/include/net/netns/xfrm.h
+@@ -66,11 +66,7 @@ struct netns_xfrm {
+ int sysctl_larval_drop;
+ u32 sysctl_acq_expires;
+
+- u8 policy_default;
+-#define XFRM_POL_DEFAULT_IN 1
+-#define XFRM_POL_DEFAULT_OUT 2
+-#define XFRM_POL_DEFAULT_FWD 4
+-#define XFRM_POL_DEFAULT_MASK 7
++ u8 policy_default[XFRM_POLICY_MAX];
+
+ #ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_hdr;
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index a964daedc17b6..ea8595651c384 100644
--- a/include/net/nfc/nci_core.h
@@ -134686,6 +205049,21 @@ index 651bba654d77d..8d2c3dd9f5953 100644
void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
struct sctp_association *sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
+diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
+index d7d2495f83c27..dac91aa38c5af 100644
+--- a/include/net/secure_seq.h
++++ b/include/net/secure_seq.h
+@@ -4,8 +4,8 @@
+
+ #include <linux/types.h>
+
+-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
++u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
++u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+ __be16 dport);
+ u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
diff --git a/include/net/seg6.h b/include/net/seg6.h
index 9d19c15e8545c..af668f17b3988 100644
--- a/include/net/seg6.h
@@ -134835,8 +205213,20 @@ index 1d20b98493a10..732b7097d78e4 100644
}
/* Structure for an attached lower socket */
+diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
+index 748cf87a4d7ea..3e02709a1df65 100644
+--- a/include/net/tc_act/tc_pedit.h
++++ b/include/net/tc_act/tc_pedit.h
+@@ -14,6 +14,7 @@ struct tcf_pedit {
+ struct tc_action common;
+ unsigned char tcfp_nkeys;
+ unsigned char tcfp_flags;
++ u32 tcfp_off_max_hint;
+ struct tc_pedit_key *tcfp_keys;
+ struct tcf_pedit_key_ex *tcfp_keys_ex;
+ };
diff --git a/include/net/tcp.h b/include/net/tcp.h
-index 60c384569e9cd..31d384c3778a1 100644
+index 60c384569e9cd..91ac329ca5789 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -48,7 +48,9 @@
@@ -134870,8 +205260,44 @@ index 60c384569e9cd..31d384c3778a1 100644
bool tcp_check_oom(struct sock *sk, int shift);
+@@ -481,6 +470,7 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
+ u32 cookie);
+ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb);
+ struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops,
++ const struct tcp_request_sock_ops *af_ops,
+ struct sock *sk, struct sk_buff *skb);
+ #ifdef CONFIG_SYN_COOKIES
+
+@@ -619,6 +609,7 @@ void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req);
+ void tcp_reset(struct sock *sk, struct sk_buff *skb);
+ void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
+ void tcp_fin(struct sock *sk);
++void tcp_check_space(struct sock *sk);
+
+ /* tcp_timer.c */
+ void tcp_init_xmit_timers(struct sock *);
+@@ -1037,6 +1028,7 @@ struct rate_sample {
+ int losses; /* number of packets marked lost upon ACK */
+ u32 acked_sacked; /* number of packets newly (S)ACKed upon ACK */
+ u32 prior_in_flight; /* in flight before this ACK */
++ u32 last_end_seq; /* end_seq of most recently ACKed packet */
+ bool is_app_limited; /* is sample from packet with bubble in pipe? */
+ bool is_retrans; /* is sample from retransmission? */
+ bool is_ack_delayed; /* is this (likely) a delayed ACK? */
+@@ -1159,6 +1151,11 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost,
+ bool is_sack_reneg, struct rate_sample *rs);
+ void tcp_rate_check_app_limited(struct sock *sk);
+
++static inline bool tcp_skb_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2)
++{
++ return t1 > t2 || (t1 == t2 && after(seq1, seq2));
++}
++
+ /* These functions determine how the current flow behaves in respect of SACK
+ * handling. SACK is negotiated with the peer, and therefore it can vary
+ * between different flows.
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
-index 2308210793a01..301a164f17e9f 100644
+index 2308210793a01..65242172e41c2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -200,6 +200,11 @@ struct xfrm_state {
@@ -134886,15 +205312,88 @@ index 2308210793a01..301a164f17e9f 100644
/* Data for encapsulator */
struct xfrm_encap_tmpl *encap;
struct sock __rcu *encap_sk;
-@@ -1162,7 +1167,7 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
+@@ -1075,24 +1080,29 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
+ }
+
+ #ifdef CONFIG_XFRM
+-static inline bool
+-xfrm_default_allow(struct net *net, int dir)
+-{
+- u8 def = net->xfrm.policy_default;
+-
+- switch (dir) {
+- case XFRM_POLICY_IN:
+- return def & XFRM_POL_DEFAULT_IN ? false : true;
+- case XFRM_POLICY_OUT:
+- return def & XFRM_POL_DEFAULT_OUT ? false : true;
+- case XFRM_POLICY_FWD:
+- return def & XFRM_POL_DEFAULT_FWD ? false : true;
+- }
++int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
++ unsigned short family);
++
++static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
++ int dir)
++{
++ if (!net->xfrm.policy_count[dir] && !secpath_exists(skb))
++ return net->xfrm.policy_default[dir] == XFRM_USERPOLICY_ACCEPT;
++
+ return false;
+ }
+
+-int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
+- unsigned short family);
++static inline bool __xfrm_check_dev_nopolicy(struct sk_buff *skb,
++ int dir, unsigned short family)
++{
++ if (dir != XFRM_POLICY_OUT && family == AF_INET) {
++ /* same dst may be used for traffic originating from
++ * devices with different policy settings.
++ */
++ return IPCB(skb)->flags & IPSKB_NOPOLICY;
++ }
++ return skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY);
++}
+
+ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
+ struct sk_buff *skb,
+@@ -1104,13 +1114,9 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
+ if (sk && sk->sk_policy[XFRM_POLICY_IN])
+ return __xfrm_policy_check(sk, ndir, skb, family);
+
+- if (xfrm_default_allow(net, dir))
+- return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
+- (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
+- __xfrm_policy_check(sk, ndir, skb, family);
+- else
+- return (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
+- __xfrm_policy_check(sk, ndir, skb, family);
++ return __xfrm_check_nopolicy(net, skb, dir) ||
++ __xfrm_check_dev_nopolicy(skb, dir, family) ||
++ __xfrm_policy_check(sk, ndir, skb, family);
+ }
+
+ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+@@ -1162,13 +1168,12 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
struct net *net = dev_net(skb->dev);
- if (xfrm_default_allow(net, XFRM_POLICY_FWD))
-+ if (xfrm_default_allow(net, XFRM_POLICY_OUT))
- return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
- (skb_dst(skb)->flags & DST_NOXFRM) ||
- __xfrm_route_forward(skb, family);
+- return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
+- (skb_dst(skb)->flags & DST_NOXFRM) ||
+- __xfrm_route_forward(skb, family);
+- else
+- return (skb_dst(skb)->flags & DST_NOXFRM) ||
+- __xfrm_route_forward(skb, family);
++ if (!net->xfrm.policy_count[XFRM_POLICY_OUT] &&
++ net->xfrm.policy_default[XFRM_POLICY_OUT] == XFRM_USERPOLICY_ACCEPT)
++ return true;
++
++ return (skb_dst(skb)->flags & DST_NOXFRM) ||
++ __xfrm_route_forward(skb, family);
+ }
+
+ static inline int xfrm4_route_forward(struct sk_buff *skb)
@@ -1562,7 +1567,6 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
@@ -134903,6 +205402,24 @@ index 2308210793a01..301a164f17e9f 100644
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu);
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
int xfrm_init_state(struct xfrm_state *x);
+@@ -1675,14 +1679,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ const struct xfrm_migrate *m, int num_bundles,
+ const struct xfrm_kmaddress *k,
+ const struct xfrm_encap_tmpl *encap);
+-struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
++struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
++ u32 if_id);
+ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
+ struct xfrm_migrate *m,
+ struct xfrm_encap_tmpl *encap);
+ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ struct xfrm_migrate *m, int num_bundles,
+ struct xfrm_kmaddress *k, struct net *net,
+- struct xfrm_encap_tmpl *encap);
++ struct xfrm_encap_tmpl *encap, u32 if_id);
+ #endif
+
+ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 4b50d9a3018a6..4ba642fc8a19a 100644
--- a/include/rdma/ib_verbs.h
@@ -134935,6 +205452,33 @@ index 2758d9df71ee9..c2a79aeee113c 100644
{ \
BUILD_BUG_ON(_index != _val); \
} \
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 4ee233e5a6ffa..d1e282f0d6f18 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -52,8 +52,10 @@ enum {
+
+ #define ISID_SIZE 6
+
+-/* Connection suspend "bit" */
+-#define ISCSI_SUSPEND_BIT 1
++/* Connection flags */
++#define ISCSI_CONN_FLAG_SUSPEND_TX BIT(0)
++#define ISCSI_CONN_FLAG_SUSPEND_RX BIT(1)
++#define ISCSI_CONN_FLAG_BOUND BIT(2)
+
+ #define ISCSI_ITT_MASK 0x1fff
+ #define ISCSI_TOTAL_CMDS_MAX 4096
+@@ -199,8 +201,7 @@ struct iscsi_conn {
+ struct list_head cmdqueue; /* data-path cmd queue */
+ struct list_head requeue; /* tasks needing another run */
+ struct work_struct xmitwork; /* per-conn. xmit workqueue */
+- unsigned long suspend_tx; /* suspend Tx */
+- unsigned long suspend_rx; /* suspend Rx */
++ unsigned long flags; /* ISCSI_CONN_FLAGs */
+
+ /* negotiated params */
+ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index eaf04c9a1dfcb..59afe8787cf7c 100644
--- a/include/scsi/scsi_cmnd.h
@@ -134948,6 +205492,18 @@ index eaf04c9a1dfcb..59afe8787cf7c 100644
struct delayed_work abort_work;
struct rcu_head rcu;
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index b97e142a7ca92..3b3dbc37653da 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -206,6 +206,7 @@ struct scsi_device {
+ unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device
+ * creation time */
+ unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */
++ unsigned silence_suspend:1; /* Do not print runtime PM related messages */
+
+ bool offline_already; /* Device offline message logged */
+
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 75363707b73f9..1a02e58eb4e44 100644
--- a/include/scsi/scsi_host.h
@@ -134960,6 +205516,40 @@ index 75363707b73f9..1a02e58eb4e44 100644
struct list_head eh_cmd_q;
struct task_struct * ehandler; /* Error recovery thread. */
struct completion * eh_action; /* Wait for specific actions on the
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index c5d7810fd7926..3ecf9702287be 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -211,6 +211,8 @@ struct iscsi_cls_conn {
+ struct mutex ep_mutex;
+ struct iscsi_endpoint *ep;
+
++ /* Used when accessing flags and queueing work. */
++ spinlock_t lock;
+ unsigned long flags;
+ struct work_struct cleanup_work;
+
+@@ -294,7 +296,7 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
+ struct iscsi_endpoint {
+ void *dd_data; /* LLD private data */
+ struct device dev;
+- uint64_t id;
++ int id;
+ struct iscsi_cls_conn *conn;
+ };
+
+diff --git a/include/sound/core.h b/include/sound/core.h
+index b7e9b58d3c788..6d4cc49584c63 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -284,6 +284,7 @@ int snd_card_disconnect(struct snd_card *card);
+ void snd_card_disconnect_sync(struct snd_card *card);
+ int snd_card_free(struct snd_card *card);
+ int snd_card_free_when_closed(struct snd_card *card);
++int snd_card_free_on_error(struct device *dev, int ret);
+ void snd_card_set_id(struct snd_card *card, const char *id);
+ int snd_card_register(struct snd_card *card);
+ int snd_card_info_init(void);
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 0e45963bb767f..82d9daa178517 100644
--- a/include/sound/hda_codec.h
@@ -135014,6 +205604,19 @@ index 375581634143c..d4e31ea16aba3 100644
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
struct hdac_ext_stream *azx_dev, bool decouple);
void snd_hdac_ext_stop_streams(struct hdac_bus *bus);
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 33451f8ff755b..e08bf475d02d4 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -398,6 +398,8 @@ struct snd_pcm_runtime {
+ wait_queue_head_t tsleep; /* transfer sleep */
+ struct fasync_struct *fasync;
+ bool stop_operating; /* sync_stop will be called */
++ struct mutex buffer_mutex; /* protect for buffer changes */
++ atomic_t buffer_accessing; /* >0: in r/w operation, <0: blocked */
+
+ /* -- private section -- */
+ void *private_data;
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index 4afd667e124c2..3e8a85e1e8094 100644
--- a/include/sound/soc-topology.h
@@ -135113,6 +205716,108 @@ index 7f42a3de59e6b..dd7d7c9efecdf 100644
__entry->root, __entry->id, __entry->level, __get_str(path),
__entry->val)
);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 0ea36b2b0662a..61a64d1b2bb68 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -95,6 +95,17 @@ TRACE_DEFINE_ENUM(ES_REFERENCED_B);
+ { FALLOC_FL_COLLAPSE_RANGE, "COLLAPSE_RANGE"}, \
+ { FALLOC_FL_ZERO_RANGE, "ZERO_RANGE"})
+
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_XATTR);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_CROSS_RENAME);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_JOURNAL_FLAG_CHANGE);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_NOMEM);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_SWAP_BOOT);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_RESIZE);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_RENAME_DIR);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_FALLOC_RANGE);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_INODE_JOURNAL_DATA);
++TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX);
++
+ #define show_fc_reason(reason) \
+ __print_symbolic(reason, \
+ { EXT4_FC_REASON_XATTR, "XATTR"}, \
+@@ -2723,41 +2734,50 @@ TRACE_EVENT(ext4_fc_commit_stop,
+
+ #define FC_REASON_NAME_STAT(reason) \
+ show_fc_reason(reason), \
+- __entry->sbi->s_fc_stats.fc_ineligible_reason_count[reason]
++ __entry->fc_ineligible_rc[reason]
+
+ TRACE_EVENT(ext4_fc_stats,
+- TP_PROTO(struct super_block *sb),
+-
+- TP_ARGS(sb),
++ TP_PROTO(struct super_block *sb),
+
+- TP_STRUCT__entry(
+- __field(dev_t, dev)
+- __field(struct ext4_sb_info *, sbi)
+- __field(int, count)
+- ),
++ TP_ARGS(sb),
+
+- TP_fast_assign(
+- __entry->dev = sb->s_dev;
+- __entry->sbi = EXT4_SB(sb);
+- ),
++ TP_STRUCT__entry(
++ __field(dev_t, dev)
++ __array(unsigned int, fc_ineligible_rc, EXT4_FC_REASON_MAX)
++ __field(unsigned long, fc_commits)
++ __field(unsigned long, fc_ineligible_commits)
++ __field(unsigned long, fc_numblks)
++ ),
+
+- TP_printk("dev %d:%d fc ineligible reasons:\n"
+- "%s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d, %s:%d; "
+- "num_commits:%ld, ineligible: %ld, numblks: %ld",
+- MAJOR(__entry->dev), MINOR(__entry->dev),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_XATTR),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_CROSS_RENAME),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_JOURNAL_FLAG_CHANGE),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_NOMEM),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_SWAP_BOOT),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_RESIZE),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_RENAME_DIR),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_FALLOC_RANGE),
+- FC_REASON_NAME_STAT(EXT4_FC_REASON_INODE_JOURNAL_DATA),
+- __entry->sbi->s_fc_stats.fc_num_commits,
+- __entry->sbi->s_fc_stats.fc_ineligible_commits,
+- __entry->sbi->s_fc_stats.fc_numblks)
++ TP_fast_assign(
++ int i;
+
++ __entry->dev = sb->s_dev;
++ for (i = 0; i < EXT4_FC_REASON_MAX; i++) {
++ __entry->fc_ineligible_rc[i] =
++ EXT4_SB(sb)->s_fc_stats.fc_ineligible_reason_count[i];
++ }
++ __entry->fc_commits = EXT4_SB(sb)->s_fc_stats.fc_num_commits;
++ __entry->fc_ineligible_commits =
++ EXT4_SB(sb)->s_fc_stats.fc_ineligible_commits;
++ __entry->fc_numblks = EXT4_SB(sb)->s_fc_stats.fc_numblks;
++ ),
++
++ TP_printk("dev %d,%d fc ineligible reasons:\n"
++ "%s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u "
++ "num_commits:%lu, ineligible: %lu, numblks: %lu",
++ MAJOR(__entry->dev), MINOR(__entry->dev),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_XATTR),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_CROSS_RENAME),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_JOURNAL_FLAG_CHANGE),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_NOMEM),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_SWAP_BOOT),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_RESIZE),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_RENAME_DIR),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_FALLOC_RANGE),
++ FC_REASON_NAME_STAT(EXT4_FC_REASON_INODE_JOURNAL_DATA),
++ __entry->fc_commits, __entry->fc_ineligible_commits,
++ __entry->fc_numblks)
+ );
+
+ #define DEFINE_TRACE_DENTRY_EVENT(__type) \
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 4e881d91c8744..4cb055af1ec0b 100644
--- a/include/trace/events/f2fs.h
@@ -135167,8 +205872,298 @@ index 4e881d91c8744..4cb055af1ec0b 100644
__entry->cino,
__entry->err)
);
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+deleted file mode 100644
+index 3d7b432ca5f31..0000000000000
+--- a/include/trace/events/random.h
++++ /dev/null
+@@ -1,247 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#undef TRACE_SYSTEM
+-#define TRACE_SYSTEM random
+-
+-#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
+-#define _TRACE_RANDOM_H
+-
+-#include <linux/writeback.h>
+-#include <linux/tracepoint.h>
+-
+-TRACE_EVENT(add_device_randomness,
+- TP_PROTO(int bytes, unsigned long IP),
+-
+- TP_ARGS(bytes, IP),
+-
+- TP_STRUCT__entry(
+- __field( int, bytes )
+- __field(unsigned long, IP )
+- ),
+-
+- TP_fast_assign(
+- __entry->bytes = bytes;
+- __entry->IP = IP;
+- ),
+-
+- TP_printk("bytes %d caller %pS",
+- __entry->bytes, (void *)__entry->IP)
+-);
+-
+-DECLARE_EVENT_CLASS(random__mix_pool_bytes,
+- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+-
+- TP_ARGS(pool_name, bytes, IP),
+-
+- TP_STRUCT__entry(
+- __field( const char *, pool_name )
+- __field( int, bytes )
+- __field(unsigned long, IP )
+- ),
+-
+- TP_fast_assign(
+- __entry->pool_name = pool_name;
+- __entry->bytes = bytes;
+- __entry->IP = IP;
+- ),
+-
+- TP_printk("%s pool: bytes %d caller %pS",
+- __entry->pool_name, __entry->bytes, (void *)__entry->IP)
+-);
+-
+-DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
+- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+-
+- TP_ARGS(pool_name, bytes, IP)
+-);
+-
+-DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+-
+- TP_ARGS(pool_name, bytes, IP)
+-);
+-
+-TRACE_EVENT(credit_entropy_bits,
+- TP_PROTO(const char *pool_name, int bits, int entropy_count,
+- unsigned long IP),
+-
+- TP_ARGS(pool_name, bits, entropy_count, IP),
+-
+- TP_STRUCT__entry(
+- __field( const char *, pool_name )
+- __field( int, bits )
+- __field( int, entropy_count )
+- __field(unsigned long, IP )
+- ),
+-
+- TP_fast_assign(
+- __entry->pool_name = pool_name;
+- __entry->bits = bits;
+- __entry->entropy_count = entropy_count;
+- __entry->IP = IP;
+- ),
+-
+- TP_printk("%s pool: bits %d entropy_count %d caller %pS",
+- __entry->pool_name, __entry->bits,
+- __entry->entropy_count, (void *)__entry->IP)
+-);
+-
+-TRACE_EVENT(debit_entropy,
+- TP_PROTO(const char *pool_name, int debit_bits),
+-
+- TP_ARGS(pool_name, debit_bits),
+-
+- TP_STRUCT__entry(
+- __field( const char *, pool_name )
+- __field( int, debit_bits )
+- ),
+-
+- TP_fast_assign(
+- __entry->pool_name = pool_name;
+- __entry->debit_bits = debit_bits;
+- ),
+-
+- TP_printk("%s: debit_bits %d", __entry->pool_name,
+- __entry->debit_bits)
+-);
+-
+-TRACE_EVENT(add_input_randomness,
+- TP_PROTO(int input_bits),
+-
+- TP_ARGS(input_bits),
+-
+- TP_STRUCT__entry(
+- __field( int, input_bits )
+- ),
+-
+- TP_fast_assign(
+- __entry->input_bits = input_bits;
+- ),
+-
+- TP_printk("input_pool_bits %d", __entry->input_bits)
+-);
+-
+-TRACE_EVENT(add_disk_randomness,
+- TP_PROTO(dev_t dev, int input_bits),
+-
+- TP_ARGS(dev, input_bits),
+-
+- TP_STRUCT__entry(
+- __field( dev_t, dev )
+- __field( int, input_bits )
+- ),
+-
+- TP_fast_assign(
+- __entry->dev = dev;
+- __entry->input_bits = input_bits;
+- ),
+-
+- TP_printk("dev %d,%d input_pool_bits %d", MAJOR(__entry->dev),
+- MINOR(__entry->dev), __entry->input_bits)
+-);
+-
+-DECLARE_EVENT_CLASS(random__get_random_bytes,
+- TP_PROTO(int nbytes, unsigned long IP),
+-
+- TP_ARGS(nbytes, IP),
+-
+- TP_STRUCT__entry(
+- __field( int, nbytes )
+- __field(unsigned long, IP )
+- ),
+-
+- TP_fast_assign(
+- __entry->nbytes = nbytes;
+- __entry->IP = IP;
+- ),
+-
+- TP_printk("nbytes %d caller %pS", __entry->nbytes, (void *)__entry->IP)
+-);
+-
+-DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
+- TP_PROTO(int nbytes, unsigned long IP),
+-
+- TP_ARGS(nbytes, IP)
+-);
+-
+-DEFINE_EVENT(random__get_random_bytes, get_random_bytes_arch,
+- TP_PROTO(int nbytes, unsigned long IP),
+-
+- TP_ARGS(nbytes, IP)
+-);
+-
+-DECLARE_EVENT_CLASS(random__extract_entropy,
+- TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+- unsigned long IP),
+-
+- TP_ARGS(pool_name, nbytes, entropy_count, IP),
+-
+- TP_STRUCT__entry(
+- __field( const char *, pool_name )
+- __field( int, nbytes )
+- __field( int, entropy_count )
+- __field(unsigned long, IP )
+- ),
+-
+- TP_fast_assign(
+- __entry->pool_name = pool_name;
+- __entry->nbytes = nbytes;
+- __entry->entropy_count = entropy_count;
+- __entry->IP = IP;
+- ),
+-
+- TP_printk("%s pool: nbytes %d entropy_count %d caller %pS",
+- __entry->pool_name, __entry->nbytes, __entry->entropy_count,
+- (void *)__entry->IP)
+-);
+-
+-
+-DEFINE_EVENT(random__extract_entropy, extract_entropy,
+- TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+- unsigned long IP),
+-
+- TP_ARGS(pool_name, nbytes, entropy_count, IP)
+-);
+-
+-TRACE_EVENT(urandom_read,
+- TP_PROTO(int got_bits, int pool_left, int input_left),
+-
+- TP_ARGS(got_bits, pool_left, input_left),
+-
+- TP_STRUCT__entry(
+- __field( int, got_bits )
+- __field( int, pool_left )
+- __field( int, input_left )
+- ),
+-
+- TP_fast_assign(
+- __entry->got_bits = got_bits;
+- __entry->pool_left = pool_left;
+- __entry->input_left = input_left;
+- ),
+-
+- TP_printk("got_bits %d nonblocking_pool_entropy_left %d "
+- "input_entropy_left %d", __entry->got_bits,
+- __entry->pool_left, __entry->input_left)
+-);
+-
+-TRACE_EVENT(prandom_u32,
+-
+- TP_PROTO(unsigned int ret),
+-
+- TP_ARGS(ret),
+-
+- TP_STRUCT__entry(
+- __field( unsigned int, ret)
+- ),
+-
+- TP_fast_assign(
+- __entry->ret = ret;
+- ),
+-
+- TP_printk("ret=%u" , __entry->ret)
+-);
+-
+-#endif /* _TRACE_RANDOM_H */
+-
+-/* This part must be outside protection */
+-#include <trace/define_trace.h>
+diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
+index e70c90116edae..4a3ab0ed6e062 100644
+--- a/include/trace/events/rxrpc.h
++++ b/include/trace/events/rxrpc.h
+@@ -83,12 +83,15 @@ enum rxrpc_call_trace {
+ rxrpc_call_error,
+ rxrpc_call_got,
+ rxrpc_call_got_kernel,
++ rxrpc_call_got_timer,
+ rxrpc_call_got_userid,
+ rxrpc_call_new_client,
+ rxrpc_call_new_service,
+ rxrpc_call_put,
+ rxrpc_call_put_kernel,
+ rxrpc_call_put_noqueue,
++ rxrpc_call_put_notimer,
++ rxrpc_call_put_timer,
+ rxrpc_call_put_userid,
+ rxrpc_call_queued,
+ rxrpc_call_queued_ref,
+@@ -278,12 +281,15 @@ enum rxrpc_tx_point {
+ EM(rxrpc_call_error, "*E*") \
+ EM(rxrpc_call_got, "GOT") \
+ EM(rxrpc_call_got_kernel, "Gke") \
++ EM(rxrpc_call_got_timer, "GTM") \
+ EM(rxrpc_call_got_userid, "Gus") \
+ EM(rxrpc_call_new_client, "NWc") \
+ EM(rxrpc_call_new_service, "NWs") \
+ EM(rxrpc_call_put, "PUT") \
+ EM(rxrpc_call_put_kernel, "Pke") \
+- EM(rxrpc_call_put_noqueue, "PNQ") \
++ EM(rxrpc_call_put_noqueue, "PnQ") \
++ EM(rxrpc_call_put_notimer, "PnT") \
++ EM(rxrpc_call_put_timer, "PTM") \
+ EM(rxrpc_call_put_userid, "Pus") \
+ EM(rxrpc_call_queued, "QUE") \
+ EM(rxrpc_call_queued_ref, "QUR") \
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
-index 2d04eb96d4183..7c48613c18304 100644
+index 2d04eb96d4183..2a598fb45bf4f 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -925,18 +925,19 @@ TRACE_EVENT(rpc_socket_nospace,
@@ -135203,7 +206198,15 @@ index 2d04eb96d4183..7c48613c18304 100644
DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class,
TP_PROTO(
-@@ -1133,8 +1134,11 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
+@@ -975,7 +976,6 @@ DEFINE_RPC_XPRT_LIFETIME_EVENT(connect);
+ DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_auto);
+ DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_done);
+ DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_force);
+-DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_cleanup);
+ DEFINE_RPC_XPRT_LIFETIME_EVENT(destroy);
+
+ DECLARE_EVENT_CLASS(rpc_xprt_event,
+@@ -1133,8 +1133,11 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
__entry->task_id = -1;
__entry->client_id = -1;
}
@@ -135217,7 +206220,7 @@ index 2d04eb96d4183..7c48613c18304 100644
),
TP_printk("task:%u@%u snd_task:%u",
-@@ -1178,8 +1182,12 @@ DECLARE_EVENT_CLASS(xprt_cong_event,
+@@ -1178,8 +1181,12 @@ DECLARE_EVENT_CLASS(xprt_cong_event,
__entry->task_id = -1;
__entry->client_id = -1;
}
@@ -135232,7 +206235,7 @@ index 2d04eb96d4183..7c48613c18304 100644
__entry->cong = xprt->cong;
__entry->cwnd = xprt->cwnd;
__entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
-@@ -1719,10 +1727,11 @@ TRACE_EVENT(svc_xprt_create_err,
+@@ -1719,10 +1726,11 @@ TRACE_EVENT(svc_xprt_create_err,
const char *program,
const char *protocol,
struct sockaddr *sap,
@@ -135245,7 +206248,7 @@ index 2d04eb96d4183..7c48613c18304 100644
TP_STRUCT__entry(
__field(long, error)
-@@ -1735,7 +1744,7 @@ TRACE_EVENT(svc_xprt_create_err,
+@@ -1735,7 +1743,7 @@ TRACE_EVENT(svc_xprt_create_err,
__entry->error = PTR_ERR(xprt);
__assign_str(program, program);
__assign_str(protocol, protocol);
@@ -135254,6 +206257,28 @@ index 2d04eb96d4183..7c48613c18304 100644
),
TP_printk("addr=%pISpc program=%s protocol=%s error=%ld",
+@@ -1915,17 +1923,18 @@ DECLARE_EVENT_CLASS(svc_deferred_event,
+ TP_STRUCT__entry(
+ __field(const void *, dr)
+ __field(u32, xid)
+- __string(addr, dr->xprt->xpt_remotebuf)
++ __array(__u8, addr, INET6_ADDRSTRLEN + 10)
+ ),
+
+ TP_fast_assign(
+ __entry->dr = dr;
+ __entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
+ (dr->xprt_hlen>>2)));
+- __assign_str(addr, dr->xprt->xpt_remotebuf);
++ snprintf(__entry->addr, sizeof(__entry->addr) - 1,
++ "%pISpc", (struct sockaddr *)&dr->addr);
+ ),
+
+- TP_printk("addr=%s dr=%p xid=0x%08x", __get_str(addr), __entry->dr,
++ TP_printk("addr=%s dr=%p xid=0x%08x", __entry->addr, __entry->dr,
+ __entry->xid)
+ );
+
@@ -2103,17 +2112,17 @@ DECLARE_EVENT_CLASS(svcsock_accept_class,
TP_STRUCT__entry(
__field(long, status)
@@ -135301,6 +206326,63 @@ index fe929e7b77ca1..7572f2f46ee89 100644
/* 0x01000000 used on x86 */
/* 0x02000000 used on x86 */
/*
+diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
+index 791f31dd0abee..a887e582f0e78 100644
+--- a/include/uapi/linux/bpf.h
++++ b/include/uapi/linux/bpf.h
+@@ -2276,8 +2276,8 @@ union bpf_attr {
+ * Return
+ * The return value depends on the result of the test, and can be:
+ *
+- * * 0, if current task belongs to the cgroup2.
+- * * 1, if current task does not belong to the cgroup2.
++ * * 1, if current task belongs to the cgroup2.
++ * * 0, if current task does not belong to the cgroup2.
+ * * A negative error code, if an error occurred.
+ *
+ * long bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags)
+@@ -2965,8 +2965,8 @@ union bpf_attr {
+ *
+ * # sysctl kernel.perf_event_max_stack=<new value>
+ * Return
+- * A non-negative value equal to or less than *size* on success,
+- * or a negative error in case of failure.
++ * The non-negative copied *buf* length equal to or less than
++ * *size* on success, or a negative error in case of failure.
+ *
+ * long bpf_skb_load_bytes_relative(const void *skb, u32 offset, void *to, u32 len, u32 start_header)
+ * Description
+@@ -4269,8 +4269,8 @@ union bpf_attr {
+ *
+ * # sysctl kernel.perf_event_max_stack=<new value>
+ * Return
+- * A non-negative value equal to or less than *size* on success,
+- * or a negative error in case of failure.
++ * The non-negative copied *buf* length equal to or less than
++ * *size* on success, or a negative error in case of failure.
+ *
+ * long bpf_load_hdr_opt(struct bpf_sock_ops *skops, void *searchby_res, u32 len, u64 flags)
+ * Description
+@@ -5347,7 +5347,8 @@ struct bpf_sock {
+ __u32 src_ip4;
+ __u32 src_ip6[4];
+ __u32 src_port; /* host byte order */
+- __u32 dst_port; /* network byte order */
++ __be16 dst_port; /* network byte order */
++ __u16 :16; /* zero padding */
+ __u32 dst_ip4;
+ __u32 dst_ip6[4];
+ __u32 state;
+@@ -6222,7 +6223,8 @@ struct bpf_sk_lookup {
+ __u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */
+ __u32 remote_ip4; /* Network byte order */
+ __u32 remote_ip6[4]; /* Network byte order */
+- __u32 remote_port; /* Network byte order */
++ __be16 remote_port; /* Network byte order */
++ __u16 :16; /* Zero padding */
+ __u32 local_ip4; /* Network byte order */
+ __u32 local_ip6[4]; /* Network byte order */
+ __u32 local_port; /* Host byte order */
diff --git a/include/uapi/linux/byteorder/big_endian.h b/include/uapi/linux/byteorder/big_endian.h
index 2199adc6a6c20..80aa5c41a7636 100644
--- a/include/uapi/linux/byteorder/big_endian.h
@@ -135325,6 +206407,58 @@ index 601c904fd5cd9..cd98982e7523e 100644
#include <linux/types.h>
#include <linux/swab.h>
+diff --git a/include/uapi/linux/can/isotp.h b/include/uapi/linux/can/isotp.h
+index c55935b64ccc8..590f8aea2b6d2 100644
+--- a/include/uapi/linux/can/isotp.h
++++ b/include/uapi/linux/can/isotp.h
+@@ -137,20 +137,16 @@ struct can_isotp_ll_options {
+ #define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */
+ #define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */
+
+-/* default values */
++/* protocol machine default values */
+
+ #define CAN_ISOTP_DEFAULT_FLAGS 0
+ #define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00
+ #define CAN_ISOTP_DEFAULT_PAD_CONTENT 0xCC /* prevent bit-stuffing */
+-#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0
++#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 50000 /* 50 micro seconds */
+ #define CAN_ISOTP_DEFAULT_RECV_BS 0
+ #define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00
+ #define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0
+
+-#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
+-#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
+-#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
+-
+ /*
+ * Remark on CAN_ISOTP_DEFAULT_RECV_* values:
+ *
+@@ -162,4 +158,24 @@ struct can_isotp_ll_options {
+ * consistency and copied directly into the flow control (FC) frame.
+ */
+
++/* link layer default values => make use of Classical CAN frames */
++
++#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
++#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
++#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
++
++/*
++ * The CAN_ISOTP_DEFAULT_FRAME_TXTIME has become a non-zero value as
++ * it only makes sense for isotp implementation tests to run without
++ * a N_As value. As user space applications usually do not set the
++ * frame_txtime element of struct can_isotp_options the new in-kernel
++ * default is very likely overwritten with zero when the sockopt()
++ * CAN_ISOTP_OPTS is invoked.
++ * To make sure that a N_As value of zero is only set intentional the
++ * value '0' is now interpreted as 'do not change the current value'.
++ * When a frame_txtime of zero is required for testing purposes this
++ * CAN_ISOTP_FRAME_TXTIME_ZERO u32 value has to be set in frame_txtime.
++ */
++#define CAN_ISOTP_FRAME_TXTIME_ZERO 0xFFFFFFFF
++
+ #endif /* !_UAPI_CAN_ISOTP_H */
diff --git a/include/uapi/linux/cyclades.h b/include/uapi/linux/cyclades.h
new file mode 100644
index 0000000000000..6225c5aebe06a
@@ -135366,6 +206500,20 @@ index 0000000000000..6225c5aebe06a
+#define CYGETWAIT 0x435913
+
+#endif /* _UAPI_LINUX_CYCLADES_H */
+diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
+index 8e4a2ca0bcbf7..b1523cb8ab307 100644
+--- a/include/uapi/linux/dma-buf.h
++++ b/include/uapi/linux/dma-buf.h
+@@ -92,7 +92,7 @@ struct dma_buf_sync {
+ * between them in actual uapi, they're just different numbers.
+ */
+ #define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *)
+-#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32)
+-#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64)
++#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, __u32)
++#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, __u64)
+
+ #endif
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 5545f1ca9237c..f7204bdfe8db1 100644
--- a/include/uapi/linux/ethtool_netlink.h
@@ -135497,6 +206645,108 @@ index e709ae8235e7f..ff6ccbc6efe96 100644
#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
+diff --git a/include/uapi/linux/rfkill.h b/include/uapi/linux/rfkill.h
+index 9b77cfc42efa3..db6c8588c1d0c 100644
+--- a/include/uapi/linux/rfkill.h
++++ b/include/uapi/linux/rfkill.h
+@@ -159,8 +159,16 @@ struct rfkill_event_ext {
+ * old behaviour for all userspace, unless it explicitly opts in to the
+ * rules outlined here by using the new &struct rfkill_event_ext.
+ *
+- * Userspace using &struct rfkill_event_ext must adhere to the following
+- * rules
++ * Additionally, some other userspace (bluez, g-s-d) was reading with a
++ * large size but as streaming reads rather than message-based, or with
++ * too strict checks for the returned size. So eventually, we completely
++ * reverted this, and extended messages need to be opted in to by using
++ * an ioctl:
++ *
++ * ioctl(fd, RFKILL_IOCTL_MAX_SIZE, sizeof(struct rfkill_event_ext));
++ *
++ * Userspace using &struct rfkill_event_ext and the ioctl must adhere to
++ * the following rules:
+ *
+ * 1. accept short writes, optionally using them to detect that it's
+ * running on an older kernel;
+@@ -175,6 +183,8 @@ struct rfkill_event_ext {
+ #define RFKILL_IOC_MAGIC 'R'
+ #define RFKILL_IOC_NOINPUT 1
+ #define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
++#define RFKILL_IOC_MAX_SIZE 2
++#define RFKILL_IOCTL_MAX_SIZE _IOW(RFKILL_IOC_MAGIC, RFKILL_IOC_MAX_SIZE, __u32)
+
+ /* and that's all userspace gets */
+
+diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
+index 9a402fdb60e97..77ee207623a9b 100644
+--- a/include/uapi/linux/rseq.h
++++ b/include/uapi/linux/rseq.h
+@@ -105,23 +105,11 @@ struct rseq {
+ * Read and set by the kernel. Set by user-space with single-copy
+ * atomicity semantics. This field should only be updated by the
+ * thread which registered this data structure. Aligned on 64-bit.
++ *
++ * 32-bit architectures should update the low order bits of the
++ * rseq_cs field, leaving the high order bits initialized to 0.
+ */
+- union {
+- __u64 ptr64;
+-#ifdef __LP64__
+- __u64 ptr;
+-#else
+- struct {
+-#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN)
+- __u32 padding; /* Initialized to zero. */
+- __u32 ptr32;
+-#else /* LITTLE */
+- __u32 ptr32;
+- __u32 padding; /* Initialized to zero. */
+-#endif /* ENDIAN */
+- } ptr;
+-#endif
+- } rseq_cs;
++ __u64 rseq_cs;
+
+ /*
+ * Restartable sequences flags field.
+diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
+index c4042dcfdc0c3..8885e69178bd7 100644
+--- a/include/uapi/linux/serial_core.h
++++ b/include/uapi/linux/serial_core.h
+@@ -68,6 +68,9 @@
+ /* NVIDIA Tegra Combined UART */
+ #define PORT_TEGRA_TCU 41
+
++/* ASPEED AST2x00 virtual UART */
++#define PORT_ASPEED_VUART 42
++
+ /* Intel EG20 */
+ #define PORT_PCH_8LINE 44
+ #define PORT_PCH_2LINE 45
+diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
+index 80d76b75bccd9..7aa2eb7662050 100644
+--- a/include/uapi/linux/virtio_ids.h
++++ b/include/uapi/linux/virtio_ids.h
+@@ -73,12 +73,12 @@
+ * Virtio Transitional IDs
+ */
+
+-#define VIRTIO_TRANS_ID_NET 1000 /* transitional virtio net */
+-#define VIRTIO_TRANS_ID_BLOCK 1001 /* transitional virtio block */
+-#define VIRTIO_TRANS_ID_BALLOON 1002 /* transitional virtio balloon */
+-#define VIRTIO_TRANS_ID_CONSOLE 1003 /* transitional virtio console */
+-#define VIRTIO_TRANS_ID_SCSI 1004 /* transitional virtio SCSI */
+-#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */
+-#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */
++#define VIRTIO_TRANS_ID_NET 0x1000 /* transitional virtio net */
++#define VIRTIO_TRANS_ID_BLOCK 0x1001 /* transitional virtio block */
++#define VIRTIO_TRANS_ID_BALLOON 0x1002 /* transitional virtio balloon */
++#define VIRTIO_TRANS_ID_CONSOLE 0x1003 /* transitional virtio console */
++#define VIRTIO_TRANS_ID_SCSI 0x1004 /* transitional virtio SCSI */
++#define VIRTIO_TRANS_ID_RNG 0x1005 /* transitional virtio rng */
++#define VIRTIO_TRANS_ID_9P 0x1009 /* transitional virtio 9p console */
+
+ #endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index eda0426ec4c2b..65e13a099b1a0 100644
--- a/include/uapi/linux/xfrm.h
@@ -135590,10 +206840,18 @@ index cb854df031ce0..c9fea9389ebec 100644
* operations on reserved batches of grant references
*/
diff --git a/init/main.c b/init/main.c
-index 3c4054a955458..bcd132d4e7bdd 100644
+index 3c4054a955458..cf79b5a766cb1 100644
--- a/init/main.c
+++ b/init/main.c
-@@ -924,7 +924,9 @@ static void __init print_unknown_bootoptions(void)
+@@ -100,6 +100,7 @@
+ #include <linux/kcsan.h>
+ #include <linux/init_syscalls.h>
+ #include <linux/stackdepot.h>
++#include <net/net_namespace.h>
+
+ #include <asm/io.h>
+ #include <asm/bugs.h>
+@@ -924,7 +925,9 @@ static void __init print_unknown_bootoptions(void)
for (p = &envp_init[2]; *p; p++)
end += sprintf(end, " %s", *p);
@@ -135604,6 +206862,61 @@ index 3c4054a955458..bcd132d4e7bdd 100644
memblock_free_ptr(unknown_options, len);
}
+@@ -1038,21 +1041,18 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
+ softirq_init();
+ timekeeping_init();
+ kfence_init();
++ time_init();
+
+ /*
+ * For best initial stack canary entropy, prepare it after:
+ * - setup_arch() for any UEFI RNG entropy and boot cmdline access
+- * - timekeeping_init() for ktime entropy used in rand_initialize()
+- * - rand_initialize() to get any arch-specific entropy like RDRAND
+- * - add_latent_entropy() to get any latent entropy
+- * - adding command line entropy
++ * - timekeeping_init() for ktime entropy used in random_init()
++ * - time_init() for making random_get_entropy() work on some platforms
++ * - random_init() to initialize the RNG from from early entropy sources
+ */
+- rand_initialize();
+- add_latent_entropy();
+- add_device_randomness(command_line, strlen(command_line));
++ random_init(command_line);
+ boot_init_stack_canary();
+
+- time_init();
+ perf_event_init();
+ profile_init();
+ call_function_init();
+@@ -1120,6 +1120,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
+ key_init();
+ security_init();
+ dbg_late_init();
++ net_ns_init();
+ vfs_caches_init();
+ pagecache_init();
+ signals_init();
+@@ -1194,7 +1195,7 @@ static int __init initcall_blacklist(char *str)
+ }
+ } while (str_entry);
+
+- return 0;
++ return 1;
+ }
+
+ static bool __init_or_module initcall_blacklisted(initcall_t fn)
+@@ -1456,7 +1457,9 @@ static noinline void __init kernel_init_freeable(void);
+ bool rodata_enabled __ro_after_init = true;
+ static int __init set_debug_rodata(char *str)
+ {
+- return strtobool(str, &rodata_enabled);
++ if (strtobool(str, &rodata_enabled))
++ pr_warn("Invalid option string for rodata: '%s'\n", str);
++ return 1;
+ }
+ __setup("rodata=", set_debug_rodata);
+ #endif
diff --git a/ipc/sem.c b/ipc/sem.c
index 6693daf4fe112..0dbdb98fdf2d9 100644
--- a/ipc/sem.c
@@ -135929,6 +207242,20 @@ index d48d8cfa1f3fa..fa2d86ef3fb80 100644
ipc_kht_remove(ids, ipcp);
ids->in_use--;
ipcp->deleted = true;
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 4df609be42d07..0e119c52a2cd6 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -113,7 +113,8 @@ obj-$(CONFIG_CPU_PM) += cpu_pm.o
+ obj-$(CONFIG_BPF) += bpf/
+ obj-$(CONFIG_KCSAN) += kcsan/
+ obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
+-obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call.o
++obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
++obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call_inline.o
+ obj-$(CONFIG_CFI_CLANG) += cfi.o
+
+ obj-$(CONFIG_PERF_EVENTS) += events/
diff --git a/kernel/async.c b/kernel/async.c
index b8d7a663497f9..b2c4ba5686ee4 100644
--- a/kernel/async.c
@@ -136168,8 +207495,140 @@ index 121d37e700a62..94ded5de91317 100644
if (!(auditd_test_task(current) || audit_ctl_owner_current())) {
long stime = audit_backlog_wait_time;
+diff --git a/kernel/audit.h b/kernel/audit.h
+index d6a2c899a8dbf..b2ef4c0d3ec03 100644
+--- a/kernel/audit.h
++++ b/kernel/audit.h
+@@ -194,6 +194,10 @@ struct audit_context {
+ struct {
+ char *name;
+ } module;
++ struct {
++ struct audit_ntp_data ntp_data;
++ struct timespec64 tk_injoffset;
++ } time;
+ };
+ int fds[2];
+ struct audit_proctitle proctitle;
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index b1cb1dbf7417f..2f036bab3c28f 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -1219,6 +1219,53 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
+ from_kuid(&init_user_ns, name->fcap.rootid));
+ }
+
++static void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
++{
++ const struct audit_ntp_data *ntp = &context->time.ntp_data;
++ const struct timespec64 *tk = &context->time.tk_injoffset;
++ static const char * const ntp_name[] = {
++ "offset",
++ "freq",
++ "status",
++ "tai",
++ "tick",
++ "adjust",
++ };
++ int type;
++
++ if (context->type == AUDIT_TIME_ADJNTPVAL) {
++ for (type = 0; type < AUDIT_NTP_NVALS; type++) {
++ if (ntp->vals[type].newval != ntp->vals[type].oldval) {
++ if (!*ab) {
++ *ab = audit_log_start(context,
++ GFP_KERNEL,
++ AUDIT_TIME_ADJNTPVAL);
++ if (!*ab)
++ return;
++ }
++ audit_log_format(*ab, "op=%s old=%lli new=%lli",
++ ntp_name[type],
++ ntp->vals[type].oldval,
++ ntp->vals[type].newval);
++ audit_log_end(*ab);
++ *ab = NULL;
++ }
++ }
++ }
++ if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
++ if (!*ab) {
++ *ab = audit_log_start(context, GFP_KERNEL,
++ AUDIT_TIME_INJOFFSET);
++ if (!*ab)
++ return;
++ }
++ audit_log_format(*ab, "sec=%lli nsec=%li",
++ (long long)tk->tv_sec, tk->tv_nsec);
++ audit_log_end(*ab);
++ *ab = NULL;
++ }
++}
++
+ static void show_special(struct audit_context *context, int *call_panic)
+ {
+ struct audit_buffer *ab;
+@@ -1327,6 +1374,11 @@ static void show_special(struct audit_context *context, int *call_panic)
+ audit_log_format(ab, "(null)");
+
+ break;
++ case AUDIT_TIME_ADJNTPVAL:
++ case AUDIT_TIME_INJOFFSET:
++ /* this call deviates from the rest, eating the buffer */
++ audit_log_time(context, &ab);
++ break;
+ }
+ audit_log_end(ab);
+ }
+@@ -2564,31 +2616,26 @@ void __audit_fanotify(unsigned int response)
+
+ void __audit_tk_injoffset(struct timespec64 offset)
+ {
+- audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET,
+- "sec=%lli nsec=%li",
+- (long long)offset.tv_sec, offset.tv_nsec);
+-}
+-
+-static void audit_log_ntp_val(const struct audit_ntp_data *ad,
+- const char *op, enum audit_ntp_type type)
+-{
+- const struct audit_ntp_val *val = &ad->vals[type];
+-
+- if (val->newval == val->oldval)
+- return;
++ struct audit_context *context = audit_context();
+
+- audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_ADJNTPVAL,
+- "op=%s old=%lli new=%lli", op, val->oldval, val->newval);
++ /* only set type if not already set by NTP */
++ if (!context->type)
++ context->type = AUDIT_TIME_INJOFFSET;
++ memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
+ }
+
+ void __audit_ntp_log(const struct audit_ntp_data *ad)
+ {
+- audit_log_ntp_val(ad, "offset", AUDIT_NTP_OFFSET);
+- audit_log_ntp_val(ad, "freq", AUDIT_NTP_FREQ);
+- audit_log_ntp_val(ad, "status", AUDIT_NTP_STATUS);
+- audit_log_ntp_val(ad, "tai", AUDIT_NTP_TAI);
+- audit_log_ntp_val(ad, "tick", AUDIT_NTP_TICK);
+- audit_log_ntp_val(ad, "adjust", AUDIT_NTP_ADJUST);
++ struct audit_context *context = audit_context();
++ int type;
++
++ for (type = 0; type < AUDIT_NTP_NVALS; type++)
++ if (ad->vals[type].newval != ad->vals[type].oldval) {
++ /* unconditionally set type, overwriting TK */
++ context->type = AUDIT_TIME_ADJNTPVAL;
++ memcpy(&context->time.ntp_data, ad, sizeof(*ad));
++ break;
++ }
+ }
+
+ void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
-index dfe61df4f974d..b8ed4da63bc8c 100644
+index dfe61df4f974d..40df35088cdbd 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4332,8 +4332,7 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
@@ -136182,10 +207641,125 @@ index dfe61df4f974d..b8ed4da63bc8c 100644
err = -EINVAL;
goto errout;
}
+@@ -4801,10 +4800,12 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ /* check for PTR_TO_RDONLY_BUF_OR_NULL or PTR_TO_RDWR_BUF_OR_NULL */
+ for (i = 0; i < prog->aux->ctx_arg_info_size; i++) {
+ const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i];
++ u32 type, flag;
+
+- if (ctx_arg_info->offset == off &&
+- (ctx_arg_info->reg_type == PTR_TO_RDONLY_BUF_OR_NULL ||
+- ctx_arg_info->reg_type == PTR_TO_RDWR_BUF_OR_NULL)) {
++ type = base_type(ctx_arg_info->reg_type);
++ flag = type_flag(ctx_arg_info->reg_type);
++ if (ctx_arg_info->offset == off && type == PTR_TO_BUF &&
++ (flag & PTR_MAYBE_NULL)) {
+ info->reg_type = ctx_arg_info->reg_type;
+ return true;
+ }
+@@ -5509,9 +5510,9 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
+ if (reg->type == PTR_TO_BTF_ID) {
+ reg_btf = reg->btf;
+ reg_ref_id = reg->btf_id;
+- } else if (reg2btf_ids[reg->type]) {
++ } else if (reg2btf_ids[base_type(reg->type)]) {
+ reg_btf = btf_vmlinux;
+- reg_ref_id = *reg2btf_ids[reg->type];
++ reg_ref_id = *reg2btf_ids[base_type(reg->type)];
+ } else {
+ bpf_log(log, "kernel function %s args#%d expected pointer to %s %s but R%d is not a pointer to btf_id\n",
+ func_name, i,
+@@ -5718,7 +5719,7 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
+ return -EINVAL;
+ }
+
+- reg->type = PTR_TO_MEM_OR_NULL;
++ reg->type = PTR_TO_MEM | PTR_MAYBE_NULL;
+ reg->id = ++env->id_gen;
+
+ continue;
+@@ -6007,12 +6008,17 @@ bool btf_id_set_contains(const struct btf_id_set *set, u32 id)
+ return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL;
+ }
+
++enum {
++ BTF_MODULE_F_LIVE = (1 << 0),
++};
++
+ #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+ struct btf_module {
+ struct list_head list;
+ struct module *module;
+ struct btf *btf;
+ struct bin_attribute *sysfs_attr;
++ int flags;
+ };
+
+ static LIST_HEAD(btf_modules);
+@@ -6038,7 +6044,8 @@ static int btf_module_notify(struct notifier_block *nb, unsigned long op,
+ int err = 0;
+
+ if (mod->btf_data_size == 0 ||
+- (op != MODULE_STATE_COMING && op != MODULE_STATE_GOING))
++ (op != MODULE_STATE_COMING && op != MODULE_STATE_LIVE &&
++ op != MODULE_STATE_GOING))
+ goto out;
+
+ switch (op) {
+@@ -6095,6 +6102,17 @@ static int btf_module_notify(struct notifier_block *nb, unsigned long op,
+ btf_mod->sysfs_attr = attr;
+ }
+
++ break;
++ case MODULE_STATE_LIVE:
++ mutex_lock(&btf_module_mutex);
++ list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
++ if (btf_mod->module != module)
++ continue;
++
++ btf_mod->flags |= BTF_MODULE_F_LIVE;
++ break;
++ }
++ mutex_unlock(&btf_module_mutex);
+ break;
+ case MODULE_STATE_GOING:
+ mutex_lock(&btf_module_mutex);
+@@ -6141,7 +6159,12 @@ struct module *btf_try_get_module(const struct btf *btf)
+ if (btf_mod->btf != btf)
+ continue;
+
+- if (try_module_get(btf_mod->module))
++ /* We must only consider module whose __init routine has
++ * finished, hence we must check for BTF_MODULE_F_LIVE flag,
++ * which is set from the notifier callback for
++ * MODULE_STATE_LIVE.
++ */
++ if ((btf_mod->flags & BTF_MODULE_F_LIVE) && try_module_get(btf_mod->module))
+ res = btf_mod->module;
+
+ break;
+@@ -6208,7 +6231,7 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = {
+ .func = bpf_btf_find_by_name_kind,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+- .arg1_type = ARG_PTR_TO_MEM,
++ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg2_type = ARG_CONST_SIZE,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_ANYTHING,
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
-index 03145d45e3d5b..7dbd68195a2b0 100644
+index 03145d45e3d5b..fe053ffd89329 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
+@@ -1753,7 +1753,7 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ };
+
@@ -1773,6 +1773,8 @@ sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_sysctl_get_new_value_proto;
case BPF_FUNC_sysctl_set_new_value:
@@ -136196,9 +207770,63 @@ index 03145d45e3d5b..7dbd68195a2b0 100644
return cgroup_base_func_proto(func_id, prog);
}
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
-index 9aabf84afd4b2..6f600cc95ccda 100644
+index 9aabf84afd4b2..a711ffe238932 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
+@@ -530,7 +530,7 @@ const struct bpf_func_proto bpf_strtol_proto = {
+ .func = bpf_strtol,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+- .arg1_type = ARG_PTR_TO_MEM,
++ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg2_type = ARG_CONST_SIZE,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_PTR_TO_LONG,
+@@ -558,7 +558,7 @@ const struct bpf_func_proto bpf_strtoul_proto = {
+ .func = bpf_strtoul,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+- .arg1_type = ARG_PTR_TO_MEM,
++ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg2_type = ARG_CONST_SIZE,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_PTR_TO_LONG,
+@@ -630,7 +630,7 @@ const struct bpf_func_proto bpf_event_output_data_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -667,7 +667,7 @@ BPF_CALL_2(bpf_per_cpu_ptr, const void *, ptr, u32, cpu)
+ const struct bpf_func_proto bpf_per_cpu_ptr_proto = {
+ .func = bpf_per_cpu_ptr,
+ .gpl_only = false,
+- .ret_type = RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL,
++ .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID,
+ .arg2_type = ARG_ANYTHING,
+ };
+@@ -680,7 +680,7 @@ BPF_CALL_1(bpf_this_cpu_ptr, const void *, percpu_ptr)
+ const struct bpf_func_proto bpf_this_cpu_ptr_proto = {
+ .func = bpf_this_cpu_ptr,
+ .gpl_only = false,
+- .ret_type = RET_PTR_TO_MEM_OR_BTF_ID,
++ .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | MEM_RDONLY,
+ .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID,
+ };
+
+@@ -1013,7 +1013,7 @@ const struct bpf_func_proto bpf_snprintf_proto = {
+ .arg1_type = ARG_PTR_TO_MEM_OR_NULL,
+ .arg2_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg3_type = ARG_PTR_TO_CONST_STR,
+- .arg4_type = ARG_PTR_TO_MEM_OR_NULL,
++ .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
@@ -1367,8 +1367,6 @@ bpf_base_func_proto(enum bpf_func_id func_id)
return &bpf_ktime_get_ns_proto;
case BPF_FUNC_ktime_get_boot_ns:
@@ -136237,8 +207865,24 @@ index 80da1db47c686..5a8d9f7467bf4 100644
switch (opt) {
case OPT_MODE:
+diff --git a/kernel/bpf/map_iter.c b/kernel/bpf/map_iter.c
+index 6a9542af4212a..b0fa190b09790 100644
+--- a/kernel/bpf/map_iter.c
++++ b/kernel/bpf/map_iter.c
+@@ -174,9 +174,9 @@ static const struct bpf_iter_reg bpf_map_elem_reg_info = {
+ .ctx_arg_info_size = 2,
+ .ctx_arg_info = {
+ { offsetof(struct bpf_iter__bpf_map_elem, key),
+- PTR_TO_RDONLY_BUF_OR_NULL },
++ PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY },
+ { offsetof(struct bpf_iter__bpf_map_elem, value),
+- PTR_TO_RDWR_BUF_OR_NULL },
++ PTR_TO_BUF | PTR_MAYBE_NULL },
+ },
+ };
+
diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c
-index 9e0c10c6892ad..f1c51c45667d3 100644
+index 9e0c10c6892ad..710ba9de12ce4 100644
--- a/kernel/bpf/ringbuf.c
+++ b/kernel/bpf/ringbuf.c
@@ -104,7 +104,7 @@ static struct bpf_ringbuf *bpf_ringbuf_area_alloc(size_t data_sz, int numa_node)
@@ -136250,11 +207894,155 @@ index 9e0c10c6892ad..f1c51c45667d3 100644
if (rb) {
kmemleak_not_leak(pages);
rb->pages = pages;
+@@ -444,7 +444,7 @@ const struct bpf_func_proto bpf_ringbuf_output_proto = {
+ .func = bpf_ringbuf_output,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_CONST_MAP_PTR,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg4_type = ARG_ANYTHING,
+ };
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
-index 6e75bbee39f0b..0dcaed4d3f4ce 100644
+index 6e75bbee39f0b..fc0f77f91224b 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
-@@ -525,13 +525,14 @@ BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf,
+@@ -219,7 +219,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
+ }
+
+ static struct perf_callchain_entry *
+-get_callchain_entry_for_task(struct task_struct *task, u32 init_nr)
++get_callchain_entry_for_task(struct task_struct *task, u32 max_depth)
+ {
+ #ifdef CONFIG_STACKTRACE
+ struct perf_callchain_entry *entry;
+@@ -230,9 +230,8 @@ get_callchain_entry_for_task(struct task_struct *task, u32 init_nr)
+ if (!entry)
+ return NULL;
+
+- entry->nr = init_nr +
+- stack_trace_save_tsk(task, (unsigned long *)(entry->ip + init_nr),
+- sysctl_perf_event_max_stack - init_nr, 0);
++ entry->nr = stack_trace_save_tsk(task, (unsigned long *)entry->ip,
++ max_depth, 0);
+
+ /* stack_trace_save_tsk() works on unsigned long array, while
+ * perf_callchain_entry uses u64 array. For 32-bit systems, it is
+@@ -244,7 +243,7 @@ get_callchain_entry_for_task(struct task_struct *task, u32 init_nr)
+ int i;
+
+ /* copy data from the end to avoid using extra buffer */
+- for (i = entry->nr - 1; i >= (int)init_nr; i--)
++ for (i = entry->nr - 1; i >= 0; i--)
+ to[i] = (u64)(from[i]);
+ }
+
+@@ -261,27 +260,19 @@ static long __bpf_get_stackid(struct bpf_map *map,
+ {
+ struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map);
+ struct stack_map_bucket *bucket, *new_bucket, *old_bucket;
+- u32 max_depth = map->value_size / stack_map_data_size(map);
+- /* stack_map_alloc() checks that max_depth <= sysctl_perf_event_max_stack */
+- u32 init_nr = sysctl_perf_event_max_stack - max_depth;
+ u32 skip = flags & BPF_F_SKIP_FIELD_MASK;
+ u32 hash, id, trace_nr, trace_len;
+ bool user = flags & BPF_F_USER_STACK;
+ u64 *ips;
+ bool hash_matches;
+
+- /* get_perf_callchain() guarantees that trace->nr >= init_nr
+- * and trace-nr <= sysctl_perf_event_max_stack, so trace_nr <= max_depth
+- */
+- trace_nr = trace->nr - init_nr;
+-
+- if (trace_nr <= skip)
++ if (trace->nr <= skip)
+ /* skipping more than usable stack trace */
+ return -EFAULT;
+
+- trace_nr -= skip;
++ trace_nr = trace->nr - skip;
+ trace_len = trace_nr * sizeof(u64);
+- ips = trace->ip + skip + init_nr;
++ ips = trace->ip + skip;
+ hash = jhash2((u32 *)ips, trace_len / sizeof(u32), 0);
+ id = hash & (smap->n_buckets - 1);
+ bucket = READ_ONCE(smap->buckets[id]);
+@@ -338,8 +329,7 @@ BPF_CALL_3(bpf_get_stackid, struct pt_regs *, regs, struct bpf_map *, map,
+ u64, flags)
+ {
+ u32 max_depth = map->value_size / stack_map_data_size(map);
+- /* stack_map_alloc() checks that max_depth <= sysctl_perf_event_max_stack */
+- u32 init_nr = sysctl_perf_event_max_stack - max_depth;
++ u32 skip = flags & BPF_F_SKIP_FIELD_MASK;
+ bool user = flags & BPF_F_USER_STACK;
+ struct perf_callchain_entry *trace;
+ bool kernel = !user;
+@@ -348,8 +338,12 @@ BPF_CALL_3(bpf_get_stackid, struct pt_regs *, regs, struct bpf_map *, map,
+ BPF_F_FAST_STACK_CMP | BPF_F_REUSE_STACKID)))
+ return -EINVAL;
+
+- trace = get_perf_callchain(regs, init_nr, kernel, user,
+- sysctl_perf_event_max_stack, false, false);
++ max_depth += skip;
++ if (max_depth > sysctl_perf_event_max_stack)
++ max_depth = sysctl_perf_event_max_stack;
++
++ trace = get_perf_callchain(regs, 0, kernel, user, max_depth,
++ false, false);
+
+ if (unlikely(!trace))
+ /* couldn't fetch the stack trace */
+@@ -440,7 +434,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
+ struct perf_callchain_entry *trace_in,
+ void *buf, u32 size, u64 flags)
+ {
+- u32 init_nr, trace_nr, copy_len, elem_size, num_elem;
++ u32 trace_nr, copy_len, elem_size, num_elem, max_depth;
+ bool user_build_id = flags & BPF_F_USER_BUILD_ID;
+ u32 skip = flags & BPF_F_SKIP_FIELD_MASK;
+ bool user = flags & BPF_F_USER_STACK;
+@@ -465,30 +459,28 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
+ goto err_fault;
+
+ num_elem = size / elem_size;
+- if (sysctl_perf_event_max_stack < num_elem)
+- init_nr = 0;
+- else
+- init_nr = sysctl_perf_event_max_stack - num_elem;
++ max_depth = num_elem + skip;
++ if (sysctl_perf_event_max_stack < max_depth)
++ max_depth = sysctl_perf_event_max_stack;
+
+ if (trace_in)
+ trace = trace_in;
+ else if (kernel && task)
+- trace = get_callchain_entry_for_task(task, init_nr);
++ trace = get_callchain_entry_for_task(task, max_depth);
+ else
+- trace = get_perf_callchain(regs, init_nr, kernel, user,
+- sysctl_perf_event_max_stack,
++ trace = get_perf_callchain(regs, 0, kernel, user, max_depth,
+ false, false);
+ if (unlikely(!trace))
+ goto err_fault;
+
+- trace_nr = trace->nr - init_nr;
+- if (trace_nr < skip)
++ if (trace->nr < skip)
+ goto err_fault;
+
+- trace_nr -= skip;
++ trace_nr = trace->nr - skip;
+ trace_nr = (trace_nr <= num_elem) ? trace_nr : num_elem;
+ copy_len = trace_nr * elem_size;
+- ips = trace->ip + skip + init_nr;
++
++ ips = trace->ip + skip;
+ if (user && user_build_id)
+ stack_map_get_build_id_offset(buf, ips, trace_nr, user);
+ else
+@@ -525,13 +517,14 @@ BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf,
u32, size, u64, flags)
{
struct pt_regs *regs;
@@ -136272,7 +208060,7 @@ index 6e75bbee39f0b..0dcaed4d3f4ce 100644
return res;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
-index 1cad6979a0d0f..42490c39dfbf5 100644
+index 1cad6979a0d0f..48e02a725563f 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -132,6 +132,21 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
@@ -136505,6 +208293,15 @@ index 1cad6979a0d0f..42490c39dfbf5 100644
fdput(f);
return err;
}
+@@ -4729,7 +4753,7 @@ static const struct bpf_func_proto bpf_sys_bpf_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_ANYTHING,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ };
+
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index fe1e857324e66..2660fbced9ad4 100644
--- a/kernel/bpf/trampoline.c
@@ -136544,10 +208341,209 @@ index fe1e857324e66..2660fbced9ad4 100644
}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
-index e76b559179054..670721e39c0e8 100644
+index e76b559179054..d2b119b4fbe74 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
-@@ -1143,7 +1143,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
+@@ -445,18 +445,6 @@ static bool reg_type_not_null(enum bpf_reg_type type)
+ type == PTR_TO_SOCK_COMMON;
+ }
+
+-static bool reg_type_may_be_null(enum bpf_reg_type type)
+-{
+- return type == PTR_TO_MAP_VALUE_OR_NULL ||
+- type == PTR_TO_SOCKET_OR_NULL ||
+- type == PTR_TO_SOCK_COMMON_OR_NULL ||
+- type == PTR_TO_TCP_SOCK_OR_NULL ||
+- type == PTR_TO_BTF_ID_OR_NULL ||
+- type == PTR_TO_MEM_OR_NULL ||
+- type == PTR_TO_RDONLY_BUF_OR_NULL ||
+- type == PTR_TO_RDWR_BUF_OR_NULL;
+-}
+-
+ static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
+ {
+ return reg->type == PTR_TO_MAP_VALUE &&
+@@ -465,12 +453,14 @@ static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
+
+ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
+ {
+- return type == PTR_TO_SOCKET ||
+- type == PTR_TO_SOCKET_OR_NULL ||
+- type == PTR_TO_TCP_SOCK ||
+- type == PTR_TO_TCP_SOCK_OR_NULL ||
+- type == PTR_TO_MEM ||
+- type == PTR_TO_MEM_OR_NULL;
++ return base_type(type) == PTR_TO_SOCKET ||
++ base_type(type) == PTR_TO_TCP_SOCK ||
++ base_type(type) == PTR_TO_MEM;
++}
++
++static bool type_is_rdonly_mem(u32 type)
++{
++ return type & MEM_RDONLY;
+ }
+
+ static bool arg_type_may_be_refcounted(enum bpf_arg_type type)
+@@ -478,14 +468,9 @@ static bool arg_type_may_be_refcounted(enum bpf_arg_type type)
+ return type == ARG_PTR_TO_SOCK_COMMON;
+ }
+
+-static bool arg_type_may_be_null(enum bpf_arg_type type)
++static bool type_may_be_null(u32 type)
+ {
+- return type == ARG_PTR_TO_MAP_VALUE_OR_NULL ||
+- type == ARG_PTR_TO_MEM_OR_NULL ||
+- type == ARG_PTR_TO_CTX_OR_NULL ||
+- type == ARG_PTR_TO_SOCKET_OR_NULL ||
+- type == ARG_PTR_TO_ALLOC_MEM_OR_NULL ||
+- type == ARG_PTR_TO_STACK_OR_NULL;
++ return type & PTR_MAYBE_NULL;
+ }
+
+ /* Determine whether the function releases some resources allocated by another
+@@ -545,39 +530,54 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
+ insn->imm == BPF_CMPXCHG;
+ }
+
+-/* string representation of 'enum bpf_reg_type' */
+-static const char * const reg_type_str[] = {
+- [NOT_INIT] = "?",
+- [SCALAR_VALUE] = "inv",
+- [PTR_TO_CTX] = "ctx",
+- [CONST_PTR_TO_MAP] = "map_ptr",
+- [PTR_TO_MAP_VALUE] = "map_value",
+- [PTR_TO_MAP_VALUE_OR_NULL] = "map_value_or_null",
+- [PTR_TO_STACK] = "fp",
+- [PTR_TO_PACKET] = "pkt",
+- [PTR_TO_PACKET_META] = "pkt_meta",
+- [PTR_TO_PACKET_END] = "pkt_end",
+- [PTR_TO_FLOW_KEYS] = "flow_keys",
+- [PTR_TO_SOCKET] = "sock",
+- [PTR_TO_SOCKET_OR_NULL] = "sock_or_null",
+- [PTR_TO_SOCK_COMMON] = "sock_common",
+- [PTR_TO_SOCK_COMMON_OR_NULL] = "sock_common_or_null",
+- [PTR_TO_TCP_SOCK] = "tcp_sock",
+- [PTR_TO_TCP_SOCK_OR_NULL] = "tcp_sock_or_null",
+- [PTR_TO_TP_BUFFER] = "tp_buffer",
+- [PTR_TO_XDP_SOCK] = "xdp_sock",
+- [PTR_TO_BTF_ID] = "ptr_",
+- [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_",
+- [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_",
+- [PTR_TO_MEM] = "mem",
+- [PTR_TO_MEM_OR_NULL] = "mem_or_null",
+- [PTR_TO_RDONLY_BUF] = "rdonly_buf",
+- [PTR_TO_RDONLY_BUF_OR_NULL] = "rdonly_buf_or_null",
+- [PTR_TO_RDWR_BUF] = "rdwr_buf",
+- [PTR_TO_RDWR_BUF_OR_NULL] = "rdwr_buf_or_null",
+- [PTR_TO_FUNC] = "func",
+- [PTR_TO_MAP_KEY] = "map_key",
+-};
++/* string representation of 'enum bpf_reg_type'
++ *
++ * Note that reg_type_str() can not appear more than once in a single verbose()
++ * statement.
++ */
++static const char *reg_type_str(struct bpf_verifier_env *env,
++ enum bpf_reg_type type)
++{
++ char postfix[16] = {0}, prefix[16] = {0};
++ static const char * const str[] = {
++ [NOT_INIT] = "?",
++ [SCALAR_VALUE] = "inv",
++ [PTR_TO_CTX] = "ctx",
++ [CONST_PTR_TO_MAP] = "map_ptr",
++ [PTR_TO_MAP_VALUE] = "map_value",
++ [PTR_TO_STACK] = "fp",
++ [PTR_TO_PACKET] = "pkt",
++ [PTR_TO_PACKET_META] = "pkt_meta",
++ [PTR_TO_PACKET_END] = "pkt_end",
++ [PTR_TO_FLOW_KEYS] = "flow_keys",
++ [PTR_TO_SOCKET] = "sock",
++ [PTR_TO_SOCK_COMMON] = "sock_common",
++ [PTR_TO_TCP_SOCK] = "tcp_sock",
++ [PTR_TO_TP_BUFFER] = "tp_buffer",
++ [PTR_TO_XDP_SOCK] = "xdp_sock",
++ [PTR_TO_BTF_ID] = "ptr_",
++ [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_",
++ [PTR_TO_MEM] = "mem",
++ [PTR_TO_BUF] = "buf",
++ [PTR_TO_FUNC] = "func",
++ [PTR_TO_MAP_KEY] = "map_key",
++ };
++
++ if (type & PTR_MAYBE_NULL) {
++ if (base_type(type) == PTR_TO_BTF_ID ||
++ base_type(type) == PTR_TO_PERCPU_BTF_ID)
++ strncpy(postfix, "or_null_", 16);
++ else
++ strncpy(postfix, "_or_null", 16);
++ }
++
++ if (type & MEM_RDONLY)
++ strncpy(prefix, "rdonly_", 16);
++
++ snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s",
++ prefix, str[base_type(type)], postfix);
++ return env->type_str_buf;
++}
+
+ static char slot_type_char[] = {
+ [STACK_INVALID] = '?',
+@@ -628,7 +628,7 @@ static void print_verifier_state(struct bpf_verifier_env *env,
+ continue;
+ verbose(env, " R%d", i);
+ print_liveness(env, reg->live);
+- verbose(env, "=%s", reg_type_str[t]);
++ verbose(env, "=%s", reg_type_str(env, t));
+ if (t == SCALAR_VALUE && reg->precise)
+ verbose(env, "P");
+ if ((t == SCALAR_VALUE || t == PTR_TO_STACK) &&
+@@ -636,9 +636,8 @@ static void print_verifier_state(struct bpf_verifier_env *env,
+ /* reg->off should be 0 for SCALAR_VALUE */
+ verbose(env, "%lld", reg->var_off.value + reg->off);
+ } else {
+- if (t == PTR_TO_BTF_ID ||
+- t == PTR_TO_BTF_ID_OR_NULL ||
+- t == PTR_TO_PERCPU_BTF_ID)
++ if (base_type(t) == PTR_TO_BTF_ID ||
++ base_type(t) == PTR_TO_PERCPU_BTF_ID)
+ verbose(env, "%s", kernel_type_name(reg->btf, reg->btf_id));
+ verbose(env, "(id=%d", reg->id);
+ if (reg_type_may_be_refcounted_or_null(t))
+@@ -647,10 +646,9 @@ static void print_verifier_state(struct bpf_verifier_env *env,
+ verbose(env, ",off=%d", reg->off);
+ if (type_is_pkt_pointer(t))
+ verbose(env, ",r=%d", reg->range);
+- else if (t == CONST_PTR_TO_MAP ||
+- t == PTR_TO_MAP_KEY ||
+- t == PTR_TO_MAP_VALUE ||
+- t == PTR_TO_MAP_VALUE_OR_NULL)
++ else if (base_type(t) == CONST_PTR_TO_MAP ||
++ base_type(t) == PTR_TO_MAP_KEY ||
++ base_type(t) == PTR_TO_MAP_VALUE)
+ verbose(env, ",ks=%d,vs=%d",
+ reg->map_ptr->key_size,
+ reg->map_ptr->value_size);
+@@ -720,7 +718,7 @@ static void print_verifier_state(struct bpf_verifier_env *env,
+ if (state->stack[i].slot_type[0] == STACK_SPILL) {
+ reg = &state->stack[i].spilled_ptr;
+ t = reg->type;
+- verbose(env, "=%s", reg_type_str[t]);
++ verbose(env, "=%s", reg_type_str(env, t));
+ if (t == SCALAR_VALUE && reg->precise)
+ verbose(env, "P");
+ if (t == SCALAR_VALUE && tnum_is_const(reg->var_off))
+@@ -1133,8 +1131,7 @@ static void mark_reg_known_zero(struct bpf_verifier_env *env,
+
+ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
+ {
+- switch (reg->type) {
+- case PTR_TO_MAP_VALUE_OR_NULL: {
++ if (base_type(reg->type) == PTR_TO_MAP_VALUE) {
+ const struct bpf_map *map = reg->map_ptr;
+
+ if (map->inner_map_meta) {
+@@ -1143,7 +1140,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
/* transfer reg's id which is unique for every map_lookup_elem
* as UID of the inner map.
*/
@@ -136557,7 +208553,43 @@ index e76b559179054..670721e39c0e8 100644
} else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
reg->type = PTR_TO_XDP_SOCK;
} else if (map->map_type == BPF_MAP_TYPE_SOCKMAP ||
-@@ -1357,22 +1358,28 @@ static void __reg_bound_offset(struct bpf_reg_state *reg)
+@@ -1152,32 +1150,10 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
+ } else {
+ reg->type = PTR_TO_MAP_VALUE;
+ }
+- break;
+- }
+- case PTR_TO_SOCKET_OR_NULL:
+- reg->type = PTR_TO_SOCKET;
+- break;
+- case PTR_TO_SOCK_COMMON_OR_NULL:
+- reg->type = PTR_TO_SOCK_COMMON;
+- break;
+- case PTR_TO_TCP_SOCK_OR_NULL:
+- reg->type = PTR_TO_TCP_SOCK;
+- break;
+- case PTR_TO_BTF_ID_OR_NULL:
+- reg->type = PTR_TO_BTF_ID;
+- break;
+- case PTR_TO_MEM_OR_NULL:
+- reg->type = PTR_TO_MEM;
+- break;
+- case PTR_TO_RDONLY_BUF_OR_NULL:
+- reg->type = PTR_TO_RDONLY_BUF;
+- break;
+- case PTR_TO_RDWR_BUF_OR_NULL:
+- reg->type = PTR_TO_RDWR_BUF;
+- break;
+- default:
+- WARN_ONCE(1, "unknown nullable register type");
++ return;
+ }
++
++ reg->type &= ~PTR_MAYBE_NULL;
+ }
+
+ static bool reg_is_pkt_pointer(const struct bpf_reg_state *reg)
+@@ -1357,22 +1333,28 @@ static void __reg_bound_offset(struct bpf_reg_state *reg)
reg->var_off = tnum_or(tnum_clear_subreg(var64_off), var32_off);
}
@@ -136595,7 +208627,7 @@ index e76b559179054..670721e39c0e8 100644
}
static void __reg_combine_32_into_64(struct bpf_reg_state *reg)
-@@ -1406,12 +1413,12 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg)
+@@ -1406,12 +1388,12 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg)
static bool __reg64_bound_s32(s64 a)
{
@@ -136610,7 +208642,68 @@ index e76b559179054..670721e39c0e8 100644
}
static void __reg_combine_64_into_32(struct bpf_reg_state *reg)
-@@ -3884,7 +3891,22 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size)
+@@ -1899,7 +1881,7 @@ static int mark_reg_read(struct bpf_verifier_env *env,
+ break;
+ if (parent->live & REG_LIVE_DONE) {
+ verbose(env, "verifier BUG type %s var_off %lld off %d\n",
+- reg_type_str[parent->type],
++ reg_type_str(env, parent->type),
+ parent->var_off.value, parent->off);
+ return -EFAULT;
+ }
+@@ -2557,9 +2539,8 @@ static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi)
+
+ static bool is_spillable_regtype(enum bpf_reg_type type)
+ {
+- switch (type) {
++ switch (base_type(type)) {
+ case PTR_TO_MAP_VALUE:
+- case PTR_TO_MAP_VALUE_OR_NULL:
+ case PTR_TO_STACK:
+ case PTR_TO_CTX:
+ case PTR_TO_PACKET:
+@@ -2568,21 +2549,13 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
+ case PTR_TO_FLOW_KEYS:
+ case CONST_PTR_TO_MAP:
+ case PTR_TO_SOCKET:
+- case PTR_TO_SOCKET_OR_NULL:
+ case PTR_TO_SOCK_COMMON:
+- case PTR_TO_SOCK_COMMON_OR_NULL:
+ case PTR_TO_TCP_SOCK:
+- case PTR_TO_TCP_SOCK_OR_NULL:
+ case PTR_TO_XDP_SOCK:
+ case PTR_TO_BTF_ID:
+- case PTR_TO_BTF_ID_OR_NULL:
+- case PTR_TO_RDONLY_BUF:
+- case PTR_TO_RDONLY_BUF_OR_NULL:
+- case PTR_TO_RDWR_BUF:
+- case PTR_TO_RDWR_BUF_OR_NULL:
++ case PTR_TO_BUF:
+ case PTR_TO_PERCPU_BTF_ID:
+ case PTR_TO_MEM:
+- case PTR_TO_MEM_OR_NULL:
+ case PTR_TO_FUNC:
+ case PTR_TO_MAP_KEY:
+ return true;
+@@ -3398,7 +3371,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
+ */
+ *reg_type = info.reg_type;
+
+- if (*reg_type == PTR_TO_BTF_ID || *reg_type == PTR_TO_BTF_ID_OR_NULL) {
++ if (base_type(*reg_type) == PTR_TO_BTF_ID) {
+ *btf = info.btf;
+ *btf_id = info.btf_id;
+ } else {
+@@ -3466,7 +3439,7 @@ static int check_sock_access(struct bpf_verifier_env *env, int insn_idx,
+ }
+
+ verbose(env, "R%d invalid %s access off=%d size=%d\n",
+- regno, reg_type_str[reg->type], off, size);
++ regno, reg_type_str(env, reg->type), off, size);
+
+ return -EACCES;
+ }
+@@ -3884,7 +3857,22 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size)
static bool bpf_map_is_rdonly(const struct bpf_map *map)
{
@@ -136634,7 +208727,116 @@ index e76b559179054..670721e39c0e8 100644
}
static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val)
-@@ -4364,9 +4386,16 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
+@@ -4178,15 +4166,30 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ mark_reg_unknown(env, regs, value_regno);
+ }
+ }
+- } else if (reg->type == PTR_TO_MEM) {
++ } else if (base_type(reg->type) == PTR_TO_MEM) {
++ bool rdonly_mem = type_is_rdonly_mem(reg->type);
++
++ if (type_may_be_null(reg->type)) {
++ verbose(env, "R%d invalid mem access '%s'\n", regno,
++ reg_type_str(env, reg->type));
++ return -EACCES;
++ }
++
++ if (t == BPF_WRITE && rdonly_mem) {
++ verbose(env, "R%d cannot write into %s\n",
++ regno, reg_type_str(env, reg->type));
++ return -EACCES;
++ }
++
+ if (t == BPF_WRITE && value_regno >= 0 &&
+ is_pointer_value(env, value_regno)) {
+ verbose(env, "R%d leaks addr into mem\n", value_regno);
+ return -EACCES;
+ }
++
+ err = check_mem_region_access(env, regno, off, size,
+ reg->mem_size, false);
+- if (!err && t == BPF_READ && value_regno >= 0)
++ if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem))
+ mark_reg_unknown(env, regs, value_regno);
+ } else if (reg->type == PTR_TO_CTX) {
+ enum bpf_reg_type reg_type = SCALAR_VALUE;
+@@ -4216,7 +4219,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ } else {
+ mark_reg_known_zero(env, regs,
+ value_regno);
+- if (reg_type_may_be_null(reg_type))
++ if (type_may_be_null(reg_type))
+ regs[value_regno].id = ++env->id_gen;
+ /* A load of ctx field could have different
+ * actual load size with the one encoded in the
+@@ -4224,8 +4227,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ * a sub-register.
+ */
+ regs[value_regno].subreg_def = DEF_NOT_SUBREG;
+- if (reg_type == PTR_TO_BTF_ID ||
+- reg_type == PTR_TO_BTF_ID_OR_NULL) {
++ if (base_type(reg_type) == PTR_TO_BTF_ID) {
+ regs[value_regno].btf = btf;
+ regs[value_regno].btf_id = btf_id;
+ }
+@@ -4278,7 +4280,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ } else if (type_is_sk_pointer(reg->type)) {
+ if (t == BPF_WRITE) {
+ verbose(env, "R%d cannot write into %s\n",
+- regno, reg_type_str[reg->type]);
++ regno, reg_type_str(env, reg->type));
+ return -EACCES;
+ }
+ err = check_sock_access(env, insn_idx, regno, off, size, t);
+@@ -4294,26 +4296,32 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ } else if (reg->type == CONST_PTR_TO_MAP) {
+ err = check_ptr_to_map_access(env, regs, regno, off, size, t,
+ value_regno);
+- } else if (reg->type == PTR_TO_RDONLY_BUF) {
+- if (t == BPF_WRITE) {
+- verbose(env, "R%d cannot write into %s\n",
+- regno, reg_type_str[reg->type]);
+- return -EACCES;
++ } else if (base_type(reg->type) == PTR_TO_BUF) {
++ bool rdonly_mem = type_is_rdonly_mem(reg->type);
++ const char *buf_info;
++ u32 *max_access;
++
++ if (rdonly_mem) {
++ if (t == BPF_WRITE) {
++ verbose(env, "R%d cannot write into %s\n",
++ regno, reg_type_str(env, reg->type));
++ return -EACCES;
++ }
++ buf_info = "rdonly";
++ max_access = &env->prog->aux->max_rdonly_access;
++ } else {
++ buf_info = "rdwr";
++ max_access = &env->prog->aux->max_rdwr_access;
+ }
++
+ err = check_buffer_access(env, reg, regno, off, size, false,
+- "rdonly",
+- &env->prog->aux->max_rdonly_access);
+- if (!err && value_regno >= 0)
+- mark_reg_unknown(env, regs, value_regno);
+- } else if (reg->type == PTR_TO_RDWR_BUF) {
+- err = check_buffer_access(env, reg, regno, off, size, false,
+- "rdwr",
+- &env->prog->aux->max_rdwr_access);
+- if (!err && t == BPF_READ && value_regno >= 0)
++ buf_info, max_access);
++
++ if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ))
+ mark_reg_unknown(env, regs, value_regno);
+ } else {
+ verbose(env, "R%d invalid mem access '%s'\n", regno,
+- reg_type_str[reg->type]);
++ reg_type_str(env, reg->type));
+ return -EACCES;
+ }
+
+@@ -4364,9 +4372,16 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
if (insn->imm == BPF_CMPXCHG) {
/* Check comparison of R0 with memory location */
@@ -136652,7 +208854,16 @@ index e76b559179054..670721e39c0e8 100644
}
if (is_pointer_value(env, insn->src_reg)) {
-@@ -4401,13 +4430,19 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
+@@ -4380,7 +4395,7 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
+ is_sk_reg(env, insn->dst_reg)) {
+ verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n",
+ insn->dst_reg,
+- reg_type_str[reg_state(env, insn->dst_reg)->type]);
++ reg_type_str(env, reg_state(env, insn->dst_reg)->type));
+ return -EACCES;
+ }
+
+@@ -4401,13 +4416,19 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
load_reg = -1;
}
@@ -136675,7 +208886,210 @@ index e76b559179054..670721e39c0e8 100644
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
BPF_SIZE(insn->code), BPF_WRITE, -1, true);
if (err)
-@@ -5750,6 +5785,7 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+@@ -4557,8 +4578,10 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+ struct bpf_call_arg_meta *meta)
+ {
+ struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
++ const char *buf_info;
++ u32 *max_access;
+
+- switch (reg->type) {
++ switch (base_type(reg->type)) {
+ case PTR_TO_PACKET:
+ case PTR_TO_PACKET_META:
+ return check_packet_access(env, regno, reg->off, access_size,
+@@ -4577,18 +4600,20 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+ return check_mem_region_access(env, regno, reg->off,
+ access_size, reg->mem_size,
+ zero_size_allowed);
+- case PTR_TO_RDONLY_BUF:
+- if (meta && meta->raw_mode)
+- return -EACCES;
+- return check_buffer_access(env, reg, regno, reg->off,
+- access_size, zero_size_allowed,
+- "rdonly",
+- &env->prog->aux->max_rdonly_access);
+- case PTR_TO_RDWR_BUF:
++ case PTR_TO_BUF:
++ if (type_is_rdonly_mem(reg->type)) {
++ if (meta && meta->raw_mode)
++ return -EACCES;
++
++ buf_info = "rdonly";
++ max_access = &env->prog->aux->max_rdonly_access;
++ } else {
++ buf_info = "rdwr";
++ max_access = &env->prog->aux->max_rdwr_access;
++ }
+ return check_buffer_access(env, reg, regno, reg->off,
+ access_size, zero_size_allowed,
+- "rdwr",
+- &env->prog->aux->max_rdwr_access);
++ buf_info, max_access);
+ case PTR_TO_STACK:
+ return check_stack_range_initialized(
+ env,
+@@ -4600,9 +4625,9 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+ register_is_null(reg))
+ return 0;
+
+- verbose(env, "R%d type=%s expected=%s\n", regno,
+- reg_type_str[reg->type],
+- reg_type_str[PTR_TO_STACK]);
++ verbose(env, "R%d type=%s ", regno,
++ reg_type_str(env, reg->type));
++ verbose(env, "expected=%s\n", reg_type_str(env, PTR_TO_STACK));
+ return -EACCES;
+ }
+ }
+@@ -4613,7 +4638,7 @@ int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+ if (register_is_null(reg))
+ return 0;
+
+- if (reg_type_may_be_null(reg->type)) {
++ if (type_may_be_null(reg->type)) {
+ /* Assuming that the register contains a value check if the memory
+ * access is safe. Temporarily save and restore the register's state as
+ * the conversion shouldn't be visible to a caller.
+@@ -4761,9 +4786,8 @@ static int process_timer_func(struct bpf_verifier_env *env, int regno,
+
+ static bool arg_type_is_mem_ptr(enum bpf_arg_type type)
+ {
+- return type == ARG_PTR_TO_MEM ||
+- type == ARG_PTR_TO_MEM_OR_NULL ||
+- type == ARG_PTR_TO_UNINIT_MEM;
++ return base_type(type) == ARG_PTR_TO_MEM ||
++ base_type(type) == ARG_PTR_TO_UNINIT_MEM;
+ }
+
+ static bool arg_type_is_mem_size(enum bpf_arg_type type)
+@@ -4865,8 +4889,7 @@ static const struct bpf_reg_types mem_types = {
+ PTR_TO_MAP_KEY,
+ PTR_TO_MAP_VALUE,
+ PTR_TO_MEM,
+- PTR_TO_RDONLY_BUF,
+- PTR_TO_RDWR_BUF,
++ PTR_TO_BUF,
+ },
+ };
+
+@@ -4897,31 +4920,26 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
+ [ARG_PTR_TO_MAP_KEY] = &map_key_value_types,
+ [ARG_PTR_TO_MAP_VALUE] = &map_key_value_types,
+ [ARG_PTR_TO_UNINIT_MAP_VALUE] = &map_key_value_types,
+- [ARG_PTR_TO_MAP_VALUE_OR_NULL] = &map_key_value_types,
+ [ARG_CONST_SIZE] = &scalar_types,
+ [ARG_CONST_SIZE_OR_ZERO] = &scalar_types,
+ [ARG_CONST_ALLOC_SIZE_OR_ZERO] = &scalar_types,
+ [ARG_CONST_MAP_PTR] = &const_map_ptr_types,
+ [ARG_PTR_TO_CTX] = &context_types,
+- [ARG_PTR_TO_CTX_OR_NULL] = &context_types,
+ [ARG_PTR_TO_SOCK_COMMON] = &sock_types,
+ #ifdef CONFIG_NET
+ [ARG_PTR_TO_BTF_ID_SOCK_COMMON] = &btf_id_sock_common_types,
+ #endif
+ [ARG_PTR_TO_SOCKET] = &fullsock_types,
+- [ARG_PTR_TO_SOCKET_OR_NULL] = &fullsock_types,
+ [ARG_PTR_TO_BTF_ID] = &btf_ptr_types,
+ [ARG_PTR_TO_SPIN_LOCK] = &spin_lock_types,
+ [ARG_PTR_TO_MEM] = &mem_types,
+- [ARG_PTR_TO_MEM_OR_NULL] = &mem_types,
+ [ARG_PTR_TO_UNINIT_MEM] = &mem_types,
+ [ARG_PTR_TO_ALLOC_MEM] = &alloc_mem_types,
+- [ARG_PTR_TO_ALLOC_MEM_OR_NULL] = &alloc_mem_types,
+ [ARG_PTR_TO_INT] = &int_ptr_types,
+ [ARG_PTR_TO_LONG] = &int_ptr_types,
+ [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types,
+ [ARG_PTR_TO_FUNC] = &func_ptr_types,
+- [ARG_PTR_TO_STACK_OR_NULL] = &stack_ptr_types,
++ [ARG_PTR_TO_STACK] = &stack_ptr_types,
+ [ARG_PTR_TO_CONST_STR] = &const_str_ptr_types,
+ [ARG_PTR_TO_TIMER] = &timer_types,
+ };
+@@ -4935,12 +4953,27 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
+ const struct bpf_reg_types *compatible;
+ int i, j;
+
+- compatible = compatible_reg_types[arg_type];
++ compatible = compatible_reg_types[base_type(arg_type)];
+ if (!compatible) {
+ verbose(env, "verifier internal error: unsupported arg type %d\n", arg_type);
+ return -EFAULT;
+ }
+
++ /* ARG_PTR_TO_MEM + RDONLY is compatible with PTR_TO_MEM and PTR_TO_MEM + RDONLY,
++ * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM and NOT with PTR_TO_MEM + RDONLY
++ *
++ * Same for MAYBE_NULL:
++ *
++ * ARG_PTR_TO_MEM + MAYBE_NULL is compatible with PTR_TO_MEM and PTR_TO_MEM + MAYBE_NULL,
++ * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM but NOT with PTR_TO_MEM + MAYBE_NULL
++ *
++ * Therefore we fold these flags depending on the arg_type before comparison.
++ */
++ if (arg_type & MEM_RDONLY)
++ type &= ~MEM_RDONLY;
++ if (arg_type & PTR_MAYBE_NULL)
++ type &= ~PTR_MAYBE_NULL;
++
+ for (i = 0; i < ARRAY_SIZE(compatible->types); i++) {
+ expected = compatible->types[i];
+ if (expected == NOT_INIT)
+@@ -4950,14 +4983,14 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
+ goto found;
+ }
+
+- verbose(env, "R%d type=%s expected=", regno, reg_type_str[type]);
++ verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, reg->type));
+ for (j = 0; j + 1 < i; j++)
+- verbose(env, "%s, ", reg_type_str[compatible->types[j]]);
+- verbose(env, "%s\n", reg_type_str[compatible->types[j]]);
++ verbose(env, "%s, ", reg_type_str(env, compatible->types[j]));
++ verbose(env, "%s\n", reg_type_str(env, compatible->types[j]));
+ return -EACCES;
+
+ found:
+- if (type == PTR_TO_BTF_ID) {
++ if (reg->type == PTR_TO_BTF_ID) {
+ if (!arg_btf_id) {
+ if (!compatible->btf_id) {
+ verbose(env, "verifier internal error: missing arg compatible BTF ID\n");
+@@ -5016,15 +5049,14 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+ return -EACCES;
+ }
+
+- if (arg_type == ARG_PTR_TO_MAP_VALUE ||
+- arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE ||
+- arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL) {
++ if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE ||
++ base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) {
+ err = resolve_map_arg_type(env, meta, &arg_type);
+ if (err)
+ return err;
+ }
+
+- if (register_is_null(reg) && arg_type_may_be_null(arg_type))
++ if (register_is_null(reg) && type_may_be_null(arg_type))
+ /* A NULL register has a SCALAR_VALUE type, so skip
+ * type checking.
+ */
+@@ -5093,10 +5125,11 @@ skip_type_check:
+ err = check_helper_mem_access(env, regno,
+ meta->map_ptr->key_size, false,
+ NULL);
+- } else if (arg_type == ARG_PTR_TO_MAP_VALUE ||
+- (arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL &&
+- !register_is_null(reg)) ||
+- arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) {
++ } else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE ||
++ base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) {
++ if (type_may_be_null(arg_type) && register_is_null(reg))
++ return 0;
++
+ /* bpf_map_xxx(..., map_ptr, ..., value) call:
+ * check [value, value + map->value_size) validity
+ */
+@@ -5750,6 +5783,7 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
}
if (insn->code == (BPF_JMP | BPF_CALL) &&
@@ -136683,7 +209097,184 @@ index e76b559179054..670721e39c0e8 100644
insn->imm == BPF_FUNC_timer_set_callback) {
struct bpf_verifier_state *async_cb;
-@@ -7004,16 +7040,16 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+@@ -6170,6 +6204,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+ int *insn_idx_p)
+ {
+ const struct bpf_func_proto *fn = NULL;
++ enum bpf_return_type ret_type;
++ enum bpf_type_flag ret_flag;
+ struct bpf_reg_state *regs;
+ struct bpf_call_arg_meta meta;
+ int insn_idx = *insn_idx_p;
+@@ -6303,13 +6339,14 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+ regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
+
+ /* update return register (already marked as written above) */
+- if (fn->ret_type == RET_INTEGER) {
++ ret_type = fn->ret_type;
++ ret_flag = type_flag(fn->ret_type);
++ if (ret_type == RET_INTEGER) {
+ /* sets type to SCALAR_VALUE */
+ mark_reg_unknown(env, regs, BPF_REG_0);
+- } else if (fn->ret_type == RET_VOID) {
++ } else if (ret_type == RET_VOID) {
+ regs[BPF_REG_0].type = NOT_INIT;
+- } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL ||
+- fn->ret_type == RET_PTR_TO_MAP_VALUE) {
++ } else if (base_type(ret_type) == RET_PTR_TO_MAP_VALUE) {
+ /* There is no offset yet applied, variable or fixed */
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+ /* remember map_ptr, so that check_map_access()
+@@ -6323,28 +6360,25 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+ }
+ regs[BPF_REG_0].map_ptr = meta.map_ptr;
+ regs[BPF_REG_0].map_uid = meta.map_uid;
+- if (fn->ret_type == RET_PTR_TO_MAP_VALUE) {
+- regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
+- if (map_value_has_spin_lock(meta.map_ptr))
+- regs[BPF_REG_0].id = ++env->id_gen;
+- } else {
+- regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
++ regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag;
++ if (!type_may_be_null(ret_type) &&
++ map_value_has_spin_lock(meta.map_ptr)) {
++ regs[BPF_REG_0].id = ++env->id_gen;
+ }
+- } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) {
++ } else if (base_type(ret_type) == RET_PTR_TO_SOCKET) {
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+- regs[BPF_REG_0].type = PTR_TO_SOCKET_OR_NULL;
+- } else if (fn->ret_type == RET_PTR_TO_SOCK_COMMON_OR_NULL) {
++ regs[BPF_REG_0].type = PTR_TO_SOCKET | ret_flag;
++ } else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) {
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+- regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON_OR_NULL;
+- } else if (fn->ret_type == RET_PTR_TO_TCP_SOCK_OR_NULL) {
++ regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON | ret_flag;
++ } else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) {
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+- regs[BPF_REG_0].type = PTR_TO_TCP_SOCK_OR_NULL;
+- } else if (fn->ret_type == RET_PTR_TO_ALLOC_MEM_OR_NULL) {
++ regs[BPF_REG_0].type = PTR_TO_TCP_SOCK | ret_flag;
++ } else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) {
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+- regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL;
++ regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag;
+ regs[BPF_REG_0].mem_size = meta.mem_size;
+- } else if (fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL ||
+- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID) {
++ } else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) {
+ const struct btf_type *t;
+
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+@@ -6362,29 +6396,30 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+ tname, PTR_ERR(ret));
+ return -EINVAL;
+ }
+- regs[BPF_REG_0].type =
+- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ?
+- PTR_TO_MEM : PTR_TO_MEM_OR_NULL;
++ regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag;
+ regs[BPF_REG_0].mem_size = tsize;
+ } else {
+- regs[BPF_REG_0].type =
+- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ?
+- PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL;
++ /* MEM_RDONLY may be carried from ret_flag, but it
++ * doesn't apply on PTR_TO_BTF_ID. Fold it, otherwise
++ * it will confuse the check of PTR_TO_BTF_ID in
++ * check_mem_access().
++ */
++ ret_flag &= ~MEM_RDONLY;
++
++ regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag;
+ regs[BPF_REG_0].btf = meta.ret_btf;
+ regs[BPF_REG_0].btf_id = meta.ret_btf_id;
+ }
+- } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL ||
+- fn->ret_type == RET_PTR_TO_BTF_ID) {
++ } else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) {
+ int ret_btf_id;
+
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+- regs[BPF_REG_0].type = fn->ret_type == RET_PTR_TO_BTF_ID ?
+- PTR_TO_BTF_ID :
+- PTR_TO_BTF_ID_OR_NULL;
++ regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag;
+ ret_btf_id = *fn->ret_btf_id;
+ if (ret_btf_id == 0) {
+- verbose(env, "invalid return type %d of func %s#%d\n",
+- fn->ret_type, func_id_name(func_id), func_id);
++ verbose(env, "invalid return type %u of func %s#%d\n",
++ base_type(ret_type), func_id_name(func_id),
++ func_id);
+ return -EINVAL;
+ }
+ /* current BPF helper definitions are only coming from
+@@ -6393,12 +6428,12 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
+ regs[BPF_REG_0].btf = btf_vmlinux;
+ regs[BPF_REG_0].btf_id = ret_btf_id;
+ } else {
+- verbose(env, "unknown return type %d of func %s#%d\n",
+- fn->ret_type, func_id_name(func_id), func_id);
++ verbose(env, "unknown return type %u of func %s#%d\n",
++ base_type(ret_type), func_id_name(func_id), func_id);
+ return -EINVAL;
+ }
+
+- if (reg_type_may_be_null(regs[BPF_REG_0].type))
++ if (type_may_be_null(regs[BPF_REG_0].type))
+ regs[BPF_REG_0].id = ++env->id_gen;
+
+ if (is_ptr_cast_function(func_id)) {
+@@ -6597,25 +6632,25 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
+
+ if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) {
+ verbose(env, "math between %s pointer and %lld is not allowed\n",
+- reg_type_str[type], val);
++ reg_type_str(env, type), val);
+ return false;
+ }
+
+ if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
+ verbose(env, "%s pointer offset %d is not allowed\n",
+- reg_type_str[type], reg->off);
++ reg_type_str(env, type), reg->off);
+ return false;
+ }
+
+ if (smin == S64_MIN) {
+ verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n",
+- reg_type_str[type]);
++ reg_type_str(env, type));
+ return false;
+ }
+
+ if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
+ verbose(env, "value %lld makes %s pointer be out of bounds\n",
+- smin, reg_type_str[type]);
++ smin, reg_type_str(env, type));
+ return false;
+ }
+
+@@ -6992,11 +7027,13 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ return -EACCES;
+ }
+
+- switch (ptr_reg->type) {
+- case PTR_TO_MAP_VALUE_OR_NULL:
++ if (ptr_reg->type & PTR_MAYBE_NULL) {
+ verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n",
+- dst, reg_type_str[ptr_reg->type]);
++ dst, reg_type_str(env, ptr_reg->type));
+ return -EACCES;
++ }
++
++ switch (base_type(ptr_reg->type)) {
+ case CONST_PTR_TO_MAP:
+ /* smin_val represents the known value */
+ if (known && smin_val == 0 && opcode == BPF_ADD)
+@@ -7004,16 +7041,16 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
fallthrough;
case PTR_TO_PACKET_END:
case PTR_TO_SOCKET:
@@ -136695,15 +209286,16 @@ index e76b559179054..670721e39c0e8 100644
case PTR_TO_XDP_SOCK:
+reject:
verbose(env, "R%d pointer arithmetic on %s prohibited\n",
- dst, reg_type_str[ptr_reg->type]);
+- dst, reg_type_str[ptr_reg->type]);
++ dst, reg_type_str(env, ptr_reg->type));
return -EACCES;
default:
-+ if (reg_type_may_be_null(ptr_reg->type))
++ if (type_may_be_null(ptr_reg->type))
+ goto reject;
break;
}
-@@ -8098,6 +8134,10 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
+@@ -8098,6 +8135,10 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
insn->dst_reg);
}
zext_32_to_64(dst_reg);
@@ -136714,7 +209306,7 @@ index e76b559179054..670721e39c0e8 100644
}
} else {
/* case: R = imm
-@@ -8212,7 +8252,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
+@@ -8212,7 +8253,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
new_range = dst_reg->off;
if (range_right_open)
@@ -136723,9 +209315,12 @@ index e76b559179054..670721e39c0e8 100644
/* Examples for register markings:
*
-@@ -8732,15 +8772,15 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state,
+@@ -8730,17 +8771,17 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state,
+ struct bpf_reg_state *reg, u32 id,
+ bool is_null)
{
- if (reg_type_may_be_null(reg->type) && reg->id == id &&
+- if (reg_type_may_be_null(reg->type) && reg->id == id &&
++ if (type_may_be_null(reg->type) && reg->id == id &&
!WARN_ON_ONCE(!reg->id)) {
- /* Old offset (both fixed and variable parts) should
- * have been known-zero, because we don't allow pointer
@@ -136745,7 +209340,16 @@ index e76b559179054..670721e39c0e8 100644
}
if (is_null) {
reg->type = SCALAR_VALUE;
-@@ -9159,9 +9199,13 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
+@@ -9108,7 +9149,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
+ */
+ if (!is_jmp32 && BPF_SRC(insn->code) == BPF_K &&
+ insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
+- reg_type_may_be_null(dst_reg->type)) {
++ type_may_be_null(dst_reg->type)) {
+ /* Mark all identical registers in each branch as either
+ * safe or unknown depending R == 0 or R != 0 conditional.
+ */
+@@ -9159,11 +9200,15 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
return 0;
}
@@ -136759,9 +209363,12 @@ index e76b559179054..670721e39c0e8 100644
+ if (insn->src_reg == BPF_PSEUDO_BTF_ID) {
dst_reg->type = aux->btf_var.reg_type;
- switch (dst_reg->type) {
+- switch (dst_reg->type) {
++ switch (base_type(dst_reg->type)) {
case PTR_TO_MEM:
-@@ -9198,7 +9242,6 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
+ dst_reg->mem_size = aux->btf_var.mem_size;
+ break;
+@@ -9198,7 +9243,6 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
}
map = env->used_maps[aux->map_index];
@@ -136769,7 +209376,136 @@ index e76b559179054..670721e39c0e8 100644
dst_reg->map_ptr = map;
if (insn->src_reg == BPF_PSEUDO_MAP_VALUE ||
-@@ -11435,6 +11478,13 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
+@@ -9361,7 +9405,7 @@ static int check_return_code(struct bpf_verifier_env *env)
+ /* enforce return zero from async callbacks like timer */
+ if (reg->type != SCALAR_VALUE) {
+ verbose(env, "In async callback the register R0 is not a known value (%s)\n",
+- reg_type_str[reg->type]);
++ reg_type_str(env, reg->type));
+ return -EINVAL;
+ }
+
+@@ -9375,7 +9419,7 @@ static int check_return_code(struct bpf_verifier_env *env)
+ if (is_subprog) {
+ if (reg->type != SCALAR_VALUE) {
+ verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n",
+- reg_type_str[reg->type]);
++ reg_type_str(env, reg->type));
+ return -EINVAL;
+ }
+ return 0;
+@@ -9439,7 +9483,7 @@ static int check_return_code(struct bpf_verifier_env *env)
+
+ if (reg->type != SCALAR_VALUE) {
+ verbose(env, "At program exit the register R0 is not a known value (%s)\n",
+- reg_type_str[reg->type]);
++ reg_type_str(env, reg->type));
+ return -EINVAL;
+ }
+
+@@ -10220,7 +10264,7 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
+ return true;
+ if (rcur->type == NOT_INIT)
+ return false;
+- switch (rold->type) {
++ switch (base_type(rold->type)) {
+ case SCALAR_VALUE:
+ if (env->explore_alu_limits)
+ return false;
+@@ -10242,6 +10286,22 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
+ }
+ case PTR_TO_MAP_KEY:
+ case PTR_TO_MAP_VALUE:
++ /* a PTR_TO_MAP_VALUE could be safe to use as a
++ * PTR_TO_MAP_VALUE_OR_NULL into the same map.
++ * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL-
++ * checked, doing so could have affected others with the same
++ * id, and we can't check for that because we lost the id when
++ * we converted to a PTR_TO_MAP_VALUE.
++ */
++ if (type_may_be_null(rold->type)) {
++ if (!type_may_be_null(rcur->type))
++ return false;
++ if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)))
++ return false;
++ /* Check our ids match any regs they're supposed to */
++ return check_ids(rold->id, rcur->id, idmap);
++ }
++
+ /* If the new min/max/var_off satisfy the old ones and
+ * everything else matches, we are OK.
+ * 'id' is not compared, since it's only used for maps with
+@@ -10253,20 +10313,6 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
+ return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 &&
+ range_within(rold, rcur) &&
+ tnum_in(rold->var_off, rcur->var_off);
+- case PTR_TO_MAP_VALUE_OR_NULL:
+- /* a PTR_TO_MAP_VALUE could be safe to use as a
+- * PTR_TO_MAP_VALUE_OR_NULL into the same map.
+- * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL-
+- * checked, doing so could have affected others with the same
+- * id, and we can't check for that because we lost the id when
+- * we converted to a PTR_TO_MAP_VALUE.
+- */
+- if (rcur->type != PTR_TO_MAP_VALUE_OR_NULL)
+- return false;
+- if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)))
+- return false;
+- /* Check our ids match any regs they're supposed to */
+- return check_ids(rold->id, rcur->id, idmap);
+ case PTR_TO_PACKET_META:
+ case PTR_TO_PACKET:
+ if (rcur->type != rold->type)
+@@ -10295,11 +10341,8 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
+ case PTR_TO_PACKET_END:
+ case PTR_TO_FLOW_KEYS:
+ case PTR_TO_SOCKET:
+- case PTR_TO_SOCKET_OR_NULL:
+ case PTR_TO_SOCK_COMMON:
+- case PTR_TO_SOCK_COMMON_OR_NULL:
+ case PTR_TO_TCP_SOCK:
+- case PTR_TO_TCP_SOCK_OR_NULL:
+ case PTR_TO_XDP_SOCK:
+ /* Only valid matches are exact, which memcmp() above
+ * would have accepted
+@@ -10825,17 +10868,13 @@ next:
+ /* Return true if it's OK to have the same insn return a different type. */
+ static bool reg_type_mismatch_ok(enum bpf_reg_type type)
+ {
+- switch (type) {
++ switch (base_type(type)) {
+ case PTR_TO_CTX:
+ case PTR_TO_SOCKET:
+- case PTR_TO_SOCKET_OR_NULL:
+ case PTR_TO_SOCK_COMMON:
+- case PTR_TO_SOCK_COMMON_OR_NULL:
+ case PTR_TO_TCP_SOCK:
+- case PTR_TO_TCP_SOCK_OR_NULL:
+ case PTR_TO_XDP_SOCK:
+ case PTR_TO_BTF_ID:
+- case PTR_TO_BTF_ID_OR_NULL:
+ return false;
+ default:
+ return true;
+@@ -11059,7 +11098,7 @@ static int do_check(struct bpf_verifier_env *env)
+ if (is_ctx_reg(env, insn->dst_reg)) {
+ verbose(env, "BPF_ST stores into R%d %s is not allowed\n",
+ insn->dst_reg,
+- reg_type_str[reg_state(env, insn->dst_reg)->type]);
++ reg_type_str(env, reg_state(env, insn->dst_reg)->type));
+ return -EACCES;
+ }
+
+@@ -11310,7 +11349,7 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
+ err = -EINVAL;
+ goto err_put;
+ }
+- aux->btf_var.reg_type = PTR_TO_MEM;
++ aux->btf_var.reg_type = PTR_TO_MEM | MEM_RDONLY;
+ aux->btf_var.mem_size = tsize;
+ } else {
+ aux->btf_var.reg_type = PTR_TO_BTF_ID;
+@@ -11435,6 +11474,13 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
}
}
@@ -136783,7 +209519,16 @@ index e76b559179054..670721e39c0e8 100644
if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
!bpf_offload_prog_map_match(prog, map)) {
verbose(env, "offload device mismatch between prog and map\n");
-@@ -13713,11 +13763,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)
+@@ -13125,7 +13171,7 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
+ mark_reg_known_zero(env, regs, i);
+ else if (regs[i].type == SCALAR_VALUE)
+ mark_reg_unknown(env, regs, i);
+- else if (regs[i].type == PTR_TO_MEM_OR_NULL) {
++ else if (base_type(regs[i].type) == PTR_TO_MEM) {
+ const u32 mem_size = regs[i].mem_size;
+
+ mark_reg_known_zero(env, regs, i);
+@@ -13713,11 +13759,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)
log->ubuf = (char __user *) (unsigned long) attr->log_buf;
log->len_total = attr->log_size;
@@ -137230,7 +209975,7 @@ index ea08f01d0111a..de8b4fa1e1fd6 100644
goto err;
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
-index 2a9695ccb65f5..f6794602ab10c 100644
+index 2a9695ccb65f5..31f94c6ea0a55 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1512,10 +1512,15 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
@@ -137289,6 +210034,20 @@ index 2a9695ccb65f5..f6794602ab10c 100644
}
/* The various types of files and directories in a cpuset file system */
+@@ -3336,8 +3347,11 @@ static struct notifier_block cpuset_track_online_nodes_nb = {
+ */
+ void __init cpuset_init_smp(void)
+ {
+- cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
+- top_cpuset.mems_allowed = node_states[N_MEMORY];
++ /*
++ * cpus_allowd/mems_allowed set to v2 values in the initial
++ * cpuset_bind() call will be reset to v1 values in another
++ * cpuset_bind() call when v1 cpuset is mounted.
++ */
+ top_cpuset.old_mems_allowed = top_cpuset.mems_allowed;
+
+ cpumask_copy(top_cpuset.effective_cpus, cpu_active_mask);
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index b264ab5652ba9..1486768f23185 100644
--- a/kernel/cgroup/rstat.c
@@ -137303,18 +210062,97 @@ index b264ab5652ba9..1486768f23185 100644
}
diff --git a/kernel/cpu.c b/kernel/cpu.c
-index 192e43a874076..407a2568f35eb 100644
+index 192e43a874076..da871eb075662 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
-@@ -31,6 +31,7 @@
+@@ -31,8 +31,10 @@
#include <linux/smpboot.h>
#include <linux/relay.h>
#include <linux/slab.h>
+#include <linux/scs.h>
#include <linux/percpu-rwsem.h>
#include <linux/cpuset.h>
++#include <linux/random.h>
+
+ #include <trace/events/power.h>
+ #define CREATE_TRACE_POINTS
+@@ -69,7 +71,6 @@ struct cpuhp_cpu_state {
+ bool rollback;
+ bool single;
+ bool bringup;
+- int cpu;
+ struct hlist_node *node;
+ struct hlist_node *last;
+ enum cpuhp_state cb_state;
+@@ -473,7 +474,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
+ #endif
+
+ static inline enum cpuhp_state
+-cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target)
++cpuhp_set_state(int cpu, struct cpuhp_cpu_state *st, enum cpuhp_state target)
+ {
+ enum cpuhp_state prev_state = st->state;
+ bool bringup = st->state < target;
+@@ -484,14 +485,15 @@ cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target)
+ st->target = target;
+ st->single = false;
+ st->bringup = bringup;
+- if (cpu_dying(st->cpu) != !bringup)
+- set_cpu_dying(st->cpu, !bringup);
++ if (cpu_dying(cpu) != !bringup)
++ set_cpu_dying(cpu, !bringup);
+
+ return prev_state;
+ }
-@@ -587,6 +588,12 @@ static int bringup_cpu(unsigned int cpu)
+ static inline void
+-cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
++cpuhp_reset_state(int cpu, struct cpuhp_cpu_state *st,
++ enum cpuhp_state prev_state)
+ {
+ bool bringup = !st->bringup;
+
+@@ -518,8 +520,8 @@ cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
+ }
+
+ st->bringup = bringup;
+- if (cpu_dying(st->cpu) != !bringup)
+- set_cpu_dying(st->cpu, !bringup);
++ if (cpu_dying(cpu) != !bringup)
++ set_cpu_dying(cpu, !bringup);
+ }
+
+ /* Regular hotplug invocation of the AP hotplug thread */
+@@ -539,15 +541,16 @@ static void __cpuhp_kick_ap(struct cpuhp_cpu_state *st)
+ wait_for_ap_thread(st, st->bringup);
+ }
+
+-static int cpuhp_kick_ap(struct cpuhp_cpu_state *st, enum cpuhp_state target)
++static int cpuhp_kick_ap(int cpu, struct cpuhp_cpu_state *st,
++ enum cpuhp_state target)
+ {
+ enum cpuhp_state prev_state;
+ int ret;
+
+- prev_state = cpuhp_set_state(st, target);
++ prev_state = cpuhp_set_state(cpu, st, target);
+ __cpuhp_kick_ap(st);
+ if ((ret = st->result)) {
+- cpuhp_reset_state(st, prev_state);
++ cpuhp_reset_state(cpu, st, prev_state);
+ __cpuhp_kick_ap(st);
+ }
+
+@@ -579,7 +582,7 @@ static int bringup_wait_for_ap(unsigned int cpu)
+ if (st->target <= CPUHP_AP_ONLINE_IDLE)
+ return 0;
+
+- return cpuhp_kick_ap(st, st->target);
++ return cpuhp_kick_ap(cpu, st, st->target);
+ }
+
+ static int bringup_cpu(unsigned int cpu)
+@@ -587,6 +590,12 @@ static int bringup_cpu(unsigned int cpu)
struct task_struct *idle = idle_thread_get(cpu);
int ret;
@@ -137327,6 +210165,92 @@ index 192e43a874076..407a2568f35eb 100644
/*
* Some architectures have to walk the irq descriptors to
* setup the vector space for the cpu which comes online.
+@@ -696,7 +705,7 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
+ ret, cpu, cpuhp_get_step(st->state)->name,
+ st->state);
+
+- cpuhp_reset_state(st, prev_state);
++ cpuhp_reset_state(cpu, st, prev_state);
+ if (can_rollback_cpu(st))
+ WARN_ON(cpuhp_invoke_callback_range(false, cpu, st,
+ prev_state));
+@@ -713,7 +722,6 @@ static void cpuhp_create(unsigned int cpu)
+
+ init_completion(&st->done_up);
+ init_completion(&st->done_down);
+- st->cpu = cpu;
+ }
+
+ static int cpuhp_should_run(unsigned int cpu)
+@@ -867,7 +875,7 @@ static int cpuhp_kick_ap_work(unsigned int cpu)
+ cpuhp_lock_release(true);
+
+ trace_cpuhp_enter(cpu, st->target, prev_state, cpuhp_kick_ap_work);
+- ret = cpuhp_kick_ap(st, st->target);
++ ret = cpuhp_kick_ap(cpu, st, st->target);
+ trace_cpuhp_exit(cpu, st->state, prev_state, ret);
+
+ return ret;
+@@ -1099,7 +1107,7 @@ static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
+ ret, cpu, cpuhp_get_step(st->state)->name,
+ st->state);
+
+- cpuhp_reset_state(st, prev_state);
++ cpuhp_reset_state(cpu, st, prev_state);
+
+ if (st->state < prev_state)
+ WARN_ON(cpuhp_invoke_callback_range(true, cpu, st,
+@@ -1126,7 +1134,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
+
+ cpuhp_tasks_frozen = tasks_frozen;
+
+- prev_state = cpuhp_set_state(st, target);
++ prev_state = cpuhp_set_state(cpu, st, target);
+ /*
+ * If the current CPU state is in the range of the AP hotplug thread,
+ * then we need to kick the thread.
+@@ -1157,7 +1165,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
+ ret = cpuhp_down_callbacks(cpu, st, target);
+ if (ret && st->state < prev_state) {
+ if (st->state == CPUHP_TEARDOWN_CPU) {
+- cpuhp_reset_state(st, prev_state);
++ cpuhp_reset_state(cpu, st, prev_state);
+ __cpuhp_kick_ap(st);
+ } else {
+ WARN(1, "DEAD callback error for CPU%d", cpu);
+@@ -1344,7 +1352,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
+
+ cpuhp_tasks_frozen = tasks_frozen;
+
+- cpuhp_set_state(st, target);
++ cpuhp_set_state(cpu, st, target);
+ /*
+ * If the current CPU state is in the range of the AP hotplug thread,
+ * then we need to kick the thread once more.
+@@ -1652,6 +1660,11 @@ static struct cpuhp_step cpuhp_hp_states[] = {
+ .startup.single = perf_event_init_cpu,
+ .teardown.single = perf_event_exit_cpu,
+ },
++ [CPUHP_RANDOM_PREPARE] = {
++ .name = "random:prepare",
++ .startup.single = random_prepare_cpu,
++ .teardown.single = NULL,
++ },
+ [CPUHP_WORKQUEUE_PREP] = {
+ .name = "workqueue:prepare",
+ .startup.single = workqueue_prepare_cpu,
+@@ -1775,6 +1788,11 @@ static struct cpuhp_step cpuhp_hp_states[] = {
+ .startup.single = workqueue_online_cpu,
+ .teardown.single = workqueue_offline_cpu,
+ },
++ [CPUHP_AP_RANDOM_ONLINE] = {
++ .name = "random:online",
++ .startup.single = random_online_cpu,
++ .teardown.single = NULL,
++ },
+ [CPUHP_AP_RCUTREE_ONLINE] = {
+ .name = "RCU/tree:online",
+ .startup.single = rcutree_online_cpu,
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index eb53f5ec62c90..256cf6db573cd 100644
--- a/kernel/crash_core.c
@@ -137390,6 +210314,48 @@ index 1ae0b4948a5a8..933155c969227 100644
return 0;
}
+diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
+index da06a5553835b..7beceb447211d 100644
+--- a/kernel/debug/debug_core.c
++++ b/kernel/debug/debug_core.c
+@@ -53,6 +53,7 @@
+ #include <linux/vmacache.h>
+ #include <linux/rcupdate.h>
+ #include <linux/irq.h>
++#include <linux/security.h>
+
+ #include <asm/cacheflush.h>
+ #include <asm/byteorder.h>
+@@ -752,6 +753,29 @@ cpu_master_loop:
+ continue;
+ kgdb_connected = 0;
+ } else {
++ /*
++ * This is a brutal way to interfere with the debugger
++ * and prevent gdb being used to poke at kernel memory.
++ * This could cause trouble if lockdown is applied when
++ * there is already an active gdb session. For now the
++ * answer is simply "don't do that". Typically lockdown
++ * *will* be applied before the debug core gets started
++ * so only developers using kgdb for fairly advanced
++ * early kernel debug can be biten by this. Hopefully
++ * they are sophisticated enough to take care of
++ * themselves, especially with help from the lockdown
++ * message printed on the console!
++ */
++ if (security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL)) {
++ if (IS_ENABLED(CONFIG_KGDB_KDB)) {
++ /* Switch back to kdb if possible... */
++ dbg_kdb_mode = 1;
++ continue;
++ } else {
++ /* ... otherwise just bail */
++ break;
++ }
++ }
+ error = gdb_serial_stub(ks);
+ }
+
diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c
index 1f9f0e47aedaa..10b454554ab03 100644
--- a/kernel/debug/kdb/kdb_bt.c
@@ -137460,10 +210426,94 @@ index 1f9f0e47aedaa..10b454554ab03 100644
}
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
-index fa6deda894a17..0852a537dad4c 100644
+index fa6deda894a17..ead4da9471270 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
-@@ -2203,8 +2203,8 @@ static void kdb_cpu_status(void)
+@@ -45,6 +45,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/uaccess.h>
+ #include <linux/slab.h>
++#include <linux/security.h>
+ #include "kdb_private.h"
+
+ #undef MODULE_PARAM_PREFIX
+@@ -166,10 +167,62 @@ struct task_struct *kdb_curr_task(int cpu)
+ }
+
+ /*
+- * Check whether the flags of the current command and the permissions
+- * of the kdb console has allow a command to be run.
++ * Update the permissions flags (kdb_cmd_enabled) to match the
++ * current lockdown state.
++ *
++ * Within this function the calls to security_locked_down() are "lazy". We
++ * avoid calling them if the current value of kdb_cmd_enabled already excludes
++ * flags that might be subject to lockdown. Additionally we deliberately check
++ * the lockdown flags independently (even though read lockdown implies write
++ * lockdown) since that results in both simpler code and clearer messages to
++ * the user on first-time debugger entry.
++ *
++ * The permission masks during a read+write lockdown permits the following
++ * flags: INSPECT, SIGNAL, REBOOT (and ALWAYS_SAFE).
++ *
++ * The INSPECT commands are not blocked during lockdown because they are
++ * not arbitrary memory reads. INSPECT covers the backtrace family (sometimes
++ * forcing them to have no arguments) and lsmod. These commands do expose
++ * some kernel state but do not allow the developer seated at the console to
++ * choose what state is reported. SIGNAL and REBOOT should not be controversial,
++ * given these are allowed for root during lockdown already.
++ */
++static void kdb_check_for_lockdown(void)
++{
++ const int write_flags = KDB_ENABLE_MEM_WRITE |
++ KDB_ENABLE_REG_WRITE |
++ KDB_ENABLE_FLOW_CTRL;
++ const int read_flags = KDB_ENABLE_MEM_READ |
++ KDB_ENABLE_REG_READ;
++
++ bool need_to_lockdown_write = false;
++ bool need_to_lockdown_read = false;
++
++ if (kdb_cmd_enabled & (KDB_ENABLE_ALL | write_flags))
++ need_to_lockdown_write =
++ security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL);
++
++ if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags))
++ need_to_lockdown_read =
++ security_locked_down(LOCKDOWN_DBG_READ_KERNEL);
++
++ /* De-compose KDB_ENABLE_ALL if required */
++ if (need_to_lockdown_write || need_to_lockdown_read)
++ if (kdb_cmd_enabled & KDB_ENABLE_ALL)
++ kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL;
++
++ if (need_to_lockdown_write)
++ kdb_cmd_enabled &= ~write_flags;
++
++ if (need_to_lockdown_read)
++ kdb_cmd_enabled &= ~read_flags;
++}
++
++/*
++ * Check whether the flags of the current command, the permissions of the kdb
++ * console and the lockdown state allow a command to be run.
+ */
+-static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
++static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
+ bool no_args)
+ {
+ /* permissions comes from userspace so needs massaging slightly */
+@@ -1180,6 +1233,9 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
+ kdb_curr_task(raw_smp_processor_id());
+
+ KDB_DEBUG_STATE("kdb_local 1", reason);
++
++ kdb_check_for_lockdown();
++
+ kdb_go_count = 0;
+ if (reason == KDB_REASON_DEBUG) {
+ /* special case below */
+@@ -2203,8 +2259,8 @@ static void kdb_cpu_status(void)
state = 'D'; /* cpu is online but unresponsive */
} else {
state = ' '; /* cpu is responding to kdb */
@@ -137474,7 +210524,7 @@ index fa6deda894a17..0852a537dad4c 100644
}
if (state != prev_state) {
if (prev_state != '?') {
-@@ -2271,37 +2271,30 @@ static int kdb_cpu(int argc, const char **argv)
+@@ -2271,37 +2327,30 @@ static int kdb_cpu(int argc, const char **argv)
void kdb_ps_suppressed(void)
{
int idle = 0, daemon = 0;
@@ -137516,7 +210566,7 @@ index fa6deda894a17..0852a537dad4c 100644
void kdb_ps1(const struct task_struct *p)
{
int cpu;
-@@ -2330,17 +2323,25 @@ void kdb_ps1(const struct task_struct *p)
+@@ -2330,17 +2379,25 @@ void kdb_ps1(const struct task_struct *p)
}
}
@@ -137544,7 +210594,7 @@ index fa6deda894a17..0852a537dad4c 100644
/* Run the active tasks first */
for_each_online_cpu(cpu) {
if (KDB_FLAG(CMD_INTERRUPT))
-@@ -2742,8 +2743,8 @@ static kdbtab_t maintab[] = {
+@@ -2742,8 +2799,8 @@ static kdbtab_t maintab[] = {
},
{ .name = "bta",
.func = kdb_bt,
@@ -137555,7 +210605,7 @@ index fa6deda894a17..0852a537dad4c 100644
.flags = KDB_ENABLE_INSPECT,
},
{ .name = "btc",
-@@ -2797,7 +2798,7 @@ static kdbtab_t maintab[] = {
+@@ -2797,7 +2854,7 @@ static kdbtab_t maintab[] = {
},
{ .name = "ps",
.func = kdb_ps,
@@ -137581,7 +210631,7 @@ index 629590084a0dc..0d2f9feea0a46 100644
extern void kdb_ps1(const struct task_struct *p);
extern void kdb_send_sig(struct task_struct *p, int sig);
diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c
-index 7507d9a8dc6ac..df2bface866ef 100644
+index 7507d9a8dc6ac..85cb51c4a17e6 100644
--- a/kernel/debug/kdb/kdb_support.c
+++ b/kernel/debug/kdb/kdb_support.c
@@ -24,6 +24,7 @@
@@ -137592,6 +210642,15 @@ index 7507d9a8dc6ac..df2bface866ef 100644
#include "kdb_private.h"
/*
+@@ -290,7 +291,7 @@ int kdb_getarea_size(void *res, unsigned long addr, size_t size)
+ */
+ int kdb_putarea_size(unsigned long addr, void *res, size_t size)
+ {
+- int ret = copy_from_kernel_nofault((char *)addr, (char *)res, size);
++ int ret = copy_to_kernel_nofault((char *)addr, (char *)res, size);
+ if (ret) {
+ if (!KDB_STATE(SUPPRESS)) {
+ kdb_func_printf("Bad address 0x%lx\n", addr);
@@ -473,82 +474,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size)
return diag;
}
@@ -137748,6 +210807,56 @@ index 7507d9a8dc6ac..df2bface866ef 100644
}
/* Maintain a small stack of kdb_flags to allow recursion without disturbing
+diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
+index 7a14ca29c3778..f8ff598596b85 100644
+--- a/kernel/dma/debug.c
++++ b/kernel/dma/debug.c
+@@ -927,7 +927,7 @@ static __init int dma_debug_cmdline(char *str)
+ global_disable = true;
+ }
+
+- return 0;
++ return 1;
+ }
+
+ static __init int dma_debug_entries_cmdline(char *str)
+@@ -936,7 +936,7 @@ static __init int dma_debug_entries_cmdline(char *str)
+ return -EINVAL;
+ if (!get_option(&str, &nr_prealloc_entries))
+ nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+- return 0;
++ return 1;
+ }
+
+ __setup("dma_debug=", dma_debug_cmdline);
+diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
+index 4632b0f4f72eb..8a6cd53dbe8ce 100644
+--- a/kernel/dma/direct.h
++++ b/kernel/dma/direct.h
+@@ -114,6 +114,7 @@ static inline void dma_direct_unmap_page(struct device *dev, dma_addr_t addr,
+ dma_direct_sync_single_for_cpu(dev, addr, size, dir);
+
+ if (unlikely(is_swiotlb_buffer(dev, phys)))
+- swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
++ swiotlb_tbl_unmap_single(dev, phys, size, dir,
++ attrs | DMA_ATTR_SKIP_CPU_SYNC);
+ }
+ #endif /* _KERNEL_DMA_DIRECT_H */
+diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
+index 8349a9f2c3453..9478eccd1c8e6 100644
+--- a/kernel/dma/mapping.c
++++ b/kernel/dma/mapping.c
+@@ -296,10 +296,6 @@ dma_addr_t dma_map_resource(struct device *dev, phys_addr_t phys_addr,
+ if (WARN_ON_ONCE(!dev->dma_mask))
+ return DMA_MAPPING_ERROR;
+
+- /* Don't allow RAM to be mapped */
+- if (WARN_ON_ONCE(pfn_valid(PHYS_PFN(phys_addr))))
+- return DMA_MAPPING_ERROR;
+-
+ if (dma_map_direct(dev, ops))
+ addr = dma_direct_map_resource(dev, phys_addr, size, dir, attrs);
+ else if (ops->map_resource)
diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c
index 5f84e6cdb78ea..4d40dcce7604b 100644
--- a/kernel/dma/pool.c
@@ -137770,6 +210879,83 @@ index 5f84e6cdb78ea..4d40dcce7604b 100644
return atomic_pool_dma;
return atomic_pool_kernel;
}
+diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
+index 87c40517e8227..2ee5419649ed7 100644
+--- a/kernel/dma/swiotlb.c
++++ b/kernel/dma/swiotlb.c
+@@ -459,7 +459,7 @@ static unsigned int wrap_index(struct io_tlb_mem *mem, unsigned int index)
+ * allocate a buffer from that IO TLB pool.
+ */
+ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
+- size_t alloc_size)
++ size_t alloc_size, unsigned int alloc_align_mask)
+ {
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ unsigned long boundary_mask = dma_get_seg_boundary(dev);
+@@ -483,6 +483,7 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
+ stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1;
+ if (alloc_size >= PAGE_SIZE)
+ stride = max(stride, stride << (PAGE_SHIFT - IO_TLB_SHIFT));
++ stride = max(stride, (alloc_align_mask >> IO_TLB_SHIFT) + 1);
+
+ spin_lock_irqsave(&mem->lock, flags);
+ if (unlikely(nslots > mem->nslabs - mem->used))
+@@ -541,7 +542,8 @@ found:
+
+ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
+ size_t mapping_size, size_t alloc_size,
+- enum dma_data_direction dir, unsigned long attrs)
++ unsigned int alloc_align_mask, enum dma_data_direction dir,
++ unsigned long attrs)
+ {
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ unsigned int offset = swiotlb_align_offset(dev, orig_addr);
+@@ -561,7 +563,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
+ return (phys_addr_t)DMA_MAPPING_ERROR;
+ }
+
+- index = swiotlb_find_slots(dev, orig_addr, alloc_size + offset);
++ index = swiotlb_find_slots(dev, orig_addr,
++ alloc_size + offset, alloc_align_mask);
+ if (index == -1) {
+ if (!(attrs & DMA_ATTR_NO_WARN))
+ dev_warn_ratelimited(dev,
+@@ -578,9 +581,14 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
+ for (i = 0; i < nr_slots(alloc_size + offset); i++)
+ mem->slots[index + i].orig_addr = slot_addr(orig_addr, i);
+ tlb_addr = slot_addr(mem->start, index) + offset;
+- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+- (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
+- swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_TO_DEVICE);
++ /*
++ * When dir == DMA_FROM_DEVICE we could omit the copy from the orig
++ * to the tlb buffer, if we knew for sure the device will
++ * overwirte the entire current content. But we don't. Thus
++ * unconditional bounce may prevent leaking swiotlb content (i.e.
++ * kernel memory) to user-space.
++ */
++ swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_TO_DEVICE);
+ return tlb_addr;
+ }
+
+@@ -675,7 +683,7 @@ dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
+ trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size,
+ swiotlb_force);
+
+- swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, dir,
++ swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, 0, dir,
+ attrs);
+ if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR)
+ return DMA_MAPPING_ERROR;
+@@ -759,7 +767,7 @@ struct page *swiotlb_alloc(struct device *dev, size_t size)
+ if (!mem)
+ return NULL;
+
+- index = swiotlb_find_slots(dev, 0, size);
++ index = swiotlb_find_slots(dev, 0, size, 0);
+ if (index == -1)
+ return NULL;
+
diff --git a/kernel/entry/syscall_user_dispatch.c b/kernel/entry/syscall_user_dispatch.c
index c240302f56e23..0b6379adff6bd 100644
--- a/kernel/entry/syscall_user_dispatch.c
@@ -137798,7 +210984,7 @@ index c240302f56e23..0b6379adff6bd 100644
sd->on_dispatch = true;
diff --git a/kernel/events/core.c b/kernel/events/core.c
-index f23ca260307f0..b81652fc2cdd9 100644
+index f23ca260307f0..565910de92e9b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -674,6 +674,23 @@ perf_event_set_state(struct perf_event *event, enum perf_event_state state)
@@ -138344,6 +211530,15 @@ index f23ca260307f0..b81652fc2cdd9 100644
rcu_read_lock();
rb = rcu_dereference(event->rb);
if (rb) {
+@@ -6270,7 +6348,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
+ again:
+ mutex_lock(&event->mmap_mutex);
+ if (event->rb) {
+- if (event->rb->nr_pages != nr_pages) {
++ if (data_page_nr(event->rb) != nr_pages) {
+ ret = -EINVAL;
+ goto unlock;
+ }
@@ -6349,7 +6427,6 @@ accounting:
ring_buffer_attach(event, rb);
@@ -138437,6 +211632,96 @@ index f23ca260307f0..b81652fc2cdd9 100644
if (perf_tp_event_match(event, &data, regs))
perf_swevent_event(event, count, &data, regs);
}
+@@ -10443,8 +10530,11 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
+ }
+
+ /* ready to consume more filters */
++ kfree(filename);
++ filename = NULL;
+ state = IF_STATE_ACTION;
+ filter = NULL;
++ kernel = 0;
+ }
+ }
+
+@@ -11506,6 +11596,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
+
+ event->state = PERF_EVENT_STATE_INACTIVE;
+
++ if (parent_event)
++ event->event_caps = parent_event->event_caps;
++
+ if (event->attr.sigtrap)
+ atomic_set(&event->event_limit, 1);
+
+@@ -12190,6 +12283,9 @@ SYSCALL_DEFINE5(perf_event_open,
+ * Do not allow to attach to a group in a different task
+ * or CPU context. If we're moving SW events, we'll fix
+ * this up later, so allow that.
++ *
++ * Racy, not holding group_leader->ctx->mutex, see comment with
++ * perf_event_ctx_lock().
+ */
+ if (!move_group && group_leader->ctx != ctx)
+ goto err_context;
+@@ -12255,6 +12351,7 @@ SYSCALL_DEFINE5(perf_event_open,
+ } else {
+ perf_event_ctx_unlock(group_leader, gctx);
+ move_group = 0;
++ goto not_move_group;
+ }
+ }
+
+@@ -12271,7 +12368,17 @@ SYSCALL_DEFINE5(perf_event_open,
+ }
+ } else {
+ mutex_lock(&ctx->mutex);
++
++ /*
++ * Now that we hold ctx->lock, (re)validate group_leader->ctx == ctx,
++ * see the group_leader && !move_group test earlier.
++ */
++ if (group_leader && group_leader->ctx != ctx) {
++ err = -EINVAL;
++ goto err_locked;
++ }
+ }
++not_move_group:
+
+ if (ctx->task == TASK_TOMBSTONE) {
+ err = -ESRCH;
+diff --git a/kernel/events/internal.h b/kernel/events/internal.h
+index 228801e207886..aa23ffdaf819f 100644
+--- a/kernel/events/internal.h
++++ b/kernel/events/internal.h
+@@ -116,6 +116,11 @@ static inline int page_order(struct perf_buffer *rb)
+ }
+ #endif
+
++static inline int data_page_nr(struct perf_buffer *rb)
++{
++ return rb->nr_pages << page_order(rb);
++}
++
+ static inline unsigned long perf_data_size(struct perf_buffer *rb)
+ {
+ return rb->nr_pages << (PAGE_SHIFT + page_order(rb));
+diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
+index 52868716ec358..fb35b926024ca 100644
+--- a/kernel/events/ring_buffer.c
++++ b/kernel/events/ring_buffer.c
+@@ -859,11 +859,6 @@ void rb_free(struct perf_buffer *rb)
+ }
+
+ #else
+-static int data_page_nr(struct perf_buffer *rb)
+-{
+- return rb->nr_pages << page_order(rb);
+-}
+-
+ static struct page *
+ __perf_mmap_to_page(struct perf_buffer *rb, unsigned long pgoff)
+ {
diff --git a/kernel/fork.c b/kernel/fork.c
index 38681ad44c76b..89475c994ca91 100644
--- a/kernel/fork.c
@@ -138512,6 +211797,145 @@ index 38681ad44c76b..89475c994ca91 100644
proc_fork_connector(p);
sched_post_fork(p);
cgroup_post_fork(p, args);
+diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
+index f7ff8919dc9bb..fdf170404650f 100644
+--- a/kernel/irq/affinity.c
++++ b/kernel/irq/affinity.c
+@@ -269,8 +269,9 @@ static int __irq_build_affinity_masks(unsigned int startvec,
+ */
+ if (numvecs <= nodes) {
+ for_each_node_mask(n, nodemsk) {
+- cpumask_or(&masks[curvec].mask, &masks[curvec].mask,
+- node_to_cpumask[n]);
++ /* Ensure that only CPUs which are in both masks are set */
++ cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
++ cpumask_or(&masks[curvec].mask, &masks[curvec].mask, nmsk);
+ if (++curvec == last_affv)
+ curvec = firstvec;
+ }
+diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
+index 221d80c31e94c..fca637d4da1a7 100644
+--- a/kernel/irq/handle.c
++++ b/kernel/irq/handle.c
+@@ -195,7 +195,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+
+ retval = __handle_irq_event_percpu(desc, &flags);
+
+- add_interrupt_randomness(desc->irq_data.irq, flags);
++ add_interrupt_randomness(desc->irq_data.irq);
+
+ if (!irq_settings_no_debug(desc))
+ note_interrupt(desc, retval);
+diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
+index 54363527feea4..e58342ace11f2 100644
+--- a/kernel/irq/internals.h
++++ b/kernel/irq/internals.h
+@@ -29,12 +29,14 @@ extern struct irqaction chained_action;
+ * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+ * IRQTF_AFFINITY - irq thread is requested to adjust affinity
+ * IRQTF_FORCED_THREAD - irq action is force threaded
++ * IRQTF_READY - signals that irq thread is ready
+ */
+ enum {
+ IRQTF_RUNTHREAD,
+ IRQTF_WARNED,
+ IRQTF_AFFINITY,
+ IRQTF_FORCED_THREAD,
++ IRQTF_READY,
+ };
+
+ /*
+diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
+index 4e3c29bb603c3..21b3ac2a29d20 100644
+--- a/kernel/irq/irqdesc.c
++++ b/kernel/irq/irqdesc.c
+@@ -407,6 +407,7 @@ static struct irq_desc *alloc_desc(int irq, int node, unsigned int flags,
+ lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+ mutex_init(&desc->request_mutex);
+ init_rcu_head(&desc->rcu);
++ init_waitqueue_head(&desc->wait_for_threads);
+
+ desc_set_defaults(irq, desc, node, affinity, owner);
+ irqd_set(&desc->irq_data, flags);
+@@ -575,6 +576,7 @@ int __init early_irq_init(void)
+ raw_spin_lock_init(&desc[i].lock);
+ lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+ mutex_init(&desc[i].request_mutex);
++ init_waitqueue_head(&desc[i].wait_for_threads);
+ desc_set_defaults(i, &desc[i], node, NULL, NULL);
+ }
+ return arch_early_irq_init();
+diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
+index 27667e82ecc91..0c3c26fb054f7 100644
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -1248,6 +1248,31 @@ static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action)
+ raw_spin_unlock_irq(&desc->lock);
+ }
+
++/*
++ * Internal function to notify that a interrupt thread is ready.
++ */
++static void irq_thread_set_ready(struct irq_desc *desc,
++ struct irqaction *action)
++{
++ set_bit(IRQTF_READY, &action->thread_flags);
++ wake_up(&desc->wait_for_threads);
++}
++
++/*
++ * Internal function to wake up a interrupt thread and wait until it is
++ * ready.
++ */
++static void wake_up_and_wait_for_irq_thread_ready(struct irq_desc *desc,
++ struct irqaction *action)
++{
++ if (!action || !action->thread)
++ return;
++
++ wake_up_process(action->thread);
++ wait_event(desc->wait_for_threads,
++ test_bit(IRQTF_READY, &action->thread_flags));
++}
++
+ /*
+ * Interrupt handler thread
+ */
+@@ -1259,6 +1284,8 @@ static int irq_thread(void *data)
+ irqreturn_t (*handler_fn)(struct irq_desc *desc,
+ struct irqaction *action);
+
++ irq_thread_set_ready(desc, action);
++
+ if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD,
+ &action->thread_flags))
+ handler_fn = irq_forced_thread_fn;
+@@ -1683,8 +1710,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
+ }
+
+ if (!shared) {
+- init_waitqueue_head(&desc->wait_for_threads);
+-
+ /* Setup the type (level, edge polarity) if configured: */
+ if (new->flags & IRQF_TRIGGER_MASK) {
+ ret = __irq_set_trigger(desc,
+@@ -1780,14 +1805,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
+
+ irq_setup_timings(desc, new);
+
+- /*
+- * Strictly no need to wake it up, but hung_task complains
+- * when no hard interrupt wakes the thread up.
+- */
+- if (new->thread)
+- wake_up_process(new->thread);
+- if (new->secondary)
+- wake_up_process(new->secondary->thread);
++ wake_up_and_wait_for_irq_thread_ready(desc, new);
++ wake_up_and_wait_for_irq_thread_ready(desc, new->secondary);
+
+ register_irq_proc(irq, desc);
+ new->dir = NULL;
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 6a5ecee6e5674..7f350ae59c5fd 100644
--- a/kernel/irq/msi.c
@@ -138558,11 +211982,56 @@ index 790a573bbe00c..2ef90d15699fb 100644
debugfs_create_file("blacklist", 0400, dir, NULL,
&kprobe_blacklist_fops);
+diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
+index 335d988bd8111..c0789383807b9 100644
+--- a/kernel/livepatch/core.c
++++ b/kernel/livepatch/core.c
+@@ -190,7 +190,7 @@ static int klp_find_object_symbol(const char *objname, const char *name,
+ return -EINVAL;
+ }
+
+-static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab,
++static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
+ unsigned int symndx, Elf_Shdr *relasec,
+ const char *sec_objname)
+ {
+@@ -218,7 +218,7 @@ static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab,
+ relas = (Elf_Rela *) relasec->sh_addr;
+ /* For each rela in this klp relocation section */
+ for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) {
+- sym = (Elf64_Sym *)sechdrs[symndx].sh_addr + ELF_R_SYM(relas[i].r_info);
++ sym = (Elf_Sym *)sechdrs[symndx].sh_addr + ELF_R_SYM(relas[i].r_info);
+ if (sym->st_shndx != SHN_LIVEPATCH) {
+ pr_err("symbol %s is not marked as a livepatch symbol\n",
+ strtab + sym->st_name);
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
-index bf1c00c881e48..92127296cf2bf 100644
+index bf1c00c881e48..a30702b847ba8 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
-@@ -888,7 +888,7 @@ look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass)
+@@ -183,11 +183,9 @@ static DECLARE_BITMAP(list_entries_in_use, MAX_LOCKDEP_ENTRIES);
+ static struct hlist_head lock_keys_hash[KEYHASH_SIZE];
+ unsigned long nr_lock_classes;
+ unsigned long nr_zapped_classes;
+-#ifndef CONFIG_DEBUG_LOCKDEP
+-static
+-#endif
++unsigned long max_lock_class_idx;
+ struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+-static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
++DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
+
+ static inline struct lock_class *hlock_class(struct held_lock *hlock)
+ {
+@@ -338,7 +336,7 @@ static inline void lock_release_holdtime(struct held_lock *hlock)
+ * elements. These elements are linked together by the lock_entry member in
+ * struct lock_class.
+ */
+-LIST_HEAD(all_lock_classes);
++static LIST_HEAD(all_lock_classes);
+ static LIST_HEAD(free_lock_classes);
+
+ /**
+@@ -888,7 +886,7 @@ look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass)
if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
return NULL;
@@ -138571,7 +212040,25 @@ index bf1c00c881e48..92127296cf2bf 100644
if (class->key == key) {
/*
* Huh! same key, different name? Did someone trample
-@@ -3450,7 +3450,7 @@ struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
+@@ -1240,6 +1238,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
+ struct lockdep_subclass_key *key;
+ struct hlist_head *hash_head;
+ struct lock_class *class;
++ int idx;
+
+ DEBUG_LOCKS_WARN_ON(!irqs_disabled());
+
+@@ -1305,6 +1304,9 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
+ * of classes.
+ */
+ list_move_tail(&class->lock_entry, &all_lock_classes);
++ idx = class - lock_classes;
++ if (idx > max_lock_class_idx)
++ max_lock_class_idx = idx;
+
+ if (verbose(class)) {
+ graph_unlock();
+@@ -3450,7 +3452,7 @@ struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
u16 chain_hlock = chain_hlocks[chain->base + i];
unsigned int class_idx = chain_hlock_class_idx(chain_hlock);
@@ -138580,7 +212067,7 @@ index bf1c00c881e48..92127296cf2bf 100644
}
/*
-@@ -3518,7 +3518,7 @@ static void print_chain_keys_chain(struct lock_chain *chain)
+@@ -3518,7 +3520,7 @@ static void print_chain_keys_chain(struct lock_chain *chain)
hlock_id = chain_hlocks[chain->base + i];
chain_key = print_chain_key_iteration(hlock_id, chain_key);
@@ -138589,7 +212076,7 @@ index bf1c00c881e48..92127296cf2bf 100644
printk("\n");
}
}
-@@ -5366,7 +5366,7 @@ int __lock_is_held(const struct lockdep_map *lock, int read)
+@@ -5366,7 +5368,7 @@ int __lock_is_held(const struct lockdep_map *lock, int read)
struct held_lock *hlock = curr->held_locks + i;
if (match_held_lock(hlock, lock)) {
@@ -138598,6 +212085,221 @@ index bf1c00c881e48..92127296cf2bf 100644
return LOCK_STATE_HELD;
return LOCK_STATE_NOT_HELD;
+@@ -5986,6 +5988,8 @@ static void zap_class(struct pending_free *pf, struct lock_class *class)
+ WRITE_ONCE(class->name, NULL);
+ nr_lock_classes--;
+ __clear_bit(class - lock_classes, lock_classes_in_use);
++ if (class - lock_classes == max_lock_class_idx)
++ max_lock_class_idx--;
+ } else {
+ WARN_ONCE(true, "%s() failed for class %s\n", __func__,
+ class->name);
+@@ -6276,7 +6280,13 @@ void lockdep_reset_lock(struct lockdep_map *lock)
+ lockdep_reset_lock_reg(lock);
+ }
+
+-/* Unregister a dynamically allocated key. */
++/*
++ * Unregister a dynamically allocated key.
++ *
++ * Unlike lockdep_register_key(), a search is always done to find a matching
++ * key irrespective of debug_locks to avoid potential invalid access to freed
++ * memory in lock_class entry.
++ */
+ void lockdep_unregister_key(struct lock_class_key *key)
+ {
+ struct hlist_head *hash_head = keyhashentry(key);
+@@ -6291,10 +6301,8 @@ void lockdep_unregister_key(struct lock_class_key *key)
+ return;
+
+ raw_local_irq_save(flags);
+- if (!graph_lock())
+- goto out_irq;
++ lockdep_lock();
+
+- pf = get_pending_free();
+ hlist_for_each_entry_rcu(k, hash_head, hash_entry) {
+ if (k == key) {
+ hlist_del_rcu(&k->hash_entry);
+@@ -6302,11 +6310,13 @@ void lockdep_unregister_key(struct lock_class_key *key)
+ break;
+ }
+ }
+- WARN_ON_ONCE(!found);
+- __lockdep_free_key_range(pf, key, 1);
+- call_rcu_zapped(pf);
+- graph_unlock();
+-out_irq:
++ WARN_ON_ONCE(!found && debug_locks);
++ if (found) {
++ pf = get_pending_free();
++ __lockdep_free_key_range(pf, key, 1);
++ call_rcu_zapped(pf);
++ }
++ lockdep_unlock();
+ raw_local_irq_restore(flags);
+
+ /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */
+diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h
+index ecb8662e7a4ed..bbe9000260d02 100644
+--- a/kernel/locking/lockdep_internals.h
++++ b/kernel/locking/lockdep_internals.h
+@@ -121,7 +121,6 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ =
+
+ #define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5)
+
+-extern struct list_head all_lock_classes;
+ extern struct lock_chain lock_chains[];
+
+ #define LOCK_USAGE_CHARS (2*XXX_LOCK_USAGE_STATES + 1)
+@@ -151,6 +150,10 @@ extern unsigned int nr_large_chain_blocks;
+
+ extern unsigned int max_lockdep_depth;
+ extern unsigned int max_bfs_queue_depth;
++extern unsigned long max_lock_class_idx;
++
++extern struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
++extern unsigned long lock_classes_in_use[];
+
+ #ifdef CONFIG_PROVE_LOCKING
+ extern unsigned long lockdep_count_forward_deps(struct lock_class *);
+@@ -205,7 +208,6 @@ struct lockdep_stats {
+ };
+
+ DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats);
+-extern struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+
+ #define __debug_atomic_inc(ptr) \
+ this_cpu_inc(lockdep_stats.ptr);
+diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c
+index b8d9a050c337a..15fdc7fa5c688 100644
+--- a/kernel/locking/lockdep_proc.c
++++ b/kernel/locking/lockdep_proc.c
+@@ -24,14 +24,33 @@
+
+ #include "lockdep_internals.h"
+
++/*
++ * Since iteration of lock_classes is done without holding the lockdep lock,
++ * it is not safe to iterate all_lock_classes list directly as the iteration
++ * may branch off to free_lock_classes or the zapped list. Iteration is done
++ * directly on the lock_classes array by checking the lock_classes_in_use
++ * bitmap and max_lock_class_idx.
++ */
++#define iterate_lock_classes(idx, class) \
++ for (idx = 0, class = lock_classes; idx <= max_lock_class_idx; \
++ idx++, class++)
++
+ static void *l_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+- return seq_list_next(v, &all_lock_classes, pos);
++ struct lock_class *class = v;
++
++ ++class;
++ *pos = class - lock_classes;
++ return (*pos > max_lock_class_idx) ? NULL : class;
+ }
+
+ static void *l_start(struct seq_file *m, loff_t *pos)
+ {
+- return seq_list_start_head(&all_lock_classes, *pos);
++ unsigned long idx = *pos;
++
++ if (idx > max_lock_class_idx)
++ return NULL;
++ return lock_classes + idx;
+ }
+
+ static void l_stop(struct seq_file *m, void *v)
+@@ -57,14 +76,16 @@ static void print_name(struct seq_file *m, struct lock_class *class)
+
+ static int l_show(struct seq_file *m, void *v)
+ {
+- struct lock_class *class = list_entry(v, struct lock_class, lock_entry);
++ struct lock_class *class = v;
+ struct lock_list *entry;
+ char usage[LOCK_USAGE_CHARS];
++ int idx = class - lock_classes;
+
+- if (v == &all_lock_classes) {
++ if (v == lock_classes)
+ seq_printf(m, "all lock classes:\n");
++
++ if (!test_bit(idx, lock_classes_in_use))
+ return 0;
+- }
+
+ seq_printf(m, "%p", class->key);
+ #ifdef CONFIG_DEBUG_LOCKDEP
+@@ -220,8 +241,11 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
+
+ #ifdef CONFIG_PROVE_LOCKING
+ struct lock_class *class;
++ unsigned long idx;
+
+- list_for_each_entry(class, &all_lock_classes, lock_entry) {
++ iterate_lock_classes(idx, class) {
++ if (!test_bit(idx, lock_classes_in_use))
++ continue;
+
+ if (class->usage_mask == 0)
+ nr_unused++;
+@@ -254,6 +278,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
+
+ sum_forward_deps += lockdep_count_forward_deps(class);
+ }
++
+ #ifdef CONFIG_DEBUG_LOCKDEP
+ DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused);
+ #endif
+@@ -345,6 +370,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
+ seq_printf(m, " max bfs queue depth: %11u\n",
+ max_bfs_queue_depth);
+ #endif
++ seq_printf(m, " max lock class index: %11lu\n",
++ max_lock_class_idx);
+ lockdep_stats_debug_show(m);
+ seq_printf(m, " debug_locks: %11u\n",
+ debug_locks);
+@@ -622,12 +649,16 @@ static int lock_stat_open(struct inode *inode, struct file *file)
+ if (!res) {
+ struct lock_stat_data *iter = data->stats;
+ struct seq_file *m = file->private_data;
++ unsigned long idx;
+
+- list_for_each_entry(class, &all_lock_classes, lock_entry) {
++ iterate_lock_classes(idx, class) {
++ if (!test_bit(idx, lock_classes_in_use))
++ continue;
+ iter->class = class;
+ iter->stats = lock_stats(class);
+ iter++;
+ }
++
+ data->iter_end = iter;
+
+ sort(data->stats, data->iter_end - data->stats,
+@@ -645,6 +676,7 @@ static ssize_t lock_stat_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ struct lock_class *class;
++ unsigned long idx;
+ char c;
+
+ if (count) {
+@@ -654,8 +686,11 @@ static ssize_t lock_stat_write(struct file *file, const char __user *buf,
+ if (c != '0')
+ return count;
+
+- list_for_each_entry(class, &all_lock_classes, lock_entry)
++ iterate_lock_classes(idx, class) {
++ if (!test_bit(idx, lock_classes_in_use))
++ continue;
+ clear_lock_stats(class);
++ }
+ }
+ return count;
+ }
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 6bb116c559b4a..ea5a701ab2408 100644
--- a/kernel/locking/rtmutex.c
@@ -139095,7 +212797,7 @@ index a332ccd829e24..97e62469a6b32 100644
pd->table = table;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
-index 559acef3fddb8..b0888e9224da3 100644
+index 559acef3fddb8..d926852f81191 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -691,7 +691,7 @@ static int load_image_and_restore(void)
@@ -139125,6 +212827,15 @@ index 559acef3fddb8..b0888e9224da3 100644
goto Finish;
}
+@@ -1326,7 +1326,7 @@ static int __init resumedelay_setup(char *str)
+ int rc = kstrtouint(str, 0, &resume_delay);
+
+ if (rc)
+- return rc;
++ pr_warn("resumedelay: bad option string '%s'\n", str);
+ return 1;
+ }
+
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 44169f3081fdc..7e646079fbeb2 100644
--- a/kernel/power/main.c
@@ -139206,6 +212917,37 @@ index eb75f394a0590..13d905dd32675 100644
s2idle_enter();
}
+diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c
+index d20526c5be15b..b663a97f5867a 100644
+--- a/kernel/power/suspend_test.c
++++ b/kernel/power/suspend_test.c
+@@ -157,22 +157,22 @@ static int __init setup_test_suspend(char *value)
+ value++;
+ suspend_type = strsep(&value, ",");
+ if (!suspend_type)
+- return 0;
++ return 1;
+
+ repeat = strsep(&value, ",");
+ if (repeat) {
+ if (kstrtou32(repeat, 0, &test_repeat_count_max))
+- return 0;
++ return 1;
+ }
+
+ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
+ if (!strcmp(pm_labels[i], suspend_type)) {
+ test_state_label = pm_labels[i];
+- return 0;
++ return 1;
+ }
+
+ printk(warn_bad_state, suspend_type);
+- return 0;
++ return 1;
+ }
+ __setup("test_suspend", setup_test_suspend);
+
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3cb89baebc796..f3a1086f7cdb2 100644
--- a/kernel/power/swap.c
@@ -139273,10 +213015,31 @@ index 105df4dfc7839..52571dcad768b 100644
#if CONFIG_PM_WAKELOCKS_LIMIT > 0
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
-index a8d0a58deebc7..99221b016c68b 100644
+index a8d0a58deebc7..7aeb13542ce7a 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -3252,6 +3252,11 @@ void defer_console_output(void)
+@@ -146,8 +146,10 @@ static int __control_devkmsg(char *str)
+
+ static int __init control_devkmsg(char *str)
+ {
+- if (__control_devkmsg(str) < 0)
++ if (__control_devkmsg(str) < 0) {
++ pr_warn("printk.devkmsg: bad option string '%s'\n", str);
+ return 1;
++ }
+
+ /*
+ * Set sysctl string accordingly:
+@@ -166,7 +168,7 @@ static int __init control_devkmsg(char *str)
+ */
+ devkmsg_log |= DEVKMSG_LOG_MASK_LOCK;
+
+- return 0;
++ return 1;
+ }
+ __setup("printk.devkmsg=", control_devkmsg);
+
+@@ -3252,6 +3254,11 @@ void defer_console_output(void)
preempt_enable();
}
@@ -139288,6 +213051,101 @@ index a8d0a58deebc7..99221b016c68b 100644
int vprintk_deferred(const char *fmt, va_list args)
{
int r;
+diff --git a/kernel/ptrace.c b/kernel/ptrace.c
+index f8589bf8d7dce..516ad5e65849f 100644
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -371,6 +371,26 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
+ return !err;
+ }
+
++static int check_ptrace_options(unsigned long data)
++{
++ if (data & ~(unsigned long)PTRACE_O_MASK)
++ return -EINVAL;
++
++ if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
++ if (!IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) ||
++ !IS_ENABLED(CONFIG_SECCOMP))
++ return -EINVAL;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED ||
++ current->ptrace & PT_SUSPEND_SECCOMP)
++ return -EPERM;
++ }
++ return 0;
++}
++
+ static int ptrace_attach(struct task_struct *task, long request,
+ unsigned long addr,
+ unsigned long flags)
+@@ -382,8 +402,16 @@ static int ptrace_attach(struct task_struct *task, long request,
+ if (seize) {
+ if (addr != 0)
+ goto out;
++ /*
++ * This duplicates the check in check_ptrace_options() because
++ * ptrace_attach() and ptrace_setoptions() have historically
++ * used different error codes for unknown ptrace options.
++ */
+ if (flags & ~(unsigned long)PTRACE_O_MASK)
+ goto out;
++ retval = check_ptrace_options(flags);
++ if (retval)
++ return retval;
+ flags = PT_PTRACED | PT_SEIZED | (flags << PT_OPT_FLAG_SHIFT);
+ } else {
+ flags = PT_PTRACED;
+@@ -656,22 +684,11 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
+ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
+ {
+ unsigned flags;
++ int ret;
+
+- if (data & ~(unsigned long)PTRACE_O_MASK)
+- return -EINVAL;
+-
+- if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
+- if (!IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) ||
+- !IS_ENABLED(CONFIG_SECCOMP))
+- return -EINVAL;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED ||
+- current->ptrace & PT_SUSPEND_SECCOMP)
+- return -EPERM;
+- }
++ ret = check_ptrace_options(data);
++ if (ret)
++ return ret;
+
+ /* Avoid intermediate state when all opts are cleared */
+ flags = child->ptrace;
+diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h
+index 9a19328ff2514..5d405943823ec 100644
+--- a/kernel/rcu/rcu_segcblist.h
++++ b/kernel/rcu/rcu_segcblist.h
+@@ -56,13 +56,13 @@ static inline long rcu_segcblist_n_cbs(struct rcu_segcblist *rsclp)
+ static inline void rcu_segcblist_set_flags(struct rcu_segcblist *rsclp,
+ int flags)
+ {
+- rsclp->flags |= flags;
++ WRITE_ONCE(rsclp->flags, rsclp->flags | flags);
+ }
+
+ static inline void rcu_segcblist_clear_flags(struct rcu_segcblist *rsclp,
+ int flags)
+ {
+- rsclp->flags &= ~flags;
++ WRITE_ONCE(rsclp->flags, rsclp->flags & ~flags);
+ }
+
+ static inline bool rcu_segcblist_test_flags(struct rcu_segcblist *rsclp,
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index ab4215266ebee..f922937eb39ad 100644
--- a/kernel/rcu/rcutorture.c
@@ -139424,7 +213282,7 @@ index 806160c44b172..6591914af4864 100644
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
-index bce848e50512e..4ca6d5b199e8e 100644
+index bce848e50512e..a4a9d68b1fdce 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -327,7 +327,7 @@ static void rcu_dynticks_eqs_online(void)
@@ -139460,7 +213318,52 @@ index bce848e50512e..4ca6d5b199e8e 100644
if (first_time) {
/* Collect dyntick-idle snapshots. */
force_qs_rnp(dyntick_save_progress_counter);
-@@ -2550,7 +2551,7 @@ static void rcu_do_batch(struct rcu_data *rdp)
+@@ -2475,7 +2476,7 @@ static void rcu_do_batch(struct rcu_data *rdp)
+ div = READ_ONCE(rcu_divisor);
+ div = div < 0 ? 7 : div > sizeof(long) * 8 - 2 ? sizeof(long) * 8 - 2 : div;
+ bl = max(rdp->blimit, pending >> div);
+- if (unlikely(bl > 100)) {
++ if (in_serving_softirq() && unlikely(bl > 100)) {
+ long rrn = READ_ONCE(rcu_resched_ns);
+
+ rrn = rrn < NSEC_PER_MSEC ? NSEC_PER_MSEC : rrn > NSEC_PER_SEC ? NSEC_PER_SEC : rrn;
+@@ -2512,18 +2513,23 @@ static void rcu_do_batch(struct rcu_data *rdp)
+ /*
+ * Stop only if limit reached and CPU has something to do.
+ */
+- if (count >= bl && !offloaded &&
+- (need_resched() ||
+- (!is_idle_task(current) && !rcu_is_callbacks_kthread())))
+- break;
+- if (unlikely(tlimit)) {
+- /* only call local_clock() every 32 callbacks */
+- if (likely((count & 31) || local_clock() < tlimit))
+- continue;
+- /* Exceeded the time limit, so leave. */
+- break;
+- }
+- if (!in_serving_softirq()) {
++ if (in_serving_softirq()) {
++ if (count >= bl && (need_resched() ||
++ (!is_idle_task(current) && !rcu_is_callbacks_kthread())))
++ break;
++
++ /*
++ * Make sure we don't spend too much time here and deprive other
++ * softirq vectors of CPU cycles.
++ */
++ if (unlikely(tlimit)) {
++ /* only call local_clock() every 32 callbacks */
++ if (likely((count & 31) || local_clock() < tlimit))
++ continue;
++ /* Exceeded the time limit, so leave. */
++ break;
++ }
++ } else {
+ local_bh_enable();
+ lockdep_assert_irqs_enabled();
+ cond_resched_tasks_rcu_qs();
+@@ -2550,7 +2556,7 @@ static void rcu_do_batch(struct rcu_data *rdp)
/* Reset ->qlen_last_fqs_check trigger if enough CBs have drained. */
if (count == 0 && rdp->qlen_last_fqs_check != 0) {
rdp->qlen_last_fqs_check = 0;
@@ -139469,7 +213372,7 @@ index bce848e50512e..4ca6d5b199e8e 100644
} else if (count < rdp->qlen_last_fqs_check - qhimark)
rdp->qlen_last_fqs_check = count;
-@@ -2898,10 +2899,10 @@ static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head,
+@@ -2898,10 +2904,10 @@ static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head,
} else {
/* Give the grace period a kick. */
rdp->blimit = DEFAULT_MAX_RCU_BLIMIT;
@@ -139482,7 +213385,7 @@ index bce848e50512e..4ca6d5b199e8e 100644
rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist);
}
}
-@@ -4128,7 +4129,7 @@ int rcutree_prepare_cpu(unsigned int cpu)
+@@ -4128,7 +4134,7 @@ int rcutree_prepare_cpu(unsigned int cpu)
/* Set up local state, ensuring consistent view of global state. */
raw_spin_lock_irqsave_rcu_node(rnp, flags);
rdp->qlen_last_fqs_check = 0;
@@ -139513,9 +213416,30 @@ index 2796084ef85a5..16f94118ca34b 100644
return;
}
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
-index d070059163d70..0d21a5cdc7247 100644
+index d070059163d70..ef2dd131e9553 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
+@@ -554,16 +554,16 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
+ raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+ }
+
+- /* Unboost if we were boosted. */
+- if (IS_ENABLED(CONFIG_RCU_BOOST) && drop_boost_mutex)
+- rt_mutex_futex_unlock(&rnp->boost_mtx.rtmutex);
+-
+ /*
+ * If this was the last task on the expedited lists,
+ * then we need to report up the rcu_node hierarchy.
+ */
+ if (!empty_exp && empty_exp_now)
+ rcu_report_exp_rnp(rnp, true);
++
++ /* Unboost if we were boosted. */
++ if (IS_ENABLED(CONFIG_RCU_BOOST) && drop_boost_mutex)
++ rt_mutex_futex_unlock(&rnp->boost_mtx.rtmutex);
+ } else {
+ local_irq_restore(flags);
+ }
@@ -1480,7 +1480,7 @@ static void rcu_bind_gp_kthread(void)
}
@@ -139552,6 +213476,99 @@ index d070059163d70..0d21a5cdc7247 100644
{
#ifdef CONFIG_TASKS_TRACE_RCU
if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB))
+diff --git a/kernel/resource.c b/kernel/resource.c
+index ca9f5198a01ff..20e10e48f0523 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -56,14 +56,6 @@ struct resource_constraint {
+
+ static DEFINE_RWLOCK(resource_lock);
+
+-/*
+- * For memory hotplug, there is no way to free resource entries allocated
+- * by boot mem after the system is up. So for reusing the resource entry
+- * we need to remember the resource.
+- */
+-static struct resource *bootmem_resource_free;
+-static DEFINE_SPINLOCK(bootmem_resource_lock);
+-
+ static struct resource *next_resource(struct resource *p)
+ {
+ if (p->child)
+@@ -148,36 +140,19 @@ __initcall(ioresources_init);
+
+ static void free_resource(struct resource *res)
+ {
+- if (!res)
+- return;
+-
+- if (!PageSlab(virt_to_head_page(res))) {
+- spin_lock(&bootmem_resource_lock);
+- res->sibling = bootmem_resource_free;
+- bootmem_resource_free = res;
+- spin_unlock(&bootmem_resource_lock);
+- } else {
++ /**
++ * If the resource was allocated using memblock early during boot
++ * we'll leak it here: we can only return full pages back to the
++ * buddy and trying to be smart and reusing them eventually in
++ * alloc_resource() overcomplicates resource handling.
++ */
++ if (res && PageSlab(virt_to_head_page(res)))
+ kfree(res);
+- }
+ }
+
+ static struct resource *alloc_resource(gfp_t flags)
+ {
+- struct resource *res = NULL;
+-
+- spin_lock(&bootmem_resource_lock);
+- if (bootmem_resource_free) {
+- res = bootmem_resource_free;
+- bootmem_resource_free = res->sibling;
+- }
+- spin_unlock(&bootmem_resource_lock);
+-
+- if (res)
+- memset(res, 0, sizeof(struct resource));
+- else
+- res = kzalloc(sizeof(struct resource), flags);
+-
+- return res;
++ return kzalloc(sizeof(struct resource), flags);
+ }
+
+ /* Return the conflict entry if you can't request it */
+diff --git a/kernel/rseq.c b/kernel/rseq.c
+index 6d45ac3dae7fb..97ac20b4f7387 100644
+--- a/kernel/rseq.c
++++ b/kernel/rseq.c
+@@ -128,10 +128,10 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
+ int ret;
+
+ #ifdef CONFIG_64BIT
+- if (get_user(ptr, &t->rseq->rseq_cs.ptr64))
++ if (get_user(ptr, &t->rseq->rseq_cs))
+ return -EFAULT;
+ #else
+- if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
++ if (copy_from_user(&ptr, &t->rseq->rseq_cs, sizeof(ptr)))
+ return -EFAULT;
+ #endif
+ if (!ptr) {
+@@ -217,9 +217,9 @@ static int clear_rseq_cs(struct task_struct *t)
+ * Set rseq_cs to NULL.
+ */
+ #ifdef CONFIG_64BIT
+- return put_user(0UL, &t->rseq->rseq_cs.ptr64);
++ return put_user(0UL, &t->rseq->rseq_cs);
+ #else
+- if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64)))
++ if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs)))
+ return -EFAULT;
+ return 0;
+ #endif
diff --git a/kernel/sched/autogroup.c b/kernel/sched/autogroup.c
index 2067080bb2358..8629b37d118e7 100644
--- a/kernel/sched/autogroup.c
@@ -139566,10 +213583,18 @@ index 2067080bb2358..8629b37d118e7 100644
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index f21714ea3db85..a0747eaa2dba7 100644
+index f21714ea3db85..779f3198b17de 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
-@@ -1914,7 +1914,7 @@ static void __init init_uclamp_rq(struct rq *rq)
+@@ -36,6 +36,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_rt_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_dl_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_irq_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_se_tp);
++EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_thermal_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(sched_cpu_capacity_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(sched_overutilized_tp);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(sched_util_est_cfs_tp);
+@@ -1914,7 +1915,7 @@ static void __init init_uclamp_rq(struct rq *rq)
};
}
@@ -139578,7 +213603,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
}
static void __init init_uclamp(void)
-@@ -3707,6 +3707,9 @@ out:
+@@ -3707,6 +3708,9 @@ out:
bool cpus_share_cache(int this_cpu, int that_cpu)
{
@@ -139588,7 +213613,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
}
-@@ -4328,8 +4331,6 @@ int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
+@@ -4328,8 +4332,6 @@ int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
*/
int sched_fork(unsigned long clone_flags, struct task_struct *p)
{
@@ -139597,7 +213622,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
__sched_fork(clone_flags, p);
/*
* We mark the process as NEW here. This guarantees that
-@@ -4375,23 +4376,6 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
+@@ -4375,23 +4377,6 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
init_entity_runnable_average(&p->se);
@@ -139621,7 +213646,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
#ifdef CONFIG_SCHED_INFO
if (likely(sched_info_on()))
-@@ -4408,6 +4392,35 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
+@@ -4408,6 +4393,35 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
return 0;
}
@@ -139657,7 +213682,16 @@ index f21714ea3db85..a0747eaa2dba7 100644
void sched_post_fork(struct task_struct *p)
{
uclamp_post_fork(p);
-@@ -6656,11 +6669,11 @@ static int __init setup_preempt_mode(char *str)
+@@ -5913,7 +5927,7 @@ static bool try_steal_cookie(int this, int that)
+ if (p == src->core_pick || p == src->curr)
+ goto next;
+
+- if (!cpumask_test_cpu(this, &p->cpus_mask))
++ if (!is_cpu_allowed(p, this))
+ goto next;
+
+ if (p->core_occupation > dst->idle->core_occupation)
+@@ -6656,11 +6670,11 @@ static int __init setup_preempt_mode(char *str)
int mode = sched_dynamic_mode(str);
if (mode < 0) {
pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
@@ -139671,7 +213705,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
}
__setup("preempt=", setup_preempt_mode);
-@@ -8195,9 +8208,7 @@ int __cond_resched_lock(spinlock_t *lock)
+@@ -8195,9 +8209,7 @@ int __cond_resched_lock(spinlock_t *lock)
if (spin_needbreak(lock) || resched) {
spin_unlock(lock);
@@ -139682,7 +213716,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
cpu_relax();
ret = 1;
spin_lock(lock);
-@@ -8215,9 +8226,7 @@ int __cond_resched_rwlock_read(rwlock_t *lock)
+@@ -8215,9 +8227,7 @@ int __cond_resched_rwlock_read(rwlock_t *lock)
if (rwlock_needbreak(lock) || resched) {
read_unlock(lock);
@@ -139693,7 +213727,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
cpu_relax();
ret = 1;
read_lock(lock);
-@@ -8235,9 +8244,7 @@ int __cond_resched_rwlock_write(rwlock_t *lock)
+@@ -8235,9 +8245,7 @@ int __cond_resched_rwlock_write(rwlock_t *lock)
if (rwlock_needbreak(lock) || resched) {
write_unlock(lock);
@@ -139704,7 +213738,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
cpu_relax();
ret = 1;
write_lock(lock);
-@@ -8637,9 +8644,6 @@ void __init init_idle(struct task_struct *idle, int cpu)
+@@ -8637,9 +8645,6 @@ void __init init_idle(struct task_struct *idle, int cpu)
idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY;
kthread_set_per_cpu(idle, cpu);
@@ -139714,7 +213748,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
#ifdef CONFIG_SMP
/*
* It's possible that init_idle() gets called multiple times on a task,
-@@ -8795,7 +8799,6 @@ void idle_task_exit(void)
+@@ -8795,7 +8800,6 @@ void idle_task_exit(void)
finish_arch_post_lock_switch();
}
@@ -139722,7 +213756,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
/* finish_cpu(), as ran on the BP, will clean up the active_mm state */
}
-@@ -9716,6 +9719,22 @@ static void sched_free_group(struct task_group *tg)
+@@ -9716,6 +9720,22 @@ static void sched_free_group(struct task_group *tg)
kmem_cache_free(task_group_cache, tg);
}
@@ -139745,7 +213779,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
/* allocate runqueue etc for a new task group */
struct task_group *sched_create_group(struct task_group *parent)
{
-@@ -9759,25 +9778,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent)
+@@ -9759,25 +9779,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent)
}
/* rcu callback to free various structures associated with a task group */
@@ -139788,7 +213822,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
spin_lock_irqsave(&task_group_lock, flags);
list_del_rcu(&tg->list);
list_del_rcu(&tg->siblings);
-@@ -9896,7 +9925,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
+@@ -9896,7 +9926,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
{
struct task_group *tg = css_tg(css);
@@ -139797,7 +213831,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
}
static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
-@@ -9906,7 +9935,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
+@@ -9906,7 +9936,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
/*
* Relies on the RCU grace period between css_released() and this.
*/
@@ -139807,7 +213841,7 @@ index f21714ea3db85..a0747eaa2dba7 100644
/*
diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
-index 893eece65bfda..ab67d97a84428 100644
+index 893eece65bfda..cacc2076ad214 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -21,15 +21,11 @@ static const char * const cpuacct_stat_desc[] = {
@@ -139951,9 +213985,11 @@ index 893eece65bfda..ab67d97a84428 100644
seq_puts(m, "\n");
}
return 0;
-@@ -339,16 +329,11 @@ static struct cftype files[] = {
+@@ -338,17 +328,13 @@ static struct cftype files[] = {
+ */
void cpuacct_charge(struct task_struct *tsk, u64 cputime)
{
++ unsigned int cpu = task_cpu(tsk);
struct cpuacct *ca;
- int index = CPUACCT_STAT_SYSTEM;
- struct pt_regs *regs = get_irq_regs() ? : task_pt_regs(tsk);
@@ -139965,10 +214001,22 @@ index 893eece65bfda..ab67d97a84428 100644
for (ca = task_ca(tsk); ca; ca = parent_ca(ca))
- __this_cpu_add(ca->cpuusage->usages[index], cputime);
-+ __this_cpu_add(*ca->cpuusage, cputime);
++ *per_cpu_ptr(ca->cpuusage, cpu) += cputime;
rcu_read_unlock();
}
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index e7af18857371e..7f6bb37d3a2f7 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -289,6 +289,7 @@ static void sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time)
+ * into the same scale so we can compare.
+ */
+ boost = (sg_cpu->iowait_boost * sg_cpu->max) >> SCHED_CAPACITY_SHIFT;
++ boost = uclamp_rq_util_with(cpu_rq(sg_cpu->cpu), boost, NULL);
+ if (sg_cpu->util < boost)
+ sg_cpu->util = boost;
+ }
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 872e481d5098c..042a6dbce8f32 100644
--- a/kernel/sched/cputime.c
@@ -139986,8 +214034,68 @@ index 872e481d5098c..042a6dbce8f32 100644
cpustat[CPUTIME_GUEST] += cputime;
}
}
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index e94314633b39d..1f811b375bf0a 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -2145,12 +2145,6 @@ static int push_dl_task(struct rq *rq)
+ return 0;
+
+ retry:
+- if (is_migration_disabled(next_task))
+- return 0;
+-
+- if (WARN_ON(next_task == rq->curr))
+- return 0;
+-
+ /*
+ * If next_task preempts rq->curr, and rq->curr
+ * can move away, it makes sense to just reschedule
+@@ -2163,6 +2157,12 @@ retry:
+ return 0;
+ }
+
++ if (is_migration_disabled(next_task))
++ return 0;
++
++ if (WARN_ON(next_task == rq->curr))
++ return 0;
++
+ /* We might release rq lock */
+ get_task_struct(next_task);
+
+diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
+index 17a653b67006a..7a2d32d2025fe 100644
+--- a/kernel/sched/debug.c
++++ b/kernel/sched/debug.c
+@@ -921,25 +921,15 @@ void print_numa_stats(struct seq_file *m, int node, unsigned long tsf,
+ static void sched_show_numa(struct task_struct *p, struct seq_file *m)
+ {
+ #ifdef CONFIG_NUMA_BALANCING
+- struct mempolicy *pol;
+-
+ if (p->mm)
+ P(mm->numa_scan_seq);
+
+- task_lock(p);
+- pol = p->mempolicy;
+- if (pol && !(pol->flags & MPOL_F_MORON))
+- pol = NULL;
+- mpol_get(pol);
+- task_unlock(p);
+-
+ P(numa_pages_migrated);
+ P(numa_preferred_nid);
+ P(total_numa_faults);
+ SEQ_printf(m, "current_node=%d, numa_group_id=%d\n",
+ task_node(p), task_numa_group_id(p));
+ show_numa_stats(p, m);
+- mpol_put(pol);
+ #endif
+ }
+
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
-index f6a05d9b54436..6420580f2730b 100644
+index f6a05d9b54436..9a4fa22a69edf 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3422,7 +3422,6 @@ void set_task_rq_fair(struct sched_entity *se,
@@ -140027,6 +214135,23 @@ index f6a05d9b54436..6420580f2730b 100644
r = removed_runnable;
sub_positive(&sa->runnable_avg, r);
+@@ -3784,11 +3794,11 @@ static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
+
+ se->avg.runnable_sum = se->avg.runnable_avg * divider;
+
+- se->avg.load_sum = divider;
+- if (se_weight(se)) {
+- se->avg.load_sum =
+- div_u64(se->avg.load_avg * se->avg.load_sum, se_weight(se));
+- }
++ se->avg.load_sum = se->avg.load_avg * divider;
++ if (se_weight(se) < se->avg.load_sum)
++ se->avg.load_sum = div_u64(se->avg.load_sum, se_weight(se));
++ else
++ se->avg.load_sum = 1;
+
+ enqueue_load_avg(cfs_rq, se);
+ cfs_rq->avg.util_avg += se->avg.util_avg;
@@ -6429,8 +6439,10 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
* pattern is IO completions.
*/
@@ -140039,7 +214164,48 @@ index f6a05d9b54436..6420580f2730b 100644
return prev;
}
-@@ -11358,8 +11370,6 @@ void free_fair_sched_group(struct task_group *tg)
+@@ -8993,9 +9005,10 @@ static bool update_pick_idlest(struct sched_group *idlest,
+ * This is an approximation as the number of running tasks may not be
+ * related to the number of busy CPUs due to sched_setaffinity.
+ */
+-static inline bool allow_numa_imbalance(int dst_running, int dst_weight)
++static inline bool
++allow_numa_imbalance(unsigned int running, unsigned int weight)
+ {
+- return (dst_running < (dst_weight >> 2));
++ return (running < (weight >> 2));
+ }
+
+ /*
+@@ -9129,12 +9142,13 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
+ return idlest;
+ #endif
+ /*
+- * Otherwise, keep the task on this node to stay close
+- * its wakeup source and improve locality. If there is
+- * a real need of migration, periodic load balance will
+- * take care of it.
++ * Otherwise, keep the task close to the wakeup source
++ * and improve locality if the number of running tasks
++ * would remain below threshold where an imbalance is
++ * allowed. If there is a real need of migration,
++ * periodic load balance will take care of it.
+ */
+- if (allow_numa_imbalance(local_sgs.sum_nr_running, sd->span_weight))
++ if (allow_numa_imbalance(local_sgs.sum_nr_running + 1, local_sgs.group_weight))
+ return NULL;
+ }
+
+@@ -9340,7 +9354,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
+ /* Consider allowing a small imbalance between NUMA groups */
+ if (env->sd->flags & SD_NUMA) {
+ env->imbalance = adjust_numa_imbalance(env->imbalance,
+- busiest->sum_nr_running, busiest->group_weight);
++ local->sum_nr_running + 1, local->group_weight);
+ }
+
+ return;
+@@ -11358,8 +11372,6 @@ void free_fair_sched_group(struct task_group *tg)
{
int i;
@@ -140048,7 +214214,7 @@ index f6a05d9b54436..6420580f2730b 100644
for_each_possible_cpu(i) {
if (tg->cfs_rq)
kfree(tg->cfs_rq[i]);
-@@ -11436,6 +11446,8 @@ void unregister_fair_sched_group(struct task_group *tg)
+@@ -11436,6 +11448,8 @@ void unregister_fair_sched_group(struct task_group *tg)
struct rq *rq;
int cpu;
@@ -140443,7 +214609,7 @@ index 1652f2bb54b79..422f3b0445cf1 100644
+
+#endif /* CONFIG_PROC_FS */
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
-index 3daf42a0f4623..54f9bb3f15605 100644
+index 3daf42a0f4623..2758cf5f7987f 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -52,11 +52,8 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
@@ -140523,7 +214689,60 @@ index 3daf42a0f4623..54f9bb3f15605 100644
}
}
}
-@@ -2779,8 +2794,12 @@ static int sched_rt_global_validate(void)
+@@ -1885,6 +1900,16 @@ static int push_rt_task(struct rq *rq, bool pull)
+ return 0;
+
+ retry:
++ /*
++ * It's possible that the next_task slipped in of
++ * higher priority than current. If that's the case
++ * just reschedule current.
++ */
++ if (unlikely(next_task->prio < rq->curr->prio)) {
++ resched_curr(rq);
++ return 0;
++ }
++
+ if (is_migration_disabled(next_task)) {
+ struct task_struct *push_task = NULL;
+ int cpu;
+@@ -1892,6 +1917,18 @@ retry:
+ if (!pull || rq->push_busy)
+ return 0;
+
++ /*
++ * Invoking find_lowest_rq() on anything but an RT task doesn't
++ * make sense. Per the above priority check, curr has to
++ * be of higher priority than next_task, so no need to
++ * reschedule when bailing out.
++ *
++ * Note that the stoppers are masqueraded as SCHED_FIFO
++ * (cf. sched_set_stop_task()), so we can't rely on rt_task().
++ */
++ if (rq->curr->sched_class != &rt_sched_class)
++ return 0;
++
+ cpu = find_lowest_rq(rq->curr);
+ if (cpu == -1 || cpu == rq->cpu)
+ return 0;
+@@ -1916,16 +1953,6 @@ retry:
+ if (WARN_ON(next_task == rq->curr))
+ return 0;
+
+- /*
+- * It's possible that the next_task slipped in of
+- * higher priority than current. If that's the case
+- * just reschedule current.
+- */
+- if (unlikely(next_task->prio < rq->curr->prio)) {
+- resched_curr(rq);
+- return 0;
+- }
+-
+ /* We might release rq lock */
+ get_task_struct(next_task);
+
+@@ -2779,8 +2806,12 @@ static int sched_rt_global_validate(void)
static void sched_rt_do_global(void)
{
@@ -140874,6 +215093,19 @@ index 487bf4f5dadf4..6e3dbb3d12170 100644
if (oact)
*oact = *k;
+diff --git a/kernel/smp.c b/kernel/smp.c
+index f43ede0ab183a..b68d63e965db6 100644
+--- a/kernel/smp.c
++++ b/kernel/smp.c
+@@ -579,7 +579,7 @@ static void flush_smp_call_function_queue(bool warn_cpu_offline)
+
+ /* There shouldn't be any pending callbacks on an offline CPU. */
+ if (unlikely(warn_cpu_offline && !cpu_online(smp_processor_id()) &&
+- !warned && !llist_empty(head))) {
++ !warned && entry != NULL)) {
+ warned = true;
+ WARN(1, "IPI on offline CPU %d\n", smp_processor_id());
+
diff --git a/kernel/stackleak.c b/kernel/stackleak.c
index ce161a8e8d975..dd07239ddff9f 100644
--- a/kernel/stackleak.c
@@ -140898,6 +215130,1154 @@ index ce161a8e8d975..dd07239ddff9f 100644
{
unsigned long sp = current_stack_pointer;
+diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c
+index 9f8117c7cfdde..9c625257023d2 100644
+--- a/kernel/stacktrace.c
++++ b/kernel/stacktrace.c
+@@ -13,6 +13,7 @@
+ #include <linux/export.h>
+ #include <linux/kallsyms.h>
+ #include <linux/stacktrace.h>
++#include <linux/interrupt.h>
+
+ /**
+ * stack_trace_print - Print the entries in the stack trace
+@@ -373,3 +374,32 @@ unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
+ #endif /* CONFIG_USER_STACKTRACE_SUPPORT */
+
+ #endif /* !CONFIG_ARCH_STACKWALK */
++
++static inline bool in_irqentry_text(unsigned long ptr)
++{
++ return (ptr >= (unsigned long)&__irqentry_text_start &&
++ ptr < (unsigned long)&__irqentry_text_end) ||
++ (ptr >= (unsigned long)&__softirqentry_text_start &&
++ ptr < (unsigned long)&__softirqentry_text_end);
++}
++
++/**
++ * filter_irq_stacks - Find first IRQ stack entry in trace
++ * @entries: Pointer to stack trace array
++ * @nr_entries: Number of entries in the storage array
++ *
++ * Return: Number of trace entries until IRQ stack starts.
++ */
++unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr_entries; i++) {
++ if (in_irqentry_text(entries[i])) {
++ /* Include the irqentry function into the stack. */
++ return i + 1;
++ }
++ }
++ return nr_entries;
++}
++EXPORT_SYMBOL_GPL(filter_irq_stacks);
+diff --git a/kernel/static_call.c b/kernel/static_call.c
+index 43ba0b1e0edbb..e9c3e69f38379 100644
+--- a/kernel/static_call.c
++++ b/kernel/static_call.c
+@@ -1,548 +1,8 @@
+ // SPDX-License-Identifier: GPL-2.0
+-#include <linux/init.h>
+ #include <linux/static_call.h>
+-#include <linux/bug.h>
+-#include <linux/smp.h>
+-#include <linux/sort.h>
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-#include <linux/cpu.h>
+-#include <linux/processor.h>
+-#include <asm/sections.h>
+-
+-extern struct static_call_site __start_static_call_sites[],
+- __stop_static_call_sites[];
+-extern struct static_call_tramp_key __start_static_call_tramp_key[],
+- __stop_static_call_tramp_key[];
+-
+-static bool static_call_initialized;
+-
+-/* mutex to protect key modules/sites */
+-static DEFINE_MUTEX(static_call_mutex);
+-
+-static void static_call_lock(void)
+-{
+- mutex_lock(&static_call_mutex);
+-}
+-
+-static void static_call_unlock(void)
+-{
+- mutex_unlock(&static_call_mutex);
+-}
+-
+-static inline void *static_call_addr(struct static_call_site *site)
+-{
+- return (void *)((long)site->addr + (long)&site->addr);
+-}
+-
+-static inline unsigned long __static_call_key(const struct static_call_site *site)
+-{
+- return (long)site->key + (long)&site->key;
+-}
+-
+-static inline struct static_call_key *static_call_key(const struct static_call_site *site)
+-{
+- return (void *)(__static_call_key(site) & ~STATIC_CALL_SITE_FLAGS);
+-}
+-
+-/* These assume the key is word-aligned. */
+-static inline bool static_call_is_init(struct static_call_site *site)
+-{
+- return __static_call_key(site) & STATIC_CALL_SITE_INIT;
+-}
+-
+-static inline bool static_call_is_tail(struct static_call_site *site)
+-{
+- return __static_call_key(site) & STATIC_CALL_SITE_TAIL;
+-}
+-
+-static inline void static_call_set_init(struct static_call_site *site)
+-{
+- site->key = (__static_call_key(site) | STATIC_CALL_SITE_INIT) -
+- (long)&site->key;
+-}
+-
+-static int static_call_site_cmp(const void *_a, const void *_b)
+-{
+- const struct static_call_site *a = _a;
+- const struct static_call_site *b = _b;
+- const struct static_call_key *key_a = static_call_key(a);
+- const struct static_call_key *key_b = static_call_key(b);
+-
+- if (key_a < key_b)
+- return -1;
+-
+- if (key_a > key_b)
+- return 1;
+-
+- return 0;
+-}
+-
+-static void static_call_site_swap(void *_a, void *_b, int size)
+-{
+- long delta = (unsigned long)_a - (unsigned long)_b;
+- struct static_call_site *a = _a;
+- struct static_call_site *b = _b;
+- struct static_call_site tmp = *a;
+-
+- a->addr = b->addr - delta;
+- a->key = b->key - delta;
+-
+- b->addr = tmp.addr + delta;
+- b->key = tmp.key + delta;
+-}
+-
+-static inline void static_call_sort_entries(struct static_call_site *start,
+- struct static_call_site *stop)
+-{
+- sort(start, stop - start, sizeof(struct static_call_site),
+- static_call_site_cmp, static_call_site_swap);
+-}
+-
+-static inline bool static_call_key_has_mods(struct static_call_key *key)
+-{
+- return !(key->type & 1);
+-}
+-
+-static inline struct static_call_mod *static_call_key_next(struct static_call_key *key)
+-{
+- if (!static_call_key_has_mods(key))
+- return NULL;
+-
+- return key->mods;
+-}
+-
+-static inline struct static_call_site *static_call_key_sites(struct static_call_key *key)
+-{
+- if (static_call_key_has_mods(key))
+- return NULL;
+-
+- return (struct static_call_site *)(key->type & ~1);
+-}
+-
+-void __static_call_update(struct static_call_key *key, void *tramp, void *func)
+-{
+- struct static_call_site *site, *stop;
+- struct static_call_mod *site_mod, first;
+-
+- cpus_read_lock();
+- static_call_lock();
+-
+- if (key->func == func)
+- goto done;
+-
+- key->func = func;
+-
+- arch_static_call_transform(NULL, tramp, func, false);
+-
+- /*
+- * If uninitialized, we'll not update the callsites, but they still
+- * point to the trampoline and we just patched that.
+- */
+- if (WARN_ON_ONCE(!static_call_initialized))
+- goto done;
+-
+- first = (struct static_call_mod){
+- .next = static_call_key_next(key),
+- .mod = NULL,
+- .sites = static_call_key_sites(key),
+- };
+-
+- for (site_mod = &first; site_mod; site_mod = site_mod->next) {
+- bool init = system_state < SYSTEM_RUNNING;
+- struct module *mod = site_mod->mod;
+-
+- if (!site_mod->sites) {
+- /*
+- * This can happen if the static call key is defined in
+- * a module which doesn't use it.
+- *
+- * It also happens in the has_mods case, where the
+- * 'first' entry has no sites associated with it.
+- */
+- continue;
+- }
+-
+- stop = __stop_static_call_sites;
+-
+- if (mod) {
+-#ifdef CONFIG_MODULES
+- stop = mod->static_call_sites +
+- mod->num_static_call_sites;
+- init = mod->state == MODULE_STATE_COMING;
+-#endif
+- }
+-
+- for (site = site_mod->sites;
+- site < stop && static_call_key(site) == key; site++) {
+- void *site_addr = static_call_addr(site);
+-
+- if (!init && static_call_is_init(site))
+- continue;
+-
+- if (!kernel_text_address((unsigned long)site_addr)) {
+- /*
+- * This skips patching built-in __exit, which
+- * is part of init_section_contains() but is
+- * not part of kernel_text_address().
+- *
+- * Skipping built-in __exit is fine since it
+- * will never be executed.
+- */
+- WARN_ONCE(!static_call_is_init(site),
+- "can't patch static call site at %pS",
+- site_addr);
+- continue;
+- }
+-
+- arch_static_call_transform(site_addr, NULL, func,
+- static_call_is_tail(site));
+- }
+- }
+-
+-done:
+- static_call_unlock();
+- cpus_read_unlock();
+-}
+-EXPORT_SYMBOL_GPL(__static_call_update);
+-
+-static int __static_call_init(struct module *mod,
+- struct static_call_site *start,
+- struct static_call_site *stop)
+-{
+- struct static_call_site *site;
+- struct static_call_key *key, *prev_key = NULL;
+- struct static_call_mod *site_mod;
+-
+- if (start == stop)
+- return 0;
+-
+- static_call_sort_entries(start, stop);
+-
+- for (site = start; site < stop; site++) {
+- void *site_addr = static_call_addr(site);
+-
+- if ((mod && within_module_init((unsigned long)site_addr, mod)) ||
+- (!mod && init_section_contains(site_addr, 1)))
+- static_call_set_init(site);
+-
+- key = static_call_key(site);
+- if (key != prev_key) {
+- prev_key = key;
+-
+- /*
+- * For vmlinux (!mod) avoid the allocation by storing
+- * the sites pointer in the key itself. Also see
+- * __static_call_update()'s @first.
+- *
+- * This allows architectures (eg. x86) to call
+- * static_call_init() before memory allocation works.
+- */
+- if (!mod) {
+- key->sites = site;
+- key->type |= 1;
+- goto do_transform;
+- }
+-
+- site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
+- if (!site_mod)
+- return -ENOMEM;
+-
+- /*
+- * When the key has a direct sites pointer, extract
+- * that into an explicit struct static_call_mod, so we
+- * can have a list of modules.
+- */
+- if (static_call_key_sites(key)) {
+- site_mod->mod = NULL;
+- site_mod->next = NULL;
+- site_mod->sites = static_call_key_sites(key);
+-
+- key->mods = site_mod;
+-
+- site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
+- if (!site_mod)
+- return -ENOMEM;
+- }
+-
+- site_mod->mod = mod;
+- site_mod->sites = site;
+- site_mod->next = static_call_key_next(key);
+- key->mods = site_mod;
+- }
+-
+-do_transform:
+- arch_static_call_transform(site_addr, NULL, key->func,
+- static_call_is_tail(site));
+- }
+-
+- return 0;
+-}
+-
+-static int addr_conflict(struct static_call_site *site, void *start, void *end)
+-{
+- unsigned long addr = (unsigned long)static_call_addr(site);
+-
+- if (addr <= (unsigned long)end &&
+- addr + CALL_INSN_SIZE > (unsigned long)start)
+- return 1;
+-
+- return 0;
+-}
+-
+-static int __static_call_text_reserved(struct static_call_site *iter_start,
+- struct static_call_site *iter_stop,
+- void *start, void *end, bool init)
+-{
+- struct static_call_site *iter = iter_start;
+-
+- while (iter < iter_stop) {
+- if (init || !static_call_is_init(iter)) {
+- if (addr_conflict(iter, start, end))
+- return 1;
+- }
+- iter++;
+- }
+-
+- return 0;
+-}
+-
+-#ifdef CONFIG_MODULES
+-
+-static int __static_call_mod_text_reserved(void *start, void *end)
+-{
+- struct module *mod;
+- int ret;
+-
+- preempt_disable();
+- mod = __module_text_address((unsigned long)start);
+- WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
+- if (!try_module_get(mod))
+- mod = NULL;
+- preempt_enable();
+-
+- if (!mod)
+- return 0;
+-
+- ret = __static_call_text_reserved(mod->static_call_sites,
+- mod->static_call_sites + mod->num_static_call_sites,
+- start, end, mod->state == MODULE_STATE_COMING);
+-
+- module_put(mod);
+-
+- return ret;
+-}
+-
+-static unsigned long tramp_key_lookup(unsigned long addr)
+-{
+- struct static_call_tramp_key *start = __start_static_call_tramp_key;
+- struct static_call_tramp_key *stop = __stop_static_call_tramp_key;
+- struct static_call_tramp_key *tramp_key;
+-
+- for (tramp_key = start; tramp_key != stop; tramp_key++) {
+- unsigned long tramp;
+-
+- tramp = (long)tramp_key->tramp + (long)&tramp_key->tramp;
+- if (tramp == addr)
+- return (long)tramp_key->key + (long)&tramp_key->key;
+- }
+-
+- return 0;
+-}
+-
+-static int static_call_add_module(struct module *mod)
+-{
+- struct static_call_site *start = mod->static_call_sites;
+- struct static_call_site *stop = start + mod->num_static_call_sites;
+- struct static_call_site *site;
+-
+- for (site = start; site != stop; site++) {
+- unsigned long s_key = __static_call_key(site);
+- unsigned long addr = s_key & ~STATIC_CALL_SITE_FLAGS;
+- unsigned long key;
+-
+- /*
+- * Is the key is exported, 'addr' points to the key, which
+- * means modules are allowed to call static_call_update() on
+- * it.
+- *
+- * Otherwise, the key isn't exported, and 'addr' points to the
+- * trampoline so we need to lookup the key.
+- *
+- * We go through this dance to prevent crazy modules from
+- * abusing sensitive static calls.
+- */
+- if (!kernel_text_address(addr))
+- continue;
+-
+- key = tramp_key_lookup(addr);
+- if (!key) {
+- pr_warn("Failed to fixup __raw_static_call() usage at: %ps\n",
+- static_call_addr(site));
+- return -EINVAL;
+- }
+-
+- key |= s_key & STATIC_CALL_SITE_FLAGS;
+- site->key = key - (long)&site->key;
+- }
+-
+- return __static_call_init(mod, start, stop);
+-}
+-
+-static void static_call_del_module(struct module *mod)
+-{
+- struct static_call_site *start = mod->static_call_sites;
+- struct static_call_site *stop = mod->static_call_sites +
+- mod->num_static_call_sites;
+- struct static_call_key *key, *prev_key = NULL;
+- struct static_call_mod *site_mod, **prev;
+- struct static_call_site *site;
+-
+- for (site = start; site < stop; site++) {
+- key = static_call_key(site);
+- if (key == prev_key)
+- continue;
+-
+- prev_key = key;
+-
+- for (prev = &key->mods, site_mod = key->mods;
+- site_mod && site_mod->mod != mod;
+- prev = &site_mod->next, site_mod = site_mod->next)
+- ;
+-
+- if (!site_mod)
+- continue;
+-
+- *prev = site_mod->next;
+- kfree(site_mod);
+- }
+-}
+-
+-static int static_call_module_notify(struct notifier_block *nb,
+- unsigned long val, void *data)
+-{
+- struct module *mod = data;
+- int ret = 0;
+-
+- cpus_read_lock();
+- static_call_lock();
+-
+- switch (val) {
+- case MODULE_STATE_COMING:
+- ret = static_call_add_module(mod);
+- if (ret) {
+- WARN(1, "Failed to allocate memory for static calls");
+- static_call_del_module(mod);
+- }
+- break;
+- case MODULE_STATE_GOING:
+- static_call_del_module(mod);
+- break;
+- }
+-
+- static_call_unlock();
+- cpus_read_unlock();
+-
+- return notifier_from_errno(ret);
+-}
+-
+-static struct notifier_block static_call_module_nb = {
+- .notifier_call = static_call_module_notify,
+-};
+-
+-#else
+-
+-static inline int __static_call_mod_text_reserved(void *start, void *end)
+-{
+- return 0;
+-}
+-
+-#endif /* CONFIG_MODULES */
+-
+-int static_call_text_reserved(void *start, void *end)
+-{
+- bool init = system_state < SYSTEM_RUNNING;
+- int ret = __static_call_text_reserved(__start_static_call_sites,
+- __stop_static_call_sites, start, end, init);
+-
+- if (ret)
+- return ret;
+-
+- return __static_call_mod_text_reserved(start, end);
+-}
+-
+-int __init static_call_init(void)
+-{
+- int ret;
+-
+- if (static_call_initialized)
+- return 0;
+-
+- cpus_read_lock();
+- static_call_lock();
+- ret = __static_call_init(NULL, __start_static_call_sites,
+- __stop_static_call_sites);
+- static_call_unlock();
+- cpus_read_unlock();
+-
+- if (ret) {
+- pr_err("Failed to allocate memory for static_call!\n");
+- BUG();
+- }
+-
+- static_call_initialized = true;
+-
+-#ifdef CONFIG_MODULES
+- register_module_notifier(&static_call_module_nb);
+-#endif
+- return 0;
+-}
+-early_initcall(static_call_init);
+
+ long __static_call_return0(void)
+ {
+ return 0;
+ }
+-
+-#ifdef CONFIG_STATIC_CALL_SELFTEST
+-
+-static int func_a(int x)
+-{
+- return x+1;
+-}
+-
+-static int func_b(int x)
+-{
+- return x+2;
+-}
+-
+-DEFINE_STATIC_CALL(sc_selftest, func_a);
+-
+-static struct static_call_data {
+- int (*func)(int);
+- int val;
+- int expect;
+-} static_call_data [] __initdata = {
+- { NULL, 2, 3 },
+- { func_b, 2, 4 },
+- { func_a, 2, 3 }
+-};
+-
+-static int __init test_static_call_init(void)
+-{
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(static_call_data); i++ ) {
+- struct static_call_data *scd = &static_call_data[i];
+-
+- if (scd->func)
+- static_call_update(sc_selftest, scd->func);
+-
+- WARN_ON(static_call(sc_selftest)(scd->val) != scd->expect);
+- }
+-
+- return 0;
+-}
+-early_initcall(test_static_call_init);
+-
+-#endif /* CONFIG_STATIC_CALL_SELFTEST */
++EXPORT_SYMBOL_GPL(__static_call_return0);
+diff --git a/kernel/static_call_inline.c b/kernel/static_call_inline.c
+new file mode 100644
+index 0000000000000..dc5665b628140
+--- /dev/null
++++ b/kernel/static_call_inline.c
+@@ -0,0 +1,543 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <linux/init.h>
++#include <linux/static_call.h>
++#include <linux/bug.h>
++#include <linux/smp.h>
++#include <linux/sort.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/cpu.h>
++#include <linux/processor.h>
++#include <asm/sections.h>
++
++extern struct static_call_site __start_static_call_sites[],
++ __stop_static_call_sites[];
++extern struct static_call_tramp_key __start_static_call_tramp_key[],
++ __stop_static_call_tramp_key[];
++
++static bool static_call_initialized;
++
++/* mutex to protect key modules/sites */
++static DEFINE_MUTEX(static_call_mutex);
++
++static void static_call_lock(void)
++{
++ mutex_lock(&static_call_mutex);
++}
++
++static void static_call_unlock(void)
++{
++ mutex_unlock(&static_call_mutex);
++}
++
++static inline void *static_call_addr(struct static_call_site *site)
++{
++ return (void *)((long)site->addr + (long)&site->addr);
++}
++
++static inline unsigned long __static_call_key(const struct static_call_site *site)
++{
++ return (long)site->key + (long)&site->key;
++}
++
++static inline struct static_call_key *static_call_key(const struct static_call_site *site)
++{
++ return (void *)(__static_call_key(site) & ~STATIC_CALL_SITE_FLAGS);
++}
++
++/* These assume the key is word-aligned. */
++static inline bool static_call_is_init(struct static_call_site *site)
++{
++ return __static_call_key(site) & STATIC_CALL_SITE_INIT;
++}
++
++static inline bool static_call_is_tail(struct static_call_site *site)
++{
++ return __static_call_key(site) & STATIC_CALL_SITE_TAIL;
++}
++
++static inline void static_call_set_init(struct static_call_site *site)
++{
++ site->key = (__static_call_key(site) | STATIC_CALL_SITE_INIT) -
++ (long)&site->key;
++}
++
++static int static_call_site_cmp(const void *_a, const void *_b)
++{
++ const struct static_call_site *a = _a;
++ const struct static_call_site *b = _b;
++ const struct static_call_key *key_a = static_call_key(a);
++ const struct static_call_key *key_b = static_call_key(b);
++
++ if (key_a < key_b)
++ return -1;
++
++ if (key_a > key_b)
++ return 1;
++
++ return 0;
++}
++
++static void static_call_site_swap(void *_a, void *_b, int size)
++{
++ long delta = (unsigned long)_a - (unsigned long)_b;
++ struct static_call_site *a = _a;
++ struct static_call_site *b = _b;
++ struct static_call_site tmp = *a;
++
++ a->addr = b->addr - delta;
++ a->key = b->key - delta;
++
++ b->addr = tmp.addr + delta;
++ b->key = tmp.key + delta;
++}
++
++static inline void static_call_sort_entries(struct static_call_site *start,
++ struct static_call_site *stop)
++{
++ sort(start, stop - start, sizeof(struct static_call_site),
++ static_call_site_cmp, static_call_site_swap);
++}
++
++static inline bool static_call_key_has_mods(struct static_call_key *key)
++{
++ return !(key->type & 1);
++}
++
++static inline struct static_call_mod *static_call_key_next(struct static_call_key *key)
++{
++ if (!static_call_key_has_mods(key))
++ return NULL;
++
++ return key->mods;
++}
++
++static inline struct static_call_site *static_call_key_sites(struct static_call_key *key)
++{
++ if (static_call_key_has_mods(key))
++ return NULL;
++
++ return (struct static_call_site *)(key->type & ~1);
++}
++
++void __static_call_update(struct static_call_key *key, void *tramp, void *func)
++{
++ struct static_call_site *site, *stop;
++ struct static_call_mod *site_mod, first;
++
++ cpus_read_lock();
++ static_call_lock();
++
++ if (key->func == func)
++ goto done;
++
++ key->func = func;
++
++ arch_static_call_transform(NULL, tramp, func, false);
++
++ /*
++ * If uninitialized, we'll not update the callsites, but they still
++ * point to the trampoline and we just patched that.
++ */
++ if (WARN_ON_ONCE(!static_call_initialized))
++ goto done;
++
++ first = (struct static_call_mod){
++ .next = static_call_key_next(key),
++ .mod = NULL,
++ .sites = static_call_key_sites(key),
++ };
++
++ for (site_mod = &first; site_mod; site_mod = site_mod->next) {
++ bool init = system_state < SYSTEM_RUNNING;
++ struct module *mod = site_mod->mod;
++
++ if (!site_mod->sites) {
++ /*
++ * This can happen if the static call key is defined in
++ * a module which doesn't use it.
++ *
++ * It also happens in the has_mods case, where the
++ * 'first' entry has no sites associated with it.
++ */
++ continue;
++ }
++
++ stop = __stop_static_call_sites;
++
++ if (mod) {
++#ifdef CONFIG_MODULES
++ stop = mod->static_call_sites +
++ mod->num_static_call_sites;
++ init = mod->state == MODULE_STATE_COMING;
++#endif
++ }
++
++ for (site = site_mod->sites;
++ site < stop && static_call_key(site) == key; site++) {
++ void *site_addr = static_call_addr(site);
++
++ if (!init && static_call_is_init(site))
++ continue;
++
++ if (!kernel_text_address((unsigned long)site_addr)) {
++ /*
++ * This skips patching built-in __exit, which
++ * is part of init_section_contains() but is
++ * not part of kernel_text_address().
++ *
++ * Skipping built-in __exit is fine since it
++ * will never be executed.
++ */
++ WARN_ONCE(!static_call_is_init(site),
++ "can't patch static call site at %pS",
++ site_addr);
++ continue;
++ }
++
++ arch_static_call_transform(site_addr, NULL, func,
++ static_call_is_tail(site));
++ }
++ }
++
++done:
++ static_call_unlock();
++ cpus_read_unlock();
++}
++EXPORT_SYMBOL_GPL(__static_call_update);
++
++static int __static_call_init(struct module *mod,
++ struct static_call_site *start,
++ struct static_call_site *stop)
++{
++ struct static_call_site *site;
++ struct static_call_key *key, *prev_key = NULL;
++ struct static_call_mod *site_mod;
++
++ if (start == stop)
++ return 0;
++
++ static_call_sort_entries(start, stop);
++
++ for (site = start; site < stop; site++) {
++ void *site_addr = static_call_addr(site);
++
++ if ((mod && within_module_init((unsigned long)site_addr, mod)) ||
++ (!mod && init_section_contains(site_addr, 1)))
++ static_call_set_init(site);
++
++ key = static_call_key(site);
++ if (key != prev_key) {
++ prev_key = key;
++
++ /*
++ * For vmlinux (!mod) avoid the allocation by storing
++ * the sites pointer in the key itself. Also see
++ * __static_call_update()'s @first.
++ *
++ * This allows architectures (eg. x86) to call
++ * static_call_init() before memory allocation works.
++ */
++ if (!mod) {
++ key->sites = site;
++ key->type |= 1;
++ goto do_transform;
++ }
++
++ site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
++ if (!site_mod)
++ return -ENOMEM;
++
++ /*
++ * When the key has a direct sites pointer, extract
++ * that into an explicit struct static_call_mod, so we
++ * can have a list of modules.
++ */
++ if (static_call_key_sites(key)) {
++ site_mod->mod = NULL;
++ site_mod->next = NULL;
++ site_mod->sites = static_call_key_sites(key);
++
++ key->mods = site_mod;
++
++ site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
++ if (!site_mod)
++ return -ENOMEM;
++ }
++
++ site_mod->mod = mod;
++ site_mod->sites = site;
++ site_mod->next = static_call_key_next(key);
++ key->mods = site_mod;
++ }
++
++do_transform:
++ arch_static_call_transform(site_addr, NULL, key->func,
++ static_call_is_tail(site));
++ }
++
++ return 0;
++}
++
++static int addr_conflict(struct static_call_site *site, void *start, void *end)
++{
++ unsigned long addr = (unsigned long)static_call_addr(site);
++
++ if (addr <= (unsigned long)end &&
++ addr + CALL_INSN_SIZE > (unsigned long)start)
++ return 1;
++
++ return 0;
++}
++
++static int __static_call_text_reserved(struct static_call_site *iter_start,
++ struct static_call_site *iter_stop,
++ void *start, void *end, bool init)
++{
++ struct static_call_site *iter = iter_start;
++
++ while (iter < iter_stop) {
++ if (init || !static_call_is_init(iter)) {
++ if (addr_conflict(iter, start, end))
++ return 1;
++ }
++ iter++;
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_MODULES
++
++static int __static_call_mod_text_reserved(void *start, void *end)
++{
++ struct module *mod;
++ int ret;
++
++ preempt_disable();
++ mod = __module_text_address((unsigned long)start);
++ WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
++ if (!try_module_get(mod))
++ mod = NULL;
++ preempt_enable();
++
++ if (!mod)
++ return 0;
++
++ ret = __static_call_text_reserved(mod->static_call_sites,
++ mod->static_call_sites + mod->num_static_call_sites,
++ start, end, mod->state == MODULE_STATE_COMING);
++
++ module_put(mod);
++
++ return ret;
++}
++
++static unsigned long tramp_key_lookup(unsigned long addr)
++{
++ struct static_call_tramp_key *start = __start_static_call_tramp_key;
++ struct static_call_tramp_key *stop = __stop_static_call_tramp_key;
++ struct static_call_tramp_key *tramp_key;
++
++ for (tramp_key = start; tramp_key != stop; tramp_key++) {
++ unsigned long tramp;
++
++ tramp = (long)tramp_key->tramp + (long)&tramp_key->tramp;
++ if (tramp == addr)
++ return (long)tramp_key->key + (long)&tramp_key->key;
++ }
++
++ return 0;
++}
++
++static int static_call_add_module(struct module *mod)
++{
++ struct static_call_site *start = mod->static_call_sites;
++ struct static_call_site *stop = start + mod->num_static_call_sites;
++ struct static_call_site *site;
++
++ for (site = start; site != stop; site++) {
++ unsigned long s_key = __static_call_key(site);
++ unsigned long addr = s_key & ~STATIC_CALL_SITE_FLAGS;
++ unsigned long key;
++
++ /*
++ * Is the key is exported, 'addr' points to the key, which
++ * means modules are allowed to call static_call_update() on
++ * it.
++ *
++ * Otherwise, the key isn't exported, and 'addr' points to the
++ * trampoline so we need to lookup the key.
++ *
++ * We go through this dance to prevent crazy modules from
++ * abusing sensitive static calls.
++ */
++ if (!kernel_text_address(addr))
++ continue;
++
++ key = tramp_key_lookup(addr);
++ if (!key) {
++ pr_warn("Failed to fixup __raw_static_call() usage at: %ps\n",
++ static_call_addr(site));
++ return -EINVAL;
++ }
++
++ key |= s_key & STATIC_CALL_SITE_FLAGS;
++ site->key = key - (long)&site->key;
++ }
++
++ return __static_call_init(mod, start, stop);
++}
++
++static void static_call_del_module(struct module *mod)
++{
++ struct static_call_site *start = mod->static_call_sites;
++ struct static_call_site *stop = mod->static_call_sites +
++ mod->num_static_call_sites;
++ struct static_call_key *key, *prev_key = NULL;
++ struct static_call_mod *site_mod, **prev;
++ struct static_call_site *site;
++
++ for (site = start; site < stop; site++) {
++ key = static_call_key(site);
++ if (key == prev_key)
++ continue;
++
++ prev_key = key;
++
++ for (prev = &key->mods, site_mod = key->mods;
++ site_mod && site_mod->mod != mod;
++ prev = &site_mod->next, site_mod = site_mod->next)
++ ;
++
++ if (!site_mod)
++ continue;
++
++ *prev = site_mod->next;
++ kfree(site_mod);
++ }
++}
++
++static int static_call_module_notify(struct notifier_block *nb,
++ unsigned long val, void *data)
++{
++ struct module *mod = data;
++ int ret = 0;
++
++ cpus_read_lock();
++ static_call_lock();
++
++ switch (val) {
++ case MODULE_STATE_COMING:
++ ret = static_call_add_module(mod);
++ if (ret) {
++ WARN(1, "Failed to allocate memory for static calls");
++ static_call_del_module(mod);
++ }
++ break;
++ case MODULE_STATE_GOING:
++ static_call_del_module(mod);
++ break;
++ }
++
++ static_call_unlock();
++ cpus_read_unlock();
++
++ return notifier_from_errno(ret);
++}
++
++static struct notifier_block static_call_module_nb = {
++ .notifier_call = static_call_module_notify,
++};
++
++#else
++
++static inline int __static_call_mod_text_reserved(void *start, void *end)
++{
++ return 0;
++}
++
++#endif /* CONFIG_MODULES */
++
++int static_call_text_reserved(void *start, void *end)
++{
++ bool init = system_state < SYSTEM_RUNNING;
++ int ret = __static_call_text_reserved(__start_static_call_sites,
++ __stop_static_call_sites, start, end, init);
++
++ if (ret)
++ return ret;
++
++ return __static_call_mod_text_reserved(start, end);
++}
++
++int __init static_call_init(void)
++{
++ int ret;
++
++ if (static_call_initialized)
++ return 0;
++
++ cpus_read_lock();
++ static_call_lock();
++ ret = __static_call_init(NULL, __start_static_call_sites,
++ __stop_static_call_sites);
++ static_call_unlock();
++ cpus_read_unlock();
++
++ if (ret) {
++ pr_err("Failed to allocate memory for static_call!\n");
++ BUG();
++ }
++
++ static_call_initialized = true;
++
++#ifdef CONFIG_MODULES
++ register_module_notifier(&static_call_module_nb);
++#endif
++ return 0;
++}
++early_initcall(static_call_init);
++
++#ifdef CONFIG_STATIC_CALL_SELFTEST
++
++static int func_a(int x)
++{
++ return x+1;
++}
++
++static int func_b(int x)
++{
++ return x+2;
++}
++
++DEFINE_STATIC_CALL(sc_selftest, func_a);
++
++static struct static_call_data {
++ int (*func)(int);
++ int val;
++ int expect;
++} static_call_data [] __initdata = {
++ { NULL, 2, 3 },
++ { func_b, 2, 4 },
++ { func_a, 2, 3 }
++};
++
++static int __init test_static_call_init(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(static_call_data); i++ ) {
++ struct static_call_data *scd = &static_call_data[i];
++
++ if (scd->func)
++ static_call_update(sc_selftest, scd->func);
++
++ WARN_ON(static_call(sc_selftest)(scd->val) != scd->expect);
++ }
++
++ return 0;
++}
++early_initcall(test_static_call_init);
++
++#endif /* CONFIG_STATIC_CALL_SELFTEST */
diff --git a/kernel/sys.c b/kernel/sys.c
index 8fdac0d90504a..3e4e8930fafc6 100644
--- a/kernel/sys.c
@@ -141123,11 +216503,50 @@ index 643d412ac6235..96b4e78104266 100644
}
/*
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index 6bffe5af8cb11..19e6b861de97b 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -186,7 +186,7 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
+ */
+ if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) {
+ #ifdef CONFIG_NO_HZ_FULL
+- WARN_ON(tick_nohz_full_running);
++ WARN_ON_ONCE(tick_nohz_full_running);
+ #endif
+ tick_do_timer_cpu = cpu;
+ }
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
-index b348749a9fc62..dcdcb85121e40 100644
+index b348749a9fc62..871c912860ed5 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
-@@ -1306,8 +1306,7 @@ int do_settimeofday64(const struct timespec64 *ts)
+@@ -17,6 +17,7 @@
+ #include <linux/clocksource.h>
+ #include <linux/jiffies.h>
+ #include <linux/time.h>
++#include <linux/timex.h>
+ #include <linux/tick.h>
+ #include <linux/stop_machine.h>
+ #include <linux/pvclock_gtod.h>
+@@ -482,7 +483,7 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf)
+ * of the following timestamps. Callers need to be aware of that and
+ * deal with it.
+ */
+-u64 ktime_get_mono_fast_ns(void)
++u64 notrace ktime_get_mono_fast_ns(void)
+ {
+ return __ktime_get_fast_ns(&tk_fast_mono);
+ }
+@@ -494,7 +495,7 @@ EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns);
+ * Contrary to ktime_get_mono_fast_ns() this is always correct because the
+ * conversion factor is not affected by NTP/PTP correction.
+ */
+-u64 ktime_get_raw_fast_ns(void)
++u64 notrace ktime_get_raw_fast_ns(void)
+ {
+ return __ktime_get_fast_ns(&tk_fast_raw);
+ }
+@@ -1306,8 +1307,7 @@ int do_settimeofday64(const struct timespec64 *ts)
timekeeping_forward_now(tk);
xt = tk_xtime(tk);
@@ -141137,11 +216556,51 @@ index b348749a9fc62..dcdcb85121e40 100644
if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) {
ret = -EINVAL;
+@@ -2381,6 +2381,20 @@ static int timekeeping_validate_timex(const struct __kernel_timex *txc)
+ return 0;
+ }
+
++/**
++ * random_get_entropy_fallback - Returns the raw clock source value,
++ * used by random.c for platforms with no valid random_get_entropy().
++ */
++unsigned long random_get_entropy_fallback(void)
++{
++ struct tk_read_base *tkr = &tk_core.timekeeper.tkr_mono;
++ struct clocksource *clock = READ_ONCE(tkr->clock);
++
++ if (unlikely(timekeeping_suspended || !clock))
++ return 0;
++ return clock->read(clock);
++}
++EXPORT_SYMBOL_GPL(random_get_entropy_fallback);
+
+ /**
+ * do_adjtimex() - Accessor function to NTP __do_adjtimex function
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
-index e3d2c23c413d4..85f1021ad4595 100644
+index e3d2c23c413d4..9dd2a39cb3b00 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
-@@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsigned int msecs)
+@@ -1722,11 +1722,14 @@ static inline void __run_timers(struct timer_base *base)
+ time_after_eq(jiffies, base->next_expiry)) {
+ levels = collect_expired_timers(base, heads);
+ /*
+- * The only possible reason for not finding any expired
+- * timer at this clk is that all matching timers have been
+- * dequeued.
++ * The two possible reasons for not finding any expired
++ * timer at this clk are that all matching timers have been
++ * dequeued or no timer has been queued since
++ * base::next_expiry was set to base::clk +
++ * NEXT_TIMER_MAX_DELTA.
+ */
+- WARN_ON_ONCE(!levels && !base->next_expiry_recalc);
++ WARN_ON_ONCE(!levels && !base->next_expiry_recalc
++ && base->timers_pending);
+ base->clk++;
+ base->next_expiry = __next_timer_interrupt(base);
+
+@@ -2054,26 +2057,28 @@ unsigned long msleep_interruptible(unsigned int msecs)
EXPORT_SYMBOL(msleep_interruptible);
/**
@@ -141254,9 +216713,75 @@ index fa91f398f28b7..c42ff77eb6ccc 100644
}
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
-index 8e2eb950aa829..5a18b861fcf75 100644
+index 8e2eb950aa829..c289010b0964e 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
+@@ -345,7 +345,7 @@ static const struct bpf_func_proto bpf_probe_write_user_proto = {
+ .gpl_only = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_ANYTHING,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ };
+
+@@ -394,7 +394,7 @@ static const struct bpf_func_proto bpf_trace_printk_proto = {
+ .func = bpf_trace_printk,
+ .gpl_only = true,
+ .ret_type = RET_INTEGER,
+- .arg1_type = ARG_PTR_TO_MEM,
++ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg2_type = ARG_CONST_SIZE,
+ };
+
+@@ -446,9 +446,9 @@ static const struct bpf_func_proto bpf_seq_printf_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID,
+ .arg1_btf_id = &btf_seq_file_ids[0],
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+- .arg4_type = ARG_PTR_TO_MEM_OR_NULL,
++ .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -463,7 +463,7 @@ static const struct bpf_func_proto bpf_seq_write_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID,
+ .arg1_btf_id = &btf_seq_file_ids[0],
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -487,7 +487,7 @@ static const struct bpf_func_proto bpf_seq_printf_btf_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID,
+ .arg1_btf_id = &btf_seq_file_ids[0],
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg4_type = ARG_ANYTHING,
+ };
+@@ -648,7 +648,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -958,7 +958,7 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_MEM,
+ .arg2_type = ARG_CONST_SIZE,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE,
+ .arg5_type = ARG_ANYTHING,
+ };
@@ -1037,8 +1037,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_ktime_get_ns_proto;
case BPF_FUNC_ktime_get_boot_ns:
@@ -141266,6 +216791,15 @@ index 8e2eb950aa829..5a18b861fcf75 100644
case BPF_FUNC_tail_call:
return &bpf_tail_call_proto;
case BPF_FUNC_get_current_pid_tgid:
+@@ -1209,7 +1207,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_tp = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
@@ -1324,9 +1322,6 @@ static const struct bpf_func_proto bpf_perf_prog_read_value_proto = {
BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
void *, buf, u32, size, u64, flags)
@@ -141293,6 +216827,24 @@ index 8e2eb950aa829..5a18b861fcf75 100644
}
static const struct bpf_func_proto bpf_read_branch_records_proto = {
+@@ -1435,7 +1429,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -1489,7 +1483,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
+ .gpl_only = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg4_type = ARG_ANYTHING,
+ };
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index feebf57c64588..c672040142e98 100644
--- a/kernel/trace/ftrace.c
@@ -141384,7 +216936,7 @@ index c5a3fbf19617e..46ae72095c1e2 100644
EXPORT_SYMBOL_GPL(ring_buffer_reset);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
-index bc677cd642240..86fb77c2ace5b 100644
+index bc677cd642240..b49756608f838 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -235,7 +235,7 @@ static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
@@ -141414,7 +216966,24 @@ index bc677cd642240..86fb77c2ace5b 100644
if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0))
tracepoint_printk = 1;
return 1;
-@@ -1714,7 +1718,8 @@ static void trace_create_maxlat_file(struct trace_array *tr,
+@@ -1492,10 +1496,12 @@ static int __init set_buf_size(char *str)
+ if (!str)
+ return 0;
+ buf_size = memparse(str, &str);
+- /* nr_entries can not be zero */
+- if (buf_size == 0)
+- return 0;
+- trace_buf_size = buf_size;
++ /*
++ * nr_entries can not be zero and the startup
++ * tests require some buffer space. Therefore
++ * ensure we have at least 4096 bytes of buffer.
++ */
++ trace_buf_size = max(4096UL, buf_size);
+ return 1;
+ }
+ __setup("trace_buf_size=", set_buf_size);
+@@ -1714,7 +1720,8 @@ static void trace_create_maxlat_file(struct trace_array *tr,
{
INIT_WORK(&tr->fsnotify_work, latency_fsnotify_workfn);
init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq);
@@ -141424,7 +216993,7 @@ index bc677cd642240..86fb77c2ace5b 100644
d_tracer, &tr->max_latency,
&tracing_max_lat_fops);
}
-@@ -1748,8 +1753,8 @@ void latency_fsnotify(struct trace_array *tr)
+@@ -1748,8 +1755,8 @@ void latency_fsnotify(struct trace_array *tr)
|| defined(CONFIG_OSNOISE_TRACER)
#define trace_create_maxlat_file(tr, d_tracer) \
@@ -141435,7 +217004,7 @@ index bc677cd642240..86fb77c2ace5b 100644
#else
#define trace_create_maxlat_file(tr, d_tracer) do { } while (0)
-@@ -3230,7 +3235,7 @@ struct trace_buffer_struct {
+@@ -3230,7 +3237,7 @@ struct trace_buffer_struct {
char buffer[4][TRACE_BUF_SIZE];
};
@@ -141444,7 +217013,7 @@ index bc677cd642240..86fb77c2ace5b 100644
/*
* This allows for lockless recording. If we're nested too deeply, then
-@@ -3240,7 +3245,7 @@ static char *get_trace_buf(void)
+@@ -3240,7 +3247,7 @@ static char *get_trace_buf(void)
{
struct trace_buffer_struct *buffer = this_cpu_ptr(trace_percpu_buffer);
@@ -141453,7 +217022,7 @@ index bc677cd642240..86fb77c2ace5b 100644
return NULL;
buffer->nesting++;
-@@ -3259,7 +3264,7 @@ static void put_trace_buf(void)
+@@ -3259,7 +3266,7 @@ static void put_trace_buf(void)
static int alloc_percpu_trace_buffer(void)
{
@@ -141462,7 +217031,26 @@ index bc677cd642240..86fb77c2ace5b 100644
if (trace_percpu_buffer)
return 0;
-@@ -3835,6 +3840,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
+@@ -3671,12 +3678,17 @@ static char *trace_iter_expand_format(struct trace_iterator *iter)
+ }
+
+ /* Returns true if the string is safe to dereference from an event */
+-static bool trace_safe_str(struct trace_iterator *iter, const char *str)
++static bool trace_safe_str(struct trace_iterator *iter, const char *str,
++ bool star, int len)
+ {
+ unsigned long addr = (unsigned long)str;
+ struct trace_event *trace_event;
+ struct trace_event_call *event;
+
++ /* Ignore strings with no length */
++ if (star && !len)
++ return true;
++
+ /* OK if part of the event data */
+ if ((addr >= (unsigned long)iter->ent) &&
+ (addr < (unsigned long)iter->ent + iter->ent_size))
+@@ -3835,6 +3847,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
iter->fmt[i] = '\0';
trace_seq_vprintf(&iter->seq, iter->fmt, ap);
@@ -141481,7 +217069,16 @@ index bc677cd642240..86fb77c2ace5b 100644
if (star)
len = va_arg(ap, int);
-@@ -6077,7 +6094,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start,
+@@ -3850,7 +3874,7 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
+ * instead. See samples/trace_events/trace-events-sample.h
+ * for reference.
+ */
+- if (WARN_ONCE(!trace_safe_str(iter, str),
++ if (WARN_ONCE(!trace_safe_str(iter, str, star, len),
+ "fmt: '%s' current_buffer: '%s'",
+ fmt, show_buffer(&iter->seq))) {
+ int ret;
+@@ -6077,7 +6101,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start,
static void trace_create_eval_file(struct dentry *d_tracer)
{
@@ -141490,7 +217087,7 @@ index bc677cd642240..86fb77c2ace5b 100644
NULL, &tracing_eval_map_fops);
}
-@@ -7736,7 +7753,8 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
+@@ -7736,7 +7760,8 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
err = kzalloc(sizeof(*err), GFP_KERNEL);
if (!err)
err = ERR_PTR(-ENOMEM);
@@ -141500,7 +217097,7 @@ index bc677cd642240..86fb77c2ace5b 100644
return err;
}
-@@ -8590,27 +8608,27 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
+@@ -8590,27 +8615,27 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
}
/* per cpu trace_pipe */
@@ -141535,7 +217132,7 @@ index bc677cd642240..86fb77c2ace5b 100644
tr, cpu, &snapshot_raw_fops);
#endif
}
-@@ -8816,8 +8834,8 @@ create_trace_option_file(struct trace_array *tr,
+@@ -8816,8 +8841,8 @@ create_trace_option_file(struct trace_array *tr,
topt->opt = opt;
topt->tr = tr;
@@ -141546,7 +217143,7 @@ index bc677cd642240..86fb77c2ace5b 100644
}
-@@ -8892,7 +8910,7 @@ create_trace_option_core_file(struct trace_array *tr,
+@@ -8892,7 +8917,7 @@ create_trace_option_core_file(struct trace_array *tr,
if (!t_options)
return NULL;
@@ -141555,7 +217152,7 @@ index bc677cd642240..86fb77c2ace5b 100644
(void *)&tr->trace_flags_index[index],
&trace_options_core_fops);
}
-@@ -9417,28 +9435,28 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
+@@ -9417,28 +9442,28 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
struct trace_event_file *file;
int cpu;
@@ -141592,7 +217189,7 @@ index bc677cd642240..86fb77c2ace5b 100644
tr, &tracing_total_entries_fops);
trace_create_file("free_buffer", 0200, d_tracer,
-@@ -9449,25 +9467,25 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
+@@ -9449,25 +9474,25 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
file = __find_event_file(tr, "ftrace", "print");
if (file && file->dir)
@@ -141624,7 +217221,7 @@ index bc677cd642240..86fb77c2ace5b 100644
tr, &buffer_percent_fops);
create_trace_options_dir(tr);
-@@ -9478,11 +9496,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
+@@ -9478,11 +9503,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
MEM_FAIL(1, "Could not allocate function filter files");
#ifdef CONFIG_TRACER_SNAPSHOT
@@ -141638,7 +217235,7 @@ index bc677cd642240..86fb77c2ace5b 100644
tr, &tracing_err_log_fops);
for_each_tracing_cpu(cpu)
-@@ -9675,19 +9693,19 @@ static __init int tracer_init_tracefs(void)
+@@ -9675,19 +9700,19 @@ static __init int tracer_init_tracefs(void)
init_tracer_tracefs(&global_trace, NULL);
ftrace_init_tracefs_toplevel(&global_trace, NULL);
@@ -141663,7 +217260,7 @@ index bc677cd642240..86fb77c2ace5b 100644
NULL, &tracing_saved_tgids_fops);
trace_eval_init();
-@@ -9699,7 +9717,7 @@ static __init int tracer_init_tracefs(void)
+@@ -9699,7 +9724,7 @@ static __init int tracer_init_tracefs(void)
#endif
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -141776,10 +217373,25 @@ index 6aed10e2f7ce0..fba8cb77a73af 100644
/*
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
-index 830b3b9940f4c..44d031ffe5112 100644
+index 830b3b9940f4c..c072e8b9849c1 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
-@@ -2312,7 +2312,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
+@@ -40,6 +40,14 @@ static LIST_HEAD(ftrace_generic_fields);
+ static LIST_HEAD(ftrace_common_fields);
+ static bool eventdir_initialized;
+
++static LIST_HEAD(module_strings);
++
++struct module_string {
++ struct list_head next;
++ struct module *module;
++ char *str;
++};
++
+ #define GFP_TRACE (GFP_KERNEL | __GFP_ZERO)
+
+ static struct kmem_cache *field_cachep;
+@@ -2312,7 +2320,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
/* the ftrace system is special, do not create enable or filter files */
if (strcmp(name, "ftrace") != 0) {
@@ -141789,7 +217401,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
&ftrace_subsystem_filter_fops);
if (!entry) {
kfree(system->filter);
-@@ -2320,7 +2321,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
+@@ -2320,7 +2329,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
pr_warn("Could not create tracefs '%s/filter' entry\n", name);
}
@@ -141798,7 +217410,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
&ftrace_system_enable_fops);
}
-@@ -2402,12 +2403,12 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
+@@ -2402,12 +2411,12 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
}
if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
@@ -141813,7 +217425,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
(void *)(long)call->event.type,
&ftrace_event_id_fops);
#endif
-@@ -2423,22 +2424,22 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
+@@ -2423,22 +2432,22 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
* triggers or filters.
*/
if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) {
@@ -141843,7 +217455,92 @@ index 830b3b9940f4c..44d031ffe5112 100644
&ftrace_event_format_fops);
#ifdef CONFIG_TRACE_EVENT_INJECT
-@@ -2677,12 +2678,22 @@ static struct trace_event_file *
+@@ -2632,6 +2641,76 @@ static void update_event_printk(struct trace_event_call *call,
+ }
+ }
+
++static void add_str_to_module(struct module *module, char *str)
++{
++ struct module_string *modstr;
++
++ modstr = kmalloc(sizeof(*modstr), GFP_KERNEL);
++
++ /*
++ * If we failed to allocate memory here, then we'll just
++ * let the str memory leak when the module is removed.
++ * If this fails to allocate, there's worse problems than
++ * a leaked string on module removal.
++ */
++ if (WARN_ON_ONCE(!modstr))
++ return;
++
++ modstr->module = module;
++ modstr->str = str;
++
++ list_add(&modstr->next, &module_strings);
++}
++
++static void update_event_fields(struct trace_event_call *call,
++ struct trace_eval_map *map)
++{
++ struct ftrace_event_field *field;
++ struct list_head *head;
++ char *ptr;
++ char *str;
++ int len = strlen(map->eval_string);
++
++ /* Dynamic events should never have field maps */
++ if (WARN_ON_ONCE(call->flags & TRACE_EVENT_FL_DYNAMIC))
++ return;
++
++ head = trace_get_fields(call);
++ list_for_each_entry(field, head, link) {
++ ptr = strchr(field->type, '[');
++ if (!ptr)
++ continue;
++ ptr++;
++
++ if (!isalpha(*ptr) && *ptr != '_')
++ continue;
++
++ if (strncmp(map->eval_string, ptr, len) != 0)
++ continue;
++
++ str = kstrdup(field->type, GFP_KERNEL);
++ if (WARN_ON_ONCE(!str))
++ return;
++ ptr = str + (ptr - field->type);
++ ptr = eval_replace(ptr, map, len);
++ /* enum/sizeof string smaller than value */
++ if (WARN_ON_ONCE(!ptr)) {
++ kfree(str);
++ continue;
++ }
++
++ /*
++ * If the event is part of a module, then we need to free the string
++ * when the module is removed. Otherwise, it will stay allocated
++ * until a reboot.
++ */
++ if (call->module)
++ add_str_to_module(call->module, str);
++
++ field->type = str;
++ }
++}
++
+ void trace_event_eval_update(struct trace_eval_map **map, int len)
+ {
+ struct trace_event_call *call, *p;
+@@ -2667,6 +2746,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)
+ first = false;
+ }
+ update_event_printk(call, map[i]);
++ update_event_fields(call, map[i]);
+ }
+ }
+ }
+@@ -2677,12 +2757,22 @@ static struct trace_event_file *
trace_create_new_event(struct trace_event_call *call,
struct trace_array *tr)
{
@@ -141866,7 +217563,30 @@ index 830b3b9940f4c..44d031ffe5112 100644
file->event_call = call;
file->tr = tr;
atomic_set(&file->sm_ref, 0);
-@@ -3433,7 +3444,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
+@@ -2840,6 +2930,7 @@ static void trace_module_add_events(struct module *mod)
+ static void trace_module_remove_events(struct module *mod)
+ {
+ struct trace_event_call *call, *p;
++ struct module_string *modstr, *m;
+
+ down_write(&trace_event_sem);
+ list_for_each_entry_safe(call, p, &ftrace_events, list) {
+@@ -2848,6 +2939,14 @@ static void trace_module_remove_events(struct module *mod)
+ if (call->module == mod)
+ __trace_remove_event_call(call);
+ }
++ /* Check for any strings allocade for this module */
++ list_for_each_entry_safe(modstr, m, &module_strings, next) {
++ if (modstr->module != mod)
++ continue;
++ list_del(&modstr->next);
++ kfree(modstr->str);
++ kfree(modstr);
++ }
+ up_write(&trace_event_sem);
+
+ /*
+@@ -3433,7 +3532,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
struct dentry *d_events;
struct dentry *entry;
@@ -141875,7 +217595,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
tr, &ftrace_set_event_fops);
if (!entry) {
pr_warn("Could not create tracefs 'set_event' entry\n");
-@@ -3446,7 +3457,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
+@@ -3446,7 +3545,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
return -ENOMEM;
}
@@ -141884,7 +217604,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
tr, &ftrace_tr_enable_fops);
if (!entry) {
pr_warn("Could not create tracefs 'enable' entry\n");
-@@ -3455,24 +3466,25 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
+@@ -3455,24 +3554,25 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
/* There are not as crucial, just warn if they are not created */
@@ -141915,7 +217635,7 @@ index 830b3b9940f4c..44d031ffe5112 100644
ring_buffer_print_entry_header,
&ftrace_show_header_fops);
if (!entry)
-@@ -3689,8 +3701,8 @@ __init int event_trace_init(void)
+@@ -3689,8 +3789,8 @@ __init int event_trace_init(void)
if (!tr)
return -ENODEV;
@@ -142448,10 +218168,107 @@ index 3a64ba4bbad6f..39ee60725519b 100644
if (!entry)
pr_warn("Could not create tracefs 'kprobe_profile' entry\n");
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
-index ce053619f289e..65a518649997b 100644
+index ce053619f289e..93de784ee681c 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
-@@ -1856,38 +1856,38 @@ static int init_tracefs(void)
+@@ -1195,6 +1195,26 @@ static int run_osnoise(void)
+ osnoise_stop_tracing();
+ }
+
++ /*
++ * In some cases, notably when running on a nohz_full CPU with
++ * a stopped tick PREEMPT_RCU has no way to account for QSs.
++ * This will eventually cause unwarranted noise as PREEMPT_RCU
++ * will force preemption as the means of ending the current
++ * grace period. We avoid this problem by calling
++ * rcu_momentary_dyntick_idle(), which performs a zero duration
++ * EQS allowing PREEMPT_RCU to end the current grace period.
++ * This call shouldn't be wrapped inside an RCU critical
++ * section.
++ *
++ * Note that in non PREEMPT_RCU kernels QSs are handled through
++ * cond_resched()
++ */
++ if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
++ local_irq_disable();
++ rcu_momentary_dyntick_idle();
++ local_irq_enable();
++ }
++
+ /*
+ * For the non-preemptive kernel config: let threads runs, if
+ * they so wish.
+@@ -1249,6 +1269,37 @@ out:
+ static struct cpumask osnoise_cpumask;
+ static struct cpumask save_cpumask;
+
++/*
++ * osnoise_sleep - sleep until the next period
++ */
++static void osnoise_sleep(void)
++{
++ u64 interval;
++ ktime_t wake_time;
++
++ mutex_lock(&interface_lock);
++ interval = osnoise_data.sample_period - osnoise_data.sample_runtime;
++ mutex_unlock(&interface_lock);
++
++ /*
++ * differently from hwlat_detector, the osnoise tracer can run
++ * without a pause because preemption is on.
++ */
++ if (!interval) {
++ /* Let synchronize_rcu_tasks() make progress */
++ cond_resched_tasks_rcu_qs();
++ return;
++ }
++
++ wake_time = ktime_add_us(ktime_get(), interval);
++ __set_current_state(TASK_INTERRUPTIBLE);
++
++ while (schedule_hrtimeout_range(&wake_time, 0, HRTIMER_MODE_ABS)) {
++ if (kthread_should_stop())
++ break;
++ }
++}
++
+ /*
+ * osnoise_main - The osnoise detection kernel thread
+ *
+@@ -1257,30 +1308,10 @@ static struct cpumask save_cpumask;
+ */
+ static int osnoise_main(void *data)
+ {
+- u64 interval;
+
+ while (!kthread_should_stop()) {
+-
+ run_osnoise();
+-
+- mutex_lock(&interface_lock);
+- interval = osnoise_data.sample_period - osnoise_data.sample_runtime;
+- mutex_unlock(&interface_lock);
+-
+- do_div(interval, USEC_PER_MSEC);
+-
+- /*
+- * differently from hwlat_detector, the osnoise tracer can run
+- * without a pause because preemption is on.
+- */
+- if (interval < 1) {
+- /* Let synchronize_rcu_tasks() make progress */
+- cond_resched_tasks_rcu_qs();
+- continue;
+- }
+-
+- if (msleep_interruptible(interval))
+- break;
++ osnoise_sleep();
+ }
+
+ return 0;
+@@ -1856,38 +1887,38 @@ static int init_tracefs(void)
if (!top_dir)
return 0;
@@ -142497,7 +218314,7 @@ index ce053619f289e..65a518649997b 100644
&timerlat_period, &trace_min_max_fops);
if (!tmp)
goto err;
-@@ -1932,6 +1932,13 @@ out_unhook_irq:
+@@ -1932,6 +1963,13 @@ out_unhook_irq:
return -EINVAL;
}
@@ -142511,7 +218328,7 @@ index ce053619f289e..65a518649997b 100644
static int __osnoise_tracer_start(struct trace_array *tr)
{
int retval;
-@@ -1949,7 +1956,14 @@ static int __osnoise_tracer_start(struct trace_array *tr)
+@@ -1949,7 +1987,14 @@ static int __osnoise_tracer_start(struct trace_array *tr)
retval = start_per_cpu_kthreads(tr);
if (retval) {
@@ -142527,7 +218344,7 @@ index ce053619f289e..65a518649997b 100644
return retval;
}
-@@ -1981,9 +1995,7 @@ static void osnoise_tracer_stop(struct trace_array *tr)
+@@ -1981,9 +2026,7 @@ static void osnoise_tracer_stop(struct trace_array *tr)
stop_per_cpu_kthreads();
@@ -142929,6 +218746,95 @@ index 6b2e3ca7ee993..5481ba44a8d68 100644
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE));
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING));
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK));
+diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
+index 9c9eb20dd2c50..b1ae7c9c3b473 100644
+--- a/kernel/watch_queue.c
++++ b/kernel/watch_queue.c
+@@ -54,6 +54,7 @@ static void watch_queue_pipe_buf_release(struct pipe_inode_info *pipe,
+ bit += page->index;
+
+ set_bit(bit, wqueue->notes_bitmap);
++ generic_pipe_buf_release(pipe, buf);
+ }
+
+ // No try_steal function => no stealing
+@@ -112,7 +113,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
+ buf->offset = offset;
+ buf->len = len;
+ buf->flags = PIPE_BUF_FLAG_WHOLE;
+- pipe->head = head + 1;
++ smp_store_release(&pipe->head, head + 1); /* vs pipe_read() */
+
+ if (!test_and_clear_bit(note, wqueue->notes_bitmap)) {
+ spin_unlock_irq(&pipe->rd_wait.lock);
+@@ -243,7 +244,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
+ goto error;
+ }
+
+- ret = pipe_resize_ring(pipe, nr_notes);
++ nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE;
++ ret = pipe_resize_ring(pipe, roundup_pow_of_two(nr_notes));
+ if (ret < 0)
+ goto error;
+
+@@ -268,11 +270,11 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
+ wqueue->notes = pages;
+ wqueue->notes_bitmap = bitmap;
+ wqueue->nr_pages = nr_pages;
+- wqueue->nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE;
++ wqueue->nr_notes = nr_notes;
+ return 0;
+
+ error_p:
+- for (i = 0; i < nr_pages; i++)
++ while (--i >= 0)
+ __free_page(pages[i]);
+ kfree(pages);
+ error:
+@@ -320,7 +322,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
+ tf[i].info_mask & WATCH_INFO_LENGTH)
+ goto err_filter;
+ /* Ignore any unknown types */
+- if (tf[i].type >= sizeof(wfilter->type_filter) * 8)
++ if (tf[i].type >= WATCH_TYPE__NR)
+ continue;
+ nr_filter++;
+ }
+@@ -336,7 +338,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
+
+ q = wfilter->filters;
+ for (i = 0; i < filter.nr_filters; i++) {
+- if (tf[i].type >= sizeof(wfilter->type_filter) * BITS_PER_LONG)
++ if (tf[i].type >= WATCH_TYPE__NR)
+ continue;
+
+ q->type = tf[i].type;
+@@ -371,6 +373,8 @@ static void __put_watch_queue(struct kref *kref)
+
+ for (i = 0; i < wqueue->nr_pages; i++)
+ __free_page(wqueue->notes[i]);
++ kfree(wqueue->notes);
++ bitmap_free(wqueue->notes_bitmap);
+
+ wfilter = rcu_access_pointer(wqueue->filter);
+ if (wfilter)
+@@ -395,6 +399,7 @@ static void free_watch(struct rcu_head *rcu)
+ put_watch_queue(rcu_access_pointer(watch->queue));
+ atomic_dec(&watch->cred->user->nr_watches);
+ put_cred(watch->cred);
++ kfree(watch);
+ }
+
+ static void __put_watch(struct kref *kref)
+@@ -566,7 +571,7 @@ void watch_queue_clear(struct watch_queue *wqueue)
+ rcu_read_lock();
+ spin_lock_bh(&wqueue->lock);
+
+- /* Prevent new additions and prevent notifications from happening */
++ /* Prevent new notifications from being stored. */
+ wqueue->defunct = true;
+
+ while (!hlist_empty(&wqueue->watches)) {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 1b3eb1e9531f4..3f4d276685768 100644
--- a/kernel/workqueue.c
@@ -142990,6 +218896,42 @@ index 1b3eb1e9531f4..3f4d276685768 100644
return ret;
}
+diff --git a/lib/Kconfig b/lib/Kconfig
+index 5e7165e6a346c..fa4b10322efcd 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -45,7 +45,6 @@ config BITREVERSE
+ config HAVE_ARCH_BITREVERSE
+ bool
+ default n
+- depends on BITREVERSE
+ help
+ This option enables the use of hardware bit-reversal instructions on
+ architectures which support such operations.
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 2a9b6dcdac4ff..7fd3fa05379e2 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -414,7 +414,8 @@ config SECTION_MISMATCH_WARN_ONLY
+ If unsure, say Y.
+
+ config DEBUG_FORCE_FUNCTION_ALIGN_64B
+- bool "Force all function address 64B aligned" if EXPERT
++ bool "Force all function address 64B aligned"
++ depends on EXPERT && (X86_64 || ARM64 || PPC32 || PPC64 || ARC)
+ help
+ There are cases that a commit from one domain changes the function
+ address alignment of other domains, and cause magic performance
+@@ -1558,8 +1559,7 @@ config WARN_ALL_UNSEEDED_RANDOM
+ so architecture maintainers really need to do what they can
+ to get the CRNG seeded sooner after the system is booted.
+ However, since users cannot do anything actionable to
+- address this, by default the kernel will issue only a single
+- warning for the first use of unseeded randomness.
++ address this, by default this option is disabled.
+
+ Say Y here if you want to receive warnings for all uses of
+ unseeded randomness. This will be of use primarily for
diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence
index e641add339475..912f252a41fc6 100644
--- a/lib/Kconfig.kfence
@@ -143034,6 +218976,280 @@ index e641add339475..912f252a41fc6 100644
config KFENCE_STRESS_TEST_FAULTS
int "Stress testing of fault handling and error reporting" if EXPERT
default 0
+diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan
+index e5372a13511df..236c5cefc4cc5 100644
+--- a/lib/Kconfig.ubsan
++++ b/lib/Kconfig.ubsan
+@@ -112,19 +112,6 @@ config UBSAN_UNREACHABLE
+ This option enables -fsanitize=unreachable which checks for control
+ flow reaching an expected-to-be-unreachable position.
+
+-config UBSAN_OBJECT_SIZE
+- bool "Perform checking for accesses beyond the end of objects"
+- default UBSAN
+- # gcc hugely expands stack usage with -fsanitize=object-size
+- # https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/
+- depends on !CC_IS_GCC
+- depends on $(cc-option,-fsanitize=object-size)
+- help
+- This option enables -fsanitize=object-size which checks for accesses
+- beyond the end of objects where the optimizer can determine both the
+- object being operated on and its size, usually seen with bad downcasts,
+- or access to struct members from NULL pointers.
+-
+ config UBSAN_BOOL
+ bool "Perform checking for non-boolean values used as boolean"
+ default UBSAN
+diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
+index 545ccbddf6a1d..8620f38e117c0 100644
+--- a/lib/crypto/Kconfig
++++ b/lib/crypto/Kconfig
+@@ -1,7 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+
+-comment "Crypto library routines"
+-
+ config CRYPTO_LIB_AES
+ tristate
+
+@@ -9,14 +7,14 @@ config CRYPTO_LIB_ARC4
+ tristate
+
+ config CRYPTO_ARCH_HAVE_LIB_BLAKE2S
+- tristate
++ bool
+ help
+ Declares whether the architecture provides an arch-specific
+ accelerated implementation of the Blake2s library interface,
+ either builtin or as a module.
+
+ config CRYPTO_LIB_BLAKE2S_GENERIC
+- tristate
++ def_bool !CRYPTO_ARCH_HAVE_LIB_BLAKE2S
+ help
+ This symbol can be depended upon by arch implementations of the
+ Blake2s library interface that require the generic code as a
+@@ -24,15 +22,6 @@ config CRYPTO_LIB_BLAKE2S_GENERIC
+ implementation is enabled, this implementation serves the users
+ of CRYPTO_LIB_BLAKE2S.
+
+-config CRYPTO_LIB_BLAKE2S
+- tristate "BLAKE2s hash function library"
+- depends on CRYPTO_ARCH_HAVE_LIB_BLAKE2S || !CRYPTO_ARCH_HAVE_LIB_BLAKE2S
+- select CRYPTO_LIB_BLAKE2S_GENERIC if CRYPTO_ARCH_HAVE_LIB_BLAKE2S=n
+- help
+- Enable the Blake2s library interface. This interface may be fulfilled
+- by either the generic implementation or an arch-specific one, if one
+- is available and enabled.
+-
+ config CRYPTO_ARCH_HAVE_LIB_CHACHA
+ tristate
+ help
+@@ -51,7 +40,7 @@ config CRYPTO_LIB_CHACHA_GENERIC
+ of CRYPTO_LIB_CHACHA.
+
+ config CRYPTO_LIB_CHACHA
+- tristate "ChaCha library interface"
++ tristate
+ depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA
+ select CRYPTO_LIB_CHACHA_GENERIC if CRYPTO_ARCH_HAVE_LIB_CHACHA=n
+ help
+@@ -76,7 +65,7 @@ config CRYPTO_LIB_CURVE25519_GENERIC
+ of CRYPTO_LIB_CURVE25519.
+
+ config CRYPTO_LIB_CURVE25519
+- tristate "Curve25519 scalar multiplication library"
++ tristate
+ depends on CRYPTO_ARCH_HAVE_LIB_CURVE25519 || !CRYPTO_ARCH_HAVE_LIB_CURVE25519
+ select CRYPTO_LIB_CURVE25519_GENERIC if CRYPTO_ARCH_HAVE_LIB_CURVE25519=n
+ help
+@@ -111,7 +100,7 @@ config CRYPTO_LIB_POLY1305_GENERIC
+ of CRYPTO_LIB_POLY1305.
+
+ config CRYPTO_LIB_POLY1305
+- tristate "Poly1305 library interface"
++ tristate
+ depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
+ select CRYPTO_LIB_POLY1305_GENERIC if CRYPTO_ARCH_HAVE_LIB_POLY1305=n
+ help
+@@ -120,7 +109,7 @@ config CRYPTO_LIB_POLY1305
+ is available and enabled.
+
+ config CRYPTO_LIB_CHACHA20POLY1305
+- tristate "ChaCha20-Poly1305 AEAD support (8-byte nonce library version)"
++ tristate
+ depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA
+ depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
+ select CRYPTO_LIB_CHACHA
+diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
+index 73205ed269bad..ed43a41f2dcc8 100644
+--- a/lib/crypto/Makefile
++++ b/lib/crypto/Makefile
+@@ -10,11 +10,10 @@ libaes-y := aes.o
+ obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o
+ libarc4-y := arc4.o
+
+-obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) += libblake2s-generic.o
+-libblake2s-generic-y += blake2s-generic.o
+-
+-obj-$(CONFIG_CRYPTO_LIB_BLAKE2S) += libblake2s.o
+-libblake2s-y += blake2s.o
++# blake2s is used by the /dev/random driver which is always builtin
++obj-y += libblake2s.o
++libblake2s-y := blake2s.o
++libblake2s-$(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) += blake2s-generic.o
+
+ obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305) += libchacha20poly1305.o
+ libchacha20poly1305-y += chacha20poly1305.o
+diff --git a/lib/crypto/blake2s-generic.c b/lib/crypto/blake2s-generic.c
+index 04ff8df245136..75ccb3e633e65 100644
+--- a/lib/crypto/blake2s-generic.c
++++ b/lib/crypto/blake2s-generic.c
+@@ -37,7 +37,11 @@ static inline void blake2s_increment_counter(struct blake2s_state *state,
+ state->t[1] += (state->t[0] < inc);
+ }
+
+-void blake2s_compress_generic(struct blake2s_state *state,const u8 *block,
++void blake2s_compress(struct blake2s_state *state, const u8 *block,
++ size_t nblocks, const u32 inc)
++ __weak __alias(blake2s_compress_generic);
++
++void blake2s_compress_generic(struct blake2s_state *state, const u8 *block,
+ size_t nblocks, const u32 inc)
+ {
+ u32 m[16];
+diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c
+index 5d9ea53be9736..409e4b7287704 100644
+--- a/lib/crypto/blake2s-selftest.c
++++ b/lib/crypto/blake2s-selftest.c
+@@ -15,7 +15,6 @@
+ * #include <stdio.h>
+ *
+ * #include <openssl/evp.h>
+- * #include <openssl/hmac.h>
+ *
+ * #define BLAKE2S_TESTVEC_COUNT 256
+ *
+@@ -58,16 +57,6 @@
+ * }
+ * printf("};\n\n");
+ *
+- * printf("static const u8 blake2s_hmac_testvecs[][BLAKE2S_HASH_SIZE] __initconst = {\n");
+- *
+- * HMAC(EVP_blake2s256(), key, sizeof(key), buf, sizeof(buf), hash, NULL);
+- * print_vec(hash, BLAKE2S_OUTBYTES);
+- *
+- * HMAC(EVP_blake2s256(), buf, sizeof(buf), key, sizeof(key), hash, NULL);
+- * print_vec(hash, BLAKE2S_OUTBYTES);
+- *
+- * printf("};\n");
+- *
+ * return 0;
+ *}
+ */
+@@ -554,15 +543,6 @@ static const u8 blake2s_testvecs[][BLAKE2S_HASH_SIZE] __initconst = {
+ 0xd6, 0x98, 0x6b, 0x07, 0x10, 0x65, 0x52, 0x65, },
+ };
+
+-static const u8 blake2s_hmac_testvecs[][BLAKE2S_HASH_SIZE] __initconst = {
+- { 0xce, 0xe1, 0x57, 0x69, 0x82, 0xdc, 0xbf, 0x43, 0xad, 0x56, 0x4c, 0x70,
+- 0xed, 0x68, 0x16, 0x96, 0xcf, 0xa4, 0x73, 0xe8, 0xe8, 0xfc, 0x32, 0x79,
+- 0x08, 0x0a, 0x75, 0x82, 0xda, 0x3f, 0x05, 0x11, },
+- { 0x77, 0x2f, 0x0c, 0x71, 0x41, 0xf4, 0x4b, 0x2b, 0xb3, 0xc6, 0xb6, 0xf9,
+- 0x60, 0xde, 0xe4, 0x52, 0x38, 0x66, 0xe8, 0xbf, 0x9b, 0x96, 0xc4, 0x9f,
+- 0x60, 0xd9, 0x24, 0x37, 0x99, 0xd6, 0xec, 0x31, },
+-};
+-
+ bool __init blake2s_selftest(void)
+ {
+ u8 key[BLAKE2S_KEY_SIZE];
+@@ -607,16 +587,5 @@ bool __init blake2s_selftest(void)
+ }
+ }
+
+- if (success) {
+- blake2s256_hmac(hash, buf, key, sizeof(buf), sizeof(key));
+- success &= !memcmp(hash, blake2s_hmac_testvecs[0], BLAKE2S_HASH_SIZE);
+-
+- blake2s256_hmac(hash, key, buf, sizeof(key), sizeof(buf));
+- success &= !memcmp(hash, blake2s_hmac_testvecs[1], BLAKE2S_HASH_SIZE);
+-
+- if (!success)
+- pr_err("blake2s256_hmac self-test: FAIL\n");
+- }
+-
+ return success;
+ }
+diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c
+index 4055aa593ec49..c71c09621c09c 100644
+--- a/lib/crypto/blake2s.c
++++ b/lib/crypto/blake2s.c
+@@ -16,63 +16,20 @@
+ #include <linux/init.h>
+ #include <linux/bug.h>
+
+-#if IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S)
+-# define blake2s_compress blake2s_compress_arch
+-#else
+-# define blake2s_compress blake2s_compress_generic
+-#endif
+-
+ void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen)
+ {
+- __blake2s_update(state, in, inlen, blake2s_compress);
++ __blake2s_update(state, in, inlen, false);
+ }
+ EXPORT_SYMBOL(blake2s_update);
+
+ void blake2s_final(struct blake2s_state *state, u8 *out)
+ {
+ WARN_ON(IS_ENABLED(DEBUG) && !out);
+- __blake2s_final(state, out, blake2s_compress);
++ __blake2s_final(state, out, false);
+ memzero_explicit(state, sizeof(*state));
+ }
+ EXPORT_SYMBOL(blake2s_final);
+
+-void blake2s256_hmac(u8 *out, const u8 *in, const u8 *key, const size_t inlen,
+- const size_t keylen)
+-{
+- struct blake2s_state state;
+- u8 x_key[BLAKE2S_BLOCK_SIZE] __aligned(__alignof__(u32)) = { 0 };
+- u8 i_hash[BLAKE2S_HASH_SIZE] __aligned(__alignof__(u32));
+- int i;
+-
+- if (keylen > BLAKE2S_BLOCK_SIZE) {
+- blake2s_init(&state, BLAKE2S_HASH_SIZE);
+- blake2s_update(&state, key, keylen);
+- blake2s_final(&state, x_key);
+- } else
+- memcpy(x_key, key, keylen);
+-
+- for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
+- x_key[i] ^= 0x36;
+-
+- blake2s_init(&state, BLAKE2S_HASH_SIZE);
+- blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
+- blake2s_update(&state, in, inlen);
+- blake2s_final(&state, i_hash);
+-
+- for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
+- x_key[i] ^= 0x5c ^ 0x36;
+-
+- blake2s_init(&state, BLAKE2S_HASH_SIZE);
+- blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
+- blake2s_update(&state, i_hash, BLAKE2S_HASH_SIZE);
+- blake2s_final(&state, i_hash);
+-
+- memcpy(out, i_hash, BLAKE2S_HASH_SIZE);
+- memzero_explicit(x_key, BLAKE2S_BLOCK_SIZE);
+- memzero_explicit(i_hash, BLAKE2S_HASH_SIZE);
+-}
+-EXPORT_SYMBOL(blake2s256_hmac);
+-
+ static int __init blake2s_mod_init(void)
+ {
+ if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) &&
diff --git a/lib/crypto/sm4.c b/lib/crypto/sm4.c
index 633b59fed9db8..284e62576d0c6 100644
--- a/lib/crypto/sm4.c
@@ -143069,6 +219285,74 @@ index a2f38e23004aa..f7a3dc13316a3 100644
* (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the
* functions below should just be kept small; it's probably not worth
* optimizing for speed.
+diff --git a/lib/dim/net_dim.c b/lib/dim/net_dim.c
+index 06811d866775c..53f6b9c6e9366 100644
+--- a/lib/dim/net_dim.c
++++ b/lib/dim/net_dim.c
+@@ -12,41 +12,41 @@
+ * Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
+ */
+ #define NET_DIM_PARAMS_NUM_PROFILES 5
+-#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
+-#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
++#define NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE 256
++#define NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE 128
+ #define NET_DIM_DEF_PROFILE_CQE 1
+ #define NET_DIM_DEF_PROFILE_EQE 1
+
+ #define NET_DIM_RX_EQE_PROFILES { \
+- {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
++ {.usec = 1, .pkts = NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 8, .pkts = NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 64, .pkts = NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 128, .pkts = NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 256, .pkts = NET_DIM_DEFAULT_RX_CQ_PKTS_FROM_EQE,} \
+ }
+
+ #define NET_DIM_RX_CQE_PROFILES { \
+- {2, 256}, \
+- {8, 128}, \
+- {16, 64}, \
+- {32, 64}, \
+- {64, 64} \
++ {.usec = 2, .pkts = 256,}, \
++ {.usec = 8, .pkts = 128,}, \
++ {.usec = 16, .pkts = 64,}, \
++ {.usec = 32, .pkts = 64,}, \
++ {.usec = 64, .pkts = 64,} \
+ }
+
+ #define NET_DIM_TX_EQE_PROFILES { \
+- {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \
+- {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \
++ {.usec = 1, .pkts = NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 8, .pkts = NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 32, .pkts = NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 64, .pkts = NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE,}, \
++ {.usec = 128, .pkts = NET_DIM_DEFAULT_TX_CQ_PKTS_FROM_EQE,} \
+ }
+
+ #define NET_DIM_TX_CQE_PROFILES { \
+- {5, 128}, \
+- {8, 64}, \
+- {16, 32}, \
+- {32, 32}, \
+- {64, 32} \
++ {.usec = 5, .pkts = 128,}, \
++ {.usec = 8, .pkts = 64,}, \
++ {.usec = 16, .pkts = 32,}, \
++ {.usec = 32, .pkts = 32,}, \
++ {.usec = 64, .pkts = 32,} \
+ }
+
+ static const struct dim_cq_moder
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index cb5abb42c16a2..84c16309cc637 100644
--- a/lib/dynamic_debug.c
@@ -143092,10 +219376,90 @@ index cb5abb42c16a2..84c16309cc637 100644
/*
* File_ops->write method for <debugfs>/dynamic_debug/control. Gathers the
* command text from userspace, parses and executes it.
+diff --git a/lib/hexdump.c b/lib/hexdump.c
+index 9301578f98e8c..06833d404398d 100644
+--- a/lib/hexdump.c
++++ b/lib/hexdump.c
+@@ -22,15 +22,33 @@ EXPORT_SYMBOL(hex_asc_upper);
+ *
+ * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
+ * input.
++ *
++ * This function is used to load cryptographic keys, so it is coded in such a
++ * way that there are no conditions or memory accesses that depend on data.
++ *
++ * Explanation of the logic:
++ * (ch - '9' - 1) is negative if ch <= '9'
++ * ('0' - 1 - ch) is negative if ch >= '0'
++ * we "and" these two values, so the result is negative if ch is in the range
++ * '0' ... '9'
++ * we are only interested in the sign, so we do a shift ">> 8"; note that right
++ * shift of a negative value is implementation-defined, so we cast the
++ * value to (unsigned) before the shift --- we have 0xffffff if ch is in
++ * the range '0' ... '9', 0 otherwise
++ * we "and" this value with (ch - '0' + 1) --- we have a value 1 ... 10 if ch is
++ * in the range '0' ... '9', 0 otherwise
++ * we add this value to -1 --- we have a value 0 ... 9 if ch is in the range '0'
++ * ... '9', -1 otherwise
++ * the next line is similar to the previous one, but we need to decode both
++ * uppercase and lowercase letters, so we use (ch & 0xdf), which converts
++ * lowercase to uppercase
+ */
+-int hex_to_bin(char ch)
++int hex_to_bin(unsigned char ch)
+ {
+- if ((ch >= '0') && (ch <= '9'))
+- return ch - '0';
+- ch = tolower(ch);
+- if ((ch >= 'a') && (ch <= 'f'))
+- return ch - 'a' + 10;
+- return -1;
++ unsigned char cu = ch & 0xdf;
++ return -1 +
++ ((ch - '0' + 1) & (unsigned)((ch - '9' - 1) & ('0' - 1 - ch)) >> 8) +
++ ((cu - 'A' + 11) & (unsigned)((cu - 'F' - 1) & ('A' - 1 - cu)) >> 8);
+ }
+ EXPORT_SYMBOL(hex_to_bin);
+
+@@ -45,10 +63,13 @@ EXPORT_SYMBOL(hex_to_bin);
+ int hex2bin(u8 *dst, const char *src, size_t count)
+ {
+ while (count--) {
+- int hi = hex_to_bin(*src++);
+- int lo = hex_to_bin(*src++);
++ int hi, lo;
+
+- if ((hi < 0) || (lo < 0))
++ hi = hex_to_bin(*src++);
++ if (unlikely(hi < 0))
++ return -EINVAL;
++ lo = hex_to_bin(*src++);
++ if (unlikely(lo < 0))
+ return -EINVAL;
+
+ *dst++ = (hi << 4) | lo;
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
-index 755c10c5138cd..c5b2f0f4b8a84 100644
+index 755c10c5138cd..6d146f77601d7 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
+@@ -191,7 +191,7 @@ static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t b
+ buf = iov->iov_base + skip;
+ copy = min(bytes, iov->iov_len - skip);
+
+- if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_pages_writeable(buf, copy)) {
++ if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_writeable(buf, copy)) {
+ kaddr = kmap_atomic(page);
+ from = kaddr + offset;
+
+@@ -275,7 +275,7 @@ static size_t copy_page_from_iter_iovec(struct page *page, size_t offset, size_t
+ buf = iov->iov_base + skip;
+ copy = min(bytes, iov->iov_len - skip);
+
+- if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_pages_readable(buf, copy)) {
++ if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_readable(buf, copy)) {
+ kaddr = kmap_atomic(page);
+ to = kaddr + offset;
+
@@ -416,6 +416,7 @@ static size_t copy_page_to_iter_pipe(struct page *page, size_t offset, size_t by
return 0;
@@ -143104,7 +219468,111 @@ index 755c10c5138cd..c5b2f0f4b8a84 100644
get_page(page);
buf->page = page;
buf->offset = offset;
-@@ -532,6 +533,7 @@ static size_t push_pipe(struct iov_iter *i, size_t size,
+@@ -430,35 +431,81 @@ out:
+ }
+
+ /*
++ * fault_in_iov_iter_readable - fault in iov iterator for reading
++ * @i: iterator
++ * @size: maximum length
++ *
+ * Fault in one or more iovecs of the given iov_iter, to a maximum length of
+- * bytes. For each iovec, fault in each page that constitutes the iovec.
++ * @size. For each iovec, fault in each page that constitutes the iovec.
++ *
++ * Returns the number of bytes not faulted in (like copy_to_user() and
++ * copy_from_user()).
+ *
+- * Return 0 on success, or non-zero if the memory could not be accessed (i.e.
+- * because it is an invalid address).
++ * Always returns 0 for non-userspace iterators.
+ */
+-int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes)
++size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t size)
+ {
+ if (iter_is_iovec(i)) {
++ size_t count = min(size, iov_iter_count(i));
+ const struct iovec *p;
+ size_t skip;
+
+- if (bytes > i->count)
+- bytes = i->count;
+- for (p = i->iov, skip = i->iov_offset; bytes; p++, skip = 0) {
+- size_t len = min(bytes, p->iov_len - skip);
+- int err;
++ size -= count;
++ for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) {
++ size_t len = min(count, p->iov_len - skip);
++ size_t ret;
+
+ if (unlikely(!len))
+ continue;
+- err = fault_in_pages_readable(p->iov_base + skip, len);
+- if (unlikely(err))
+- return err;
+- bytes -= len;
++ ret = fault_in_readable(p->iov_base + skip, len);
++ count -= len - ret;
++ if (ret)
++ break;
+ }
++ return count + size;
+ }
+ return 0;
+ }
+-EXPORT_SYMBOL(iov_iter_fault_in_readable);
++EXPORT_SYMBOL(fault_in_iov_iter_readable);
++
++/*
++ * fault_in_iov_iter_writeable - fault in iov iterator for writing
++ * @i: iterator
++ * @size: maximum length
++ *
++ * Faults in the iterator using get_user_pages(), i.e., without triggering
++ * hardware page faults. This is primarily useful when we already know that
++ * some or all of the pages in @i aren't in memory.
++ *
++ * Returns the number of bytes not faulted in, like copy_to_user() and
++ * copy_from_user().
++ *
++ * Always returns 0 for non-user-space iterators.
++ */
++size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t size)
++{
++ if (iter_is_iovec(i)) {
++ size_t count = min(size, iov_iter_count(i));
++ const struct iovec *p;
++ size_t skip;
++
++ size -= count;
++ for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) {
++ size_t len = min(count, p->iov_len - skip);
++ size_t ret;
++
++ if (unlikely(!len))
++ continue;
++ ret = fault_in_safe_writeable(p->iov_base + skip, len);
++ count -= len - ret;
++ if (ret)
++ break;
++ }
++ return count + size;
++ }
++ return 0;
++}
++EXPORT_SYMBOL(fault_in_iov_iter_writeable);
+
+ void iov_iter_init(struct iov_iter *i, unsigned int direction,
+ const struct iovec *iov, unsigned long nr_segs,
+@@ -467,6 +514,7 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
+ WARN_ON(direction & ~(READ | WRITE));
+ *i = (struct iov_iter) {
+ .iter_type = ITER_IOVEC,
++ .nofault = false,
+ .data_source = direction,
+ .iov = iov,
+ .nr_segs = nr_segs,
+@@ -532,6 +580,7 @@ static size_t push_pipe(struct iov_iter *i, size_t size,
break;
buf->ops = &default_pipe_buf_ops;
@@ -143112,20 +219580,50 @@ index 755c10c5138cd..c5b2f0f4b8a84 100644
buf->page = page;
buf->offset = 0;
buf->len = min_t(ssize_t, left, PAGE_SIZE);
-@@ -1488,7 +1490,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
- res = get_user_pages_fast(addr, n,
- iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0,
- pages);
+@@ -1481,14 +1530,18 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
+ return 0;
+
+ if (likely(iter_is_iovec(i))) {
++ unsigned int gup_flags = 0;
+ unsigned long addr;
+
++ if (iov_iter_rw(i) != WRITE)
++ gup_flags |= FOLL_WRITE;
++ if (i->nofault)
++ gup_flags |= FOLL_NOFAULT;
++
+ addr = first_iovec_segment(i, &len, start, maxsize, maxpages);
+ n = DIV_ROUND_UP(len, PAGE_SIZE);
+- res = get_user_pages_fast(addr, n,
+- iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0,
+- pages);
- if (unlikely(res < 0))
++ res = get_user_pages_fast(addr, n, gup_flags, pages);
+ if (unlikely(res <= 0))
return res;
return (res == n ? len : res * PAGE_SIZE) - *start;
}
-@@ -1612,8 +1614,9 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
+@@ -1603,17 +1656,23 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
+ return 0;
+
+ if (likely(iter_is_iovec(i))) {
++ unsigned int gup_flags = 0;
+ unsigned long addr;
+
++ if (iov_iter_rw(i) != WRITE)
++ gup_flags |= FOLL_WRITE;
++ if (i->nofault)
++ gup_flags |= FOLL_NOFAULT;
++
+ addr = first_iovec_segment(i, &len, start, maxsize, ~0U);
+ n = DIV_ROUND_UP(len, PAGE_SIZE);
+ p = get_pages_array(n);
+ if (!p)
return -ENOMEM;
- res = get_user_pages_fast(addr, n,
- iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p);
+- res = get_user_pages_fast(addr, n,
+- iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p);
- if (unlikely(res < 0)) {
++ res = get_user_pages_fast(addr, n, gup_flags, p);
+ if (unlikely(res <= 0)) {
kvfree(p);
+ *pages = NULL;
@@ -143175,8 +219673,21 @@ index f246b847024e3..9aef816e573c1 100644
kunit_print_test_stats(&test, param_stats);
+diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
+index 0dd434e40487c..71e5c58530996 100644
+--- a/lib/kunit/try-catch.c
++++ b/lib/kunit/try-catch.c
+@@ -52,7 +52,7 @@ static unsigned long kunit_test_timeout(void)
+ * If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
+ * the task will be killed and an oops generated.
+ */
+- return 300 * MSEC_PER_SEC; /* 5 min */
++ return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
+ }
+
+ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
diff --git a/lib/logic_iomem.c b/lib/logic_iomem.c
-index 9bdfde0c0f86d..549b22d4bcde1 100644
+index 9bdfde0c0f86d..e7ea9b28d8db5 100644
--- a/lib/logic_iomem.c
+++ b/lib/logic_iomem.c
@@ -21,15 +21,15 @@ struct logic_iomem_area {
@@ -143198,16 +219709,34 @@ index 9bdfde0c0f86d..549b22d4bcde1 100644
#endif
static DEFINE_MUTEX(regions_mtx);
-@@ -79,7 +79,7 @@ static void __iomem *real_ioremap(phys_addr_t offset, size_t size)
+@@ -68,7 +68,7 @@ int logic_iomem_add_region(struct resource *resource,
+ }
+ EXPORT_SYMBOL(logic_iomem_add_region);
+
+-#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
++#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
+ static void __iomem *real_ioremap(phys_addr_t offset, size_t size)
+ {
+ WARN(1, "invalid ioremap(0x%llx, 0x%zx)\n",
+@@ -79,9 +79,9 @@ static void __iomem *real_ioremap(phys_addr_t offset, size_t size)
static void real_iounmap(void __iomem *addr)
{
WARN(1, "invalid iounmap for addr 0x%llx\n",
- (unsigned long long __force)addr);
+ (unsigned long long)(uintptr_t __force)addr);
}
- #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
+-#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
++#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
-@@ -173,7 +173,7 @@ EXPORT_SYMBOL(iounmap);
+ void __iomem *ioremap(phys_addr_t offset, size_t size)
+ {
+@@ -168,12 +168,12 @@ void iounmap(void __iomem *addr)
+ }
+ EXPORT_SYMBOL(iounmap);
+
+-#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
++#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
+ #define MAKE_FALLBACK(op, sz) \
static u##sz real_raw_read ## op(const volatile void __iomem *addr) \
{ \
WARN(1, "Invalid read" #op " at address %llx\n", \
@@ -143243,15 +219772,37 @@ index 9bdfde0c0f86d..549b22d4bcde1 100644
memset(buffer, 0xff, size);
}
-@@ -210,7 +211,7 @@ static void real_memcpy_toio(volatile void __iomem *addr, const void *buffer,
+@@ -210,9 +211,9 @@ static void real_memcpy_toio(volatile void __iomem *addr, const void *buffer,
size_t size)
{
WARN(1, "Invalid memcpy_toio at address 0x%llx\n",
- (unsigned long long __force)addr);
+ (unsigned long long)(uintptr_t __force)addr);
}
- #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
-
+-#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
++#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
+
+ #define MAKE_OP(op, sz) \
+ u##sz __raw_read ## op(const volatile void __iomem *addr) \
+diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
+index 926f4823d5eac..fd1728d94babb 100644
+--- a/lib/lz4/lz4_decompress.c
++++ b/lib/lz4/lz4_decompress.c
+@@ -271,8 +271,12 @@ static FORCE_INLINE int LZ4_decompress_generic(
+ ip += length;
+ op += length;
+
+- /* Necessarily EOF, due to parsing restrictions */
+- if (!partialDecoding || (cpy == oend))
++ /* Necessarily EOF when !partialDecoding.
++ * When partialDecoding, it is EOF if we've either
++ * filled the output buffer or
++ * can't proceed with reading an offset for following match.
++ */
++ if (!partialDecoding || (cpy == oend) || (ip >= (iend - 2)))
+ break;
+ } else {
+ /* may overwrite up to WILDCOPYLENGTH beyond cpy */
diff --git a/lib/mpi/mpi-mod.c b/lib/mpi/mpi-mod.c
index 47bc59edd4ff9..54fcc01564d9d 100644
--- a/lib/mpi/mpi-mod.c
@@ -143282,11 +219833,259 @@ index f9e89001b52eb..199ab201d5019 100644
clear_bit_unlock(0, &backtrace_flag);
put_cpu();
}
+diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile
+index a4c7cd74cff58..4fb7700a741bd 100644
+--- a/lib/raid6/test/Makefile
++++ b/lib/raid6/test/Makefile
+@@ -4,6 +4,8 @@
+ # from userspace.
+ #
+
++pound := \#
++
+ CC = gcc
+ OPTFLAGS = -O2 # Adjust as desired
+ CFLAGS = -I.. -I ../../../include -g $(OPTFLAGS)
+@@ -42,7 +44,7 @@ else ifeq ($(HAS_NEON),yes)
+ OBJS += neon.o neon1.o neon2.o neon4.o neon8.o recov_neon.o recov_neon_inner.o
+ CFLAGS += -DCONFIG_KERNEL_MODE_NEON=1
+ else
+- HAS_ALTIVEC := $(shell printf '\#include <altivec.h>\nvector int a;\n' |\
++ HAS_ALTIVEC := $(shell printf '$(pound)include <altivec.h>\nvector int a;\n' |\
+ gcc -c -x c - >/dev/null && rm ./-.o && echo yes)
+ ifeq ($(HAS_ALTIVEC),yes)
+ CFLAGS += -I../../../arch/powerpc/include
+diff --git a/lib/raid6/test/test.c b/lib/raid6/test/test.c
+index a3cf071941ab4..841a55242abaa 100644
+--- a/lib/raid6/test/test.c
++++ b/lib/raid6/test/test.c
+@@ -19,7 +19,6 @@
+ #define NDISKS 16 /* Including P and Q */
+
+ const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+-struct raid6_calls raid6_call;
+
+ char *dataptrs[NDISKS];
+ char data[NDISKS][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+diff --git a/lib/random32.c b/lib/random32.c
+index 4d0e05e471d72..f0ab17c2244be 100644
+--- a/lib/random32.c
++++ b/lib/random32.c
+@@ -39,8 +39,9 @@
+ #include <linux/random.h>
+ #include <linux/sched.h>
+ #include <linux/bitops.h>
++#include <linux/slab.h>
++#include <linux/notifier.h>
+ #include <asm/unaligned.h>
+-#include <trace/events/random.h>
+
+ /**
+ * prandom_u32_state - seeded pseudo-random number generator.
+@@ -386,7 +387,6 @@ u32 prandom_u32(void)
+ struct siprand_state *state = get_cpu_ptr(&net_rand_state);
+ u32 res = siprand_u32(state);
+
+- trace_prandom_u32(res);
+ put_cpu_ptr(&net_rand_state);
+ return res;
+ }
+@@ -552,9 +552,11 @@ static void prandom_reseed(struct timer_list *unused)
+ * To avoid worrying about whether it's safe to delay that interrupt
+ * long enough to seed all CPUs, just schedule an immediate timer event.
+ */
+-static void prandom_timer_start(struct random_ready_callback *unused)
++static int prandom_timer_start(struct notifier_block *nb,
++ unsigned long action, void *data)
+ {
+ mod_timer(&seed_timer, jiffies);
++ return 0;
+ }
+
+ #ifdef CONFIG_RANDOM32_SELFTEST
+@@ -618,13 +620,13 @@ core_initcall(prandom32_state_selftest);
+ */
+ static int __init prandom_init_late(void)
+ {
+- static struct random_ready_callback random_ready = {
+- .func = prandom_timer_start
++ static struct notifier_block random_ready = {
++ .notifier_call = prandom_timer_start
+ };
+- int ret = add_random_ready_callback(&random_ready);
++ int ret = register_random_ready_notifier(&random_ready);
+
+ if (ret == -EALREADY) {
+- prandom_timer_start(&random_ready);
++ prandom_timer_start(&random_ready, 0, NULL);
+ ret = 0;
+ }
+ return ret;
+diff --git a/lib/sha1.c b/lib/sha1.c
+index 9bd1935a14727..0494766fc574e 100644
+--- a/lib/sha1.c
++++ b/lib/sha1.c
+@@ -9,6 +9,7 @@
+ #include <linux/kernel.h>
+ #include <linux/export.h>
+ #include <linux/bitops.h>
++#include <linux/string.h>
+ #include <crypto/sha1.h>
+ #include <asm/unaligned.h>
+
+@@ -55,7 +56,8 @@
+ #define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+ __u32 TEMP = input(t); setW(t, TEMP); \
+ E += TEMP + rol32(A,5) + (fn) + (constant); \
+- B = ror32(B, 2); } while (0)
++ B = ror32(B, 2); \
++ TEMP = E; E = D; D = C; C = B; B = A; A = TEMP; } while (0)
+
+ #define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+ #define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+@@ -84,6 +86,7 @@
+ void sha1_transform(__u32 *digest, const char *data, __u32 *array)
+ {
+ __u32 A, B, C, D, E;
++ unsigned int i = 0;
+
+ A = digest[0];
+ B = digest[1];
+@@ -92,94 +95,24 @@ void sha1_transform(__u32 *digest, const char *data, __u32 *array)
+ E = digest[4];
+
+ /* Round 1 - iterations 0-16 take their input from 'data' */
+- T_0_15( 0, A, B, C, D, E);
+- T_0_15( 1, E, A, B, C, D);
+- T_0_15( 2, D, E, A, B, C);
+- T_0_15( 3, C, D, E, A, B);
+- T_0_15( 4, B, C, D, E, A);
+- T_0_15( 5, A, B, C, D, E);
+- T_0_15( 6, E, A, B, C, D);
+- T_0_15( 7, D, E, A, B, C);
+- T_0_15( 8, C, D, E, A, B);
+- T_0_15( 9, B, C, D, E, A);
+- T_0_15(10, A, B, C, D, E);
+- T_0_15(11, E, A, B, C, D);
+- T_0_15(12, D, E, A, B, C);
+- T_0_15(13, C, D, E, A, B);
+- T_0_15(14, B, C, D, E, A);
+- T_0_15(15, A, B, C, D, E);
++ for (; i < 16; ++i)
++ T_0_15(i, A, B, C, D, E);
+
+ /* Round 1 - tail. Input from 512-bit mixing array */
+- T_16_19(16, E, A, B, C, D);
+- T_16_19(17, D, E, A, B, C);
+- T_16_19(18, C, D, E, A, B);
+- T_16_19(19, B, C, D, E, A);
++ for (; i < 20; ++i)
++ T_16_19(i, A, B, C, D, E);
+
+ /* Round 2 */
+- T_20_39(20, A, B, C, D, E);
+- T_20_39(21, E, A, B, C, D);
+- T_20_39(22, D, E, A, B, C);
+- T_20_39(23, C, D, E, A, B);
+- T_20_39(24, B, C, D, E, A);
+- T_20_39(25, A, B, C, D, E);
+- T_20_39(26, E, A, B, C, D);
+- T_20_39(27, D, E, A, B, C);
+- T_20_39(28, C, D, E, A, B);
+- T_20_39(29, B, C, D, E, A);
+- T_20_39(30, A, B, C, D, E);
+- T_20_39(31, E, A, B, C, D);
+- T_20_39(32, D, E, A, B, C);
+- T_20_39(33, C, D, E, A, B);
+- T_20_39(34, B, C, D, E, A);
+- T_20_39(35, A, B, C, D, E);
+- T_20_39(36, E, A, B, C, D);
+- T_20_39(37, D, E, A, B, C);
+- T_20_39(38, C, D, E, A, B);
+- T_20_39(39, B, C, D, E, A);
++ for (; i < 40; ++i)
++ T_20_39(i, A, B, C, D, E);
+
+ /* Round 3 */
+- T_40_59(40, A, B, C, D, E);
+- T_40_59(41, E, A, B, C, D);
+- T_40_59(42, D, E, A, B, C);
+- T_40_59(43, C, D, E, A, B);
+- T_40_59(44, B, C, D, E, A);
+- T_40_59(45, A, B, C, D, E);
+- T_40_59(46, E, A, B, C, D);
+- T_40_59(47, D, E, A, B, C);
+- T_40_59(48, C, D, E, A, B);
+- T_40_59(49, B, C, D, E, A);
+- T_40_59(50, A, B, C, D, E);
+- T_40_59(51, E, A, B, C, D);
+- T_40_59(52, D, E, A, B, C);
+- T_40_59(53, C, D, E, A, B);
+- T_40_59(54, B, C, D, E, A);
+- T_40_59(55, A, B, C, D, E);
+- T_40_59(56, E, A, B, C, D);
+- T_40_59(57, D, E, A, B, C);
+- T_40_59(58, C, D, E, A, B);
+- T_40_59(59, B, C, D, E, A);
++ for (; i < 60; ++i)
++ T_40_59(i, A, B, C, D, E);
+
+ /* Round 4 */
+- T_60_79(60, A, B, C, D, E);
+- T_60_79(61, E, A, B, C, D);
+- T_60_79(62, D, E, A, B, C);
+- T_60_79(63, C, D, E, A, B);
+- T_60_79(64, B, C, D, E, A);
+- T_60_79(65, A, B, C, D, E);
+- T_60_79(66, E, A, B, C, D);
+- T_60_79(67, D, E, A, B, C);
+- T_60_79(68, C, D, E, A, B);
+- T_60_79(69, B, C, D, E, A);
+- T_60_79(70, A, B, C, D, E);
+- T_60_79(71, E, A, B, C, D);
+- T_60_79(72, D, E, A, B, C);
+- T_60_79(73, C, D, E, A, B);
+- T_60_79(74, B, C, D, E, A);
+- T_60_79(75, A, B, C, D, E);
+- T_60_79(76, E, A, B, C, D);
+- T_60_79(77, D, E, A, B, C);
+- T_60_79(78, C, D, E, A, B);
+- T_60_79(79, B, C, D, E, A);
++ for (; i < 80; ++i)
++ T_60_79(i, A, B, C, D, E);
+
+ digest[0] += A;
+ digest[1] += B;
diff --git a/lib/siphash.c b/lib/siphash.c
-index a90112ee72a1f..72b9068ab57bf 100644
+index a90112ee72a1f..71d315a6ad623 100644
--- a/lib/siphash.c
+++ b/lib/siphash.c
-@@ -49,6 +49,7 @@
+@@ -18,19 +18,13 @@
+ #include <asm/word-at-a-time.h>
+ #endif
+
+-#define SIPROUND \
+- do { \
+- v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \
+- v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \
+- v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \
+- v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
+- } while (0)
++#define SIPROUND SIPHASH_PERMUTATION(v0, v1, v2, v3)
+
+ #define PREAMBLE(len) \
+- u64 v0 = 0x736f6d6570736575ULL; \
+- u64 v1 = 0x646f72616e646f6dULL; \
+- u64 v2 = 0x6c7967656e657261ULL; \
+- u64 v3 = 0x7465646279746573ULL; \
++ u64 v0 = SIPHASH_CONST_0; \
++ u64 v1 = SIPHASH_CONST_1; \
++ u64 v2 = SIPHASH_CONST_2; \
++ u64 v3 = SIPHASH_CONST_3; \
+ u64 b = ((u64)(len)) << 56; \
+ v3 ^= key->key[1]; \
+ v2 ^= key->key[0]; \
+@@ -49,6 +43,7 @@
SIPROUND; \
return (v0 ^ v1) ^ (v2 ^ v3);
@@ -143294,7 +220093,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
{
const u8 *end = data + len - (len % sizeof(u64));
-@@ -80,8 +81,8 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
+@@ -80,8 +75,8 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
POSTAMBLE
}
EXPORT_SYMBOL(__siphash_aligned);
@@ -143304,7 +220103,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
{
const u8 *end = data + len - (len % sizeof(u64));
-@@ -113,7 +114,6 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
+@@ -113,7 +108,6 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
POSTAMBLE
}
EXPORT_SYMBOL(__siphash_unaligned);
@@ -143312,7 +220111,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
/**
* siphash_1u64 - compute 64-bit siphash PRF value of a u64
-@@ -250,6 +250,7 @@ EXPORT_SYMBOL(siphash_3u32);
+@@ -250,6 +244,7 @@ EXPORT_SYMBOL(siphash_3u32);
HSIPROUND; \
return (v0 ^ v1) ^ (v2 ^ v3);
@@ -143320,7 +220119,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
{
const u8 *end = data + len - (len % sizeof(u64));
-@@ -280,8 +281,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
+@@ -280,8 +275,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
HPOSTAMBLE
}
EXPORT_SYMBOL(__hsiphash_aligned);
@@ -143330,7 +220129,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u32 __hsiphash_unaligned(const void *data, size_t len,
const hsiphash_key_t *key)
{
-@@ -313,7 +314,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len,
+@@ -313,7 +308,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len,
HPOSTAMBLE
}
EXPORT_SYMBOL(__hsiphash_unaligned);
@@ -143338,7 +220137,32 @@ index a90112ee72a1f..72b9068ab57bf 100644
/**
* hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32
-@@ -418,6 +418,7 @@ EXPORT_SYMBOL(hsiphash_4u32);
+@@ -389,19 +383,13 @@ u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
+ }
+ EXPORT_SYMBOL(hsiphash_4u32);
+ #else
+-#define HSIPROUND \
+- do { \
+- v0 += v1; v1 = rol32(v1, 5); v1 ^= v0; v0 = rol32(v0, 16); \
+- v2 += v3; v3 = rol32(v3, 8); v3 ^= v2; \
+- v0 += v3; v3 = rol32(v3, 7); v3 ^= v0; \
+- v2 += v1; v1 = rol32(v1, 13); v1 ^= v2; v2 = rol32(v2, 16); \
+- } while (0)
++#define HSIPROUND HSIPHASH_PERMUTATION(v0, v1, v2, v3)
+
+ #define HPREAMBLE(len) \
+- u32 v0 = 0; \
+- u32 v1 = 0; \
+- u32 v2 = 0x6c796765U; \
+- u32 v3 = 0x74656462U; \
++ u32 v0 = HSIPHASH_CONST_0; \
++ u32 v1 = HSIPHASH_CONST_1; \
++ u32 v2 = HSIPHASH_CONST_2; \
++ u32 v3 = HSIPHASH_CONST_3; \
+ u32 b = ((u32)(len)) << 24; \
+ v3 ^= key->key[1]; \
+ v2 ^= key->key[0]; \
+@@ -418,6 +406,7 @@ EXPORT_SYMBOL(hsiphash_4u32);
HSIPROUND; \
return v1 ^ v3;
@@ -143346,7 +220170,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
{
const u8 *end = data + len - (len % sizeof(u32));
-@@ -438,8 +439,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
+@@ -438,8 +427,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
HPOSTAMBLE
}
EXPORT_SYMBOL(__hsiphash_aligned);
@@ -143356,7 +220180,7 @@ index a90112ee72a1f..72b9068ab57bf 100644
u32 __hsiphash_unaligned(const void *data, size_t len,
const hsiphash_key_t *key)
{
-@@ -461,7 +462,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len,
+@@ -461,7 +450,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len,
HPOSTAMBLE
}
EXPORT_SYMBOL(__hsiphash_unaligned);
@@ -143364,6 +220188,45 @@ index a90112ee72a1f..72b9068ab57bf 100644
/**
* hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32
+diff --git a/lib/stackdepot.c b/lib/stackdepot.c
+index 0a2e417f83cba..e90f0f19e77f9 100644
+--- a/lib/stackdepot.c
++++ b/lib/stackdepot.c
+@@ -20,7 +20,6 @@
+ */
+
+ #include <linux/gfp.h>
+-#include <linux/interrupt.h>
+ #include <linux/jhash.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+@@ -341,26 +340,3 @@ fast_exit:
+ return retval;
+ }
+ EXPORT_SYMBOL_GPL(stack_depot_save);
+-
+-static inline int in_irqentry_text(unsigned long ptr)
+-{
+- return (ptr >= (unsigned long)&__irqentry_text_start &&
+- ptr < (unsigned long)&__irqentry_text_end) ||
+- (ptr >= (unsigned long)&__softirqentry_text_start &&
+- ptr < (unsigned long)&__softirqentry_text_end);
+-}
+-
+-unsigned int filter_irq_stacks(unsigned long *entries,
+- unsigned int nr_entries)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < nr_entries; i++) {
+- if (in_irqentry_text(entries[i])) {
+- /* Include the irqentry function into the stack. */
+- return i + 1;
+- }
+- }
+- return nr_entries;
+-}
+-EXPORT_SYMBOL_GPL(filter_irq_stacks);
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 3806a52ce697a..2ddc10bd9add6 100644
--- a/lib/string_helpers.c
@@ -143520,6 +220383,40 @@ index c259842f6d443..ac794e3540693 100644
.unlocked_ioctl = dmirror_fops_unlocked_ioctl,
.llseek = default_llseek,
.owner = THIS_MODULE,
+diff --git a/lib/test_kmod.c b/lib/test_kmod.c
+index ce15893914131..cb800b1d0d99c 100644
+--- a/lib/test_kmod.c
++++ b/lib/test_kmod.c
+@@ -1149,6 +1149,7 @@ static struct kmod_test_device *register_test_dev_kmod(void)
+ if (ret) {
+ pr_err("could not register misc device: %d\n", ret);
+ free_test_dev_kmod(test_dev);
++ test_dev = NULL;
+ goto out;
+ }
+
+diff --git a/lib/test_lockup.c b/lib/test_lockup.c
+index 906b598740a7b..c3fd87d6c2dd0 100644
+--- a/lib/test_lockup.c
++++ b/lib/test_lockup.c
+@@ -417,9 +417,14 @@ static bool test_kernel_ptr(unsigned long addr, int size)
+ return false;
+
+ /* should be at least readable kernel address */
+- if (access_ok(ptr, 1) ||
+- access_ok(ptr + size - 1, 1) ||
+- get_kernel_nofault(buf, ptr) ||
++ if (!IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) &&
++ (access_ok((void __user *)ptr, 1) ||
++ access_ok((void __user *)ptr + size - 1, 1))) {
++ pr_err("user space ptr invalid in kernel: %#lx\n", addr);
++ return true;
++ }
++
++ if (get_kernel_nofault(buf, ptr) ||
+ get_kernel_nofault(buf, ptr + size - 1)) {
+ pr_err("invalid kernel ptr: %#lx\n", addr);
+ return true;
diff --git a/lib/test_meminit.c b/lib/test_meminit.c
index e4f706a404b3a..3ca717f113977 100644
--- a/lib/test_meminit.c
@@ -143532,6 +220429,281 @@ index e4f706a404b3a..3ca717f113977 100644
*total_failures += fail;
return 1;
}
+diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c
+index 7e7bbd0f3fd27..2062be1f2e80f 100644
+--- a/lib/test_ubsan.c
++++ b/lib/test_ubsan.c
+@@ -79,15 +79,6 @@ static void test_ubsan_load_invalid_value(void)
+ eval2 = eval;
+ }
+
+-static void test_ubsan_null_ptr_deref(void)
+-{
+- volatile int *ptr = NULL;
+- int val;
+-
+- UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
+- val = *ptr;
+-}
+-
+ static void test_ubsan_misaligned_access(void)
+ {
+ volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};
+@@ -98,29 +89,16 @@ static void test_ubsan_misaligned_access(void)
+ *ptr = val;
+ }
+
+-static void test_ubsan_object_size_mismatch(void)
+-{
+- /* "((aligned(8)))" helps this not into be misaligned for ptr-access. */
+- volatile int val __aligned(8) = 4;
+- volatile long long *ptr, val2;
+-
+- UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
+- ptr = (long long *)&val;
+- val2 = *ptr;
+-}
+-
+ static const test_ubsan_fp test_ubsan_array[] = {
+ test_ubsan_shift_out_of_bounds,
+ test_ubsan_out_of_bounds,
+ test_ubsan_load_invalid_value,
+ test_ubsan_misaligned_access,
+- test_ubsan_object_size_mismatch,
+ };
+
+ /* Excluded because they Oops the module. */
+ static const test_ubsan_fp skip_ubsan_array[] = {
+ test_ubsan_divrem_overflow,
+- test_ubsan_null_ptr_deref,
+ };
+
+ static int __init test_ubsan_init(void)
+diff --git a/lib/test_xarray.c b/lib/test_xarray.c
+index 8b1c318189ce8..e77d4856442c3 100644
+--- a/lib/test_xarray.c
++++ b/lib/test_xarray.c
+@@ -1463,6 +1463,25 @@ unlock:
+ XA_BUG_ON(xa, !xa_empty(xa));
+ }
+
++static noinline void check_create_range_5(struct xarray *xa,
++ unsigned long index, unsigned int order)
++{
++ XA_STATE_ORDER(xas, xa, index, order);
++ unsigned int i;
++
++ xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL);
++
++ for (i = 0; i < order + 10; i++) {
++ do {
++ xas_lock(&xas);
++ xas_create_range(&xas);
++ xas_unlock(&xas);
++ } while (xas_nomem(&xas, GFP_KERNEL));
++ }
++
++ xa_destroy(xa);
++}
++
+ static noinline void check_create_range(struct xarray *xa)
+ {
+ unsigned int order;
+@@ -1490,6 +1509,9 @@ static noinline void check_create_range(struct xarray *xa)
+ check_create_range_4(xa, (3U << order) + 1, order);
+ check_create_range_4(xa, (3U << order) - 1, order);
+ check_create_range_4(xa, (1U << 24) + 1, order);
++
++ check_create_range_5(xa, 0, order);
++ check_create_range_5(xa, (1U << order), order);
+ }
+
+ check_create_range_3();
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index d7ad44f2c8f57..a60f0bb2ea902 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -49,12 +49,16 @@
+
+ #include <asm/page.h> /* for PAGE_SIZE */
+ #include <asm/byteorder.h> /* cpu_to_le16 */
++#include <asm/unaligned.h>
+
+ #include <linux/string_helpers.h>
+ #include "kstrtox.h"
+
+-static unsigned long long simple_strntoull(const char *startp, size_t max_chars,
+- char **endp, unsigned int base)
++/* Disable pointer hashing if requested */
++bool no_hash_pointers __ro_after_init;
++EXPORT_SYMBOL_GPL(no_hash_pointers);
++
++static noinline unsigned long long simple_strntoull(const char *startp, size_t max_chars, char **endp, unsigned int base)
+ {
+ const char *cp;
+ unsigned long long result = 0ULL;
+@@ -757,14 +761,16 @@ static void enable_ptr_key_workfn(struct work_struct *work)
+
+ static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
+
+-static void fill_random_ptr_key(struct random_ready_callback *unused)
++static int fill_random_ptr_key(struct notifier_block *nb,
++ unsigned long action, void *data)
+ {
+ /* This may be in an interrupt handler. */
+ queue_work(system_unbound_wq, &enable_ptr_key_work);
++ return 0;
+ }
+
+-static struct random_ready_callback random_ready = {
+- .func = fill_random_ptr_key
++static struct notifier_block random_ready = {
++ .notifier_call = fill_random_ptr_key
+ };
+
+ static int __init initialize_ptr_random(void)
+@@ -778,7 +784,7 @@ static int __init initialize_ptr_random(void)
+ return 0;
+ }
+
+- ret = add_random_ready_callback(&random_ready);
++ ret = register_random_ready_notifier(&random_ready);
+ if (!ret) {
+ return 0;
+ } else if (ret == -EALREADY) {
+@@ -848,6 +854,19 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr,
+ return pointer_string(buf, end, (const void *)hashval, spec);
+ }
+
++static char *default_pointer(char *buf, char *end, const void *ptr,
++ struct printf_spec spec)
++{
++ /*
++ * default is to _not_ leak addresses, so hash before printing,
++ * unless no_hash_pointers is specified on the command line.
++ */
++ if (unlikely(no_hash_pointers))
++ return pointer_string(buf, end, ptr, spec);
++
++ return ptr_to_id(buf, end, ptr, spec);
++}
++
+ int kptr_restrict __read_mostly;
+
+ static noinline_for_stack
+@@ -857,7 +876,7 @@ char *restricted_pointer(char *buf, char *end, const void *ptr,
+ switch (kptr_restrict) {
+ case 0:
+ /* Handle as %p, hash and do _not_ leak addresses. */
+- return ptr_to_id(buf, end, ptr, spec);
++ return default_pointer(buf, end, ptr, spec);
+ case 1: {
+ const struct cred *cred;
+
+@@ -1771,7 +1790,7 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
+ char output[sizeof("0123 little-endian (0x01234567)")];
+ char *p = output;
+ unsigned int i;
+- u32 val;
++ u32 orig, val;
+
+ if (fmt[1] != 'c' || fmt[2] != 'c')
+ return error_string(buf, end, "(%p4?)", spec);
+@@ -1779,21 +1798,22 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
+ if (check_pointer(&buf, end, fourcc, spec))
+ return buf;
+
+- val = *fourcc & ~BIT(31);
++ orig = get_unaligned(fourcc);
++ val = orig & ~BIT(31);
+
+- for (i = 0; i < sizeof(*fourcc); i++) {
++ for (i = 0; i < sizeof(u32); i++) {
+ unsigned char c = val >> (i * 8);
+
+ /* Print non-control ASCII characters as-is, dot otherwise */
+ *p++ = isascii(c) && isprint(c) ? c : '.';
+ }
+
+- strcpy(p, *fourcc & BIT(31) ? " big-endian" : " little-endian");
++ strcpy(p, orig & BIT(31) ? " big-endian" : " little-endian");
+ p += strlen(p);
+
+ *p++ = ' ';
+ *p++ = '(';
+- p = special_hex_number(p, output + sizeof(output) - 2, *fourcc, sizeof(u32));
++ p = special_hex_number(p, output + sizeof(output) - 2, orig, sizeof(u32));
+ *p++ = ')';
+ *p = '\0';
+
+@@ -2225,10 +2245,6 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
+ return widen_string(buf, buf - buf_start, end, spec);
+ }
+
+-/* Disable pointer hashing if requested */
+-bool no_hash_pointers __ro_after_init;
+-EXPORT_SYMBOL_GPL(no_hash_pointers);
+-
+ int __init no_hash_pointers_enable(char *str)
+ {
+ if (no_hash_pointers)
+@@ -2457,7 +2473,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+ case 'e':
+ /* %pe with a non-ERR_PTR gets treated as plain %p */
+ if (!IS_ERR(ptr))
+- break;
++ return default_pointer(buf, end, ptr, spec);
+ return err_ptr(buf, end, ptr, spec);
+ case 'u':
+ case 'k':
+@@ -2467,16 +2483,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+ default:
+ return error_string(buf, end, "(einval)", spec);
+ }
++ default:
++ return default_pointer(buf, end, ptr, spec);
+ }
+-
+- /*
+- * default is to _not_ leak addresses, so hash before printing,
+- * unless no_hash_pointers is specified on the command line.
+- */
+- if (unlikely(no_hash_pointers))
+- return pointer_string(buf, end, ptr, spec);
+- else
+- return ptr_to_id(buf, end, ptr, spec);
+ }
+
+ /*
+diff --git a/lib/xarray.c b/lib/xarray.c
+index f5d8f54907b4f..96e2d7748e5aa 100644
+--- a/lib/xarray.c
++++ b/lib/xarray.c
+@@ -722,6 +722,8 @@ void xas_create_range(struct xa_state *xas)
+
+ for (;;) {
+ struct xa_node *node = xas->xa_node;
++ if (node->shift >= shift)
++ break;
+ xas->xa_node = xa_parent_locked(xas->xa, node);
+ xas->xa_offset = node->offset - 1;
+ if (node->offset != 0)
+@@ -1079,6 +1081,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
+ xa_mk_node(child));
+ if (xa_is_value(curr))
+ values--;
++ xas_update(xas, child);
+ } else {
+ unsigned int canon = offset - xas->xa_sibs;
+
+@@ -1093,6 +1096,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
+ } while (offset-- > xas->xa_offset);
+
+ node->nr_values += values;
++ xas_update(xas, node);
+ }
+ EXPORT_SYMBOL_GPL(xas_split);
+ #endif
diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c
index 7a6781e3f47b6..d548cf0e59fe6 100644
--- a/lib/xz/xz_dec_lzma2.c
@@ -143784,9 +220956,18 @@ index 1403639302e48..718d0d3ad8c4e 100644
static void __init pte_savedwrite_tests(struct pgtable_debug_args *args)
diff --git a/mm/filemap.c b/mm/filemap.c
-index dae481293b5d9..1293c3409e429 100644
+index dae481293b5d9..00e391e758801 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
+@@ -90,7 +90,7 @@
+ * ->lock_page (filemap_fault, access_process_vm)
+ *
+ * ->i_rwsem (generic_perform_write)
+- * ->mmap_lock (fault_in_pages_readable->do_page_fault)
++ * ->mmap_lock (fault_in_readable->do_page_fault)
+ *
+ * bdi->wb.list_lock
+ * sb_lock (fs/fs-writeback.c)
@@ -2093,7 +2093,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start,
if (!xa_is_value(page)) {
if (page->index < start)
@@ -143810,8 +220991,17 @@ index dae481293b5d9..1293c3409e429 100644
continue;
put_page:
put_page(head);
+@@ -3757,7 +3760,7 @@ again:
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ */
+- if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
++ if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
+ status = -EFAULT;
+ break;
+ }
diff --git a/mm/gup.c b/mm/gup.c
-index 886d6148d3d03..52f08e3177e9f 100644
+index 886d6148d3d03..05068d3d2557e 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -124,8 +124,8 @@ static inline struct page *try_get_compound_head(struct page *page, int refs)
@@ -143864,8 +221054,158 @@ index 886d6148d3d03..52f08e3177e9f 100644
}
/**
+@@ -440,7 +465,7 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address,
+ pte_t *pte, unsigned int flags)
+ {
+ /* No page to get reference */
+- if (flags & FOLL_GET)
++ if (flags & (FOLL_GET | FOLL_PIN))
+ return -EFAULT;
+
+ if (flags & FOLL_TOUCH) {
+@@ -918,6 +943,8 @@ static int faultin_page(struct vm_area_struct *vma,
+ /* mlock all present pages, but do not fault in new pages */
+ if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
+ return -ENOENT;
++ if (*flags & FOLL_NOFAULT)
++ return -EFAULT;
+ if (*flags & FOLL_WRITE)
+ fault_flags |= FAULT_FLAG_WRITE;
+ if (*flags & FOLL_REMOTE)
+@@ -1656,6 +1683,122 @@ finish_or_fault:
+ }
+ #endif /* !CONFIG_MMU */
+
++/**
++ * fault_in_writeable - fault in userspace address range for writing
++ * @uaddr: start of address range
++ * @size: size of address range
++ *
++ * Returns the number of bytes not faulted in (like copy_to_user() and
++ * copy_from_user()).
++ */
++size_t fault_in_writeable(char __user *uaddr, size_t size)
++{
++ char __user *start = uaddr, *end;
++
++ if (unlikely(size == 0))
++ return 0;
++ if (!PAGE_ALIGNED(uaddr)) {
++ if (unlikely(__put_user(0, uaddr) != 0))
++ return size;
++ uaddr = (char __user *)PAGE_ALIGN((unsigned long)uaddr);
++ }
++ end = (char __user *)PAGE_ALIGN((unsigned long)start + size);
++ if (unlikely(end < start))
++ end = NULL;
++ while (uaddr != end) {
++ if (unlikely(__put_user(0, uaddr) != 0))
++ goto out;
++ uaddr += PAGE_SIZE;
++ }
++
++out:
++ if (size > uaddr - start)
++ return size - (uaddr - start);
++ return 0;
++}
++EXPORT_SYMBOL(fault_in_writeable);
++
++/*
++ * fault_in_safe_writeable - fault in an address range for writing
++ * @uaddr: start of address range
++ * @size: length of address range
++ *
++ * Faults in an address range for writing. This is primarily useful when we
++ * already know that some or all of the pages in the address range aren't in
++ * memory.
++ *
++ * Unlike fault_in_writeable(), this function is non-destructive.
++ *
++ * Note that we don't pin or otherwise hold the pages referenced that we fault
++ * in. There's no guarantee that they'll stay in memory for any duration of
++ * time.
++ *
++ * Returns the number of bytes not faulted in, like copy_to_user() and
++ * copy_from_user().
++ */
++size_t fault_in_safe_writeable(const char __user *uaddr, size_t size)
++{
++ unsigned long start = (unsigned long)uaddr, end;
++ struct mm_struct *mm = current->mm;
++ bool unlocked = false;
++
++ if (unlikely(size == 0))
++ return 0;
++ end = PAGE_ALIGN(start + size);
++ if (end < start)
++ end = 0;
++
++ mmap_read_lock(mm);
++ do {
++ if (fixup_user_fault(mm, start, FAULT_FLAG_WRITE, &unlocked))
++ break;
++ start = (start + PAGE_SIZE) & PAGE_MASK;
++ } while (start != end);
++ mmap_read_unlock(mm);
++
++ if (size > (unsigned long)uaddr - start)
++ return size - ((unsigned long)uaddr - start);
++ return 0;
++}
++EXPORT_SYMBOL(fault_in_safe_writeable);
++
++/**
++ * fault_in_readable - fault in userspace address range for reading
++ * @uaddr: start of user address range
++ * @size: size of user address range
++ *
++ * Returns the number of bytes not faulted in (like copy_to_user() and
++ * copy_from_user()).
++ */
++size_t fault_in_readable(const char __user *uaddr, size_t size)
++{
++ const char __user *start = uaddr, *end;
++ volatile char c;
++
++ if (unlikely(size == 0))
++ return 0;
++ if (!PAGE_ALIGNED(uaddr)) {
++ if (unlikely(__get_user(c, uaddr) != 0))
++ return size;
++ uaddr = (const char __user *)PAGE_ALIGN((unsigned long)uaddr);
++ }
++ end = (const char __user *)PAGE_ALIGN((unsigned long)start + size);
++ if (unlikely(end < start))
++ end = NULL;
++ while (uaddr != end) {
++ if (unlikely(__get_user(c, uaddr) != 0))
++ goto out;
++ uaddr += PAGE_SIZE;
++ }
++
++out:
++ (void)c;
++ if (size > uaddr - start)
++ return size - (uaddr - start);
++ return 0;
++}
++EXPORT_SYMBOL(fault_in_readable);
++
+ /**
+ * get_dump_page() - pin user page in memory while writing it to core dump
+ * @addr: user address
+@@ -2708,7 +2851,7 @@ static int internal_get_user_pages_fast(unsigned long start,
+
+ if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM |
+ FOLL_FORCE | FOLL_PIN | FOLL_GET |
+- FOLL_FAST_ONLY)))
++ FOLL_FAST_ONLY | FOLL_NOFAULT)))
+ return -EINVAL;
+
+ if (gup_flags & FOLL_PIN)
diff --git a/mm/highmem.c b/mm/highmem.c
-index 4212ad0e4a195..1f0c8a52fd807 100644
+index 4212ad0e4a195..4f942678e9da2 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -504,16 +504,22 @@ static inline int kmap_local_calc_idx(int idx)
@@ -143936,6 +221276,15 @@ index 4212ad0e4a195..1f0c8a52fd807 100644
int i;
/* Clear kmaps */
+@@ -619,7 +627,7 @@ void __kmap_local_sched_out(void)
+
+ /* With debug all even slots are unmapped and act as guard */
+ if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL) && !(i & 0x01)) {
+- WARN_ON_ONCE(!pte_none(pteval));
++ WARN_ON_ONCE(pte_val(pteval) != 0);
+ continue;
+ }
+ if (WARN_ON_ONCE(pte_none(pteval)))
@@ -635,8 +643,9 @@ void __kmap_local_sched_out(void)
idx = arch_kmap_local_map_idx(i, pte_pfn(pteval));
@@ -143956,6 +221305,15 @@ index 4212ad0e4a195..1f0c8a52fd807 100644
int i;
/* Restore kmaps */
+@@ -655,7 +664,7 @@ void __kmap_local_sched_in(void)
+
+ /* With debug all even slots are unmapped and act as guard */
+ if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL) && !(i & 0x01)) {
+- WARN_ON_ONCE(!pte_none(pteval));
++ WARN_ON_ONCE(pte_val(pteval) != 0);
+ continue;
+ }
+ if (WARN_ON_ONCE(pte_none(pteval)))
@@ -664,7 +673,8 @@ void __kmap_local_sched_in(void)
/* See comment in __kmap_local_sched_out() */
idx = arch_kmap_local_map_idx(i, pte_pfn(pteval));
@@ -143989,6 +221347,28 @@ index 842e265992380..bd56641c79d4e 100644
vma->vm_flags & VM_READ)
return 0;
+diff --git a/mm/huge_memory.c b/mm/huge_memory.c
+index c5142d237e482..8cc150a883615 100644
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -2617,11 +2617,16 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
+ struct address_space *mapping = NULL;
+ int extra_pins, ret;
+ pgoff_t end;
++ bool is_hzp;
+
+- VM_BUG_ON_PAGE(is_huge_zero_page(head), head);
+ VM_BUG_ON_PAGE(!PageLocked(head), head);
+ VM_BUG_ON_PAGE(!PageCompound(head), head);
+
++ is_hzp = is_huge_zero_page(head);
++ VM_WARN_ON_ONCE_PAGE(is_hzp, head);
++ if (is_hzp)
++ return -EBUSY;
++
+ if (PageWriteback(head))
+ return -EBUSY;
+
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 95dc7b83381f9..f5ed98843557b 100644
--- a/mm/hugetlb.c
@@ -144072,7 +221452,7 @@ index 95dc7b83381f9..f5ed98843557b 100644
put_page(page);
goto out;
diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
-index d8ccff4c1275e..47ed4fc33a29e 100644
+index d8ccff4c1275e..1bd6a3f13467b 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -132,11 +132,22 @@ static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache)
@@ -144098,6 +221478,20 @@ index d8ccff4c1275e..47ed4fc33a29e 100644
/*
* As the object now gets freed from the quarantine, assume that its
* free track is no longer valid.
+@@ -304,6 +315,13 @@ static void per_cpu_remove_cache(void *arg)
+ struct qlist_head *q;
+
+ q = this_cpu_ptr(&cpu_quarantine);
++ /*
++ * Ensure the ordering between the writing to q->offline and
++ * per_cpu_remove_cache. Prevent cpu_quarantine from being corrupted
++ * by interrupt.
++ */
++ if (READ_ONCE(q->offline))
++ return;
+ qlist_move_cache(q, &to_free, cache);
+ qlist_free_all(&to_free, cache);
+ }
diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
index 8d95ee52d0194..dd79840e60964 100644
--- a/mm/kasan/shadow.c
@@ -144128,10 +221522,37 @@ index 8d95ee52d0194..dd79840e60964 100644
}
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
-index 7a97db8bc8e75..84555b8233efc 100644
+index 7a97db8bc8e75..d25202766fbba 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
-@@ -97,10 +97,11 @@ struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS];
+@@ -10,12 +10,15 @@
+ #include <linux/atomic.h>
+ #include <linux/bug.h>
+ #include <linux/debugfs.h>
++#include <linux/hash.h>
+ #include <linux/irq_work.h>
++#include <linux/jhash.h>
+ #include <linux/kcsan-checks.h>
+ #include <linux/kfence.h>
+ #include <linux/kmemleak.h>
+ #include <linux/list.h>
+ #include <linux/lockdep.h>
++#include <linux/log2.h>
+ #include <linux/memblock.h>
+ #include <linux/moduleparam.h>
+ #include <linux/random.h>
+@@ -82,6 +85,10 @@ static const struct kernel_param_ops sample_interval_param_ops = {
+ };
+ module_param_cb(sample_interval, &sample_interval_param_ops, &kfence_sample_interval, 0600);
+
++/* Pool usage% threshold when currently covered allocations are skipped. */
++static unsigned long kfence_skip_covered_thresh __read_mostly = 75;
++module_param_named(skip_covered_thresh, kfence_skip_covered_thresh, ulong, 0644);
++
+ /* The pool of pages used for guard pages and objects. */
+ char *__kfence_pool __ro_after_init;
+ EXPORT_SYMBOL(__kfence_pool); /* Export for test modules. */
+@@ -97,14 +104,41 @@ struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS];
static struct list_head kfence_freelist = LIST_HEAD_INIT(kfence_freelist);
static DEFINE_RAW_SPINLOCK(kfence_freelist_lock); /* Lock protecting freelist. */
@@ -144146,7 +221567,274 @@ index 7a97db8bc8e75..84555b8233efc 100644
/* Gates the allocation, ensuring only one succeeds in a given period. */
atomic_t kfence_allocation_gate = ATOMIC_INIT(1);
-@@ -577,6 +578,7 @@ static const struct file_operations objects_fops = {
+
++/*
++ * A Counting Bloom filter of allocation coverage: limits currently covered
++ * allocations of the same source filling up the pool.
++ *
++ * Assuming a range of 15%-85% unique allocations in the pool at any point in
++ * time, the below parameters provide a probablity of 0.02-0.33 for false
++ * positive hits respectively:
++ *
++ * P(alloc_traces) = (1 - e^(-HNUM * (alloc_traces / SIZE)) ^ HNUM
++ */
++#define ALLOC_COVERED_HNUM 2
++#define ALLOC_COVERED_ORDER (const_ilog2(CONFIG_KFENCE_NUM_OBJECTS) + 2)
++#define ALLOC_COVERED_SIZE (1 << ALLOC_COVERED_ORDER)
++#define ALLOC_COVERED_HNEXT(h) hash_32(h, ALLOC_COVERED_ORDER)
++#define ALLOC_COVERED_MASK (ALLOC_COVERED_SIZE - 1)
++static atomic_t alloc_covered[ALLOC_COVERED_SIZE];
++
++/* Stack depth used to determine uniqueness of an allocation. */
++#define UNIQUE_ALLOC_STACK_DEPTH ((size_t)8)
++
++/*
++ * Randomness for stack hashes, making the same collisions across reboots and
++ * different machines less likely.
++ */
++static u32 stack_hash_seed __ro_after_init;
++
+ /* Statistics counters for debugfs. */
+ enum kfence_counter_id {
+ KFENCE_COUNTER_ALLOCATED,
+@@ -112,6 +146,9 @@ enum kfence_counter_id {
+ KFENCE_COUNTER_FREES,
+ KFENCE_COUNTER_ZOMBIES,
+ KFENCE_COUNTER_BUGS,
++ KFENCE_COUNTER_SKIP_INCOMPAT,
++ KFENCE_COUNTER_SKIP_CAPACITY,
++ KFENCE_COUNTER_SKIP_COVERED,
+ KFENCE_COUNTER_COUNT,
+ };
+ static atomic_long_t counters[KFENCE_COUNTER_COUNT];
+@@ -121,40 +158,67 @@ static const char *const counter_names[] = {
+ [KFENCE_COUNTER_FREES] = "total frees",
+ [KFENCE_COUNTER_ZOMBIES] = "zombie allocations",
+ [KFENCE_COUNTER_BUGS] = "total bugs",
++ [KFENCE_COUNTER_SKIP_INCOMPAT] = "skipped allocations (incompatible)",
++ [KFENCE_COUNTER_SKIP_CAPACITY] = "skipped allocations (capacity)",
++ [KFENCE_COUNTER_SKIP_COVERED] = "skipped allocations (covered)",
+ };
+ static_assert(ARRAY_SIZE(counter_names) == KFENCE_COUNTER_COUNT);
+
+ /* === Internals ============================================================ */
+
+-static bool kfence_protect(unsigned long addr)
++static inline bool should_skip_covered(void)
+ {
+- return !KFENCE_WARN_ON(!kfence_protect_page(ALIGN_DOWN(addr, PAGE_SIZE), true));
++ unsigned long thresh = (CONFIG_KFENCE_NUM_OBJECTS * kfence_skip_covered_thresh) / 100;
++
++ return atomic_long_read(&counters[KFENCE_COUNTER_ALLOCATED]) > thresh;
+ }
+
+-static bool kfence_unprotect(unsigned long addr)
++static u32 get_alloc_stack_hash(unsigned long *stack_entries, size_t num_entries)
+ {
+- return !KFENCE_WARN_ON(!kfence_protect_page(ALIGN_DOWN(addr, PAGE_SIZE), false));
++ num_entries = min(num_entries, UNIQUE_ALLOC_STACK_DEPTH);
++ num_entries = filter_irq_stacks(stack_entries, num_entries);
++ return jhash(stack_entries, num_entries * sizeof(stack_entries[0]), stack_hash_seed);
+ }
+
+-static inline struct kfence_metadata *addr_to_metadata(unsigned long addr)
++/*
++ * Adds (or subtracts) count @val for allocation stack trace hash
++ * @alloc_stack_hash from Counting Bloom filter.
++ */
++static void alloc_covered_add(u32 alloc_stack_hash, int val)
+ {
+- long index;
++ int i;
+
+- /* The checks do not affect performance; only called from slow-paths. */
++ for (i = 0; i < ALLOC_COVERED_HNUM; i++) {
++ atomic_add(val, &alloc_covered[alloc_stack_hash & ALLOC_COVERED_MASK]);
++ alloc_stack_hash = ALLOC_COVERED_HNEXT(alloc_stack_hash);
++ }
++}
+
+- if (!is_kfence_address((void *)addr))
+- return NULL;
++/*
++ * Returns true if the allocation stack trace hash @alloc_stack_hash is
++ * currently contained (non-zero count) in Counting Bloom filter.
++ */
++static bool alloc_covered_contains(u32 alloc_stack_hash)
++{
++ int i;
+
+- /*
+- * May be an invalid index if called with an address at the edge of
+- * __kfence_pool, in which case we would report an "invalid access"
+- * error.
+- */
+- index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1;
+- if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS)
+- return NULL;
++ for (i = 0; i < ALLOC_COVERED_HNUM; i++) {
++ if (!atomic_read(&alloc_covered[alloc_stack_hash & ALLOC_COVERED_MASK]))
++ return false;
++ alloc_stack_hash = ALLOC_COVERED_HNEXT(alloc_stack_hash);
++ }
+
+- return &kfence_metadata[index];
++ return true;
++}
++
++static bool kfence_protect(unsigned long addr)
++{
++ return !KFENCE_WARN_ON(!kfence_protect_page(ALIGN_DOWN(addr, PAGE_SIZE), true));
++}
++
++static bool kfence_unprotect(unsigned long addr)
++{
++ return !KFENCE_WARN_ON(!kfence_protect_page(ALIGN_DOWN(addr, PAGE_SIZE), false));
+ }
+
+ static inline unsigned long metadata_to_pageaddr(const struct kfence_metadata *meta)
+@@ -183,19 +247,26 @@ static inline unsigned long metadata_to_pageaddr(const struct kfence_metadata *m
+ * Update the object's metadata state, including updating the alloc/free stacks
+ * depending on the state transition.
+ */
+-static noinline void metadata_update_state(struct kfence_metadata *meta,
+- enum kfence_object_state next)
++static noinline void
++metadata_update_state(struct kfence_metadata *meta, enum kfence_object_state next,
++ unsigned long *stack_entries, size_t num_stack_entries)
+ {
+ struct kfence_track *track =
+ next == KFENCE_OBJECT_FREED ? &meta->free_track : &meta->alloc_track;
+
+ lockdep_assert_held(&meta->lock);
+
+- /*
+- * Skip over 1 (this) functions; noinline ensures we do not accidentally
+- * skip over the caller by never inlining.
+- */
+- track->num_stack_entries = stack_trace_save(track->stack_entries, KFENCE_STACK_DEPTH, 1);
++ if (stack_entries) {
++ memcpy(track->stack_entries, stack_entries,
++ num_stack_entries * sizeof(stack_entries[0]));
++ } else {
++ /*
++ * Skip over 1 (this) functions; noinline ensures we do not
++ * accidentally skip over the caller by never inlining.
++ */
++ num_stack_entries = stack_trace_save(track->stack_entries, KFENCE_STACK_DEPTH, 1);
++ }
++ track->num_stack_entries = num_stack_entries;
+ track->pid = task_pid_nr(current);
+ track->cpu = raw_smp_processor_id();
+ track->ts_nsec = local_clock(); /* Same source as printk timestamps. */
+@@ -257,7 +328,9 @@ static __always_inline void for_each_canary(const struct kfence_metadata *meta,
+ }
+ }
+
+-static void *kfence_guarded_alloc(struct kmem_cache *cache, size_t size, gfp_t gfp)
++static void *kfence_guarded_alloc(struct kmem_cache *cache, size_t size, gfp_t gfp,
++ unsigned long *stack_entries, size_t num_stack_entries,
++ u32 alloc_stack_hash)
+ {
+ struct kfence_metadata *meta = NULL;
+ unsigned long flags;
+@@ -271,8 +344,10 @@ static void *kfence_guarded_alloc(struct kmem_cache *cache, size_t size, gfp_t g
+ list_del_init(&meta->list);
+ }
+ raw_spin_unlock_irqrestore(&kfence_freelist_lock, flags);
+- if (!meta)
++ if (!meta) {
++ atomic_long_inc(&counters[KFENCE_COUNTER_SKIP_CAPACITY]);
+ return NULL;
++ }
+
+ if (unlikely(!raw_spin_trylock_irqsave(&meta->lock, flags))) {
+ /*
+@@ -314,10 +389,12 @@ static void *kfence_guarded_alloc(struct kmem_cache *cache, size_t size, gfp_t g
+ addr = (void *)meta->addr;
+
+ /* Update remaining metadata. */
+- metadata_update_state(meta, KFENCE_OBJECT_ALLOCATED);
++ metadata_update_state(meta, KFENCE_OBJECT_ALLOCATED, stack_entries, num_stack_entries);
+ /* Pairs with READ_ONCE() in kfence_shutdown_cache(). */
+ WRITE_ONCE(meta->cache, cache);
+ meta->size = size;
++ meta->alloc_stack_hash = alloc_stack_hash;
++
+ for_each_canary(meta, set_canary_byte);
+
+ /* Set required struct page fields. */
+@@ -330,6 +407,8 @@ static void *kfence_guarded_alloc(struct kmem_cache *cache, size_t size, gfp_t g
+
+ raw_spin_unlock_irqrestore(&meta->lock, flags);
+
++ alloc_covered_add(alloc_stack_hash, 1);
++
+ /* Memory initialization. */
+
+ /*
+@@ -394,10 +473,12 @@ static void kfence_guarded_free(void *addr, struct kfence_metadata *meta, bool z
+ memzero_explicit(addr, meta->size);
+
+ /* Mark the object as freed. */
+- metadata_update_state(meta, KFENCE_OBJECT_FREED);
++ metadata_update_state(meta, KFENCE_OBJECT_FREED, NULL, 0);
+
+ raw_spin_unlock_irqrestore(&meta->lock, flags);
+
++ alloc_covered_add(meta->alloc_stack_hash, -1);
++
+ /* Protect to detect use-after-frees. */
+ kfence_protect((unsigned long)addr);
+
+@@ -429,6 +510,7 @@ static bool __init kfence_init_pool(void)
+ unsigned long addr = (unsigned long)__kfence_pool;
+ struct page *pages;
+ int i;
++ char *p;
+
+ if (!__kfence_pool)
+ return false;
+@@ -447,6 +529,8 @@ static bool __init kfence_init_pool(void)
+ * enters __slab_free() slow-path.
+ */
+ for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
++ struct page *page = &pages[i];
++
+ if (!i || (i % 2))
+ continue;
+
+@@ -454,7 +538,11 @@ static bool __init kfence_init_pool(void)
+ if (WARN_ON(compound_head(&pages[i]) != &pages[i]))
+ goto err;
+
+- __SetPageSlab(&pages[i]);
++ __SetPageSlab(page);
++#ifdef CONFIG_MEMCG
++ page->memcg_data = (unsigned long)&kfence_metadata[i / 2 - 1].objcg |
++ MEMCG_DATA_OBJCGS;
++#endif
+ }
+
+ /*
+@@ -505,6 +593,16 @@ err:
+ * fails for the first page, and therefore expect addr==__kfence_pool in
+ * most failure cases.
+ */
++ for (p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
++ struct page *page = virt_to_page(p);
++
++ if (!PageSlab(page))
++ continue;
++#ifdef CONFIG_MEMCG
++ page->memcg_data = 0;
++#endif
++ __ClearPageSlab(page);
++ }
+ memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
+ __kfence_pool = NULL;
+ return false;
+@@ -577,6 +675,7 @@ static const struct file_operations objects_fops = {
.open = open_objects,
.read = seq_read,
.llseek = seq_lseek,
@@ -144154,7 +221842,13 @@ index 7a97db8bc8e75..84555b8233efc 100644
};
static int __init kfence_debugfs_init(void)
-@@ -668,6 +670,8 @@ void __init kfence_init(void)
+@@ -663,11 +762,14 @@ void __init kfence_init(void)
+ if (!kfence_sample_interval)
+ return;
+
++ stack_hash_seed = (u32)random_get_entropy();
+ if (!kfence_init_pool()) {
+ pr_err("%s failed\n", __func__);
return;
}
@@ -144163,9 +221857,35 @@ index 7a97db8bc8e75..84555b8233efc 100644
WRITE_ONCE(kfence_enabled, true);
queue_delayed_work(system_unbound_wq, &kfence_timer, 0);
pr_info("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n", KFENCE_POOL_SIZE,
-@@ -752,12 +756,7 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags)
- (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32)))
+@@ -736,12 +838,18 @@ void kfence_shutdown_cache(struct kmem_cache *s)
+
+ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags)
+ {
++ unsigned long stack_entries[KFENCE_STACK_DEPTH];
++ size_t num_stack_entries;
++ u32 alloc_stack_hash;
++
+ /*
+ * Perform size check before switching kfence_allocation_gate, so that
+ * we don't disable KFENCE without making an allocation.
+ */
+- if (size > PAGE_SIZE)
++ if (size > PAGE_SIZE) {
++ atomic_long_inc(&counters[KFENCE_COUNTER_SKIP_INCOMPAT]);
return NULL;
++ }
+
+ /*
+ * Skip allocations from non-default zones, including DMA. We cannot
+@@ -749,15 +857,12 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags)
+ * properties (e.g. reside in DMAable memory).
+ */
+ if ((flags & GFP_ZONEMASK) ||
+- (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32)))
++ (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32))) {
++ atomic_long_inc(&counters[KFENCE_COUNTER_SKIP_INCOMPAT]);
+ return NULL;
++ }
- /*
- * allocation_gate only needs to become non-zero, so it doesn't make
@@ -144177,11 +221897,210 @@ index 7a97db8bc8e75..84555b8233efc 100644
return NULL;
#ifdef CONFIG_KFENCE_STATIC_KEYS
/*
+@@ -776,7 +881,25 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags)
+ if (!READ_ONCE(kfence_enabled))
+ return NULL;
+
+- return kfence_guarded_alloc(s, size, flags);
++ num_stack_entries = stack_trace_save(stack_entries, KFENCE_STACK_DEPTH, 0);
++
++ /*
++ * Do expensive check for coverage of allocation in slow-path after
++ * allocation_gate has already become non-zero, even though it might
++ * mean not making any allocation within a given sample interval.
++ *
++ * This ensures reasonable allocation coverage when the pool is almost
++ * full, including avoiding long-lived allocations of the same source
++ * filling up the pool (e.g. pagecache allocations).
++ */
++ alloc_stack_hash = get_alloc_stack_hash(stack_entries, num_stack_entries);
++ if (should_skip_covered() && alloc_covered_contains(alloc_stack_hash)) {
++ atomic_long_inc(&counters[KFENCE_COUNTER_SKIP_COVERED]);
++ return NULL;
++ }
++
++ return kfence_guarded_alloc(s, size, flags, stack_entries, num_stack_entries,
++ alloc_stack_hash);
+ }
+
+ size_t kfence_ksize(const void *addr)
+@@ -805,6 +928,9 @@ void __kfence_free(void *addr)
+ {
+ struct kfence_metadata *meta = addr_to_metadata((unsigned long)addr);
+
++#ifdef CONFIG_MEMCG
++ KFENCE_WARN_ON(meta->objcg);
++#endif
+ /*
+ * If the objects of the cache are SLAB_TYPESAFE_BY_RCU, defer freeing
+ * the object, as the object page may be recycled for other-typed
+diff --git a/mm/kfence/kfence.h b/mm/kfence/kfence.h
+index c1f23c61e5f91..600f2e2431d6d 100644
+--- a/mm/kfence/kfence.h
++++ b/mm/kfence/kfence.h
+@@ -87,10 +87,36 @@ struct kfence_metadata {
+ /* Allocation and free stack information. */
+ struct kfence_track alloc_track;
+ struct kfence_track free_track;
++ /* For updating alloc_covered on frees. */
++ u32 alloc_stack_hash;
++#ifdef CONFIG_MEMCG
++ struct obj_cgroup *objcg;
++#endif
+ };
+
+ extern struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS];
+
++static inline struct kfence_metadata *addr_to_metadata(unsigned long addr)
++{
++ long index;
++
++ /* The checks do not affect performance; only called from slow-paths. */
++
++ if (!is_kfence_address((void *)addr))
++ return NULL;
++
++ /*
++ * May be an invalid index if called with an address at the edge of
++ * __kfence_pool, in which case we would report an "invalid access"
++ * error.
++ */
++ index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1;
++ if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS)
++ return NULL;
++
++ return &kfence_metadata[index];
++}
++
+ /* KFENCE error types for report generation. */
+ enum kfence_error_type {
+ KFENCE_ERROR_OOB, /* Detected a out-of-bounds access. */
+diff --git a/mm/kfence/report.c b/mm/kfence/report.c
+index f93a7b2a338be..37e140e7f201e 100644
+--- a/mm/kfence/report.c
++++ b/mm/kfence/report.c
+@@ -273,3 +273,50 @@ void kfence_report_error(unsigned long address, bool is_write, struct pt_regs *r
+ /* We encountered a memory safety error, taint the kernel! */
+ add_taint(TAINT_BAD_PAGE, LOCKDEP_STILL_OK);
+ }
++
++#ifdef CONFIG_PRINTK
++static void kfence_to_kp_stack(const struct kfence_track *track, void **kp_stack)
++{
++ int i, j;
++
++ i = get_stack_skipnr(track->stack_entries, track->num_stack_entries, NULL);
++ for (j = 0; i < track->num_stack_entries && j < KS_ADDRS_COUNT; ++i, ++j)
++ kp_stack[j] = (void *)track->stack_entries[i];
++ if (j < KS_ADDRS_COUNT)
++ kp_stack[j] = NULL;
++}
++
++bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++{
++ struct kfence_metadata *meta = addr_to_metadata((unsigned long)object);
++ unsigned long flags;
++
++ if (!meta)
++ return false;
++
++ /*
++ * If state is UNUSED at least show the pointer requested; the rest
++ * would be garbage data.
++ */
++ kpp->kp_ptr = object;
++
++ /* Requesting info an a never-used object is almost certainly a bug. */
++ if (WARN_ON(meta->state == KFENCE_OBJECT_UNUSED))
++ return true;
++
++ raw_spin_lock_irqsave(&meta->lock, flags);
++
++ kpp->kp_page = page;
++ kpp->kp_slab_cache = meta->cache;
++ kpp->kp_objp = (void *)meta->addr;
++ kfence_to_kp_stack(&meta->alloc_track, kpp->kp_stack);
++ if (meta->state == KFENCE_OBJECT_FREED)
++ kfence_to_kp_stack(&meta->free_track, kpp->kp_free_stack);
++ /* get_stack_skipnr() ensures the first entry is outside allocator. */
++ kpp->kp_ret = kpp->kp_stack[0];
++
++ raw_spin_unlock_irqrestore(&meta->lock, flags);
++
++ return true;
++}
++#endif
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
-index b57383c17cf60..adbe5aa011848 100644
+index b57383c17cf60..859303aae1809 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
-@@ -1403,7 +1403,8 @@ static void kmemleak_scan(void)
+@@ -789,6 +789,8 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
+ unsigned long flags;
+ struct kmemleak_object *object;
+ struct kmemleak_scan_area *area = NULL;
++ unsigned long untagged_ptr;
++ unsigned long untagged_objp;
+
+ object = find_and_get_object(ptr, 1);
+ if (!object) {
+@@ -797,6 +799,9 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
+ return;
+ }
+
++ untagged_ptr = (unsigned long)kasan_reset_tag((void *)ptr);
++ untagged_objp = (unsigned long)kasan_reset_tag((void *)object->pointer);
++
+ if (scan_area_cache)
+ area = kmem_cache_alloc(scan_area_cache, gfp_kmemleak_mask(gfp));
+
+@@ -808,8 +813,8 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
+ goto out_unlock;
+ }
+ if (size == SIZE_MAX) {
+- size = object->pointer + object->size - ptr;
+- } else if (ptr + size > object->pointer + object->size) {
++ size = untagged_objp + object->size - untagged_ptr;
++ } else if (untagged_ptr + size > untagged_objp + object->size) {
+ kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
+ dump_object_info(object);
+ kmem_cache_free(scan_area_cache, area);
+@@ -1120,7 +1125,7 @@ EXPORT_SYMBOL(kmemleak_no_scan);
+ void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count,
+ gfp_t gfp)
+ {
+- if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
++ if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn)
+ kmemleak_alloc(__va(phys), size, min_count, gfp);
+ }
+ EXPORT_SYMBOL(kmemleak_alloc_phys);
+@@ -1134,7 +1139,7 @@ EXPORT_SYMBOL(kmemleak_alloc_phys);
+ */
+ void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size)
+ {
+- if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
++ if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn)
+ kmemleak_free_part(__va(phys), size);
+ }
+ EXPORT_SYMBOL(kmemleak_free_part_phys);
+@@ -1146,7 +1151,7 @@ EXPORT_SYMBOL(kmemleak_free_part_phys);
+ */
+ void __ref kmemleak_not_leak_phys(phys_addr_t phys)
+ {
+- if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
++ if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn)
+ kmemleak_not_leak(__va(phys));
+ }
+ EXPORT_SYMBOL(kmemleak_not_leak_phys);
+@@ -1158,7 +1163,7 @@ EXPORT_SYMBOL(kmemleak_not_leak_phys);
+ */
+ void __ref kmemleak_ignore_phys(phys_addr_t phys)
+ {
+- if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
++ if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn)
+ kmemleak_ignore(__va(phys));
+ }
+ EXPORT_SYMBOL(kmemleak_ignore_phys);
+@@ -1403,7 +1408,8 @@ static void kmemleak_scan(void)
{
unsigned long flags;
struct kmemleak_object *object;
@@ -144191,7 +222110,7 @@ index b57383c17cf60..adbe5aa011848 100644
int new_leaks = 0;
jiffies_last_scan = jiffies;
-@@ -1443,9 +1444,9 @@ static void kmemleak_scan(void)
+@@ -1443,9 +1449,9 @@ static void kmemleak_scan(void)
* Struct page scanning for each node.
*/
get_online_mems();
@@ -144204,7 +222123,7 @@ index b57383c17cf60..adbe5aa011848 100644
unsigned long pfn;
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
-@@ -1454,8 +1455,8 @@ static void kmemleak_scan(void)
+@@ -1454,8 +1460,8 @@ static void kmemleak_scan(void)
if (!page)
continue;
@@ -144215,6 +222134,20 @@ index b57383c17cf60..adbe5aa011848 100644
continue;
/* only scan if page is in use */
if (page_count(page) == 0)
+diff --git a/mm/madvise.c b/mm/madvise.c
+index 0734db8d53a7a..8e5ca01a6cc07 100644
+--- a/mm/madvise.c
++++ b/mm/madvise.c
+@@ -1294,8 +1294,7 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
+ iov_iter_advance(&iter, iovec.iov_len);
+ }
+
+- if (ret == 0)
+- ret = total_len - iov_iter_count(&iter);
++ ret = (total_len - iov_iter_count(&iter)) ? : ret;
+
+ release_mm:
+ mmput(mm);
diff --git a/mm/memblock.c b/mm/memblock.c
index 5096500b26473..2b7397781c99a 100644
--- a/mm/memblock.c
@@ -144243,7 +222176,7 @@ index 5096500b26473..2b7397781c99a 100644
memblock_memory = NULL;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
-index 6da5020a8656d..32ba963ebf2e5 100644
+index 6da5020a8656d..971546bb99e04 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -103,11 +103,6 @@ static bool do_memsw_account(void)
@@ -144306,7 +222239,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
percpu_ref_kill(&objcg->refcnt);
}
-@@ -635,6 +630,64 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_node *mctz)
+@@ -635,6 +630,74 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_node *mctz)
return mz;
}
@@ -144330,6 +222263,9 @@ index 6da5020a8656d..32ba963ebf2e5 100644
+static DEFINE_SPINLOCK(stats_flush_lock);
+static DEFINE_PER_CPU(unsigned int, stats_updates);
+static atomic_t stats_flush_threshold = ATOMIC_INIT(0);
++static u64 flush_next_time;
++
++#define FLUSH_TIME (2UL*HZ)
+
+static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val)
+{
@@ -144351,6 +222287,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
+ if (!spin_trylock_irqsave(&stats_flush_lock, flag))
+ return;
+
++ flush_next_time = jiffies_64 + 2*FLUSH_TIME;
+ cgroup_rstat_flush_irqsafe(root_mem_cgroup->css.cgroup);
+ atomic_set(&stats_flush_threshold, 0);
+ spin_unlock_irqrestore(&stats_flush_lock, flag);
@@ -144362,16 +222299,22 @@ index 6da5020a8656d..32ba963ebf2e5 100644
+ __mem_cgroup_flush_stats();
+}
+
++void mem_cgroup_flush_stats_delayed(void)
++{
++ if (time_after64(jiffies_64, flush_next_time))
++ mem_cgroup_flush_stats();
++}
++
+static void flush_memcg_stats_dwork(struct work_struct *w)
+{
+ __mem_cgroup_flush_stats();
-+ queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ);
++ queue_delayed_work(system_unbound_wq, &stats_flush_dwork, FLUSH_TIME);
+}
+
/**
* __mod_memcg_state - update cgroup memory statistics
* @memcg: the memory cgroup
-@@ -647,7 +700,7 @@ void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val)
+@@ -647,7 +710,7 @@ void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val)
return;
__this_cpu_add(memcg->vmstats_percpu->state[idx], val);
@@ -144380,7 +222323,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
}
/* idx can be of type enum memcg_stat_item or node_stat_item. */
-@@ -675,10 +728,12 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
+@@ -675,10 +738,12 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
memcg = pn->memcg;
/* Update memcg */
@@ -144394,7 +222337,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
}
/**
-@@ -780,7 +835,7 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx,
+@@ -780,7 +845,7 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx,
return;
__this_cpu_add(memcg->vmstats_percpu->events[idx], count);
@@ -144403,7 +222346,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
}
static unsigned long memcg_events(struct mem_cgroup *memcg, int event)
-@@ -1414,7 +1469,7 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
+@@ -1414,7 +1479,7 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
*
* Current memory state:
*/
@@ -144412,7 +222355,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
for (i = 0; i < ARRAY_SIZE(memory_stats); i++) {
u64 size;
-@@ -1575,7 +1630,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
+@@ -1575,7 +1640,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
* A few threads which were not waiting at mutex_lock_killable() can
* fail to bail out. Therefore, check again after holding oom_lock.
*/
@@ -144421,7 +222364,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
unlock:
mutex_unlock(&oom_lock);
-@@ -2530,6 +2585,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
+@@ -2530,6 +2595,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
struct page_counter *counter;
enum oom_status oom_status;
unsigned long nr_reclaimed;
@@ -144429,7 +222372,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
bool may_swap = true;
bool drained = false;
unsigned long pflags;
-@@ -2564,15 +2620,6 @@ retry:
+@@ -2564,15 +2630,6 @@ retry:
if (gfp_mask & __GFP_ATOMIC)
goto force;
@@ -144445,7 +222388,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
/*
* Prevent unbounded recursion when reclaim operations need to
* allocate memory. This might exceed the limits temporarily,
-@@ -2630,8 +2677,9 @@ retry:
+@@ -2630,8 +2687,9 @@ retry:
if (gfp_mask & __GFP_RETRY_MAYFAIL)
goto nomem;
@@ -144457,7 +222400,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
/*
* keep retrying as long as the memcg oom killer is able to make
-@@ -2640,14 +2688,10 @@ retry:
+@@ -2640,14 +2698,10 @@ retry:
*/
oom_status = mem_cgroup_oom(mem_over_limit, gfp_mask,
get_order(nr_pages * PAGE_SIZE));
@@ -144474,7 +222417,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
}
nomem:
if (!(gfp_mask & __GFP_NOFAIL))
-@@ -3518,8 +3562,7 @@ static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
+@@ -3518,8 +3572,7 @@ static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
unsigned long val;
if (mem_cgroup_is_root(memcg)) {
@@ -144484,7 +222427,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
val = memcg_page_state(memcg, NR_FILE_PAGES) +
memcg_page_state(memcg, NR_ANON_MAPPED);
if (swap)
-@@ -3900,7 +3943,7 @@ static int memcg_numa_stat_show(struct seq_file *m, void *v)
+@@ -3900,7 +3953,7 @@ static int memcg_numa_stat_show(struct seq_file *m, void *v)
int nid;
struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
@@ -144493,7 +222436,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
seq_printf(m, "%s=%lu", stat->name,
-@@ -3972,7 +4015,7 @@ static int memcg_stat_show(struct seq_file *m, void *v)
+@@ -3972,7 +4025,7 @@ static int memcg_stat_show(struct seq_file *m, void *v)
BUILD_BUG_ON(ARRAY_SIZE(memcg1_stat_names) != ARRAY_SIZE(memcg1_stats));
@@ -144502,7 +222445,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) {
unsigned long nr;
-@@ -4475,7 +4518,7 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+@@ -4475,7 +4528,7 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
struct mem_cgroup *memcg = mem_cgroup_from_css(wb->memcg_css);
struct mem_cgroup *parent;
@@ -144511,7 +222454,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
*pdirty = memcg_page_state(memcg, NR_FILE_DIRTY);
*pwriteback = memcg_page_state(memcg, NR_WRITEBACK);
-@@ -5341,21 +5384,6 @@ static void mem_cgroup_css_reset(struct cgroup_subsys_state *css)
+@@ -5341,21 +5394,6 @@ static void mem_cgroup_css_reset(struct cgroup_subsys_state *css)
memcg_wb_domain_size_changed(memcg);
}
@@ -144533,7 +222476,7 @@ index 6da5020a8656d..32ba963ebf2e5 100644
static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(css);
-@@ -6373,7 +6401,7 @@ static int memory_numa_stat_show(struct seq_file *m, void *v)
+@@ -6373,7 +6411,7 @@ static int memory_numa_stat_show(struct seq_file *m, void *v)
int i;
struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
@@ -144542,6 +222485,15 @@ index 6da5020a8656d..32ba963ebf2e5 100644
for (i = 0; i < ARRAY_SIZE(memory_stats); i++) {
int nid;
+@@ -7077,7 +7115,7 @@ static int __init cgroup_memory(char *s)
+ if (!strcmp(token, "nokmem"))
+ cgroup_memory_nokmem = true;
+ }
+- return 0;
++ return 1;
+ }
+ __setup("cgroup.memory=", cgroup_memory);
+
diff --git a/mm/memfd.c b/mm/memfd.c
index 081dd33e6a61b..475d095dd7f53 100644
--- a/mm/memfd.c
@@ -144624,10 +222576,31 @@ index 081dd33e6a61b..475d095dd7f53 100644
xas_pause(&xas);
xas_unlock_irq(&xas);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
-index bdbbb32211a58..f66977a171966 100644
+index bdbbb32211a58..c3ceb74369334 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
-@@ -1437,17 +1437,12 @@ static int memory_failure_hugetlb(unsigned long pfn, int flags)
+@@ -705,8 +705,10 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn,
+ (void *)&priv);
+ if (ret == 1 && priv.tk.addr)
+ kill_proc(&priv.tk, pfn, flags);
++ else
++ ret = 0;
+ mmap_read_unlock(p->mm);
+- return ret ? -EFAULT : -EHWPOISON;
++ return ret > 0 ? -EHWPOISON : -EFAULT;
+ }
+
+ static const char *action_name[] = {
+@@ -1215,7 +1217,7 @@ try_again:
+ }
+ out:
+ if (ret == -EIO)
+- dump_page(p, "hwpoison: unhandlable page");
++ pr_err("Memory failure: %#lx: unhandlable page.\n", page_to_pfn(p));
+
+ return ret;
+ }
+@@ -1437,17 +1439,12 @@ static int memory_failure_hugetlb(unsigned long pfn, int flags)
if (!(flags & MF_COUNT_INCREASED)) {
res = get_hwpoison_page(p, flags);
if (!res) {
@@ -144649,7 +222622,7 @@ index bdbbb32211a58..f66977a171966 100644
}
unlock_page(head);
res = MF_FAILED;
-@@ -2206,6 +2201,7 @@ retry:
+@@ -2206,6 +2203,7 @@ retry:
} else if (ret == 0) {
if (soft_offline_free_page(page) && try_again) {
try_again = false;
@@ -144657,11 +222630,121 @@ index bdbbb32211a58..f66977a171966 100644
goto retry;
}
}
+diff --git a/mm/memory.c b/mm/memory.c
+index c52be6d6b6055..26d115ded4ab7 100644
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -1301,6 +1301,17 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
+ return ret;
+ }
+
++/* Whether we should zap all COWed (private) pages too */
++static inline bool should_zap_cows(struct zap_details *details)
++{
++ /* By default, zap all pages */
++ if (!details)
++ return true;
++
++ /* Or, we zap COWed pages only if the caller wants to */
++ return !details->check_mapping;
++}
++
+ static unsigned long zap_pte_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long addr, unsigned long end,
+@@ -1396,16 +1407,18 @@ again:
+ continue;
+ }
+
+- /* If details->check_mapping, we leave swap entries. */
+- if (unlikely(details))
+- continue;
+-
+- if (!non_swap_entry(entry))
++ if (!non_swap_entry(entry)) {
++ /* Genuine swap entry, hence a private anon page */
++ if (!should_zap_cows(details))
++ continue;
+ rss[MM_SWAPENTS]--;
+- else if (is_migration_entry(entry)) {
++ } else if (is_migration_entry(entry)) {
+ struct page *page;
+
+ page = pfn_swap_entry_to_page(entry);
++ if (details && details->check_mapping &&
++ details->check_mapping != page_rmapping(page))
++ continue;
+ rss[mm_counter(page)]--;
+ }
+ if (unlikely(!free_swap_and_cache(entry)))
+@@ -3861,11 +3874,20 @@ static vm_fault_t __do_fault(struct vm_fault *vmf)
+ return ret;
+
+ if (unlikely(PageHWPoison(vmf->page))) {
+- if (ret & VM_FAULT_LOCKED)
+- unlock_page(vmf->page);
+- put_page(vmf->page);
++ struct page *page = vmf->page;
++ vm_fault_t poisonret = VM_FAULT_HWPOISON;
++ if (ret & VM_FAULT_LOCKED) {
++ if (page_mapped(page))
++ unmap_mapping_pages(page_mapping(page),
++ page->index, 1, false);
++ /* Retry if a clean page was removed from the cache. */
++ if (invalidate_inode_page(page))
++ poisonret = VM_FAULT_NOPAGE;
++ unlock_page(page);
++ }
++ put_page(page);
+ vmf->page = NULL;
+- return VM_FAULT_HWPOISON;
++ return poisonret;
+ }
+
+ if (unlikely(!(ret & VM_FAULT_LOCKED)))
+@@ -5445,6 +5467,8 @@ long copy_huge_page_from_user(struct page *dst_page,
+ if (rc)
+ break;
+
++ flush_dcache_page(subpage);
++
+ cond_resched();
+ }
+ return ret_val;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
-index d12e0608fced2..fa9ed9c98739a 100644
+index d12e0608fced2..e75872035c768 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
-@@ -2140,8 +2140,7 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
+@@ -783,7 +783,6 @@ static int vma_replace_policy(struct vm_area_struct *vma,
+ static int mbind_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end, struct mempolicy *new_pol)
+ {
+- struct vm_area_struct *next;
+ struct vm_area_struct *prev;
+ struct vm_area_struct *vma;
+ int err = 0;
+@@ -798,8 +797,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
+ if (start > vma->vm_start)
+ prev = vma;
+
+- for (; vma && vma->vm_start < end; prev = vma, vma = next) {
+- next = vma->vm_next;
++ for (; vma && vma->vm_start < end; prev = vma, vma = vma->vm_next) {
+ vmstart = max(start, vma->vm_start);
+ vmend = min(end, vma->vm_end);
+
+@@ -813,10 +811,6 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
+ new_pol, vma->vm_userfaultfd_ctx);
+ if (prev) {
+ vma = prev;
+- next = vma->vm_next;
+- if (mpol_equal(vma_policy(vma), new_pol))
+- continue;
+- /* vma_merge() joined vma && vma->next, case 8 */
+ goto replace;
+ }
+ if (vma->vm_start != vmstart) {
+@@ -2140,8 +2134,7 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
* memory with both reclaim and compact as well.
*/
if (!page && (gfp & __GFP_DIRECT_RECLAIM))
@@ -144671,6 +222754,120 @@ index d12e0608fced2..fa9ed9c98739a 100644
goto out;
}
+@@ -2568,6 +2561,7 @@ alloc_new:
+ mpol_new = kmem_cache_alloc(policy_cache, GFP_KERNEL);
+ if (!mpol_new)
+ goto err_out;
++ atomic_set(&mpol_new->refcnt, 1);
+ goto restart;
+ }
+
+diff --git a/mm/migrate.c b/mm/migrate.c
+index 1852d787e6ab6..afb944b600fe6 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -948,9 +948,12 @@ static int move_to_new_page(struct page *newpage, struct page *page,
+ if (!PageMappingFlags(page))
+ page->mapping = NULL;
+
+- if (likely(!is_zone_device_page(newpage)))
+- flush_dcache_page(newpage);
++ if (likely(!is_zone_device_page(newpage))) {
++ int i, nr = compound_nr(newpage);
+
++ for (i = 0; i < nr; i++)
++ flush_dcache_page(newpage + i);
++ }
+ }
+ out:
+ return rc;
+diff --git a/mm/mlock.c b/mm/mlock.c
+index 16d2ee160d43c..0cee3f97d3df7 100644
+--- a/mm/mlock.c
++++ b/mm/mlock.c
+@@ -826,18 +826,18 @@ int user_shm_lock(size_t size, struct ucounts *ucounts)
+
+ locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
+- if (lock_limit == RLIM_INFINITY)
+- allowed = 1;
+- lock_limit >>= PAGE_SHIFT;
++ if (lock_limit != RLIM_INFINITY)
++ lock_limit >>= PAGE_SHIFT;
+ spin_lock(&shmlock_user_lock);
+ memlock = inc_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_MEMLOCK, locked);
+
+- if (!allowed && (memlock == LONG_MAX || memlock > lock_limit) && !capable(CAP_IPC_LOCK)) {
++ if ((memlock == LONG_MAX || memlock > lock_limit) && !capable(CAP_IPC_LOCK)) {
+ dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_MEMLOCK, locked);
+ goto out;
+ }
+ if (!get_ucounts(ucounts)) {
+ dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_MEMLOCK, locked);
++ allowed = 0;
+ goto out;
+ }
+ allowed = 1;
+diff --git a/mm/mmap.c b/mm/mmap.c
+index 88dcc5c252255..6bb553ed5c557 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2113,14 +2113,6 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
+ return addr;
+ }
+
+-#ifndef arch_get_mmap_end
+-#define arch_get_mmap_end(addr) (TASK_SIZE)
+-#endif
+-
+-#ifndef arch_get_mmap_base
+-#define arch_get_mmap_base(addr, base) (base)
+-#endif
+-
+ /* Get an address range which is currently unmapped.
+ * For shmat() with addr=0.
+ *
+@@ -2551,7 +2543,7 @@ static int __init cmdline_parse_stack_guard_gap(char *p)
+ if (!*endptr)
+ stack_guard_gap = val << PAGE_SHIFT;
+
+- return 0;
++ return 1;
+ }
+ __setup("stack_guard_gap=", cmdline_parse_stack_guard_gap);
+
+diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
+index 459d195d2ff64..f45ff1b7626a6 100644
+--- a/mm/mmu_notifier.c
++++ b/mm/mmu_notifier.c
+@@ -1036,6 +1036,18 @@ int mmu_interval_notifier_insert_locked(
+ }
+ EXPORT_SYMBOL_GPL(mmu_interval_notifier_insert_locked);
+
++static bool
++mmu_interval_seq_released(struct mmu_notifier_subscriptions *subscriptions,
++ unsigned long seq)
++{
++ bool ret;
++
++ spin_lock(&subscriptions->lock);
++ ret = subscriptions->invalidate_seq != seq;
++ spin_unlock(&subscriptions->lock);
++ return ret;
++}
++
+ /**
+ * mmu_interval_notifier_remove - Remove a interval notifier
+ * @interval_sub: Interval subscription to unregister
+@@ -1083,7 +1095,7 @@ void mmu_interval_notifier_remove(struct mmu_interval_notifier *interval_sub)
+ lock_map_release(&__mmu_notifier_invalidate_range_start_map);
+ if (seq)
+ wait_event(subscriptions->wq,
+- READ_ONCE(subscriptions->invalidate_seq) != seq);
++ mmu_interval_seq_released(subscriptions, seq));
+
+ /* pairs with mmgrab in mmu_interval_notifier_insert() */
+ mmdrop(mm);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 883e2cc85cad8..ed18dc49533f6 100644
--- a/mm/mprotect.c
@@ -144684,11 +222881,141 @@ index 883e2cc85cad8..ed18dc49533f6 100644
continue;
/*
+diff --git a/mm/mremap.c b/mm/mremap.c
+index badfe17ade1f0..3a3cf4cc2c632 100644
+--- a/mm/mremap.c
++++ b/mm/mremap.c
+@@ -486,6 +486,9 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
+ pmd_t *old_pmd, *new_pmd;
+ pud_t *old_pud, *new_pud;
+
++ if (!len)
++ return 0;
++
+ old_end = old_addr + len;
+ flush_cache_range(vma, old_addr, old_end);
+
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
-index 989f35a2bbb1d..bfa9e348c3a3a 100644
+index 989f35a2bbb1d..262f752d3d516 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
-@@ -1120,27 +1120,24 @@ bool out_of_memory(struct oom_control *oc)
+@@ -635,7 +635,7 @@ done:
+ */
+ set_bit(MMF_OOM_SKIP, &mm->flags);
+
+- /* Drop a reference taken by wake_oom_reaper */
++ /* Drop a reference taken by queue_oom_reaper */
+ put_task_struct(tsk);
+ }
+
+@@ -645,12 +645,12 @@ static int oom_reaper(void *unused)
+ struct task_struct *tsk = NULL;
+
+ wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL);
+- spin_lock(&oom_reaper_lock);
++ spin_lock_irq(&oom_reaper_lock);
+ if (oom_reaper_list != NULL) {
+ tsk = oom_reaper_list;
+ oom_reaper_list = tsk->oom_reaper_list;
+ }
+- spin_unlock(&oom_reaper_lock);
++ spin_unlock_irq(&oom_reaper_lock);
+
+ if (tsk)
+ oom_reap_task(tsk);
+@@ -659,22 +659,48 @@ static int oom_reaper(void *unused)
+ return 0;
+ }
+
+-static void wake_oom_reaper(struct task_struct *tsk)
++static void wake_oom_reaper(struct timer_list *timer)
+ {
+- /* mm is already queued? */
+- if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
+- return;
++ struct task_struct *tsk = container_of(timer, struct task_struct,
++ oom_reaper_timer);
++ struct mm_struct *mm = tsk->signal->oom_mm;
++ unsigned long flags;
+
+- get_task_struct(tsk);
++ /* The victim managed to terminate on its own - see exit_mmap */
++ if (test_bit(MMF_OOM_SKIP, &mm->flags)) {
++ put_task_struct(tsk);
++ return;
++ }
+
+- spin_lock(&oom_reaper_lock);
++ spin_lock_irqsave(&oom_reaper_lock, flags);
+ tsk->oom_reaper_list = oom_reaper_list;
+ oom_reaper_list = tsk;
+- spin_unlock(&oom_reaper_lock);
++ spin_unlock_irqrestore(&oom_reaper_lock, flags);
+ trace_wake_reaper(tsk->pid);
+ wake_up(&oom_reaper_wait);
+ }
+
++/*
++ * Give the OOM victim time to exit naturally before invoking the oom_reaping.
++ * The timers timeout is arbitrary... the longer it is, the longer the worst
++ * case scenario for the OOM can take. If it is too small, the oom_reaper can
++ * get in the way and release resources needed by the process exit path.
++ * e.g. The futex robust list can sit in Anon|Private memory that gets reaped
++ * before the exit path is able to wake the futex waiters.
++ */
++#define OOM_REAPER_DELAY (2*HZ)
++static void queue_oom_reaper(struct task_struct *tsk)
++{
++ /* mm is already queued? */
++ if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
++ return;
++
++ get_task_struct(tsk);
++ timer_setup(&tsk->oom_reaper_timer, wake_oom_reaper, 0);
++ tsk->oom_reaper_timer.expires = jiffies + OOM_REAPER_DELAY;
++ add_timer(&tsk->oom_reaper_timer);
++}
++
+ static int __init oom_init(void)
+ {
+ oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper");
+@@ -682,7 +708,7 @@ static int __init oom_init(void)
+ }
+ subsys_initcall(oom_init)
+ #else
+-static inline void wake_oom_reaper(struct task_struct *tsk)
++static inline void queue_oom_reaper(struct task_struct *tsk)
+ {
+ }
+ #endif /* CONFIG_MMU */
+@@ -933,7 +959,7 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
+ rcu_read_unlock();
+
+ if (can_oom_reap)
+- wake_oom_reaper(victim);
++ queue_oom_reaper(victim);
+
+ mmdrop(mm);
+ put_task_struct(victim);
+@@ -969,7 +995,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
+ task_lock(victim);
+ if (task_will_free_mem(victim)) {
+ mark_oom_victim(victim);
+- wake_oom_reaper(victim);
++ queue_oom_reaper(victim);
+ task_unlock(victim);
+ put_task_struct(victim);
+ return;
+@@ -1067,7 +1093,7 @@ bool out_of_memory(struct oom_control *oc)
+ */
+ if (task_will_free_mem(current)) {
+ mark_oom_victim(current);
+- wake_oom_reaper(current);
++ queue_oom_reaper(current);
+ return true;
+ }
+
+@@ -1120,27 +1146,24 @@ bool out_of_memory(struct oom_control *oc)
}
/*
@@ -144727,7 +223054,7 @@ index 989f35a2bbb1d..bfa9e348c3a3a 100644
SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 23d3339ac4e8e..7773bae3b6edb 100644
+index 23d3339ac4e8e..47c22810c3c5f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4210,7 +4210,9 @@ void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...)
@@ -144741,7 +223068,44 @@ index 23d3339ac4e8e..7773bae3b6edb 100644
return;
va_start(args, fmt);
-@@ -9449,3 +9451,18 @@ bool take_page_off_buddy(struct page *page)
+@@ -6090,7 +6092,7 @@ static int build_zonerefs_node(pg_data_t *pgdat, struct zoneref *zonerefs)
+ do {
+ zone_type--;
+ zone = pgdat->node_zones + zone_type;
+- if (managed_zone(zone)) {
++ if (populated_zone(zone)) {
+ zoneref_set_zone(zone, &zonerefs[nr_zones++]);
+ check_highest_zone(zone_type);
+ }
+@@ -7897,10 +7899,17 @@ restart:
+
+ out2:
+ /* Align start of ZONE_MOVABLE on all nids to MAX_ORDER_NR_PAGES */
+- for (nid = 0; nid < MAX_NUMNODES; nid++)
++ for (nid = 0; nid < MAX_NUMNODES; nid++) {
++ unsigned long start_pfn, end_pfn;
++
+ zone_movable_pfn[nid] =
+ roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
+
++ get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
++ if (zone_movable_pfn[nid] >= end_pfn)
++ zone_movable_pfn[nid] = 0;
++ }
++
+ out:
+ /* restore the node_state */
+ node_states[N_MEMORY] = saved_node_state;
+@@ -8160,7 +8169,7 @@ void __init mem_init_print_info(void)
+ */
+ #define adj_init_size(start, end, size, pos, adj) \
+ do { \
+- if (start <= pos && pos < end && size > adj) \
++ if (&start[0] <= &pos[0] && &pos[0] < &end[0] && size > adj) \
+ size -= adj; \
+ } while (0)
+
+@@ -9449,3 +9458,18 @@ bool take_page_off_buddy(struct page *page)
return ret;
}
#endif
@@ -144760,8 +223124,158 @@ index 23d3339ac4e8e..7773bae3b6edb 100644
+ return false;
+}
+#endif /* CONFIG_ZONE_DMA */
+diff --git a/mm/page_io.c b/mm/page_io.c
+index c493ce9ebcf50..66c6fbb07bc4c 100644
+--- a/mm/page_io.c
++++ b/mm/page_io.c
+@@ -50,54 +50,6 @@ void end_swap_bio_write(struct bio *bio)
+ bio_put(bio);
+ }
+
+-static void swap_slot_free_notify(struct page *page)
+-{
+- struct swap_info_struct *sis;
+- struct gendisk *disk;
+- swp_entry_t entry;
+-
+- /*
+- * There is no guarantee that the page is in swap cache - the software
+- * suspend code (at least) uses end_swap_bio_read() against a non-
+- * swapcache page. So we must check PG_swapcache before proceeding with
+- * this optimization.
+- */
+- if (unlikely(!PageSwapCache(page)))
+- return;
+-
+- sis = page_swap_info(page);
+- if (data_race(!(sis->flags & SWP_BLKDEV)))
+- return;
+-
+- /*
+- * The swap subsystem performs lazy swap slot freeing,
+- * expecting that the page will be swapped out again.
+- * So we can avoid an unnecessary write if the page
+- * isn't redirtied.
+- * This is good for real swap storage because we can
+- * reduce unnecessary I/O and enhance wear-leveling
+- * if an SSD is used as the as swap device.
+- * But if in-memory swap device (eg zram) is used,
+- * this causes a duplicated copy between uncompressed
+- * data in VM-owned memory and compressed data in
+- * zram-owned memory. So let's free zram-owned memory
+- * and make the VM-owned decompressed page *dirty*,
+- * so the page should be swapped out somewhere again if
+- * we again wish to reclaim it.
+- */
+- disk = sis->bdev->bd_disk;
+- entry.val = page_private(page);
+- if (disk->fops->swap_slot_free_notify && __swap_count(entry) == 1) {
+- unsigned long offset;
+-
+- offset = swp_offset(entry);
+-
+- SetPageDirty(page);
+- disk->fops->swap_slot_free_notify(sis->bdev,
+- offset);
+- }
+-}
+-
+ static void end_swap_bio_read(struct bio *bio)
+ {
+ struct page *page = bio_first_page_all(bio);
+@@ -113,7 +65,6 @@ static void end_swap_bio_read(struct bio *bio)
+ }
+
+ SetPageUptodate(page);
+- swap_slot_free_notify(page);
+ out:
+ unlock_page(page);
+ WRITE_ONCE(bio->bi_private, NULL);
+@@ -392,11 +343,6 @@ int swap_readpage(struct page *page, bool synchronous)
+ if (sis->flags & SWP_SYNCHRONOUS_IO) {
+ ret = bdev_read_page(sis->bdev, swap_page_sector(page), page);
+ if (!ret) {
+- if (trylock_page(page)) {
+- swap_slot_free_notify(page);
+- unlock_page(page);
+- }
+-
+ count_vm_event(PSWPIN);
+ goto out;
+ }
+diff --git a/mm/rmap.c b/mm/rmap.c
+index 6aebd17472512..3e340ee380cb9 100644
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -1570,7 +1570,30 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
+
+ /* MADV_FREE page check */
+ if (!PageSwapBacked(page)) {
+- if (!PageDirty(page)) {
++ int ref_count, map_count;
++
++ /*
++ * Synchronize with gup_pte_range():
++ * - clear PTE; barrier; read refcount
++ * - inc refcount; barrier; read PTE
++ */
++ smp_mb();
++
++ ref_count = page_ref_count(page);
++ map_count = page_mapcount(page);
++
++ /*
++ * Order reads for page refcount and dirty flag
++ * (see comments in __remove_mapping()).
++ */
++ smp_rmb();
++
++ /*
++ * The only page refs must be one from isolation
++ * plus the rmap(s) (dropped by discard:).
++ */
++ if (ref_count == 1 + map_count &&
++ !PageDirty(page)) {
+ /* Invalidate as we cleared the pte */
+ mmu_notifier_invalidate_range(mm,
+ address, address + PAGE_SIZE);
+diff --git a/mm/secretmem.c b/mm/secretmem.c
+index 22b310adb53d9..5a62ef3bcfcff 100644
+--- a/mm/secretmem.c
++++ b/mm/secretmem.c
+@@ -158,6 +158,22 @@ const struct address_space_operations secretmem_aops = {
+ .isolate_page = secretmem_isolate_page,
+ };
+
++static int secretmem_setattr(struct user_namespace *mnt_userns,
++ struct dentry *dentry, struct iattr *iattr)
++{
++ struct inode *inode = d_inode(dentry);
++ unsigned int ia_valid = iattr->ia_valid;
++
++ if ((ia_valid & ATTR_SIZE) && inode->i_size)
++ return -EINVAL;
++
++ return simple_setattr(mnt_userns, dentry, iattr);
++}
++
++static const struct inode_operations secretmem_iops = {
++ .setattr = secretmem_setattr,
++};
++
+ static struct vfsmount *secretmem_mnt;
+
+ static struct file *secretmem_file_create(unsigned long flags)
+@@ -177,6 +193,7 @@ static struct file *secretmem_file_create(unsigned long flags)
+ mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
+ mapping_set_unevictable(inode->i_mapping);
+
++ inode->i_op = &secretmem_iops;
+ inode->i_mapping->a_ops = &secretmem_aops;
+
+ /* pretend we are a normal file with zero size */
diff --git a/mm/shmem.c b/mm/shmem.c
-index b5860f4a2738e..1609a8daba26e 100644
+index b5860f4a2738e..342d1bc728670 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -555,7 +555,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
@@ -144861,8 +223375,41 @@ index b5860f4a2738e..1609a8daba26e 100644
return split;
}
+@@ -2389,8 +2394,10 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
+ /* don't free the page */
+ goto out_unacct_blocks;
+ }
++
++ flush_dcache_page(page);
+ } else { /* ZEROPAGE */
+- clear_highpage(page);
++ clear_user_highpage(page, dst_addr);
+ }
+ } else {
+ page = *pagep;
+diff --git a/mm/slab.c b/mm/slab.c
+index 874b3f8fe80da..1bd283e98c58c 100644
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -3429,6 +3429,7 @@ static __always_inline void __cache_free(struct kmem_cache *cachep, void *objp,
+
+ if (is_kfence_address(objp)) {
+ kmemleak_free_recursive(objp, cachep->flags);
++ memcg_slab_free_hook(cachep, &objp, 1);
+ __kfence_free(objp);
+ return;
+ }
+@@ -3657,7 +3658,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller);
+ #endif /* CONFIG_NUMA */
+
+ #ifdef CONFIG_PRINTK
+-void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
+ {
+ struct kmem_cache *cachep;
+ unsigned int objnr;
diff --git a/mm/slab.h b/mm/slab.h
-index 58c01a34e5b86..56ad7eea3ddfb 100644
+index 58c01a34e5b86..1ae1bdd485c17 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -147,7 +147,7 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size,
@@ -144874,10 +223421,68 @@ index 58c01a34e5b86..56ad7eea3ddfb 100644
#endif
/* Common flags available with current configuration */
+@@ -643,7 +643,7 @@ struct kmem_obj_info {
+ void *kp_stack[KS_ADDRS_COUNT];
+ void *kp_free_stack[KS_ADDRS_COUNT];
+ };
+-void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page);
++void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page);
+ #endif
+
+ #endif /* MM_SLAB_H */
+diff --git a/mm/slab_common.c b/mm/slab_common.c
+index ec2bb0beed757..022319e7deaf7 100644
+--- a/mm/slab_common.c
++++ b/mm/slab_common.c
+@@ -568,6 +568,13 @@ bool kmem_valid_obj(void *object)
+ }
+ EXPORT_SYMBOL_GPL(kmem_valid_obj);
+
++static void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++{
++ if (__kfence_obj_info(kpp, object, page))
++ return;
++ __kmem_obj_info(kpp, object, page);
++}
++
+ /**
+ * kmem_dump_obj - Print available slab provenance information
+ * @object: slab object for which to find provenance information.
+@@ -603,6 +610,8 @@ void kmem_dump_obj(void *object)
+ pr_cont(" slab%s %s", cp, kp.kp_slab_cache->name);
+ else
+ pr_cont(" slab%s", cp);
++ if (is_kfence_address(object))
++ pr_cont(" (kfence)");
+ if (kp.kp_objp)
+ pr_cont(" start %px", kp.kp_objp);
+ if (kp.kp_data_offset)
+diff --git a/mm/slob.c b/mm/slob.c
+index 74d3f6e60666e..f3fc15df971af 100644
+--- a/mm/slob.c
++++ b/mm/slob.c
+@@ -462,7 +462,7 @@ out:
+ }
+
+ #ifdef CONFIG_PRINTK
+-void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
+ {
+ kpp->kp_ptr = object;
+ kpp->kp_page = page;
diff --git a/mm/slub.c b/mm/slub.c
-index d8f77346376d8..ca6ba6bdf27b1 100644
+index d8f77346376d8..b75eebc0350e7 100644
--- a/mm/slub.c
+++ b/mm/slub.c
+@@ -4299,7 +4299,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s)
+ }
+
+ #ifdef CONFIG_PRINTK
+-void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
++void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
+ {
+ void *base;
+ int __maybe_unused i;
@@ -5072,6 +5072,7 @@ struct loc_track {
unsigned long max;
unsigned long count;
@@ -144923,11 +223528,100 @@ index d8f77346376d8..ca6ba6bdf27b1 100644
return ppos;
}
+diff --git a/mm/swap_state.c b/mm/swap_state.c
+index bc7cee6b2ec54..122a37cbc081f 100644
+--- a/mm/swap_state.c
++++ b/mm/swap_state.c
+@@ -478,7 +478,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
+ * __read_swap_cache_async(), which has set SWAP_HAS_CACHE
+ * in swap_map, but not yet added its page to swap cache.
+ */
+- cond_resched();
++ schedule_timeout_uninterruptible(1);
+ }
+
+ /*
+diff --git a/mm/usercopy.c b/mm/usercopy.c
+index b3de3c4eefba7..540968b481e7e 100644
+--- a/mm/usercopy.c
++++ b/mm/usercopy.c
+@@ -294,7 +294,10 @@ static bool enable_checks __initdata = true;
+
+ static int __init parse_hardened_usercopy(char *str)
+ {
+- return strtobool(str, &enable_checks);
++ if (strtobool(str, &enable_checks))
++ pr_warn("Invalid option string for hardened_usercopy: '%s'\n",
++ str);
++ return 1;
+ }
+
+ __setup("hardened_usercopy=", parse_hardened_usercopy);
+diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
+index 7a90084155343..c9bab48856c65 100644
+--- a/mm/userfaultfd.c
++++ b/mm/userfaultfd.c
+@@ -151,6 +151,8 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
+ /* don't free the page */
+ goto out;
+ }
++
++ flush_dcache_page(page);
+ } else {
+ page = *pagep;
+ *pagep = NULL;
+@@ -621,6 +623,7 @@ retry:
+ err = -EFAULT;
+ goto out;
+ }
++ flush_dcache_page(page);
+ goto retry;
+ } else
+ BUG_ON(page);
diff --git a/mm/util.c b/mm/util.c
-index bacabe4469065..ea09dd33ab594 100644
+index bacabe4469065..3073de05c2bd4 100644
--- a/mm/util.c
+++ b/mm/util.c
-@@ -594,8 +594,10 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
+@@ -343,6 +343,38 @@ unsigned long randomize_stack_top(unsigned long stack_top)
+ #endif
+ }
+
++/**
++ * randomize_page - Generate a random, page aligned address
++ * @start: The smallest acceptable address the caller will take.
++ * @range: The size of the area, starting at @start, within which the
++ * random address must fall.
++ *
++ * If @start + @range would overflow, @range is capped.
++ *
++ * NOTE: Historical use of randomize_range, which this replaces, presumed that
++ * @start was already page aligned. We now align it regardless.
++ *
++ * Return: A page aligned address within [start, start + range). On error,
++ * @start is returned.
++ */
++unsigned long randomize_page(unsigned long start, unsigned long range)
++{
++ if (!PAGE_ALIGNED(start)) {
++ range -= PAGE_ALIGN(start) - start;
++ start = PAGE_ALIGN(start);
++ }
++
++ if (start > ULONG_MAX - range)
++ range = ULONG_MAX - start;
++
++ range >>= PAGE_SHIFT;
++
++ if (range == 0)
++ return start;
++
++ return start + (get_random_long() % range << PAGE_SHIFT);
++}
++
+ #ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
+ unsigned long arch_randomize_brk(struct mm_struct *mm)
+ {
+@@ -594,8 +626,10 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
return ret;
/* Don't even allow crazy sizes */
@@ -144953,6 +223647,19 @@ index e8a807c781107..8375eecc55de5 100644
return addr;
+diff --git a/mm/workingset.c b/mm/workingset.c
+index d5b81e4f4cbe8..880d882f3325f 100644
+--- a/mm/workingset.c
++++ b/mm/workingset.c
+@@ -352,7 +352,7 @@ void workingset_refault(struct page *page, void *shadow)
+
+ inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file);
+
+- mem_cgroup_flush_stats();
++ mem_cgroup_flush_stats_delayed();
+ /*
+ * Compare the distance to the existing workingset size. We
+ * don't activate pages that couldn't stay resident even if
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 68e8831068f4b..b897ce3b399a1 100644
--- a/mm/zsmalloc.c
@@ -145073,7 +223780,7 @@ index 3ec1a51a6944e..432ac5a16f2e0 100644
gnttab_end_foreign_access(ring->ref, 0, 0);
free_page((unsigned long)ring->intf);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
-index 2631efc6e359f..ea3431ac46a14 100644
+index 2631efc6e359f..7b69503dc46a2 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -77,6 +77,7 @@ static void ax25_kill_by_device(struct net_device *dev)
@@ -145084,25 +223791,74 @@ index 2631efc6e359f..ea3431ac46a14 100644
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return;
-@@ -85,11 +86,15 @@ static void ax25_kill_by_device(struct net_device *dev)
+@@ -85,11 +86,26 @@ static void ax25_kill_by_device(struct net_device *dev)
again:
ax25_for_each(s, &ax25_list) {
if (s->ax25_dev == ax25_dev) {
- s->ax25_dev = NULL;
+ sk = s->sk;
++ if (!sk) {
++ spin_unlock_bh(&ax25_list_lock);
++ ax25_disconnect(s, ENETUNREACH);
++ s->ax25_dev = NULL;
++ spin_lock_bh(&ax25_list_lock);
++ goto again;
++ }
+ sock_hold(sk);
spin_unlock_bh(&ax25_list_lock);
+ lock_sock(sk);
+ ax25_disconnect(s, ENETUNREACH);
+ s->ax25_dev = NULL;
++ if (sk->sk_socket) {
++ dev_put(ax25_dev->dev);
++ ax25_dev_put(ax25_dev);
++ }
+ release_sock(sk);
- ax25_disconnect(s, ENETUNREACH);
spin_lock_bh(&ax25_list_lock);
-
+ sock_put(sk);
/* The entry could have been deleted from the
* list meanwhile and thus the next pointer is
* no longer valid. Play it safe and restart
-@@ -534,7 +539,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
+@@ -353,21 +369,25 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
+ if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+ return -EFAULT;
+
+- if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
+- return -ENODEV;
+-
+ if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
+ return -EINVAL;
+
+ if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)
+ return -EINVAL;
+
++ ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr);
++ if (!ax25_dev)
++ return -ENODEV;
++
+ digi.ndigi = ax25_ctl.digi_count;
+ for (k = 0; k < digi.ndigi; k++)
+ digi.calls[k] = ax25_ctl.digi_addr[k];
+
+- if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev)) == NULL)
++ ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev);
++ if (!ax25) {
++ ax25_dev_put(ax25_dev);
+ return -ENOTCONN;
++ }
+
+ switch (ax25_ctl.cmd) {
+ case AX25_KILL:
+@@ -434,6 +454,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
+ }
+
+ out_put:
++ ax25_dev_put(ax25_dev);
+ ax25_cb_put(ax25);
+ return ret;
+
+@@ -534,7 +555,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
ax25_cb *ax25;
struct net_device *dev;
char devname[IFNAMSIZ];
@@ -145111,7 +223867,7 @@ index 2631efc6e359f..ea3431ac46a14 100644
int res = 0;
if (level != SOL_AX25)
-@@ -566,7 +571,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
+@@ -566,7 +587,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T1:
@@ -145120,7 +223876,7 @@ index 2631efc6e359f..ea3431ac46a14 100644
res = -EINVAL;
break;
}
-@@ -575,7 +580,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
+@@ -575,7 +596,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T2:
@@ -145129,7 +223885,7 @@ index 2631efc6e359f..ea3431ac46a14 100644
res = -EINVAL;
break;
}
-@@ -591,7 +596,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
+@@ -591,7 +612,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T3:
@@ -145138,7 +223894,7 @@ index 2631efc6e359f..ea3431ac46a14 100644
res = -EINVAL;
break;
}
-@@ -599,7 +604,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
+@@ -599,7 +620,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_IDLE:
@@ -145147,6 +223903,277 @@ index 2631efc6e359f..ea3431ac46a14 100644
res = -EINVAL;
break;
}
+@@ -960,14 +981,16 @@ static int ax25_release(struct socket *sock)
+ {
+ struct sock *sk = sock->sk;
+ ax25_cb *ax25;
++ ax25_dev *ax25_dev;
+
+ if (sk == NULL)
+ return 0;
+
+ sock_hold(sk);
+- sock_orphan(sk);
+ lock_sock(sk);
++ sock_orphan(sk);
+ ax25 = sk_to_ax25(sk);
++ ax25_dev = ax25->ax25_dev;
+
+ if (sk->sk_type == SOCK_SEQPACKET) {
+ switch (ax25->state) {
+@@ -1029,6 +1052,15 @@ static int ax25_release(struct socket *sock)
+ sk->sk_state_change(sk);
+ ax25_destroy_socket(ax25);
+ }
++ if (ax25_dev) {
++ del_timer_sync(&ax25->timer);
++ del_timer_sync(&ax25->t1timer);
++ del_timer_sync(&ax25->t2timer);
++ del_timer_sync(&ax25->t3timer);
++ del_timer_sync(&ax25->idletimer);
++ dev_put(ax25_dev->dev);
++ ax25_dev_put(ax25_dev);
++ }
+
+ sock->sk = NULL;
+ release_sock(sk);
+@@ -1105,8 +1137,10 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ }
+ }
+
+- if (ax25_dev != NULL)
++ if (ax25_dev) {
+ ax25_fillin_cb(ax25, ax25_dev);
++ dev_hold(ax25_dev->dev);
++ }
+
+ done:
+ ax25_cb_add(ax25);
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index 4ac2e0847652a..d2e0cc67d91a7 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -37,6 +37,7 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
+ for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
+ if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
+ res = ax25_dev;
++ ax25_dev_hold(ax25_dev);
+ }
+ spin_unlock_bh(&ax25_dev_lock);
+
+@@ -56,6 +57,7 @@ void ax25_dev_device_up(struct net_device *dev)
+ return;
+ }
+
++ refcount_set(&ax25_dev->refcount, 1);
+ dev->ax25_ptr = ax25_dev;
+ ax25_dev->dev = dev;
+ dev_hold(dev);
+@@ -84,6 +86,7 @@ void ax25_dev_device_up(struct net_device *dev)
+ ax25_dev->next = ax25_dev_list;
+ ax25_dev_list = ax25_dev;
+ spin_unlock_bh(&ax25_dev_lock);
++ ax25_dev_hold(ax25_dev);
+
+ ax25_register_dev_sysctl(ax25_dev);
+ }
+@@ -113,9 +116,10 @@ void ax25_dev_device_down(struct net_device *dev)
+ if ((s = ax25_dev_list) == ax25_dev) {
+ ax25_dev_list = s->next;
+ spin_unlock_bh(&ax25_dev_lock);
++ ax25_dev_put(ax25_dev);
+ dev->ax25_ptr = NULL;
+ dev_put(dev);
+- kfree(ax25_dev);
++ ax25_dev_put(ax25_dev);
+ return;
+ }
+
+@@ -123,9 +127,10 @@ void ax25_dev_device_down(struct net_device *dev)
+ if (s->next == ax25_dev) {
+ s->next = ax25_dev->next;
+ spin_unlock_bh(&ax25_dev_lock);
++ ax25_dev_put(ax25_dev);
+ dev->ax25_ptr = NULL;
+ dev_put(dev);
+- kfree(ax25_dev);
++ ax25_dev_put(ax25_dev);
+ return;
+ }
+
+@@ -133,6 +138,7 @@ void ax25_dev_device_down(struct net_device *dev)
+ }
+ spin_unlock_bh(&ax25_dev_lock);
+ dev->ax25_ptr = NULL;
++ ax25_dev_put(ax25_dev);
+ }
+
+ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+@@ -144,20 +150,32 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+
+ switch (cmd) {
+ case SIOCAX25ADDFWD:
+- if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
++ fwd_dev = ax25_addr_ax25dev(&fwd->port_to);
++ if (!fwd_dev) {
++ ax25_dev_put(ax25_dev);
+ return -EINVAL;
+- if (ax25_dev->forward != NULL)
++ }
++ if (ax25_dev->forward) {
++ ax25_dev_put(fwd_dev);
++ ax25_dev_put(ax25_dev);
+ return -EINVAL;
++ }
+ ax25_dev->forward = fwd_dev->dev;
++ ax25_dev_put(fwd_dev);
++ ax25_dev_put(ax25_dev);
+ break;
+
+ case SIOCAX25DELFWD:
+- if (ax25_dev->forward == NULL)
++ if (!ax25_dev->forward) {
++ ax25_dev_put(ax25_dev);
+ return -EINVAL;
++ }
+ ax25_dev->forward = NULL;
++ ax25_dev_put(ax25_dev);
+ break;
+
+ default:
++ ax25_dev_put(ax25_dev);
+ return -EINVAL;
+ }
+
+diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
+index d0b2e094bd552..9751207f77572 100644
+--- a/net/ax25/ax25_route.c
++++ b/net/ax25/ax25_route.c
+@@ -75,11 +75,13 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ ax25_dev *ax25_dev;
+ int i;
+
+- if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
+- return -EINVAL;
+ if (route->digi_count > AX25_MAX_DIGIS)
+ return -EINVAL;
+
++ ax25_dev = ax25_addr_ax25dev(&route->port_addr);
++ if (!ax25_dev)
++ return -EINVAL;
++
+ write_lock_bh(&ax25_route_lock);
+
+ ax25_rt = ax25_route_list;
+@@ -91,6 +93,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ if (route->digi_count != 0) {
+ if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+ return -ENOMEM;
+ }
+ ax25_rt->digipeat->lastrepeat = -1;
+@@ -101,6 +104,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ }
+ }
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+ return 0;
+ }
+ ax25_rt = ax25_rt->next;
+@@ -108,6 +112,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+
+ if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+ return -ENOMEM;
+ }
+
+@@ -120,6 +125,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ write_unlock_bh(&ax25_route_lock);
+ kfree(ax25_rt);
++ ax25_dev_put(ax25_dev);
+ return -ENOMEM;
+ }
+ ax25_rt->digipeat->lastrepeat = -1;
+@@ -132,6 +138,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ ax25_rt->next = ax25_route_list;
+ ax25_route_list = ax25_rt;
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+
+ return 0;
+ }
+@@ -173,6 +180,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route)
+ }
+ }
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+
+ return 0;
+ }
+@@ -215,6 +223,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
+
+ out:
+ write_unlock_bh(&ax25_route_lock);
++ ax25_dev_put(ax25_dev);
+ return err;
+ }
+
+diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
+index 15ab812c4fe4b..3a476e4f6cd0b 100644
+--- a/net/ax25/ax25_subr.c
++++ b/net/ax25/ax25_subr.c
+@@ -261,12 +261,20 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
+ {
+ ax25_clear_queues(ax25);
+
+- if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
+- ax25_stop_heartbeat(ax25);
+- ax25_stop_t1timer(ax25);
+- ax25_stop_t2timer(ax25);
+- ax25_stop_t3timer(ax25);
+- ax25_stop_idletimer(ax25);
++ if (reason == ENETUNREACH) {
++ del_timer_sync(&ax25->timer);
++ del_timer_sync(&ax25->t1timer);
++ del_timer_sync(&ax25->t2timer);
++ del_timer_sync(&ax25->t3timer);
++ del_timer_sync(&ax25->idletimer);
++ } else {
++ if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
++ ax25_stop_heartbeat(ax25);
++ ax25_stop_t1timer(ax25);
++ ax25_stop_t2timer(ax25);
++ ax25_stop_t3timer(ax25);
++ ax25_stop_idletimer(ax25);
++ }
+
+ ax25->state = AX25_STATE_0;
+
+diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
+index 0899a729a23f4..c120c7c6d25fc 100644
+--- a/net/batman-adv/fragmentation.c
++++ b/net/batman-adv/fragmentation.c
+@@ -475,6 +475,17 @@ int batadv_frag_send_packet(struct sk_buff *skb,
+ goto free_skb;
+ }
+
++ /* GRO might have added fragments to the fragment list instead of
++ * frags[]. But this is not handled by skb_split and must be
++ * linearized to avoid incorrect length information after all
++ * batman-adv fragments were created and submitted to the
++ * hard-interface
++ */
++ if (skb_has_frag_list(skb) && __skb_linearize(skb)) {
++ ret = -ENOMEM;
++ goto free_skb;
++ }
++
+ /* Create one header to be copied to all fragments */
+ frag_header.packet_type = BATADV_UNICAST_FRAG;
+ frag_header.version = BATADV_COMPAT_VERSION;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 8a2b78f9c4b2c..35fadb9248498 100644
--- a/net/batman-adv/hard-interface.c
@@ -145220,9 +224247,18 @@ index 8a2b78f9c4b2c..35fadb9248498 100644
out:
batadv_hardif_put(hard_iface);
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
-index a3b6658ed7899..6e3419beca098 100644
+index a3b6658ed7899..2853634a39790 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
+@@ -134,7 +134,7 @@ static u8 batadv_mcast_mla_rtr_flags_softif_get_ipv6(struct net_device *dev)
+ {
+ struct inet6_dev *in6_dev = __in6_dev_get(dev);
+
+- if (in6_dev && in6_dev->cnf.mc_forwarding)
++ if (in6_dev && atomic_read(&in6_dev->cnf.mc_forwarding))
+ return BATADV_NO_FLAGS;
+ else
+ return BATADV_MCAST_WANT_NO_RTR6;
@@ -1339,6 +1339,7 @@ batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv,
* @bat_priv: the bat priv with all the soft interface information
* @skb: The multicast packet to check
@@ -145501,8 +224537,22 @@ index 0a2d78e811cf5..83eb84e8e688f 100644
}
static void __exit cmtp_exit(void)
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 2b5059a56cdaa..7a7e92be1652c 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -541,7 +541,9 @@ static void le_conn_timeout(struct work_struct *work)
+ if (conn->role == HCI_ROLE_SLAVE) {
+ /* Disable LE Advertising */
+ le_disable_advertising(hdev);
++ hci_dev_lock(hdev);
+ hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
++ hci_dev_unlock(hdev);
+ return;
+ }
+
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
-index 8a47a3017d61d..53f1b08017aab 100644
+index 8a47a3017d61d..cdca53732304c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -742,7 +742,8 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
@@ -145515,6 +224565,28 @@ index 8a47a3017d61d..53f1b08017aab 100644
/* Read LE Min/Max Tx Power*/
hci_req_add(req, HCI_OP_LE_READ_TRANSMIT_POWER,
0, NULL);
+@@ -3906,10 +3907,10 @@ int hci_register_dev(struct hci_dev *hdev)
+ */
+ switch (hdev->dev_type) {
+ case HCI_PRIMARY:
+- id = ida_simple_get(&hci_index_ida, 0, 0, GFP_KERNEL);
++ id = ida_simple_get(&hci_index_ida, 0, HCI_MAX_ID, GFP_KERNEL);
+ break;
+ case HCI_AMP:
+- id = ida_simple_get(&hci_index_ida, 1, 0, GFP_KERNEL);
++ id = ida_simple_get(&hci_index_ida, 1, HCI_MAX_ID, GFP_KERNEL);
+ break;
+ default:
+ return -EINVAL;
+@@ -3918,7 +3919,7 @@ int hci_register_dev(struct hci_dev *hdev)
+ if (id < 0)
+ return id;
+
+- sprintf(hdev->name, "hci%d", id);
++ snprintf(hdev->name, sizeof(hdev->name), "hci%d", id);
+ hdev->id = id;
+
+ BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
@@ -3998,6 +3999,7 @@ int hci_register_dev(struct hci_dev *hdev)
return id;
@@ -145523,8 +224595,16 @@ index 8a47a3017d61d..53f1b08017aab 100644
destroy_workqueue(hdev->workqueue);
destroy_workqueue(hdev->req_workqueue);
err:
+@@ -4081,6 +4083,7 @@ void hci_release_dev(struct hci_dev *hdev)
+ hci_dev_unlock(hdev);
+
+ ida_simple_remove(&hci_index_ida, hdev->id);
++ kfree_skb(hdev->sent_cmd);
+ kfree(hdev);
+ }
+ EXPORT_SYMBOL(hci_release_dev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
-index 0bca035bf2dcc..868a22df32850 100644
+index 0bca035bf2dcc..e984a8b4b9143 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1325,8 +1325,10 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
@@ -145540,7 +224620,18 @@ index 0bca035bf2dcc..868a22df32850 100644
/* If just one instance was disabled check if there are
* any other instance enabled before clearing HCI_LE_ADV
*/
-@@ -5780,7 +5782,13 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
+@@ -5151,8 +5153,9 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
+ hci_dev_lock(hdev);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+- if (hcon) {
++ if (hcon && hcon->type == AMP_LINK) {
+ hcon->state = BT_CLOSED;
++ hci_disconn_cfm(hcon, ev->reason);
+ hci_conn_del(hcon);
+ }
+
+@@ -5780,7 +5783,13 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_ev_le_advertising_info *ev = ptr;
s8 rssi;
@@ -145581,6 +224672,18 @@ index 7827639ecf5c3..4e3e0451b08c1 100644
module_put(THIS_MODULE);
}
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 77ba68209dbd8..c57a45df7a267 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -1436,6 +1436,7 @@ static void l2cap_ecred_connect(struct l2cap_chan *chan)
+
+ l2cap_ecred_init(chan, 0);
+
++ memset(&data, 0, sizeof(data));
+ data.pdu.req.psm = chan->psm;
+ data.pdu.req.mtu = cpu_to_le16(chan->imtu);
+ data.pdu.req.mps = cpu_to_le16(chan->mps);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c99d65ef13b1e..d2c6785205992 100644
--- a/net/bluetooth/l2cap_sock.c
@@ -146139,6 +225242,46 @@ index 98a8815865128..6e047e178c0ab 100644
return err;
}
+diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
+index b5f4ef35357c8..655ee0e2de86d 100644
+--- a/net/bpf/test_run.c
++++ b/net/bpf/test_run.c
+@@ -954,7 +954,7 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kat
+ if (!range_is_zero(user_ctx, offsetofend(typeof(*user_ctx), local_port), sizeof(*user_ctx)))
+ goto out;
+
+- if (user_ctx->local_port > U16_MAX || user_ctx->remote_port > U16_MAX) {
++ if (user_ctx->local_port > U16_MAX) {
+ ret = -ERANGE;
+ goto out;
+ }
+@@ -962,7 +962,7 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kat
+ ctx.family = (u16)user_ctx->family;
+ ctx.protocol = (u16)user_ctx->protocol;
+ ctx.dport = (u16)user_ctx->local_port;
+- ctx.sport = (__force __be16)user_ctx->remote_port;
++ ctx.sport = user_ctx->remote_port;
+
+ switch (ctx.family) {
+ case AF_INET:
+diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
+index b50382f957c12..6743c8a0fe8e1 100644
+--- a/net/bridge/br_input.c
++++ b/net/bridge/br_input.c
+@@ -39,6 +39,13 @@ static int br_pass_frame_up(struct sk_buff *skb)
+ dev_sw_netstats_rx_add(brdev, skb->len);
+
+ vg = br_vlan_group_rcu(br);
++
++ /* Reset the offload_fwd_mark because there could be a stacked
++ * bridge above, and it should not think this bridge it doing
++ * that bridge's work forwarding out its ports.
++ */
++ br_switchdev_frame_unmark(skb);
++
+ /* Bridge is just like any other port. Make sure the
+ * packet is allowed except in promisc mode when someone
+ * may be running packet capture.
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 793b0db9d9a36..9922497e59f8c 100644
--- a/net/bridge/br_ioctl.c
@@ -146451,7 +225594,7 @@ index eba0efe64d05a..fbf858ddec352 100644
return;
diff --git a/net/can/isotp.c b/net/can/isotp.c
-index df6968b28bf41..d2a430b6a13bd 100644
+index df6968b28bf41..26821487a0573 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -56,6 +56,7 @@
@@ -146473,7 +225616,13 @@ index df6968b28bf41..d2a430b6a13bd 100644
u32 state;
u8 bs;
u8 sn;
-@@ -145,6 +146,7 @@ struct isotp_sock {
+@@ -140,11 +141,13 @@ struct isotp_sock {
+ struct can_isotp_options opt;
+ struct can_isotp_fc_options rxfc, txfc;
+ struct can_isotp_ll_options ll;
++ u32 frame_txtime;
+ u32 force_tx_stmin;
+ u32 force_rx_stmin;
struct tpcon rx, tx;
struct list_head notifier;
wait_queue_head_t wait;
@@ -146481,7 +225630,16 @@ index df6968b28bf41..d2a430b6a13bd 100644
};
static LIST_HEAD(isotp_notifier_list);
-@@ -615,11 +617,17 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
+@@ -358,7 +361,7 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
+
+ so->tx_gap = ktime_set(0, 0);
+ /* add transmission time for CAN frame N_As */
+- so->tx_gap = ktime_add_ns(so->tx_gap, so->opt.frame_txtime);
++ so->tx_gap = ktime_add_ns(so->tx_gap, so->frame_txtime);
+ /* add waiting time for consecutive frames N_Cs */
+ if (so->opt.flags & CAN_ISOTP_FORCE_TXSTMIN)
+ so->tx_gap = ktime_add_ns(so->tx_gap,
+@@ -615,11 +618,17 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
n_pci_type = cf->data[ae] & 0xF0;
@@ -146500,7 +225658,7 @@ index df6968b28bf41..d2a430b6a13bd 100644
}
switch (n_pci_type) {
-@@ -668,6 +676,9 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
+@@ -668,6 +677,9 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
isotp_rcv_cf(sk, cf, ae, skb);
break;
}
@@ -146510,7 +225668,15 @@ index df6968b28bf41..d2a430b6a13bd 100644
}
static void isotp_fill_dataframe(struct canfd_frame *cf, struct isotp_sock *so,
-@@ -876,7 +887,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+@@ -854,6 +866,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+ struct canfd_frame *cf;
+ int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
+ int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0;
++ s64 hrtimer_sec = 0;
+ int off;
+ int err;
+
+@@ -876,7 +889,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (!size || size > MAX_MSG_LENGTH) {
err = -EINVAL;
@@ -146519,7 +225685,7 @@ index df6968b28bf41..d2a430b6a13bd 100644
}
/* take care of a potential SF_DL ESC offset for TX_DL > 8 */
-@@ -886,24 +897,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+@@ -886,24 +899,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) &&
(size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) {
err = -EINVAL;
@@ -146548,16 +225714,32 @@ index df6968b28bf41..d2a430b6a13bd 100644
}
can_skb_reserve(skb);
-@@ -965,7 +976,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+@@ -952,7 +965,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+ isotp_create_fframe(cf, so, ae);
+
+ /* start timeout for FC */
+- hrtimer_start(&so->txtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT);
++ hrtimer_sec = 1;
++ hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
++ HRTIMER_MODE_REL_SOFT);
+ }
+
+ /* send the first or only CAN frame */
+@@ -965,7 +980,12 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (err) {
pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
__func__, ERR_PTR(err));
- goto err_out;
++
++ /* no transmission -> no timeout monitoring */
++ if (hrtimer_sec)
++ hrtimer_cancel(&so->txtimer);
++
+ goto err_out_drop;
}
if (wait_tx_done) {
-@@ -978,6 +989,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+@@ -978,6 +998,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return size;
@@ -146567,7 +225749,183 @@ index df6968b28bf41..d2a430b6a13bd 100644
err_out:
so->tx.state = old_state;
if (so->tx.state == ISOTP_IDLE)
-@@ -1444,6 +1458,7 @@ static int isotp_init(struct sock *sk)
+@@ -991,26 +1014,29 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ {
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+- int err = 0;
+- int noblock;
++ struct isotp_sock *so = isotp_sk(sk);
++ int noblock = flags & MSG_DONTWAIT;
++ int ret = 0;
+
+- noblock = flags & MSG_DONTWAIT;
+- flags &= ~MSG_DONTWAIT;
++ if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))
++ return -EINVAL;
+
+- skb = skb_recv_datagram(sk, flags, noblock, &err);
++ if (!so->bound)
++ return -EADDRNOTAVAIL;
++
++ flags &= ~MSG_DONTWAIT;
++ skb = skb_recv_datagram(sk, flags, noblock, &ret);
+ if (!skb)
+- return err;
++ return ret;
+
+ if (size < skb->len)
+ msg->msg_flags |= MSG_TRUNC;
+ else
+ size = skb->len;
+
+- err = memcpy_to_msg(msg, skb->data, size);
+- if (err < 0) {
+- skb_free_datagram(sk, skb);
+- return err;
+- }
++ ret = memcpy_to_msg(msg, skb->data, size);
++ if (ret < 0)
++ goto out_err;
+
+ sock_recv_timestamp(msg, sk, skb);
+
+@@ -1020,9 +1046,13 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+ }
+
++ /* set length of return value */
++ ret = (flags & MSG_TRUNC) ? skb->len : size;
++
++out_err:
+ skb_free_datagram(sk, skb);
+
+- return size;
++ return ret;
+ }
+
+ static int isotp_release(struct socket *sock)
+@@ -1090,6 +1120,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
+ struct net *net = sock_net(sk);
+ int ifindex;
+ struct net_device *dev;
++ canid_t tx_id, rx_id;
+ int err = 0;
+ int notify_enetdown = 0;
+ int do_rx_reg = 1;
+@@ -1097,35 +1128,38 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
+ if (len < ISOTP_MIN_NAMELEN)
+ return -EINVAL;
+
+- if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
+- return -EADDRNOTAVAIL;
++ /* sanitize tx/rx CAN identifiers */
++ tx_id = addr->can_addr.tp.tx_id;
++ if (tx_id & CAN_EFF_FLAG)
++ tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
++ else
++ tx_id &= CAN_SFF_MASK;
++
++ rx_id = addr->can_addr.tp.rx_id;
++ if (rx_id & CAN_EFF_FLAG)
++ rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
++ else
++ rx_id &= CAN_SFF_MASK;
+
+ if (!addr->can_ifindex)
+ return -ENODEV;
+
+ lock_sock(sk);
+
++ if (so->bound) {
++ err = -EINVAL;
++ goto out;
++ }
++
+ /* do not register frame reception for functional addressing */
+ if (so->opt.flags & CAN_ISOTP_SF_BROADCAST)
+ do_rx_reg = 0;
+
+ /* do not validate rx address for functional addressing */
+- if (do_rx_reg) {
+- if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id) {
+- err = -EADDRNOTAVAIL;
+- goto out;
+- }
+-
+- if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
+- err = -EADDRNOTAVAIL;
+- goto out;
+- }
+- }
+-
+- if (so->bound && addr->can_ifindex == so->ifindex &&
+- addr->can_addr.tp.rx_id == so->rxid &&
+- addr->can_addr.tp.tx_id == so->txid)
++ if (do_rx_reg && rx_id == tx_id) {
++ err = -EADDRNOTAVAIL;
+ goto out;
++ }
+
+ dev = dev_get_by_index(net, addr->can_ifindex);
+ if (!dev) {
+@@ -1148,29 +1182,15 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
+ ifindex = dev->ifindex;
+
+ if (do_rx_reg)
+- can_rx_register(net, dev, addr->can_addr.tp.rx_id,
+- SINGLE_MASK(addr->can_addr.tp.rx_id),
++ can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
+ isotp_rcv, sk, "isotp", sk);
+
+ dev_put(dev);
+
+- if (so->bound && do_rx_reg) {
+- /* unregister old filter */
+- if (so->ifindex) {
+- dev = dev_get_by_index(net, so->ifindex);
+- if (dev) {
+- can_rx_unregister(net, dev, so->rxid,
+- SINGLE_MASK(so->rxid),
+- isotp_rcv, sk);
+- dev_put(dev);
+- }
+- }
+- }
+-
+ /* switch to new settings */
+ so->ifindex = ifindex;
+- so->rxid = addr->can_addr.tp.rx_id;
+- so->txid = addr->can_addr.tp.tx_id;
++ so->rxid = rx_id;
++ so->txid = tx_id;
+ so->bound = 1;
+
+ out:
+@@ -1224,6 +1244,14 @@ static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
+ /* no separate rx_ext_address is given => use ext_address */
+ if (!(so->opt.flags & CAN_ISOTP_RX_EXT_ADDR))
+ so->opt.rx_ext_address = so->opt.ext_address;
++
++ /* check for frame_txtime changes (0 => no changes) */
++ if (so->opt.frame_txtime) {
++ if (so->opt.frame_txtime == CAN_ISOTP_FRAME_TXTIME_ZERO)
++ so->frame_txtime = 0;
++ else
++ so->frame_txtime = so->opt.frame_txtime;
++ }
+ break;
+
+ case CAN_ISOTP_RECV_FC:
+@@ -1425,6 +1453,7 @@ static int isotp_init(struct sock *sk)
+ so->opt.rxpad_content = CAN_ISOTP_DEFAULT_PAD_CONTENT;
+ so->opt.txpad_content = CAN_ISOTP_DEFAULT_PAD_CONTENT;
+ so->opt.frame_txtime = CAN_ISOTP_DEFAULT_FRAME_TXTIME;
++ so->frame_txtime = CAN_ISOTP_DEFAULT_FRAME_TXTIME;
+ so->rxfc.bs = CAN_ISOTP_DEFAULT_RECV_BS;
+ so->rxfc.stmin = CAN_ISOTP_DEFAULT_RECV_STMIN;
+ so->rxfc.wftmax = CAN_ISOTP_DEFAULT_RECV_WFTMAX;
+@@ -1444,6 +1473,7 @@ static int isotp_init(struct sock *sk)
so->txtimer.function = isotp_tx_timer_handler;
init_waitqueue_head(&so->wait);
@@ -146631,6 +225989,491 @@ index 6c0a0ebdd024c..307ee1174a6e2 100644
if (j1939_tp_im_transmitter(skcb))
j1939_xtp_rx_abort(priv, skb, true);
+diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
+index ff8624a7c9643..f6b7436458aeb 100644
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -537,43 +537,6 @@ static void request_init(struct ceph_osd_request *req)
+ target_init(&req->r_t);
+ }
+
+-/*
+- * This is ugly, but it allows us to reuse linger registration and ping
+- * requests, keeping the structure of the code around send_linger{_ping}()
+- * reasonable. Setting up a min_nr=2 mempool for each linger request
+- * and dealing with copying ops (this blasts req only, watch op remains
+- * intact) isn't any better.
+- */
+-static void request_reinit(struct ceph_osd_request *req)
+-{
+- struct ceph_osd_client *osdc = req->r_osdc;
+- bool mempool = req->r_mempool;
+- unsigned int num_ops = req->r_num_ops;
+- u64 snapid = req->r_snapid;
+- struct ceph_snap_context *snapc = req->r_snapc;
+- bool linger = req->r_linger;
+- struct ceph_msg *request_msg = req->r_request;
+- struct ceph_msg *reply_msg = req->r_reply;
+-
+- dout("%s req %p\n", __func__, req);
+- WARN_ON(kref_read(&req->r_kref) != 1);
+- request_release_checks(req);
+-
+- WARN_ON(kref_read(&request_msg->kref) != 1);
+- WARN_ON(kref_read(&reply_msg->kref) != 1);
+- target_destroy(&req->r_t);
+-
+- request_init(req);
+- req->r_osdc = osdc;
+- req->r_mempool = mempool;
+- req->r_num_ops = num_ops;
+- req->r_snapid = snapid;
+- req->r_snapc = snapc;
+- req->r_linger = linger;
+- req->r_request = request_msg;
+- req->r_reply = reply_msg;
+-}
+-
+ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
+ struct ceph_snap_context *snapc,
+ unsigned int num_ops,
+@@ -918,14 +881,30 @@ EXPORT_SYMBOL(osd_req_op_xattr_init);
+ * @watch_opcode: CEPH_OSD_WATCH_OP_*
+ */
+ static void osd_req_op_watch_init(struct ceph_osd_request *req, int which,
+- u64 cookie, u8 watch_opcode)
++ u8 watch_opcode, u64 cookie, u32 gen)
+ {
+ struct ceph_osd_req_op *op;
+
+ op = osd_req_op_init(req, which, CEPH_OSD_OP_WATCH, 0);
+ op->watch.cookie = cookie;
+ op->watch.op = watch_opcode;
+- op->watch.gen = 0;
++ op->watch.gen = gen;
++}
++
++/*
++ * prot_ver, timeout and notify payload (may be empty) should already be
++ * encoded in @request_pl
++ */
++static void osd_req_op_notify_init(struct ceph_osd_request *req, int which,
++ u64 cookie, struct ceph_pagelist *request_pl)
++{
++ struct ceph_osd_req_op *op;
++
++ op = osd_req_op_init(req, which, CEPH_OSD_OP_NOTIFY, 0);
++ op->notify.cookie = cookie;
++
++ ceph_osd_data_pagelist_init(&op->notify.request_data, request_pl);
++ op->indata_len = request_pl->length;
+ }
+
+ /*
+@@ -2727,10 +2706,13 @@ static void linger_release(struct kref *kref)
+ WARN_ON(!list_empty(&lreq->pending_lworks));
+ WARN_ON(lreq->osd);
+
+- if (lreq->reg_req)
+- ceph_osdc_put_request(lreq->reg_req);
+- if (lreq->ping_req)
+- ceph_osdc_put_request(lreq->ping_req);
++ if (lreq->request_pl)
++ ceph_pagelist_release(lreq->request_pl);
++ if (lreq->notify_id_pages)
++ ceph_release_page_vector(lreq->notify_id_pages, 1);
++
++ ceph_osdc_put_request(lreq->reg_req);
++ ceph_osdc_put_request(lreq->ping_req);
+ target_destroy(&lreq->t);
+ kfree(lreq);
+ }
+@@ -2999,6 +2981,12 @@ static void linger_commit_cb(struct ceph_osd_request *req)
+ struct ceph_osd_linger_request *lreq = req->r_priv;
+
+ mutex_lock(&lreq->lock);
++ if (req != lreq->reg_req) {
++ dout("%s lreq %p linger_id %llu unknown req (%p != %p)\n",
++ __func__, lreq, lreq->linger_id, req, lreq->reg_req);
++ goto out;
++ }
++
+ dout("%s lreq %p linger_id %llu result %d\n", __func__, lreq,
+ lreq->linger_id, req->r_result);
+ linger_reg_commit_complete(lreq, req->r_result);
+@@ -3022,6 +3010,7 @@ static void linger_commit_cb(struct ceph_osd_request *req)
+ }
+ }
+
++out:
+ mutex_unlock(&lreq->lock);
+ linger_put(lreq);
+ }
+@@ -3044,6 +3033,12 @@ static void linger_reconnect_cb(struct ceph_osd_request *req)
+ struct ceph_osd_linger_request *lreq = req->r_priv;
+
+ mutex_lock(&lreq->lock);
++ if (req != lreq->reg_req) {
++ dout("%s lreq %p linger_id %llu unknown req (%p != %p)\n",
++ __func__, lreq, lreq->linger_id, req, lreq->reg_req);
++ goto out;
++ }
++
+ dout("%s lreq %p linger_id %llu result %d last_error %d\n", __func__,
+ lreq, lreq->linger_id, req->r_result, lreq->last_error);
+ if (req->r_result < 0) {
+@@ -3053,46 +3048,64 @@ static void linger_reconnect_cb(struct ceph_osd_request *req)
+ }
+ }
+
++out:
+ mutex_unlock(&lreq->lock);
+ linger_put(lreq);
+ }
+
+ static void send_linger(struct ceph_osd_linger_request *lreq)
+ {
+- struct ceph_osd_request *req = lreq->reg_req;
+- struct ceph_osd_req_op *op = &req->r_ops[0];
++ struct ceph_osd_client *osdc = lreq->osdc;
++ struct ceph_osd_request *req;
++ int ret;
+
+- verify_osdc_wrlocked(req->r_osdc);
++ verify_osdc_wrlocked(osdc);
++ mutex_lock(&lreq->lock);
+ dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id);
+
+- if (req->r_osd)
+- cancel_linger_request(req);
++ if (lreq->reg_req) {
++ if (lreq->reg_req->r_osd)
++ cancel_linger_request(lreq->reg_req);
++ ceph_osdc_put_request(lreq->reg_req);
++ }
++
++ req = ceph_osdc_alloc_request(osdc, NULL, 1, true, GFP_NOIO);
++ BUG_ON(!req);
+
+- request_reinit(req);
+ target_copy(&req->r_t, &lreq->t);
+ req->r_mtime = lreq->mtime;
+
+- mutex_lock(&lreq->lock);
+ if (lreq->is_watch && lreq->committed) {
+- WARN_ON(op->op != CEPH_OSD_OP_WATCH ||
+- op->watch.cookie != lreq->linger_id);
+- op->watch.op = CEPH_OSD_WATCH_OP_RECONNECT;
+- op->watch.gen = ++lreq->register_gen;
++ osd_req_op_watch_init(req, 0, CEPH_OSD_WATCH_OP_RECONNECT,
++ lreq->linger_id, ++lreq->register_gen);
+ dout("lreq %p reconnect register_gen %u\n", lreq,
+- op->watch.gen);
++ req->r_ops[0].watch.gen);
+ req->r_callback = linger_reconnect_cb;
+ } else {
+- if (!lreq->is_watch)
++ if (lreq->is_watch) {
++ osd_req_op_watch_init(req, 0, CEPH_OSD_WATCH_OP_WATCH,
++ lreq->linger_id, 0);
++ } else {
+ lreq->notify_id = 0;
+- else
+- WARN_ON(op->watch.op != CEPH_OSD_WATCH_OP_WATCH);
++
++ refcount_inc(&lreq->request_pl->refcnt);
++ osd_req_op_notify_init(req, 0, lreq->linger_id,
++ lreq->request_pl);
++ ceph_osd_data_pages_init(
++ osd_req_op_data(req, 0, notify, response_data),
++ lreq->notify_id_pages, PAGE_SIZE, 0, false, false);
++ }
+ dout("lreq %p register\n", lreq);
+ req->r_callback = linger_commit_cb;
+ }
+- mutex_unlock(&lreq->lock);
++
++ ret = ceph_osdc_alloc_messages(req, GFP_NOIO);
++ BUG_ON(ret);
+
+ req->r_priv = linger_get(lreq);
+ req->r_linger = true;
++ lreq->reg_req = req;
++ mutex_unlock(&lreq->lock);
+
+ submit_request(req, true);
+ }
+@@ -3102,6 +3115,12 @@ static void linger_ping_cb(struct ceph_osd_request *req)
+ struct ceph_osd_linger_request *lreq = req->r_priv;
+
+ mutex_lock(&lreq->lock);
++ if (req != lreq->ping_req) {
++ dout("%s lreq %p linger_id %llu unknown req (%p != %p)\n",
++ __func__, lreq, lreq->linger_id, req, lreq->ping_req);
++ goto out;
++ }
++
+ dout("%s lreq %p linger_id %llu result %d ping_sent %lu last_error %d\n",
+ __func__, lreq, lreq->linger_id, req->r_result, lreq->ping_sent,
+ lreq->last_error);
+@@ -3117,6 +3136,7 @@ static void linger_ping_cb(struct ceph_osd_request *req)
+ lreq->register_gen, req->r_ops[0].watch.gen);
+ }
+
++out:
+ mutex_unlock(&lreq->lock);
+ linger_put(lreq);
+ }
+@@ -3124,8 +3144,8 @@ static void linger_ping_cb(struct ceph_osd_request *req)
+ static void send_linger_ping(struct ceph_osd_linger_request *lreq)
+ {
+ struct ceph_osd_client *osdc = lreq->osdc;
+- struct ceph_osd_request *req = lreq->ping_req;
+- struct ceph_osd_req_op *op = &req->r_ops[0];
++ struct ceph_osd_request *req;
++ int ret;
+
+ if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD)) {
+ dout("%s PAUSERD\n", __func__);
+@@ -3137,19 +3157,26 @@ static void send_linger_ping(struct ceph_osd_linger_request *lreq)
+ __func__, lreq, lreq->linger_id, lreq->ping_sent,
+ lreq->register_gen);
+
+- if (req->r_osd)
+- cancel_linger_request(req);
++ if (lreq->ping_req) {
++ if (lreq->ping_req->r_osd)
++ cancel_linger_request(lreq->ping_req);
++ ceph_osdc_put_request(lreq->ping_req);
++ }
+
+- request_reinit(req);
+- target_copy(&req->r_t, &lreq->t);
++ req = ceph_osdc_alloc_request(osdc, NULL, 1, true, GFP_NOIO);
++ BUG_ON(!req);
+
+- WARN_ON(op->op != CEPH_OSD_OP_WATCH ||
+- op->watch.cookie != lreq->linger_id ||
+- op->watch.op != CEPH_OSD_WATCH_OP_PING);
+- op->watch.gen = lreq->register_gen;
++ target_copy(&req->r_t, &lreq->t);
++ osd_req_op_watch_init(req, 0, CEPH_OSD_WATCH_OP_PING, lreq->linger_id,
++ lreq->register_gen);
+ req->r_callback = linger_ping_cb;
++
++ ret = ceph_osdc_alloc_messages(req, GFP_NOIO);
++ BUG_ON(ret);
++
+ req->r_priv = linger_get(lreq);
+ req->r_linger = true;
++ lreq->ping_req = req;
+
+ ceph_osdc_get_request(req);
+ account_request(req);
+@@ -3165,12 +3192,6 @@ static void linger_submit(struct ceph_osd_linger_request *lreq)
+
+ down_write(&osdc->lock);
+ linger_register(lreq);
+- if (lreq->is_watch) {
+- lreq->reg_req->r_ops[0].watch.cookie = lreq->linger_id;
+- lreq->ping_req->r_ops[0].watch.cookie = lreq->linger_id;
+- } else {
+- lreq->reg_req->r_ops[0].notify.cookie = lreq->linger_id;
+- }
+
+ calc_target(osdc, &lreq->t, false);
+ osd = lookup_create_osd(osdc, lreq->t.osd, true);
+@@ -3202,9 +3223,9 @@ static void cancel_linger_map_check(struct ceph_osd_linger_request *lreq)
+ */
+ static void __linger_cancel(struct ceph_osd_linger_request *lreq)
+ {
+- if (lreq->is_watch && lreq->ping_req->r_osd)
++ if (lreq->ping_req && lreq->ping_req->r_osd)
+ cancel_linger_request(lreq->ping_req);
+- if (lreq->reg_req->r_osd)
++ if (lreq->reg_req && lreq->reg_req->r_osd)
+ cancel_linger_request(lreq->reg_req);
+ cancel_linger_map_check(lreq);
+ unlink_linger(lreq->osd, lreq);
+@@ -4653,43 +4674,6 @@ again:
+ }
+ EXPORT_SYMBOL(ceph_osdc_sync);
+
+-static struct ceph_osd_request *
+-alloc_linger_request(struct ceph_osd_linger_request *lreq)
+-{
+- struct ceph_osd_request *req;
+-
+- req = ceph_osdc_alloc_request(lreq->osdc, NULL, 1, false, GFP_NOIO);
+- if (!req)
+- return NULL;
+-
+- ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid);
+- ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
+- return req;
+-}
+-
+-static struct ceph_osd_request *
+-alloc_watch_request(struct ceph_osd_linger_request *lreq, u8 watch_opcode)
+-{
+- struct ceph_osd_request *req;
+-
+- req = alloc_linger_request(lreq);
+- if (!req)
+- return NULL;
+-
+- /*
+- * Pass 0 for cookie because we don't know it yet, it will be
+- * filled in by linger_submit().
+- */
+- osd_req_op_watch_init(req, 0, 0, watch_opcode);
+-
+- if (ceph_osdc_alloc_messages(req, GFP_NOIO)) {
+- ceph_osdc_put_request(req);
+- return NULL;
+- }
+-
+- return req;
+-}
+-
+ /*
+ * Returns a handle, caller owns a ref.
+ */
+@@ -4719,18 +4703,6 @@ ceph_osdc_watch(struct ceph_osd_client *osdc,
+ lreq->t.flags = CEPH_OSD_FLAG_WRITE;
+ ktime_get_real_ts64(&lreq->mtime);
+
+- lreq->reg_req = alloc_watch_request(lreq, CEPH_OSD_WATCH_OP_WATCH);
+- if (!lreq->reg_req) {
+- ret = -ENOMEM;
+- goto err_put_lreq;
+- }
+-
+- lreq->ping_req = alloc_watch_request(lreq, CEPH_OSD_WATCH_OP_PING);
+- if (!lreq->ping_req) {
+- ret = -ENOMEM;
+- goto err_put_lreq;
+- }
+-
+ linger_submit(lreq);
+ ret = linger_reg_commit_wait(lreq);
+ if (ret) {
+@@ -4768,8 +4740,8 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc,
+ ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
+ req->r_flags = CEPH_OSD_FLAG_WRITE;
+ ktime_get_real_ts64(&req->r_mtime);
+- osd_req_op_watch_init(req, 0, lreq->linger_id,
+- CEPH_OSD_WATCH_OP_UNWATCH);
++ osd_req_op_watch_init(req, 0, CEPH_OSD_WATCH_OP_UNWATCH,
++ lreq->linger_id, 0);
+
+ ret = ceph_osdc_alloc_messages(req, GFP_NOIO);
+ if (ret)
+@@ -4855,35 +4827,6 @@ out_put_req:
+ }
+ EXPORT_SYMBOL(ceph_osdc_notify_ack);
+
+-static int osd_req_op_notify_init(struct ceph_osd_request *req, int which,
+- u64 cookie, u32 prot_ver, u32 timeout,
+- void *payload, u32 payload_len)
+-{
+- struct ceph_osd_req_op *op;
+- struct ceph_pagelist *pl;
+- int ret;
+-
+- op = osd_req_op_init(req, which, CEPH_OSD_OP_NOTIFY, 0);
+- op->notify.cookie = cookie;
+-
+- pl = ceph_pagelist_alloc(GFP_NOIO);
+- if (!pl)
+- return -ENOMEM;
+-
+- ret = ceph_pagelist_encode_32(pl, 1); /* prot_ver */
+- ret |= ceph_pagelist_encode_32(pl, timeout);
+- ret |= ceph_pagelist_encode_32(pl, payload_len);
+- ret |= ceph_pagelist_append(pl, payload, payload_len);
+- if (ret) {
+- ceph_pagelist_release(pl);
+- return -ENOMEM;
+- }
+-
+- ceph_osd_data_pagelist_init(&op->notify.request_data, pl);
+- op->indata_len = pl->length;
+- return 0;
+-}
+-
+ /*
+ * @timeout: in seconds
+ *
+@@ -4902,7 +4845,6 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc,
+ size_t *preply_len)
+ {
+ struct ceph_osd_linger_request *lreq;
+- struct page **pages;
+ int ret;
+
+ WARN_ON(!timeout);
+@@ -4915,41 +4857,35 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc,
+ if (!lreq)
+ return -ENOMEM;
+
+- lreq->preply_pages = preply_pages;
+- lreq->preply_len = preply_len;
+-
+- ceph_oid_copy(&lreq->t.base_oid, oid);
+- ceph_oloc_copy(&lreq->t.base_oloc, oloc);
+- lreq->t.flags = CEPH_OSD_FLAG_READ;
+-
+- lreq->reg_req = alloc_linger_request(lreq);
+- if (!lreq->reg_req) {
++ lreq->request_pl = ceph_pagelist_alloc(GFP_NOIO);
++ if (!lreq->request_pl) {
+ ret = -ENOMEM;
+ goto out_put_lreq;
+ }
+
+- /*
+- * Pass 0 for cookie because we don't know it yet, it will be
+- * filled in by linger_submit().
+- */
+- ret = osd_req_op_notify_init(lreq->reg_req, 0, 0, 1, timeout,
+- payload, payload_len);
+- if (ret)
++ ret = ceph_pagelist_encode_32(lreq->request_pl, 1); /* prot_ver */
++ ret |= ceph_pagelist_encode_32(lreq->request_pl, timeout);
++ ret |= ceph_pagelist_encode_32(lreq->request_pl, payload_len);
++ ret |= ceph_pagelist_append(lreq->request_pl, payload, payload_len);
++ if (ret) {
++ ret = -ENOMEM;
+ goto out_put_lreq;
++ }
+
+ /* for notify_id */
+- pages = ceph_alloc_page_vector(1, GFP_NOIO);
+- if (IS_ERR(pages)) {
+- ret = PTR_ERR(pages);
++ lreq->notify_id_pages = ceph_alloc_page_vector(1, GFP_NOIO);
++ if (IS_ERR(lreq->notify_id_pages)) {
++ ret = PTR_ERR(lreq->notify_id_pages);
++ lreq->notify_id_pages = NULL;
+ goto out_put_lreq;
+ }
+- ceph_osd_data_pages_init(osd_req_op_data(lreq->reg_req, 0, notify,
+- response_data),
+- pages, PAGE_SIZE, 0, false, true);
+
+- ret = ceph_osdc_alloc_messages(lreq->reg_req, GFP_NOIO);
+- if (ret)
+- goto out_put_lreq;
++ lreq->preply_pages = preply_pages;
++ lreq->preply_len = preply_len;
++
++ ceph_oid_copy(&lreq->t.base_oid, oid);
++ ceph_oloc_copy(&lreq->t.base_oloc, oloc);
++ lreq->t.flags = CEPH_OSD_FLAG_READ;
+
+ linger_submit(lreq);
+ ret = linger_reg_commit_wait(lreq);
diff --git a/net/core/Makefile b/net/core/Makefile
index 35ced6201814c..4268846f2f475 100644
--- a/net/core/Makefile
@@ -146640,10 +226483,36 @@ index 35ced6201814c..4268846f2f475 100644
obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
+obj-$(CONFIG_OF) += of_net.o
+diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c
+index 68d2cbf8331ac..ea61dfe19c869 100644
+--- a/net/core/bpf_sk_storage.c
++++ b/net/core/bpf_sk_storage.c
+@@ -929,7 +929,7 @@ static struct bpf_iter_reg bpf_sk_storage_map_reg_info = {
+ { offsetof(struct bpf_iter__bpf_sk_storage_map, sk),
+ PTR_TO_BTF_ID_OR_NULL },
+ { offsetof(struct bpf_iter__bpf_sk_storage_map, value),
+- PTR_TO_RDWR_BUF_OR_NULL },
++ PTR_TO_BUF | PTR_MAYBE_NULL },
+ },
+ .seq_info = &iter_seq_info,
+ };
diff --git a/net/core/dev.c b/net/core/dev.c
-index eb3a366bf212c..33dc2a3ff7d78 100644
+index eb3a366bf212c..5907212c00f37 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
+@@ -741,11 +741,11 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+ const struct net_device *last_dev;
+ struct net_device_path_ctx ctx = {
+ .dev = dev,
+- .daddr = daddr,
+ };
+ struct net_device_path *path;
+ int ret = 0;
+
++ memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
+ stack->num_paths = 0;
+ while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
+ last_dev = ctx.dev;
@@ -2921,6 +2921,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
if (dev->num_tc)
netif_setup_tc(dev, txq);
@@ -146700,6 +226569,16 @@ index eb3a366bf212c..33dc2a3ff7d78 100644
if (old_prog == new_prog) {
/* no-op, don't disturb drivers */
bpf_prog_put(new_prog);
+@@ -11367,8 +11378,7 @@ static int __net_init netdev_init(struct net *net)
+ BUILD_BUG_ON(GRO_HASH_BUCKETS >
+ 8 * sizeof_field(struct napi_struct, gro_bitmask));
+
+- if (net != &init_net)
+- INIT_LIST_HEAD(&net->dev_base_head);
++ INIT_LIST_HEAD(&net->dev_base_head);
+
+ net->dev_name_head = netdev_create_hash();
+ if (net->dev_name_head == NULL)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index a856ae401ea5c..db76c55e1a6d7 100644
--- a/net/core/devlink.c
@@ -146819,9 +226698,39 @@ index 79df7cd9dbc16..1bb567a3b329c 100644
if (err != -EAGAIN) {
diff --git a/net/core/filter.c b/net/core/filter.c
-index 2e32cee2c4690..76e406965b6f9 100644
+index 2e32cee2c4690..821278b906b71 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
+@@ -1713,7 +1713,7 @@ static const struct bpf_func_proto bpf_skb_store_bytes_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE,
+ .arg5_type = ARG_ANYTHING,
+ };
+@@ -2018,9 +2018,9 @@ static const struct bpf_func_proto bpf_csum_diff_proto = {
+ .gpl_only = false,
+ .pkt_access = true,
+ .ret_type = RET_INTEGER,
+- .arg1_type = ARG_PTR_TO_MEM_OR_NULL,
++ .arg1_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg2_type = ARG_CONST_SIZE_OR_ZERO,
+- .arg3_type = ARG_PTR_TO_MEM_OR_NULL,
++ .arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg5_type = ARG_ANYTHING,
+ };
+@@ -2541,7 +2541,7 @@ static const struct bpf_func_proto bpf_redirect_neigh_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_ANYTHING,
+- .arg2_type = ARG_PTR_TO_MEM_OR_NULL,
++ .arg2_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ .arg4_type = ARG_ANYTHING,
+ };
@@ -2711,6 +2711,9 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
if (unlikely(flags))
return -EINVAL;
@@ -146832,6 +226741,60 @@ index 2e32cee2c4690..76e406965b6f9 100644
/* First find the starting scatterlist element */
i = msg->sg.start;
do {
+@@ -4174,7 +4177,7 @@ static const struct bpf_func_proto bpf_skb_event_output_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -4188,7 +4191,7 @@ const struct bpf_func_proto bpf_skb_output_proto = {
+ .arg1_btf_id = &bpf_skb_output_btf_ids[0],
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -4371,7 +4374,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ };
+@@ -4397,7 +4400,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ };
+
+@@ -4567,7 +4570,7 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
+@@ -4581,7 +4584,7 @@ const struct bpf_func_proto bpf_xdp_output_proto = {
+ .arg1_btf_id = &bpf_xdp_output_btf_ids[0],
+ .arg2_type = ARG_CONST_MAP_PTR,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE_OR_ZERO,
+ };
+
@@ -4742,12 +4745,14 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case SO_RCVBUF:
@@ -146847,7 +226810,231 @@ index 2e32cee2c4690..76e406965b6f9 100644
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
WRITE_ONCE(sk->sk_sndbuf,
max_t(int, val * 2, SOCK_MIN_SNDBUF));
-@@ -7162,6 +7167,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+@@ -5067,7 +5072,7 @@ const struct bpf_func_proto bpf_sk_setsockopt_proto = {
+ .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE,
+ };
+
+@@ -5101,7 +5106,7 @@ static const struct bpf_func_proto bpf_sock_addr_setsockopt_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE,
+ };
+
+@@ -5135,7 +5140,7 @@ static const struct bpf_func_proto bpf_sock_ops_setsockopt_proto = {
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE,
+ };
+
+@@ -5310,7 +5315,7 @@ static const struct bpf_func_proto bpf_bind_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ };
+
+@@ -5898,7 +5903,7 @@ static const struct bpf_func_proto bpf_lwt_in_push_encap_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE
+ };
+
+@@ -5908,7 +5913,7 @@ static const struct bpf_func_proto bpf_lwt_xmit_push_encap_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE
+ };
+
+@@ -5951,7 +5956,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE
+ };
+
+@@ -6039,7 +6044,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_action_proto = {
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+- .arg3_type = ARG_PTR_TO_MEM,
++ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg4_type = ARG_CONST_SIZE
+ };
+
+@@ -6264,7 +6269,7 @@ static const struct bpf_func_proto bpf_skc_lookup_tcp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6283,7 +6288,7 @@ static const struct bpf_func_proto bpf_sk_lookup_tcp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6302,7 +6307,7 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6339,7 +6344,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6362,7 +6367,7 @@ static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6385,7 +6390,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = {
+ .pkt_access = true,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6404,7 +6409,7 @@ static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = {
+ .gpl_only = false,
+ .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6423,7 +6428,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = {
+ .gpl_only = false,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6442,7 +6447,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = {
+ .gpl_only = false,
+ .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+@@ -6714,24 +6719,33 @@ BPF_CALL_5(bpf_tcp_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len
+ if (!th->ack || th->rst || th->syn)
+ return -ENOENT;
+
++ if (unlikely(iph_len < sizeof(struct iphdr)))
++ return -EINVAL;
++
+ if (tcp_synq_no_recent_overflow(sk))
+ return -ENOENT;
+
+ cookie = ntohl(th->ack_seq) - 1;
+
+- switch (sk->sk_family) {
+- case AF_INET:
+- if (unlikely(iph_len < sizeof(struct iphdr)))
++ /* Both struct iphdr and struct ipv6hdr have the version field at the
++ * same offset so we can cast to the shorter header (struct iphdr).
++ */
++ switch (((struct iphdr *)iph)->version) {
++ case 4:
++ if (sk->sk_family == AF_INET6 && ipv6_only_sock(sk))
+ return -EINVAL;
+
+ ret = __cookie_v4_check((struct iphdr *)iph, th, cookie);
+ break;
+
+ #if IS_BUILTIN(CONFIG_IPV6)
+- case AF_INET6:
++ case 6:
+ if (unlikely(iph_len < sizeof(struct ipv6hdr)))
+ return -EINVAL;
+
++ if (sk->sk_family != AF_INET6)
++ return -EINVAL;
++
+ ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie);
+ break;
+ #endif /* CONFIG_IPV6 */
+@@ -6755,9 +6769,9 @@ static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = {
+ .pkt_access = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE,
+ };
+
+@@ -6824,9 +6838,9 @@ static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = {
+ .pkt_access = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+- .arg4_type = ARG_PTR_TO_MEM,
++ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg5_type = ARG_CONST_SIZE,
+ };
+
+@@ -7055,7 +7069,7 @@ static const struct bpf_func_proto bpf_sock_ops_store_hdr_opt_proto = {
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+- .arg2_type = ARG_PTR_TO_MEM,
++ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ };
+@@ -7162,6 +7176,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
#endif
case BPF_FUNC_sk_storage_get:
return &bpf_sk_storage_get_cg_sock_proto;
@@ -146856,7 +227043,38 @@ index 2e32cee2c4690..76e406965b6f9 100644
default:
return bpf_base_func_proto(func_id);
}
-@@ -8174,9 +8181,9 @@ void bpf_warn_invalid_xdp_action(u32 act)
+@@ -7959,6 +7975,7 @@ bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
+ struct bpf_insn_access_aux *info)
+ {
+ const int size_default = sizeof(__u32);
++ int field_size;
+
+ if (off < 0 || off >= sizeof(struct bpf_sock))
+ return false;
+@@ -7970,7 +7987,6 @@ bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
+ case offsetof(struct bpf_sock, family):
+ case offsetof(struct bpf_sock, type):
+ case offsetof(struct bpf_sock, protocol):
+- case offsetof(struct bpf_sock, dst_port):
+ case offsetof(struct bpf_sock, src_port):
+ case offsetof(struct bpf_sock, rx_queue_mapping):
+ case bpf_ctx_range(struct bpf_sock, src_ip4):
+@@ -7979,6 +7995,14 @@ bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
+ case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
+ bpf_ctx_record_field_size(info, size_default);
+ return bpf_ctx_narrow_access_ok(off, size, size_default);
++ case bpf_ctx_range(struct bpf_sock, dst_port):
++ field_size = size == size_default ?
++ size_default : sizeof_field(struct bpf_sock, dst_port);
++ bpf_ctx_record_field_size(info, field_size);
++ return bpf_ctx_narrow_access_ok(off, size, field_size);
++ case offsetofend(struct bpf_sock, dst_port) ...
++ offsetof(struct bpf_sock, dst_ip4) - 1:
++ return false;
+ }
+
+ return size == size_default;
+@@ -8174,9 +8198,9 @@ void bpf_warn_invalid_xdp_action(u32 act)
{
const u32 act_max = XDP_REDIRECT;
@@ -146869,7 +227087,7 @@ index 2e32cee2c4690..76e406965b6f9 100644
}
EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
-@@ -9735,22 +9742,46 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
+@@ -9735,22 +9759,46 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
static struct bpf_insn *bpf_convert_data_end_access(const struct bpf_insn *si,
struct bpf_insn *insn)
{
@@ -146922,7 +227140,7 @@ index 2e32cee2c4690..76e406965b6f9 100644
return insn;
}
-@@ -9761,11 +9792,33 @@ static u32 sk_skb_convert_ctx_access(enum bpf_access_type type,
+@@ -9761,11 +9809,33 @@ static u32 sk_skb_convert_ctx_access(enum bpf_access_type type,
struct bpf_prog *prog, u32 *target_size)
{
struct bpf_insn *insn = insn_buf;
@@ -146956,7 +227174,7 @@ index 2e32cee2c4690..76e406965b6f9 100644
default:
return bpf_convert_ctx_access(type, si, insn_buf, prog,
target_size);
-@@ -10260,6 +10313,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id,
+@@ -10260,6 +10330,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id,
return &sk_reuseport_load_bytes_relative_proto;
case BPF_FUNC_get_socket_cookie:
return &bpf_get_socket_ptr_cookie_proto;
@@ -146965,7 +227183,17 @@ index 2e32cee2c4690..76e406965b6f9 100644
default:
return bpf_base_func_proto(func_id);
}
-@@ -10741,6 +10796,8 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id)
+@@ -10468,7 +10540,8 @@ static bool sk_lookup_is_valid_access(int off, int size,
+ case bpf_ctx_range(struct bpf_sk_lookup, local_ip4):
+ case bpf_ctx_range_till(struct bpf_sk_lookup, remote_ip6[0], remote_ip6[3]):
+ case bpf_ctx_range_till(struct bpf_sk_lookup, local_ip6[0], local_ip6[3]):
+- case bpf_ctx_range(struct bpf_sk_lookup, remote_port):
++ case offsetof(struct bpf_sk_lookup, remote_port) ...
++ offsetof(struct bpf_sk_lookup, local_ip4) - 1:
+ case bpf_ctx_range(struct bpf_sk_lookup, local_port):
+ bpf_ctx_record_field_size(info, sizeof(__u32));
+ return bpf_ctx_narrow_access_ok(off, size, sizeof(__u32));
+@@ -10741,6 +10814,8 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id)
case BPF_FUNC_skc_to_udp6_sock:
func = &bpf_skc_to_udp6_sock_proto;
break;
@@ -146975,7 +227203,7 @@ index 2e32cee2c4690..76e406965b6f9 100644
return bpf_base_func_proto(func_id);
}
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
-index bac0184cf3de7..edffdaa875f1f 100644
+index bac0184cf3de7..bc50bd331d5b6 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -238,7 +238,7 @@ void
@@ -146995,6 +227223,47 @@ index bac0184cf3de7..edffdaa875f1f 100644
return;
}
+@@ -1180,6 +1181,7 @@ proto_again:
+ VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ }
+ key_vlan->vlan_tpid = saved_vlan_tpid;
++ key_vlan->vlan_eth_type = proto;
+ }
+
+ fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
+diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
+index 2f7940bcf7151..3fd207fe1284a 100644
+--- a/net/core/lwt_bpf.c
++++ b/net/core/lwt_bpf.c
+@@ -158,10 +158,8 @@ static int bpf_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+ return dst->lwtstate->orig_output(net, sk, skb);
+ }
+
+-static int xmit_check_hhlen(struct sk_buff *skb)
++static int xmit_check_hhlen(struct sk_buff *skb, int hh_len)
+ {
+- int hh_len = skb_dst(skb)->dev->hard_header_len;
+-
+ if (skb_headroom(skb) < hh_len) {
+ int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb));
+
+@@ -273,6 +271,7 @@ static int bpf_xmit(struct sk_buff *skb)
+
+ bpf = bpf_lwt_lwtunnel(dst->lwtstate);
+ if (bpf->xmit.prog) {
++ int hh_len = dst->dev->hard_header_len;
+ __be16 proto = skb->protocol;
+ int ret;
+
+@@ -290,7 +289,7 @@ static int bpf_xmit(struct sk_buff *skb)
+ /* If the header was expanded, headroom might be too
+ * small for L2 header to come, expand as needed.
+ */
+- ret = xmit_check_hhlen(skb);
++ ret = xmit_check_hhlen(skb, hh_len);
+ if (unlikely(ret))
+ return ret;
+
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 2820aca2173a8..9ccd64e8a666a 100644
--- a/net/core/lwtunnel.c
@@ -147226,7 +227495,7 @@ index d8b9dbabd4a43..88cc0ad7d386e 100644
seq_puts(seq, "ALL ");
else
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
-index b2e49eb7001d6..d7f9ee830d34c 100644
+index b2e49eb7001d6..9e5657f632453 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -175,6 +175,14 @@ static int change_carrier(struct net_device *dev, unsigned long new_carrier)
@@ -147244,7 +227513,7 @@ index b2e49eb7001d6..d7f9ee830d34c 100644
return netdev_store(dev, attr, buf, len, change_carrier);
}
-@@ -196,6 +204,12 @@ static ssize_t speed_show(struct device *dev,
+@@ -196,10 +204,16 @@ static ssize_t speed_show(struct device *dev,
struct net_device *netdev = to_net_dev(dev);
int ret = -EINVAL;
@@ -147257,6 +227526,11 @@ index b2e49eb7001d6..d7f9ee830d34c 100644
if (!rtnl_trylock())
return restart_syscall();
+- if (netif_running(netdev)) {
++ if (netif_running(netdev) && netif_device_present(netdev)) {
+ struct ethtool_link_ksettings cmd;
+
+ if (!__ethtool_get_link_ksettings(netdev, &cmd))
@@ -216,6 +230,12 @@ static ssize_t duplex_show(struct device *dev,
struct net_device *netdev = to_net_dev(dev);
int ret = -EINVAL;
@@ -147360,10 +227634,25 @@ index b2e49eb7001d6..d7f9ee830d34c 100644
{
for (; dev; dev = dev->parent) {
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
-index a448a9b5bb2d6..9702d2b0d9207 100644
+index a448a9b5bb2d6..9745cb6fdf516 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
-@@ -164,8 +164,10 @@ static void ops_exit_list(const struct pernet_operations *ops,
+@@ -44,13 +44,7 @@ EXPORT_SYMBOL_GPL(net_rwsem);
+ static struct key_tag init_net_key_domain = { .usage = REFCOUNT_INIT(1) };
+ #endif
+
+-struct net init_net = {
+- .ns.count = REFCOUNT_INIT(1),
+- .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
+-#ifdef CONFIG_KEYS
+- .key_domain = &init_net_key_domain,
+-#endif
+-};
++struct net init_net;
+ EXPORT_SYMBOL(init_net);
+
+ static bool init_net_initialized;
+@@ -164,8 +158,10 @@ static void ops_exit_list(const struct pernet_operations *ops,
{
struct net *net;
if (ops->exit) {
@@ -147375,7 +227664,7 @@ index a448a9b5bb2d6..9702d2b0d9207 100644
}
if (ops->exit_batch)
ops->exit_batch(net_exit_list);
-@@ -473,7 +475,9 @@ struct net *copy_net_ns(unsigned long flags,
+@@ -473,7 +469,9 @@ struct net *copy_net_ns(unsigned long flags,
if (rv < 0) {
put_userns:
@@ -147385,7 +227674,7 @@ index a448a9b5bb2d6..9702d2b0d9207 100644
put_user_ns(user_ns);
net_free(net);
dec_ucounts:
-@@ -605,7 +609,9 @@ static void cleanup_net(struct work_struct *work)
+@@ -605,7 +603,9 @@ static void cleanup_net(struct work_struct *work)
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
list_del_init(&net->exit_list);
dec_net_namespaces(net->ucounts);
@@ -147395,6 +227684,38 @@ index a448a9b5bb2d6..9702d2b0d9207 100644
put_user_ns(net->user_ns);
net_free(net);
}
+@@ -1075,7 +1075,7 @@ out:
+ rtnl_set_sk_err(net, RTNLGRP_NSID, err);
+ }
+
+-static int __init net_ns_init(void)
++void __init net_ns_init(void)
+ {
+ struct net_generic *ng;
+
+@@ -1096,6 +1096,9 @@ static int __init net_ns_init(void)
+
+ rcu_assign_pointer(init_net.gen, ng);
+
++#ifdef CONFIG_KEYS
++ init_net.key_domain = &init_net_key_domain;
++#endif
+ down_write(&pernet_ops_rwsem);
+ if (setup_net(&init_net, &init_user_ns))
+ panic("Could not setup the initial network namespace");
+@@ -1110,12 +1113,8 @@ static int __init net_ns_init(void)
+ RTNL_FLAG_DOIT_UNLOCKED);
+ rtnl_register(PF_UNSPEC, RTM_GETNSID, rtnl_net_getid, rtnl_net_dumpid,
+ RTNL_FLAG_DOIT_UNLOCKED);
+-
+- return 0;
+ }
+
+-pure_initcall(net_ns_init);
+-
+ static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list)
+ {
+ ops_pre_exit_list(ops, net_exit_list);
diff --git a/net/core/of_net.c b/net/core/of_net.c
new file mode 100644
index 0000000000000..dbac3a172a11e
@@ -147547,7 +227868,7 @@ index 0000000000000..dbac3a172a11e
+}
+EXPORT_SYMBOL(of_get_mac_address);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index 8ccce85562a1d..91d7a5a5a08d0 100644
+index 8ccce85562a1d..9c0e8ccf9bc58 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1698,6 +1698,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
@@ -147597,10 +227918,97 @@ index 8ccce85562a1d..91d7a5a5a08d0 100644
if (dev) {
master_dev = netdev_master_upper_dev_get(dev);
if (master_dev)
+@@ -3627,13 +3631,24 @@ static int rtnl_alt_ifname(int cmd, struct net_device *dev, struct nlattr *attr,
+ bool *changed, struct netlink_ext_ack *extack)
+ {
+ char *alt_ifname;
++ size_t size;
+ int err;
+
+ err = nla_validate(attr, attr->nla_len, IFLA_MAX, ifla_policy, extack);
+ if (err)
+ return err;
+
+- alt_ifname = nla_strdup(attr, GFP_KERNEL);
++ if (cmd == RTM_NEWLINKPROP) {
++ size = rtnl_prop_list_size(dev);
++ size += nla_total_size(ALTIFNAMSIZ);
++ if (size >= U16_MAX) {
++ NL_SET_ERR_MSG(extack,
++ "effective property list too long");
++ return -EINVAL;
++ }
++ }
++
++ alt_ifname = nla_strdup(attr, GFP_KERNEL_ACCOUNT);
+ if (!alt_ifname)
+ return -ENOMEM;
+
+diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
+index b5bc680d47553..7131cd1fb2ad5 100644
+--- a/net/core/secure_seq.c
++++ b/net/core/secure_seq.c
+@@ -22,6 +22,8 @@
+ static siphash_key_t net_secret __read_mostly;
+ static siphash_key_t ts_secret __read_mostly;
+
++#define EPHEMERAL_PORT_SHUFFLE_PERIOD (10 * HZ)
++
+ static __always_inline void net_secret_init(void)
+ {
+ net_get_random_once(&net_secret, sizeof(net_secret));
+@@ -94,17 +96,19 @@ u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
+ }
+ EXPORT_SYMBOL(secure_tcpv6_seq);
+
+-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
++u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+ __be16 dport)
+ {
+ const struct {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
++ unsigned int timeseed;
+ __be16 dport;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .saddr = *(struct in6_addr *)saddr,
+ .daddr = *(struct in6_addr *)daddr,
+- .dport = dport
++ .timeseed = jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD,
++ .dport = dport,
+ };
+ net_secret_init();
+ return siphash(&combined, offsetofend(typeof(combined), dport),
+@@ -142,11 +146,13 @@ u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
+ }
+ EXPORT_SYMBOL_GPL(secure_tcp_seq);
+
+-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
++u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
+ {
+ net_secret_init();
+- return siphash_3u32((__force u32)saddr, (__force u32)daddr,
+- (__force u16)dport, &net_secret);
++ return siphash_4u32((__force u32)saddr, (__force u32)daddr,
++ (__force u16)dport,
++ jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD,
++ &net_secret);
+ }
+ EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
+ #endif
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index fe9358437380c..6cb7ec85c9a1f 100644
+index fe9358437380c..7ef0f5a8ab036 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
+@@ -203,7 +203,7 @@ static void __build_skb_around(struct sk_buff *skb, void *data,
+ skb->head = data;
+ skb->data = data;
+ skb_reset_tail_pointer(skb);
+- skb->end = skb->tail + size;
++ skb_set_end_offset(skb, size);
+ skb->mac_header = (typeof(skb->mac_header))~0U;
+ skb->transport_header = (typeof(skb->transport_header))~0U;
+
@@ -832,7 +832,7 @@ void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt)
ntohs(skb->protocol), skb->pkt_type, skb->skb_iif);
@@ -147610,7 +228018,60 @@ index fe9358437380c..6cb7ec85c9a1f 100644
level, dev->name, &dev->features);
if (sk)
printk("%ssk family=%hu type=%u proto=%u\n",
-@@ -2254,7 +2254,7 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta)
+@@ -1738,11 +1738,10 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
+ skb->head = data;
+ skb->head_frag = 0;
+ skb->data += off;
++
++ skb_set_end_offset(skb, size);
+ #ifdef NET_SKBUFF_DATA_USES_OFFSET
+- skb->end = size;
+ off = nhead;
+-#else
+- skb->end = skb->head + size;
+ #endif
+ skb->tail += off;
+ skb_headers_offset_update(skb, nhead);
+@@ -1790,6 +1789,38 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
+ }
+ EXPORT_SYMBOL(skb_realloc_headroom);
+
++int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri)
++{
++ unsigned int saved_end_offset, saved_truesize;
++ struct skb_shared_info *shinfo;
++ int res;
++
++ saved_end_offset = skb_end_offset(skb);
++ saved_truesize = skb->truesize;
++
++ res = pskb_expand_head(skb, 0, 0, pri);
++ if (res)
++ return res;
++
++ skb->truesize = saved_truesize;
++
++ if (likely(skb_end_offset(skb) == saved_end_offset))
++ return 0;
++
++ shinfo = skb_shinfo(skb);
++
++ /* We are about to change back skb->end,
++ * we need to move skb_shinfo() to its new location.
++ */
++ memmove(skb->head + saved_end_offset,
++ shinfo,
++ offsetof(struct skb_shared_info, frags[shinfo->nr_frags]));
++
++ skb_set_end_offset(skb, saved_end_offset);
++
++ return 0;
++}
++
+ /**
+ * skb_expand_head - reallocate header of &sk_buff
+ * @skb: buffer to reallocate
+@@ -2254,7 +2285,7 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta)
/* Free pulled out fragments. */
while ((list = skb_shinfo(skb)->frag_list) != insp) {
skb_shinfo(skb)->frag_list = list->next;
@@ -147619,7 +228080,7 @@ index fe9358437380c..6cb7ec85c9a1f 100644
}
/* And insert new clone at head. */
if (clone) {
-@@ -3449,19 +3449,7 @@ EXPORT_SYMBOL(skb_split);
+@@ -3449,19 +3480,7 @@ EXPORT_SYMBOL(skb_split);
*/
static int skb_prepare_for_shift(struct sk_buff *skb)
{
@@ -147640,7 +228101,16 @@ index fe9358437380c..6cb7ec85c9a1f 100644
}
/**
-@@ -3865,6 +3853,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
+@@ -3854,7 +3873,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
+ unsigned int delta_len = 0;
+ struct sk_buff *tail = NULL;
+ struct sk_buff *nskb, *tmp;
+- int err;
++ int len_diff, err;
+
+ skb_push(skb, -skb_network_offset(skb) + offset);
+
+@@ -3865,6 +3884,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
list_skb = list_skb->next;
err = 0;
@@ -147648,7 +228118,7 @@ index fe9358437380c..6cb7ec85c9a1f 100644
if (skb_shared(nskb)) {
tmp = skb_clone(nskb, GFP_ATOMIC);
if (tmp) {
-@@ -3889,7 +3878,6 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
+@@ -3889,14 +3909,15 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
tail = nskb;
delta_len += nskb->len;
@@ -147656,7 +228126,16 @@ index fe9358437380c..6cb7ec85c9a1f 100644
skb_push(nskb, -skb_network_offset(nskb) + offset);
-@@ -4856,7 +4844,7 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
+ skb_release_head_state(nskb);
++ len_diff = skb_network_header_len(nskb) - skb_network_header_len(skb);
+ __copy_skb_header(nskb, skb);
+
+ skb_headers_offset_update(nskb, skb_headroom(nskb) - skb_headroom(skb));
++ nskb->transport_header += len_diff;
+ skb_copy_from_linear_data_offset(skb, -tnl_hlen,
+ nskb->data - tnl_hlen,
+ offset + tnl_hlen);
+@@ -4856,7 +4877,7 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
serr->ee.ee_data = skb_shinfo(skb)->tskey;
if (sk->sk_protocol == IPPROTO_TCP &&
sk->sk_type == SOCK_STREAM)
@@ -147665,7 +228144,43 @@ index fe9358437380c..6cb7ec85c9a1f 100644
}
err = sock_queue_err_skb(sk, skb);
-@@ -6232,7 +6220,7 @@ static int pskb_carve_frag_list(struct sk_buff *skb,
+@@ -5371,11 +5392,18 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
+ if (skb_cloned(to))
+ return false;
+
+- /* The page pool signature of struct page will eventually figure out
+- * which pages can be recycled or not but for now let's prohibit slab
+- * allocated and page_pool allocated SKBs from being coalesced.
++ /* In general, avoid mixing slab allocated and page_pool allocated
++ * pages within the same SKB. However when @to is not pp_recycle and
++ * @from is cloned, we can transition frag pages from page_pool to
++ * reference counted.
++ *
++ * On the other hand, don't allow coalescing two pp_recycle SKBs if
++ * @from is cloned, in case the SKB is using page_pool fragment
++ * references (PP_FLAG_PAGE_FRAG). Since we only take full page
++ * references for cloned SKBs at the moment that would result in
++ * inconsistent reference counts.
+ */
+- if (to->pp_recycle != from->pp_recycle)
++ if (to->pp_recycle != (from->pp_recycle && !skb_cloned(from)))
+ return false;
+
+ if (len <= skb_tailroom(to)) {
+@@ -6171,11 +6199,7 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb->head = data;
+ skb->data = data;
+ skb->head_frag = 0;
+-#ifdef NET_SKBUFF_DATA_USES_OFFSET
+- skb->end = size;
+-#else
+- skb->end = skb->head + size;
+-#endif
++ skb_set_end_offset(skb, size);
+ skb_set_tail_pointer(skb, skb_headlen(skb));
+ skb_headers_offset_update(skb, 0);
+ skb->cloned = 0;
+@@ -6232,7 +6256,7 @@ static int pskb_carve_frag_list(struct sk_buff *skb,
/* Free pulled out fragments. */
while ((list = shinfo->frag_list) != insp) {
shinfo->frag_list = list->next;
@@ -147674,11 +228189,65 @@ index fe9358437380c..6cb7ec85c9a1f 100644
}
/* And insert new clone at head. */
if (clone) {
+@@ -6313,11 +6337,7 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ skb->head = data;
+ skb->head_frag = 0;
+ skb->data = data;
+-#ifdef NET_SKBUFF_DATA_USES_OFFSET
+- skb->end = size;
+-#else
+- skb->end = skb->head + size;
+-#endif
++ skb_set_end_offset(skb, size);
+ skb_reset_tail_pointer(skb);
+ skb_headers_offset_update(skb, 0);
+ skb->cloned = 0;
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
-index a86ef7e844f8c..929a2b096b04e 100644
+index a86ef7e844f8c..cc381165ea080 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
-@@ -508,6 +508,7 @@ static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
+@@ -27,6 +27,7 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
+ int elem_first_coalesce)
+ {
+ struct page_frag *pfrag = sk_page_frag(sk);
++ u32 osize = msg->sg.size;
+ int ret = 0;
+
+ len -= msg->sg.size;
+@@ -35,13 +36,17 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
+ u32 orig_offset;
+ int use, i;
+
+- if (!sk_page_frag_refill(sk, pfrag))
+- return -ENOMEM;
++ if (!sk_page_frag_refill(sk, pfrag)) {
++ ret = -ENOMEM;
++ goto msg_trim;
++ }
+
+ orig_offset = pfrag->offset;
+ use = min_t(int, len, pfrag->size - orig_offset);
+- if (!sk_wmem_schedule(sk, use))
+- return -ENOMEM;
++ if (!sk_wmem_schedule(sk, use)) {
++ ret = -ENOMEM;
++ goto msg_trim;
++ }
+
+ i = msg->sg.end;
+ sk_msg_iter_var_prev(i);
+@@ -71,6 +76,10 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
+ }
+
+ return ret;
++
++msg_trim:
++ sk_msg_trim(sk, msg, osize);
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(sk_msg_alloc);
+
+@@ -508,6 +517,7 @@ static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
}
static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
@@ -147686,7 +228255,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
struct sk_psock *psock,
struct sock *sk,
struct sk_msg *msg)
-@@ -521,11 +522,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
+@@ -521,11 +531,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
*/
if (skb_linearize(skb))
return -EAGAIN;
@@ -147700,7 +228269,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
msg->sg.start = 0;
msg->sg.size = copied;
msg->sg.end = num_sge;
-@@ -536,9 +537,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
+@@ -536,9 +546,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
return copied;
}
@@ -147714,7 +228283,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
{
struct sock *sk = psock->sk;
struct sk_msg *msg;
-@@ -549,7 +552,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
+@@ -549,7 +561,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
* correctly.
*/
if (unlikely(skb->sk == sk))
@@ -147723,7 +228292,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
msg = sk_psock_create_ingress_msg(sk, skb);
if (!msg)
return -EAGAIN;
-@@ -561,7 +564,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
+@@ -561,7 +573,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
* into user buffers.
*/
skb_set_owner_r(skb, sk);
@@ -147732,7 +228301,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
if (err < 0)
kfree(msg);
return err;
-@@ -571,7 +574,8 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
+@@ -571,7 +583,8 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
* skb. In this case we do not need to check memory limits or skb_set_owner_r
* because the skb is already accounted for here.
*/
@@ -147742,7 +228311,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
{
struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
struct sock *sk = psock->sk;
-@@ -581,7 +585,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb
+@@ -581,7 +594,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb
return -EAGAIN;
sk_msg_init(msg);
skb_set_owner_r(skb, sk);
@@ -147751,7 +228320,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
if (err < 0)
kfree(msg);
return err;
-@@ -595,7 +599,7 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
+@@ -595,7 +608,7 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
return -EAGAIN;
return skb_send_sock(psock->sk, skb, off, len);
}
@@ -147760,7 +228329,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
}
static void sk_psock_skb_state(struct sk_psock *psock,
-@@ -638,6 +642,12 @@ static void sk_psock_backlog(struct work_struct *work)
+@@ -638,6 +651,12 @@ static void sk_psock_backlog(struct work_struct *work)
while ((skb = skb_dequeue(&psock->ingress_skb))) {
len = skb->len;
off = 0;
@@ -147773,7 +228342,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
start:
ingress = skb_bpf_ingress(skb);
skb_bpf_redirect_clear(skb);
-@@ -877,6 +887,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)
+@@ -877,6 +896,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)
* return code, but then didn't set a redirect interface.
*/
if (unlikely(!sk_other)) {
@@ -147781,7 +228350,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
sock_drop(from->sk, skb);
return -EIO;
}
-@@ -944,6 +955,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
+@@ -944,6 +964,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
{
struct sock *sk_other;
int err = 0;
@@ -147789,7 +228358,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
switch (verdict) {
case __SK_PASS:
-@@ -951,6 +963,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
+@@ -951,6 +972,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
sk_other = psock->sk;
if (sock_flag(sk_other, SOCK_DEAD) ||
!sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
@@ -147797,7 +228366,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
goto out_free;
}
-@@ -963,7 +976,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
+@@ -963,7 +985,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
* retrying later from workqueue.
*/
if (skb_queue_empty(&psock->ingress_skb)) {
@@ -147814,7 +228383,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
}
if (err < 0) {
spin_lock_bh(&psock->ingress_lock);
-@@ -1029,6 +1050,8 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
+@@ -1029,6 +1059,8 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
skb_dst_drop(skb);
skb_bpf_redirect_clear(skb);
ret = bpf_prog_run_pin_on_cpu(prog, skb);
@@ -147823,7 +228392,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
skb->sk = NULL;
}
-@@ -1101,6 +1124,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
+@@ -1101,6 +1133,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
{
@@ -147832,7 +228401,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
if (!psock->saved_data_ready)
return;
-@@ -1128,7 +1153,7 @@ static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb,
+@@ -1128,7 +1162,7 @@ static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb,
struct sk_psock *psock;
struct bpf_prog *prog;
int ret = __SK_DROP;
@@ -147841,7 +228410,7 @@ index a86ef7e844f8c..929a2b096b04e 100644
/* clone here so sk_eat_skb() in tcp_read_sock does not drop our data */
skb = skb_clone(skb, GFP_ATOMIC);
-@@ -1189,6 +1214,9 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
+@@ -1189,6 +1223,9 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock)
{
@@ -147898,7 +228467,7 @@ index c1601f75ec4b3..deaed1b206823 100644
/* Before updating sk_refcnt, we must commit prior changes to memory
* (Documentation/RCU/rculist_nulls.rst for details)
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
-index e252b8ec2b85e..8288b5382f08d 100644
+index e252b8ec2b85e..6351b6af7aca9 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -167,8 +167,11 @@ static void sock_map_del_link(struct sock *sk,
@@ -147973,6 +228542,15 @@ index e252b8ec2b85e..8288b5382f08d 100644
return ret;
}
+@@ -1565,7 +1575,7 @@ static struct bpf_iter_reg sock_map_iter_reg = {
+ .ctx_arg_info_size = 2,
+ .ctx_arg_info = {
+ { offsetof(struct bpf_iter__sockmap, key),
+- PTR_TO_RDONLY_BUF_OR_NULL },
++ PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY },
+ { offsetof(struct bpf_iter__sockmap, sk),
+ PTR_TO_BTF_ID_OR_NULL },
+ },
diff --git a/net/core/stream.c b/net/core/stream.c
index 4f1d4aa5fb38d..a166a32b411fa 100644
--- a/net/core/stream.c
@@ -148113,30 +228691,52 @@ index abb5c596a8176..fc44dadc778bb 100644
}
module_init(dccp_init);
-diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
-index 41f36ad8b0ec6..4ff03fb262e02 100644
---- a/net/dsa/dsa.c
-+++ b/net/dsa/dsa.c
-@@ -349,6 +349,7 @@ void dsa_flush_workqueue(void)
- {
- flush_workqueue(dsa_owq);
- }
-+EXPORT_SYMBOL_GPL(dsa_flush_workqueue);
-
- int dsa_devlink_param_get(struct devlink *dl, u32 id,
- struct devlink_param_gset_ctx *ctx)
-diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
-index a5c9bc7b66c6e..33ab7d7af9eb4 100644
---- a/net/dsa/dsa_priv.h
-+++ b/net/dsa/dsa_priv.h
-@@ -170,7 +170,6 @@ void dsa_tag_driver_put(const struct dsa_device_ops *ops);
- const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf);
-
- bool dsa_schedule_work(struct work_struct *work);
--void dsa_flush_workqueue(void);
- const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops);
-
- static inline int dsa_tag_protocol_overhead(const struct dsa_device_ops *ops)
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index e9911b18bdbfa..64a56db3de586 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1341,6 +1341,7 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
+ const char *user_protocol;
+
+ master = of_find_net_device_by_node(ethernet);
++ of_node_put(ethernet);
+ if (!master)
+ return -EPROBE_DEFER;
+
+@@ -1630,6 +1631,10 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
+ struct dsa_port *dp;
+
+ mutex_lock(&dsa2_mutex);
++
++ if (!ds->setup)
++ goto out;
++
+ rtnl_lock();
+
+ list_for_each_entry(dp, &ds->dst->ports, list) {
+@@ -1664,6 +1669,7 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
+ unregister_netdevice_many(&unregister_list);
+
+ rtnl_unlock();
++out:
+ mutex_unlock(&dsa2_mutex);
+ }
+ EXPORT_SYMBOL_GPL(dsa_switch_shutdown);
+diff --git a/net/dsa/port.c b/net/dsa/port.c
+index 616330a16d319..63e88de963936 100644
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1201,8 +1201,10 @@ int dsa_port_link_register_of(struct dsa_port *dp)
+ if (ds->ops->phylink_mac_link_down)
+ ds->ops->phylink_mac_link_down(ds, port,
+ MLO_AN_FIXED, PHY_INTERFACE_MODE_NA);
++ of_node_put(phy_np);
+ return dsa_port_phylink_register(dp);
+ }
++ of_node_put(phy_np);
+ return 0;
+ }
+
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 6466d0539af9f..fb69f2f14234e 100644
--- a/net/dsa/switch.c
@@ -148177,6 +228777,25 @@ index 6466d0539af9f..fb69f2f14234e 100644
return -EOPNOTSUPP;
if (ds->index == info->sw_index)
+diff --git a/net/dsa/tag_hellcreek.c b/net/dsa/tag_hellcreek.c
+index f64b805303cd7..eb204ad36eeec 100644
+--- a/net/dsa/tag_hellcreek.c
++++ b/net/dsa/tag_hellcreek.c
+@@ -21,6 +21,14 @@ static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+ u8 *tag;
+
++ /* Calculate checksums (if required) before adding the trailer tag to
++ * avoid including it in calculations. That would lead to wrong
++ * checksums after the switch strips the tag.
++ */
++ if (skb->ip_summed == CHECKSUM_PARTIAL &&
++ skb_checksum_help(skb))
++ return NULL;
++
+ /* Tag encoding */
+ tag = skb_put(skb, HELLCREEK_TAG_LEN);
+ *tag = BIT(dp->index);
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index cb548188f8134..98d7d7120bab2 100644
--- a/net/dsa/tag_lan9303.c
@@ -148420,6 +229039,39 @@ index 1d816a5fd3eb9..77534b44b8c7c 100644
ipv4_proc_init();
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 922dd73e57406..83a47998c4b18 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -1116,13 +1116,18 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
+ return err;
+ }
+
+-static int arp_invalidate(struct net_device *dev, __be32 ip)
++int arp_invalidate(struct net_device *dev, __be32 ip, bool force)
+ {
+ struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
+ int err = -ENXIO;
+ struct neigh_table *tbl = &arp_tbl;
+
+ if (neigh) {
++ if ((neigh->nud_state & NUD_VALID) && !force) {
++ neigh_release(neigh);
++ return 0;
++ }
++
+ if (neigh->nud_state & ~NUD_NOARP)
+ err = neigh_update(neigh, NULL, NUD_FAILED,
+ NEIGH_UPDATE_F_OVERRIDE|
+@@ -1169,7 +1174,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
+ if (!dev)
+ return -EINVAL;
+ }
+- return arp_invalidate(dev, ip);
++ return arp_invalidate(dev, ip, true);
+ }
+
+ /*
diff --git a/net/ipv4/bpf_tcp_ca.c b/net/ipv4/bpf_tcp_ca.c
index 0dcee9df13268..d3a2dbd13ea6b 100644
--- a/net/ipv4/bpf_tcp_ca.c
@@ -148447,10 +229099,21 @@ index f4468980b6757..4744c7839de53 100644
static void __devinet_sysctl_unregister(struct net *net,
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
-index 851f542928a33..e1b1d080e908d 100644
+index 851f542928a33..d747166bb291c 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
-@@ -671,7 +671,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
+@@ -455,6 +455,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
+ return err;
+ }
+
++ if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
++ ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
++ goto cow;
++
+ if (!skb_cloned(skb)) {
+ if (tailen <= skb_tailroom(skb)) {
+ nfrags = 1;
+@@ -671,7 +675,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
u32 padto;
@@ -148459,11 +229122,46 @@ index 851f542928a33..e1b1d080e908d 100644
if (skb->len < padto)
esp.tfclen = padto - skb->len;
}
+diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
+index 8e4e9aa12130d..dad5d29a6a8db 100644
+--- a/net/ipv4/esp4_offload.c
++++ b/net/ipv4/esp4_offload.c
+@@ -159,6 +159,9 @@ static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x,
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
+ }
+
++ if (proto == IPPROTO_IPV6)
++ skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
++
+ __skb_pull(skb, skb_transport_offset(skb));
+ ops = rcu_dereference(inet_offloads[proto]);
+ if (likely(ops && ops->callbacks.gso_segment))
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
-index 9fe13e4f5d08a..4d61ddd8a0ecf 100644
+index 9fe13e4f5d08a..1eb7795edb9dc 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
-@@ -1582,7 +1582,7 @@ static int __net_init fib_net_init(struct net *net)
+@@ -1112,9 +1112,11 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
+ return;
+
+ /* Add broadcast address, if it is explicitly assigned. */
+- if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
++ if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) {
+ fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32,
+ prim, 0);
++ arp_invalidate(dev, ifa->ifa_broadcast, false);
++ }
+
+ if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
+ (prefix != addr || ifa->ifa_prefixlen < 32)) {
+@@ -1128,6 +1130,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
+ if (ifa->ifa_prefixlen < 31) {
+ fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
+ 32, prim, 0);
++ arp_invalidate(dev, prefix | ~mask, false);
+ }
+ }
+ }
+@@ -1582,7 +1585,7 @@ static int __net_init fib_net_init(struct net *net)
int error;
#ifdef CONFIG_IP_ROUTE_CLASSID
@@ -148521,7 +229219,7 @@ index ce54a30c2ef1e..d279cb8ac1584 100644
net->ipv4.fib_has_custom_rules = true;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
-index 3364cb9c67e01..d244c57b73031 100644
+index 3364cb9c67e01..b5563f5ff1765 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -29,6 +29,7 @@
@@ -148670,7 +229368,22 @@ index 3364cb9c67e01..d244c57b73031 100644
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
if (nla)
fib_cfg.fc_encap_type = nla_get_u16(nla);
-@@ -902,6 +934,7 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+@@ -855,8 +887,13 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+ }
+
+ if (cfg->fc_oif || cfg->fc_gw_family) {
+- struct fib_nh *nh = fib_info_nh(fi, 0);
++ struct fib_nh *nh;
++
++ /* cannot match on nexthop object attributes */
++ if (fi->nh)
++ return 1;
+
++ nh = fib_info_nh(fi, 0);
+ if (cfg->fc_encap) {
+ if (fib_encap_match(net, cfg->fc_encap_type,
+ cfg->fc_encap, nh, cfg, extack))
+@@ -902,6 +939,7 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
attrlen = rtnh_attrlen(rtnh);
if (attrlen > 0) {
struct nlattr *nla, *nlav, *attrs = rtnh_attrs(rtnh);
@@ -148678,7 +229391,7 @@ index 3364cb9c67e01..d244c57b73031 100644
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
nlav = nla_find(attrs, attrlen, RTA_VIA);
-@@ -912,12 +945,17 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+@@ -912,12 +950,17 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
}
if (nla) {
@@ -148698,7 +229411,7 @@ index 3364cb9c67e01..d244c57b73031 100644
err = fib_gw_from_via(&cfg2, nlav, extack);
if (err)
-@@ -940,8 +978,14 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+@@ -940,8 +983,14 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
#ifdef CONFIG_IP_ROUTE_CLASSID
nla = nla_find(attrs, attrlen, RTA_FLOW);
@@ -148715,7 +229428,7 @@ index 3364cb9c67e01..d244c57b73031 100644
#endif
}
-@@ -1393,7 +1437,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
+@@ -1393,7 +1442,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
#endif
err = -ENOBUFS;
@@ -148726,7 +229439,7 @@ index 3364cb9c67e01..d244c57b73031 100644
unsigned int new_size = fib_info_hash_size << 1;
struct hlist_head *new_info_hash;
struct hlist_head *new_laddrhash;
-@@ -1425,7 +1471,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
+@@ -1425,7 +1476,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
return ERR_PTR(err);
}
@@ -148734,7 +229447,7 @@ index 3364cb9c67e01..d244c57b73031 100644
fi->fib_net = net;
fi->fib_protocol = cfg->fc_protocol;
fi->fib_scope = cfg->fc_scope;
-@@ -1552,6 +1597,7 @@ link_it:
+@@ -1552,6 +1602,7 @@ link_it:
refcount_set(&fi->fib_treeref, 1);
refcount_set(&fi->fib_clntref, 1);
spin_lock_bh(&fib_info_lock);
@@ -148742,7 +229455,7 @@ index 3364cb9c67e01..d244c57b73031 100644
hlist_add_head(&fi->fib_hash,
&fib_info_hash[fib_info_hashfn(fi)]);
if (fi->fib_prefsrc) {
-@@ -1565,12 +1611,10 @@ link_it:
+@@ -1565,12 +1616,10 @@ link_it:
} else {
change_nexthops(fi) {
struct hlist_head *head;
@@ -148756,7 +229469,7 @@ index 3364cb9c67e01..d244c57b73031 100644
hlist_add_head(&nexthop_nh->nh_hash, head);
} endfor_nexthops(fi)
}
-@@ -1922,8 +1966,7 @@ void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig)
+@@ -1922,8 +1971,7 @@ void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig)
void fib_sync_mtu(struct net_device *dev, u32 orig_mtu)
{
@@ -148766,7 +229479,7 @@ index 3364cb9c67e01..d244c57b73031 100644
struct fib_nh *nh;
hlist_for_each_entry(nh, head, nh_hash) {
-@@ -1942,12 +1985,11 @@ void fib_sync_mtu(struct net_device *dev, u32 orig_mtu)
+@@ -1942,12 +1990,11 @@ void fib_sync_mtu(struct net_device *dev, u32 orig_mtu)
*/
int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force)
{
@@ -148782,7 +229495,7 @@ index 3364cb9c67e01..d244c57b73031 100644
if (force)
scope = -1;
-@@ -2092,7 +2134,6 @@ out:
+@@ -2092,7 +2139,6 @@ out:
int fib_sync_up(struct net_device *dev, unsigned char nh_flags)
{
struct fib_info *prev_fi;
@@ -148790,7 +229503,7 @@ index 3364cb9c67e01..d244c57b73031 100644
struct hlist_head *head;
struct fib_nh *nh;
int ret;
-@@ -2108,8 +2149,7 @@ int fib_sync_up(struct net_device *dev, unsigned char nh_flags)
+@@ -2108,8 +2154,7 @@ int fib_sync_up(struct net_device *dev, unsigned char nh_flags)
}
prev_fi = NULL;
@@ -148847,6 +229560,38 @@ index 8060524f42566..f7f74d5c14da6 100644
err = fib_dump_info(skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index d2e2b3d18c668..930f6c41f519c 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -2403,9 +2403,10 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
+ /* decrease mem now to avoid the memleak warning */
+ atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
+ &sk->sk_omem_alloc);
+- kfree_rcu(psl, rcu);
+ }
+ rcu_assign_pointer(pmc->sflist, newpsl);
++ if (psl)
++ kfree_rcu(psl, rcu);
+ psl = newpsl;
+ }
+ rv = 1; /* > 0 for insert logic below if sl_count is 0 */
+@@ -2507,11 +2508,13 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
+ /* decrease mem now to avoid the memleak warning */
+ atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
+ &sk->sk_omem_alloc);
+- kfree_rcu(psl, rcu);
+- } else
++ } else {
+ (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
+ 0, NULL, 0);
++ }
+ rcu_assign_pointer(pmc->sflist, newpsl);
++ if (psl)
++ kfree_rcu(psl, rcu);
+ pmc->sfmode = msf->imsf_fmode;
+ err = 0;
+ done:
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index f25d02ad4a8af..62a67fdc344cd 100644
--- a/net/ipv4/inet_connection_sock.c
@@ -148930,9 +229675,18 @@ index 05cd198d7a6ba..341096807100c 100644
rcu_read_lock();
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
-index bfb522e513461..75737267746f8 100644
+index bfb522e513461..ee9c587031b4b 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
+@@ -504,7 +504,7 @@ not_unique:
+ return -EADDRNOTAVAIL;
+ }
+
+-static u32 inet_sk_port_offset(const struct sock *sk)
++static u64 inet_sk_port_offset(const struct sock *sk)
+ {
+ const struct inet_sock *inet = inet_sk(sk);
+
@@ -598,7 +598,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk)
if (ok) {
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -148942,6 +229696,172 @@ index bfb522e513461..75737267746f8 100644
inet_sk_set_state(sk, TCP_CLOSE);
sock_set_flag(sk, SOCK_DEAD);
inet_csk_destroy_sock(sk);
+@@ -637,7 +637,9 @@ int __inet_hash(struct sock *sk, struct sock *osk)
+ int err = 0;
+
+ if (sk->sk_state != TCP_LISTEN) {
++ local_bh_disable();
+ inet_ehash_nolisten(sk, osk, NULL);
++ local_bh_enable();
+ return 0;
+ }
+ WARN_ON(!sk_unhashed(sk));
+@@ -669,45 +671,54 @@ int inet_hash(struct sock *sk)
+ {
+ int err = 0;
+
+- if (sk->sk_state != TCP_CLOSE) {
+- local_bh_disable();
++ if (sk->sk_state != TCP_CLOSE)
+ err = __inet_hash(sk, NULL);
+- local_bh_enable();
+- }
+
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(inet_hash);
+
+-void inet_unhash(struct sock *sk)
++static void __inet_unhash(struct sock *sk, struct inet_listen_hashbucket *ilb)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+- struct inet_listen_hashbucket *ilb = NULL;
+- spinlock_t *lock;
+-
+ if (sk_unhashed(sk))
+ return;
+
+- if (sk->sk_state == TCP_LISTEN) {
+- ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+- lock = &ilb->lock;
+- } else {
+- lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
+- }
+- spin_lock_bh(lock);
+- if (sk_unhashed(sk))
+- goto unlock;
+-
+ if (rcu_access_pointer(sk->sk_reuseport_cb))
+ reuseport_stop_listen_sock(sk);
+ if (ilb) {
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
++
+ inet_unhash2(hashinfo, sk);
+ ilb->count--;
+ }
+ __sk_nulls_del_node_init_rcu(sk);
+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+-unlock:
+- spin_unlock_bh(lock);
++}
++
++void inet_unhash(struct sock *sk)
++{
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
++
++ if (sk_unhashed(sk))
++ return;
++
++ if (sk->sk_state == TCP_LISTEN) {
++ struct inet_listen_hashbucket *ilb;
++
++ ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
++ /* Don't disable bottom halves while acquiring the lock to
++ * avoid circular locking dependency on PREEMPT_RT.
++ */
++ spin_lock(&ilb->lock);
++ __inet_unhash(sk, ilb);
++ spin_unlock(&ilb->lock);
++ } else {
++ spinlock_t *lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
++
++ spin_lock_bh(lock);
++ __inet_unhash(sk, NULL);
++ spin_unlock_bh(lock);
++ }
+ }
+ EXPORT_SYMBOL_GPL(inet_unhash);
+
+@@ -715,15 +726,17 @@ EXPORT_SYMBOL_GPL(inet_unhash);
+ * Note that we use 32bit integers (vs RFC 'short integers')
+ * because 2^16 is not a multiple of num_ephemeral and this
+ * property might be used by clever attacker.
+- * RFC claims using TABLE_LENGTH=10 buckets gives an improvement,
+- * we use 256 instead to really give more isolation and
+- * privacy, this only consumes 1 KB of kernel memory.
++ * RFC claims using TABLE_LENGTH=10 buckets gives an improvement, though
++ * attacks were since demonstrated, thus we use 65536 instead to really
++ * give more isolation and privacy, at the expense of 256kB of kernel
++ * memory.
+ */
+-#define INET_TABLE_PERTURB_SHIFT 8
+-static u32 table_perturb[1 << INET_TABLE_PERTURB_SHIFT];
++#define INET_TABLE_PERTURB_SHIFT 16
++#define INET_TABLE_PERTURB_SIZE (1 << INET_TABLE_PERTURB_SHIFT)
++static u32 *table_perturb;
+
+ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+- struct sock *sk, u32 port_offset,
++ struct sock *sk, u64 port_offset,
+ int (*check_established)(struct inet_timewait_death_row *,
+ struct sock *, __u16, struct inet_timewait_sock **))
+ {
+@@ -763,10 +776,13 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ if (likely(remaining > 1))
+ remaining &= ~1U;
+
+- net_get_random_once(table_perturb, sizeof(table_perturb));
+- index = hash_32(port_offset, INET_TABLE_PERTURB_SHIFT);
++ net_get_random_once(table_perturb,
++ INET_TABLE_PERTURB_SIZE * sizeof(*table_perturb));
++ index = port_offset & (INET_TABLE_PERTURB_SIZE - 1);
++
++ offset = READ_ONCE(table_perturb[index]) + (port_offset >> 32);
++ offset %= remaining;
+
+- offset = (READ_ONCE(table_perturb[index]) + port_offset) % remaining;
+ /* In first pass we try ports of @low parity.
+ * inet_csk_get_port() does the opposite choice.
+ */
+@@ -820,11 +836,12 @@ next_port:
+ return -EADDRNOTAVAIL;
+
+ ok:
+- /* If our first attempt found a candidate, skip next candidate
+- * in 1/16 of cases to add some noise.
++ /* Here we want to add a little bit of randomness to the next source
++ * port that will be chosen. We use a max() with a random here so that
++ * on low contention the randomness is maximal and on high contention
++ * it may be inexistent.
+ */
+- if (!i && !(prandom_u32() % 16))
+- i = 2;
++ i = max_t(int, i, (prandom_u32() & 7) * 2);
+ WRITE_ONCE(table_perturb[index], READ_ONCE(table_perturb[index]) + i + 2);
+
+ /* Head lock still held and bh's disabled */
+@@ -848,7 +865,7 @@ ok:
+ int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk)
+ {
+- u32 port_offset = 0;
++ u64 port_offset = 0;
+
+ if (!inet_sk(sk)->inet_num)
+ port_offset = inet_sk_port_offset(sk);
+@@ -898,6 +915,12 @@ void __init inet_hashinfo2_init(struct inet_hashinfo *h, const char *name,
+ low_limit,
+ high_limit);
+ init_hashinfo_lhash2(h);
++
++ /* this one is used for source ports of outgoing connections */
++ table_perturb = kmalloc_array(INET_TABLE_PERTURB_SIZE,
++ sizeof(*table_perturb), GFP_KERNEL);
++ if (!table_perturb)
++ panic("TCP: failed to alloc table_perturb");
+ }
+
+ int inet_hashinfo2_init_mod(struct inet_hashinfo *h)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index cfeb8890f94ee..fad803d2d711e 100644
--- a/net/ipv4/ip_fragment.c
@@ -148957,10 +229877,46 @@ index cfeb8890f94ee..fad803d2d711e 100644
spin_lock(&qp->q.lock);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
-index 0fe6c936dc54a..e7f3e37e4aa83 100644
+index 0fe6c936dc54a..276a3b7b0e9c1 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
-@@ -604,8 +604,9 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+@@ -459,14 +459,12 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
+ __be16 proto)
+ {
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+-
+- if (tunnel->parms.o_flags & TUNNEL_SEQ)
+- tunnel->o_seqno++;
++ __be16 flags = tunnel->parms.o_flags;
+
+ /* Push GRE header. */
+ gre_build_header(skb, tunnel->tun_hlen,
+- tunnel->parms.o_flags, proto, tunnel->parms.o_key,
+- htonl(tunnel->o_seqno));
++ flags, proto, tunnel->parms.o_key,
++ (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0);
+
+ ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
+ }
+@@ -504,7 +502,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
+ (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
+ gre_build_header(skb, tunnel_hlen, flags, proto,
+ tunnel_id_to_key32(tun_info->key.tun_id),
+- (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
++ (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0);
+
+ ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
+
+@@ -581,7 +579,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ gre_build_header(skb, 8, TUNNEL_SEQ,
+- proto, 0, htonl(tunnel->o_seqno++));
++ proto, 0, htonl(atomic_fetch_inc(&tunnel->o_seqno)));
+
+ ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
+
+@@ -604,8 +602,9 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
key = &info->key;
ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
@@ -149137,7 +230093,7 @@ index 9e8100728d464..5dbd4b5505eba 100644
}
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
-index 1e44a43acfe2d..36e89b6873876 100644
+index 1e44a43acfe2d..c4a2565da2806 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -172,16 +172,22 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
@@ -149174,6 +230130,42 @@ index 1e44a43acfe2d..36e89b6873876 100644
continue;
sock_hold(sk);
+@@ -298,6 +305,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
+ struct net *net = sock_net(sk);
+ if (sk->sk_family == AF_INET) {
+ struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
++ u32 tb_id = RT_TABLE_LOCAL;
+ int chk_addr_ret;
+
+ if (addr_len < sizeof(*addr))
+@@ -313,8 +321,10 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
+
+ if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
+ chk_addr_ret = RTN_LOCAL;
+- else
+- chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
++ else {
++ tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
++ chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
++ }
+
+ if ((!inet_can_nonlocal_bind(net, isk) &&
+ chk_addr_ret != RTN_LOCAL) ||
+@@ -352,6 +362,14 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
+ return -ENODEV;
+ }
+ }
++
++ if (!dev && sk->sk_bound_dev_if) {
++ dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
++ if (!dev) {
++ rcu_read_unlock();
++ return -ENODEV;
++ }
++ }
+ has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev,
+ scoped);
+ rcu_read_unlock();
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index b0d3a09dc84e7..f30273afb5399 100644
--- a/net/ipv4/proc.c
@@ -149211,10 +230203,158 @@ index bb446e60cf580..b8689052079cd 100644
/*
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
-index d6899ab5fb39b..23833660584df 100644
+index d6899ab5fb39b..1db2fda228306 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
-@@ -3401,8 +3401,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
+@@ -506,6 +506,15 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
+ }
+ EXPORT_SYMBOL(__ip_select_ident);
+
++static void ip_rt_fix_tos(struct flowi4 *fl4)
++{
++ __u8 tos = RT_FL_TOS(fl4);
++
++ fl4->flowi4_tos = tos & IPTOS_RT_MASK;
++ fl4->flowi4_scope = tos & RTO_ONLINK ?
++ RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
++}
++
+ static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
+ const struct sock *sk,
+ const struct iphdr *iph,
+@@ -831,6 +840,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
+ rt = (struct rtable *) dst;
+
+ __build_flow_key(net, &fl4, sk, iph, oif, tos, prot, mark, 0);
++ ip_rt_fix_tos(&fl4);
+ __ip_do_redirect(rt, skb, &fl4, true);
+ }
+
+@@ -1055,6 +1065,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
+ struct flowi4 fl4;
+
+ ip_rt_build_flow_key(&fl4, sk, skb);
++ ip_rt_fix_tos(&fl4);
+
+ /* Don't make lookup fail for bridged encapsulations */
+ if (skb && netif_is_any_bridge_port(skb->dev))
+@@ -1129,6 +1140,8 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
+ goto out;
+
+ new = true;
++ } else {
++ ip_rt_fix_tos(&fl4);
+ }
+
+ __ip_rt_update_pmtu((struct rtable *)xfrm_dst_path(&rt->dst), &fl4, mtu);
+@@ -1714,6 +1727,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
+ unsigned int flags = RTCF_MULTICAST;
+ struct rtable *rth;
++ bool no_policy;
+ u32 itag = 0;
+ int err;
+
+@@ -1724,8 +1738,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ if (our)
+ flags |= RTCF_LOCAL;
+
++ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
++ if (no_policy)
++ IPCB(skb)->flags |= IPSKB_NOPOLICY;
++
+ rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
+- IN_DEV_ORCONF(in_dev, NOPOLICY), false);
++ no_policy, false);
+ if (!rth)
+ return -ENOBUFS;
+
+@@ -1741,6 +1759,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ #endif
+ RT_CACHE_STAT_INC(in_slow_mc);
+
++ skb_dst_drop(skb);
+ skb_dst_set(skb, &rth->dst);
+ return 0;
+ }
+@@ -1783,7 +1802,7 @@ static int __mkroute_input(struct sk_buff *skb,
+ struct rtable *rth;
+ int err;
+ struct in_device *out_dev;
+- bool do_cache;
++ bool do_cache, no_policy;
+ u32 itag = 0;
+
+ /* get a working reference to the output device */
+@@ -1828,6 +1847,10 @@ static int __mkroute_input(struct sk_buff *skb,
+ }
+ }
+
++ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
++ if (no_policy)
++ IPCB(skb)->flags |= IPSKB_NOPOLICY;
++
+ fnhe = find_exception(nhc, daddr);
+ if (do_cache) {
+ if (fnhe)
+@@ -1840,8 +1863,7 @@ static int __mkroute_input(struct sk_buff *skb,
+ }
+ }
+
+- rth = rt_dst_alloc(out_dev->dev, 0, res->type,
+- IN_DEV_ORCONF(in_dev, NOPOLICY),
++ rth = rt_dst_alloc(out_dev->dev, 0, res->type, no_policy,
+ IN_DEV_ORCONF(out_dev, NOXFRM));
+ if (!rth) {
+ err = -ENOBUFS;
+@@ -2216,6 +2238,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ struct rtable *rth;
+ struct flowi4 fl4;
+ bool do_cache = true;
++ bool no_policy;
+
+ /* IP on this device is disabled. */
+
+@@ -2333,6 +2356,10 @@ brd_input:
+ RT_CACHE_STAT_INC(in_brd);
+
+ local_input:
++ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
++ if (no_policy)
++ IPCB(skb)->flags |= IPSKB_NOPOLICY;
++
+ do_cache &= res->fi && !itag;
+ if (do_cache) {
+ struct fib_nh_common *nhc = FIB_RES_NHC(*res);
+@@ -2347,7 +2374,7 @@ local_input:
+
+ rth = rt_dst_alloc(ip_rt_get_dev(net, res),
+ flags | RTCF_LOCAL, res->type,
+- IN_DEV_ORCONF(in_dev, NOPOLICY), false);
++ no_policy, false);
+ if (!rth)
+ goto e_nobufs;
+
+@@ -2609,7 +2636,6 @@ add:
+ struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
+ const struct sk_buff *skb)
+ {
+- __u8 tos = RT_FL_TOS(fl4);
+ struct fib_result res = {
+ .type = RTN_UNSPEC,
+ .fi = NULL,
+@@ -2619,9 +2645,7 @@ struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
+ struct rtable *rth;
+
+ fl4->flowi4_iif = LOOPBACK_IFINDEX;
+- fl4->flowi4_tos = tos & IPTOS_RT_MASK;
+- fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
+- RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
++ ip_rt_fix_tos(fl4);
+
+ rcu_read_lock();
+ rth = ip_route_output_key_hash_rcu(net, fl4, &res, skb);
+@@ -3401,8 +3425,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
fa->fa_tos == fri.tos &&
fa->fa_info == res.fi &&
fa->fa_type == fri.type) {
@@ -149225,8 +230365,41 @@ index d6899ab5fb39b..23833660584df 100644
break;
}
}
+diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
+index 33792cf55a793..10b469aee4920 100644
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -283,6 +283,7 @@ bool cookie_ecn_ok(const struct tcp_options_received *tcp_opt,
+ EXPORT_SYMBOL(cookie_ecn_ok);
+
+ struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops,
++ const struct tcp_request_sock_ops *af_ops,
+ struct sock *sk,
+ struct sk_buff *skb)
+ {
+@@ -299,6 +300,10 @@ struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops,
+ return NULL;
+
+ treq = tcp_rsk(req);
++
++ /* treq->af_specific might be used to perform TCP_MD5 lookup */
++ treq->af_specific = af_ops;
++
+ treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield;
+ #if IS_ENABLED(CONFIG_MPTCP)
+ treq->is_mptcp = sk_is_mptcp(sk);
+@@ -366,7 +371,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
+ goto out;
+
+ ret = NULL;
+- req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, sk, skb);
++ req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops,
++ &tcp_request_sock_ipv4_ops, sk, skb);
+ if (!req)
+ goto out;
+
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index f5c336f8b0c8e..f48f1059b31a6 100644
+index f5c336f8b0c8e..ef68d55e09448 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -287,8 +287,8 @@ enum {
@@ -149249,7 +230422,25 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
tcp_unlink_write_queue(skb, sk);
if (tcp_write_queue_empty(sk))
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
-@@ -1776,6 +1776,9 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
+@@ -1663,11 +1663,13 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ if (!copied)
+ copied = used;
+ break;
+- } else if (used <= len) {
+- seq += used;
+- copied += used;
+- offset += used;
+ }
++ if (WARN_ON_ONCE(used > len))
++ used = len;
++ seq += used;
++ copied += used;
++ offset += used;
++
+ /* If recv_actor drops the lock (e.g. TCP splice
+ * receive) the skb pointer might be invalid when
+ * getting here: tcp_collapse might have deleted it
+@@ -1776,6 +1778,9 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
{
skb_frag_t *frag;
@@ -149259,7 +230450,7 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
offset_skb -= skb_headlen(skb);
if ((int)offset_skb < 0 || skb_has_frag_list(skb))
return NULL;
-@@ -2687,11 +2690,36 @@ void tcp_shutdown(struct sock *sk, int how)
+@@ -2687,11 +2692,36 @@ void tcp_shutdown(struct sock *sk, int how)
}
EXPORT_SYMBOL(tcp_shutdown);
@@ -149297,7 +230488,7 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
out_of_socket_memory = tcp_out_of_memory(sk);
if (too_many_orphans)
-@@ -2800,7 +2828,7 @@ adjudge_to_death:
+@@ -2800,7 +2830,7 @@ adjudge_to_death:
/* remove backlog if any, without releasing ownership. */
__release_sock(sk);
@@ -149306,7 +230497,7 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
/* Have we already been destroyed by a softirq or backlog? */
if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
-@@ -3011,8 +3039,7 @@ int tcp_disconnect(struct sock *sk, int flags)
+@@ -3011,8 +3041,7 @@ int tcp_disconnect(struct sock *sk, int flags)
icsk->icsk_ack.rcv_mss = TCP_MIN_MSS;
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
__sk_dst_reset(sk);
@@ -149316,7 +230507,7 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
tcp_saved_syn_free(tp);
tp->compressed_ack = 0;
tp->segs_in = 0;
-@@ -4502,7 +4529,10 @@ void __init tcp_init(void)
+@@ -4502,7 +4531,10 @@ void __init tcp_init(void)
sizeof_field(struct sk_buff, cb));
percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL);
@@ -149329,10 +230520,24 @@ index f5c336f8b0c8e..f48f1059b31a6 100644
inet_hashinfo2_init(&tcp_hashinfo, "tcp_listen_portaddr_hash",
thash_entries, 21, /* one slot per 2 MB*/
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
-index 5f4d6f45d87f7..9b9b02052fd36 100644
+index 5f4d6f45d87f7..1cdcb4df0eb7e 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
-@@ -172,6 +172,68 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
+@@ -138,10 +138,9 @@ int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg,
+ struct sk_psock *psock = sk_psock_get(sk);
+ int ret;
+
+- if (unlikely(!psock)) {
+- sk_msg_free(sk, msg);
+- return 0;
+- }
++ if (unlikely(!psock))
++ return -EPIPE;
++
+ ret = ingress ? bpf_tcp_ingress(sk, psock, msg, bytes, flags) :
+ tcp_bpf_push_locked(sk, msg, bytes, flags, false);
+ sk_psock_put(sk, psock);
+@@ -172,6 +171,68 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
return ret;
}
@@ -149401,7 +230606,29 @@ index 5f4d6f45d87f7..9b9b02052fd36 100644
static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len)
{
-@@ -464,6 +526,8 @@ enum {
+@@ -273,7 +334,7 @@ more_data:
+ cork = true;
+ psock->cork = NULL;
+ }
+- sk_msg_return(sk, msg, tosend);
++ sk_msg_return(sk, msg, msg->sg.size);
+ release_sock(sk);
+
+ ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags);
+@@ -313,8 +374,11 @@ more_data:
+ }
+ if (msg &&
+ msg->sg.data[msg->sg.start].page_link &&
+- msg->sg.data[msg->sg.start].length)
++ msg->sg.data[msg->sg.start].length) {
++ if (eval == __SK_REDIRECT)
++ sk_mem_charge(sk, msg->sg.size);
+ goto more_data;
++ }
+ }
+ return ret;
+ }
+@@ -464,6 +528,8 @@ enum {
enum {
TCP_BPF_BASE,
TCP_BPF_TX,
@@ -149410,7 +230637,7 @@ index 5f4d6f45d87f7..9b9b02052fd36 100644
TCP_BPF_NUM_CFGS,
};
-@@ -475,7 +539,6 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
+@@ -475,7 +541,6 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
struct proto *base)
{
prot[TCP_BPF_BASE] = *base;
@@ -149418,7 +230645,7 @@ index 5f4d6f45d87f7..9b9b02052fd36 100644
prot[TCP_BPF_BASE].close = sock_map_close;
prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg;
prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable;
-@@ -483,6 +546,12 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
+@@ -483,6 +548,12 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
prot[TCP_BPF_TX] = prot[TCP_BPF_BASE];
prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg;
prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage;
@@ -149431,7 +230658,7 @@ index 5f4d6f45d87f7..9b9b02052fd36 100644
}
static void tcp_bpf_check_v6_needs_rebuild(struct proto *ops)
-@@ -520,6 +589,10 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
+@@ -520,6 +591,10 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE;
@@ -149466,7 +230693,7 @@ index 4a30deaa9a37f..8d2d4d652f6d4 100644
u32 now = bictcp_clock_us(sk);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index 141e85e6422b1..509f577869d4e 100644
+index 141e85e6422b1..dfd32cd3b95e7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1652,6 +1652,8 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
@@ -149478,7 +230705,36 @@ index 141e85e6422b1..509f577869d4e 100644
len = skb->len;
pcount = tcp_skb_pcount(skb);
if (tcp_skb_shift(prev, skb, pcount, len))
-@@ -5770,7 +5772,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
+@@ -3858,7 +3860,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
+ tcp_process_tlp_ack(sk, ack, flag);
+
+ if (tcp_ack_is_dubious(sk, flag)) {
+- if (!(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP))) {
++ if (!(flag & (FLAG_SND_UNA_ADVANCED |
++ FLAG_NOT_DUP | FLAG_DSACKING_ACK))) {
+ num_dupack = 1;
+ /* Consider if pure acks were aggregated in tcp_add_backlog() */
+ if (!(flag & FLAG_DATA))
+@@ -5418,7 +5421,17 @@ static void tcp_new_space(struct sock *sk)
+ INDIRECT_CALL_1(sk->sk_write_space, sk_stream_write_space, sk);
+ }
+
+-static void tcp_check_space(struct sock *sk)
++/* Caller made space either from:
++ * 1) Freeing skbs in rtx queues (after tp->snd_una has advanced)
++ * 2) Sent skbs from output queue (and thus advancing tp->snd_nxt)
++ *
++ * We might be able to generate EPOLLOUT to the application if:
++ * 1) Space consumed in output/rtx queues is below sk->sk_sndbuf/2
++ * 2) notsent amount (tp->write_seq - tp->snd_nxt) became
++ * small enough that tcp_stream_memory_free() decides it
++ * is time to generate EPOLLOUT.
++ */
++void tcp_check_space(struct sock *sk)
+ {
+ /* pairs with tcp_poll() */
+ smp_mb();
+@@ -5770,7 +5783,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
trace_tcp_probe(sk, skb);
tcp_mstamp_refresh(tp);
@@ -149540,11 +230796,32 @@ index 5b8ce65dfc067..0fe9461647da5 100644
}
}
EXPORT_SYMBOL(inet_sk_rx_dst_set);
+diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
+index 0a4f3f16140ad..13783fc58e030 100644
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -538,7 +538,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
+ newtp->tsoffset = treq->ts_off;
+ #ifdef CONFIG_TCP_MD5SIG
+ newtp->md5sig_info = NULL; /*XXX*/
+- if (newtp->af_specific->md5_lookup(sk, newsk))
++ if (treq->af_specific->req_md5_lookup(sk, req_to_sk(req)))
+ newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
+ #endif
+ if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
-index 6d72f3ea48c4e..0492f6942778d 100644
+index 6d72f3ea48c4e..df413282fa2e5 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
-@@ -1562,7 +1562,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
+@@ -82,6 +82,7 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb)
+
+ NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPORIGDATASENT,
+ tcp_skb_pcount(skb));
++ tcp_check_space(sk);
+ }
+
+ /* SND.NXT, if window was not shrunk or the amount of shrunk was less than one
+@@ -1562,7 +1563,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
return -ENOMEM;
}
@@ -149553,7 +230830,7 @@ index 6d72f3ea48c4e..0492f6942778d 100644
return -ENOMEM;
/* Get a new skb... force flag on. */
-@@ -1672,7 +1672,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
+@@ -1672,7 +1673,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
{
u32 delta_truesize;
@@ -149562,7 +230839,7 @@ index 6d72f3ea48c4e..0492f6942778d 100644
return -ENOMEM;
delta_truesize = __pskb_trim_head(skb, len);
-@@ -3184,7 +3184,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
+@@ -3184,7 +3185,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
cur_mss, GFP_ATOMIC))
return -ENOMEM; /* We'll try again later. */
} else {
@@ -149571,6 +230848,65 @@ index 6d72f3ea48c4e..0492f6942778d 100644
return -ENOMEM;
diff = tcp_skb_pcount(skb);
+@@ -3734,6 +3735,7 @@ static void tcp_connect_queue_skb(struct sock *sk, struct sk_buff *skb)
+ */
+ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
+ {
++ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_fastopen_request *fo = tp->fastopen_req;
+ int space, err = 0;
+@@ -3748,8 +3750,10 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
+ * private TCP options. The cost is reduced data space in SYN :(
+ */
+ tp->rx_opt.mss_clamp = tcp_mss_clamp(tp, tp->rx_opt.mss_clamp);
++ /* Sync mss_cache after updating the mss_clamp */
++ tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+
+- space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
++ space = __tcp_mtu_to_mss(sk, icsk->icsk_pmtu_cookie) -
+ MAX_TCP_OPTION_SPACE;
+
+ space = min_t(size_t, space, fo->size);
+diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c
+index 0de6935659635..6ab197928abbc 100644
+--- a/net/ipv4/tcp_rate.c
++++ b/net/ipv4/tcp_rate.c
+@@ -73,26 +73,31 @@ void tcp_rate_skb_sent(struct sock *sk, struct sk_buff *skb)
+ *
+ * If an ACK (s)acks multiple skbs (e.g., stretched-acks), this function is
+ * called multiple times. We favor the information from the most recently
+- * sent skb, i.e., the skb with the highest prior_delivered count.
++ * sent skb, i.e., the skb with the most recently sent time and the highest
++ * sequence.
+ */
+ void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb,
+ struct rate_sample *rs)
+ {
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
++ u64 tx_tstamp;
+
+ if (!scb->tx.delivered_mstamp)
+ return;
+
++ tx_tstamp = tcp_skb_timestamp_us(skb);
+ if (!rs->prior_delivered ||
+- after(scb->tx.delivered, rs->prior_delivered)) {
++ tcp_skb_sent_after(tx_tstamp, tp->first_tx_mstamp,
++ scb->end_seq, rs->last_end_seq)) {
+ rs->prior_delivered = scb->tx.delivered;
+ rs->prior_mstamp = scb->tx.delivered_mstamp;
+ rs->is_app_limited = scb->tx.is_app_limited;
+ rs->is_retrans = scb->sacked & TCPCB_RETRANS;
++ rs->last_end_seq = scb->end_seq;
+
+ /* Record send time of most recently ACKed packet: */
+- tp->first_tx_mstamp = tcp_skb_timestamp_us(skb);
++ tp->first_tx_mstamp = tx_tstamp;
+ /* Find the duration of the "send phase" of this window: */
+ rs->interval_us = tcp_stamp_us_delta(tp->first_tx_mstamp,
+ scb->tx.first_tx_mstamp);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 2fffcf2b54f3f..835b9d6e4e686 100644
--- a/net/ipv4/udp.c
@@ -149652,9 +230988,18 @@ index b91003538d87a..bc3a043a5d5c7 100644
list_del(&node->list);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
-index c6a90b7bbb70e..e852bbc839dd8 100644
+index c6a90b7bbb70e..3a8838b79bb69 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
+@@ -552,7 +552,7 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+ #ifdef CONFIG_IPV6_MROUTE
+ if ((all || type == NETCONFA_MC_FORWARDING) &&
+ nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+- devconf->mc_forwarding) < 0)
++ atomic_read(&devconf->mc_forwarding)) < 0)
+ goto nla_put_failure;
+ #endif
+ if ((all || type == NETCONFA_PROXY_NEIGH) &&
@@ -1837,8 +1837,8 @@ out:
}
EXPORT_SYMBOL(ipv6_dev_get_saddr);
@@ -149753,6 +231098,31 @@ index c6a90b7bbb70e..e852bbc839dd8 100644
ipv6_mc_down(idev);
}
+@@ -4980,6 +5000,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
+ nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid))
+ goto error;
+
++ spin_lock_bh(&ifa->lock);
+ if (!((ifa->flags&IFA_F_PERMANENT) &&
+ (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
+ preferred = ifa->prefered_lft;
+@@ -5001,6 +5022,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
+ preferred = INFINITY_LIFE_TIME;
+ valid = INFINITY_LIFE_TIME;
+ }
++ spin_unlock_bh(&ifa->lock);
+
+ if (!ipv6_addr_any(&ifa->peer_addr)) {
+ if (nla_put_in6_addr(skb, IFA_LOCAL, &ifa->addr) < 0 ||
+@@ -5515,7 +5537,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+ array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
+ #endif
+ #ifdef CONFIG_IPV6_MROUTE
+- array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
++ array[DEVCONF_MC_FORWARDING] = atomic_read(&cnf->mc_forwarding);
+ #endif
+ array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
+ array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index b5878bb8e419d..dab4a047590b7 100644
--- a/net/ipv6/af_inet6.c
@@ -149809,10 +231179,21 @@ index b5878bb8e419d..dab4a047590b7 100644
.fib6_rt_update = fib6_rt_update,
.ip6_del_rt = ip6_del_rt,
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
-index ed2f061b87685..883b53fd78467 100644
+index ed2f061b87685..6219d97cac7a3 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
-@@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
+@@ -491,6 +491,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
+ return err;
+ }
+
++ if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
++ ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
++ goto cow;
++
+ if (!skb_cloned(skb)) {
+ if (tailen <= skb_tailroom(skb)) {
+ nfrags = 1;
+@@ -708,7 +712,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
u32 padto;
@@ -149821,12 +231202,11 @@ index ed2f061b87685..883b53fd78467 100644
if (skb->len < padto)
esp.tfclen = padto - skb->len;
}
-@@ -808,6 +808,12 @@ int esp6_input_done2(struct sk_buff *skb, int err)
+@@ -808,6 +812,11 @@ int esp6_input_done2(struct sk_buff *skb, int err)
struct tcphdr *th;
offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
-+
-+ if (offset < 0) {
++ if (offset == -1) {
+ err = -EINVAL;
+ goto out;
+ }
@@ -149834,6 +231214,20 @@ index ed2f061b87685..883b53fd78467 100644
uh = (void *)(skb->data + offset);
th = (void *)(skb->data + offset);
hdr_len += offset;
+diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
+index a349d47980776..302170882382a 100644
+--- a/net/ipv6/esp6_offload.c
++++ b/net/ipv6/esp6_offload.c
+@@ -198,6 +198,9 @@ static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x,
+ ipv6_skip_exthdr(skb, 0, &proto, &frag);
+ }
+
++ if (proto == IPPROTO_IPIP)
++ skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6;
++
+ __skb_pull(skb, skb_transport_offset(skb));
+ ops = rcu_dereference(inet6_offloads[proto]);
+ if (likely(ops && ops->callbacks.gso_segment))
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 40f3e4f9f33a2..dcedfe29d9d93 100644
--- a/net/ipv6/fib6_rules.c
@@ -149894,6 +231288,41 @@ index a7c31ab67c5d6..96c5cc0f30ceb 100644
raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
return;
+diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
+index 67c9114835c84..40203255ed88b 100644
+--- a/net/ipv6/inet6_hashtables.c
++++ b/net/ipv6/inet6_hashtables.c
+@@ -308,7 +308,7 @@ not_unique:
+ return -EADDRNOTAVAIL;
+ }
+
+-static u32 inet6_sk_port_offset(const struct sock *sk)
++static u64 inet6_sk_port_offset(const struct sock *sk)
+ {
+ const struct inet_sock *inet = inet_sk(sk);
+
+@@ -320,7 +320,7 @@ static u32 inet6_sk_port_offset(const struct sock *sk)
+ int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk)
+ {
+- u32 port_offset = 0;
++ u64 port_offset = 0;
+
+ if (!inet_sk(sk)->inet_num)
+ port_offset = inet6_sk_port_offset(sk);
+@@ -333,11 +333,8 @@ int inet6_hash(struct sock *sk)
+ {
+ int err = 0;
+
+- if (sk->sk_state != TCP_CLOSE) {
+- local_bh_disable();
++ if (sk->sk_state != TCP_CLOSE)
+ err = __inet_hash(sk, NULL);
+- local_bh_enable();
+- }
+
+ return err;
+ }
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 0371d2c141455..a506e57c4032a 100644
--- a/net/ipv6/ip6_fib.c
@@ -149983,10 +231412,36 @@ index aa673a6a7e432..ceb85c67ce395 100644
done:
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
-index 3ad201d372d88..466a5610e3ca9 100644
+index 3ad201d372d88..a817ac6d97598 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
-@@ -755,6 +755,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
+@@ -724,6 +724,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
+ {
+ struct ip6_tnl *tunnel = netdev_priv(dev);
+ __be16 protocol;
++ __be16 flags;
+
+ if (dev->type == ARPHRD_ETHER)
+ IPCB(skb)->flags = 0;
+@@ -733,16 +734,13 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
+ else
+ fl6->daddr = tunnel->parms.raddr;
+
+- if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen))
+- return -ENOMEM;
+-
+ /* Push GRE header. */
+ protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto;
+
+ if (tunnel->parms.collect_md) {
+ struct ip_tunnel_info *tun_info;
+ const struct ip_tunnel_key *key;
+- __be16 flags;
++ int tun_hlen;
+
+ tun_info = skb_tunnel_info_txcheck(skb);
+ if (IS_ERR(tun_info) ||
+@@ -755,25 +753,32 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
fl6->daddr = key->u.ipv6.dst;
fl6->flowlabel = key->label;
fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
@@ -149994,7 +231449,39 @@ index 3ad201d372d88..466a5610e3ca9 100644
dsfield = key->tos;
flags = key->tun_flags &
-@@ -990,6 +991,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
+ (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
+- tunnel->tun_hlen = gre_calc_hlen(flags);
++ tun_hlen = gre_calc_hlen(flags);
+
+- gre_build_header(skb, tunnel->tun_hlen,
++ if (skb_cow_head(skb, dev->needed_headroom ?: tun_hlen + tunnel->encap_hlen))
++ return -ENOMEM;
++
++ gre_build_header(skb, tun_hlen,
+ flags, protocol,
+ tunnel_id_to_key32(tun_info->key.tun_id),
+- (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++)
++ (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno))
+ : 0);
+
+ } else {
+- if (tunnel->parms.o_flags & TUNNEL_SEQ)
+- tunnel->o_seqno++;
++ if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen))
++ return -ENOMEM;
++
++ flags = tunnel->parms.o_flags;
+
+- gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags,
++ gre_build_header(skb, tunnel->tun_hlen, flags,
+ protocol, tunnel->parms.o_key,
+- htonl(tunnel->o_seqno));
++ (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno))
++ : 0);
+ }
+
+ return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,
+@@ -990,6 +995,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
@@ -150002,7 +231489,16 @@ index 3ad201d372d88..466a5610e3ca9 100644
dsfield = key->tos;
if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
-@@ -1098,6 +1100,7 @@ static void ip6gre_tnl_link_config_common(struct ip6_tnl *t)
+@@ -1050,7 +1056,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
+ /* Push GRE header. */
+ proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN)
+ : htons(ETH_P_ERSPAN2);
+- gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++));
++ gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(atomic_fetch_inc(&t->o_seqno)));
+
+ /* TooBig packet may have updated dst->dev's mtu */
+ if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
+@@ -1098,6 +1104,7 @@ static void ip6gre_tnl_link_config_common(struct ip6_tnl *t)
fl6->flowi6_oif = p->link;
fl6->flowlabel = 0;
fl6->flowi6_proto = IPPROTO_GRE;
@@ -150010,7 +231506,7 @@ index 3ad201d372d88..466a5610e3ca9 100644
if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
-@@ -1544,7 +1547,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
+@@ -1544,7 +1551,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
static struct inet6_protocol ip6gre_protocol __read_mostly = {
.handler = gre_rcv,
.err_handler = ip6gre_err,
@@ -150019,6 +231515,19 @@ index 3ad201d372d88..466a5610e3ca9 100644
};
static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
+diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
+index 80256717868e6..d4b1e2c5aa76d 100644
+--- a/net/ipv6/ip6_input.c
++++ b/net/ipv6/ip6_input.c
+@@ -508,7 +508,7 @@ int ip6_mc_input(struct sk_buff *skb)
+ /*
+ * IPv6 multicast router mode is now supported ;)
+ */
+- if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
++ if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
+ !(ipv6_addr_type(&hdr->daddr) &
+ (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
+ likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 1b9827ff8ccf4..172565d125704 100644
--- a/net/ipv6/ip6_offload.c
@@ -150033,7 +231542,7 @@ index 1b9827ff8ccf4..172565d125704 100644
if (IS_ERR_OR_NULL(segs))
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 2f044a49afa8c..61970fd839c36 100644
+index 2f044a49afa8c..04c3cb4c5fec4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -174,7 +174,7 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff
@@ -150045,6 +231554,15 @@ index 2f044a49afa8c..61970fd839c36 100644
return dst_output(net, sk, skb);
}
#endif
+@@ -485,7 +485,7 @@ int ip6_forward(struct sk_buff *skb)
+ goto drop;
+
+ if (!net->ipv6.devconf_all->disable_policy &&
+- !idev->cnf.disable_policy &&
++ (!idev || !idev->cnf.disable_policy) &&
+ !xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
+ __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
+ goto drop;
@@ -1408,8 +1408,6 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
if (np->frag_size)
mtu = np->frag_size;
@@ -150074,8 +231592,8 @@ index 2f044a49afa8c..61970fd839c36 100644
sizeof(struct frag_hdr) : 0) +
rt->rt6i_nfheader_len;
-+ if (mtu < fragheaderlen ||
-+ ((mtu - fragheaderlen) & ~7) + fragheaderlen < sizeof(struct frag_hdr))
++ if (mtu <= fragheaderlen ||
++ ((mtu - fragheaderlen) & ~7) + fragheaderlen <= sizeof(struct frag_hdr))
+ goto emsgsize;
+
+ maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
@@ -150121,7 +231639,7 @@ index 1d8e3ffa225d8..42c37ec832f15 100644
case SIOCGETTUNNEL:
if (dev == ip6n->fb_tnl_dev) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
-index 36ed9efb88254..6a4065d81aa91 100644
+index 36ed9efb88254..91f1c5f56d5fa 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -248,7 +248,9 @@ static int __net_init ip6mr_rules_init(struct net *net)
@@ -150134,10 +231652,74 @@ index 36ed9efb88254..6a4065d81aa91 100644
err1:
fib_rules_unregister(ops);
return err;
+@@ -737,7 +739,7 @@ static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
+
+ in6_dev = __in6_dev_get(dev);
+ if (in6_dev) {
+- in6_dev->cnf.mc_forwarding--;
++ atomic_dec(&in6_dev->cnf.mc_forwarding);
+ inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
+ NETCONFA_MC_FORWARDING,
+ dev->ifindex, &in6_dev->cnf);
+@@ -905,7 +907,7 @@ static int mif6_add(struct net *net, struct mr_table *mrt,
+
+ in6_dev = __in6_dev_get(dev);
+ if (in6_dev) {
+- in6_dev->cnf.mc_forwarding++;
++ atomic_inc(&in6_dev->cnf.mc_forwarding);
+ inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
+ NETCONFA_MC_FORWARDING,
+ dev->ifindex, &in6_dev->cnf);
+@@ -1555,7 +1557,7 @@ static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
+ } else {
+ rcu_assign_pointer(mrt->mroute_sk, sk);
+ sock_set_flag(sk, SOCK_RCU_FREE);
+- net->ipv6.devconf_all->mc_forwarding++;
++ atomic_inc(&net->ipv6.devconf_all->mc_forwarding);
+ }
+ write_unlock_bh(&mrt_lock);
+
+@@ -1588,7 +1590,7 @@ int ip6mr_sk_done(struct sock *sk)
+ * so the RCU grace period before sk freeing
+ * is guaranteed by sk_destruct()
+ */
+- net->ipv6.devconf_all->mc_forwarding--;
++ atomic_dec(&net->ipv6.devconf_all->mc_forwarding);
+ write_unlock_bh(&mrt_lock);
+ inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
+ NETCONFA_MC_FORWARDING,
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
-index bed8155508c85..909f937befd71 100644
+index bed8155508c85..7f695c39d9a8c 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
+@@ -460,10 +460,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
+ newpsl->sl_addr[i] = psl->sl_addr[i];
+ atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
+ &sk->sk_omem_alloc);
+- kfree_rcu(psl, rcu);
+ }
++ rcu_assign_pointer(pmc->sflist, newpsl);
++ kfree_rcu(psl, rcu);
+ psl = newpsl;
+- rcu_assign_pointer(pmc->sflist, psl);
+ }
+ rv = 1; /* > 0 for insert logic below if sl_count is 0 */
+ for (i = 0; i < psl->sl_count; i++) {
+@@ -565,12 +565,12 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf,
+ psl->sl_count, psl->sl_addr, 0);
+ atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
+ &sk->sk_omem_alloc);
+- kfree_rcu(psl, rcu);
+ } else {
+ ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
+ }
+- mutex_unlock(&idev->mc_lock);
+ rcu_assign_pointer(pmc->sflist, newpsl);
++ mutex_unlock(&idev->mc_lock);
++ kfree_rcu(psl, rcu);
+ pmc->sfmode = gsf->gf_fmode;
+ err = 0;
+ done:
@@ -1371,27 +1371,23 @@ static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
}
@@ -150215,6 +231797,40 @@ index bed8155508c85..909f937befd71 100644
/* <draft-ietf-magma-mld-source-05.txt>:
* use unspecified address as the source address
* when a valid link-local address is not available.
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index 6ab710b5a1a82..118e834e91902 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -24,14 +24,13 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
+ {
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct sock *sk = sk_to_full_sk(sk_partial);
++ struct net_device *dev = skb_dst(skb)->dev;
+ struct flow_keys flkeys;
+ unsigned int hh_len;
+ struct dst_entry *dst;
+ int strict = (ipv6_addr_type(&iph->daddr) &
+ (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
+ struct flowi6 fl6 = {
+- .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
+- strict ? skb_dst(skb)->dev->ifindex : 0,
+ .flowi6_mark = skb->mark,
+ .flowi6_uid = sock_net_uid(net, sk),
+ .daddr = iph->daddr,
+@@ -39,6 +38,13 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
+ };
+ int err;
+
++ if (sk && sk->sk_bound_dev_if)
++ fl6.flowi6_oif = sk->sk_bound_dev_if;
++ else if (strict)
++ fl6.flowi6_oif = dev->ifindex;
++ else
++ fl6.flowi6_oif = l3mdev_master_ifindex(dev);
++
+ fib6_rules_early_flow_dissect(net, skb, &fl6, &flkeys);
+ dst = ip6_route_output(net, sk, &fl6);
+ err = dst->error;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 60f1e4f5be5aa..c51d5ce3711c2 100644
--- a/net/ipv6/raw.c
@@ -150230,7 +231846,7 @@ index 60f1e4f5be5aa..c51d5ce3711c2 100644
return -EFAULT;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
-index 9b9ef09382ab9..e0766bdf20e7d 100644
+index 9b9ef09382ab9..0ca7c780d97a2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2802,7 +2802,7 @@ static void ip6_link_failure(struct sk_buff *skb)
@@ -150242,7 +231858,33 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
}
}
rcu_read_unlock();
-@@ -3680,6 +3680,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh)
+@@ -3303,6 +3303,7 @@ static int ip6_dst_gc(struct dst_ops *ops)
+ int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
+ int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
+ unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
++ unsigned int val;
+ int entries;
+
+ entries = dst_entries_get_fast(ops);
+@@ -3313,13 +3314,13 @@ static int ip6_dst_gc(struct dst_ops *ops)
+ entries <= rt_max_size)
+ goto out;
+
+- net->ipv6.ip6_rt_gc_expire++;
+- fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, true);
++ fib6_run_gc(atomic_inc_return(&net->ipv6.ip6_rt_gc_expire), net, true);
+ entries = dst_entries_get_slow(ops);
+ if (entries < ops->gc_thresh)
+- net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
++ atomic_set(&net->ipv6.ip6_rt_gc_expire, rt_gc_timeout >> 1);
+ out:
+- net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
++ val = atomic_read(&net->ipv6.ip6_rt_gc_expire);
++ atomic_set(&net->ipv6.ip6_rt_gc_expire, val - (val >> rt_elasticity));
+ return entries > rt_max_size;
+ }
+
+@@ -3680,6 +3681,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh)
fib_nh_common_release(&fib6_nh->nh_common);
}
@@ -150268,7 +231910,16 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
gfp_t gfp_flags,
struct netlink_ext_ack *extack)
-@@ -5205,6 +5224,19 @@ out:
+@@ -4490,7 +4510,7 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
+ struct inet6_dev *idev;
+ int type;
+
+- if (netif_is_l3_master(skb->dev) &&
++ if (netif_is_l3_master(skb->dev) ||
+ dst->dev == net->loopback_dev)
+ idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif));
+ else
+@@ -5205,6 +5225,19 @@ out:
return should_notify;
}
@@ -150288,7 +231939,7 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
static int ip6_route_multipath_add(struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{
-@@ -5245,10 +5277,18 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
+@@ -5245,10 +5278,18 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
if (nla) {
@@ -150308,7 +231959,7 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
if (nla)
r_cfg.fc_encap_type = nla_get_u16(nla);
-@@ -5415,7 +5455,13 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,
+@@ -5415,7 +5456,13 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
if (nla) {
@@ -150323,7 +231974,7 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
r_cfg.fc_flags |= RTF_GATEWAY;
}
}
-@@ -5423,6 +5469,7 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,
+@@ -5423,6 +5470,7 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,
if (err)
last_err = err;
@@ -150331,7 +231982,7 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
rtnh = rtnh_next(rtnh, &remaining);
}
-@@ -5720,11 +5767,11 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+@@ -5720,11 +5768,11 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
}
if (!dst) {
@@ -150346,7 +231997,7 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
rtm->rtm_flags |= RTM_F_OFFLOAD_FAILED;
}
-@@ -6182,19 +6229,20 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
+@@ -6182,19 +6230,20 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
struct sk_buff *skb;
int err;
@@ -150373,6 +232024,15 @@ index 9b9ef09382ab9..e0766bdf20e7d 100644
if (!rcu_access_pointer(f6i->fib6_node))
/* The route was removed from the tree, do not send
+@@ -6480,7 +6529,7 @@ static int __net_init ip6_route_net_init(struct net *net)
+ net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
+ net->ipv6.sysctl.skip_notify_on_dev_down = 0;
+
+- net->ipv6.ip6_rt_gc_expire = 30*HZ;
++ atomic_set(&net->ipv6.ip6_rt_gc_expire, 30*HZ);
+
+ ret = 0;
+ out:
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index e412817fba2f3..fa6b64c95d3ae 100644
--- a/net/ipv6/seg6.c
@@ -150529,6 +232189,20 @@ index ef0c7a7c18e23..626cb53aa57ab 100644
free_netdev(sitn->fb_tunnel_dev);
err_alloc_dev:
return err;
+diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
+index e8cfb9e997bf0..ca92dd6981dea 100644
+--- a/net/ipv6/syncookies.c
++++ b/net/ipv6/syncookies.c
+@@ -170,7 +170,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
+ goto out;
+
+ ret = NULL;
+- req = cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops, sk, skb);
++ req = cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops,
++ &tcp_request_sock_ipv6_ops, sk, skb);
+ if (!req)
+ goto out;
+
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b03dd02c9f13c..8eedf59e9cf25 100644
--- a/net/ipv6/tcp_ipv6.c
@@ -150663,6 +232337,207 @@ index 8d785232b4796..932c6f2a54946 100644
fl6.daddr = *daddr;
if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
fl6.saddr = np->saddr;
+diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
+index d0d280077721b..ad07904642cad 100644
+--- a/net/ipv6/xfrm6_output.c
++++ b/net/ipv6/xfrm6_output.c
+@@ -45,6 +45,19 @@ static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buf
+ return xfrm_output(sk, skb);
+ }
+
++static int xfrm6_noneed_fragment(struct sk_buff *skb)
++{
++ struct frag_hdr *fh;
++ u8 prevhdr = ipv6_hdr(skb)->nexthdr;
++
++ if (prevhdr != NEXTHDR_FRAGMENT)
++ return 0;
++ fh = (struct frag_hdr *)(skb->data + sizeof(struct ipv6hdr));
++ if (fh->nexthdr == NEXTHDR_ESP || fh->nexthdr == NEXTHDR_AUTH)
++ return 1;
++ return 0;
++}
++
+ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+ {
+ struct dst_entry *dst = skb_dst(skb);
+@@ -73,6 +86,9 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+ xfrm6_local_rxpmtu(skb, mtu);
+ kfree_skb(skb);
+ return -EMSGSIZE;
++ } else if (toobig && xfrm6_noneed_fragment(skb)) {
++ skb->ignore_df = 1;
++ goto skip_frag;
+ } else if (!skb->ignore_df && toobig && skb->sk) {
+ xfrm_local_error(skb, mtu);
+ kfree_skb(skb);
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index de24a7d474dfd..92e9d75dba2f4 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1699,7 +1699,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
+
+ xfrm_probe_algs();
+
+- supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);
++ supp_skb = compose_sadb_supported(hdr, GFP_KERNEL | __GFP_ZERO);
+ if (!supp_skb) {
+ if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
+ pfk->registered &= ~(1<<hdr->sadb_msg_satype);
+@@ -2623,7 +2623,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
+ }
+
+ return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
+- kma ? &k : NULL, net, NULL);
++ kma ? &k : NULL, net, NULL, 0);
+
+ out:
+ return err;
+@@ -2826,8 +2826,10 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
+ void *ext_hdrs[SADB_EXT_MAX];
+ int err;
+
+- pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
+- BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
++ err = pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
++ BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
++ if (err)
++ return err;
+
+ memset(ext_hdrs, 0, sizeof(ext_hdrs));
+ err = parse_exthdrs(skb, hdr, ext_hdrs);
+diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
+index 17927966abb33..8b14a24f10404 100644
+--- a/net/l3mdev/l3mdev.c
++++ b/net/l3mdev/l3mdev.c
+@@ -147,7 +147,7 @@ int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
+
+ dev = dev_get_by_index_rcu(net, ifindex);
+ while (dev && !netif_is_l3_master(dev))
+- dev = netdev_master_upper_dev_get(dev);
++ dev = netdev_master_upper_dev_get_rcu(dev);
+
+ return dev ? dev->ifindex : 0;
+ }
+diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
+index 3086f4a6ae683..99305aadaa087 100644
+--- a/net/llc/af_llc.c
++++ b/net/llc/af_llc.c
+@@ -275,6 +275,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
+ {
+ struct sock *sk = sock->sk;
+ struct llc_sock *llc = llc_sk(sk);
++ struct net_device *dev = NULL;
+ struct llc_sap *sap;
+ int rc = -EINVAL;
+
+@@ -286,14 +287,14 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
+ goto out;
+ rc = -ENODEV;
+ if (sk->sk_bound_dev_if) {
+- llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
+- if (llc->dev && addr->sllc_arphrd != llc->dev->type) {
+- dev_put(llc->dev);
+- llc->dev = NULL;
++ dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
++ if (dev && addr->sllc_arphrd != dev->type) {
++ dev_put(dev);
++ dev = NULL;
+ }
+ } else
+- llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
+- if (!llc->dev)
++ dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
++ if (!dev)
+ goto out;
+ rc = -EUSERS;
+ llc->laddr.lsap = llc_ui_autoport();
+@@ -303,6 +304,11 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
+ sap = llc_sap_open(llc->laddr.lsap, NULL);
+ if (!sap)
+ goto out;
++
++ /* Note: We do not expect errors from this point. */
++ llc->dev = dev;
++ dev = NULL;
++
+ memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
+ memcpy(&llc->addr, addr, sizeof(llc->addr));
+ /* assign new connection to its SAP */
+@@ -310,6 +316,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
+ sock_reset_flag(sk, SOCK_ZAPPED);
+ rc = 0;
+ out:
++ dev_put(dev);
+ return rc;
+ }
+
+@@ -332,6 +339,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
+ struct sock *sk = sock->sk;
+ struct llc_sock *llc = llc_sk(sk);
++ struct net_device *dev = NULL;
+ struct llc_sap *sap;
+ int rc = -EINVAL;
+
+@@ -347,25 +355,27 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ rc = -ENODEV;
+ rcu_read_lock();
+ if (sk->sk_bound_dev_if) {
+- llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
+- if (llc->dev) {
++ dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
++ if (dev) {
+ if (is_zero_ether_addr(addr->sllc_mac))
+- memcpy(addr->sllc_mac, llc->dev->dev_addr,
++ memcpy(addr->sllc_mac, dev->dev_addr,
+ IFHWADDRLEN);
+- if (addr->sllc_arphrd != llc->dev->type ||
++ if (addr->sllc_arphrd != dev->type ||
+ !ether_addr_equal(addr->sllc_mac,
+- llc->dev->dev_addr)) {
++ dev->dev_addr)) {
+ rc = -EINVAL;
+- llc->dev = NULL;
++ dev = NULL;
+ }
+ }
+- } else
+- llc->dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd,
++ } else {
++ dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd,
+ addr->sllc_mac);
+- dev_hold(llc->dev);
++ }
++ dev_hold(dev);
+ rcu_read_unlock();
+- if (!llc->dev)
++ if (!dev)
+ goto out;
++
+ if (!addr->sllc_sap) {
+ rc = -EUSERS;
+ addr->sllc_sap = llc_ui_autoport();
+@@ -397,6 +407,11 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ goto out_put;
+ }
+ }
++
++ /* Note: We do not expect errors from this point. */
++ llc->dev = dev;
++ dev = NULL;
++
+ llc->laddr.lsap = addr->sllc_sap;
+ memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
+ memcpy(&llc->addr, addr, sizeof(llc->addr));
+@@ -407,6 +422,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ out_put:
+ llc_sap_put(sap);
+ out:
++ dev_put(dev);
+ release_sock(sk);
+ return rc;
+ }
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index cce28e3b22323..ef729b1e39ea3 100644
--- a/net/mac80211/agg-rx.c
@@ -150687,7 +232562,7 @@ index cce28e3b22323..ef729b1e39ea3 100644
return;
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 430a585875388..74a878f213d3e 100644
+index 430a585875388..1deb3d874a4b9 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -9,7 +9,7 @@
@@ -150695,7 +232570,7 @@ index 430a585875388..74a878f213d3e 100644
* Copyright 2007-2010, Intel Corporation
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2020 Intel Corporation
-+ * Copyright (C) 2018 - 2021 Intel Corporation
++ * Copyright (C) 2018 - 2022 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -150743,7 +232618,22 @@ index 430a585875388..74a878f213d3e 100644
if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
return;
} else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
-@@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
+@@ -625,6 +626,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
+ return -EINVAL;
+ }
+
++ if (test_sta_flag(sta, WLAN_STA_MFP) &&
++ !test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
++ ht_dbg(sdata,
++ "MFP STA not authorized - deny BA session request %pM tid %d\n",
++ sta->sta.addr, tid);
++ return -EINVAL;
++ }
++
+ /*
+ * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a
+ * member of an IBSS, and has no other existing Block Ack agreement
+@@ -889,6 +898,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
bool send_delba = false;
@@ -150751,7 +232641,7 @@ index 430a585875388..74a878f213d3e 100644
ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
sta->sta.addr, tid);
-@@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
+@@ -906,10 +916,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
send_delba = true;
ieee80211_remove_tid_tx(sta, tid);
@@ -150767,7 +232657,7 @@ index 430a585875388..74a878f213d3e 100644
ieee80211_send_delba(sdata, sta->sta.addr, tid,
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index d69b31c20fe28..1bf83b8d84021 100644
+index d69b31c20fe28..3f625e836a03f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -80,7 +80,8 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
@@ -150801,7 +232691,30 @@ index d69b31c20fe28..1bf83b8d84021 100644
return err;
}
-@@ -2669,7 +2674,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
+@@ -2105,14 +2110,12 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
+ const struct mesh_setup *setup)
+ {
+ u8 *new_ie;
+- const u8 *old_ie;
+ struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
+ struct ieee80211_sub_if_data, u.mesh);
+ int i;
+
+ /* allocate information elements */
+ new_ie = NULL;
+- old_ie = ifmsh->ie;
+
+ if (setup->ie_len) {
+ new_ie = kmemdup(setup->ie, setup->ie_len,
+@@ -2122,7 +2125,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
+ }
+ ifmsh->ie_len = setup->ie_len;
+ ifmsh->ie = new_ie;
+- kfree(old_ie);
+
+ /* now copy the rest of the setup parameters */
+ ifmsh->mesh_id_len = setup->mesh_id_len;
+@@ -2669,7 +2671,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
@@ -150811,7 +232724,7 @@ index d69b31c20fe28..1bf83b8d84021 100644
if (!sdata)
return -EOPNOTSUPP;
}
-@@ -2729,7 +2735,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
+@@ -2729,7 +2732,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
mutex_unlock(&local->iflist_mtx);
if (has_monitor) {
@@ -150839,7 +232752,7 @@ index cd3731cbf6c68..c336267f4599c 100644
if (!check_sdata_in_driver(sdata))
return;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
-index 159af6c3ffb05..6a88195e5abef 100644
+index 159af6c3ffb05..d30bd21697a3b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -376,7 +376,7 @@ struct ieee80211_mgd_auth_data {
@@ -150889,6 +232802,15 @@ index 159af6c3ffb05..6a88195e5abef 100644
int mesh_paths_generation;
int mpp_paths_generation;
};
+@@ -2359,7 +2379,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ const struct cfg80211_chan_def *chandef);
+ u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
+-u8 *ieee80211_ie_build_he_cap(u8 *pos,
++u8 *ieee80211_ie_build_he_cap(u32 disable_flags, u8 *pos,
+ const struct ieee80211_sta_he_cap *he_cap,
+ u8 *end);
+ void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 62c95597704b4..041859b5b71d0 100644
--- a/net/mac80211/iface.c
@@ -150946,6 +232868,46 @@ index fb3aaa3c56069..b71a1428d883c 100644
local->tpt_led_trigger->rx_bytes += bytes;
#endif
}
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index 45fb517591ee9..5311c3cd3050d 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -1131,17 +1131,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ local->scan_ies_len +=
+ 2 + sizeof(struct ieee80211_vht_cap);
+
+- /* HE cap element is variable in size - set len to allow max size */
+ /*
+- * TODO: 1 is added at the end of the calculation to accommodate for
+- * the temporary placing of the HE capabilities IE under EXT.
+- * Remove it once it is placed in the final place.
+- */
+- if (supp_he)
++ * HE cap element is variable in size - set len to allow max size */
++ if (supp_he) {
+ local->scan_ies_len +=
+- 2 + sizeof(struct ieee80211_he_cap_elem) +
++ 3 + sizeof(struct ieee80211_he_cap_elem) +
+ sizeof(struct ieee80211_he_mcs_nss_supp) +
+- IEEE80211_HE_PPE_THRES_MAX_LEN + 1;
++ IEEE80211_HE_PPE_THRES_MAX_LEN;
++ }
+
+ if (!local->ops->hw_scan) {
+ /* For hw_scan, driver needs to set these up. */
+diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
+index 5dcfd53a4ab6c..42bd81a303101 100644
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -580,7 +580,7 @@ int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
+ return -ENOMEM;
+
+ pos = skb_put(skb, ie_len);
+- ieee80211_ie_build_he_cap(pos, he_cap, pos + ie_len);
++ ieee80211_ie_build_he_cap(0, pos, he_cap, pos + ie_len);
+
+ return 0;
+ }
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 77080b4f87b8a..b2b717a78114f 100644
--- a/net/mac80211/mesh.h
@@ -151201,7 +233163,7 @@ index 7cab1cf09bf1a..acc1c299f1ae5 100644
+ mesh_table_free(&sdata->u.mesh.mpp_paths);
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
-index c0ea3b1aa9e1c..6c8505edce75b 100644
+index c0ea3b1aa9e1c..1548f532dc1ad 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -37,6 +37,7 @@
@@ -151212,7 +233174,41 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_TIMEOUT_LONG (HZ / 2)
#define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
-@@ -664,7 +665,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
+@@ -629,7 +630,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb,
+ struct ieee80211_supported_band *sband)
+ {
+- u8 *pos;
++ u8 *pos, *pre_he_pos;
+ const struct ieee80211_sta_he_cap *he_cap = NULL;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ u8 he_cap_size;
+@@ -646,25 +647,26 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
+
+ he_cap = ieee80211_get_he_iftype_cap(sband,
+ ieee80211_vif_type_p2p(&sdata->vif));
+- if (!he_cap || !reg_cap)
++ if (!he_cap || !chanctx_conf || !reg_cap)
+ return;
+
+- /*
+- * TODO: the 1 added is because this temporarily is under the EXTENSION
+- * IE. Get rid of it when it moves.
+- */
++ /* get a max size estimate */
+ he_cap_size =
+ 2 + 1 + sizeof(he_cap->he_cap_elem) +
+ ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem) +
+ ieee80211_he_ppe_size(he_cap->ppe_thres[0],
+ he_cap->he_cap_elem.phy_cap_info);
+ pos = skb_put(skb, he_cap_size);
+- ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
++ pre_he_pos = pos;
++ pos = ieee80211_ie_build_he_cap(sdata->u.mgd.flags,
++ pos, he_cap, pos + he_cap_size);
++ /* trim excess if any */
++ skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos));
+
ieee80211_ie_build_he_6ghz_cap(sdata, skb);
}
@@ -151221,7 +233217,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-@@ -684,6 +685,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
+@@ -684,6 +686,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_prep_tx_info info = {};
@@ -151229,7 +233225,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
/* we know it's writable, cast away the const */
if (assoc_data->ie_len)
-@@ -697,7 +699,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
+@@ -697,7 +700,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock();
@@ -151238,7 +233234,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
}
chan = chanctx_conf->def.chan;
rcu_read_unlock();
-@@ -748,7 +750,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
+@@ -748,7 +751,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
(iftd ? iftd->vendor_elems.len : 0),
GFP_KERNEL);
if (!skb)
@@ -151247,7 +233243,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
skb_reserve(skb, local->hw.extra_tx_headroom);
-@@ -1029,15 +1031,22 @@ skip_rates:
+@@ -1029,15 +1032,22 @@ skip_rates:
skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
}
@@ -151274,7 +233270,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
ifmgd->assoc_req_ies_len = pos - ie_start;
drv_mgd_prepare_tx(local, sdata, &info);
-@@ -1047,6 +1056,8 @@ skip_rates:
+@@ -1047,6 +1057,8 @@ skip_rates:
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_INTFL_MLME_CONN_TX;
ieee80211_tx_skb(sdata, skb);
@@ -151283,7 +233279,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
}
void ieee80211_send_pspoll(struct ieee80211_local *local,
-@@ -2446,11 +2457,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
+@@ -2446,11 +2458,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
u16 tx_time)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -151305,7 +233301,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
if (likely(!tx_tspec->admitted_time))
return;
-@@ -2977,8 +2995,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+@@ -2977,8 +2996,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
(status_code == WLAN_STATUS_ANTI_CLOG_REQUIRED ||
(auth_transaction == 1 &&
(status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
@@ -151322,7 +233318,20 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
sdata_info(sdata, "%pM denied authentication (status %d)\n",
mgmt->sa, status_code);
-@@ -4444,6 +4469,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
+@@ -3515,6 +3541,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
+ cbss->transmitted_bss->bssid);
+ bss_conf->bssid_indicator = cbss->max_bssid_indicator;
+ bss_conf->bssid_index = cbss->bssid_index;
++ } else {
++ bss_conf->nontransmitted = false;
++ memset(bss_conf->transmitter_bssid, 0,
++ sizeof(bss_conf->transmitter_bssid));
++ bss_conf->bssid_indicator = 0;
++ bss_conf->bssid_index = 0;
+ }
+
+ /*
+@@ -4444,6 +4476,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
struct ieee80211_local *local = sdata->local;
@@ -151330,7 +233339,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
sdata_assert_lock(sdata);
-@@ -4464,7 +4490,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
+@@ -4464,7 +4497,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
sdata_info(sdata, "associate with %pM (try %d/%d)\n",
assoc_data->bss->bssid, assoc_data->tries,
IEEE80211_ASSOC_MAX_TRIES);
@@ -151341,7 +233350,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
-@@ -4537,10 +4565,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
+@@ -4537,10 +4572,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (ifmgd->auth_data && ifmgd->auth_data->timeout_started &&
time_after(jiffies, ifmgd->auth_data->timeout)) {
@@ -151355,7 +233364,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
*/
ieee80211_destroy_auth_data(sdata, false);
} else if (ieee80211_auth(sdata)) {
-@@ -5209,7 +5237,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
+@@ -5209,7 +5244,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
*/
if (new_sta) {
u32 rates = 0, basic_rates = 0;
@@ -151365,7 +233374,7 @@ index c0ea3b1aa9e1c..6c8505edce75b 100644
const struct cfg80211_bss_ies *ies;
int shift = ieee80211_vif_get_shift(&sdata->vif);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index c4071b015c188..eab6283b3479c 100644
+index c4071b015c188..743e97ba352c8 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -364,7 +364,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
@@ -151377,7 +233386,17 @@ index c4071b015c188..eab6283b3479c 100644
/* the order of the following fields is important */
-@@ -1952,7 +1952,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
+@@ -1400,8 +1400,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
+ goto dont_reorder;
+
+ /* not part of a BA session */
+- if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
+- ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
++ if (ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
+ goto dont_reorder;
+
+ /* new, potentially un-ordered, ampdu frame - process it */
+@@ -1952,7 +1951,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
int keyid = rx->sta->ptk_idx;
sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
@@ -151387,7 +233406,7 @@ index c4071b015c188..eab6283b3479c 100644
cs = rx->sta->cipher_scheme;
keyid = ieee80211_get_keyid(rx->skb, cs);
-@@ -2601,7 +2602,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
+@@ -2601,7 +2601,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
* address, so that the authenticator (e.g. hostapd) will see
* the frame, but bridge won't forward it anywhere else. Note
* that due to earlier filtering, the only other address can
@@ -151397,7 +233416,7 @@ index c4071b015c188..eab6283b3479c 100644
*/
if (unlikely(skb->protocol == sdata->control_port_protocol &&
!ether_addr_equal(ehdr->h_dest, sdata->vif.addr)))
-@@ -2916,13 +2918,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
+@@ -2916,13 +2917,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
ether_addr_equal(sdata->vif.addr, hdr->addr3))
return RX_CONTINUE;
@@ -151413,7 +233432,7 @@ index c4071b015c188..eab6283b3479c 100644
if (!--mesh_hdr->ttl) {
if (!is_multicast_ether_addr(hdr->addr1))
-@@ -4517,12 +4519,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
+@@ -4517,12 +4518,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
/* deliver to local stack */
skb->protocol = eth_type_trans(skb, fast_rx->dev);
@@ -151427,7 +233446,7 @@ index c4071b015c188..eab6283b3479c 100644
}
static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
-@@ -4873,6 +4870,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
+@@ -4873,6 +4869,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
struct ieee80211_rate *rate = NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
@@ -151435,7 +233454,7 @@ index c4071b015c188..eab6283b3479c 100644
WARN_ON_ONCE(softirq_count() == 0);
-@@ -4931,7 +4929,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
+@@ -4931,7 +4928,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
goto drop;
break;
case RX_ENC_VHT:
@@ -151444,7 +233463,7 @@ index c4071b015c188..eab6283b3479c 100644
!status->nss ||
status->nss > 8,
"Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
-@@ -4969,9 +4967,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
+@@ -4969,9 +4966,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
if (!(status->flag & RX_FLAG_8023))
skb = ieee80211_rx_monitor(local, skb, rate);
if (skb) {
@@ -151649,7 +233668,7 @@ index 8921088a5df65..a499b07fee336 100644
return result;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
-index 49cb96d251695..2fe71ed9137b0 100644
+index 49cb96d251695..be1911d8089fa 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -796,7 +796,7 @@ static void __iterate_interfaces(struct ieee80211_local *local,
@@ -151675,6 +233694,15 @@ index 49cb96d251695..2fe71ed9137b0 100644
switch (elem->data[0]) {
case WLAN_EID_EXT_HE_MU_EDCA:
+@@ -1954,7 +1959,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
+ if (he_cap &&
+ cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band),
+ IEEE80211_CHAN_NO_HE)) {
+- pos = ieee80211_ie_build_he_cap(pos, he_cap, end);
++ pos = ieee80211_ie_build_he_cap(0, pos, he_cap, end);
+ if (!pos)
+ goto out_err;
+ }
@@ -2379,7 +2384,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
@@ -151694,6 +233722,55 @@ index 49cb96d251695..2fe71ed9137b0 100644
if (sdata && ieee80211_sdata_running(sdata))
ieee80211_assign_chanctx(local, sdata);
}
+@@ -2897,10 +2903,11 @@ u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
+ he_cap->he_cap_elem.phy_cap_info);
+ }
+
+-u8 *ieee80211_ie_build_he_cap(u8 *pos,
++u8 *ieee80211_ie_build_he_cap(u32 disable_flags, u8 *pos,
+ const struct ieee80211_sta_he_cap *he_cap,
+ u8 *end)
+ {
++ struct ieee80211_he_cap_elem elem;
+ u8 n;
+ u8 ie_len;
+ u8 *orig_pos = pos;
+@@ -2913,7 +2920,23 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
+ if (!he_cap)
+ return orig_pos;
+
+- n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem);
++ /* modify on stack first to calculate 'n' and 'ie_len' correctly */
++ elem = he_cap->he_cap_elem;
++
++ if (disable_flags & IEEE80211_STA_DISABLE_40MHZ)
++ elem.phy_cap_info[0] &=
++ ~(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G);
++
++ if (disable_flags & IEEE80211_STA_DISABLE_160MHZ)
++ elem.phy_cap_info[0] &=
++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
++
++ if (disable_flags & IEEE80211_STA_DISABLE_80P80MHZ)
++ elem.phy_cap_info[0] &=
++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
++
++ n = ieee80211_he_mcs_nss_size(&elem);
+ ie_len = 2 + 1 +
+ sizeof(he_cap->he_cap_elem) + n +
+ ieee80211_he_ppe_size(he_cap->ppe_thres[0],
+@@ -2927,8 +2950,8 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
+ *pos++ = WLAN_EID_EXT_HE_CAPABILITY;
+
+ /* Fixed data */
+- memcpy(pos, &he_cap->he_cap_elem, sizeof(he_cap->he_cap_elem));
+- pos += sizeof(he_cap->he_cap_elem);
++ memcpy(pos, &elem, sizeof(elem));
++ pos += sizeof(elem);
+
+ memcpy(pos, &he_cap->he_mcs_nss_supp, n);
+ pos += n;
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 9ea6004abe1be..62c6733e07923 100644
--- a/net/mac80211/wme.c
@@ -151766,9 +233843,18 @@ index a9526ac29dffe..85cc1a28cbe9f 100644
}
diff --git a/net/mctp/route.c b/net/mctp/route.c
-index 5ca186d53cb0f..fb1bf4ec85296 100644
+index 5ca186d53cb0f..bbb13dbc9227d 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
+@@ -396,7 +396,7 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb)
+
+ rc = dev_hard_header(skb, skb->dev, ntohs(skb->protocol),
+ daddr, skb->dev->dev_addr, skb->len);
+- if (rc) {
++ if (rc < 0) {
+ kfree_skb(skb);
+ return -EHOSTUNREACH;
+ }
@@ -760,7 +760,7 @@ static int mctp_route_add(struct mctp_dev *mdev, mctp_eid_t daddr_start,
}
@@ -151973,9 +234059,27 @@ index ecd3d8b117e0b..2966fcb6548ba 100644
MPTCP_MIB_MPPRIOTX, /* Transmit a MP_PRIO */
MPTCP_MIB_MPPRIORX, /* Received a MP_PRIO */
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
-index f0f22eb4fd5f7..e515ba9ccb5d8 100644
+index f0f22eb4fd5f7..193f0fcce8d85 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
+@@ -107,7 +107,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
+ ptr += 2;
+ }
+ if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) {
+- mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
++ mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
+ mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
+ ptr += 2;
+ }
+@@ -221,7 +221,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
+
+ if (opsize == expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) {
+ mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
+- mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
++ mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
+ ptr += 2;
+ }
+
@@ -422,28 +422,6 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
return false;
}
@@ -152054,7 +234158,54 @@ index f0f22eb4fd5f7..e515ba9ccb5d8 100644
new_wnd_end = new_snd_una + tcp_sk(ssk)->snd_wnd;
-@@ -1334,6 +1321,7 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
+@@ -1227,7 +1214,7 @@ static void mptcp_set_rwin(const struct tcp_sock *tp)
+ WRITE_ONCE(msk->rcv_wnd_sent, ack_seq);
+ }
+
+-static u16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __sum16 sum)
++__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)
+ {
+ struct csum_pseudo_header header;
+ __wsum csum;
+@@ -1242,14 +1229,24 @@ static u16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __sum1
+ header.data_len = htons(data_len);
+ header.csum = 0;
+
+- csum = csum_partial(&header, sizeof(header), ~csum_unfold(sum));
+- return (__force u16)csum_fold(csum);
++ csum = csum_partial(&header, sizeof(header), sum);
++ return csum_fold(csum);
+ }
+
+-static u16 mptcp_make_csum(const struct mptcp_ext *mpext)
++static __sum16 mptcp_make_csum(const struct mptcp_ext *mpext)
+ {
+ return __mptcp_make_csum(mpext->data_seq, mpext->subflow_seq, mpext->data_len,
+- mpext->csum);
++ ~csum_unfold(mpext->csum));
++}
++
++static void put_len_csum(u16 len, __sum16 csum, void *data)
++{
++ __sum16 *sumptr = data + 2;
++ __be16 *ptr = data;
++
++ put_unaligned_be16(len, ptr);
++
++ put_unaligned(csum, sumptr);
+ }
+
+ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
+@@ -1328,12 +1325,14 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
+ put_unaligned_be32(mpext->subflow_seq, ptr);
+ ptr += 1;
+ if (opts->csum_reqd) {
+- put_unaligned_be32(mpext->data_len << 16 |
+- mptcp_make_csum(mpext), ptr);
++ put_len_csum(mpext->data_len,
++ mptcp_make_csum(mpext),
++ ptr);
+ } else {
put_unaligned_be32(mpext->data_len << 16 |
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
}
@@ -152062,6 +234213,24 @@ index f0f22eb4fd5f7..e515ba9ccb5d8 100644
}
} else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
+@@ -1376,11 +1375,12 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
+ goto mp_capable_done;
+
+ if (opts->csum_reqd) {
+- put_unaligned_be32(opts->data_len << 16 |
+- __mptcp_make_csum(opts->data_seq,
+- opts->subflow_seq,
+- opts->data_len,
+- opts->csum), ptr);
++ put_len_csum(opts->data_len,
++ __mptcp_make_csum(opts->data_seq,
++ opts->subflow_seq,
++ opts->data_len,
++ ~csum_unfold(opts->csum)),
++ ptr);
+ } else {
+ put_unaligned_be32(opts->data_len << 16 |
+ TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 6ab386ff32944..d9790d6fbce9c 100644
--- a/net/mptcp/pm.c
@@ -152460,7 +234629,7 @@ index d073b21113828..d6def23b8cba0 100644
static int mptcp_hash(struct sock *sk)
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
-index dc984676c5eb1..82c5dc4d6b49d 100644
+index dc984676c5eb1..e193b710b471a 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -401,6 +401,7 @@ struct mptcp_delegated_action {
@@ -152471,7 +234640,17 @@ index dc984676c5eb1..82c5dc4d6b49d 100644
/* MPTCP subflow context */
struct mptcp_subflow_context {
-@@ -506,23 +507,23 @@ static inline void mptcp_add_pending_subflow(struct mptcp_sock *msk,
+@@ -435,7 +436,8 @@ struct mptcp_subflow_context {
+ rx_eof : 1,
+ can_ack : 1, /* only after processing the remote a key */
+ disposable : 1, /* ctx can be free at ulp release time */
+- stale : 1; /* unable to snd/rcv data, do not use for xmit */
++ stale : 1, /* unable to snd/rcv data, do not use for xmit */
++ valid_csum_seen : 1; /* at least one csum validated */
+ enum mptcp_data_avail data_avail;
+ u32 remote_nonce;
+ u64 thmac;
+@@ -506,23 +508,23 @@ static inline void mptcp_add_pending_subflow(struct mptcp_sock *msk,
void mptcp_subflow_process_delegated(struct sock *ssk);
@@ -152500,7 +234679,7 @@ index dc984676c5eb1..82c5dc4d6b49d 100644
delegated = this_cpu_ptr(&mptcp_delegated_actions);
schedule = list_empty(&delegated->head);
list_add_tail(&subflow->delegated_node, &delegated->head);
-@@ -547,16 +548,16 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated)
+@@ -547,16 +549,16 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated)
static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow)
{
@@ -152520,6 +234699,14 @@ index dc984676c5eb1..82c5dc4d6b49d 100644
}
int mptcp_is_enabled(const struct net *net);
+@@ -717,6 +719,7 @@ void mptcp_token_destroy(struct mptcp_sock *msk);
+ void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn);
+
+ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac);
++__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum);
+
+ void __init mptcp_pm_init(void);
+ void mptcp_pm_data_init(struct mptcp_sock *msk);
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 8c03afac5ca03..4bb305342fcc7 100644
--- a/net/mptcp/sockopt.c
@@ -152532,6 +234719,79 @@ index 8c03afac5ca03..4bb305342fcc7 100644
case TCP_CORK:
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index 6172f380dfb76..5ef9013b94c74 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -845,9 +845,8 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
+ bool csum_reqd)
+ {
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+- struct csum_pseudo_header header;
+ u32 offset, seq, delta;
+- __wsum csum;
++ __sum16 csum;
+ int len;
+
+ if (!csum_reqd)
+@@ -908,19 +907,20 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
+ * while the pseudo header requires the original DSS data len,
+ * including that
+ */
+- header.data_seq = cpu_to_be64(subflow->map_seq);
+- header.subflow_seq = htonl(subflow->map_subflow_seq);
+- header.data_len = htons(subflow->map_data_len + subflow->map_data_fin);
+- header.csum = 0;
+-
+- csum = csum_partial(&header, sizeof(header), subflow->map_data_csum);
+- if (unlikely(csum_fold(csum))) {
++ csum = __mptcp_make_csum(subflow->map_seq,
++ subflow->map_subflow_seq,
++ subflow->map_data_len + subflow->map_data_fin,
++ subflow->map_data_csum);
++ if (unlikely(csum)) {
+ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR);
+- subflow->send_mp_fail = 1;
+- MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
++ if (subflow->mp_join || subflow->valid_csum_seen) {
++ subflow->send_mp_fail = 1;
++ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
++ }
+ return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY;
+ }
+
++ subflow->valid_csum_seen = 1;
+ return MAPPING_OK;
+ }
+
+@@ -1102,6 +1102,18 @@ static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ss
+ }
+ }
+
++static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
++{
++ struct mptcp_sock *msk = mptcp_sk(subflow->conn);
++
++ if (subflow->mp_join)
++ return false;
++ else if (READ_ONCE(msk->csum_enabled))
++ return !subflow->valid_csum_seen;
++ else
++ return !subflow->fully_established;
++}
++
+ static bool subflow_check_data_avail(struct sock *ssk)
+ {
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+@@ -1179,7 +1191,7 @@ fallback:
+ return true;
+ }
+
+- if (subflow->mp_join || subflow->fully_established) {
++ if (!subflow_can_fallback(subflow)) {
+ /* fatal protocol error, close the socket.
+ * subflow_error_report() will introduce the appropriate barriers
+ */
diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
index ba9ae482141b0..dda8b76b77988 100644
--- a/net/ncsi/ncsi-cmd.c
@@ -152633,6 +234893,19 @@ index 63d032191e626..60332fdb6dd44 100644
#ifdef CONFIG_NETFILTER_INGRESS
if (nf_ingress_hook(reg, pf))
net_inc_ingress_queue();
+diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
+index 2c467c422dc63..fb67f1ca2495b 100644
+--- a/net/netfilter/ipvs/ip_vs_conn.c
++++ b/net/netfilter/ipvs/ip_vs_conn.c
+@@ -1495,7 +1495,7 @@ int __init ip_vs_conn_init(void)
+ pr_info("Connection hash table configured "
+ "(size=%d, memory=%ldKbytes)\n",
+ ip_vs_conn_tab_size,
+- (long)(ip_vs_conn_tab_size*sizeof(struct list_head))/1024);
++ (long)(ip_vs_conn_tab_size*sizeof(*ip_vs_conn_tab))/1024);
+ IP_VS_DBG(0, "Each connection entry needs %zd bytes at least\n",
+ sizeof(struct ip_vs_conn));
+
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 128690c512dff..393058a43aa73 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
@@ -152666,10 +234939,87 @@ index 128690c512dff..393058a43aa73 100644
if (!atomic_read(&cp->n_control)) {
resched = true;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
-index 770a63103c7a4..7f79974607643 100644
+index 770a63103c7a4..31399c53dfb13 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
-@@ -684,7 +684,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
+@@ -66,6 +66,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash);
+ struct conntrack_gc_work {
+ struct delayed_work dwork;
+ u32 next_bucket;
++ u32 avg_timeout;
++ u32 start_time;
+ bool exiting;
+ bool early_drop;
+ };
+@@ -77,8 +79,19 @@ static __read_mostly bool nf_conntrack_locks_all;
+ /* serialize hash resizes and nf_ct_iterate_cleanup */
+ static DEFINE_MUTEX(nf_conntrack_mutex);
+
+-#define GC_SCAN_INTERVAL (120u * HZ)
++#define GC_SCAN_INTERVAL_MAX (60ul * HZ)
++#define GC_SCAN_INTERVAL_MIN (1ul * HZ)
++
++/* clamp timeouts to this value (TCP unacked) */
++#define GC_SCAN_INTERVAL_CLAMP (300ul * HZ)
++
++/* large initial bias so that we don't scan often just because we have
++ * three entries with a 1s timeout.
++ */
++#define GC_SCAN_INTERVAL_INIT INT_MAX
++
+ #define GC_SCAN_MAX_DURATION msecs_to_jiffies(10)
++#define GC_SCAN_EXPIRED_MAX (64000u / HZ)
+
+ #define MIN_CHAINLEN 8u
+ #define MAX_CHAINLEN (32u - MIN_CHAINLEN)
+@@ -558,7 +571,7 @@ static void nf_ct_del_from_dying_or_unconfirmed_list(struct nf_conn *ct)
+
+ #define NFCT_ALIGN(len) (((len) + NFCT_INFOMASK) & ~NFCT_INFOMASK)
+
+-/* Released via destroy_conntrack() */
++/* Released via nf_ct_destroy() */
+ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
+ const struct nf_conntrack_zone *zone,
+ gfp_t flags)
+@@ -585,7 +598,7 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
+ tmpl->status = IPS_TEMPLATE;
+ write_pnet(&tmpl->ct_net, net);
+ nf_ct_zone_add(tmpl, zone);
+- atomic_set(&tmpl->ct_general.use, 0);
++ refcount_set(&tmpl->ct_general.use, 1);
+
+ return tmpl;
+ }
+@@ -612,13 +625,12 @@ static void destroy_gre_conntrack(struct nf_conn *ct)
+ #endif
+ }
+
+-static void
+-destroy_conntrack(struct nf_conntrack *nfct)
++void nf_ct_destroy(struct nf_conntrack *nfct)
+ {
+ struct nf_conn *ct = (struct nf_conn *)nfct;
+
+- pr_debug("destroy_conntrack(%p)\n", ct);
+- WARN_ON(atomic_read(&nfct->use) != 0);
++ pr_debug("%s(%p)\n", __func__, ct);
++ WARN_ON(refcount_read(&nfct->use) != 0);
+
+ if (unlikely(nf_ct_is_template(ct))) {
+ nf_ct_tmpl_free(ct);
+@@ -643,9 +655,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
+ if (ct->master)
+ nf_ct_put(ct->master);
+
+- pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
++ pr_debug("%s: returning ct=%p to slab\n", __func__, ct);
+ nf_conntrack_free(ct);
+ }
++EXPORT_SYMBOL(nf_ct_destroy);
+
+ static void nf_ct_delete_from_lists(struct nf_conn *ct)
+ {
+@@ -684,7 +697,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
tstamp = nf_conn_tstamp_find(ct);
if (tstamp) {
@@ -152678,7 +235028,52 @@ index 770a63103c7a4..7f79974607643 100644
tstamp->stop = ktime_get_real_ns();
if (timeout < 0)
-@@ -1036,7 +1036,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx)
+@@ -742,7 +755,7 @@ nf_ct_match(const struct nf_conn *ct1, const struct nf_conn *ct2)
+ /* caller must hold rcu readlock and none of the nf_conntrack_locks */
+ static void nf_ct_gc_expired(struct nf_conn *ct)
+ {
+- if (!atomic_inc_not_zero(&ct->ct_general.use))
++ if (!refcount_inc_not_zero(&ct->ct_general.use))
+ return;
+
+ if (nf_ct_should_gc(ct))
+@@ -810,7 +823,7 @@ __nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone,
+ * in, try to obtain a reference and re-check tuple
+ */
+ ct = nf_ct_tuplehash_to_ctrack(h);
+- if (likely(atomic_inc_not_zero(&ct->ct_general.use))) {
++ if (likely(refcount_inc_not_zero(&ct->ct_general.use))) {
+ if (likely(nf_ct_key_equal(h, tuple, zone, net)))
+ goto found;
+
+@@ -907,7 +920,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
+
+ smp_wmb();
+ /* The caller holds a reference to this object */
+- atomic_set(&ct->ct_general.use, 2);
++ refcount_set(&ct->ct_general.use, 2);
+ __nf_conntrack_hash_insert(ct, hash, reply_hash);
+ nf_conntrack_double_unlock(hash, reply_hash);
+ NF_CT_STAT_INC(net, insert);
+@@ -958,7 +971,7 @@ static void __nf_conntrack_insert_prepare(struct nf_conn *ct)
+ {
+ struct nf_conn_tstamp *tstamp;
+
+- atomic_inc(&ct->ct_general.use);
++ refcount_inc(&ct->ct_general.use);
+ ct->status |= IPS_CONFIRMED;
+
+ /* set conntrack timestamp, if enabled. */
+@@ -989,7 +1002,7 @@ static int __nf_ct_resolve_clash(struct sk_buff *skb,
+
+ nf_ct_acct_merge(ct, ctinfo, loser_ct);
+ nf_ct_add_to_dying_list(loser_ct);
+- nf_conntrack_put(&loser_ct->ct_general);
++ nf_ct_put(loser_ct);
+ nf_ct_set(skb, ct, ctinfo);
+
+ NF_CT_STAT_INC(net, clash_resolve);
+@@ -1036,7 +1049,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx)
}
/* We want the clashing entry to go away real soon: 1 second timeout. */
@@ -152687,7 +235082,158 @@ index 770a63103c7a4..7f79974607643 100644
/* IPS_NAT_CLASH removes the entry automatically on the first
* reply. Also prevents UDP tracker from moving the entry to
-@@ -1560,7 +1560,7 @@ __nf_conntrack_alloc(struct net *net,
+@@ -1351,7 +1364,7 @@ static unsigned int early_drop_list(struct net *net,
+ nf_ct_is_dying(tmp))
+ continue;
+
+- if (!atomic_inc_not_zero(&tmp->ct_general.use))
++ if (!refcount_inc_not_zero(&tmp->ct_general.use))
+ continue;
+
+ /* kill only if still in same netns -- might have moved due to
+@@ -1420,16 +1433,28 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
+
+ static void gc_worker(struct work_struct *work)
+ {
+- unsigned long end_time = jiffies + GC_SCAN_MAX_DURATION;
+ unsigned int i, hashsz, nf_conntrack_max95 = 0;
+- unsigned long next_run = GC_SCAN_INTERVAL;
++ u32 end_time, start_time = nfct_time_stamp;
+ struct conntrack_gc_work *gc_work;
++ unsigned int expired_count = 0;
++ unsigned long next_run;
++ s32 delta_time;
++
+ gc_work = container_of(work, struct conntrack_gc_work, dwork.work);
+
+ i = gc_work->next_bucket;
+ if (gc_work->early_drop)
+ nf_conntrack_max95 = nf_conntrack_max / 100u * 95u;
+
++ if (i == 0) {
++ gc_work->avg_timeout = GC_SCAN_INTERVAL_INIT;
++ gc_work->start_time = start_time;
++ }
++
++ next_run = gc_work->avg_timeout;
++
++ end_time = start_time + GC_SCAN_MAX_DURATION;
++
+ do {
+ struct nf_conntrack_tuple_hash *h;
+ struct hlist_nulls_head *ct_hash;
+@@ -1446,6 +1471,7 @@ static void gc_worker(struct work_struct *work)
+
+ hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[i], hnnode) {
+ struct nf_conntrack_net *cnet;
++ unsigned long expires;
+ struct net *net;
+
+ tmp = nf_ct_tuplehash_to_ctrack(h);
+@@ -1455,11 +1481,29 @@ static void gc_worker(struct work_struct *work)
+ continue;
+ }
+
++ if (expired_count > GC_SCAN_EXPIRED_MAX) {
++ rcu_read_unlock();
++
++ gc_work->next_bucket = i;
++ gc_work->avg_timeout = next_run;
++
++ delta_time = nfct_time_stamp - gc_work->start_time;
++
++ /* re-sched immediately if total cycle time is exceeded */
++ next_run = delta_time < (s32)GC_SCAN_INTERVAL_MAX;
++ goto early_exit;
++ }
++
+ if (nf_ct_is_expired(tmp)) {
+ nf_ct_gc_expired(tmp);
++ expired_count++;
+ continue;
+ }
+
++ expires = clamp(nf_ct_expires(tmp), GC_SCAN_INTERVAL_MIN, GC_SCAN_INTERVAL_CLAMP);
++ next_run += expires;
++ next_run /= 2u;
++
+ if (nf_conntrack_max95 == 0 || gc_worker_skip_ct(tmp))
+ continue;
+
+@@ -1469,7 +1513,7 @@ static void gc_worker(struct work_struct *work)
+ continue;
+
+ /* need to take reference to avoid possible races */
+- if (!atomic_inc_not_zero(&tmp->ct_general.use))
++ if (!refcount_inc_not_zero(&tmp->ct_general.use))
+ continue;
+
+ if (gc_worker_skip_ct(tmp)) {
+@@ -1477,8 +1521,10 @@ static void gc_worker(struct work_struct *work)
+ continue;
+ }
+
+- if (gc_worker_can_early_drop(tmp))
++ if (gc_worker_can_early_drop(tmp)) {
+ nf_ct_kill(tmp);
++ expired_count++;
++ }
+
+ nf_ct_put(tmp);
+ }
+@@ -1491,33 +1537,38 @@ static void gc_worker(struct work_struct *work)
+ cond_resched();
+ i++;
+
+- if (time_after(jiffies, end_time) && i < hashsz) {
++ delta_time = nfct_time_stamp - end_time;
++ if (delta_time > 0 && i < hashsz) {
++ gc_work->avg_timeout = next_run;
+ gc_work->next_bucket = i;
+ next_run = 0;
+- break;
++ goto early_exit;
+ }
+ } while (i < hashsz);
+
++ gc_work->next_bucket = 0;
++
++ next_run = clamp(next_run, GC_SCAN_INTERVAL_MIN, GC_SCAN_INTERVAL_MAX);
++
++ delta_time = max_t(s32, nfct_time_stamp - gc_work->start_time, 1);
++ if (next_run > (unsigned long)delta_time)
++ next_run -= delta_time;
++ else
++ next_run = 1;
++
++early_exit:
+ if (gc_work->exiting)
+ return;
+
+- /*
+- * Eviction will normally happen from the packet path, and not
+- * from this gc worker.
+- *
+- * This worker is only here to reap expired entries when system went
+- * idle after a busy period.
+- */
+- if (next_run) {
++ if (next_run)
+ gc_work->early_drop = false;
+- gc_work->next_bucket = 0;
+- }
++
+ queue_delayed_work(system_power_efficient_wq, &gc_work->dwork, next_run);
+ }
+
+ static void conntrack_gc_work_init(struct conntrack_gc_work *gc_work)
+ {
+- INIT_DEFERRABLE_WORK(&gc_work->dwork, gc_worker);
++ INIT_DELAYED_WORK(&gc_work->dwork, gc_worker);
+ gc_work->exiting = false;
+ }
+
+@@ -1560,7 +1611,7 @@ __nf_conntrack_alloc(struct net *net,
/* save hash for reusing when confirming */
*(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash;
ct->status = 0;
@@ -152696,9 +235242,41 @@ index 770a63103c7a4..7f79974607643 100644
write_pnet(&ct->ct_net, net);
memset(&ct->__nfct_init_offset, 0,
offsetof(struct nf_conn, proto) -
-@@ -1922,15 +1922,17 @@ repeat:
+@@ -1571,7 +1622,7 @@ __nf_conntrack_alloc(struct net *net,
+ /* Because we use RCU lookups, we set ct_general.use to zero before
+ * this is inserted in any list.
+ */
+- atomic_set(&ct->ct_general.use, 0);
++ refcount_set(&ct->ct_general.use, 0);
+ return ct;
+ out:
+ atomic_dec(&cnet->count);
+@@ -1596,7 +1647,7 @@ void nf_conntrack_free(struct nf_conn *ct)
+ /* A freed object has refcnt == 0, that's
+ * the golden rule for SLAB_TYPESAFE_BY_RCU
+ */
+- WARN_ON(atomic_read(&ct->ct_general.use) != 0);
++ WARN_ON(refcount_read(&ct->ct_general.use) != 0);
+
+ nf_ct_ext_destroy(ct);
+ kmem_cache_free(nf_conntrack_cachep, ct);
+@@ -1688,8 +1739,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
+ if (!exp)
+ __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC);
+
+- /* Now it is inserted into the unconfirmed list, bump refcount */
+- nf_conntrack_get(&ct->ct_general);
++ /* Now it is inserted into the unconfirmed list, set refcount to 1. */
++ refcount_set(&ct->ct_general.use, 1);
+ nf_ct_add_to_unconfirmed_list(ct);
+
+ local_bh_enable();
+@@ -1920,17 +1971,19 @@ repeat:
+ /* Invalid: inverse of the return code tells
+ * the netfilter core what to do */
pr_debug("nf_conntrack_in: Can't track with proto module\n");
- nf_conntrack_put(&ct->ct_general);
+- nf_conntrack_put(&ct->ct_general);
++ nf_ct_put(ct);
skb->_nfct = 0;
- NF_CT_STAT_INC_ATOMIC(state->net, invalid);
- if (ret == -NF_DROP)
@@ -152717,10 +235295,73 @@ index 770a63103c7a4..7f79974607643 100644
ret = -ret;
goto out;
}
+@@ -2299,7 +2352,7 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
+
+ return NULL;
+ found:
+- atomic_inc(&ct->ct_general.use);
++ refcount_inc(&ct->ct_general.use);
+ spin_unlock(lockp);
+ local_bh_enable();
+ return ct;
+@@ -2772,7 +2825,7 @@ err_cachep:
+
+ static struct nf_ct_hook nf_conntrack_hook = {
+ .update = nf_conntrack_update,
+- .destroy = destroy_conntrack,
++ .destroy = nf_ct_destroy,
+ .get_tuple_skb = nf_conntrack_get_tuple_skb,
+ };
+
+diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
+index f562eeef42349..6d056ebba57c6 100644
+--- a/net/netfilter/nf_conntrack_expect.c
++++ b/net/netfilter/nf_conntrack_expect.c
+@@ -203,12 +203,12 @@ nf_ct_find_expectation(struct net *net,
+ * about to invoke ->destroy(), or nf_ct_delete() via timeout
+ * or early_drop().
+ *
+- * The atomic_inc_not_zero() check tells: If that fails, we
++ * The refcount_inc_not_zero() check tells: If that fails, we
+ * know that the ct is being destroyed. If it succeeds, we
+ * can be sure the ct cannot disappear underneath.
+ */
+ if (unlikely(nf_ct_is_dying(exp->master) ||
+- !atomic_inc_not_zero(&exp->master->ct_general.use)))
++ !refcount_inc_not_zero(&exp->master->ct_general.use)))
+ return NULL;
+
+ if (exp->flags & NF_CT_EXPECT_PERMANENT) {
+diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
+index ae4488a13c70c..ceb38a7b37cb7 100644
+--- a/net/netfilter/nf_conntrack_helper.c
++++ b/net/netfilter/nf_conntrack_helper.c
+@@ -556,6 +556,12 @@ static const struct nf_ct_ext_type helper_extend = {
+ .id = NF_CT_EXT_HELPER,
+ };
+
++void nf_ct_set_auto_assign_helper_warned(struct net *net)
++{
++ nf_ct_pernet(net)->auto_assign_helper_warned = true;
++}
++EXPORT_SYMBOL_GPL(nf_ct_set_auto_assign_helper_warned);
++
+ void nf_conntrack_helper_pernet_init(struct net *net)
+ {
+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
-index f1e5443fe7c74..1c02be04aaf5c 100644
+index f1e5443fe7c74..ef0a78aa9ba9e 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -508,7 +508,7 @@ nla_put_failure:
+
+ static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
+ {
+- if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
++ if (nla_put_be32(skb, CTA_USE, htonl(refcount_read(&ct->ct_general.use))))
+ goto nla_put_failure;
+ return 0;
+
@@ -1011,11 +1011,9 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
CTA_TUPLE_REPLY,
filter->family,
@@ -152735,6 +235376,24 @@ index f1e5443fe7c74..1c02be04aaf5c 100644
}
return filter;
+@@ -1202,7 +1200,7 @@ restart:
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (nf_ct_is_expired(ct)) {
+ if (i < ARRAY_SIZE(nf_ct_evict) &&
+- atomic_inc_not_zero(&ct->ct_general.use))
++ refcount_inc_not_zero(&ct->ct_general.use))
+ nf_ct_evict[i++] = ct;
+ continue;
+ }
+@@ -1750,7 +1748,7 @@ restart:
+ NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
+ ct, dying ? true : false, 0);
+ if (res < 0) {
+- if (!atomic_inc_not_zero(&ct->ct_general.use))
++ if (!refcount_inc_not_zero(&ct->ct_general.use))
+ continue;
+ cb->args[0] = cpu;
+ cb->args[1] = (unsigned long)ct;
@@ -2000,7 +1998,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct,
if (timeout > INT_MAX)
@@ -152774,6 +235433,48 @@ index 2394238d01c91..5a936334b517a 100644
}
ct->proto.sctp.state = new_state;
+diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
+index af5115e127cfd..3cee5d8ee7027 100644
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -341,8 +341,8 @@ static void tcp_options(const struct sk_buff *skb,
+ if (!ptr)
+ return;
+
+- state->td_scale =
+- state->flags = 0;
++ state->td_scale = 0;
++ state->flags &= IP_CT_TCP_FLAG_BE_LIBERAL;
+
+ while (length > 0) {
+ int opcode=*ptr++;
+@@ -839,6 +839,16 @@ static bool tcp_can_early_drop(const struct nf_conn *ct)
+ return false;
+ }
+
++static void nf_ct_tcp_state_reset(struct ip_ct_tcp_state *state)
++{
++ state->td_end = 0;
++ state->td_maxend = 0;
++ state->td_maxwin = 0;
++ state->td_maxack = 0;
++ state->td_scale = 0;
++ state->flags &= IP_CT_TCP_FLAG_BE_LIBERAL;
++}
++
+ /* Returns verdict for packet, or -1 for invalid. */
+ int nf_conntrack_tcp_packet(struct nf_conn *ct,
+ struct sk_buff *skb,
+@@ -945,8 +955,7 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
+ ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK;
+ ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags =
+ ct->proto.tcp.last_flags;
+- memset(&ct->proto.tcp.seen[dir], 0,
+- sizeof(struct ip_ct_tcp_state));
++ nf_ct_tcp_state_reset(&ct->proto.tcp.seen[dir]);
+ break;
+ }
+ ct->proto.tcp.last_index = index;
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index f8e3c0d2602f6..3b516cffc779b 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
@@ -152802,21 +235503,336 @@ index f8e3c0d2602f6..3b516cffc779b 100644
nf_conntrack_event_cache(IPCT_ASSURED, ct);
} else {
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
+diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
+index 80f675d884b26..55aa55b252b20 100644
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -303,7 +303,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ int ret = 0;
+
+ WARN_ON(!ct);
+- if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
++ if (unlikely(!refcount_inc_not_zero(&ct->ct_general.use)))
+ return 0;
+
+ if (nf_ct_should_gc(ct)) {
+@@ -370,7 +370,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
+ ct_show_delta_time(s, ct);
+
+- seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use));
++ seq_printf(s, "use=%u\n", refcount_read(&ct->ct_general.use));
+
+ if (seq_has_overflowed(s))
+ goto release;
+@@ -823,7 +823,7 @@ static struct ctl_table nf_ct_sysctl_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+-#if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD)
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
+ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = {
+ .procname = "nf_flowtable_udp_timeout",
+ .maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
-index 87a7388b6c894..ed37bb9b4e588 100644
+index 87a7388b6c894..9fb407084c506 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
-@@ -201,8 +201,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
+@@ -48,7 +48,7 @@ struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
+ struct flow_offload *flow;
+
+ if (unlikely(nf_ct_is_dying(ct) ||
+- !atomic_inc_not_zero(&ct->ct_general.use)))
++ !refcount_inc_not_zero(&ct->ct_general.use)))
+ return NULL;
+
+ flow = kzalloc(sizeof(*flow), GFP_ATOMIC);
+@@ -173,12 +173,11 @@ EXPORT_SYMBOL_GPL(flow_offload_route_init);
+
+ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
+ {
+- tcp->state = TCP_CONNTRACK_ESTABLISHED;
+ tcp->seen[0].td_maxwin = 0;
+ tcp->seen[1].td_maxwin = 0;
+ }
+
+-static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
++static void flow_offload_fixup_ct(struct nf_conn *ct)
+ {
+ struct net *net = nf_ct_net(ct);
+ int l4num = nf_ct_protonum(ct);
+@@ -187,7 +186,9 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
+ if (l4num == IPPROTO_TCP) {
+ struct nf_tcp_net *tn = nf_tcp_pernet(net);
+
+- timeout = tn->timeouts[TCP_CONNTRACK_ESTABLISHED];
++ flow_offload_fixup_tcp(&ct->proto.tcp);
++
++ timeout = tn->timeouts[ct->proto.tcp.state];
+ timeout -= tn->offload_timeout;
+ } else if (l4num == IPPROTO_UDP) {
+ struct nf_udp_net *tn = nf_udp_pernet(net);
+@@ -201,20 +202,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
if (timeout < 0)
timeout = 0;
- if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
- ct->timeout = nfct_time_stamp + timeout;
+-}
+-
+-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+-{
+- if (nf_ct_protonum(ct) == IPPROTO_TCP)
+- flow_offload_fixup_tcp(&ct->proto.tcp);
+-}
+-
+-static void flow_offload_fixup_ct(struct nf_conn *ct)
+-{
+- flow_offload_fixup_ct_state(ct);
+- flow_offload_fixup_ct_timeout(ct);
+ if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout)
+ WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout);
}
- static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+ static void flow_offload_route_release(struct flow_offload *flow)
+@@ -329,8 +318,10 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
+ u32 timeout;
+
+ timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
+- if (READ_ONCE(flow->timeout) != timeout)
++ if (timeout - READ_ONCE(flow->timeout) > HZ)
+ WRITE_ONCE(flow->timeout, timeout);
++ else
++ return;
+
+ if (likely(!nf_flowtable_hw_offload(flow_table)))
+ return;
+@@ -353,22 +344,14 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
+ rhashtable_remove_fast(&flow_table->rhashtable,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
+ nf_flow_offload_rhash_params);
+-
+- clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
+-
+- if (nf_flow_has_expired(flow))
+- flow_offload_fixup_ct(flow->ct);
+- else
+- flow_offload_fixup_ct_timeout(flow->ct);
+-
+ flow_offload_free(flow);
+ }
+
+ void flow_offload_teardown(struct flow_offload *flow)
+ {
++ clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
+ set_bit(NF_FLOW_TEARDOWN, &flow->flags);
+-
+- flow_offload_fixup_ct_state(flow->ct);
++ flow_offload_fixup_ct(flow->ct);
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_teardown);
+
+@@ -399,7 +382,8 @@ EXPORT_SYMBOL_GPL(flow_offload_lookup);
+
+ static int
+ nf_flow_table_iterate(struct nf_flowtable *flow_table,
+- void (*iter)(struct flow_offload *flow, void *data),
++ void (*iter)(struct nf_flowtable *flowtable,
++ struct flow_offload *flow, void *data),
+ void *data)
+ {
+ struct flow_offload_tuple_rhash *tuplehash;
+@@ -423,7 +407,7 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
+
+ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]);
+
+- iter(flow, data);
++ iter(flow_table, flow, data);
+ }
+ rhashtable_walk_stop(&hti);
+ rhashtable_walk_exit(&hti);
+@@ -431,34 +415,12 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
+ return err;
+ }
+
+-static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple)
++static void nf_flow_offload_gc_step(struct nf_flowtable *flow_table,
++ struct flow_offload *flow, void *data)
+ {
+- struct dst_entry *dst;
+-
+- if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
+- tuple->xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
+- dst = tuple->dst_cache;
+- if (!dst_check(dst, tuple->dst_cookie))
+- return true;
+- }
+-
+- return false;
+-}
+-
+-static bool nf_flow_has_stale_dst(struct flow_offload *flow)
+-{
+- return flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple) ||
+- flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple);
+-}
+-
+-static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
+-{
+- struct nf_flowtable *flow_table = data;
+-
+ if (nf_flow_has_expired(flow) ||
+- nf_ct_is_dying(flow->ct) ||
+- nf_flow_has_stale_dst(flow))
+- set_bit(NF_FLOW_TEARDOWN, &flow->flags);
++ nf_ct_is_dying(flow->ct))
++ flow_offload_teardown(flow);
+
+ if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
+ if (test_bit(NF_FLOW_HW, &flow->flags)) {
+@@ -479,7 +441,7 @@ static void nf_flow_offload_work_gc(struct work_struct *work)
+ struct nf_flowtable *flow_table;
+
+ flow_table = container_of(work, struct nf_flowtable, gc_work.work);
+- nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, flow_table);
++ nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
+ }
+
+@@ -595,7 +557,8 @@ int nf_flow_table_init(struct nf_flowtable *flowtable)
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_table_init);
+
+-static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data)
++static void nf_flow_table_do_cleanup(struct nf_flowtable *flow_table,
++ struct flow_offload *flow, void *data)
+ {
+ struct net_device *dev = data;
+
+@@ -637,11 +600,10 @@ void nf_flow_table_free(struct nf_flowtable *flow_table)
+
+ cancel_delayed_work_sync(&flow_table->gc_work);
+ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
+- nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, flow_table);
++ nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+ nf_flow_table_offload_flush(flow_table);
+ if (nf_flowtable_hw_offload(flow_table))
+- nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step,
+- flow_table);
++ nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+ rhashtable_destroy(&flow_table->rhashtable);
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_table_free);
+diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c
+index bc4126d8ef65f..280fdd32965f6 100644
+--- a/net/netfilter/nf_flow_table_inet.c
++++ b/net/netfilter/nf_flow_table_inet.c
+@@ -6,12 +6,29 @@
+ #include <linux/rhashtable.h>
+ #include <net/netfilter/nf_flow_table.h>
+ #include <net/netfilter/nf_tables.h>
++#include <linux/if_vlan.h>
+
+ static unsigned int
+ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+ {
++ struct vlan_ethhdr *veth;
++ __be16 proto;
++
+ switch (skb->protocol) {
++ case htons(ETH_P_8021Q):
++ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
++ proto = veth->h_vlan_encapsulated_proto;
++ break;
++ case htons(ETH_P_PPP_SES):
++ proto = nf_flow_pppoe_proto(skb);
++ break;
++ default:
++ proto = skb->protocol;
++ break;
++ }
++
++ switch (proto) {
+ case htons(ETH_P_IP):
+ return nf_flow_offload_ip_hook(priv, skb, state);
+ case htons(ETH_P_IPV6):
+diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
+index 889cf88d3dba6..28026467b54cd 100644
+--- a/net/netfilter/nf_flow_table_ip.c
++++ b/net/netfilter/nf_flow_table_ip.c
+@@ -8,8 +8,6 @@
+ #include <linux/ipv6.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_ether.h>
+-#include <linux/if_pppox.h>
+-#include <linux/ppp_defs.h>
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_route.h>
+@@ -229,6 +227,15 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
+ return true;
+ }
+
++static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple)
++{
++ if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH &&
++ tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM)
++ return true;
++
++ return dst_check(tuple->dst_cache, tuple->dst_cookie);
++}
++
+ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct dst_entry *dst)
+@@ -239,22 +246,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+ return NF_STOLEN;
+ }
+
+-static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
+-{
+- __be16 proto;
+-
+- proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
+- sizeof(struct pppoe_hdr)));
+- switch (proto) {
+- case htons(PPP_IP):
+- return htons(ETH_P_IP);
+- case htons(PPP_IPV6):
+- return htons(ETH_P_IPV6);
+- }
+-
+- return 0;
+-}
+-
+ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
+ u32 *offset)
+ {
+@@ -364,6 +355,11 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+ if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
+ return NF_ACCEPT;
+
++ if (!nf_flow_dst_check(&tuplehash->tuple)) {
++ flow_offload_teardown(flow);
++ return NF_ACCEPT;
++ }
++
+ if (skb_try_make_writable(skb, thoff + hdrsize))
+ return NF_DROP;
+
+@@ -600,6 +596,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+ if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff))
+ return NF_ACCEPT;
+
++ if (!nf_flow_dst_check(&tuplehash->tuple)) {
++ flow_offload_teardown(flow);
++ return NF_ACCEPT;
++ }
++
+ if (skb_try_make_writable(skb, thoff + hdrsize))
+ return NF_DROP;
+
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index d6bf1b2cd541b..b561e0a44a45f 100644
--- a/net/netfilter/nf_flow_table_offload.c
@@ -152920,8 +235936,20 @@ index 6d12afabfe8a3..63d1516816b1f 100644
switch (entry->state.pf) {
case AF_INET:
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 3d6d49420db8b..2dfc5dae06563 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -349,7 +349,6 @@ static int __net_init synproxy_net_init(struct net *net)
+ goto err2;
+
+ __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+- nf_conntrack_get(&ct->ct_general);
+ snet->tmpl = ct;
+
+ snet->stats = alloc_percpu(struct synproxy_stats);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index c0851fec11d46..2b2e0210a7f9e 100644
+index c0851fec11d46..2feb88ffcd81f 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4481,12 +4481,12 @@ struct nft_set_elem_catchall {
@@ -152994,7 +236022,58 @@ index c0851fec11d46..2b2e0210a7f9e 100644
nft_trans_destroy(trans);
} else {
trans->ctx.table->use--;
-@@ -9574,10 +9579,13 @@ EXPORT_SYMBOL_GPL(__nft_release_basechain);
+@@ -9203,17 +9208,23 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
+ }
+ EXPORT_SYMBOL_GPL(nft_parse_u32_check);
+
+-static unsigned int nft_parse_register(const struct nlattr *attr)
++static int nft_parse_register(const struct nlattr *attr, u32 *preg)
+ {
+ unsigned int reg;
+
+ reg = ntohl(nla_get_be32(attr));
+ switch (reg) {
+ case NFT_REG_VERDICT...NFT_REG_4:
+- return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
++ *preg = reg * NFT_REG_SIZE / NFT_REG32_SIZE;
++ break;
++ case NFT_REG32_00...NFT_REG32_15:
++ *preg = reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
++ break;
+ default:
+- return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
++ return -ERANGE;
+ }
++
++ return 0;
+ }
+
+ /**
+@@ -9255,7 +9266,10 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
+ u32 reg;
+ int err;
+
+- reg = nft_parse_register(attr);
++ err = nft_parse_register(attr, &reg);
++ if (err < 0)
++ return err;
++
+ err = nft_validate_register_load(reg, len);
+ if (err < 0)
+ return err;
+@@ -9310,7 +9324,10 @@ int nft_parse_register_store(const struct nft_ctx *ctx,
+ int err;
+ u32 reg;
+
+- reg = nft_parse_register(attr);
++ err = nft_parse_register(attr, &reg);
++ if (err < 0)
++ return err;
++
+ err = nft_validate_register_store(ctx, reg, data, type, len);
+ if (err < 0)
+ return err;
+@@ -9574,10 +9591,13 @@ EXPORT_SYMBOL_GPL(__nft_release_basechain);
static void __nft_release_hook(struct net *net, struct nft_table *table)
{
@@ -153008,6 +236087,19 @@ index c0851fec11d46..2b2e0210a7f9e 100644
}
static void __nft_release_hooks(struct net *net)
+diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
+index 866cfba04d6c0..907e848dbc178 100644
+--- a/net/netfilter/nf_tables_core.c
++++ b/net/netfilter/nf_tables_core.c
+@@ -162,7 +162,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
+ struct nft_rule *const *rules;
+ const struct nft_rule *rule;
+ const struct nft_expr *expr, *last;
+- struct nft_regs regs;
++ struct nft_regs regs = {};
+ unsigned int stackptr = 0;
+ struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
+ bool genbit = READ_ONCE(net->nft.gencursor);
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index 9656c16462222..2d36952b13920 100644
--- a/net/netfilter/nf_tables_offload.c
@@ -153069,6 +236161,52 @@ index 4c3fbaaeb1030..8787d0613ad83 100644
}
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 99b1de14ff7ee..9c7472af9e4a1 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -259,10 +259,13 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
+
+ ct = this_cpu_read(nft_ct_pcpu_template);
+
+- if (likely(atomic_read(&ct->ct_general.use) == 1)) {
++ if (likely(refcount_read(&ct->ct_general.use) == 1)) {
++ refcount_inc(&ct->ct_general.use);
+ nf_ct_zone_add(ct, &zone);
+ } else {
+- /* previous skb got queued to userspace */
++ /* previous skb got queued to userspace, allocate temporary
++ * one until percpu template can be reused.
++ */
+ ct = nf_ct_tmpl_alloc(nft_net(pkt), &zone, GFP_ATOMIC);
+ if (!ct) {
+ regs->verdict.code = NF_DROP;
+@@ -270,7 +273,6 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
+ }
+ }
+
+- atomic_inc(&ct->ct_general.use);
+ nf_ct_set(skb, ct, IP_CT_NEW);
+ }
+ #endif
+@@ -375,7 +377,6 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
+ return false;
+ }
+
+- atomic_set(&tmp->ct_general.use, 1);
+ per_cpu(nft_ct_pcpu_template, cpu) = tmp;
+ }
+
+@@ -1040,6 +1041,9 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ goto err_put_helper;
+
++ /* Avoid the bogus warning, helper will be assigned after CT init */
++ nf_ct_set_auto_assign_helper_warned(ctx->net);
++
+ return 0;
+
+ err_put_helper:
diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c
index bbf3fcba3df40..5b5c607fbf83f 100644
--- a/net/netfilter/nft_dup_netdev.c
@@ -153159,6 +236297,80 @@ index af4ee874a067c..dbe1f2e7dd9ed 100644
}
static void nft_exthdr_sctp_eval(const struct nft_expr *expr,
+diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
+index 0af34ad414796..aac6db8680d47 100644
+--- a/net/netfilter/nft_flow_offload.c
++++ b/net/netfilter/nft_flow_offload.c
+@@ -36,6 +36,15 @@ static void nft_default_forward_path(struct nf_flow_route *route,
+ route->tuple[dir].xmit_type = nft_xmit_type(dst_cache);
+ }
+
++static bool nft_is_valid_ether_device(const struct net_device *dev)
++{
++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
++ return false;
++
++ return true;
++}
++
+ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
+ const struct dst_entry *dst_cache,
+ const struct nf_conn *ct,
+@@ -47,6 +56,9 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
+ struct neighbour *n;
+ u8 nud_state;
+
++ if (!nft_is_valid_ether_device(dev))
++ goto out;
++
+ n = dst_neigh_lookup(dst_cache, daddr);
+ if (!n)
+ return -1;
+@@ -60,6 +72,7 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
+ if (!(nud_state & NUD_VALID))
+ return -1;
+
++out:
+ return dev_fill_forward_path(dev, ha, stack);
+ }
+
+@@ -78,15 +91,6 @@ struct nft_forward_info {
+ enum flow_offload_xmit_type xmit_type;
+ };
+
+-static bool nft_is_valid_ether_device(const struct net_device *dev)
+-{
+- if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
+- dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
+- return false;
+-
+- return true;
+-}
+-
+ static void nft_dev_path_info(const struct net_device_path_stack *stack,
+ struct nft_forward_info *info,
+ unsigned char *ha, struct nf_flowtable *flowtable)
+@@ -119,7 +123,8 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
+ info->indev = NULL;
+ break;
+ }
+- info->outdev = path->dev;
++ if (!info->outdev)
++ info->outdev = path->dev;
+ info->encap[info->num_encaps].id = path->encap.id;
+ info->encap[info->num_encaps].proto = path->encap.proto;
+ info->num_encaps++;
+@@ -293,7 +298,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
+ case IPPROTO_TCP:
+ tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt),
+ sizeof(_tcph), &_tcph);
+- if (unlikely(!tcph || tcph->fin || tcph->rst))
++ if (unlikely(!tcph || tcph->fin || tcph->rst ||
++ !nf_conntrack_tcp_established(ct)))
+ goto out;
+ break;
+ case IPPROTO_UDP:
diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
index cd59afde5b2f8..7730409f6f091 100644
--- a/net/netfilter/nft_fwd_netdev.c
@@ -153266,6 +236478,131 @@ index e517663e0cd17..6f4116e729581 100644
NFT_PIPAPO_AVX2_AND(7, 2, 3);
/* Stall */
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index d600a566da324..7325bee7d1442 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -349,7 +349,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
+ *ext = &rbe->ext;
+ return -EEXIST;
+ } else {
+- p = &parent->rb_left;
++ overlap = false;
++ if (nft_rbtree_interval_end(rbe))
++ p = &parent->rb_left;
++ else
++ p = &parent->rb_right;
+ }
+ }
+
+diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
+index d601974c9d2e0..9ad9cc0d1d27c 100644
+--- a/net/netfilter/nft_socket.c
++++ b/net/netfilter/nft_socket.c
+@@ -36,12 +36,11 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt,
+
+ #ifdef CONFIG_SOCK_CGROUP_DATA
+ static noinline bool
+-nft_sock_get_eval_cgroupv2(u32 *dest, const struct nft_pktinfo *pkt, u32 level)
++nft_sock_get_eval_cgroupv2(u32 *dest, struct sock *sk, const struct nft_pktinfo *pkt, u32 level)
+ {
+- struct sock *sk = skb_to_full_sk(pkt->skb);
+ struct cgroup *cgrp;
+
+- if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
++ if (!sk_fullsock(sk))
+ return false;
+
+ cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
+@@ -54,6 +53,32 @@ nft_sock_get_eval_cgroupv2(u32 *dest, const struct nft_pktinfo *pkt, u32 level)
+ }
+ #endif
+
++static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt)
++{
++ const struct net_device *indev = nft_in(pkt);
++ const struct sk_buff *skb = pkt->skb;
++ struct sock *sk = NULL;
++
++ if (!indev)
++ return NULL;
++
++ switch (nft_pf(pkt)) {
++ case NFPROTO_IPV4:
++ sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, indev);
++ break;
++#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
++ case NFPROTO_IPV6:
++ sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, indev);
++ break;
++#endif
++ default:
++ WARN_ON_ONCE(1);
++ break;
++ }
++
++ return sk;
++}
++
+ static void nft_socket_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+@@ -67,20 +92,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
+ sk = NULL;
+
+ if (!sk)
+- switch(nft_pf(pkt)) {
+- case NFPROTO_IPV4:
+- sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, nft_in(pkt));
+- break;
+-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+- case NFPROTO_IPV6:
+- sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, nft_in(pkt));
+- break;
+-#endif
+- default:
+- WARN_ON_ONCE(1);
+- regs->verdict.code = NFT_BREAK;
+- return;
+- }
++ sk = nft_socket_do_lookup(pkt);
+
+ if (!sk) {
+ regs->verdict.code = NFT_BREAK;
+@@ -108,7 +120,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
+ break;
+ #ifdef CONFIG_SOCK_CGROUP_DATA
+ case NFT_SOCKET_CGROUPV2:
+- if (!nft_sock_get_eval_cgroupv2(dest, pkt, priv->level)) {
++ if (!nft_sock_get_eval_cgroupv2(dest, sk, pkt, priv->level)) {
+ regs->verdict.code = NFT_BREAK;
+ return;
+ }
+@@ -198,6 +210,16 @@ static int nft_socket_dump(struct sk_buff *skb,
+ return 0;
+ }
+
++static int nft_socket_validate(const struct nft_ctx *ctx,
++ const struct nft_expr *expr,
++ const struct nft_data **data)
++{
++ return nft_chain_validate_hooks(ctx->chain,
++ (1 << NF_INET_PRE_ROUTING) |
++ (1 << NF_INET_LOCAL_IN) |
++ (1 << NF_INET_LOCAL_OUT));
++}
++
+ static struct nft_expr_type nft_socket_type;
+ static const struct nft_expr_ops nft_socket_ops = {
+ .type = &nft_socket_type,
+@@ -205,6 +227,7 @@ static const struct nft_expr_ops nft_socket_ops = {
+ .eval = nft_socket_eval,
+ .init = nft_socket_init,
+ .dump = nft_socket_dump,
++ .validate = nft_socket_validate,
+ };
+
+ static struct nft_expr_type nft_socket_type __read_mostly = {
diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c
index a0109fa1e92d0..1133e06f3c40e 100644
--- a/net/netfilter/nft_synproxy.c
@@ -153282,6 +236619,27 @@ index a0109fa1e92d0..1133e06f3c40e 100644
break;
}
+diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
+index 0a913ce07425a..267757b0392a6 100644
+--- a/net/netfilter/xt_CT.c
++++ b/net/netfilter/xt_CT.c
+@@ -24,7 +24,7 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
+ return XT_CONTINUE;
+
+ if (ct) {
+- atomic_inc(&ct->ct_general.use);
++ refcount_inc(&ct->ct_general.use);
+ nf_ct_set(skb, ct, IP_CT_NEW);
+ } else {
+ nf_ct_set(skb, ct, IP_CT_UNTRACKED);
+@@ -201,7 +201,6 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
+ goto err4;
+ }
+ __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+- nf_conntrack_get(&ct->ct_general);
+ out:
+ info->ct = ct;
+ return 0;
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 5e6459e116055..7013f55f05d1e 100644
--- a/net/netfilter/xt_socket.c
@@ -153298,11 +236656,33 @@ index 5e6459e116055..7013f55f05d1e 100644
}
static struct xt_match socket_mt_reg[] __read_mostly = {
+diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
+index beb0e573266d0..54c0830039470 100644
+--- a/net/netlabel/netlabel_kapi.c
++++ b/net/netlabel/netlabel_kapi.c
+@@ -885,6 +885,8 @@ int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len,
+ unsigned char bitmask;
+ unsigned char byte;
+
++ if (offset >= bitmap_len)
++ return -1;
+ byte_offset = offset / 8;
+ byte = bitmap[byte_offset];
+ bit_spot = offset;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
-index ada47e59647a0..81ba8e51e01ff 100644
+index ada47e59647a0..974d32632ef41 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
-@@ -1871,6 +1871,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+@@ -157,6 +157,8 @@ EXPORT_SYMBOL(do_trace_netlink_extack);
+
+ static inline u32 netlink_group_mask(u32 group)
+ {
++ if (group > 32)
++ return 0;
+ return group ? 1 << (group - 1) : 0;
+ }
+
+@@ -1871,6 +1873,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
@@ -153314,6 +236694,28 @@ index ada47e59647a0..81ba8e51e01ff 100644
err = scm_send(sock, msg, &scm, true);
if (err < 0)
return err;
+@@ -1989,7 +1996,6 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ copied = len;
+ }
+
+- skb_reset_transport_header(data_skb);
+ err = skb_copy_datagram_msg(data_skb, 0, msg, copied);
+
+ if (msg->msg_name) {
+@@ -2277,6 +2283,13 @@ static int netlink_dump(struct sock *sk)
+ * single netdev. The outcome is MSG_TRUNC error.
+ */
+ skb_reserve(skb, skb_tailroom(skb) - alloc_size);
++
++ /* Make sure malicious BPF programs can not read unitialized memory
++ * from skb->head -> skb->data
++ */
++ skb_reset_network_header(skb);
++ skb_reset_mac_header(skb);
++
+ netlink_skb_set_owner_r(skb, sk);
+
+ if (nlk->dump_done_errno > 0) {
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 6d16e1ab1a8ab..e5c8a295e6406 100644
--- a/net/netrom/af_netrom.c
@@ -153366,16 +236768,25 @@ index 6d16e1ab1a8ab..e5c8a295e6406 100644
nr->idle = opt * 60 * HZ;
return 0;
diff --git a/net/nfc/core.c b/net/nfc/core.c
-index 3c645c1d99c9b..dc7a2404efdf9 100644
+index 3c645c1d99c9b..5b286e1e0a6ff 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
+@@ -38,7 +38,7 @@ int nfc_fw_download(struct nfc_dev *dev, const char *firmware_name)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
@@ -94,13 +94,13 @@ int nfc_dev_up(struct nfc_dev *dev)
device_lock(&dev->dev);
- if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
- rc = -ERFKILL;
-+ if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
goto error;
}
@@ -153387,6 +236798,96 @@ index 3c645c1d99c9b..dc7a2404efdf9 100644
goto error;
}
+@@ -142,7 +142,7 @@ int nfc_dev_down(struct nfc_dev *dev)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -207,7 +207,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -246,7 +246,7 @@ int nfc_stop_poll(struct nfc_dev *dev)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -291,7 +291,7 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -335,7 +335,7 @@ int nfc_dep_link_down(struct nfc_dev *dev)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -401,7 +401,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -448,7 +448,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -495,7 +495,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ kfree_skb(skb);
+ goto error;
+@@ -552,7 +552,7 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
+@@ -601,7 +601,7 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
+
+ device_lock(&dev->dev);
+
+- if (!device_is_registered(&dev->dev)) {
++ if (dev->shutting_down) {
+ rc = -ENODEV;
+ goto error;
+ }
@@ -1125,11 +1125,7 @@ int nfc_register_device(struct nfc_dev *dev)
if (rc)
pr_err("Could not register llcp device\n");
@@ -153400,10 +236901,11 @@ index 3c645c1d99c9b..dc7a2404efdf9 100644
dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
if (dev->rfkill) {
-@@ -1138,6 +1134,12 @@ int nfc_register_device(struct nfc_dev *dev)
+@@ -1138,6 +1134,13 @@ int nfc_register_device(struct nfc_dev *dev)
dev->rfkill = NULL;
}
}
++ dev->shutting_down = false;
+ device_unlock(&dev->dev);
+
+ rc = nfc_genl_device_added(dev);
@@ -153413,7 +236915,7 @@ index 3c645c1d99c9b..dc7a2404efdf9 100644
return 0;
}
-@@ -1154,10 +1156,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
+@@ -1154,24 +1157,24 @@ void nfc_unregister_device(struct nfc_dev *dev)
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
@@ -153427,11 +236929,14 @@ index 3c645c1d99c9b..dc7a2404efdf9 100644
rfkill_unregister(dev->rfkill);
rfkill_destroy(dev->rfkill);
}
++ dev->shutting_down = true;
+ device_unlock(&dev->dev);
if (dev->ops->check_presence) {
- device_lock(&dev->dev);
-@@ -1167,11 +1176,6 @@ void nfc_unregister_device(struct nfc_dev *dev)
+- device_lock(&dev->dev);
+- dev->shutting_down = true;
+- device_unlock(&dev->dev);
+ del_timer_sync(&dev->check_pres_timer);
cancel_work_sync(&dev->check_pres_work);
}
@@ -153460,7 +236965,7 @@ index 6cfd30fc07985..0b93a17b9f11f 100644
DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, addr,
msg->msg_name);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
-index 82ab39d80726e..e41e2e9e54984 100644
+index 82ab39d80726e..189c9f428a3c2 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -144,12 +144,15 @@ inline int nci_request(struct nci_dev *ndev,
@@ -153495,7 +237000,7 @@ index 82ab39d80726e..e41e2e9e54984 100644
if (test_bit(NCI_UP, &ndev->flags)) {
rc = -EALREADY;
goto done;
-@@ -545,6 +553,10 @@ done:
+@@ -545,9 +553,17 @@ done:
static int nci_close_device(struct nci_dev *ndev)
{
nci_req_cancel(ndev, ENODEV);
@@ -153506,7 +237011,14 @@ index 82ab39d80726e..e41e2e9e54984 100644
mutex_lock(&ndev->req_lock);
if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
-@@ -582,8 +594,8 @@ static int nci_close_device(struct nci_dev *ndev)
++ /* Need to flush the cmd wq in case
++ * there is a queued/running cmd_work
++ */
++ flush_workqueue(ndev->cmd_wq);
+ del_timer_sync(&ndev->cmd_timer);
+ del_timer_sync(&ndev->data_timer);
+ mutex_unlock(&ndev->req_lock);
+@@ -582,8 +598,8 @@ static int nci_close_device(struct nci_dev *ndev)
del_timer_sync(&ndev->cmd_timer);
@@ -153517,7 +237029,7 @@ index 82ab39d80726e..e41e2e9e54984 100644
mutex_unlock(&ndev->req_lock);
-@@ -1270,6 +1282,12 @@ void nci_unregister_device(struct nci_dev *ndev)
+@@ -1270,6 +1286,12 @@ void nci_unregister_device(struct nci_dev *ndev)
{
struct nci_conn_info *conn_info, *n;
@@ -153530,8 +237042,43 @@ index 82ab39d80726e..e41e2e9e54984 100644
nci_close_device(ndev);
destroy_workqueue(ndev->cmd_wq);
+diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
+index 6055dc9a82aa0..aa5e712adf078 100644
+--- a/net/nfc/nci/data.c
++++ b/net/nfc/nci/data.c
+@@ -118,7 +118,7 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
+
+ skb_frag = nci_skb_alloc(ndev,
+ (NCI_DATA_HDR_SIZE + frag_len),
+- GFP_KERNEL);
++ GFP_ATOMIC);
+ if (skb_frag == NULL) {
+ rc = -ENOMEM;
+ goto free_exit;
+diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
+index e199912ee1e59..85b808fdcbc3a 100644
+--- a/net/nfc/nci/hci.c
++++ b/net/nfc/nci/hci.c
+@@ -153,7 +153,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
+
+ i = 0;
+ skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
+- NCI_DATA_HDR_SIZE, GFP_KERNEL);
++ NCI_DATA_HDR_SIZE, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+@@ -184,7 +184,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
+ if (i < data_len) {
+ skb = nci_skb_alloc(ndev,
+ conn_info->max_pkt_payload_len +
+- NCI_DATA_HDR_SIZE, GFP_KERNEL);
++ NCI_DATA_HDR_SIZE, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
-index 49089c50872e6..8048a3dcc5f8b 100644
+index 49089c50872e6..a207f0b8137b0 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -636,8 +636,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
@@ -153547,6 +237094,24 @@ index 49089c50872e6..8048a3dcc5f8b 100644
return 0;
}
+@@ -1242,7 +1244,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
+ struct sk_buff *msg;
+ void *hdr;
+
+- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ if (!msg)
+ return -ENOMEM;
+
+@@ -1258,7 +1260,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
+
+ genlmsg_end(msg, hdr);
+
+- genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
++ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
+
+ return 0;
+
@@ -1392,8 +1394,10 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
{
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
@@ -153561,7 +237126,7 @@ index 49089c50872e6..8048a3dcc5f8b 100644
return 0;
}
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
-index 076774034bb96..780d9e2246f39 100644
+index 076774034bb96..8955f31fa47e9 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -423,12 +423,43 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
@@ -153634,6 +237199,228 @@ index 076774034bb96..780d9e2246f39 100644
flow_key->ip.ttl = nh->hop_limit;
}
return 0;
+@@ -1021,7 +1051,7 @@ static int clone(struct datapath *dp, struct sk_buff *skb,
+ int rem = nla_len(attr);
+ bool dont_clone_flow_key;
+
+- /* The first action is always 'OVS_CLONE_ATTR_ARG'. */
++ /* The first action is always 'OVS_CLONE_ATTR_EXEC'. */
+ clone_arg = nla_data(attr);
+ dont_clone_flow_key = nla_get_u32(clone_arg);
+ actions = nla_next(clone_arg, &rem);
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 1b5eae57bc900..815916056e0de 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -574,7 +574,7 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
+ struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+
+ nf_ct_delete(ct, 0, 0);
+- nf_conntrack_put(&ct->ct_general);
++ nf_ct_put(ct);
+ }
+ }
+
+@@ -723,7 +723,7 @@ static bool skb_nfct_cached(struct net *net,
+ if (nf_ct_is_confirmed(ct))
+ nf_ct_delete(ct, 0, 0);
+
+- nf_conntrack_put(&ct->ct_general);
++ nf_ct_put(ct);
+ nf_ct_set(skb, NULL, 0);
+ return false;
+ }
+@@ -732,6 +732,57 @@ static bool skb_nfct_cached(struct net *net,
+ }
+
+ #if IS_ENABLED(CONFIG_NF_NAT)
++static void ovs_nat_update_key(struct sw_flow_key *key,
++ const struct sk_buff *skb,
++ enum nf_nat_manip_type maniptype)
++{
++ if (maniptype == NF_NAT_MANIP_SRC) {
++ __be16 src;
++
++ key->ct_state |= OVS_CS_F_SRC_NAT;
++ if (key->eth.type == htons(ETH_P_IP))
++ key->ipv4.addr.src = ip_hdr(skb)->saddr;
++ else if (key->eth.type == htons(ETH_P_IPV6))
++ memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
++ sizeof(key->ipv6.addr.src));
++ else
++ return;
++
++ if (key->ip.proto == IPPROTO_UDP)
++ src = udp_hdr(skb)->source;
++ else if (key->ip.proto == IPPROTO_TCP)
++ src = tcp_hdr(skb)->source;
++ else if (key->ip.proto == IPPROTO_SCTP)
++ src = sctp_hdr(skb)->source;
++ else
++ return;
++
++ key->tp.src = src;
++ } else {
++ __be16 dst;
++
++ key->ct_state |= OVS_CS_F_DST_NAT;
++ if (key->eth.type == htons(ETH_P_IP))
++ key->ipv4.addr.dst = ip_hdr(skb)->daddr;
++ else if (key->eth.type == htons(ETH_P_IPV6))
++ memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
++ sizeof(key->ipv6.addr.dst));
++ else
++ return;
++
++ if (key->ip.proto == IPPROTO_UDP)
++ dst = udp_hdr(skb)->dest;
++ else if (key->ip.proto == IPPROTO_TCP)
++ dst = tcp_hdr(skb)->dest;
++ else if (key->ip.proto == IPPROTO_SCTP)
++ dst = sctp_hdr(skb)->dest;
++ else
++ return;
++
++ key->tp.dst = dst;
++ }
++}
++
+ /* Modelled after nf_nat_ipv[46]_fn().
+ * range is only used for new, uninitialized NAT state.
+ * Returns either NF_ACCEPT or NF_DROP.
+@@ -739,7 +790,7 @@ static bool skb_nfct_cached(struct net *net,
+ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct nf_nat_range2 *range,
+- enum nf_nat_manip_type maniptype)
++ enum nf_nat_manip_type maniptype, struct sw_flow_key *key)
+ {
+ int hooknum, nh_off, err = NF_ACCEPT;
+
+@@ -811,58 +862,11 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
+ push:
+ skb_push_rcsum(skb, nh_off);
+
+- return err;
+-}
+-
+-static void ovs_nat_update_key(struct sw_flow_key *key,
+- const struct sk_buff *skb,
+- enum nf_nat_manip_type maniptype)
+-{
+- if (maniptype == NF_NAT_MANIP_SRC) {
+- __be16 src;
+-
+- key->ct_state |= OVS_CS_F_SRC_NAT;
+- if (key->eth.type == htons(ETH_P_IP))
+- key->ipv4.addr.src = ip_hdr(skb)->saddr;
+- else if (key->eth.type == htons(ETH_P_IPV6))
+- memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
+- sizeof(key->ipv6.addr.src));
+- else
+- return;
+-
+- if (key->ip.proto == IPPROTO_UDP)
+- src = udp_hdr(skb)->source;
+- else if (key->ip.proto == IPPROTO_TCP)
+- src = tcp_hdr(skb)->source;
+- else if (key->ip.proto == IPPROTO_SCTP)
+- src = sctp_hdr(skb)->source;
+- else
+- return;
+-
+- key->tp.src = src;
+- } else {
+- __be16 dst;
+-
+- key->ct_state |= OVS_CS_F_DST_NAT;
+- if (key->eth.type == htons(ETH_P_IP))
+- key->ipv4.addr.dst = ip_hdr(skb)->daddr;
+- else if (key->eth.type == htons(ETH_P_IPV6))
+- memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
+- sizeof(key->ipv6.addr.dst));
+- else
+- return;
+-
+- if (key->ip.proto == IPPROTO_UDP)
+- dst = udp_hdr(skb)->dest;
+- else if (key->ip.proto == IPPROTO_TCP)
+- dst = tcp_hdr(skb)->dest;
+- else if (key->ip.proto == IPPROTO_SCTP)
+- dst = sctp_hdr(skb)->dest;
+- else
+- return;
++ /* Update the flow key if NAT successful. */
++ if (err == NF_ACCEPT)
++ ovs_nat_update_key(key, skb, maniptype);
+
+- key->tp.dst = dst;
+- }
++ return err;
+ }
+
+ /* Returns NF_DROP if the packet should be dropped, NF_ACCEPT otherwise. */
+@@ -904,7 +908,7 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
+ } else {
+ return NF_ACCEPT; /* Connection is not NATed. */
+ }
+- err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
++ err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype, key);
+
+ if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
+ if (ct->status & IPS_SRC_NAT) {
+@@ -914,17 +918,13 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
+ maniptype = NF_NAT_MANIP_SRC;
+
+ err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
+- maniptype);
++ maniptype, key);
+ } else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
+ err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
+- NF_NAT_MANIP_SRC);
++ NF_NAT_MANIP_SRC, key);
+ }
+ }
+
+- /* Mark NAT done if successful and update the flow key. */
+- if (err == NF_ACCEPT)
+- ovs_nat_update_key(key, skb, maniptype);
+-
+ return err;
+ }
+ #else /* !CONFIG_NF_NAT */
+@@ -967,7 +967,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
+
+ /* Associate skb with specified zone. */
+ if (tmpl) {
+- nf_conntrack_put(skb_nfct(skb));
++ ct = nf_ct_get(skb, &ctinfo);
++ nf_ct_put(ct);
+ nf_conntrack_get(&tmpl->ct_general);
+ nf_ct_set(skb, tmpl, IP_CT_NEW);
+ }
+@@ -1328,7 +1329,12 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
+
+ int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+- nf_conntrack_put(skb_nfct(skb));
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct;
++
++ ct = nf_ct_get(skb, &ctinfo);
++
++ nf_ct_put(ct);
+ nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+ ovs_ct_fill_key(skb, key, false);
+
+@@ -1716,7 +1722,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
+ goto err_free_ct;
+
+ __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
+- nf_conntrack_get(&ct_info.ct->ct_general);
+ return 0;
+ err_free_ct:
+ __ovs_ct_free_action(&ct_info);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9713035b89e3a..02096f2ec6784 100644
--- a/net/openvswitch/flow.c
@@ -153688,8 +237475,166 @@ index 9713035b89e3a..02096f2ec6784 100644
return err;
}
+diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
+index fd1f809e9bc1b..d77c21ff066c9 100644
+--- a/net/openvswitch/flow_netlink.c
++++ b/net/openvswitch/flow_netlink.c
+@@ -2201,8 +2201,8 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
+ icmpv6_key->icmpv6_type = ntohs(output->tp.src);
+ icmpv6_key->icmpv6_code = ntohs(output->tp.dst);
+
+- if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
+- icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
++ if (swkey->tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
++ swkey->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
+ struct ovs_key_nd *nd_key;
+
+ nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key));
+@@ -2288,6 +2288,62 @@ static struct sw_flow_actions *nla_alloc_flow_actions(int size)
+ return sfa;
+ }
+
++static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len);
++
++static void ovs_nla_free_check_pkt_len_action(const struct nlattr *action)
++{
++ const struct nlattr *a;
++ int rem;
++
++ nla_for_each_nested(a, action, rem) {
++ switch (nla_type(a)) {
++ case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL:
++ case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER:
++ ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
++ break;
++ }
++ }
++}
++
++static void ovs_nla_free_clone_action(const struct nlattr *action)
++{
++ const struct nlattr *a = nla_data(action);
++ int rem = nla_len(action);
++
++ switch (nla_type(a)) {
++ case OVS_CLONE_ATTR_EXEC:
++ /* The real list of actions follows this attribute. */
++ a = nla_next(a, &rem);
++ ovs_nla_free_nested_actions(a, rem);
++ break;
++ }
++}
++
++static void ovs_nla_free_dec_ttl_action(const struct nlattr *action)
++{
++ const struct nlattr *a = nla_data(action);
++
++ switch (nla_type(a)) {
++ case OVS_DEC_TTL_ATTR_ACTION:
++ ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
++ break;
++ }
++}
++
++static void ovs_nla_free_sample_action(const struct nlattr *action)
++{
++ const struct nlattr *a = nla_data(action);
++ int rem = nla_len(action);
++
++ switch (nla_type(a)) {
++ case OVS_SAMPLE_ATTR_ARG:
++ /* The real list of actions follows this attribute. */
++ a = nla_next(a, &rem);
++ ovs_nla_free_nested_actions(a, rem);
++ break;
++ }
++}
++
+ static void ovs_nla_free_set_action(const struct nlattr *a)
+ {
+ const struct nlattr *ovs_key = nla_data(a);
+@@ -2301,25 +2357,54 @@ static void ovs_nla_free_set_action(const struct nlattr *a)
+ }
+ }
+
+-void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
++static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
+ {
+ const struct nlattr *a;
+ int rem;
+
+- if (!sf_acts)
++ /* Whenever new actions are added, the need to update this
++ * function should be considered.
++ */
++ BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23);
++
++ if (!actions)
+ return;
+
+- nla_for_each_attr(a, sf_acts->actions, sf_acts->actions_len, rem) {
++ nla_for_each_attr(a, actions, len, rem) {
+ switch (nla_type(a)) {
+- case OVS_ACTION_ATTR_SET:
+- ovs_nla_free_set_action(a);
++ case OVS_ACTION_ATTR_CHECK_PKT_LEN:
++ ovs_nla_free_check_pkt_len_action(a);
++ break;
++
++ case OVS_ACTION_ATTR_CLONE:
++ ovs_nla_free_clone_action(a);
+ break;
++
+ case OVS_ACTION_ATTR_CT:
+ ovs_ct_free_action(a);
+ break;
++
++ case OVS_ACTION_ATTR_DEC_TTL:
++ ovs_nla_free_dec_ttl_action(a);
++ break;
++
++ case OVS_ACTION_ATTR_SAMPLE:
++ ovs_nla_free_sample_action(a);
++ break;
++
++ case OVS_ACTION_ATTR_SET:
++ ovs_nla_free_set_action(a);
++ break;
+ }
+ }
++}
++
++void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
++{
++ if (!sf_acts)
++ return;
+
++ ovs_nla_free_nested_actions(sf_acts->actions, sf_acts->actions_len);
+ kfree(sf_acts);
+ }
+
+@@ -2351,7 +2436,7 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
+ new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
+
+ if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
+- if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) {
++ if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) {
+ OVS_NLERR(log, "Flow action size exceeds max %u",
+ MAX_ACTIONS_BUFSIZE);
+ return ERR_PTR(-EMSGSIZE);
+@@ -3429,7 +3514,9 @@ static int clone_action_to_attr(const struct nlattr *attr,
+ if (!start)
+ return -EMSGSIZE;
+
+- err = ovs_nla_put_actions(nla_data(attr), rem, skb);
++ /* Skipping the OVS_CLONE_ATTR_EXEC that is always the first attribute. */
++ attr = nla_next(nla_data(attr), &rem);
++ err = ovs_nla_put_actions(attr, rem, skb);
+
+ if (err)
+ nla_nest_cancel(skb, start);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
-index 2a2bc64f75cfd..e00c38f242c32 100644
+index 2a2bc64f75cfd..88c3b5cf8d94c 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1738,6 +1738,7 @@ static int fanout_add(struct sock *sk, struct fanout_args *args)
@@ -153712,7 +237657,47 @@ index 2a2bc64f75cfd..e00c38f242c32 100644
po->rollover = rollover;
rollover = NULL;
refcount_set(&match->sk_ref, refcount_read(&match->sk_ref) + 1);
-@@ -3323,6 +3327,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
+@@ -2277,8 +2281,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
+ copy_skb = skb_get(skb);
+ skb_head = skb->data;
+ }
+- if (copy_skb)
++ if (copy_skb) {
++ memset(&PACKET_SKB_CB(copy_skb)->sa.ll, 0,
++ sizeof(PACKET_SKB_CB(copy_skb)->sa.ll));
+ skb_set_owner_r(copy_skb, sk);
++ }
+ }
+ snaplen = po->rx_ring.frame_size - macoff;
+ if ((int)snaplen < 0) {
+@@ -2813,8 +2820,9 @@ tpacket_error:
+
+ status = TP_STATUS_SEND_REQUEST;
+ err = po->xmit(skb);
+- if (unlikely(err > 0)) {
+- err = net_xmit_errno(err);
++ if (unlikely(err != 0)) {
++ if (err > 0)
++ err = net_xmit_errno(err);
+ if (err && __packet_get_status(po, ph) ==
+ TP_STATUS_AVAILABLE) {
+ /* skb was destructed already */
+@@ -3015,8 +3023,12 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
+ skb->no_fcs = 1;
+
+ err = po->xmit(skb);
+- if (err > 0 && (err = net_xmit_errno(err)) != 0)
+- goto out_unlock;
++ if (unlikely(err != 0)) {
++ if (err > 0)
++ err = net_xmit_errno(err);
++ if (err)
++ goto out_unlock;
++ }
+
+ dev_put(dev);
+
+@@ -3323,6 +3335,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
po->prot_hook.func = packet_rcv_spkt;
po->prot_hook.af_packet_priv = sk;
@@ -153720,7 +237705,27 @@ index 2a2bc64f75cfd..e00c38f242c32 100644
if (proto) {
po->prot_hook.type = proto;
-@@ -3904,7 +3909,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
+@@ -3429,6 +3442,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ sock_recv_ts_and_drops(msg, sk, skb);
+
+ if (msg->msg_name) {
++ const size_t max_len = min(sizeof(skb->cb),
++ sizeof(struct sockaddr_storage));
+ int copy_len;
+
+ /* If the address length field is there to be filled
+@@ -3451,6 +3466,10 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ msg->msg_namelen = sizeof(struct sockaddr_ll);
+ }
+ }
++ if (WARN_ON_ONCE(copy_len > max_len)) {
++ copy_len = max_len;
++ msg->msg_namelen = copy_len;
++ }
+ memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len);
+ }
+
+@@ -3904,7 +3923,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
}
case PACKET_FANOUT_DATA:
{
@@ -153730,7 +237735,7 @@ index 2a2bc64f75cfd..e00c38f242c32 100644
return -EINVAL;
return fanout_set_data(po, optval, optlen);
-@@ -4457,9 +4463,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
+@@ -4457,9 +4477,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
}
out_free_pg_vec:
@@ -153789,8 +237794,157 @@ index abf19c0e3ba0b..5327d130c4b56 100644
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
}
release_sock(sk);
+diff --git a/net/rfkill/core.c b/net/rfkill/core.c
+index ac15a944573f7..068c7bcd30c94 100644
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -78,6 +78,7 @@ struct rfkill_data {
+ struct mutex mtx;
+ wait_queue_head_t read_wait;
+ bool input_handler;
++ u8 max_size;
+ };
+
+
+@@ -1141,6 +1142,8 @@ static int rfkill_fop_open(struct inode *inode, struct file *file)
+ if (!data)
+ return -ENOMEM;
+
++ data->max_size = RFKILL_EVENT_SIZE_V1;
++
+ INIT_LIST_HEAD(&data->events);
+ mutex_init(&data->mtx);
+ init_waitqueue_head(&data->read_wait);
+@@ -1223,6 +1226,7 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
+ list);
+
+ sz = min_t(unsigned long, sizeof(ev->ev), count);
++ sz = min_t(unsigned long, sz, data->max_size);
+ ret = sz;
+ if (copy_to_user(buf, &ev->ev, sz))
+ ret = -EFAULT;
+@@ -1237,6 +1241,7 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
+ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+ {
++ struct rfkill_data *data = file->private_data;
+ struct rfkill *rfkill;
+ struct rfkill_event_ext ev;
+ int ret;
+@@ -1251,6 +1256,7 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
+ * our API version even in a write() call, if it cares.
+ */
+ count = min(count, sizeof(ev));
++ count = min_t(size_t, count, data->max_size);
+ if (copy_from_user(&ev, buf, count))
+ return -EFAULT;
+
+@@ -1310,31 +1316,47 @@ static int rfkill_fop_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-#ifdef CONFIG_RFKILL_INPUT
+ static long rfkill_fop_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+ struct rfkill_data *data = file->private_data;
++ int ret = -ENOSYS;
++ u32 size;
+
+ if (_IOC_TYPE(cmd) != RFKILL_IOC_MAGIC)
+ return -ENOSYS;
+
+- if (_IOC_NR(cmd) != RFKILL_IOC_NOINPUT)
+- return -ENOSYS;
+-
+ mutex_lock(&data->mtx);
+-
+- if (!data->input_handler) {
+- if (atomic_inc_return(&rfkill_input_disabled) == 1)
+- printk(KERN_DEBUG "rfkill: input handler disabled\n");
+- data->input_handler = true;
++ switch (_IOC_NR(cmd)) {
++#ifdef CONFIG_RFKILL_INPUT
++ case RFKILL_IOC_NOINPUT:
++ if (!data->input_handler) {
++ if (atomic_inc_return(&rfkill_input_disabled) == 1)
++ printk(KERN_DEBUG "rfkill: input handler disabled\n");
++ data->input_handler = true;
++ }
++ ret = 0;
++ break;
++#endif
++ case RFKILL_IOC_MAX_SIZE:
++ if (get_user(size, (__u32 __user *)arg)) {
++ ret = -EFAULT;
++ break;
++ }
++ if (size < RFKILL_EVENT_SIZE_V1 || size > U8_MAX) {
++ ret = -EINVAL;
++ break;
++ }
++ data->max_size = size;
++ ret = 0;
++ break;
++ default:
++ break;
+ }
+-
+ mutex_unlock(&data->mtx);
+
+- return 0;
++ return ret;
+ }
+-#endif
+
+ static const struct file_operations rfkill_fops = {
+ .owner = THIS_MODULE,
+@@ -1343,10 +1365,8 @@ static const struct file_operations rfkill_fops = {
+ .write = rfkill_fop_write,
+ .poll = rfkill_fop_poll,
+ .release = rfkill_fop_release,
+-#ifdef CONFIG_RFKILL_INPUT
+ .unlocked_ioctl = rfkill_fop_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+-#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
+index 7bd6f8a66a3ef..969e532f77a90 100644
+--- a/net/rxrpc/ar-internal.h
++++ b/net/rxrpc/ar-internal.h
+@@ -777,14 +777,12 @@ void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool,
+ enum rxrpc_propose_ack_trace);
+ void rxrpc_process_call(struct work_struct *);
+
+-static inline void rxrpc_reduce_call_timer(struct rxrpc_call *call,
+- unsigned long expire_at,
+- unsigned long now,
+- enum rxrpc_timer_trace why)
+-{
+- trace_rxrpc_timer(call, why, now);
+- timer_reduce(&call->timer, expire_at);
+-}
++void rxrpc_reduce_call_timer(struct rxrpc_call *call,
++ unsigned long expire_at,
++ unsigned long now,
++ enum rxrpc_timer_trace why);
++
++void rxrpc_delete_call_timer(struct rxrpc_call *call);
+
+ /*
+ * call_object.c
+@@ -808,6 +806,7 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
+ bool __rxrpc_queue_call(struct rxrpc_call *);
+ bool rxrpc_queue_call(struct rxrpc_call *);
+ void rxrpc_see_call(struct rxrpc_call *);
++bool rxrpc_try_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op);
+ void rxrpc_get_call(struct rxrpc_call *, enum rxrpc_call_trace);
+ void rxrpc_put_call(struct rxrpc_call *, enum rxrpc_call_trace);
+ void rxrpc_cleanup_call(struct rxrpc_call *);
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
-index 6be2672a65eab..df864e6922679 100644
+index 6be2672a65eab..22e05de5d1ca9 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -157,7 +157,7 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call)
@@ -153823,6 +237977,97 @@ index 6be2672a65eab..df864e6922679 100644
WRITE_ONCE(call->resend_at, resend_at);
if (unacked)
+@@ -312,7 +310,7 @@ recheck_state:
+ }
+
+ if (call->state == RXRPC_CALL_COMPLETE) {
+- del_timer_sync(&call->timer);
++ rxrpc_delete_call_timer(call);
+ goto out_put;
+ }
+
+diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
+index 4eb91d958a48d..043508fd8d8a5 100644
+--- a/net/rxrpc/call_object.c
++++ b/net/rxrpc/call_object.c
+@@ -53,10 +53,30 @@ static void rxrpc_call_timer_expired(struct timer_list *t)
+
+ if (call->state < RXRPC_CALL_COMPLETE) {
+ trace_rxrpc_timer(call, rxrpc_timer_expired, jiffies);
+- rxrpc_queue_call(call);
++ __rxrpc_queue_call(call);
++ } else {
++ rxrpc_put_call(call, rxrpc_call_put);
++ }
++}
++
++void rxrpc_reduce_call_timer(struct rxrpc_call *call,
++ unsigned long expire_at,
++ unsigned long now,
++ enum rxrpc_timer_trace why)
++{
++ if (rxrpc_try_get_call(call, rxrpc_call_got_timer)) {
++ trace_rxrpc_timer(call, why, now);
++ if (timer_reduce(&call->timer, expire_at))
++ rxrpc_put_call(call, rxrpc_call_put_notimer);
+ }
+ }
+
++void rxrpc_delete_call_timer(struct rxrpc_call *call)
++{
++ if (del_timer_sync(&call->timer))
++ rxrpc_put_call(call, rxrpc_call_put_timer);
++}
++
+ static struct lock_class_key rxrpc_call_user_mutex_lock_class_key;
+
+ /*
+@@ -463,6 +483,17 @@ void rxrpc_see_call(struct rxrpc_call *call)
+ }
+ }
+
++bool rxrpc_try_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
++{
++ const void *here = __builtin_return_address(0);
++ int n = atomic_fetch_add_unless(&call->usage, 1, 0);
++
++ if (n == 0)
++ return false;
++ trace_rxrpc_call(call->debug_id, op, n, here, NULL);
++ return true;
++}
++
+ /*
+ * Note the addition of a ref on a call.
+ */
+@@ -510,8 +541,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
+ spin_unlock_bh(&call->lock);
+
+ rxrpc_put_call_slot(call);
+-
+- del_timer_sync(&call->timer);
++ rxrpc_delete_call_timer(call);
+
+ /* Make sure we don't get any more notifications */
+ write_lock_bh(&rx->recvmsg_lock);
+@@ -618,6 +648,8 @@ static void rxrpc_destroy_call(struct work_struct *work)
+ struct rxrpc_call *call = container_of(work, struct rxrpc_call, processor);
+ struct rxrpc_net *rxnet = call->rxnet;
+
++ rxrpc_delete_call_timer(call);
++
+ rxrpc_put_connection(call->conn);
+ rxrpc_put_peer(call->peer);
+ kfree(call->rxtx_buffer);
+@@ -652,8 +684,6 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
+
+ memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
+
+- del_timer_sync(&call->timer);
+-
+ ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
+ ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
+
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index dbea0bfee48e9..8120138dac018 100644
--- a/net/rxrpc/conn_client.c
@@ -153861,6 +238106,40 @@ index dbea0bfee48e9..8120138dac018 100644
found_bundle:
rxrpc_get_bundle(bundle);
spin_unlock(&local->client_bundles_lock);
+diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
+index a4111408ffd0c..6a1611b0e3037 100644
+--- a/net/rxrpc/local_object.c
++++ b/net/rxrpc/local_object.c
+@@ -117,6 +117,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
+ local, srx->transport_type, srx->transport.family);
+
+ udp_conf.family = srx->transport.family;
++ udp_conf.use_udp_checksums = true;
+ if (udp_conf.family == AF_INET) {
+ udp_conf.local_ip = srx->transport.sin.sin_addr;
+ udp_conf.local_udp_port = srx->transport.sin.sin_port;
+@@ -124,6 +125,8 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
+ } else {
+ udp_conf.local_ip6 = srx->transport.sin6.sin6_addr;
+ udp_conf.local_udp_port = srx->transport.sin6.sin6_port;
++ udp_conf.use_udp6_tx_checksums = true;
++ udp_conf.use_udp6_rx_checksums = true;
+ #endif
+ }
+ ret = udp_sock_create(net, &udp_conf, &local->socket);
+diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c
+index 25bbc4cc8b135..cc7e30733feb0 100644
+--- a/net/rxrpc/net_ns.c
++++ b/net/rxrpc/net_ns.c
+@@ -115,6 +115,8 @@ static __net_exit void rxrpc_exit_net(struct net *net)
+ rxnet->live = false;
+ del_timer_sync(&rxnet->peer_keepalive_timer);
+ cancel_work_sync(&rxnet->peer_keepalive_work);
++ /* Remove the timer again as the worker may have restarted it. */
++ del_timer_sync(&rxnet->peer_keepalive_timer);
+ rxrpc_destroy_all_calls(rxnet);
+ rxrpc_destroy_all_connections(rxnet);
+ rxrpc_destroy_all_peers(rxnet);
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 10f2bf2e9068a..a45c83f22236e 100644
--- a/net/rxrpc/output.c
@@ -153933,6 +238212,38 @@ index 4e565eeab4260..be61d6f5be8d1 100644
}
static u32 rxrpc_bound_rto(u32 rto)
+diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
+index ead3471307ee5..ee269e0e6ee87 100644
+--- a/net/rxrpc/server_key.c
++++ b/net/rxrpc/server_key.c
+@@ -84,6 +84,9 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
+
+ prep->payload.data[1] = (struct rxrpc_security *)sec;
+
++ if (!sec->preparse_server_key)
++ return -EINVAL;
++
+ return sec->preparse_server_key(prep);
+ }
+
+@@ -91,7 +94,7 @@ static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
+ {
+ const struct rxrpc_security *sec = prep->payload.data[1];
+
+- if (sec)
++ if (sec && sec->free_preparse_server_key)
+ sec->free_preparse_server_key(prep);
+ }
+
+@@ -99,7 +102,7 @@ static void rxrpc_destroy_s(struct key *key)
+ {
+ const struct rxrpc_security *sec = key->payload.data[1];
+
+- if (sec)
++ if (sec && sec->destroy_server_key)
+ sec->destroy_server_key(key);
+ }
+
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 7dd3a2dc5fa40..7d53272727bfa 100644
--- a/net/sched/act_api.c
@@ -153965,7 +238276,7 @@ index 7dd3a2dc5fa40..7d53272727bfa 100644
if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK;
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
-index 90866ae45573a..4ffea1290ce1c 100644
+index 90866ae45573a..f4fd584fba08a 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -516,11 +516,6 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
@@ -153980,7 +238291,39 @@ index 90866ae45573a..4ffea1290ce1c 100644
switch (family) {
case NFPROTO_IPV4:
if (!tcf_ct_flow_table_fill_tuple_ipv4(skb, &tuple, &tcph))
-@@ -690,10 +685,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+@@ -588,22 +583,25 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
+ if (!ct)
+ return false;
+ if (!net_eq(net, read_pnet(&ct->ct_net)))
+- return false;
++ goto drop_ct;
+ if (nf_ct_zone(ct)->id != zone_id)
+- return false;
++ goto drop_ct;
+
+ /* Force conntrack entry direction. */
+ if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
+ if (nf_ct_is_confirmed(ct))
+ nf_ct_kill(ct);
+
+- nf_conntrack_put(&ct->ct_general);
+- nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+-
+- return false;
++ goto drop_ct;
+ }
+
+ return true;
++
++drop_ct:
++ nf_ct_put(ct);
++ nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
++
++ return false;
+ }
+
+ /* Trim the skb to the length specified by the IP/IPv6 header,
+@@ -690,10 +688,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
u8 family, u16 zone, bool *defrag)
{
enum ip_conntrack_info ctinfo;
@@ -153992,7 +238335,7 @@ index 90866ae45573a..4ffea1290ce1c 100644
/* Previously seen (loopback)? Ignore. */
ct = nf_ct_get(skb, &ctinfo);
-@@ -708,7 +703,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+@@ -708,7 +706,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
return err;
skb_get(skb);
@@ -154001,7 +238344,7 @@ index 90866ae45573a..4ffea1290ce1c 100644
if (family == NFPROTO_IPV4) {
enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
-@@ -722,7 +717,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+@@ -722,7 +720,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
if (!err) {
*defrag = true;
@@ -154010,7 +238353,7 @@ index 90866ae45573a..4ffea1290ce1c 100644
}
} else { /* NFPROTO_IPV6 */
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
-@@ -735,7 +730,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+@@ -735,7 +733,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
if (!err) {
*defrag = true;
@@ -154019,7 +238362,7 @@ index 90866ae45573a..4ffea1290ce1c 100644
}
#else
err = -EOPNOTSUPP;
-@@ -744,7 +739,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+@@ -744,7 +742,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
}
if (err != -EINPROGRESS)
@@ -154028,7 +238371,16 @@ index 90866ae45573a..4ffea1290ce1c 100644
skb_clear_hash(skb);
skb->ignore_df = 1;
return err;
-@@ -839,6 +834,12 @@ static int ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
+@@ -762,7 +760,7 @@ static void tcf_ct_params_free(struct rcu_head *head)
+ tcf_ct_flow_table_put(params);
+
+ if (params->tmpl)
+- nf_conntrack_put(&params->tmpl->ct_general);
++ nf_ct_put(params->tmpl);
+ kfree(params);
+ }
+
+@@ -839,6 +837,12 @@ static int ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
}
err = nf_nat_packet(ct, ctinfo, hooknum, skb);
@@ -154041,7 +238393,7 @@ index 90866ae45573a..4ffea1290ce1c 100644
out:
return err;
}
-@@ -963,7 +964,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
+@@ -963,10 +967,10 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
tcf_action_update_bstats(&c->common, skb);
if (clear) {
@@ -154049,8 +238401,12 @@ index 90866ae45573a..4ffea1290ce1c 100644
+ tc_skb_cb(skb)->post_ct = false;
ct = nf_ct_get(skb, &ctinfo);
if (ct) {
- nf_conntrack_put(&ct->ct_general);
-@@ -1048,7 +1049,8 @@ do_nat:
+- nf_conntrack_put(&ct->ct_general);
++ nf_ct_put(ct);
+ nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+ }
+
+@@ -1048,7 +1052,8 @@ do_nat:
out_push:
skb_push_rcsum(skb, nh_ofs);
@@ -154060,6 +238416,14 @@ index 90866ae45573a..4ffea1290ce1c 100644
out_clear:
if (defrag)
qdisc_skb_cb(skb)->pkt_len = skb->len;
+@@ -1227,7 +1232,6 @@ static int tcf_ct_fill_params(struct net *net,
+ return -ENOMEM;
+ }
+ __set_bit(IPS_CONFIRMED_BIT, &tmpl->status);
+- nf_conntrack_get(&tmpl->ct_general);
+ p->tmpl = tmpl;
+
+ return 0;
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index d64b0eeccbe4d..efc963ab995a3 100644
--- a/net/sched/act_mirred.c
@@ -154105,8 +238469,74 @@ index d64b0eeccbe4d..efc963ab995a3 100644
expects_nh = want_ingress || !m_mac_header_xmit;
at_nh = skb->data == skb_network_header(skb);
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index c6c862c459cc3..1262a84b725fc 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -149,7 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+ struct nlattr *pattr;
+ struct tcf_pedit *p;
+ int ret = 0, err;
+- int ksize;
++ int i, ksize;
+ u32 index;
+
+ if (!nla) {
+@@ -228,6 +228,22 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+ p->tcfp_nkeys = parm->nkeys;
+ }
+ memcpy(p->tcfp_keys, parm->keys, ksize);
++ p->tcfp_off_max_hint = 0;
++ for (i = 0; i < p->tcfp_nkeys; ++i) {
++ u32 cur = p->tcfp_keys[i].off;
++
++ /* sanitize the shift value for any later use */
++ p->tcfp_keys[i].shift = min_t(size_t, BITS_PER_TYPE(int) - 1,
++ p->tcfp_keys[i].shift);
++
++ /* The AT option can read a single byte, we can bound the actual
++ * value with uchar max.
++ */
++ cur += (0xff & p->tcfp_keys[i].offmask) >> p->tcfp_keys[i].shift;
++
++ /* Each key touches 4 bytes starting from the computed offset */
++ p->tcfp_off_max_hint = max(p->tcfp_off_max_hint, cur + 4);
++ }
+
+ p->tcfp_flags = parm->flags;
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
+@@ -308,13 +324,18 @@ static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
+ struct tcf_result *res)
+ {
+ struct tcf_pedit *p = to_pedit(a);
++ u32 max_offset;
+ int i;
+
+- if (skb_unclone(skb, GFP_ATOMIC))
+- return p->tcf_action;
+-
+ spin_lock(&p->tcf_lock);
+
++ max_offset = (skb_transport_header_was_set(skb) ?
++ skb_transport_offset(skb) :
++ skb_network_offset(skb)) +
++ p->tcfp_off_max_hint;
++ if (skb_ensure_writable(skb, min(skb->len, max_offset)))
++ goto unlock;
++
+ tcf_lastuse_update(&p->tcf_tm);
+
+ if (p->tcfp_nkeys > 0) {
+@@ -403,6 +424,7 @@ bad:
+ p->tcf_qstats.overlimits++;
+ done:
+ bstats_update(&p->tcf_bstats, skb);
++unlock:
+ spin_unlock(&p->tcf_lock);
+ return p->tcf_action;
+ }
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
-index 2ef8f5a6205a9..cd44cac7fbcf9 100644
+index 2ef8f5a6205a9..4b552c10e7b98 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1044,7 +1044,7 @@ static int __tcf_qdisc_find(struct net *net, struct Qdisc **q,
@@ -154138,6 +238568,18 @@ index 2ef8f5a6205a9..cd44cac7fbcf9 100644
}
return ret;
+@@ -1648,10 +1653,10 @@ static int tcf_chain_tp_insert(struct tcf_chain *chain,
+ if (chain->flushing)
+ return -EAGAIN;
+
++ RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info));
+ if (*chain_info->pprev == chain->filter_chain)
+ tcf_chain0_head_change(chain, tp);
+ tcf_proto_get(tp);
+- RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info));
+ rcu_assign_pointer(*chain_info->pprev, tp);
+
+ return 0;
@@ -1940,9 +1945,9 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
bool prio_allocate;
u32 parent;
@@ -154205,7 +238647,7 @@ index 2ef8f5a6205a9..cd44cac7fbcf9 100644
}
} else if (is_tcf_skbedit_ptype(act)) {
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
-index eb6345a027e13..709348262410c 100644
+index eb6345a027e13..32b03a13f9b25 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -19,6 +19,7 @@
@@ -154235,6 +238677,137 @@ index eb6345a027e13..709348262410c 100644
skb_flow_dissect_hash(skb, &mask->dissector, &skb_key);
skb_flow_dissect(skb, &mask->dissector, &skb_key, 0);
+@@ -1002,6 +1004,7 @@ static int fl_set_key_mpls(struct nlattr **tb,
+ static void fl_set_key_vlan(struct nlattr **tb,
+ __be16 ethertype,
+ int vlan_id_key, int vlan_prio_key,
++ int vlan_next_eth_type_key,
+ struct flow_dissector_key_vlan *key_val,
+ struct flow_dissector_key_vlan *key_mask)
+ {
+@@ -1020,6 +1023,11 @@ static void fl_set_key_vlan(struct nlattr **tb,
+ }
+ key_val->vlan_tpid = ethertype;
+ key_mask->vlan_tpid = cpu_to_be16(~0);
++ if (tb[vlan_next_eth_type_key]) {
++ key_val->vlan_eth_type =
++ nla_get_be16(tb[vlan_next_eth_type_key]);
++ key_mask->vlan_eth_type = cpu_to_be16(~0);
++ }
+ }
+
+ static void fl_set_key_flag(u32 flower_key, u32 flower_mask,
+@@ -1516,8 +1524,9 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
+
+ if (eth_type_vlan(ethertype)) {
+ fl_set_key_vlan(tb, ethertype, TCA_FLOWER_KEY_VLAN_ID,
+- TCA_FLOWER_KEY_VLAN_PRIO, &key->vlan,
+- &mask->vlan);
++ TCA_FLOWER_KEY_VLAN_PRIO,
++ TCA_FLOWER_KEY_VLAN_ETH_TYPE,
++ &key->vlan, &mask->vlan);
+
+ if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
+ ethertype = nla_get_be16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
+@@ -1525,6 +1534,7 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
+ fl_set_key_vlan(tb, ethertype,
+ TCA_FLOWER_KEY_CVLAN_ID,
+ TCA_FLOWER_KEY_CVLAN_PRIO,
++ TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+ &key->cvlan, &mask->cvlan);
+ fl_set_key_val(tb, &key->basic.n_proto,
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+@@ -2880,13 +2890,13 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
+ goto nla_put_failure;
+
+ if (mask->basic.n_proto) {
+- if (mask->cvlan.vlan_tpid) {
++ if (mask->cvlan.vlan_eth_type) {
+ if (nla_put_be16(skb, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+ key->basic.n_proto))
+ goto nla_put_failure;
+- } else if (mask->vlan.vlan_tpid) {
++ } else if (mask->vlan.vlan_eth_type) {
+ if (nla_put_be16(skb, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
+- key->basic.n_proto))
++ key->vlan.vlan_eth_type))
+ goto nla_put_failure;
+ }
+ }
+diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
+index 4272814487f09..5d30db0d71574 100644
+--- a/net/sched/cls_u32.c
++++ b/net/sched/cls_u32.c
+@@ -386,14 +386,19 @@ static int u32_init(struct tcf_proto *tp)
+ return 0;
+ }
+
+-static int u32_destroy_key(struct tc_u_knode *n, bool free_pf)
++static void __u32_destroy_key(struct tc_u_knode *n)
+ {
+ struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
+
+ tcf_exts_destroy(&n->exts);
+- tcf_exts_put_net(&n->exts);
+ if (ht && --ht->refcnt == 0)
+ kfree(ht);
++ kfree(n);
++}
++
++static void u32_destroy_key(struct tc_u_knode *n, bool free_pf)
++{
++ tcf_exts_put_net(&n->exts);
+ #ifdef CONFIG_CLS_U32_PERF
+ if (free_pf)
+ free_percpu(n->pf);
+@@ -402,8 +407,7 @@ static int u32_destroy_key(struct tc_u_knode *n, bool free_pf)
+ if (free_pf)
+ free_percpu(n->pcpu_success);
+ #endif
+- kfree(n);
+- return 0;
++ __u32_destroy_key(n);
+ }
+
+ /* u32_delete_key_rcu should be called when free'ing a copied
+@@ -810,10 +814,6 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp,
+ new->flags = n->flags;
+ RCU_INIT_POINTER(new->ht_down, ht);
+
+- /* bump reference count as long as we hold pointer to structure */
+- if (ht)
+- ht->refcnt++;
+-
+ #ifdef CONFIG_CLS_U32_PERF
+ /* Statistics may be incremented by readers during update
+ * so we must keep them in tact. When the node is later destroyed
+@@ -835,6 +835,10 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp,
+ return NULL;
+ }
+
++ /* bump reference count as long as we hold pointer to structure */
++ if (ht)
++ ht->refcnt++;
++
+ return new;
+ }
+
+@@ -898,13 +902,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
+ tca[TCA_RATE], flags, extack);
+
+ if (err) {
+- u32_destroy_key(new, false);
++ __u32_destroy_key(new);
+ return err;
+ }
+
+ err = u32_replace_hw_knode(tp, new, flags, extack);
+ if (err) {
+- u32_destroy_key(new, false);
++ __u32_destroy_key(new);
+ return err;
+ }
+
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 12f39a2dffd47..0fb387c9d706d 100644
--- a/net/sched/sch_api.c
@@ -154654,7 +239227,7 @@ index 58a9d42b52b8f..aea435b0aeb34 100644
max_cl_shift = __fls(max_classes);
q->max_agg_classes = 1<<max_cl_shift;
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
-index b9fd18d986464..a66398fb2d6d0 100644
+index b9fd18d986464..474ba4db5de2d 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -95,18 +95,22 @@ static ktime_t sched_base_time(const struct sched_gate_list *sched)
@@ -154694,7 +239267,17 @@ index b9fd18d986464..a66398fb2d6d0 100644
}
/* There are a few scenarios where we will have to modify the txtime from
-@@ -1352,6 +1356,7 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb,
+@@ -413,7 +417,8 @@ static int taprio_enqueue_one(struct sk_buff *skb, struct Qdisc *sch,
+ {
+ struct taprio_sched *q = qdisc_priv(sch);
+
+- if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
++ /* sk_flags are only safe to use on full sockets. */
++ if (skb->sk && sk_fullsock(skb->sk) && sock_flag(skb->sk, SOCK_TXTIME)) {
+ if (!is_valid_interval(skb, sch))
+ return qdisc_drop(skb, sch, to_free);
+ } else if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+@@ -1352,6 +1357,7 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb,
}
} else if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]) {
int clockid = nla_get_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]);
@@ -154702,7 +239285,7 @@ index b9fd18d986464..a66398fb2d6d0 100644
/* We only support static clockids and we don't allow
* for it to be modified after the first init.
-@@ -1366,22 +1371,24 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb,
+@@ -1366,22 +1372,24 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb,
switch (clockid) {
case CLOCK_REALTIME:
@@ -154732,10 +239315,38 @@ index b9fd18d986464..a66398fb2d6d0 100644
q->clockid = clockid;
} else {
diff --git a/net/sctp/diag.c b/net/sctp/diag.c
-index 760b367644c12..034e2c74497df 100644
+index 760b367644c12..d9c6d8f30f093 100644
--- a/net/sctp/diag.c
+++ b/net/sctp/diag.c
-@@ -245,54 +245,49 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
+@@ -61,10 +61,6 @@ static void inet_diag_msg_sctpasoc_fill(struct inet_diag_msg *r,
+ r->idiag_timer = SCTP_EVENT_TIMEOUT_T3_RTX;
+ r->idiag_retrans = asoc->rtx_data_chunks;
+ r->idiag_expires = jiffies_to_msecs(t3_rtx->expires - jiffies);
+- } else {
+- r->idiag_timer = 0;
+- r->idiag_retrans = 0;
+- r->idiag_expires = 0;
+ }
+ }
+
+@@ -144,13 +140,14 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc,
+ r = nlmsg_data(nlh);
+ BUG_ON(!sk_fullsock(sk));
+
++ r->idiag_timer = 0;
++ r->idiag_retrans = 0;
++ r->idiag_expires = 0;
+ if (asoc) {
+ inet_diag_msg_sctpasoc_fill(r, sk, asoc);
+ } else {
+ inet_diag_msg_common_fill(r, sk);
+ r->idiag_state = sk->sk_state;
+- r->idiag_timer = 0;
+- r->idiag_retrans = 0;
+ }
+
+ if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
+@@ -245,54 +242,49 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
+ 64;
}
@@ -154807,7 +239418,7 @@ index 760b367644c12..034e2c74497df 100644
struct sctp_comm_param *commp = p;
struct sock *sk = ep->base.sk;
struct sk_buff *skb = commp->skb;
-@@ -302,6 +297,8 @@ static int sctp_sock_dump(struct sctp_transport *tsp, void *p)
+@@ -302,6 +294,8 @@ static int sctp_sock_dump(struct sctp_transport *tsp, void *p)
int err = 0;
lock_sock(sk);
@@ -154816,7 +239427,7 @@ index 760b367644c12..034e2c74497df 100644
list_for_each_entry(assoc, &ep->asocs, asocs) {
if (cb->args[4] < cb->args[1])
goto next;
-@@ -344,9 +341,8 @@ release:
+@@ -344,9 +338,8 @@ release:
return err;
}
@@ -154827,7 +239438,7 @@ index 760b367644c12..034e2c74497df 100644
struct sctp_comm_param *commp = p;
struct sock *sk = ep->base.sk;
const struct inet_diag_req_v2 *r = commp->r;
-@@ -429,15 +425,15 @@ static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+@@ -429,15 +422,15 @@ static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
static int sctp_diag_dump_one(struct netlink_callback *cb,
const struct inet_diag_req_v2 *req)
{
@@ -154847,7 +239458,7 @@ index 760b367644c12..034e2c74497df 100644
};
if (req->sdiag_family == AF_INET) {
-@@ -460,7 +456,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb,
+@@ -460,7 +453,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb,
paddr.v6.sin6_family = AF_INET6;
}
@@ -154856,7 +239467,7 @@ index 760b367644c12..034e2c74497df 100644
net, &laddr, &paddr, &commp);
}
-@@ -505,8 +501,8 @@ skip:
+@@ -505,8 +498,8 @@ skip:
if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE)))
goto done;
@@ -154938,8 +239549,47 @@ index 4dfb5ea82b05b..cdfdbd353c678 100644
}
/* alloc head skb */
+diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
+index ff47091c385e7..b3950963fc8f0 100644
+--- a/net/sctp/outqueue.c
++++ b/net/sctp/outqueue.c
+@@ -911,6 +911,7 @@ static void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx)
+ ctx->asoc->base.sk->sk_err = -error;
+ return;
+ }
++ ctx->asoc->stats.octrlchunks++;
+ break;
+
+ case SCTP_CID_ABORT:
+@@ -935,7 +936,10 @@ static void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx)
+
+ case SCTP_CID_HEARTBEAT:
+ if (chunk->pmtu_probe) {
+- sctp_packet_singleton(ctx->transport, chunk, ctx->gfp);
++ error = sctp_packet_singleton(ctx->transport,
++ chunk, ctx->gfp);
++ if (!error)
++ ctx->asoc->stats.octrlchunks++;
+ break;
+ }
+ fallthrough;
+diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
+index b3815b568e8e5..463c4a58d2c36 100644
+--- a/net/sctp/sm_sideeffect.c
++++ b/net/sctp/sm_sideeffect.c
+@@ -458,6 +458,10 @@ void sctp_generate_reconf_event(struct timer_list *t)
+ goto out_unlock;
+ }
+
++ /* This happens when the response arrives after the timer is triggered. */
++ if (!asoc->strreset_chunk)
++ goto out_unlock;
++
+ error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
+ SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_RECONF),
+ asoc->state, asoc->ep, asoc,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
-index 6b937bfd47515..6b3c32264cbc8 100644
+index 6b937bfd47515..5f6e6a6e91b3d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5317,32 +5317,41 @@ int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *),
@@ -155032,6 +239682,15 @@ index 6b937bfd47515..6b3c32264cbc8 100644
/* 7.2.1 Association Status (SCTP_STATUS)
+@@ -5626,7 +5641,7 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
+ */
+- sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
++ sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sock->sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
+
+ /* Populate the fields of the newsk from the oldsk and migrate the
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index a3d3ca6dd63dd..133f1719bf1b7 100644
--- a/net/sctp/transport.c
@@ -155083,7 +239742,7 @@ index a3d3ca6dd63dd..133f1719bf1b7 100644
bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
-index 78b663dbfa1f9..5c4c0320e822a 100644
+index 78b663dbfa1f9..fb801c249d923 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -148,14 +148,18 @@ static int __smc_release(struct smc_sock *smc)
@@ -155329,7 +239988,16 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
}
/* check if there is a rdma device available for this connection. */
-@@ -1362,11 +1515,12 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
+@@ -1070,6 +1223,8 @@ static void smc_connect_work(struct work_struct *work)
+ smc->sk.sk_state = SMC_CLOSED;
+ if (rc == -EPIPE || rc == -EAGAIN)
+ smc->sk.sk_err = EPIPE;
++ else if (rc == -ECONNREFUSED)
++ smc->sk.sk_err = ECONNREFUSED;
+ else if (signal_pending(current))
+ smc->sk.sk_err = -sock_intr_errno(timeo);
+ sock_put(&smc->sk); /* passive closing */
+@@ -1362,11 +1517,12 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
{
/* RDMA setup failed, switch back to TCP */
smc_conn_abort(new_smc, local_first);
@@ -155344,7 +240012,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) {
if (smc_clc_send_decline(new_smc, reason_code, version) < 0) {
smc_listen_out_err(new_smc);
-@@ -1739,8 +1893,11 @@ static void smc_listen_work(struct work_struct *work)
+@@ -1739,8 +1895,11 @@ static void smc_listen_work(struct work_struct *work)
/* check if peer is smc capable */
if (!tcp_sk(newclcsock->sk)->syn_smc) {
@@ -155358,7 +240026,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
return;
}
-@@ -1866,10 +2023,9 @@ out:
+@@ -1866,10 +2025,9 @@ out:
static void smc_clcsock_data_ready(struct sock *listen_clcsock)
{
@@ -155371,7 +240039,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
if (!lsmc)
return;
lsmc->clcsk_data_ready(listen_clcsock);
-@@ -1914,8 +2070,10 @@ static int smc_listen(struct socket *sock, int backlog)
+@@ -1914,8 +2072,10 @@ static int smc_listen(struct socket *sock, int backlog)
smc->clcsock->sk->sk_user_data =
(void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY);
rc = kernel_listen(smc->clcsock, backlog);
@@ -155383,7 +240051,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0;
sk->sk_state = SMC_LISTEN;
-@@ -2024,7 +2182,9 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+@@ -2024,7 +2184,9 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (msg->msg_flags & MSG_FASTOPEN) {
if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
@@ -155394,7 +240062,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
} else {
rc = -EINVAL;
goto out;
-@@ -2148,8 +2308,10 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
+@@ -2148,8 +2310,10 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
static int smc_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
@@ -155405,7 +240073,16 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
int rc1 = 0;
smc = smc_sk(sk);
-@@ -2176,7 +2338,11 @@ static int smc_shutdown(struct socket *sock, int how)
+@@ -2170,13 +2334,19 @@ static int smc_shutdown(struct socket *sock, int how)
+ if (smc->use_fallback) {
+ rc = kernel_sock_shutdown(smc->clcsock, how);
+ sk->sk_shutdown = smc->clcsock->sk->sk_shutdown;
+- if (sk->sk_shutdown == SHUTDOWN_MASK)
++ if (sk->sk_shutdown == SHUTDOWN_MASK) {
+ sk->sk_state = SMC_CLOSED;
++ sock_put(sk);
++ }
+ goto out;
}
switch (how) {
case SHUT_RDWR: /* shutdown in both directions */
@@ -155417,7 +240094,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
break;
case SHUT_WR:
rc = smc_close_shutdown_write(smc);
-@@ -2186,7 +2352,7 @@ static int smc_shutdown(struct socket *sock, int how)
+@@ -2186,7 +2356,7 @@ static int smc_shutdown(struct socket *sock, int how)
/* nothing more to do because peer is not involved */
break;
}
@@ -155426,7 +240103,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
rc1 = kernel_sock_shutdown(smc->clcsock, how);
/* map sock_shutdown_cmd constants to sk_shutdown value range */
sk->sk_shutdown |= how + 1;
-@@ -2211,6 +2377,11 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
+@@ -2211,6 +2381,11 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
/* generic setsockopts reaching us here always apply to the
* CLC socket
*/
@@ -155438,7 +240115,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
if (unlikely(!smc->clcsock->ops->setsockopt))
rc = -EOPNOTSUPP;
else
-@@ -2220,6 +2391,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
+@@ -2220,6 +2395,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
sk->sk_err = smc->clcsock->sk->sk_err;
sk_error_report(sk);
}
@@ -155446,7 +240123,7 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
if (optlen < sizeof(int))
return -EINVAL;
-@@ -2236,7 +2408,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
+@@ -2236,7 +2412,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
case TCP_FASTOPEN_NO_COOKIE:
/* option not supported by SMC */
if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
@@ -155455,7 +240132,29 @@ index 78b663dbfa1f9..5c4c0320e822a 100644
} else {
rc = -EINVAL;
}
-@@ -2279,13 +2451,23 @@ static int smc_getsockopt(struct socket *sock, int level, int optname,
+@@ -2247,8 +2423,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
+ sk->sk_state != SMC_CLOSED) {
+ if (val) {
+ SMC_STAT_INC(smc, ndly_cnt);
+- mod_delayed_work(smc->conn.lgr->tx_wq,
+- &smc->conn.tx_work, 0);
++ smc_tx_pending(&smc->conn);
++ cancel_delayed_work(&smc->conn.tx_work);
+ }
+ }
+ break;
+@@ -2258,8 +2434,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
+ sk->sk_state != SMC_CLOSED) {
+ if (!val) {
+ SMC_STAT_INC(smc, cork_cnt);
+- mod_delayed_work(smc->conn.lgr->tx_wq,
+- &smc->conn.tx_work, 0);
++ smc_tx_pending(&smc->conn);
++ cancel_delayed_work(&smc->conn.tx_work);
+ }
+ }
+ break;
+@@ -2279,13 +2455,23 @@ static int smc_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct smc_sock *smc;
@@ -155682,7 +240381,7 @@ index 0f9ffba07d268..84102db5bb314 100644
/* peer event has changed the state */
goto again;
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
-index d2206743dc714..dee336eef6d21 100644
+index d2206743dc714..7401ec67ebcf9 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -170,8 +170,10 @@ static int smc_lgr_register_conn(struct smc_connection *conn, bool first)
@@ -155871,6 +240570,15 @@ index d2206743dc714..dee336eef6d21 100644
INIT_WORK(&smc->conn.abort_work, smc_conn_abort_work);
if (ini->is_smcd) {
conn->rx_off = sizeof(struct smcd_cdc_msg);
+@@ -1818,7 +1822,7 @@ static struct smc_buf_desc *smc_buf_get_slot(int compressed_bufsize,
+ */
+ static inline int smc_rmb_wnd_update_limit(int rmbe_size)
+ {
+- return min_t(int, rmbe_size / 10, SOCK_MIN_SNDBUF / 2);
++ return max_t(int, rmbe_size / 10, SOCK_MIN_SNDBUF / 2);
+ }
+
+ /* map an rmb buf to a link */
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index c043ecdca5c44..9a0523f4c7ba6 100644
--- a/net/smc/smc_core.h
@@ -155942,7 +240650,7 @@ index f1d323439a2af..ee1f0fdba0855 100644
if (!smc_llc_send_message_wait(&lgr->lnk[i], &delllc))
break;
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
-index 4a964e9190b02..707615809e5a9 100644
+index 4a964e9190b02..79ee0618d919b 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -112,7 +112,7 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name)
@@ -155999,7 +240707,19 @@ index 4a964e9190b02..707615809e5a9 100644
return rc;
}
-@@ -371,7 +371,7 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
+@@ -310,8 +310,9 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
+ list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
+ if (!strncmp(ibdev->ibdev->name, ib_name,
+ sizeof(ibdev->ibdev->name)) ||
+- !strncmp(dev_name(ibdev->ibdev->dev.parent), ib_name,
+- IB_DEVICE_NAME_MAX - 1)) {
++ (ibdev->ibdev->dev.parent &&
++ !strncmp(dev_name(ibdev->ibdev->dev.parent), ib_name,
++ IB_DEVICE_NAME_MAX - 1))) {
+ goto out;
+ }
+ }
+@@ -371,7 +372,7 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
rc = -EEXIST;
new_netdev = true;
@@ -156008,7 +240728,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) {
if (tmp_pe->type == SMC_PNET_ETH &&
!strncmp(tmp_pe->eth_name, eth_name, IFNAMSIZ)) {
-@@ -381,9 +381,9 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
+@@ -381,9 +382,9 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
}
if (new_netdev) {
list_add_tail(&new_pe->list, &pnettable->pnetlist);
@@ -156020,7 +240740,7 @@ index 4a964e9190b02..707615809e5a9 100644
kfree(new_pe);
goto out_put;
}
-@@ -444,7 +444,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
+@@ -444,7 +445,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
new_pe->ib_port = ib_port;
new_ibdev = true;
@@ -156029,7 +240749,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) {
if (tmp_pe->type == SMC_PNET_IB &&
!strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) {
-@@ -454,9 +454,9 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
+@@ -454,9 +455,9 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
}
if (new_ibdev) {
list_add_tail(&new_pe->list, &pnettable->pnetlist);
@@ -156041,7 +240761,7 @@ index 4a964e9190b02..707615809e5a9 100644
kfree(new_pe);
}
return (new_ibdev) ? 0 : -EEXIST;
-@@ -601,7 +601,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid,
+@@ -601,7 +602,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid,
pnettable = &sn->pnettable;
/* dump pnettable entries */
@@ -156050,7 +240770,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(pnetelem, &pnettable->pnetlist, list) {
if (pnetid && !smc_pnet_match(pnetelem->pnet_name, pnetid))
continue;
-@@ -616,7 +616,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid,
+@@ -616,7 +617,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid,
break;
}
}
@@ -156059,7 +240779,7 @@ index 4a964e9190b02..707615809e5a9 100644
return idx;
}
-@@ -860,7 +860,7 @@ int smc_pnet_net_init(struct net *net)
+@@ -860,7 +861,7 @@ int smc_pnet_net_init(struct net *net)
struct smc_pnetids_ndev *pnetids_ndev = &sn->pnetids_ndev;
INIT_LIST_HEAD(&pnettable->pnetlist);
@@ -156068,7 +240788,7 @@ index 4a964e9190b02..707615809e5a9 100644
INIT_LIST_HEAD(&pnetids_ndev->list);
rwlock_init(&pnetids_ndev->lock);
-@@ -940,7 +940,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev,
+@@ -940,7 +941,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev,
sn = net_generic(net, smc_net_id);
pnettable = &sn->pnettable;
@@ -156077,7 +240797,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(pnetelem, &pnettable->pnetlist, list) {
if (pnetelem->type == SMC_PNET_ETH && ndev == pnetelem->ndev) {
/* get pnetid of netdev device */
-@@ -949,7 +949,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev,
+@@ -949,7 +950,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev,
break;
}
}
@@ -156086,7 +240806,7 @@ index 4a964e9190b02..707615809e5a9 100644
return rc;
}
-@@ -1130,7 +1130,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
+@@ -1130,7 +1131,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
sn = net_generic(&init_net, smc_net_id);
pnettable = &sn->pnettable;
@@ -156095,7 +240815,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) {
if (tmp_pe->type == SMC_PNET_IB &&
!strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX) &&
-@@ -1140,7 +1140,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
+@@ -1140,7 +1141,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
break;
}
}
@@ -156104,7 +240824,7 @@ index 4a964e9190b02..707615809e5a9 100644
return rc;
}
-@@ -1159,7 +1159,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev)
+@@ -1159,7 +1160,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev)
sn = net_generic(&init_net, smc_net_id);
pnettable = &sn->pnettable;
@@ -156113,7 +240833,7 @@ index 4a964e9190b02..707615809e5a9 100644
list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) {
if (tmp_pe->type == SMC_PNET_IB &&
!strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) {
-@@ -1168,7 +1168,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev)
+@@ -1168,7 +1169,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev)
break;
}
}
@@ -156135,6 +240855,84 @@ index 14039272f7e42..80a88eea49491 100644
struct list_head pnetlist;
};
+diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
+index 170b733bc7367..45b0575520da4 100644
+--- a/net/smc/smc_rx.c
++++ b/net/smc/smc_rx.c
+@@ -354,12 +354,12 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
+ }
+ break;
+ }
++ if (!timeo)
++ return -EAGAIN;
+ if (signal_pending(current)) {
+ read_done = sock_intr_errno(timeo);
+ break;
+ }
+- if (!timeo)
+- return -EAGAIN;
+ }
+
+ if (!smc_rx_data_available(conn)) {
+diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c
+index 738a4a99c8279..31ee76131a79e 100644
+--- a/net/smc/smc_tx.c
++++ b/net/smc/smc_tx.c
+@@ -594,27 +594,32 @@ int smc_tx_sndbuf_nonempty(struct smc_connection *conn)
+ return rc;
+ }
+
+-/* Wakeup sndbuf consumers from process context
+- * since there is more data to transmit
+- */
+-void smc_tx_work(struct work_struct *work)
++void smc_tx_pending(struct smc_connection *conn)
+ {
+- struct smc_connection *conn = container_of(to_delayed_work(work),
+- struct smc_connection,
+- tx_work);
+ struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
+ int rc;
+
+- lock_sock(&smc->sk);
+ if (smc->sk.sk_err)
+- goto out;
++ return;
+
+ rc = smc_tx_sndbuf_nonempty(conn);
+ if (!rc && conn->local_rx_ctrl.prod_flags.write_blocked &&
+ !atomic_read(&conn->bytes_to_rcv))
+ conn->local_rx_ctrl.prod_flags.write_blocked = 0;
++}
++
++/* Wakeup sndbuf consumers from process context
++ * since there is more data to transmit
++ */
++void smc_tx_work(struct work_struct *work)
++{
++ struct smc_connection *conn = container_of(to_delayed_work(work),
++ struct smc_connection,
++ tx_work);
++ struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
+
+-out:
++ lock_sock(&smc->sk);
++ smc_tx_pending(conn);
+ release_sock(&smc->sk);
+ }
+
+diff --git a/net/smc/smc_tx.h b/net/smc/smc_tx.h
+index 07e6ad76224a0..a59f370b8b432 100644
+--- a/net/smc/smc_tx.h
++++ b/net/smc/smc_tx.h
+@@ -27,6 +27,7 @@ static inline int smc_tx_prepared_sends(struct smc_connection *conn)
+ return smc_curs_diff(conn->sndbuf_desc->len, &sent, &prep);
+ }
+
++void smc_tx_pending(struct smc_connection *conn);
+ void smc_tx_work(struct work_struct *work);
+ void smc_tx_init(struct smc_sock *smc);
+ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len);
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index a419e9af36b98..59ca1a2d5c650 100644
--- a/net/smc/smc_wr.c
@@ -156400,11 +241198,128 @@ index 6e4dbd577a39f..d435bffc61999 100644
}
static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
+diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+index 61c276bddaf25..f549e4c05defc 100644
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -98,6 +98,7 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
+ * done without the correct namespace:
+ */
+ .flags = RPC_CLNT_CREATE_NOPING |
++ RPC_CLNT_CREATE_CONNECTED |
+ RPC_CLNT_CREATE_NO_IDLE_TIMEOUT
+ };
+ struct rpc_clnt *clnt;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
-index f056ff9314442..5da1d7e8468a5 100644
+index f056ff9314442..0a0818e55879a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
-@@ -2903,7 +2903,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
+@@ -76,6 +76,7 @@ static int rpc_encode_header(struct rpc_task *task,
+ static int rpc_decode_header(struct rpc_task *task,
+ struct xdr_stream *xdr);
+ static int rpc_ping(struct rpc_clnt *clnt);
++static int rpc_ping_noreply(struct rpc_clnt *clnt);
+ static void rpc_check_timeout(struct rpc_task *task);
+
+ static void rpc_register_client(struct rpc_clnt *clnt)
+@@ -483,6 +484,12 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
+ rpc_shutdown_client(clnt);
+ return ERR_PTR(err);
+ }
++ } else if (args->flags & RPC_CLNT_CREATE_CONNECTED) {
++ int err = rpc_ping_noreply(clnt);
++ if (err != 0) {
++ rpc_shutdown_client(clnt);
++ return ERR_PTR(err);
++ }
+ }
+
+ clnt->cl_softrtry = 1;
+@@ -1065,8 +1072,13 @@ rpc_task_get_next_xprt(struct rpc_clnt *clnt)
+ static
+ void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
+ {
+- if (task->tk_xprt)
+- return;
++ if (task->tk_xprt) {
++ if (!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) &&
++ (task->tk_flags & RPC_TASK_MOVEABLE)))
++ return;
++ xprt_release(task);
++ xprt_put(task->tk_xprt);
++ }
+ if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
+ task->tk_xprt = rpc_task_get_first_xprt(clnt);
+ else
+@@ -2200,6 +2212,7 @@ call_transmit_status(struct rpc_task *task)
+ * socket just returned a connection error,
+ * then hold onto the transport lock.
+ */
++ case -ENOMEM:
+ case -ENOBUFS:
+ rpc_delay(task, HZ>>2);
+ fallthrough;
+@@ -2283,6 +2296,7 @@ call_bc_transmit_status(struct rpc_task *task)
+ case -ENOTCONN:
+ case -EPIPE:
+ break;
++ case -ENOMEM:
+ case -ENOBUFS:
+ rpc_delay(task, HZ>>2);
+ fallthrough;
+@@ -2365,6 +2379,11 @@ call_status(struct rpc_task *task)
+ case -EPIPE:
+ case -EAGAIN:
+ break;
++ case -ENFILE:
++ case -ENOBUFS:
++ case -ENOMEM:
++ rpc_delay(task, HZ>>2);
++ break;
+ case -EIO:
+ /* shutdown or soft timeout */
+ goto out_exit;
+@@ -2692,6 +2711,10 @@ static const struct rpc_procinfo rpcproc_null = {
+ .p_decode = rpcproc_decode_null,
+ };
+
++static const struct rpc_procinfo rpcproc_null_noreply = {
++ .p_encode = rpcproc_encode_null,
++};
++
+ static void
+ rpc_null_call_prepare(struct rpc_task *task, void *data)
+ {
+@@ -2745,6 +2768,28 @@ static int rpc_ping(struct rpc_clnt *clnt)
+ return status;
+ }
+
++static int rpc_ping_noreply(struct rpc_clnt *clnt)
++{
++ struct rpc_message msg = {
++ .rpc_proc = &rpcproc_null_noreply,
++ };
++ struct rpc_task_setup task_setup_data = {
++ .rpc_client = clnt,
++ .rpc_message = &msg,
++ .callback_ops = &rpc_null_ops,
++ .flags = RPC_TASK_SOFT | RPC_TASK_SOFTCONN | RPC_TASK_NULLCREDS,
++ };
++ struct rpc_task *task;
++ int status;
++
++ task = rpc_run_task(&task_setup_data);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ status = task->tk_status;
++ rpc_put_task(task);
++ return status;
++}
++
+ struct rpc_cb_add_xprt_calldata {
+ struct rpc_xprt_switch *xps;
+ struct rpc_xprt *xprt;
+@@ -2903,7 +2948,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
unsigned long connect_timeout;
unsigned long reconnect_timeout;
unsigned char resvport, reuseport;
@@ -156413,7 +241328,7 @@ index f056ff9314442..5da1d7e8468a5 100644
rcu_read_lock();
xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
-@@ -2917,8 +2917,11 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
+@@ -2917,8 +2962,11 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
reuseport = xprt->reuseport;
connect_timeout = xprt->connect_timeout;
reconnect_timeout = xprt->max_reconnect_timeout;
@@ -156451,6 +241366,43 @@ index ee5336d73fddc..35588f0afa864 100644
dput(dentry);
return ret;
}
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index c045f63d11fa6..f0f55fbd13752 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -186,11 +186,6 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue,
+
+ /*
+ * Add new request to wait queue.
+- *
+- * Swapper tasks always get inserted at the head of the queue.
+- * This should avoid many nasty memory deadlocks and hopefully
+- * improve overall performance.
+- * Everyone else gets appended to the queue to ensure proper FIFO behavior.
+ */
+ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
+ struct rpc_task *task,
+@@ -199,8 +194,6 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
+ INIT_LIST_HEAD(&task->u.tk_wait.timer_list);
+ if (RPC_IS_PRIORITY(queue))
+ __rpc_add_wait_queue_priority(queue, task, queue_priority);
+- else if (RPC_IS_SWAPPER(task))
+- list_add(&task->u.tk_wait.list, &queue->tasks[0]);
+ else
+ list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
+ task->tk_waitqueue = queue;
+@@ -1012,8 +1005,10 @@ int rpc_malloc(struct rpc_task *task)
+ struct rpc_buffer *buf;
+ gfp_t gfp = GFP_NOFS;
+
++ if (RPC_IS_ASYNC(task))
++ gfp = GFP_NOWAIT | __GFP_NOWARN;
+ if (RPC_IS_SWAPPER(task))
+- gfp = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
++ gfp |= __GFP_MEMALLOC;
+
+ size += sizeof(struct rpc_buffer);
+ if (size <= RPC_BUFFER_MAXSIZE)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index a3bbe5ce4570f..08ca797bb8a46 100644
--- a/net/sunrpc/svc.c
@@ -156479,7 +241431,7 @@ index a3bbe5ce4570f..08ca797bb8a46 100644
/* Some types of transport can present the write payload
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
-index 6316bd2b8f37b..d4b663401be14 100644
+index 6316bd2b8f37b..935bba065636c 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -243,7 +243,7 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
@@ -156491,6 +241443,38 @@ index 6316bd2b8f37b..d4b663401be14 100644
return xprt;
}
+@@ -1213,6 +1213,8 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
+ dr->daddr = rqstp->rq_daddr;
+ dr->argslen = rqstp->rq_arg.len >> 2;
+ dr->xprt_hlen = rqstp->rq_xprt_hlen;
++ dr->xprt_ctxt = rqstp->rq_xprt_ctxt;
++ rqstp->rq_xprt_ctxt = NULL;
+
+ /* back up head to the start of the buffer and copy */
+ skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
+@@ -1251,6 +1253,7 @@ static noinline int svc_deferred_recv(struct svc_rqst *rqstp)
+ rqstp->rq_xprt_hlen = dr->xprt_hlen;
+ rqstp->rq_daddr = dr->daddr;
+ rqstp->rq_respages = rqstp->rq_pages;
++ rqstp->rq_xprt_ctxt = dr->xprt_ctxt;
+ svc_xprt_received(rqstp->rq_xprt);
+ return (dr->argslen<<2) - dr->xprt_hlen;
+ }
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index 478f857cdaed4..6ea3d87e11475 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -1096,7 +1096,9 @@ static int svc_tcp_sendmsg(struct socket *sock, struct xdr_buf *xdr,
+ int ret;
+
+ *sentp = 0;
+- xdr_alloc_bvec(xdr, GFP_KERNEL);
++ ret = xdr_alloc_bvec(xdr, GFP_KERNEL);
++ if (ret < 0)
++ return ret;
+
+ ret = kernel_sendmsg(sock, &msg, &rm, 1, rm.iov_len);
+ if (ret < 0)
diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c
index 9a6f17e18f73b..326a31422a3c1 100644
--- a/net/sunrpc/sysfs.c
@@ -156554,10 +241538,52 @@ index 9a6f17e18f73b..326a31422a3c1 100644
} else {
count = -EINVAL;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
-index cfd681700d1a1..d4aeee83763e6 100644
+index cfd681700d1a1..2db834318d141 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
-@@ -1603,15 +1603,14 @@ xprt_transmit(struct rpc_task *task)
+@@ -767,7 +767,8 @@ EXPORT_SYMBOL_GPL(xprt_disconnect_done);
+ */
+ static void xprt_schedule_autoclose_locked(struct rpc_xprt *xprt)
+ {
+- set_bit(XPRT_CLOSE_WAIT, &xprt->state);
++ if (test_and_set_bit(XPRT_CLOSE_WAIT, &xprt->state))
++ return;
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ queue_work(xprtiod_workqueue, &xprt->task_cleanup);
+ else if (xprt->snd_task && !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
+@@ -928,12 +929,7 @@ void xprt_connect(struct rpc_task *task)
+ if (!xprt_lock_write(xprt, task))
+ return;
+
+- if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state)) {
+- trace_xprt_disconnect_cleanup(xprt);
+- xprt->ops->close(xprt);
+- }
+-
+- if (!xprt_connected(xprt)) {
++ if (!xprt_connected(xprt) && !test_bit(XPRT_CLOSE_WAIT, &xprt->state)) {
+ task->tk_rqstp->rq_connect_cookie = xprt->connect_cookie;
+ rpc_sleep_on_timeout(&xprt->pending, task, NULL,
+ xprt_request_timeout(task->tk_rqstp));
+@@ -1353,17 +1349,6 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
+ INIT_LIST_HEAD(&req->rq_xmit2);
+ goto out;
+ }
+- } else if (RPC_IS_SWAPPER(task)) {
+- list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
+- if (pos->rq_cong || pos->rq_bytes_sent)
+- continue;
+- if (RPC_IS_SWAPPER(pos->rq_task))
+- continue;
+- /* Note: req is added _before_ pos */
+- list_add_tail(&req->rq_xmit, &pos->rq_xmit);
+- INIT_LIST_HEAD(&req->rq_xmit2);
+- goto out;
+- }
+ } else if (!req->rq_seqno) {
+ list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
+ if (pos->rq_task->tk_owner != task->tk_owner)
+@@ -1603,15 +1588,14 @@ xprt_transmit(struct rpc_task *task)
{
struct rpc_rqst *next, *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
@@ -156578,7 +241604,7 @@ index cfd681700d1a1..d4aeee83763e6 100644
xprt_pin_rqst(next);
spin_unlock(&xprt->queue_lock);
status = xprt_request_transmit(next, task);
-@@ -1619,13 +1618,16 @@ xprt_transmit(struct rpc_task *task)
+@@ -1619,13 +1603,16 @@ xprt_transmit(struct rpc_task *task)
status = 0;
spin_lock(&xprt->queue_lock);
xprt_unpin_rqst(next);
@@ -156602,6 +241628,76 @@ index cfd681700d1a1..d4aeee83763e6 100644
}
spin_unlock(&xprt->queue_lock);
}
+@@ -1684,12 +1671,15 @@ out:
+ static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt)
+ {
+ struct rpc_rqst *req = ERR_PTR(-EAGAIN);
++ gfp_t gfp_mask = GFP_KERNEL;
+
+ if (xprt->num_reqs >= xprt->max_reqs)
+ goto out;
+ ++xprt->num_reqs;
+ spin_unlock(&xprt->reserve_lock);
+- req = kzalloc(sizeof(struct rpc_rqst), GFP_NOFS);
++ if (current->flags & PF_WQ_WORKER)
++ gfp_mask |= __GFP_NORETRY | __GFP_NOWARN;
++ req = kzalloc(sizeof(*req), gfp_mask);
+ spin_lock(&xprt->reserve_lock);
+ if (req != NULL)
+ goto out;
+@@ -2109,7 +2099,14 @@ static void xprt_destroy(struct rpc_xprt *xprt)
+ */
+ wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
+
++ /*
++ * xprt_schedule_autodisconnect() can run after XPRT_LOCKED
++ * is cleared. We use ->transport_lock to ensure the mod_timer()
++ * can only run *before* del_time_sync(), never after.
++ */
++ spin_lock(&xprt->transport_lock);
+ del_timer_sync(&xprt->timer);
++ spin_unlock(&xprt->transport_lock);
+
+ /*
+ * Destroy sockets etc from the system workqueue so they can
+diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+index 6be23ce7a93d2..387a5da09dafb 100644
+--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+@@ -826,7 +826,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
+ goto out_err;
+ if (ret == 0)
+ goto out_drop;
+- rqstp->rq_xprt_hlen = ret;
++ rqstp->rq_xprt_hlen = 0;
+
+ if (svc_rdma_is_reverse_direction_reply(xprt, ctxt))
+ goto out_backchannel;
+diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
+index 16e5696314a4f..32df237967472 100644
+--- a/net/sunrpc/xprtrdma/transport.c
++++ b/net/sunrpc/xprtrdma/transport.c
+@@ -521,7 +521,7 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
+ return;
+
+ out_sleep:
+- task->tk_status = -EAGAIN;
++ task->tk_status = -ENOMEM;
+ xprt_add_backlog(xprt, task);
+ }
+
+@@ -574,8 +574,10 @@ xprt_rdma_allocate(struct rpc_task *task)
+ gfp_t flags;
+
+ flags = RPCRDMA_DEF_GFP;
++ if (RPC_IS_ASYNC(task))
++ flags = GFP_NOWAIT | __GFP_NOWARN;
+ if (RPC_IS_SWAPPER(task))
+- flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
++ flags |= __GFP_MEMALLOC;
+
+ if (!rpcrdma_check_regbuf(r_xprt, req->rl_sendbuf, rqst->rq_callsize,
+ flags))
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index aaec3c9be8db6..1295f9ab839fd 100644
--- a/net/sunrpc/xprtrdma/verbs.c
@@ -156630,6 +241726,233 @@ index aaec3c9be8db6..1295f9ab839fd 100644
goto out_destroy;
}
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 04f1b78bcbca3..897dfce7dd271 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -763,12 +763,12 @@ xs_stream_start_connect(struct sock_xprt *transport)
+ /**
+ * xs_nospace - handle transmit was incomplete
+ * @req: pointer to RPC request
++ * @transport: pointer to struct sock_xprt
+ *
+ */
+-static int xs_nospace(struct rpc_rqst *req)
++static int xs_nospace(struct rpc_rqst *req, struct sock_xprt *transport)
+ {
+- struct rpc_xprt *xprt = req->rq_xprt;
+- struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
++ struct rpc_xprt *xprt = &transport->xprt;
+ struct sock *sk = transport->inet;
+ int ret = -EAGAIN;
+
+@@ -779,25 +779,49 @@ static int xs_nospace(struct rpc_rqst *req)
+
+ /* Don't race with disconnect */
+ if (xprt_connected(xprt)) {
++ struct socket_wq *wq;
++
++ rcu_read_lock();
++ wq = rcu_dereference(sk->sk_wq);
++ set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags);
++ rcu_read_unlock();
++
+ /* wait for more buffer space */
++ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ sk->sk_write_pending++;
+ xprt_wait_for_buffer_space(xprt);
+ } else
+ ret = -ENOTCONN;
+
+ spin_unlock(&xprt->transport_lock);
++ return ret;
++}
+
+- /* Race breaker in case memory is freed before above code is called */
+- if (ret == -EAGAIN) {
+- struct socket_wq *wq;
++static int xs_sock_nospace(struct rpc_rqst *req)
++{
++ struct sock_xprt *transport =
++ container_of(req->rq_xprt, struct sock_xprt, xprt);
++ struct sock *sk = transport->inet;
++ int ret = -EAGAIN;
+
+- rcu_read_lock();
+- wq = rcu_dereference(sk->sk_wq);
+- set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags);
+- rcu_read_unlock();
++ lock_sock(sk);
++ if (!sock_writeable(sk))
++ ret = xs_nospace(req, transport);
++ release_sock(sk);
++ return ret;
++}
+
+- sk->sk_write_space(sk);
+- }
++static int xs_stream_nospace(struct rpc_rqst *req)
++{
++ struct sock_xprt *transport =
++ container_of(req->rq_xprt, struct sock_xprt, xprt);
++ struct sock *sk = transport->inet;
++ int ret = -EAGAIN;
++
++ lock_sock(sk);
++ if (!sk_stream_memory_free(sk))
++ ret = xs_nospace(req, transport);
++ release_sock(sk);
+ return ret;
+ }
+
+@@ -856,7 +880,7 @@ static int xs_local_send_request(struct rpc_rqst *req)
+
+ /* Close the stream if the previous transmission was incomplete */
+ if (xs_send_request_was_aborted(transport, req)) {
+- xs_close(xprt);
++ xprt_force_disconnect(xprt);
+ return -ENOTCONN;
+ }
+
+@@ -887,14 +911,14 @@ static int xs_local_send_request(struct rpc_rqst *req)
+ case -ENOBUFS:
+ break;
+ case -EAGAIN:
+- status = xs_nospace(req);
++ status = xs_stream_nospace(req);
+ break;
+ default:
+ dprintk("RPC: sendmsg returned unrecognized error %d\n",
+ -status);
+ fallthrough;
+ case -EPIPE:
+- xs_close(xprt);
++ xprt_force_disconnect(xprt);
+ status = -ENOTCONN;
+ }
+
+@@ -963,7 +987,7 @@ process_status:
+ /* Should we call xs_close() here? */
+ break;
+ case -EAGAIN:
+- status = xs_nospace(req);
++ status = xs_sock_nospace(req);
+ break;
+ case -ENETUNREACH:
+ case -ENOBUFS:
+@@ -1083,7 +1107,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
+ /* Should we call xs_close() here? */
+ break;
+ case -EAGAIN:
+- status = xs_nospace(req);
++ status = xs_stream_nospace(req);
+ break;
+ case -ECONNRESET:
+ case -ECONNREFUSED:
+@@ -1181,6 +1205,16 @@ static void xs_reset_transport(struct sock_xprt *transport)
+
+ if (sk == NULL)
+ return;
++ /*
++ * Make sure we're calling this in a context from which it is safe
++ * to call __fput_sync(). In practice that means rpciod and the
++ * system workqueue.
++ */
++ if (!(current->flags & PF_WQ_WORKER)) {
++ WARN_ON_ONCE(1);
++ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
++ return;
++ }
+
+ if (atomic_read(&transport->xprt.swapper))
+ sk_clear_memalloc(sk);
+@@ -1204,7 +1238,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
+ mutex_unlock(&transport->recv_mutex);
+
+ trace_rpc_socket_close(xprt, sock);
+- fput(filp);
++ __fput_sync(filp);
+
+ xprt_disconnect_done(xprt);
+ }
+@@ -2233,6 +2267,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ fallthrough;
+ case -EINPROGRESS:
+ /* SYN_SENT! */
++ set_bit(XPRT_SOCK_CONNECT_SENT, &transport->sock_state);
+ if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
+ xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+ break;
+@@ -2258,10 +2293,14 @@ static void xs_tcp_setup_socket(struct work_struct *work)
+ struct rpc_xprt *xprt = &transport->xprt;
+ int status = -EIO;
+
+- if (!sock) {
+- sock = xs_create_sock(xprt, transport,
+- xs_addr(xprt)->sa_family, SOCK_STREAM,
+- IPPROTO_TCP, true);
++ if (xprt_connected(xprt))
++ goto out;
++ if (test_and_clear_bit(XPRT_SOCK_CONNECT_SENT,
++ &transport->sock_state) ||
++ !sock) {
++ xs_reset_transport(transport);
++ sock = xs_create_sock(xprt, transport, xs_addr(xprt)->sa_family,
++ SOCK_STREAM, IPPROTO_TCP, true);
+ if (IS_ERR(sock)) {
+ status = PTR_ERR(sock);
+ goto out;
+@@ -2343,11 +2382,7 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
+
+ if (transport->sock != NULL) {
+ dprintk("RPC: xs_connect delayed xprt %p for %lu "
+- "seconds\n",
+- xprt, xprt->reestablish_timeout / HZ);
+-
+- /* Start by resetting any existing state */
+- xs_reset_transport(transport);
++ "seconds\n", xprt, xprt->reestablish_timeout / HZ);
+
+ delay = xprt_reconnect_delay(xprt);
+ xprt_reconnect_backoff(xprt, XS_TCP_INIT_REEST_TO);
+@@ -2823,9 +2858,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
+ }
+ xprt_set_bound(xprt);
+ xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
+- ret = ERR_PTR(xs_local_setup_socket(transport));
+- if (ret)
+- goto out_err;
+ break;
+ default:
+ ret = ERR_PTR(-EAFNOSUPPORT);
+diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
+index 443f8e5b94777..36b466cfd9e11 100644
+--- a/net/tipc/bearer.c
++++ b/net/tipc/bearer.c
+@@ -352,16 +352,18 @@ static int tipc_enable_bearer(struct net *net, const char *name,
+ goto rejected;
+ }
+
+- test_and_set_bit_lock(0, &b->up);
+- rcu_assign_pointer(tn->bearer_list[bearer_id], b);
+- if (skb)
+- tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr);
+-
++ /* Create monitoring data before accepting activate messages */
+ if (tipc_mon_create(net, bearer_id)) {
+ bearer_disable(net, b);
++ kfree_skb(skb);
+ return -ENOMEM;
+ }
+
++ test_and_set_bit_lock(0, &b->up);
++ rcu_assign_pointer(tn->bearer_list[bearer_id], b);
++ if (skb)
++ tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr);
++
+ pr_info("Enabled bearer <%s>, priority %u\n", name, prio);
+
+ return res;
diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c
index dc60c32bb70df..b5074957e8812 100644
--- a/net/tipc/crypto.c
@@ -156655,7 +241978,7 @@ index dc60c32bb70df..b5074957e8812 100644
unsigned int keylen;
diff --git a/net/tipc/link.c b/net/tipc/link.c
-index 1b7a487c88419..4e7936d9b4424 100644
+index 1b7a487c88419..115a4a7950f50 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1298,8 +1298,11 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
@@ -156692,13 +242015,25 @@ index 1b7a487c88419..4e7936d9b4424 100644
if (tipc_link_is_blocked(l) || !xmitq)
goto exit;
-@@ -2305,7 +2312,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
+@@ -2278,6 +2285,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
+ break;
- /* Receive Gap ACK blocks from peer if any */
- glen = tipc_get_gap_ack_blks(&ga, l, hdr, true);
--
-+ if(glen > dlen)
+ case STATE_MSG:
++ /* Validate Gap ACK blocks, drop if invalid */
++ glen = tipc_get_gap_ack_blks(&ga, l, hdr, true);
++ if (glen > dlen)
+ break;
++
+ l->rcv_nxt_state = msg_seqno(hdr) + 1;
+
+ /* Update own tolerance if peer indicates a non-zero value */
+@@ -2303,9 +2315,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
+ break;
+ }
+
+- /* Receive Gap ACK blocks from peer if any */
+- glen = tipc_get_gap_ack_blks(&ga, l, hdr, true);
+-
tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr,
&l->mon_state, l->bearer_id);
@@ -156787,7 +242122,7 @@ index 9947b7dfe1d2d..6ef95ce565bd3 100644
}
}
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
-index ad570c2450be8..7545321c3440b 100644
+index ad570c2450be8..17f8c523e33b0 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1461,6 +1461,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
@@ -156799,7 +242134,17 @@ index ad570c2450be8..7545321c3440b 100644
/* Determine destination */
if (atype == TIPC_SERVICE_RANGE) {
return tipc_sendmcast(sock, ua, m, dlen, timeout);
-@@ -3747,7 +3749,7 @@ static int __tipc_nl_list_sk_publ(struct sk_buff *skb,
+@@ -2850,7 +2852,8 @@ static void tipc_sk_retry_connect(struct sock *sk, struct sk_buff_head *list)
+
+ /* Try again later if dest link is congested */
+ if (tsk->cong_link_cnt) {
+- sk_reset_timer(sk, &sk->sk_timer, msecs_to_jiffies(100));
++ sk_reset_timer(sk, &sk->sk_timer,
++ jiffies + msecs_to_jiffies(100));
+ return;
+ }
+ /* Prepare SYN for retransmit */
+@@ -3747,7 +3750,7 @@ static int __tipc_nl_list_sk_publ(struct sk_buff *skb,
if (p->key == *last_publ)
break;
}
@@ -156808,6 +242153,40 @@ index ad570c2450be8..7545321c3440b 100644
/* We never set seq or call nl_dump_check_consistent()
* this means that setting prev_seq here will cause the
* consistence check to fail in the netlink callback
+diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
+index b932469ee69cc..f3e3d009cf1cf 100644
+--- a/net/tls/tls_device.c
++++ b/net/tls/tls_device.c
+@@ -483,11 +483,13 @@ handle_error:
+ copy = min_t(size_t, size, (pfrag->size - pfrag->offset));
+ copy = min_t(size_t, copy, (max_open_record_len - record->len));
+
+- rc = tls_device_copy_data(page_address(pfrag->page) +
+- pfrag->offset, copy, msg_iter);
+- if (rc)
+- goto handle_error;
+- tls_append_frag(record, pfrag, copy);
++ if (copy) {
++ rc = tls_device_copy_data(page_address(pfrag->page) +
++ pfrag->offset, copy, msg_iter);
++ if (rc)
++ goto handle_error;
++ tls_append_frag(record, pfrag, copy);
++ }
+
+ size -= copy;
+ if (!size) {
+@@ -1345,7 +1347,10 @@ static int tls_device_down(struct net_device *netdev)
+
+ /* Device contexts for RX and TX will be freed in on sk_destruct
+ * by tls_device_free_ctx. rx_conf and tx_conf stay in TLS_HW.
++ * Now release the ref taken above.
+ */
++ if (refcount_dec_and_test(&ctx->refcount))
++ tls_device_free_ctx(ctx);
+ }
+
+ up_write(&device_offload_lock);
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 9ab81db8a6545..9aac9c60d786d 100644
--- a/net/tls/tls_main.c
@@ -156909,7 +242288,7 @@ index 9ab81db8a6545..9aac9c60d786d 100644
tcp_register_ulp(&tcp_tls_ulp_ops);
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
-index 1b08b877a8900..bd96ec26f4f99 100644
+index 1b08b877a8900..794ef3b3d7d4b 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -515,7 +515,7 @@ static int tls_do_encryption(struct sock *sk,
@@ -156921,7 +242300,12 @@ index 1b08b877a8900..bd96ec26f4f99 100644
sge->offset += prot->prepend_size;
sge->length -= prot->prepend_size;
-@@ -1487,7 +1487,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
+@@ -1483,11 +1483,11 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
+ if (prot->version == TLS_1_3_VERSION ||
+ prot->cipher_type == TLS_CIPHER_CHACHA20_POLY1305)
+ memcpy(iv + iv_offset, tls_ctx->rx.iv,
+- crypto_aead_ivsize(ctx->aead_recv));
++ prot->iv_size + prot->salt_size);
else
memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size);
@@ -156999,10 +242383,40 @@ index 1b08b877a8900..bd96ec26f4f99 100644
splice_read_end:
release_sock(sk);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 78e08e82c08c4..b0bfc78e421ce 100644
+index 78e08e82c08c4..62f47821d783f 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
-@@ -2882,9 +2882,6 @@ static int unix_shutdown(struct socket *sock, int mode)
+@@ -1996,7 +1996,7 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
+ if (ousk->oob_skb)
+ consume_skb(ousk->oob_skb);
+
+- ousk->oob_skb = skb;
++ WRITE_ONCE(ousk->oob_skb, skb);
+
+ scm_stat_add(other, skb);
+ skb_queue_tail(&other->sk_receive_queue, skb);
+@@ -2514,9 +2514,8 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
+
+ oob_skb = u->oob_skb;
+
+- if (!(state->flags & MSG_PEEK)) {
+- u->oob_skb = NULL;
+- }
++ if (!(state->flags & MSG_PEEK))
++ WRITE_ONCE(u->oob_skb, NULL);
+
+ unix_state_unlock(sk);
+
+@@ -2551,7 +2550,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
+ skb = NULL;
+ } else if (sock_flag(sk, SOCK_URGINLINE)) {
+ if (!(flags & MSG_PEEK)) {
+- u->oob_skb = NULL;
++ WRITE_ONCE(u->oob_skb, NULL);
+ consume_skb(skb);
+ }
+ } else if (!(flags & MSG_PEEK)) {
+@@ -2882,9 +2881,6 @@ static int unix_shutdown(struct socket *sock, int mode)
unix_state_lock(sk);
sk->sk_shutdown |= mode;
@@ -157012,6 +242426,30 @@ index 78e08e82c08c4..b0bfc78e421ce 100644
other = unix_peer(sk);
if (other)
sock_hold(other);
+@@ -3009,11 +3005,10 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ case SIOCATMARK:
+ {
+ struct sk_buff *skb;
+- struct unix_sock *u = unix_sk(sk);
+ int answ = 0;
+
+ skb = skb_peek(&sk->sk_receive_queue);
+- if (skb && skb == u->oob_skb)
++ if (skb && skb == READ_ONCE(unix_sk(sk)->oob_skb))
+ answ = 1;
+ err = put_user(answ, (int __user *)arg);
+ }
+@@ -3054,6 +3049,10 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
+ mask |= EPOLLIN | EPOLLRDNORM;
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
++#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
++ if (READ_ONCE(unix_sk(sk)->oob_skb))
++ mask |= EPOLLPRI;
++#endif
+
+ /* Connection-based need to check for termination and startup */
+ if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 12e2ddaf887f2..d45d5366115a7 100644
--- a/net/unix/garbage.c
@@ -157077,10 +242515,34 @@ index 052ae709ce289..aa27a02478dc1 100644
user->unix_inflight--;
spin_unlock(&unix_gc_lock);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
-index e2c0cfb334d20..91a5c65707ba1 100644
+index e2c0cfb334d20..5df530e89e5ac 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
-@@ -1322,6 +1322,8 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
+@@ -333,7 +333,8 @@ void vsock_remove_sock(struct vsock_sock *vsk)
+ }
+ EXPORT_SYMBOL_GPL(vsock_remove_sock);
+
+-void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
++void vsock_for_each_connected_socket(struct vsock_transport *transport,
++ void (*fn)(struct sock *sk))
+ {
+ int i;
+
+@@ -342,8 +343,12 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
+ for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) {
+ struct vsock_sock *vsk;
+ list_for_each_entry(vsk, &vsock_connected_table[i],
+- connected_table)
++ connected_table) {
++ if (vsk->transport != transport)
++ continue;
++
+ fn(sk_vsock(vsk));
++ }
+ }
+
+ spin_unlock_bh(&vsock_table_lock);
+@@ -1322,6 +1327,8 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
* non-blocking call.
*/
err = -EALREADY;
@@ -157089,7 +242551,7 @@ index e2c0cfb334d20..91a5c65707ba1 100644
break;
default:
if ((sk->sk_state == TCP_LISTEN) ||
-@@ -1398,6 +1400,7 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
+@@ -1398,6 +1405,7 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
sk->sk_state = sk->sk_state == TCP_ESTABLISHED ? TCP_CLOSING : TCP_CLOSE;
sock->state = SS_UNCONNECTED;
vsock_transport_cancel_pkt(vsk);
@@ -157097,6 +242559,63 @@ index e2c0cfb334d20..91a5c65707ba1 100644
goto out_wait;
} else if (timeout == 0) {
err = -ETIMEDOUT;
+diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
+index 4f7c99dfd16cf..c5f936fbf876d 100644
+--- a/net/vmw_vsock/virtio_transport.c
++++ b/net/vmw_vsock/virtio_transport.c
+@@ -24,6 +24,7 @@
+ static struct workqueue_struct *virtio_vsock_workqueue;
+ static struct virtio_vsock __rcu *the_virtio_vsock;
+ static DEFINE_MUTEX(the_virtio_vsock_mutex); /* protects the_virtio_vsock */
++static struct virtio_transport virtio_transport; /* forward declaration */
+
+ struct virtio_vsock {
+ struct virtio_device *vdev;
+@@ -384,7 +385,8 @@ static void virtio_vsock_event_handle(struct virtio_vsock *vsock,
+ switch (le32_to_cpu(event->id)) {
+ case VIRTIO_VSOCK_EVENT_TRANSPORT_RESET:
+ virtio_vsock_update_guest_cid(vsock);
+- vsock_for_each_connected_socket(virtio_vsock_reset_sock);
++ vsock_for_each_connected_socket(&virtio_transport.transport,
++ virtio_vsock_reset_sock);
+ break;
+ }
+ }
+@@ -620,6 +622,13 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
+ INIT_WORK(&vsock->event_work, virtio_transport_event_work);
+ INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work);
+
++ if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET))
++ vsock->seqpacket_allow = true;
++
++ vdev->priv = vsock;
++
++ virtio_device_ready(vdev);
++
+ mutex_lock(&vsock->tx_lock);
+ vsock->tx_run = true;
+ mutex_unlock(&vsock->tx_lock);
+@@ -634,10 +643,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
+ vsock->event_run = true;
+ mutex_unlock(&vsock->event_lock);
+
+- if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET))
+- vsock->seqpacket_allow = true;
+-
+- vdev->priv = vsock;
+ rcu_assign_pointer(the_virtio_vsock, vsock);
+
+ mutex_unlock(&the_virtio_vsock_mutex);
+@@ -662,7 +667,8 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
+ synchronize_rcu();
+
+ /* Reset all connected sockets when the device disappear */
+- vsock_for_each_connected_socket(virtio_vsock_reset_sock);
++ vsock_for_each_connected_socket(&virtio_transport.transport,
++ virtio_vsock_reset_sock);
+
+ /* Stop all work handlers to make sure no one is accessing the device,
+ * so we can safely call vdev->config->reset().
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 59ee1be5a6dd3..ec2c2afbf0d06 100644
--- a/net/vmw_vsock/virtio_transport_common.c
@@ -157111,6 +242630,29 @@ index 59ee1be5a6dd3..ec2c2afbf0d06 100644
if (space_available)
sk->sk_write_space(sk);
+diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
+index 7aef34e32bdf8..b17dc9745188e 100644
+--- a/net/vmw_vsock/vmci_transport.c
++++ b/net/vmw_vsock/vmci_transport.c
+@@ -75,6 +75,8 @@ static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
+
+ static int PROTOCOL_OVERRIDE = -1;
+
++static struct vsock_transport vmci_transport; /* forward declaration */
++
+ /* Helper function to convert from a VMCI error code to a VSock error code. */
+
+ static s32 vmci_transport_error_to_vsock_error(s32 vmci_error)
+@@ -882,7 +884,8 @@ static void vmci_transport_qp_resumed_cb(u32 sub_id,
+ const struct vmci_event_data *e_data,
+ void *client_data)
+ {
+- vsock_for_each_connected_socket(vmci_transport_handle_detach);
++ vsock_for_each_connected_socket(&vmci_transport,
++ vmci_transport_handle_detach);
+ }
+
+ static void vmci_transport_recv_pkt_work(struct work_struct *work)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index aaba847d79eb2..441136646f89a 100644
--- a/net/wireless/core.c
@@ -157175,10 +242717,20 @@ index aaba847d79eb2..441136646f89a 100644
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index bf7cd47525472..99564db14aa12 100644
+index bf7cd47525472..7c65ad17bf50a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -922,33 +922,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
+@@ -509,7 +509,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+ .len = IEEE80211_MAX_MESH_ID_LEN },
+ [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
+
+- [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
++ /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
++ [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
+ [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
+
+ [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
+@@ -922,33 +923,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
[NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
};
@@ -157226,7 +242778,23 @@ index bf7cd47525472..99564db14aa12 100644
if (IS_ERR(*wdev)) {
rtnl_unlock();
return PTR_ERR(*wdev);
-@@ -6001,7 +6005,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
+@@ -3075,6 +3080,15 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
+ } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
+ chandef->width =
+ nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
++ if (chandef->chan->band == NL80211_BAND_S1GHZ) {
++ /* User input error for channel width doesn't match channel */
++ if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
++ NL_SET_ERR_MSG_ATTR(extack,
++ attrs[NL80211_ATTR_CHANNEL_WIDTH],
++ "bad channel width");
++ return -EINVAL;
++ }
++ }
+ if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
+ chandef->center_freq1 =
+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
+@@ -6001,7 +6015,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
int sta_idx = cb->args[2];
int err;
@@ -157235,7 +242803,7 @@ index bf7cd47525472..99564db14aa12 100644
if (err)
return err;
/* nl80211_prepare_wdev_dump acquired it in the successful case */
-@@ -6896,7 +6900,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
+@@ -6896,7 +6910,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
int path_idx = cb->args[2];
int err;
@@ -157244,7 +242812,7 @@ index bf7cd47525472..99564db14aa12 100644
if (err)
return err;
/* nl80211_prepare_wdev_dump acquired it in the successful case */
-@@ -7096,7 +7100,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
+@@ -7096,7 +7110,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
int path_idx = cb->args[2];
int err;
@@ -157253,7 +242821,7 @@ index bf7cd47525472..99564db14aa12 100644
if (err)
return err;
/* nl80211_prepare_wdev_dump acquired it in the successful case */
-@@ -9518,7 +9522,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -9518,7 +9532,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
int start = cb->args[2], idx = 0;
int err;
@@ -157262,7 +242830,7 @@ index bf7cd47525472..99564db14aa12 100644
if (err)
return err;
/* nl80211_prepare_wdev_dump acquired it in the successful case */
-@@ -9651,7 +9655,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -9651,7 +9665,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
if (!attrbuf)
return -ENOMEM;
@@ -157271,7 +242839,33 @@ index bf7cd47525472..99564db14aa12 100644
if (res) {
kfree(attrbuf);
return res;
-@@ -13173,6 +13177,9 @@ static int handle_nan_filter(struct nlattr *attr_filter,
+@@ -11327,18 +11341,23 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
+ struct cfg80211_bitrate_mask mask;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
++ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ if (!rdev->ops->set_bitrate_mask)
+ return -EOPNOTSUPP;
+
++ wdev_lock(wdev);
+ err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
+ NL80211_ATTR_TX_RATES, &mask,
+ dev, true);
+ if (err)
+- return err;
++ goto out;
+
+- return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
++ err = rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
++out:
++ wdev_unlock(wdev);
++ return err;
+ }
+
+ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
+@@ -13173,6 +13192,9 @@ static int handle_nan_filter(struct nlattr *attr_filter,
i = 0;
nla_for_each_nested(attr, attr_filter, rem) {
filter[i].filter = nla_memdup(attr, GFP_KERNEL);
@@ -157281,7 +242875,7 @@ index bf7cd47525472..99564db14aa12 100644
filter[i].len = nla_len(attr);
i++;
}
-@@ -13185,6 +13192,15 @@ static int handle_nan_filter(struct nlattr *attr_filter,
+@@ -13185,6 +13207,15 @@ static int handle_nan_filter(struct nlattr *attr_filter,
}
return 0;
@@ -157297,6 +242891,16 @@ index bf7cd47525472..99564db14aa12 100644
}
static int nl80211_nan_add_func(struct sk_buff *skb,
+@@ -17509,7 +17540,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
+ wdev->chandef = *chandef;
+ wdev->preset_chandef = *chandef;
+
+- if (wdev->iftype == NL80211_IFTYPE_STATION &&
++ if ((wdev->iftype == NL80211_IFTYPE_STATION ||
++ wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
+ !WARN_ON(!wdev->current_bss))
+ cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
+
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index a3f387770f1bf..d642e3be4ee78 100644
--- a/net/wireless/nl80211.h
@@ -157346,6 +242950,48 @@ index df87c7f3a0492..795e86b371bba 100644
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
return cfg80211_chandef_usable(wiphy, &chandef,
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index adc0d14cfd860..1a8b76c9dd567 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -702,8 +702,12 @@ static bool cfg80211_find_ssid_match(struct cfg80211_colocated_ap *ap,
+
+ for (i = 0; i < request->n_ssids; i++) {
+ /* wildcard ssid in the scan request */
+- if (!request->ssids[i].ssid_len)
++ if (!request->ssids[i].ssid_len) {
++ if (ap->multi_bss && !ap->transmitted_bssid)
++ continue;
++
+ return true;
++ }
+
+ if (ap->ssid_len &&
+ ap->ssid_len == request->ssids[i].ssid_len) {
+@@ -829,6 +833,9 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
+ !cfg80211_find_ssid_match(ap, request))
+ continue;
+
++ if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid)
++ continue;
++
+ cfg80211_scan_req_add_chan(request, chan, true);
+ memcpy(scan_6ghz_params->bssid, ap->bssid, ETH_ALEN);
+ scan_6ghz_params->short_ssid = ap->short_ssid;
+@@ -1971,11 +1978,13 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
+ /* this is a nontransmitting bss, we need to add it to
+ * transmitting bss' list if it is not there
+ */
++ spin_lock_bh(&rdev->bss_lock);
+ if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
+ &res->pub)) {
+ if (__cfg80211_unlink_bss(rdev, res))
+ rdev->bss_generation++;
+ }
++ spin_unlock_bh(&rdev->bss_lock);
+ }
+
+ trace_cfg80211_return_bss(&res->pub);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index a1a99a5749844..4ddc269164f86 100644
--- a/net/wireless/util.c
@@ -157358,6 +243004,191 @@ index a1a99a5749844..4ddc269164f86 100644
cfg80211_stop_ap(rdev, dev, true);
break;
case NL80211_IFTYPE_ADHOC:
+diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
+index 3583354a7d7fe..3a171828638b1 100644
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -1765,10 +1765,15 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
+
+ write_lock_bh(&x25_list_lock);
+
+- sk_for_each(s, &x25_list)
+- if (x25_sk(s)->neighbour == nb)
++ sk_for_each(s, &x25_list) {
++ if (x25_sk(s)->neighbour == nb) {
++ write_unlock_bh(&x25_list_lock);
++ lock_sock(s);
+ x25_disconnect(s, ENETUNREACH, 0, 0);
+-
++ release_sock(s);
++ write_lock_bh(&x25_list_lock);
++ }
++ }
+ write_unlock_bh(&x25_list_lock);
+
+ /* Remove any related forwards */
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index d6b500dc42084..444ad0bc09083 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -418,18 +418,8 @@ EXPORT_SYMBOL(xsk_tx_peek_release_desc_batch);
+ static int xsk_wakeup(struct xdp_sock *xs, u8 flags)
+ {
+ struct net_device *dev = xs->dev;
+- int err;
+-
+- rcu_read_lock();
+- err = dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, flags);
+- rcu_read_unlock();
+-
+- return err;
+-}
+
+-static int xsk_zc_xmit(struct xdp_sock *xs)
+-{
+- return xsk_wakeup(xs, XDP_WAKEUP_TX);
++ return dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, flags);
+ }
+
+ static void xsk_destruct_skb(struct sk_buff *skb)
+@@ -548,6 +538,12 @@ static int xsk_generic_xmit(struct sock *sk)
+
+ mutex_lock(&xs->mutex);
+
++ /* Since we dropped the RCU read lock, the socket state might have changed. */
++ if (unlikely(!xsk_is_bound(xs))) {
++ err = -ENXIO;
++ goto out;
++ }
++
+ if (xs->queue_id >= xs->dev->real_num_tx_queues)
+ goto out;
+
+@@ -611,16 +607,26 @@ out:
+ return err;
+ }
+
+-static int __xsk_sendmsg(struct sock *sk)
++static int xsk_xmit(struct sock *sk)
+ {
+ struct xdp_sock *xs = xdp_sk(sk);
++ int ret;
+
+ if (unlikely(!(xs->dev->flags & IFF_UP)))
+ return -ENETDOWN;
+ if (unlikely(!xs->tx))
+ return -ENOBUFS;
+
+- return xs->zc ? xsk_zc_xmit(xs) : xsk_generic_xmit(sk);
++ if (xs->zc)
++ return xsk_wakeup(xs, XDP_WAKEUP_TX);
++
++ /* Drop the RCU lock since the SKB path might sleep. */
++ rcu_read_unlock();
++ ret = xsk_generic_xmit(sk);
++ /* Reaquire RCU lock before going into common code. */
++ rcu_read_lock();
++
++ return ret;
+ }
+
+ static bool xsk_no_wakeup(struct sock *sk)
+@@ -634,7 +640,7 @@ static bool xsk_no_wakeup(struct sock *sk)
+ #endif
+ }
+
+-static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
++static int __xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
+ {
+ bool need_wait = !(m->msg_flags & MSG_DONTWAIT);
+ struct sock *sk = sock->sk;
+@@ -649,16 +655,27 @@ static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
+ if (sk_can_busy_loop(sk))
+ sk_busy_loop(sk, 1); /* only support non-blocking sockets */
+
+- if (xsk_no_wakeup(sk))
++ if (xs->zc && xsk_no_wakeup(sk))
+ return 0;
+
+ pool = xs->pool;
+ if (pool->cached_need_wakeup & XDP_WAKEUP_TX)
+- return __xsk_sendmsg(sk);
++ return xsk_xmit(sk);
+ return 0;
+ }
+
+-static int xsk_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags)
++static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
++{
++ int ret;
++
++ rcu_read_lock();
++ ret = __xsk_sendmsg(sock, m, total_len);
++ rcu_read_unlock();
++
++ return ret;
++}
++
++static int __xsk_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags)
+ {
+ bool need_wait = !(flags & MSG_DONTWAIT);
+ struct sock *sk = sock->sk;
+@@ -684,6 +701,17 @@ static int xsk_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int fl
+ return 0;
+ }
+
++static int xsk_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags)
++{
++ int ret;
++
++ rcu_read_lock();
++ ret = __xsk_recvmsg(sock, m, len, flags);
++ rcu_read_unlock();
++
++ return ret;
++}
++
+ static __poll_t xsk_poll(struct file *file, struct socket *sock,
+ struct poll_table_struct *wait)
+ {
+@@ -694,8 +722,11 @@ static __poll_t xsk_poll(struct file *file, struct socket *sock,
+
+ sock_poll_wait(file, sock, wait);
+
+- if (unlikely(!xsk_is_bound(xs)))
++ rcu_read_lock();
++ if (unlikely(!xsk_is_bound(xs))) {
++ rcu_read_unlock();
+ return mask;
++ }
+
+ pool = xs->pool;
+
+@@ -704,7 +735,7 @@ static __poll_t xsk_poll(struct file *file, struct socket *sock,
+ xsk_wakeup(xs, pool->cached_need_wakeup);
+ else
+ /* Poll needs to drive Tx also in copy mode */
+- __xsk_sendmsg(sk);
++ xsk_xmit(sk);
+ }
+
+ if (xs->rx && !xskq_prod_is_empty(xs->rx))
+@@ -712,6 +743,7 @@ static __poll_t xsk_poll(struct file *file, struct socket *sock,
+ if (xs->tx && xsk_tx_writeable(xs))
+ mask |= EPOLLOUT | EPOLLWRNORM;
+
++ rcu_read_unlock();
+ return mask;
+ }
+
+@@ -743,7 +775,6 @@ static void xsk_unbind_dev(struct xdp_sock *xs)
+
+ /* Wait for driver to stop using the xdp socket. */
+ xp_del_xsk(xs->pool, xs);
+- xs->dev = NULL;
+ synchronize_net();
+ dev_put(dev);
+ }
diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c
index 2bf2693901631..a0f62fa02e06e 100644
--- a/net/xfrm/xfrm_compat.c
@@ -157416,10 +243247,22 @@ index e843b0d9e2a61..c255aac6b816b 100644
err = dev->xfrmdev_ops->xdo_dev_state_add(x);
if (err) {
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
-index 41de46b5ffa94..4e3c62d1ad9e9 100644
+index 41de46b5ffa94..1e8b26eecb3f8 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
-@@ -637,11 +637,16 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
+@@ -304,7 +304,10 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
+ if (mtu < IPV6_MIN_MTU)
+ mtu = IPV6_MIN_MTU;
+
+- icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
++ if (skb->len > 1280)
++ icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
++ else
++ goto xmit;
+ } else {
+ if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
+ goto xmit;
+@@ -637,11 +640,16 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct net *net = dev_net(dev);
@@ -157437,7 +243280,7 @@ index 41de46b5ffa94..4e3c62d1ad9e9 100644
xi = xfrmi_locate(net, &p);
if (xi)
return -EEXIST;
-@@ -666,9 +671,14 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
+@@ -666,9 +674,14 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
{
struct xfrm_if *xi = netdev_priv(dev);
struct net *net = xi->net;
@@ -157510,7 +243353,7 @@ index 229544bc70c21..4dc4a7bbe51cf 100644
if (skb_is_gso(skb)) {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
-index 37d17a79617c9..37b149f632624 100644
+index 37d17a79617c9..a6271b955e11d 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -31,8 +31,10 @@
@@ -157524,6 +243367,15 @@ index 37d17a79617c9..37b149f632624 100644
#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/mip6.h>
#endif
+@@ -3158,7 +3160,7 @@ ok:
+
+ nopol:
+ if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
+- !xfrm_default_allow(net, dir)) {
++ net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
+ err = -EPERM;
+ goto error;
+ }
@@ -3296,7 +3298,7 @@ decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse)
fl4->flowi4_proto = iph->protocol;
fl4->daddr = reverse ? iph->saddr : iph->daddr;
@@ -157560,11 +243412,105 @@ index 37d17a79617c9..37b149f632624 100644
#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_MH:
offset += ipv6_optlen(exthdr);
+@@ -3550,7 +3572,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
+ }
+
+ if (!pol) {
+- if (!xfrm_default_allow(net, dir)) {
++ if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
+ return 0;
+ }
+@@ -3610,7 +3632,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
+ }
+ xfrm_nr = ti;
+
+- if (!xfrm_default_allow(net, dir) && !xfrm_nr) {
++ if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK &&
++ !xfrm_nr) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
+ goto reject;
+ }
+@@ -4099,6 +4122,9 @@ static int __net_init xfrm_net_init(struct net *net)
+ spin_lock_init(&net->xfrm.xfrm_policy_lock);
+ seqcount_spinlock_init(&net->xfrm.xfrm_policy_hash_generation, &net->xfrm.xfrm_policy_lock);
+ mutex_init(&net->xfrm.xfrm_cfg_mutex);
++ net->xfrm.policy_default[XFRM_POLICY_IN] = XFRM_USERPOLICY_ACCEPT;
++ net->xfrm.policy_default[XFRM_POLICY_FWD] = XFRM_USERPOLICY_ACCEPT;
++ net->xfrm.policy_default[XFRM_POLICY_OUT] = XFRM_USERPOLICY_ACCEPT;
+
+ rv = xfrm_statistics_init(net);
+ if (rv < 0)
+@@ -4237,7 +4263,7 @@ static bool xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp,
+ }
+
+ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *sel,
+- u8 dir, u8 type, struct net *net)
++ u8 dir, u8 type, struct net *net, u32 if_id)
+ {
+ struct xfrm_policy *pol, *ret = NULL;
+ struct hlist_head *chain;
+@@ -4246,7 +4272,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
+ spin_lock_bh(&net->xfrm.xfrm_policy_lock);
+ chain = policy_hash_direct(net, &sel->daddr, &sel->saddr, sel->family, dir);
+ hlist_for_each_entry(pol, chain, bydst) {
+- if (xfrm_migrate_selector_match(sel, &pol->selector) &&
++ if ((if_id == 0 || pol->if_id == if_id) &&
++ xfrm_migrate_selector_match(sel, &pol->selector) &&
+ pol->type == type) {
+ ret = pol;
+ priority = ret->priority;
+@@ -4258,7 +4285,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
+ if ((pol->priority >= priority) && ret)
+ break;
+
+- if (xfrm_migrate_selector_match(sel, &pol->selector) &&
++ if ((if_id == 0 || pol->if_id == if_id) &&
++ xfrm_migrate_selector_match(sel, &pol->selector) &&
+ pol->type == type) {
+ ret = pol;
+ break;
+@@ -4374,7 +4402,7 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
+ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ struct xfrm_migrate *m, int num_migrate,
+ struct xfrm_kmaddress *k, struct net *net,
+- struct xfrm_encap_tmpl *encap)
++ struct xfrm_encap_tmpl *encap, u32 if_id)
+ {
+ int i, err, nx_cur = 0, nx_new = 0;
+ struct xfrm_policy *pol = NULL;
+@@ -4393,14 +4421,14 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ }
+
+ /* Stage 1 - find policy */
+- if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
++ if ((pol = xfrm_migrate_policy_find(sel, dir, type, net, if_id)) == NULL) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ /* Stage 2 - find and update state(s) */
+ for (i = 0, mp = m; i < num_migrate; i++, mp++) {
+- if ((x = xfrm_migrate_state_find(mp, net))) {
++ if ((x = xfrm_migrate_state_find(mp, net, if_id))) {
+ x_cur[nx_cur] = x;
+ nx_cur++;
+ xc = xfrm_state_migrate(x, mp, encap);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
-index a2f4001221d16..100b4b3723e72 100644
+index a2f4001221d16..f7bfa19169688 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
-@@ -1593,6 +1593,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+@@ -1578,9 +1578,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+ memcpy(&x->mark, &orig->mark, sizeof(x->mark));
+ memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
+
+- if (xfrm_init_state(x) < 0)
+- goto error;
+-
+ x->props.flags = orig->props.flags;
+ x->props.extra_flags = orig->props.extra_flags;
+
+@@ -1593,6 +1590,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
x->km.seq = orig->km.seq;
x->replay = orig->replay;
x->preplay = orig->preplay;
@@ -157574,7 +243520,47 @@ index a2f4001221d16..100b4b3723e72 100644
return x;
-@@ -2242,7 +2245,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
+@@ -1602,7 +1602,8 @@ out:
+ return NULL;
+ }
+
+-struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
++struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
++ u32 if_id)
+ {
+ unsigned int h;
+ struct xfrm_state *x = NULL;
+@@ -1618,6 +1619,8 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
+ continue;
+ if (m->reqid && x->props.reqid != m->reqid)
+ continue;
++ if (if_id != 0 && x->if_id != if_id)
++ continue;
+ if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
+ m->old_family) ||
+ !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
+@@ -1633,6 +1636,8 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
+ if (x->props.mode != m->mode ||
+ x->id.proto != m->proto)
+ continue;
++ if (if_id != 0 && x->if_id != if_id)
++ continue;
+ if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
+ m->old_family) ||
+ !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
+@@ -1659,6 +1664,11 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
+ if (!xc)
+ return NULL;
+
++ xc->props.family = m->new_family;
++
++ if (xfrm_init_state(xc) < 0)
++ goto error;
++
+ memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
+ memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
+
+@@ -2242,7 +2252,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
}
EXPORT_SYMBOL(km_query);
@@ -157583,7 +243569,7 @@ index a2f4001221d16..100b4b3723e72 100644
{
int err = -EINVAL;
struct xfrm_mgr *km;
-@@ -2257,6 +2260,24 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
+@@ -2257,6 +2267,24 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
rcu_read_unlock();
return err;
}
@@ -157608,7 +243594,7 @@ index a2f4001221d16..100b4b3723e72 100644
EXPORT_SYMBOL(km_new_mapping);
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
-@@ -2550,7 +2571,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
+@@ -2550,7 +2578,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_delete_tunnel);
@@ -157617,7 +243603,7 @@ index a2f4001221d16..100b4b3723e72 100644
{
const struct xfrm_type *type = READ_ONCE(x->type);
struct crypto_aead *aead;
-@@ -2581,17 +2602,7 @@ u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu)
+@@ -2581,17 +2609,7 @@ u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu)
return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
net_adj) & ~(blksize - 1)) + net_adj - 2;
}
@@ -157637,7 +243623,7 @@ index a2f4001221d16..100b4b3723e72 100644
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
{
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
-index 3a3cb09eec122..b10f88822c0df 100644
+index 3a3cb09eec122..5fba82757ce5e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -282,6 +282,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
@@ -157669,22 +243655,7 @@ index 3a3cb09eec122..b10f88822c0df 100644
}
static void xfrm_smark_init(struct nlattr **attrs, struct xfrm_mark *m)
-@@ -621,8 +629,13 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
-
- xfrm_smark_init(attrs, &x->props.smark);
-
-- if (attrs[XFRMA_IF_ID])
-+ if (attrs[XFRMA_IF_ID]) {
- x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
-+ if (!x->if_id) {
-+ err = -EINVAL;
-+ goto error;
-+ }
-+ }
-
- err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
- if (err)
-@@ -1024,8 +1037,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
+@@ -1024,8 +1032,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
if (ret)
goto out;
}
@@ -157699,37 +243670,99 @@ index 3a3cb09eec122..b10f88822c0df 100644
out:
return ret;
}
-@@ -1413,8 +1431,13 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
+@@ -1980,12 +1993,9 @@ static int xfrm_notify_userpolicy(struct net *net)
+ }
- mark = xfrm_mark_get(attrs, &m);
+ up = nlmsg_data(nlh);
+- up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+- up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+- up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
++ up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
++ up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
++ up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
-- if (attrs[XFRMA_IF_ID])
-+ if (attrs[XFRMA_IF_ID]) {
- if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
-+ if (!if_id) {
-+ err = -EINVAL;
-+ goto out_noput;
-+ }
-+ }
+ nlmsg_end(skb, nlh);
+
+@@ -1996,26 +2006,26 @@ static int xfrm_notify_userpolicy(struct net *net)
+ return err;
+ }
- if (p->info.seq) {
- x = xfrm_find_acq_byseq(net, mark, p->info.seq);
-@@ -1727,8 +1750,13 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us
++static bool xfrm_userpolicy_is_valid(__u8 policy)
++{
++ return policy == XFRM_USERPOLICY_BLOCK ||
++ policy == XFRM_USERPOLICY_ACCEPT;
++}
++
+ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct nlattr **attrs)
+ {
+ struct net *net = sock_net(skb->sk);
+ struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
+
+- if (up->in == XFRM_USERPOLICY_BLOCK)
+- net->xfrm.policy_default |= XFRM_POL_DEFAULT_IN;
+- else if (up->in == XFRM_USERPOLICY_ACCEPT)
+- net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_IN;
++ if (xfrm_userpolicy_is_valid(up->in))
++ net->xfrm.policy_default[XFRM_POLICY_IN] = up->in;
+
+- if (up->fwd == XFRM_USERPOLICY_BLOCK)
+- net->xfrm.policy_default |= XFRM_POL_DEFAULT_FWD;
+- else if (up->fwd == XFRM_USERPOLICY_ACCEPT)
+- net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_FWD;
++ if (xfrm_userpolicy_is_valid(up->fwd))
++ net->xfrm.policy_default[XFRM_POLICY_FWD] = up->fwd;
+
+- if (up->out == XFRM_USERPOLICY_BLOCK)
+- net->xfrm.policy_default |= XFRM_POL_DEFAULT_OUT;
+- else if (up->out == XFRM_USERPOLICY_ACCEPT)
+- net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_OUT;
++ if (xfrm_userpolicy_is_valid(up->out))
++ net->xfrm.policy_default[XFRM_POLICY_OUT] = up->out;
+
+ rt_genid_bump_all(net);
+
+@@ -2045,13 +2055,9 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
+ }
+
+ r_up = nlmsg_data(r_nlh);
+-
+- r_up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+- r_up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+- r_up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
+- XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
++ r_up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
++ r_up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
++ r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
+ nlmsg_end(r_skb, r_nlh);
+
+ return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);
+@@ -2579,6 +2585,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
+ int n = 0;
+ struct net *net = sock_net(skb->sk);
+ struct xfrm_encap_tmpl *encap = NULL;
++ u32 if_id = 0;
- xfrm_mark_get(attrs, &xp->mark);
+ if (attrs[XFRMA_MIGRATE] == NULL)
+ return -EINVAL;
+@@ -2603,7 +2610,10 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
+ return -ENOMEM;
+ }
-- if (attrs[XFRMA_IF_ID])
-+ if (attrs[XFRMA_IF_ID]) {
- xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
-+ if (!xp->if_id) {
-+ err = -EINVAL;
-+ goto error;
-+ }
-+ }
+- err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);
++ if (attrs[XFRMA_IF_ID])
++ if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
++
++ err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap, if_id);
- return xp;
- error:
-@@ -3058,7 +3086,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
+ kfree(encap);
+
+@@ -3058,7 +3068,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
if (x->props.extra_flags)
l += nla_total_size(sizeof(x->props.extra_flags));
if (x->xso.dev)
@@ -157738,7 +243771,7 @@ index 3a3cb09eec122..b10f88822c0df 100644
if (x->props.smark.v | x->props.smark.m) {
l += nla_total_size(sizeof(x->props.smark.v));
l += nla_total_size(sizeof(x->props.smark.m));
-@@ -3069,6 +3097,9 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
+@@ -3069,6 +3079,9 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
/* Must count x->lastused as it may become non-zero behind our back. */
l += nla_total_size_64bit(sizeof(u64));
@@ -158078,8 +244111,30 @@ index d97465ff8c62c..5f44b877ecf5f 100644
__attribute__((unused))
static inline char *safe_strncpy(char *dst, const char *src, size_t size)
{
+diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
+index 49d7a6ad7e397..1fb79b3ecdd51 100644
+--- a/samples/bpf/xdpsock_user.c
++++ b/samples/bpf/xdpsock_user.c
+@@ -1673,14 +1673,15 @@ int main(int argc, char **argv)
+
+ setlocale(LC_ALL, "");
+
++ prev_time = get_nsecs();
++ start_time = prev_time;
++
+ if (!opt_quiet) {
+ ret = pthread_create(&pt, NULL, poller, NULL);
+ if (ret)
+ exit_with_error(ret);
+ }
+
+- prev_time = get_nsecs();
+- start_time = prev_time;
+
+ if (opt_bench == BENCH_RXDROP)
+ rx_drop_all();
diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c
-index 5b9a09957c6e0..89e6bf27cd9f6 100644
+index 5b9a09957c6e0..d620f3da086f7 100644
--- a/samples/ftrace/ftrace-direct-modify.c
+++ b/samples/ftrace/ftrace-direct-modify.c
@@ -3,6 +3,9 @@
@@ -158092,8 +244147,26 @@ index 5b9a09957c6e0..89e6bf27cd9f6 100644
void my_direct_func1(void)
{
trace_printk("my direct func1\n");
+@@ -28,7 +31,7 @@ asm (
+ " call my_direct_func1\n"
+ " leave\n"
+ " .size my_tramp1, .-my_tramp1\n"
+-" ret\n"
++ ASM_RET
+ " .type my_tramp2, @function\n"
+ " .globl my_tramp2\n"
+ " my_tramp2:"
+@@ -36,7 +39,7 @@ asm (
+ " movq %rsp, %rbp\n"
+ " call my_direct_func2\n"
+ " leave\n"
+-" ret\n"
++ ASM_RET
+ " .size my_tramp2, .-my_tramp2\n"
+ " .popsection\n"
+ );
diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c
-index 3f0079c9bd6fa..11b99325f3dbf 100644
+index 3f0079c9bd6fa..3927cb880d1ab 100644
--- a/samples/ftrace/ftrace-direct-too.c
+++ b/samples/ftrace/ftrace-direct-too.c
@@ -4,6 +4,9 @@
@@ -158106,8 +244179,17 @@ index 3f0079c9bd6fa..11b99325f3dbf 100644
void my_direct_func(struct vm_area_struct *vma,
unsigned long address, unsigned int flags)
{
+@@ -28,7 +31,7 @@ asm (
+ " popq %rsi\n"
+ " popq %rdi\n"
+ " leave\n"
+-" ret\n"
++ ASM_RET
+ " .size my_tramp, .-my_tramp\n"
+ " .popsection\n"
+ );
diff --git a/samples/ftrace/ftrace-direct.c b/samples/ftrace/ftrace-direct.c
-index a2729d1ef17f5..642c50b5f7166 100644
+index a2729d1ef17f5..1e901bb8d7293 100644
--- a/samples/ftrace/ftrace-direct.c
+++ b/samples/ftrace/ftrace-direct.c
@@ -4,6 +4,8 @@
@@ -158119,6 +244201,15 @@ index a2729d1ef17f5..642c50b5f7166 100644
void my_direct_func(struct task_struct *p)
{
trace_printk("waking up %s-%d\n", p->comm, p->pid);
+@@ -22,7 +24,7 @@ asm (
+ " call my_direct_func\n"
+ " popq %rdi\n"
+ " leave\n"
+-" ret\n"
++ ASM_RET
+ " .size my_tramp, .-my_tramp\n"
+ " .popsection\n"
+ );
diff --git a/samples/kprobes/kretprobe_example.c b/samples/kprobes/kretprobe_example.c
index 5dc1bf3baa98b..228321ecb1616 100644
--- a/samples/kprobes/kretprobe_example.c
@@ -158132,6 +244223,40 @@ index 5dc1bf3baa98b..228321ecb1616 100644
}
pr_info("Planted return probe at %s: %p\n",
my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
+diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c
+index 7a15910d21718..8859fc1935428 100644
+--- a/samples/landlock/sandboxer.c
++++ b/samples/landlock/sandboxer.c
+@@ -134,6 +134,7 @@ static int populate_ruleset(
+ ret = 0;
+
+ out_free_name:
++ free(path_list);
+ free(env_path_name);
+ return ret;
+ }
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 3efc984d4c690..2b988b6ccacb6 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -224,6 +224,17 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),
+ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
+
+ ifdef CONFIG_STACK_VALIDATION
++
++objtool_args = \
++ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
++ $(if $(part-of-module), --module) \
++ $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
++ $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
++ $(if $(CONFIG_RETPOLINE), --retpoline) \
++ $(if $(CONFIG_X86_SMAP), --uaccess) \
++ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \
++ $(if $(CONFIG_SLS), --sls)
++
+ ifndef CONFIG_LTO_CLANG
+
+ __objtool_obj := $(objtree)/tools/objtool/objtool
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index d538255038747..8be892887d716 100644
--- a/scripts/Makefile.extrawarn
@@ -158144,6 +244269,91 @@ index d538255038747..8be892887d716 100644
endif
endif
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index 54582673fc1a0..0a8a4689c3ebb 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -232,17 +232,6 @@ ifeq ($(CONFIG_LTO_CLANG),y)
+ mod-prelink-ext := .lto
+ endif
+
+-# Objtool arguments are also needed for modfinal with LTO, so we define
+-# then here to avoid duplication.
+-objtool_args = \
+- $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
+- $(if $(part-of-module), --module) \
+- $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
+- $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
+- $(if $(CONFIG_RETPOLINE), --retpoline) \
+- $(if $(CONFIG_X86_SMAP), --uaccess) \
+- $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
+-
+ # Useful for describing the dependency of composite objects
+ # Usage:
+ # $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
+diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
+index 9e2092fd5206c..7099c603ff0ad 100644
+--- a/scripts/Makefile.ubsan
++++ b/scripts/Makefile.ubsan
+@@ -8,7 +8,6 @@ ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds
+ ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
+ ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero
+ ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
+-ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size
+ ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
+ ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
+ ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
+diff --git a/scripts/atomic/fallbacks/read_acquire b/scripts/atomic/fallbacks/read_acquire
+index 803ba75610766..a0ea1d26e6b2e 100755
+--- a/scripts/atomic/fallbacks/read_acquire
++++ b/scripts/atomic/fallbacks/read_acquire
+@@ -2,6 +2,15 @@ cat <<EOF
+ static __always_inline ${ret}
+ arch_${atomic}_read_acquire(const ${atomic}_t *v)
+ {
+- return smp_load_acquire(&(v)->counter);
++ ${int} ret;
++
++ if (__native_word(${atomic}_t)) {
++ ret = smp_load_acquire(&(v)->counter);
++ } else {
++ ret = arch_${atomic}_read(v);
++ __atomic_acquire_fence();
++ }
++
++ return ret;
+ }
+ EOF
+diff --git a/scripts/atomic/fallbacks/set_release b/scripts/atomic/fallbacks/set_release
+index 86ede759f24ea..05cdb7f42477a 100755
+--- a/scripts/atomic/fallbacks/set_release
++++ b/scripts/atomic/fallbacks/set_release
+@@ -2,6 +2,11 @@ cat <<EOF
+ static __always_inline void
+ arch_${atomic}_set_release(${atomic}_t *v, ${int} i)
+ {
+- smp_store_release(&(v)->counter, i);
++ if (__native_word(${atomic}_t)) {
++ smp_store_release(&(v)->counter, i);
++ } else {
++ __atomic_release_fence();
++ arch_${atomic}_set(v, i);
++ }
+ }
+ EOF
+diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
+index 95aaf7431bffa..1cba78e1dce68 100644
+--- a/scripts/dtc/Makefile
++++ b/scripts/dtc/Makefile
+@@ -29,7 +29,7 @@ dtc-objs += yamltree.o
+ # To include <yaml.h> installed in a non-default path
+ HOSTCFLAGS_yamltree.o := $(shell pkg-config --cflags yaml-0.1)
+ # To link libyaml installed in a non-default path
+-HOSTLDLIBS_dtc := $(shell pkg-config yaml-0.1 --libs)
++HOSTLDLIBS_dtc := $(shell pkg-config --libs yaml-0.1)
+ endif
+
+ # Generated files need one more search path to include headers in source tree
diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff
index d3422ee15e300..f2bbde4bba86b 100755
--- a/scripts/dtc/dtx_diff
@@ -158163,6 +244373,125 @@ index d3422ee15e300..f2bbde4bba86b 100755
`basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
`basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
+diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c
+index 589454bce9301..8425da41de0da 100644
+--- a/scripts/gcc-plugins/latent_entropy_plugin.c
++++ b/scripts/gcc-plugins/latent_entropy_plugin.c
+@@ -86,25 +86,31 @@ static struct plugin_info latent_entropy_plugin_info = {
+ .help = "disable\tturn off latent entropy instrumentation\n",
+ };
+
+-static unsigned HOST_WIDE_INT seed;
+-/*
+- * get_random_seed() (this is a GCC function) generates the seed.
+- * This is a simple random generator without any cryptographic security because
+- * the entropy doesn't come from here.
+- */
++static unsigned HOST_WIDE_INT deterministic_seed;
++static unsigned HOST_WIDE_INT rnd_buf[32];
++static size_t rnd_idx = ARRAY_SIZE(rnd_buf);
++static int urandom_fd = -1;
++
+ static unsigned HOST_WIDE_INT get_random_const(void)
+ {
+- unsigned int i;
+- unsigned HOST_WIDE_INT ret = 0;
+-
+- for (i = 0; i < 8 * sizeof(ret); i++) {
+- ret = (ret << 1) | (seed & 1);
+- seed >>= 1;
+- if (ret & 1)
+- seed ^= 0xD800000000000000ULL;
++ if (deterministic_seed) {
++ unsigned HOST_WIDE_INT w = deterministic_seed;
++ w ^= w << 13;
++ w ^= w >> 7;
++ w ^= w << 17;
++ deterministic_seed = w;
++ return deterministic_seed;
+ }
+
+- return ret;
++ if (urandom_fd < 0) {
++ urandom_fd = open("/dev/urandom", O_RDONLY);
++ gcc_assert(urandom_fd >= 0);
++ }
++ if (rnd_idx >= ARRAY_SIZE(rnd_buf)) {
++ gcc_assert(read(urandom_fd, rnd_buf, sizeof(rnd_buf)) == sizeof(rnd_buf));
++ rnd_idx = 0;
++ }
++ return rnd_buf[rnd_idx++];
+ }
+
+ static tree tree_get_random_const(tree type)
+@@ -537,8 +543,6 @@ static void latent_entropy_start_unit(void *gcc_data __unused,
+ tree type, id;
+ int quals;
+
+- seed = get_random_seed(false);
+-
+ if (in_lto_p)
+ return;
+
+@@ -573,6 +577,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
+ const struct plugin_argument * const argv = plugin_info->argv;
+ int i;
+
++ /*
++ * Call get_random_seed() with noinit=true, so that this returns
++ * 0 in the case where no seed has been passed via -frandom-seed.
++ */
++ deterministic_seed = get_random_seed(true);
++
+ static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = {
+ {
+ .base = &latent_entropy_decl,
+diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
+index e9db7dcb3e5f4..b04aa8e91a41f 100644
+--- a/scripts/gcc-plugins/stackleak_plugin.c
++++ b/scripts/gcc-plugins/stackleak_plugin.c
+@@ -429,6 +429,23 @@ static unsigned int stackleak_cleanup_execute(void)
+ return 0;
+ }
+
++/*
++ * STRING_CST may or may not be NUL terminated:
++ * https://gcc.gnu.org/onlinedocs/gccint/Constant-expressions.html
++ */
++static inline bool string_equal(tree node, const char *string, int length)
++{
++ if (TREE_STRING_LENGTH(node) < length)
++ return false;
++ if (TREE_STRING_LENGTH(node) > length + 1)
++ return false;
++ if (TREE_STRING_LENGTH(node) == length + 1 &&
++ TREE_STRING_POINTER(node)[length] != '\0')
++ return false;
++ return !memcmp(TREE_STRING_POINTER(node), string, length);
++}
++#define STRING_EQUAL(node, str) string_equal(node, str, strlen(str))
++
+ static bool stackleak_gate(void)
+ {
+ tree section;
+@@ -438,13 +455,13 @@ static bool stackleak_gate(void)
+ if (section && TREE_VALUE(section)) {
+ section = TREE_VALUE(TREE_VALUE(section));
+
+- if (!strncmp(TREE_STRING_POINTER(section), ".init.text", 10))
++ if (STRING_EQUAL(section, ".init.text"))
+ return false;
+- if (!strncmp(TREE_STRING_POINTER(section), ".devinit.text", 13))
++ if (STRING_EQUAL(section, ".devinit.text"))
+ return false;
+- if (!strncmp(TREE_STRING_POINTER(section), ".cpuinit.text", 13))
++ if (STRING_EQUAL(section, ".cpuinit.text"))
+ return false;
+- if (!strncmp(TREE_STRING_POINTER(section), ".meminit.text", 13))
++ if (STRING_EQUAL(section, ".meminit.text"))
+ return false;
+ }
+
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index cf72680cd7692..4a828bca071e8 100644
--- a/scripts/kconfig/confdata.c
@@ -158219,6 +244548,33 @@ index b2d8b8aa2d99e..8f636a23bc3f2 100755
}
}
close $fh;
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index d74cee5c4326a..59a3df87907ef 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -139,6 +139,9 @@ objtool_link()
+ if [ -n "${CONFIG_X86_SMAP}" ]; then
+ objtoolopt="${objtoolopt} --uaccess"
+ fi
++ if [ -n "${CONFIG_SLS}" ]; then
++ objtoolopt="${objtoolopt} --sls"
++ fi
+ info OBJTOOL ${1}
+ tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
+ fi
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index cb8ab7d91d307..ca491aa2b3762 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -669,7 +669,7 @@ static void handle_modversion(const struct module *mod,
+ unsigned int crc;
+
+ if (sym->st_shndx == SHN_UNDEF) {
+- warn("EXPORT symbol \"%s\" [%s%s] version ...\n"
++ warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n"
+ "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n",
+ symname, mod->name, mod->is_vmlinux ? "" : ".ko",
+ symname);
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 7d631aaa0ae11..3ccb2c70add4d 100755
--- a/scripts/recordmcount.pl
@@ -158327,7 +244683,7 @@ index 23240d793b074..895f4b9ce8c6b 100644
pr_debug("%s() = %d\n", __func__, ret);
return ret;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
-index 1c8435dfabeea..08f907382c618 100644
+index 1c8435dfabeea..7d87772f0ce68 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -78,7 +78,7 @@ static struct xattr_list evm_config_default_xattrnames[] = {
@@ -158339,6 +244695,15 @@ index 1c8435dfabeea..08f907382c618 100644
static int __init evm_set_fixmode(char *str)
{
if (strncmp(str, "fix", 3) == 0)
+@@ -86,7 +86,7 @@ static int __init evm_set_fixmode(char *str)
+ else
+ pr_err("invalid \"%s\" mode", str);
+
+- return 0;
++ return 1;
+ }
+ __setup("evm=", evm_set_fixmode);
+
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 3d8e9d5db5aa5..3ad8f7734208b 100644
--- a/security/integrity/ima/ima_fs.c
@@ -158541,11 +244906,102 @@ index 29220056207f4..0ec5e4c22cb2a 100644
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
task_pid_nr(current),
from_kuid(&init_user_ns, current_uid()),
+diff --git a/security/keys/keyctl_pkey.c b/security/keys/keyctl_pkey.c
+index 5de0d599a2748..97bc27bbf0797 100644
+--- a/security/keys/keyctl_pkey.c
++++ b/security/keys/keyctl_pkey.c
+@@ -135,15 +135,23 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par
+
+ switch (op) {
+ case KEYCTL_PKEY_ENCRYPT:
++ if (uparams.in_len > info.max_dec_size ||
++ uparams.out_len > info.max_enc_size)
++ return -EINVAL;
++ break;
+ case KEYCTL_PKEY_DECRYPT:
+ if (uparams.in_len > info.max_enc_size ||
+ uparams.out_len > info.max_dec_size)
+ return -EINVAL;
+ break;
+ case KEYCTL_PKEY_SIGN:
++ if (uparams.in_len > info.max_data_size ||
++ uparams.out_len > info.max_sig_size)
++ return -EINVAL;
++ break;
+ case KEYCTL_PKEY_VERIFY:
+- if (uparams.in_len > info.max_sig_size ||
+- uparams.out_len > info.max_data_size)
++ if (uparams.in_len > info.max_data_size ||
++ uparams.in2_len > info.max_sig_size)
+ return -EINVAL;
+ break;
+ default:
+@@ -151,7 +159,7 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par
+ }
+
+ params->in_len = uparams.in_len;
+- params->out_len = uparams.out_len;
++ params->out_len = uparams.out_len; /* Note: same as in2_len */
+ return 0;
+ }
+
+diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
+index d5c891d8d3534..9b9d3ef79cbe3 100644
+--- a/security/keys/trusted-keys/trusted_core.c
++++ b/security/keys/trusted-keys/trusted_core.c
+@@ -27,10 +27,10 @@ module_param_named(source, trusted_key_source, charp, 0);
+ MODULE_PARM_DESC(source, "Select trusted keys source (tpm or tee)");
+
+ static const struct trusted_key_source trusted_key_sources[] = {
+-#if defined(CONFIG_TCG_TPM)
++#if IS_REACHABLE(CONFIG_TCG_TPM)
+ { "tpm", &trusted_key_tpm_ops },
+ #endif
+-#if defined(CONFIG_TEE)
++#if IS_REACHABLE(CONFIG_TEE)
+ { "tee", &trusted_key_tee_ops },
+ #endif
+ };
+@@ -351,7 +351,7 @@ static int __init init_trusted(void)
+
+ static void __exit cleanup_trusted(void)
+ {
+- static_call(trusted_key_exit)();
++ static_call_cond(trusted_key_exit)();
+ }
+
+ late_initcall(init_trusted);
+diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
+index 32396962f04d6..7e27ce394020d 100644
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -192,7 +192,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
+ return PTR_ERR(ruleset);
+
+ /* Creates anonymous FD referring to the ruleset. */
+- ruleset_fd = anon_inode_getfd("landlock-ruleset", &ruleset_fops,
++ ruleset_fd = anon_inode_getfd("[landlock-ruleset]", &ruleset_fops,
+ ruleset, O_RDWR | O_CLOEXEC);
+ if (ruleset_fd < 0)
+ landlock_put_ruleset(ruleset);
diff --git a/security/security.c b/security/security.c
-index 9ffa9e9c5c554..67264cb08fb31 100644
+index 9ffa9e9c5c554..7b9f9d3fffe52 100644
--- a/security/security.c
+++ b/security/security.c
-@@ -747,25 +747,25 @@ static int lsm_superblock_alloc(struct super_block *sb)
+@@ -59,10 +59,12 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
+ [LOCKDOWN_DEBUGFS] = "debugfs access",
+ [LOCKDOWN_XMON_WR] = "xmon write access",
+ [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
++ [LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
+ [LOCKDOWN_INTEGRITY_MAX] = "integrity",
+ [LOCKDOWN_KCORE] = "/proc/kcore access",
+ [LOCKDOWN_KPROBES] = "use of kprobes",
+ [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
++ [LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM",
+ [LOCKDOWN_PERF] = "unsafe use of perf",
+ [LOCKDOWN_TRACEFS] = "use of tracefs",
+ [LOCKDOWN_XMON_RW] = "xmon read and write access",
+@@ -747,25 +749,25 @@ static int lsm_superblock_alloc(struct super_block *sb)
/* Security operations */
@@ -158578,8 +245034,33 @@ index 9ffa9e9c5c554..67264cb08fb31 100644
{
return call_int_hook(binder_transfer_file, 0, from, to, file);
}
+@@ -884,9 +886,22 @@ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
+ return call_int_hook(fs_context_dup, 0, fc, src_fc);
+ }
+
+-int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)
++int security_fs_context_parse_param(struct fs_context *fc,
++ struct fs_parameter *param)
+ {
+- return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param);
++ struct security_hook_list *hp;
++ int trc;
++ int rc = -ENOPARAM;
++
++ hlist_for_each_entry(hp, &security_hook_heads.fs_context_parse_param,
++ list) {
++ trc = hp->hook.fs_context_parse_param(fc, param);
++ if (trc == 0)
++ rc = 0;
++ else if (trc != -ENOPARAM)
++ return trc;
++ }
++ return rc;
+ }
+
+ int security_sb_alloc(struct super_block *sb)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index e7ebd45ca3457..baa12d1007c7c 100644
+index e7ebd45ca3457..9ce029b2f2267 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -255,29 +255,6 @@ static inline u32 task_sid_obj(const struct task_struct *task)
@@ -158612,61 +245093,36 @@ index e7ebd45ca3457..baa12d1007c7c 100644
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
/*
-@@ -634,10 +611,11 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
- return 0;
- }
+@@ -378,6 +355,10 @@ static void inode_free_security(struct inode *inode)
+
+ struct selinux_mnt_opts {
+ const char *fscontext, *context, *rootcontext, *defcontext;
++ u32 fscontext_sid;
++ u32 context_sid;
++ u32 rootcontext_sid;
++ u32 defcontext_sid;
+ };
--static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
-+static int parse_sid(struct super_block *sb, const char *s, u32 *sid,
-+ gfp_t gfp)
+ static void selinux_free_mnt_opts(void *mnt_opts)
+@@ -515,7 +496,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
+
+ static int sb_check_xattr_support(struct super_block *sb)
{
- int rc = security_context_str_to_sid(&selinux_state, s,
-- sid, GFP_KERNEL);
-+ sid, gfp);
+- struct superblock_security_struct *sbsec = sb->s_security;
++ struct superblock_security_struct *sbsec = selinux_superblock(sb);
+ struct dentry *root = sb->s_root;
+ struct inode *root_inode = d_backing_inode(root);
+ u32 sid;
+@@ -641,7 +622,7 @@ static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
if (rc)
pr_warn("SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n",
-@@ -708,7 +686,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
- */
- if (opts) {
- if (opts->fscontext) {
-- rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
-+ rc = parse_sid(sb, opts->fscontext, &fscontext_sid,
-+ GFP_KERNEL);
- if (rc)
- goto out;
- if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
-@@ -717,7 +696,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
- sbsec->flags |= FSCONTEXT_MNT;
- }
- if (opts->context) {
-- rc = parse_sid(sb, opts->context, &context_sid);
-+ rc = parse_sid(sb, opts->context, &context_sid,
-+ GFP_KERNEL);
- if (rc)
- goto out;
- if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
-@@ -726,7 +706,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
- sbsec->flags |= CONTEXT_MNT;
- }
- if (opts->rootcontext) {
-- rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
-+ rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid,
-+ GFP_KERNEL);
- if (rc)
- goto out;
- if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
-@@ -735,7 +716,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
- sbsec->flags |= ROOTCONTEXT_MNT;
- }
- if (opts->defcontext) {
-- rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
-+ rc = parse_sid(sb, opts->defcontext, &defcontext_sid,
-+ GFP_KERNEL);
- if (rc)
- goto out;
- if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
-@@ -1005,18 +987,22 @@ out:
+- s, sb->s_id, sb->s_type->name, rc);
++ s, sb ? sb->s_id : "?", sb ? sb->s_type->name : "?", rc);
+ return rc;
+ }
+
+@@ -1005,42 +986,58 @@ out:
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
struct selinux_mnt_opts *opts = *mnt_opts;
@@ -158691,7 +245147,32 @@ index e7ebd45ca3457..baa12d1007c7c 100644
switch (token) {
case Opt_context:
if (opts->context || opts->defcontext)
-@@ -1041,6 +1027,10 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
+ goto Einval;
+ opts->context = s;
++ if (selinux_initialized(&selinux_state))
++ parse_sid(NULL, s, &opts->context_sid);
+ break;
+ case Opt_fscontext:
+ if (opts->fscontext)
+ goto Einval;
+ opts->fscontext = s;
++ if (selinux_initialized(&selinux_state))
++ parse_sid(NULL, s, &opts->fscontext_sid);
+ break;
+ case Opt_rootcontext:
+ if (opts->rootcontext)
+ goto Einval;
+ opts->rootcontext = s;
++ if (selinux_initialized(&selinux_state))
++ parse_sid(NULL, s, &opts->rootcontext_sid);
+ break;
+ case Opt_defcontext:
+ if (opts->context || opts->defcontext)
+ goto Einval;
+ opts->defcontext = s;
++ if (selinux_initialized(&selinux_state))
++ parse_sid(NULL, s, &opts->defcontext_sid);
+ break;
}
return 0;
Einval:
@@ -158702,7 +245183,7 @@ index e7ebd45ca3457..baa12d1007c7c 100644
pr_warn(SEL_MOUNT_FAIL_MSG);
return -EINVAL;
}
-@@ -2066,18 +2056,19 @@ static inline u32 open_file_to_av(struct file *file)
+@@ -2066,18 +2063,19 @@ static inline u32 open_file_to_av(struct file *file)
/* Hook functions begin here. */
@@ -158727,7 +245208,7 @@ index e7ebd45ca3457..baa12d1007c7c 100644
int rc;
if (mysid != fromsid) {
-@@ -2088,24 +2079,24 @@ static int selinux_binder_transaction(struct task_struct *from,
+@@ -2088,24 +2086,24 @@ static int selinux_binder_transaction(struct task_struct *from,
return rc;
}
@@ -158759,75 +245240,97 @@ index e7ebd45ca3457..baa12d1007c7c 100644
struct file_security_struct *fsec = selinux_file(file);
struct dentry *dentry = file->f_path.dentry;
struct inode_security_struct *isec;
-@@ -2723,14 +2714,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
+@@ -2704,9 +2702,7 @@ free_opt:
+ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
+ {
+ struct selinux_mnt_opts *opts = mnt_opts;
+- struct superblock_security_struct *sbsec = sb->s_security;
+- u32 sid;
+- int rc;
++ struct superblock_security_struct *sbsec = selinux_superblock(sb);
+
+ /*
+ * Superblock not initialized (i.e. no options) - reject if any
+@@ -2723,34 +2719,36 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
if (opts->fscontext) {
- rc = parse_sid(sb, opts->fscontext, &sid);
-+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT);
- if (rc)
+- if (rc)
++ if (opts->fscontext_sid == SECSID_NULL)
return 1;
- if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
+- if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
++ else if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
++ opts->fscontext_sid))
return 1;
}
if (opts->context) {
- rc = parse_sid(sb, opts->context, &sid);
-+ rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT);
- if (rc)
- return 1;
- if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
-@@ -2740,14 +2731,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
- struct inode_security_struct *root_isec;
-
- root_isec = backing_inode_security(sb->s_root);
-- rc = parse_sid(sb, opts->rootcontext, &sid);
-+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT);
- if (rc)
+- if (rc)
++ if (opts->context_sid == SECSID_NULL)
return 1;
- if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
+- if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
++ else if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
++ opts->context_sid))
return 1;
}
- if (opts->defcontext) {
-- rc = parse_sid(sb, opts->defcontext, &sid);
-+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT);
- if (rc)
- return 1;
- if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
-@@ -2770,14 +2761,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
- return 0;
-
- if (opts->fscontext) {
-- rc = parse_sid(sb, opts->fscontext, &sid);
-+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL);
- if (rc)
- return rc;
- if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
- goto out_bad_option;
- }
- if (opts->context) {
-- rc = parse_sid(sb, opts->context, &sid);
-+ rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL);
- if (rc)
- return rc;
- if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
-@@ -2786,14 +2777,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
if (opts->rootcontext) {
- struct inode_security_struct *root_isec;
- root_isec = backing_inode_security(sb->s_root);
+- struct inode_security_struct *root_isec;
+-
+- root_isec = backing_inode_security(sb->s_root);
- rc = parse_sid(sb, opts->rootcontext, &sid);
-+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL);
- if (rc)
- return rc;
- if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
- goto out_bad_option;
+- if (rc)
+- return 1;
+- if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
++ if (opts->rootcontext_sid == SECSID_NULL)
+ return 1;
++ else {
++ struct inode_security_struct *root_isec;
++
++ root_isec = backing_inode_security(sb->s_root);
++ if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
++ opts->rootcontext_sid))
++ return 1;
++ }
}
if (opts->defcontext) {
- rc = parse_sid(sb, opts->defcontext, &sid);
-+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL);
- if (rc)
- return rc;
- if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
-@@ -5829,7 +5820,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
+- if (rc)
++ if (opts->defcontext_sid == SECSID_NULL)
+ return 1;
+- if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
++ else if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
++ opts->defcontext_sid))
+ return 1;
+ }
+ return 0;
+@@ -2917,10 +2915,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
+ return opt;
+
+ rc = selinux_add_opt(opt, param->string, &fc->security);
+- if (!rc) {
++ if (!rc)
+ param->string = NULL;
+- rc = 1;
+- }
++
+ return rc;
+ }
+
+@@ -3798,6 +3795,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
+ CAP_OPT_NONE, true);
+ break;
+
++ case FIOCLEX:
++ case FIONCLEX:
++ if (!selinux_policycap_ioctl_skip_cloexec())
++ error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
++ break;
++
+ /* default case assumes that the command will go
+ * to the file's ioctl() function.
+ */
+@@ -5829,7 +5832,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
char *addrp;
@@ -158858,6 +245361,63 @@ index 727c4e43219d7..ff7aea6b3774a 100644
mutex_lock(&state->policy_mutex);
selinux_ima_measure_state_locked(state);
+diff --git a/security/selinux/include/policycap.h b/security/selinux/include/policycap.h
+index 2ec038efbb03c..a9e572ca4fd96 100644
+--- a/security/selinux/include/policycap.h
++++ b/security/selinux/include/policycap.h
+@@ -11,6 +11,7 @@ enum {
+ POLICYDB_CAPABILITY_CGROUPSECLABEL,
+ POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
+ POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS,
++ POLICYDB_CAPABILITY_IOCTL_SKIP_CLOEXEC,
+ __POLICYDB_CAPABILITY_MAX
+ };
+ #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+diff --git a/security/selinux/include/policycap_names.h b/security/selinux/include/policycap_names.h
+index b89289f092c93..ebd64afe1defd 100644
+--- a/security/selinux/include/policycap_names.h
++++ b/security/selinux/include/policycap_names.h
+@@ -12,7 +12,8 @@ const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
+ "always_check_network",
+ "cgroup_seclabel",
+ "nnp_nosuid_transition",
+- "genfs_seclabel_symlinks"
++ "genfs_seclabel_symlinks",
++ "ioctl_skip_cloexec"
+ };
+
+ #endif /* _SELINUX_POLICYCAP_NAMES_H_ */
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index ac0ece01305a6..c0d966020ebdd 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -219,6 +219,13 @@ static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
+ return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS]);
+ }
+
++static inline bool selinux_policycap_ioctl_skip_cloexec(void)
++{
++ struct selinux_state *state = &selinux_state;
++
++ return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_IOCTL_SKIP_CLOEXEC]);
++}
++
+ struct selinux_policy_convert_data;
+
+ struct selinux_load_state {
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index e4cd7cb856f37..f2f6203e0fff5 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -2127,6 +2127,8 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
+ }
+
+ ret = sel_make_avc_files(dentry);
++ if (ret)
++ goto err;
+
+ dentry = sel_make_dir(sb->s_root, "ss", &fsi->last_ino);
+ if (IS_ERR(dentry)) {
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 2ec6e5cd25d9b..feb206f3acb4a 100644
--- a/security/selinux/ss/conditional.c
@@ -158880,7 +245440,7 @@ index 2ec6e5cd25d9b..feb206f3acb4a 100644
}
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
-index b8f6b3e0a9219..a91fb0ed00de3 100644
+index b8f6b3e0a9219..298098bb9c06d 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -30,13 +30,20 @@ static u32 hashtab_compute_size(u32 nel)
@@ -158909,6 +245469,16 @@ index b8f6b3e0a9219..a91fb0ed00de3 100644
}
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
+@@ -171,7 +178,8 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
+ kmem_cache_free(hashtab_node_cachep, cur);
+ }
+ }
+- kmem_cache_free(hashtab_node_cachep, new);
++ kfree(new->htable);
++ memset(new, 0, sizeof(*new));
+ return -ENOMEM;
+ }
+
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index e5f1b2757a83a..c4931bf6f92a4 100644
--- a/security/selinux/ss/services.c
@@ -159154,6 +245724,32 @@ index e5f1b2757a83a..c4931bf6f92a4 100644
} else {
rc = __security_genfs_sid(policy, fstype, "/",
SECCLASS_DIR, &sbsec->sid);
+diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
+index be83e5ce4469c..debe15207d2bf 100644
+--- a/security/selinux/xfrm.c
++++ b/security/selinux/xfrm.c
+@@ -347,7 +347,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ int rc;
+ struct xfrm_sec_ctx *ctx;
+ char *ctx_str = NULL;
+- int str_len;
++ u32 str_len;
+
+ if (!polsec)
+ return 0;
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 21a0e7c3b8dee..3f3f56f6be4da 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -2505,7 +2505,7 @@ static int smk_ipv6_check(struct smack_known *subject,
+ #ifdef CONFIG_AUDIT
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+ ad.a.u.net->family = PF_INET6;
+- ad.a.u.net->dport = ntohs(address->sin6_port);
++ ad.a.u.net->dport = address->sin6_port;
+ if (act == SMK_RECEIVING)
+ ad.a.u.net->v6info.saddr = address->sin6_addr;
+ else
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 3a75d2a8f5178..658eab05599e6 100644
--- a/security/smack/smackfs.c
@@ -159199,6 +245795,28 @@ index 3a75d2a8f5178..658eab05599e6 100644
rc = count;
/*
* This mapping may have been cached, so clear the cache.
+diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c
+index 3445ae6fd4794..363b65be87ab7 100644
+--- a/security/tomoyo/load_policy.c
++++ b/security/tomoyo/load_policy.c
+@@ -24,7 +24,7 @@ static const char *tomoyo_loader;
+ static int __init tomoyo_loader_setup(char *str)
+ {
+ tomoyo_loader = str;
+- return 0;
++ return 1;
+ }
+
+ __setup("TOMOYO_loader=", tomoyo_loader_setup);
+@@ -64,7 +64,7 @@ static const char *tomoyo_trigger;
+ static int __init tomoyo_trigger_setup(char *str)
+ {
+ tomoyo_trigger = str;
+- return 0;
++ return 1;
+ }
+
+ __setup("TOMOYO_trigger=", tomoyo_trigger_setup);
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 1da2e3722b126..6799b1122c9d8 100644
--- a/security/tomoyo/util.c
@@ -159309,6 +245927,52 @@ index 470dabc60aa0e..edff063e088d2 100644
return 0;
}
+diff --git a/sound/core/init.c b/sound/core/init.c
+index ac335f5906c6b..362588e3a275b 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -209,6 +209,12 @@ static void __snd_card_release(struct device *dev, void *data)
+ * snd_card_register(), the very first devres action to call snd_card_free()
+ * is added automatically. In that way, the resource disconnection is assured
+ * at first, then released in the expected order.
++ *
++ * If an error happens at the probe before snd_card_register() is called and
++ * there have been other devres resources, you'd need to free the card manually
++ * via snd_card_free() call in the error; otherwise it may lead to UAF due to
++ * devres call orders. You can use snd_card_free_on_error() helper for
++ * handling it more easily.
+ */
+ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+ struct module *module, size_t extra_size,
+@@ -235,6 +241,28 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+ }
+ EXPORT_SYMBOL_GPL(snd_devm_card_new);
+
++/**
++ * snd_card_free_on_error - a small helper for handling devm probe errors
++ * @dev: the managed device object
++ * @ret: the return code from the probe callback
++ *
++ * This function handles the explicit snd_card_free() call at the error from
++ * the probe callback. It's just a small helper for simplifying the error
++ * handling with the managed devices.
++ */
++int snd_card_free_on_error(struct device *dev, int ret)
++{
++ struct snd_card *card;
++
++ if (!ret)
++ return 0;
++ card = devres_find(dev, __snd_card_release, NULL, NULL);
++ if (card)
++ snd_card_free(card);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(snd_card_free_on_error);
++
+ static int snd_card_init(struct snd_card *card, struct device *parent,
+ int idx, const char *xid, struct module *module,
+ size_t extra_size)
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 32350c6aba849..d1e3055f2b6a5 100644
--- a/sound/core/jack.c
@@ -159529,7 +246193,7 @@ index 6a5abdd4271ba..9620115cfdc09 100644
static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg)
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
-index 82a818734a5f7..3ee9edf858156 100644
+index 82a818734a5f7..f158f0abd25d8 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
@@ -159598,7 +246262,19 @@ index 82a818734a5f7..3ee9edf858156 100644
s = runtime->oss.maxfrags;
if (oss_periods > s)
oss_periods = s;
-@@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
+@@ -768,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
+
+ if (oss_period_size < 16)
+ return -EINVAL;
++
++ /* don't allocate too large period; 1MB period must be enough */
++ if (oss_period_size > 1024 * 1024)
++ return -ENOMEM;
++
+ runtime->oss.period_bytes = oss_period_size;
+ runtime->oss.period_frames = 1;
+ runtime->oss.periods = oss_periods;
+@@ -878,8 +889,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
err = -EINVAL;
goto failure;
}
@@ -159616,7 +246292,21 @@ index 82a818734a5f7..3ee9edf858156 100644
format = snd_pcm_oss_format_from(runtime->oss.format);
-@@ -1956,7 +1969,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign
+@@ -1030,10 +1048,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
+ goto failure;
+ }
+ #endif
+- oss_period_size *= oss_frame_size;
+-
+- oss_buffer_size = oss_period_size * runtime->oss.periods;
+- if (oss_buffer_size < 0) {
++ oss_period_size = array_size(oss_period_size, oss_frame_size);
++ oss_buffer_size = array_size(oss_period_size, runtime->oss.periods);
++ if (oss_buffer_size <= 0) {
+ err = -EINVAL;
+ goto failure;
+ }
+@@ -1956,7 +1973,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign
if (runtime->oss.subdivision || runtime->oss.fragshift)
return -EINVAL;
fragshift = val & 0xffff;
@@ -159625,7 +246315,7 @@ index 82a818734a5f7..3ee9edf858156 100644
return -EINVAL;
runtime->oss.fragshift = fragshift;
runtime->oss.maxfrags = (val >> 16) & 0xffff;
-@@ -2052,7 +2065,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
+@@ -2052,7 +2069,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
int err, cmd;
#ifdef OSS_DEBUG
@@ -159634,8 +246324,24 @@ index 82a818734a5f7..3ee9edf858156 100644
#endif
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
+index 061ba06bc9262..82e180c776ae1 100644
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -62,7 +62,10 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
+ width = snd_pcm_format_physical_width(format->format);
+ if (width < 0)
+ return width;
+- size = frames * format->channels * width;
++ size = array3_size(frames, format->channels, width);
++ /* check for too large period size once again */
++ if (size > 1024 * 1024)
++ return -ENOMEM;
+ if (snd_BUG_ON(size % 8))
+ return -ENXIO;
+ size /= 8;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
-index 6fd3677685d70..ba4a987ed1c62 100644
+index 6fd3677685d70..977d54320a5ca 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -810,7 +810,11 @@ EXPORT_SYMBOL(snd_pcm_new_internal);
@@ -159651,6 +246357,334 @@ index 6fd3677685d70..ba4a987ed1c62 100644
pstr->chmap_kctl = NULL;
}
}
+@@ -965,6 +969,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
+ init_waitqueue_head(&runtime->tsleep);
+
+ runtime->status->state = SNDRV_PCM_STATE_OPEN;
++ mutex_init(&runtime->buffer_mutex);
++ atomic_set(&runtime->buffer_accessing, 0);
+
+ substream->runtime = runtime;
+ substream->private_data = pcm->private_data;
+@@ -998,6 +1004,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
+ } else {
+ substream->runtime = NULL;
+ }
++ mutex_destroy(&runtime->buffer_mutex);
+ kfree(runtime);
+ put_pid(substream->pid);
+ substream->pid = NULL;
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index a144a3f68e9eb..491064f55515b 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2255,10 +2255,15 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ err = -EINVAL;
+ goto _end_unlock;
+ }
++ if (!atomic_inc_unless_negative(&runtime->buffer_accessing)) {
++ err = -EBUSY;
++ goto _end_unlock;
++ }
+ snd_pcm_stream_unlock_irq(substream);
+ err = writer(substream, appl_ofs, data, offset, frames,
+ transfer);
+ snd_pcm_stream_lock_irq(substream);
++ atomic_dec(&runtime->buffer_accessing);
+ if (err < 0)
+ goto _end_unlock;
+ err = pcm_accessible_state(runtime);
+diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
+index 7fbd1ccbb5b01..f1fb856ff4ac7 100644
+--- a/sound/core/pcm_memory.c
++++ b/sound/core/pcm_memory.c
+@@ -158,19 +158,20 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
+ size_t size;
+ struct snd_dma_buffer new_dmab;
+
++ mutex_lock(&substream->pcm->open_mutex);
+ if (substream->runtime) {
+ buffer->error = -EBUSY;
+- return;
++ goto unlock;
+ }
+ if (!snd_info_get_line(buffer, line, sizeof(line))) {
+ snd_info_get_str(str, line, sizeof(str));
+ size = simple_strtoul(str, NULL, 10) * 1024;
+ if ((size != 0 && size < 8192) || size > substream->dma_max) {
+ buffer->error = -EINVAL;
+- return;
++ goto unlock;
+ }
+ if (substream->dma_buffer.bytes == size)
+- return;
++ goto unlock;
+ memset(&new_dmab, 0, sizeof(new_dmab));
+ new_dmab.dev = substream->dma_buffer.dev;
+ if (size > 0) {
+@@ -183,7 +184,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
+ substream->pcm->card->number, substream->pcm->device,
+ substream->stream ? 'c' : 'p', substream->number,
+ substream->pcm->name, size);
+- return;
++ goto unlock;
+ }
+ substream->buffer_bytes_max = size;
+ } else {
+@@ -195,6 +196,8 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
+ } else {
+ buffer->error = -EINVAL;
+ }
++ unlock:
++ mutex_unlock(&substream->pcm->open_mutex);
+ }
+
+ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
+diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
+index 4866aed97aacc..5588b6a1ee8bd 100644
+--- a/sound/core/pcm_misc.c
++++ b/sound/core/pcm_misc.c
+@@ -433,7 +433,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
+ return 0;
+ width = pcm_formats[(INT)format].phys; /* physical width */
+ pat = pcm_formats[(INT)format].silence;
+- if (! width)
++ if (!width || !pat)
+ return -EINVAL;
+ /* signed or 1 byte data */
+ if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index d233cb3b41d8b..f38c2e5e9a297 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -672,6 +672,30 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ return 0;
+ }
+
++/* acquire buffer_mutex; if it's in r/w operation, return -EBUSY, otherwise
++ * block the further r/w operations
++ */
++static int snd_pcm_buffer_access_lock(struct snd_pcm_runtime *runtime)
++{
++ if (!atomic_dec_unless_positive(&runtime->buffer_accessing))
++ return -EBUSY;
++ mutex_lock(&runtime->buffer_mutex);
++ return 0; /* keep buffer_mutex, unlocked by below */
++}
++
++/* release buffer_mutex and clear r/w access flag */
++static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
++{
++ mutex_unlock(&runtime->buffer_mutex);
++ atomic_inc(&runtime->buffer_accessing);
++}
++
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
++#define is_oss_stream(substream) ((substream)->oss.oss)
++#else
++#define is_oss_stream(substream) false
++#endif
++
+ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -683,22 +707,25 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
++ err = snd_pcm_buffer_access_lock(runtime);
++ if (err < 0)
++ return err;
+ snd_pcm_stream_lock_irq(substream);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_SETUP:
+ case SNDRV_PCM_STATE_PREPARED:
++ if (!is_oss_stream(substream) &&
++ atomic_read(&substream->mmap_count))
++ err = -EBADFD;
+ break;
+ default:
+- snd_pcm_stream_unlock_irq(substream);
+- return -EBADFD;
++ err = -EBADFD;
++ break;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+- if (!substream->oss.oss)
+-#endif
+- if (atomic_read(&substream->mmap_count))
+- return -EBADFD;
++ if (err)
++ goto unlock;
+
+ snd_pcm_sync_stop(substream, true);
+
+@@ -786,16 +813,21 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ if (usecs >= 0)
+ cpu_latency_qos_add_request(&substream->latency_pm_qos_req,
+ usecs);
+- return 0;
++ err = 0;
+ _error:
+- /* hardware might be unusable from this time,
+- so we force application to retry to set
+- the correct hardware parameter settings */
+- snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
+- if (substream->ops->hw_free != NULL)
+- substream->ops->hw_free(substream);
+- if (substream->managed_buffer_alloc)
+- snd_pcm_lib_free_pages(substream);
++ if (err) {
++ /* hardware might be unusable from this time,
++ * so we force application to retry to set
++ * the correct hardware parameter settings
++ */
++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
++ if (substream->ops->hw_free != NULL)
++ substream->ops->hw_free(substream);
++ if (substream->managed_buffer_alloc)
++ snd_pcm_lib_free_pages(substream);
++ }
++ unlock:
++ snd_pcm_buffer_access_unlock(runtime);
+ return err;
+ }
+
+@@ -835,26 +867,33 @@ static int do_hw_free(struct snd_pcm_substream *substream)
+ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+ struct snd_pcm_runtime *runtime;
+- int result;
++ int result = 0;
+
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
++ result = snd_pcm_buffer_access_lock(runtime);
++ if (result < 0)
++ return result;
+ snd_pcm_stream_lock_irq(substream);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_SETUP:
+ case SNDRV_PCM_STATE_PREPARED:
++ if (atomic_read(&substream->mmap_count))
++ result = -EBADFD;
+ break;
+ default:
+- snd_pcm_stream_unlock_irq(substream);
+- return -EBADFD;
++ result = -EBADFD;
++ break;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+- if (atomic_read(&substream->mmap_count))
+- return -EBADFD;
++ if (result)
++ goto unlock;
+ result = do_hw_free(substream);
+ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
+ cpu_latency_qos_remove_request(&substream->latency_pm_qos_req);
++ unlock:
++ snd_pcm_buffer_access_unlock(runtime);
+ return result;
+ }
+
+@@ -1160,15 +1199,17 @@ struct action_ops {
+ static int snd_pcm_action_group(const struct action_ops *ops,
+ struct snd_pcm_substream *substream,
+ snd_pcm_state_t state,
+- bool do_lock)
++ bool stream_lock)
+ {
+ struct snd_pcm_substream *s = NULL;
+ struct snd_pcm_substream *s1;
+ int res = 0, depth = 1;
+
+ snd_pcm_group_for_each_entry(s, substream) {
+- if (do_lock && s != substream) {
+- if (s->pcm->nonatomic)
++ if (s != substream) {
++ if (!stream_lock)
++ mutex_lock_nested(&s->runtime->buffer_mutex, depth);
++ else if (s->pcm->nonatomic)
+ mutex_lock_nested(&s->self_group.mutex, depth);
+ else
+ spin_lock_nested(&s->self_group.lock, depth);
+@@ -1196,18 +1237,18 @@ static int snd_pcm_action_group(const struct action_ops *ops,
+ ops->post_action(s, state);
+ }
+ _unlock:
+- if (do_lock) {
+- /* unlock streams */
+- snd_pcm_group_for_each_entry(s1, substream) {
+- if (s1 != substream) {
+- if (s1->pcm->nonatomic)
+- mutex_unlock(&s1->self_group.mutex);
+- else
+- spin_unlock(&s1->self_group.lock);
+- }
+- if (s1 == s) /* end */
+- break;
++ /* unlock streams */
++ snd_pcm_group_for_each_entry(s1, substream) {
++ if (s1 != substream) {
++ if (!stream_lock)
++ mutex_unlock(&s1->runtime->buffer_mutex);
++ else if (s1->pcm->nonatomic)
++ mutex_unlock(&s1->self_group.mutex);
++ else
++ spin_unlock(&s1->self_group.lock);
+ }
++ if (s1 == s) /* end */
++ break;
+ }
+ return res;
+ }
+@@ -1337,10 +1378,15 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
+
+ /* Guarantee the group members won't change during non-atomic action */
+ down_read(&snd_pcm_link_rwsem);
++ res = snd_pcm_buffer_access_lock(substream->runtime);
++ if (res < 0)
++ goto unlock;
+ if (snd_pcm_stream_linked(substream))
+ res = snd_pcm_action_group(ops, substream, state, false);
+ else
+ res = snd_pcm_action_single(ops, substream, state);
++ snd_pcm_buffer_access_unlock(substream->runtime);
++ unlock:
+ up_read(&snd_pcm_link_rwsem);
+ return res;
+ }
+@@ -1830,11 +1876,13 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
+ int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
+ if (err < 0)
+ return err;
++ snd_pcm_stream_lock_irq(substream);
+ runtime->hw_ptr_base = 0;
+ runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
+ runtime->status->hw_ptr % runtime->period_size;
+ runtime->silence_start = runtime->status->hw_ptr;
+ runtime->silence_filled = 0;
++ snd_pcm_stream_unlock_irq(substream);
+ return 0;
+ }
+
+@@ -1842,10 +1890,12 @@ static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
++ snd_pcm_stream_lock_irq(substream);
+ runtime->control->appl_ptr = runtime->status->hw_ptr;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ runtime->silence_size > 0)
+ snd_pcm_playback_silence(substream, ULONG_MAX);
++ snd_pcm_stream_unlock_irq(substream);
+ }
+
+ static const struct action_ops snd_pcm_action_reset = {
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6f30231bdb884..befa9809ff001 100644
--- a/sound/core/rawmidi.c
@@ -159764,6 +246798,28 @@ index 92b7008fcdb86..b3214baa89193 100644
}
/*
+diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
+index 11235baaf6fa5..f212f233ea618 100644
+--- a/sound/drivers/mtpav.c
++++ b/sound/drivers/mtpav.c
+@@ -693,8 +693,6 @@ static int snd_mtpav_probe(struct platform_device *dev)
+ mtp_card->outmidihwport = 0xffffffff;
+ timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);
+
+- card->private_free = snd_mtpav_free;
+-
+ err = snd_mtpav_get_RAWMIDI(mtp_card);
+ if (err < 0)
+ return err;
+@@ -716,6 +714,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
+ if (err < 0)
+ return err;
+
++ card->private_free = snd_mtpav_free;
++
+ platform_set_drvdata(dev, card);
+ printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
+ return 0;
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index e1b69c65c3c88..e2b7be67f0e30 100644
--- a/sound/drivers/opl3/opl3_midi.c
@@ -159777,6 +246833,33 @@ index e1b69c65c3c88..e2b7be67f0e30 100644
opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK +
voice_offset + 3);
reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
+diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c
+index bbfbebf4affbc..df44dd5dc4b22 100644
+--- a/sound/firewire/fcp.c
++++ b/sound/firewire/fcp.c
+@@ -240,9 +240,7 @@ int fcp_avc_transaction(struct fw_unit *unit,
+ t.response_match_bytes = response_match_bytes;
+ t.state = STATE_PENDING;
+ init_waitqueue_head(&t.wait);
+-
+- if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03)
+- t.deferrable = true;
++ t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03);
+
+ spin_lock_irq(&transactions_lock);
+ list_add_tail(&t.list, &transactions);
+diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c
+index 626c0c34b0b66..3a53914277d35 100644
+--- a/sound/firewire/fireworks/fireworks_hwdep.c
++++ b/sound/firewire/fireworks/fireworks_hwdep.c
+@@ -34,6 +34,7 @@ hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained,
+ type = SNDRV_FIREWIRE_EVENT_EFW_RESPONSE;
+ if (copy_to_user(buf, &type, sizeof(type)))
+ return -EFAULT;
++ count += sizeof(type);
+ remained -= sizeof(type);
+ buf += sizeof(type);
+
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c
index fff18b5d4e052..f4a702def3979 100644
--- a/sound/firewire/oxfw/oxfw-stream.c
@@ -160187,6 +247270,58 @@ index 6ffa48dd59830..570b88e0b2018 100644
default y
help
Support for sound devices connected via the ISA bus.
+diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
+index b6bdebd9ef275..10112e1bb25dc 100644
+--- a/sound/isa/cs423x/cs4236.c
++++ b/sound/isa/cs423x/cs4236.c
+@@ -494,7 +494,7 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+ static int dev;
+ int err;
+ struct snd_card *card;
+- struct pnp_dev *cdev;
++ struct pnp_dev *cdev, *iter;
+ char cid[PNP_ID_LEN];
+
+ if (pnp_device_is_isapnp(pdev))
+@@ -510,9 +510,11 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+ strcpy(cid, pdev->id[0].id);
+ cid[5] = '1';
+ cdev = NULL;
+- list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) {
+- if (!strcmp(cdev->id[0].id, cid))
++ list_for_each_entry(iter, &(pdev->protocol->devices), protocol_list) {
++ if (!strcmp(iter->id[0].id, cid)) {
++ cdev = iter;
+ break;
++ }
+ }
+ err = snd_cs423x_card_new(&pdev->dev, dev, &card);
+ if (err < 0)
+diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
+index ea001c80149dd..3164eb8510fa4 100644
+--- a/sound/isa/galaxy/galaxy.c
++++ b/sound/isa/galaxy/galaxy.c
+@@ -478,7 +478,7 @@ static void snd_galaxy_free(struct snd_card *card)
+ galaxy_set_config(galaxy, galaxy->config);
+ }
+
+-static int snd_galaxy_probe(struct device *dev, unsigned int n)
++static int __snd_galaxy_probe(struct device *dev, unsigned int n)
+ {
+ struct snd_galaxy *galaxy;
+ struct snd_wss *chip;
+@@ -598,6 +598,11 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
+ return 0;
+ }
+
++static int snd_galaxy_probe(struct device *dev, unsigned int n)
++{
++ return snd_card_free_on_error(dev, __snd_galaxy_probe(dev, n));
++}
++
+ static struct isa_driver snd_galaxy_driver = {
+ .match = snd_galaxy_match,
+ .probe = snd_galaxy_probe,
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
index a1c770d826dda..6d664dd8dde0b 100644
--- a/sound/isa/gus/gus_dma.c
@@ -160200,6 +247335,45 @@ index a1c770d826dda..6d664dd8dde0b 100644
snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd);
kfree(block);
#if 0
+diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
+index 26ab7ff807684..60398fced046b 100644
+--- a/sound/isa/sc6000.c
++++ b/sound/isa/sc6000.c
+@@ -537,7 +537,7 @@ static void snd_sc6000_free(struct snd_card *card)
+ sc6000_setup_board(vport, 0);
+ }
+
+-static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
++static int __snd_sc6000_probe(struct device *devptr, unsigned int dev)
+ {
+ static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
+ static const int possible_dmas[] = { 1, 3, 0, -1 };
+@@ -662,6 +662,11 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
+ return 0;
+ }
+
++static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
++{
++ return snd_card_free_on_error(devptr, __snd_sc6000_probe(devptr, dev));
++}
++
+ static struct isa_driver snd_sc6000_driver = {
+ .match = snd_sc6000_match,
+ .probe = snd_sc6000_probe,
+diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
+index 69cbc79fbb716..2aaaa68071744 100644
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -1094,7 +1094,8 @@ wavefront_send_sample (snd_wavefront_t *dev,
+
+ if (dataptr < data_end) {
+
+- __get_user (sample_short, dataptr);
++ if (get_user(sample_short, dataptr))
++ return -EFAULT;
+ dataptr += skip;
+
+ if (data_is_unsigned) { /* GUS ? */
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 93bc9bef7641f..41ce125971777 100644
--- a/sound/pci/Kconfig
@@ -160212,6 +247386,430 @@ index 93bc9bef7641f..41ce125971777 100644
select SND_SB16_DSP
help
Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
+diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
+index 01f296d524ce6..cb60a07d39a8e 100644
+--- a/sound/pci/ac97/ac97_codec.c
++++ b/sound/pci/ac97/ac97_codec.c
+@@ -938,8 +938,8 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct
+ int codec = kcontrol->private_value & 3;
+
+ mutex_lock(&ac97->page_mutex);
+- ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
+- ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
++ ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
++ ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
+ mutex_unlock(&ac97->page_mutex);
+ return 0;
+ }
+diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
+index bba4dae8dcc70..50e30704bf6f9 100644
+--- a/sound/pci/ad1889.c
++++ b/sound/pci/ad1889.c
+@@ -844,8 +844,8 @@ snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
+ }
+
+ static int
+-snd_ad1889_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++__snd_ad1889_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ int err;
+ static int devno;
+@@ -904,6 +904,12 @@ snd_ad1889_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_ad1889_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_ad1889_probe(pci, pci_id));
++}
++
+ static const struct pci_device_id snd_ad1889_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
+ { 0, },
+diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
+index 92eb59db106de..2378a39abaebe 100644
+--- a/sound/pci/ali5451/ali5451.c
++++ b/sound/pci/ali5451/ali5451.c
+@@ -2124,8 +2124,8 @@ static int snd_ali_create(struct snd_card *card,
+ return 0;
+ }
+
+-static int snd_ali_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_ali_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct snd_ali *codec;
+@@ -2170,6 +2170,12 @@ static int snd_ali_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_ali_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_ali_probe(pci, pci_id));
++}
++
+ static struct pci_driver ali5451_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_ali_ids,
+diff --git a/sound/pci/als300.c b/sound/pci/als300.c
+index b86565dcdbe41..c70aff0601205 100644
+--- a/sound/pci/als300.c
++++ b/sound/pci/als300.c
+@@ -708,7 +708,7 @@ static int snd_als300_probe(struct pci_dev *pci,
+
+ err = snd_als300_create(card, pci, chip_type);
+ if (err < 0)
+- return err;
++ goto error;
+
+ strcpy(card->driver, "ALS300");
+ if (chip->chip_type == DEVICE_ALS300_PLUS)
+@@ -723,11 +723,15 @@ static int snd_als300_probe(struct pci_dev *pci,
+
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver als300_driver = {
+diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
+index 535eccd124bee..f33aeb692a112 100644
+--- a/sound/pci/als4000.c
++++ b/sound/pci/als4000.c
+@@ -806,8 +806,8 @@ static void snd_card_als4000_free( struct snd_card *card )
+ snd_als4000_free_gameport(acard);
+ }
+
+-static int snd_card_als4000_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_card_als4000_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -930,6 +930,12 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_card_als4000_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_card_als4000_probe(pci, pci_id));
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static int snd_als4000_suspend(struct device *dev)
+ {
+diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
+index b8e035d5930d2..43d01f1847ed7 100644
+--- a/sound/pci/atiixp.c
++++ b/sound/pci/atiixp.c
+@@ -1572,8 +1572,8 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
+ }
+
+
+-static int snd_atiixp_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_atiixp_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct atiixp *chip;
+@@ -1623,6 +1623,12 @@ static int snd_atiixp_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_atiixp_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_atiixp_probe(pci, pci_id));
++}
++
+ static struct pci_driver atiixp_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_atiixp_ids,
+diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
+index 178dce8ef1e99..8864c4c3c7e13 100644
+--- a/sound/pci/atiixp_modem.c
++++ b/sound/pci/atiixp_modem.c
+@@ -1201,8 +1201,8 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
+ }
+
+
+-static int snd_atiixp_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_atiixp_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct atiixp_modem *chip;
+@@ -1247,6 +1247,12 @@ static int snd_atiixp_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_atiixp_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_atiixp_probe(pci, pci_id));
++}
++
+ static struct pci_driver atiixp_modem_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_atiixp_ids,
+diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
+index 342ef2a6655e3..eb234153691bc 100644
+--- a/sound/pci/au88x0/au88x0.c
++++ b/sound/pci/au88x0/au88x0.c
+@@ -193,7 +193,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
+
+ // constructor -- see "Constructor" sub-section
+ static int
+-snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++__snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -310,6 +310,12 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ return 0;
+ }
+
++static int
++snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_vortex_probe(pci, pci_id));
++}
++
+ // pci_driver definition
+ static struct pci_driver vortex_driver = {
+ .name = KBUILD_MODNAME,
+diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
+index d56f126d6fdd9..29a4bcdec237a 100644
+--- a/sound/pci/aw2/aw2-alsa.c
++++ b/sound/pci/aw2/aw2-alsa.c
+@@ -275,7 +275,7 @@ static int snd_aw2_probe(struct pci_dev *pci,
+ /* (3) Create main component */
+ err = snd_aw2_create(card, pci);
+ if (err < 0)
+- return err;
++ goto error;
+
+ /* initialize mutex */
+ mutex_init(&chip->mtx);
+@@ -294,13 +294,17 @@ static int snd_aw2_probe(struct pci_dev *pci,
+ /* (6) Register card instance */
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+
+ /* (7) Set PCI driver data */
+ pci_set_drvdata(pci, card);
+
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ /* open callback */
+diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
+index 089050470ff27..7f329dfc5404a 100644
+--- a/sound/pci/azt3328.c
++++ b/sound/pci/azt3328.c
+@@ -2427,7 +2427,7 @@ snd_azf3328_create(struct snd_card *card,
+ }
+
+ static int
+-snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++__snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2520,6 +2520,12 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ return 0;
+ }
+
++static int
++snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_azf3328_probe(pci, pci_id));
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static inline void
+ snd_azf3328_suspend_regs(const struct snd_azf3328 *chip,
+diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
+index d23f931638410..621985bfee5d7 100644
+--- a/sound/pci/bt87x.c
++++ b/sound/pci/bt87x.c
+@@ -805,8 +805,8 @@ static int snd_bt87x_detect_card(struct pci_dev *pci)
+ return SND_BT87X_BOARD_UNKNOWN;
+ }
+
+-static int snd_bt87x_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_bt87x_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -889,6 +889,12 @@ static int snd_bt87x_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_bt87x_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_bt87x_probe(pci, pci_id));
++}
++
+ /* default entries for all Bt87x cards - it's not exported */
+ /* driver_data is set to 0 to call detection */
+ static const struct pci_device_id snd_bt87x_default_ids[] = {
+diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
+index 36fb150b72fb5..f4cc112bddf3e 100644
+--- a/sound/pci/ca0106/ca0106_main.c
++++ b/sound/pci/ca0106/ca0106_main.c
+@@ -1725,8 +1725,8 @@ static int snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
+ }
+
+
+-static int snd_ca0106_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_ca0106_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1786,6 +1786,12 @@ static int snd_ca0106_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_ca0106_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_ca0106_probe(pci, pci_id));
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static int snd_ca0106_suspend(struct device *dev)
+ {
+diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
+index ea20236f35dbc..42fcbed9220c1 100644
+--- a/sound/pci/cmipci.c
++++ b/sound/pci/cmipci.c
+@@ -298,7 +298,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
+ #define CM_MICGAINZ 0x01 /* mic boost */
+ #define CM_MICGAINZ_SHIFT 0
+
+-#define CM_REG_MIXER3 0x24
+ #define CM_REG_AUX_VOL 0x26
+ #define CM_VAUXL_MASK 0xf0
+ #define CM_VAUXR_MASK 0x0f
+@@ -3250,15 +3249,19 @@ static int snd_cmipci_probe(struct pci_dev *pci,
+
+ err = snd_cmipci_create(card, pci, dev);
+ if (err < 0)
+- return err;
++ goto error;
+
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+@@ -3267,7 +3270,7 @@ static int snd_cmipci_probe(struct pci_dev *pci,
+ */
+ static const unsigned char saved_regs[] = {
+ CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL,
+- CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL,
++ CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_AUX_VOL, CM_REG_PLL,
+ CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2,
+ CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC,
+ CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0,
+diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
+index e7367402b84a3..0c9cadf7b3b80 100644
+--- a/sound/pci/cs4281.c
++++ b/sound/pci/cs4281.c
+@@ -1827,8 +1827,8 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
+ spin_unlock_irqrestore(&opl3->reg_lock, flags);
+ }
+
+-static int snd_cs4281_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_cs4281_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1888,6 +1888,12 @@ static int snd_cs4281_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_cs4281_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_cs4281_probe(pci, pci_id));
++}
++
+ /*
+ * Power Management
+ */
+diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
+index 499fa0148f9a4..440b8f9b40c96 100644
+--- a/sound/pci/cs5535audio/cs5535audio.c
++++ b/sound/pci/cs5535audio/cs5535audio.c
+@@ -281,8 +281,8 @@ static int snd_cs5535audio_create(struct snd_card *card,
+ return 0;
+ }
+
+-static int snd_cs5535audio_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_cs5535audio_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -331,6 +331,12 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_cs5535audio_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_cs5535audio_probe(pci, pci_id));
++}
++
+ static struct pci_driver cs5535audio_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_cs5535audio_ids,
diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c
index da6e6350ceafa..d074727c3e21d 100644
--- a/sound/pci/ctxfi/ctamixer.c
@@ -160256,6 +247854,26 @@ index da6e6350ceafa..d074727c3e21d 100644
}
static int sum_index(const struct rsc *rsc)
+diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
+index 78f35e88aed6b..fbdb8a3d5b8e5 100644
+--- a/sound/pci/ctxfi/ctatc.c
++++ b/sound/pci/ctxfi/ctatc.c
+@@ -36,6 +36,7 @@
+ | ((IEC958_AES3_CON_FS_48000) << 24))
+
+ static const struct snd_pci_quirk subsys_20k1_list[] = {
++ SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0021, "SB046x", CTSB046X),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
+@@ -64,6 +65,7 @@ static const struct snd_pci_quirk subsys_20k2_list[] = {
+
+ static const char *ct_subsys_name[NUM_CTCARDS] = {
+ /* 20k1 models */
++ [CTSB046X] = "SB046x",
+ [CTSB055X] = "SB055x",
+ [CTSB073X] = "SB073x",
+ [CTUAA] = "UAA",
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index f589da0453424..7fc720046ce29 100644
--- a/sound/pci/ctxfi/ctdaio.c
@@ -160301,6 +247919,21 @@ index f589da0453424..7fc720046ce29 100644
}
static const struct rsc_ops daio_out_rsc_ops = {
+diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h
+index f406b626a28c4..2875cec83b8f2 100644
+--- a/sound/pci/ctxfi/cthardware.h
++++ b/sound/pci/ctxfi/cthardware.h
+@@ -26,8 +26,9 @@ enum CHIPTYP {
+
+ enum CTCARDS {
+ /* 20k1 models */
++ CTSB046X,
++ CT20K1_MODEL_FIRST = CTSB046X,
+ CTSB055X,
+- CT20K1_MODEL_FIRST = CTSB055X,
+ CTSB073X,
+ CTUAA,
+ CT20K1_UNKNOWN,
diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c
index 81ad269345182..be1d3e61309ce 100644
--- a/sound/pci/ctxfi/ctresource.c
@@ -160366,6 +247999,173 @@ index bd4697b442334..4a94b4708a77e 100644
}
static int srcimp_index(const struct rsc *rsc)
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index 25b012ef5c3e6..c70c3ac4e99a5 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -1970,8 +1970,8 @@ static int snd_echo_create(struct snd_card *card,
+ }
+
+ /* constructor */
+-static int snd_echo_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_echo_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2139,6 +2139,11 @@ static int snd_echo_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_echo_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_echo_probe(pci, pci_id));
++}
+
+
+ #if defined(CONFIG_PM_SLEEP)
+diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
+index c49c44dc10820..89043392f3ec7 100644
+--- a/sound/pci/emu10k1/emu10k1x.c
++++ b/sound/pci/emu10k1/emu10k1x.c
+@@ -1491,8 +1491,8 @@ static int snd_emu10k1x_midi(struct emu10k1x *emu)
+ return 0;
+ }
+
+-static int snd_emu10k1x_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_emu10k1x_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1554,6 +1554,12 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_emu10k1x_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_emu10k1x_probe(pci, pci_id));
++}
++
+ // PCI IDs
+ static const struct pci_device_id snd_emu10k1x_ids[] = {
+ { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */
+diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
+index 2651f0c64c062..94efe347a97a9 100644
+--- a/sound/pci/ens1370.c
++++ b/sound/pci/ens1370.c
+@@ -2304,8 +2304,8 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-static int snd_audiopci_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_audiopci_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2369,6 +2369,12 @@ static int snd_audiopci_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_audiopci_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_audiopci_probe(pci, pci_id));
++}
++
+ static struct pci_driver ens137x_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_audiopci_ids,
+diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
+index 00b976f42a3db..e34ec6f89e7e0 100644
+--- a/sound/pci/es1938.c
++++ b/sound/pci/es1938.c
+@@ -1716,8 +1716,8 @@ static int snd_es1938_mixer(struct es1938 *chip)
+ }
+
+
+-static int snd_es1938_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_es1938_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1796,6 +1796,12 @@ static int snd_es1938_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_es1938_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_es1938_probe(pci, pci_id));
++}
++
+ static struct pci_driver es1938_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_es1938_ids,
+diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
+index 6a8a02a9ecf41..4a7e20bb11bca 100644
+--- a/sound/pci/es1968.c
++++ b/sound/pci/es1968.c
+@@ -2741,8 +2741,8 @@ static int snd_es1968_create(struct snd_card *card,
+
+ /*
+ */
+-static int snd_es1968_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_es1968_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2848,6 +2848,12 @@ static int snd_es1968_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_es1968_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_es1968_probe(pci, pci_id));
++}
++
+ static struct pci_driver es1968_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_es1968_ids,
+diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
+index 9c22ff19e56d2..62b3cb126c6d0 100644
+--- a/sound/pci/fm801.c
++++ b/sound/pci/fm801.c
+@@ -1268,8 +1268,8 @@ static int snd_fm801_create(struct snd_card *card,
+ return 0;
+ }
+
+-static int snd_card_fm801_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_card_fm801_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1333,6 +1333,12 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_card_fm801_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_card_fm801_probe(pci, pci_id));
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static const unsigned char saved_regs[] = {
+ FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 4a854475a0e60..500d0d474d27b 100644
--- a/sound/pci/hda/hda_auto_parser.c
@@ -160954,10 +248754,53 @@ index ade2b838590cf..d0b725c7285b6 100644
unsigned int paged:1;
unsigned int last_page;
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
-index 65d2c55399195..ffcde7409d2a5 100644
+index 65d2c55399195..24da843f39a11 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
-@@ -2947,7 +2947,8 @@ static int parse_intel_hdmi(struct hda_codec *codec)
+@@ -1387,7 +1387,7 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
+
+ last_try:
+ /* the last try; check the empty slots in pins */
+- for (i = 0; i < spec->num_nids; i++) {
++ for (i = 0; i < spec->pcm_used; i++) {
+ if (!test_bit(i, &spec->pcm_bitmap))
+ return i;
+ }
+@@ -1617,6 +1617,7 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
+ struct hda_codec *codec = per_pin->codec;
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld = &spec->temp_eld;
++ struct device *dev = hda_codec_dev(codec);
+ hda_nid_t pin_nid = per_pin->pin_nid;
+ int dev_id = per_pin->dev_id;
+ /*
+@@ -1630,8 +1631,13 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
+ int present;
+ int ret;
+
++#ifdef CONFIG_PM
++ if (dev->power.runtime_status == RPM_SUSPENDING)
++ return;
++#endif
++
+ ret = snd_hda_power_up_pm(codec);
+- if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec)))
++ if (ret < 0 && pm_runtime_suspended(dev))
+ goto out;
+
+ present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
+@@ -2257,7 +2263,9 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
+ * dev_num is the device entry number in a pin
+ */
+
+- if (codec->mst_no_extra_pcms)
++ if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms)
++ pcm_num = spec->num_cvts;
++ else if (codec->mst_no_extra_pcms)
+ pcm_num = spec->num_nids;
+ else
+ pcm_num = spec->num_nids + spec->dev_num - 1;
+@@ -2947,7 +2955,8 @@ static int parse_intel_hdmi(struct hda_codec *codec)
/* Intel Haswell and onwards; audio component with eld notifier */
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
@@ -160967,7 +248810,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
{
struct hdmi_spec *spec;
int err;
-@@ -2980,7 +2981,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
+@@ -2980,7 +2989,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
* Enable silent stream feature, if it is enabled via
* module param or Kconfig option
*/
@@ -160976,7 +248819,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
spec->send_silent_stream = true;
return parse_intel_hdmi(codec);
-@@ -2988,12 +2989,18 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
+@@ -2988,12 +2997,18 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
static int patch_i915_hsw_hdmi(struct hda_codec *codec)
{
@@ -160997,7 +248840,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
}
static int patch_i915_icl_hdmi(struct hda_codec *codec)
-@@ -3004,7 +3011,8 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
+@@ -3004,7 +3019,8 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
*/
static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb};
@@ -161007,7 +248850,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
}
static int patch_i915_tgl_hdmi(struct hda_codec *codec)
-@@ -3016,7 +3024,8 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec)
+@@ -3016,7 +3032,8 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec)
static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
int ret;
@@ -161017,7 +248860,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
if (!ret) {
struct hdmi_spec *spec = codec->spec;
-@@ -4380,10 +4389,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
+@@ -4380,10 +4397,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi),
@@ -161031,7 +248874,7 @@ index 65d2c55399195..ffcde7409d2a5 100644
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
-index 965b096f416f6..83b56c1ba3996 100644
+index 965b096f416f6..040825ea9a089 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -97,6 +97,7 @@ struct alc_spec {
@@ -161152,7 +248995,37 @@ index 965b096f416f6..83b56c1ba3996 100644
}
/*
-@@ -1148,6 +1195,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
+@@ -885,6 +932,9 @@ static int alc_init(struct hda_codec *codec)
+ return 0;
+ }
+
++#define alc_free snd_hda_gen_free
++
++#ifdef CONFIG_PM
+ static inline void alc_shutup(struct hda_codec *codec)
+ {
+ struct alc_spec *spec = codec->spec;
+@@ -898,9 +948,6 @@ static inline void alc_shutup(struct hda_codec *codec)
+ alc_shutup_pins(codec);
+ }
+
+-#define alc_free snd_hda_gen_free
+-
+-#ifdef CONFIG_PM
+ static void alc_power_eapd(struct hda_codec *codec)
+ {
+ alc_auto_setup_eapd(codec, false);
+@@ -914,9 +961,7 @@ static int alc_suspend(struct hda_codec *codec)
+ spec->power_hook(codec);
+ return 0;
+ }
+-#endif
+
+-#ifdef CONFIG_PM
+ static int alc_resume(struct hda_codec *codec)
+ {
+ struct alc_spec *spec = codec->spec;
+@@ -1148,6 +1193,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
codec->spdif_status_reset = 1;
codec->forced_resume = 1;
codec->patch_ops = alc_patch_ops;
@@ -161160,7 +249033,7 @@ index 965b096f416f6..83b56c1ba3996 100644
err = alc_codec_rename_from_preset(codec);
if (err < 0) {
-@@ -1924,6 +1972,7 @@ enum {
+@@ -1924,6 +1970,7 @@ enum {
ALC887_FIXUP_ASUS_BASS,
ALC887_FIXUP_BASS_CHMAP,
ALC1220_FIXUP_GB_DUAL_CODECS,
@@ -161168,7 +249041,7 @@ index 965b096f416f6..83b56c1ba3996 100644
ALC1220_FIXUP_CLEVO_P950,
ALC1220_FIXUP_CLEVO_PB51ED,
ALC1220_FIXUP_CLEVO_PB51ED_PINS,
-@@ -2113,6 +2162,30 @@ static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
+@@ -2113,6 +2160,30 @@ static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
}
}
@@ -161199,7 +249072,7 @@ index 965b096f416f6..83b56c1ba3996 100644
static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
-@@ -2415,6 +2488,10 @@ static const struct hda_fixup alc882_fixups[] = {
+@@ -2415,6 +2486,10 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_gb_dual_codecs,
},
@@ -161210,7 +249083,7 @@ index 965b096f416f6..83b56c1ba3996 100644
[ALC1220_FIXUP_CLEVO_P950] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_p950,
-@@ -2517,8 +2594,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+@@ -2517,8 +2592,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
@@ -161222,7 +249095,11 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950),
-@@ -2539,6 +2617,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+@@ -2536,9 +2612,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
++ SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
@@ -161230,7 +249107,7 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
-@@ -2592,6 +2671,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
+@@ -2592,6 +2670,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
{.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
{.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"},
{.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
@@ -161238,7 +249115,18 @@ index 965b096f416f6..83b56c1ba3996 100644
{.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
{}
};
-@@ -4355,6 +4435,16 @@ static void alc287_fixup_hp_gpio_led(struct hda_codec *codec,
+@@ -3532,8 +3611,8 @@ static void alc256_shutup(struct hda_codec *codec)
+ /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
+ * when booting with headset plugged. So skip setting it for the codec alc257
+ */
+- if (spec->codec_variant != ALC269_TYPE_ALC257 &&
+- spec->codec_variant != ALC269_TYPE_ALC256)
++ if (codec->core.vendor_id != 0x10ec0236 &&
++ codec->core.vendor_id != 0x10ec0257)
+ alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
+
+ if (!spec->no_shutup_pins)
+@@ -4355,6 +4434,16 @@ static void alc287_fixup_hp_gpio_led(struct hda_codec *codec,
alc_fixup_hp_gpio_led(codec, action, 0x10, 0);
}
@@ -161255,7 +249143,7 @@ index 965b096f416f6..83b56c1ba3996 100644
/* turn on/off mic-mute LED per capture hook via VREF change */
static int vref_micmute_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
-@@ -6492,22 +6582,64 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
+@@ -6492,22 +6581,64 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
/* for alc285_fixup_ideapad_s740_coef() */
#include "ideapad_s740_helper.c"
@@ -161334,6 +249222,14 @@ index 965b096f416f6..83b56c1ba3996 100644
}
enum {
+@@ -6684,6 +6815,7 @@ enum {
+ ALC236_FIXUP_HP_MUTE_LED,
+ ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+ ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
++ ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+ ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
+ ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS,
+ ALC269VC_FIXUP_ACER_HEADSET_MIC,
@@ -6709,6 +6841,7 @@ enum {
ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
ALC287_FIXUP_HP_GPIO_LED,
@@ -161365,7 +249261,22 @@ index 965b096f416f6..83b56c1ba3996 100644
},
[ALC288_FIXUP_DELL_HEADSET_MODE] = {
.type = HDA_FIXUP_FUNC,
-@@ -8321,6 +8461,18 @@ static const struct hda_fixup alc269_fixups[] = {
+@@ -7998,6 +8138,14 @@ static const struct hda_fixup alc269_fixups[] = {
+ { }
+ },
+ },
++ [ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
++ .type = HDA_FIXUP_VERBS,
++ .v.verbs = (const struct hda_verb[]) {
++ { 0x20, AC_VERB_SET_COEF_INDEX, 0x08},
++ { 0x20, AC_VERB_SET_PROC_COEF, 0x2fcf},
++ { }
++ },
++ },
+ [ALC295_FIXUP_ASUS_MIC_NO_PRESENCE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+@@ -8321,6 +8469,18 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
},
@@ -161384,7 +249295,7 @@ index 965b096f416f6..83b56c1ba3996 100644
[ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS] = {
.type = HDA_FIXUP_VERBS,
//.v.verbs = legion_15imhg05_coefs,
-@@ -8428,9 +8580,32 @@ static const struct hda_fixup alc269_fixups[] = {
+@@ -8428,9 +8588,32 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE,
},
@@ -161419,7 +249330,7 @@ index 965b096f416f6..83b56c1ba3996 100644
},
};
-@@ -8468,6 +8643,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8468,6 +8651,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
@@ -161427,7 +249338,7 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
-@@ -8601,14 +8777,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8601,14 +8785,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
@@ -161445,7 +249356,7 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
-@@ -8617,6 +8796,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8617,6 +8804,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),
@@ -161453,7 +249364,7 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
-@@ -8643,6 +8823,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8643,6 +8831,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
@@ -161462,7 +249373,7 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-@@ -8668,6 +8850,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8668,6 +8858,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
@@ -161470,15 +249381,24 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE),
-@@ -8683,6 +8866,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8683,6 +8874,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
++ SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
+ SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
-@@ -8731,11 +8915,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8715,6 +8908,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
+ SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+ SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
++ SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+ SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+@@ -8731,11 +8925,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -161494,22 +249414,27 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
-@@ -8762,7 +8950,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8761,8 +8959,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1558, 0x8561, "Clevo NH[57][0-9][ER][ACDH]Q", ALC269_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[57][0-9]RZ[Q]", ALC269_FIXUP_DMIC),
SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1558, 0x866d, "Clevo NP5[05]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1558, 0x867c, "Clevo NP7[01]PNP", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1558, 0x867d, "Clevo NP7[01]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME),
SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
-@@ -8828,13 +9016,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8828,13 +9029,18 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
+ SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
+ SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
++ SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
+ SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
@@ -161523,7 +249448,12 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
-@@ -8858,6 +9050,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8854,10 +9060,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x505d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x505f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x5062, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
++ SND_PCI_QUIRK(0x17aa, 0x508b, "Thinkpad X12 Gen 1", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -161531,16 +249461,32 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
-@@ -8865,7 +9058,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -8865,7 +9073,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
- SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS),
+ SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS),
++ SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1111, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1119, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1129, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1147, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
-@@ -9055,6 +9248,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
+@@ -9046,6 +9262,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
+ {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
+ {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
+ {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
++ {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
+ {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
+ {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
+ {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"},
+@@ -9055,6 +9272,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"},
{.id = ALC623_FIXUP_LENOVO_THINKSTATION_P340, .name = "alc623-lenovo-thinkstation-p340"},
{.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"},
@@ -161548,7 +249494,7 @@ index 965b096f416f6..83b56c1ba3996 100644
{}
};
#define ALC225_STANDARD_PINS \
-@@ -10167,6 +10361,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
+@@ -10167,6 +10385,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
}
}
@@ -161576,7 +249522,7 @@ index 965b096f416f6..83b56c1ba3996 100644
static const struct coef_fw alc668_coefs[] = {
WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
-@@ -10247,6 +10462,8 @@ enum {
+@@ -10247,6 +10486,8 @@ enum {
ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
ALC668_FIXUP_HEADSET_MIC,
ALC668_FIXUP_MIC_DET_COEF,
@@ -161585,7 +249531,7 @@ index 965b096f416f6..83b56c1ba3996 100644
};
static const struct hda_fixup alc662_fixups[] = {
-@@ -10653,6 +10870,19 @@ static const struct hda_fixup alc662_fixups[] = {
+@@ -10653,6 +10894,19 @@ static const struct hda_fixup alc662_fixups[] = {
{}
},
},
@@ -161605,10 +249551,19 @@ index 965b096f416f6..83b56c1ba3996 100644
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
-@@ -10697,6 +10927,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
+@@ -10679,6 +10933,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+ SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
++ SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
+ SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
+ SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
+ SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
+@@ -10697,6 +10952,11 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
++ SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
@@ -161616,8 +249571,336 @@ index 965b096f416f6..83b56c1ba3996 100644
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
+diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
+index f6275868877a7..6fab2ad85bbec 100644
+--- a/sound/pci/ice1712/ice1724.c
++++ b/sound/pci/ice1712/ice1724.c
+@@ -2519,8 +2519,8 @@ static int snd_vt1724_create(struct snd_card *card,
+ *
+ */
+
+-static int snd_vt1724_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_vt1724_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2662,6 +2662,12 @@ static int snd_vt1724_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_vt1724_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_vt1724_probe(pci, pci_id));
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static int snd_vt1724_suspend(struct device *dev)
+ {
+diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
+index a51032b3ac4d8..ae285c0a629c8 100644
+--- a/sound/pci/intel8x0.c
++++ b/sound/pci/intel8x0.c
+@@ -3109,8 +3109,8 @@ static int check_default_spdif_aclink(struct pci_dev *pci)
+ return 0;
+ }
+
+-static int snd_intel8x0_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_intel8x0_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct intel8x0 *chip;
+@@ -3189,6 +3189,12 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_intel8x0_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_intel8x0_probe(pci, pci_id));
++}
++
+ static struct pci_driver intel8x0_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_intel8x0_ids,
+diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
+index 7de3cb2f17b52..2845cc006d0cf 100644
+--- a/sound/pci/intel8x0m.c
++++ b/sound/pci/intel8x0m.c
+@@ -1178,8 +1178,8 @@ static struct shortname_table {
+ { 0 },
+ };
+
+-static int snd_intel8x0m_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_intel8x0m_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct intel8x0m *chip;
+@@ -1225,6 +1225,12 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_intel8x0m_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_intel8x0m_probe(pci, pci_id));
++}
++
+ static struct pci_driver intel8x0m_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_intel8x0m_ids,
+diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
+index 5c9e240ff6a9c..33b4f95d65b3f 100644
+--- a/sound/pci/korg1212/korg1212.c
++++ b/sound/pci/korg1212/korg1212.c
+@@ -2355,7 +2355,7 @@ snd_korg1212_probe(struct pci_dev *pci,
+
+ err = snd_korg1212_create(card, pci);
+ if (err < 0)
+- return err;
++ goto error;
+
+ strcpy(card->driver, "korg1212");
+ strcpy(card->shortname, "korg1212");
+@@ -2366,10 +2366,14 @@ snd_korg1212_probe(struct pci_dev *pci,
+
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver korg1212_driver = {
+diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
+index 5269a1d396a5b..1aa30e90b86a7 100644
+--- a/sound/pci/lola/lola.c
++++ b/sound/pci/lola/lola.c
+@@ -637,8 +637,8 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
+ return 0;
+ }
+
+-static int lola_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __lola_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -687,6 +687,12 @@ static int lola_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int lola_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __lola_probe(pci, pci_id));
++}
++
+ /* PCI IDs */
+ static const struct pci_device_id lola_ids[] = {
+ { PCI_VDEVICE(DIGIGRAM, 0x0001) },
+diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
+index 168a1084f7303..bd9b6148dd6fb 100644
+--- a/sound/pci/lx6464es/lx6464es.c
++++ b/sound/pci/lx6464es/lx6464es.c
+@@ -1019,7 +1019,7 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
+ err = snd_lx6464es_create(card, pci);
+ if (err < 0) {
+ dev_err(card->dev, "error during snd_lx6464es_create\n");
+- return err;
++ goto error;
+ }
+
+ strcpy(card->driver, "LX6464ES");
+@@ -1036,12 +1036,16 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
+
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+
+ dev_dbg(chip->card->dev, "initialization successful\n");
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver lx6464es_driver = {
+diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
+index 056838ead21d6..261850775c807 100644
+--- a/sound/pci/maestro3.c
++++ b/sound/pci/maestro3.c
+@@ -2637,7 +2637,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
+ /*
+ */
+ static int
+-snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++__snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2702,6 +2702,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ return 0;
+ }
+
++static int
++snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_m3_probe(pci, pci_id));
++}
++
+ static struct pci_driver m3_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_m3_ids,
+diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
+index c9c178504959e..f99a1e96e9231 100644
+--- a/sound/pci/nm256/nm256.c
++++ b/sound/pci/nm256/nm256.c
+@@ -1573,7 +1573,6 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
+ chip->coeffs_current = 0;
+
+ snd_nm256_init_chip(chip);
+- card->private_free = snd_nm256_free;
+
+ // pci_set_master(pci); /* needed? */
+ return 0;
+@@ -1680,6 +1679,7 @@ static int snd_nm256_probe(struct pci_dev *pci,
+ err = snd_card_register(card);
+ if (err < 0)
+ return err;
++ card->private_free = snd_nm256_free;
+
+ pci_set_drvdata(pci, card);
+ return 0;
+diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
+index 4fb3f2484fdba..92ffe9dc20c55 100644
+--- a/sound/pci/oxygen/oxygen_lib.c
++++ b/sound/pci/oxygen/oxygen_lib.c
+@@ -576,7 +576,7 @@ static void oxygen_card_free(struct snd_card *card)
+ mutex_destroy(&chip->mutex);
+ }
+
+-int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
++static int __oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ struct module *owner,
+ const struct pci_device_id *ids,
+ int (*get_model)(struct oxygen *chip,
+@@ -701,6 +701,16 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ pci_set_drvdata(pci, card);
+ return 0;
+ }
++
++int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
++ struct module *owner,
++ const struct pci_device_id *ids,
++ int (*get_model)(struct oxygen *chip,
++ const struct pci_device_id *id))
++{
++ return snd_card_free_on_error(&pci->dev,
++ __oxygen_pci_probe(pci, index, id, owner, ids, get_model));
++}
+ EXPORT_SYMBOL(oxygen_pci_probe);
+
+ #ifdef CONFIG_PM_SLEEP
+diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
+index 5a987c683c41c..b37c877c2c160 100644
+--- a/sound/pci/riptide/riptide.c
++++ b/sound/pci/riptide/riptide.c
+@@ -2023,7 +2023,7 @@ static void snd_riptide_joystick_remove(struct pci_dev *pci)
+ #endif
+
+ static int
+-snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++__snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -2124,6 +2124,12 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ return 0;
+ }
+
++static int
++snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_card_riptide_probe(pci, pci_id));
++}
++
+ static struct pci_driver driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_riptide_ids,
+diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
+index 5b6bd9f0b2f77..9c0ac025e1432 100644
+--- a/sound/pci/rme32.c
++++ b/sound/pci/rme32.c
+@@ -1875,7 +1875,7 @@ static void snd_rme32_card_free(struct snd_card *card)
+ }
+
+ static int
+-snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++__snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct rme32 *rme32;
+@@ -1927,6 +1927,12 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ return 0;
+ }
+
++static int
++snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_rme32_probe(pci, pci_id));
++}
++
+ static struct pci_driver rme32_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_rme32_ids,
+diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
+index 8fc8115049203..bccb7e0d3d116 100644
+--- a/sound/pci/rme96.c
++++ b/sound/pci/rme96.c
+@@ -2430,8 +2430,8 @@ static void snd_rme96_card_free(struct snd_card *card)
+ }
+
+ static int
+-snd_rme96_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++__snd_rme96_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct rme96 *rme96;
+@@ -2498,6 +2498,12 @@ snd_rme96_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_rme96_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_rme96_probe(pci, pci_id));
++}
++
+ static struct pci_driver rme96_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_rme96_ids,
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
-index 75aa2ea733a59..96c12dfb24cf9 100644
+index 75aa2ea733a59..3db641318d3ae 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -468,8 +468,11 @@ struct hdsp {
@@ -161699,8 +249982,63 @@ index 75aa2ea733a59..96c12dfb24cf9 100644
hdsp->capture_pid = current->pid;
hdsp->capture_substream = substream;
+@@ -5439,17 +5444,21 @@ static int snd_hdsp_probe(struct pci_dev *pci,
+ hdsp->pci = pci;
+ err = snd_hdsp_create(card, hdsp);
+ if (err)
+- return err;
++ goto error;
+
+ strcpy(card->shortname, "Hammerfall DSP");
+ sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
+ hdsp->port, hdsp->irq);
+ err = snd_card_register(card);
+ if (err)
+- return err;
++ goto error;
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver hdsp_driver = {
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index ff06ee82607cf..fa1812e7a49dc 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -6895,7 +6895,7 @@ static int snd_hdspm_probe(struct pci_dev *pci,
+
+ err = snd_hdspm_create(card, hdspm);
+ if (err < 0)
+- return err;
++ goto error;
+
+ if (hdspm->io_type != MADIface) {
+ snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
+@@ -6914,12 +6914,16 @@ static int snd_hdspm_probe(struct pci_dev *pci,
+
+ err = snd_card_register(card);
+ if (err < 0)
+- return err;
++ goto error;
+
+ pci_set_drvdata(pci, card);
+
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver hdspm_driver = {
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
-index e76f737ac9e8e..7755e19aa7761 100644
+index e76f737ac9e8e..1d614fe89a6ae 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -208,8 +208,11 @@ struct snd_rme9652 {
@@ -161782,8 +250120,479 @@ index e76f737ac9e8e..7755e19aa7761 100644
if (rme9652->playback_substream == NULL) {
rme9652_stop(rme9652);
+@@ -2567,7 +2572,7 @@ static int snd_rme9652_probe(struct pci_dev *pci,
+ rme9652->pci = pci;
+ err = snd_rme9652_create(card, rme9652, precise_ptr[dev]);
+ if (err)
+- return err;
++ goto error;
+
+ strcpy(card->shortname, rme9652->card_name);
+
+@@ -2575,10 +2580,14 @@ static int snd_rme9652_probe(struct pci_dev *pci,
+ card->shortname, rme9652->port, rme9652->irq);
+ err = snd_card_register(card);
+ if (err)
+- return err;
++ goto error;
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static struct pci_driver rme9652_driver = {
+diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
+index 0b722b0e0604b..fabe393607f8f 100644
+--- a/sound/pci/sis7019.c
++++ b/sound/pci/sis7019.c
+@@ -1331,8 +1331,8 @@ static int sis_chip_create(struct snd_card *card,
+ return 0;
+ }
+
+-static int snd_sis7019_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_sis7019_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct sis7019 *sis;
+@@ -1352,8 +1352,8 @@ static int snd_sis7019_probe(struct pci_dev *pci,
+ if (!codecs)
+ codecs = SIS_PRIMARY_CODEC_PRESENT;
+
+- rc = snd_card_new(&pci->dev, index, id, THIS_MODULE,
+- sizeof(*sis), &card);
++ rc = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
++ sizeof(*sis), &card);
+ if (rc < 0)
+ return rc;
+
+@@ -1386,6 +1386,12 @@ static int snd_sis7019_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_sis7019_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_sis7019_probe(pci, pci_id));
++}
++
+ static struct pci_driver sis7019_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_sis7019_ids,
+diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
+index c8c49881008fd..f91cbf6eeca0f 100644
+--- a/sound/pci/sonicvibes.c
++++ b/sound/pci/sonicvibes.c
+@@ -1387,8 +1387,8 @@ static int snd_sonicvibes_midi(struct sonicvibes *sonic,
+ return 0;
+ }
+
+-static int snd_sonic_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_sonic_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+@@ -1459,6 +1459,12 @@ static int snd_sonic_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_sonic_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_sonic_probe(pci, pci_id));
++}
++
+ static struct pci_driver sonicvibes_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_sonic_ids,
+diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
+index 65514f7e42d7d..361b83fd721e6 100644
+--- a/sound/pci/via82xx.c
++++ b/sound/pci/via82xx.c
+@@ -2458,8 +2458,8 @@ static int check_dxs_list(struct pci_dev *pci, int revision)
+ return VIA_DXS_48K;
+ };
+
+-static int snd_via82xx_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_via82xx_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct via82xx *chip;
+@@ -2569,6 +2569,12 @@ static int snd_via82xx_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_via82xx_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_via82xx_probe(pci, pci_id));
++}
++
+ static struct pci_driver via82xx_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_via82xx_ids,
+diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
+index 234f7fbed2364..ca7f024bf8ec6 100644
+--- a/sound/pci/via82xx_modem.c
++++ b/sound/pci/via82xx_modem.c
+@@ -1103,8 +1103,8 @@ static int snd_via82xx_create(struct snd_card *card,
+ }
+
+
+-static int snd_via82xx_probe(struct pci_dev *pci,
+- const struct pci_device_id *pci_id)
++static int __snd_via82xx_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
+ {
+ struct snd_card *card;
+ struct via82xx_modem *chip;
+@@ -1157,6 +1157,12 @@ static int snd_via82xx_probe(struct pci_dev *pci,
+ return 0;
+ }
+
++static int snd_via82xx_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ return snd_card_free_on_error(&pci->dev, __snd_via82xx_probe(pci, pci_id));
++}
++
+ static struct pci_driver via82xx_modem_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_via82xx_modem_ids,
+diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
+index f10de38976cb5..bfca4cf423cf1 100644
+--- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c
++++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
+@@ -281,7 +281,7 @@ static int acp5x_dma_hw_params(struct snd_soc_component *component,
+ return -EINVAL;
+ }
+ size = params_buffer_bytes(params);
+- rtd->dma_addr = substream->dma_buffer.addr;
++ rtd->dma_addr = substream->runtime->dma_addr;
+ rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+ config_acp5x_dma(rtd, substream->stream);
+ return 0;
+@@ -426,51 +426,51 @@ static int acp5x_audio_remove(struct platform_device *pdev)
+ static int __maybe_unused acp5x_pcm_resume(struct device *dev)
+ {
+ struct i2s_dev_data *adata;
+- u32 val, reg_val, frmt_val;
++ struct i2s_stream_instance *rtd;
++ u32 val;
+
+- reg_val = 0;
+- frmt_val = 0;
+ adata = dev_get_drvdata(dev);
+
+ if (adata->play_stream && adata->play_stream->runtime) {
+- struct i2s_stream_instance *rtd =
+- adata->play_stream->runtime->private_data;
++ rtd = adata->play_stream->runtime->private_data;
+ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
+- switch (rtd->i2s_instance) {
+- case I2S_HS_INSTANCE:
+- reg_val = ACP_HSTDM_ITER;
+- frmt_val = ACP_HSTDM_TXFRMT;
+- break;
+- case I2S_SP_INSTANCE:
+- default:
+- reg_val = ACP_I2STDM_ITER;
+- frmt_val = ACP_I2STDM_TXFRMT;
++ acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_HSTDM_ITER);
++ if (adata->tdm_mode == TDM_ENABLE) {
++ acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_HSTDM_TXFRMT);
++ val = acp_readl(adata->acp5x_base + ACP_HSTDM_ITER);
++ acp_writel(val | 0x2, adata->acp5x_base + ACP_HSTDM_ITER);
++ }
++ }
++ if (adata->i2ssp_play_stream && adata->i2ssp_play_stream->runtime) {
++ rtd = adata->i2ssp_play_stream->runtime->private_data;
++ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
++ acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_I2STDM_ITER);
++ if (adata->tdm_mode == TDM_ENABLE) {
++ acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_I2STDM_TXFRMT);
++ val = acp_readl(adata->acp5x_base + ACP_I2STDM_ITER);
++ acp_writel(val | 0x2, adata->acp5x_base + ACP_I2STDM_ITER);
+ }
+- acp_writel((rtd->xfer_resolution << 3),
+- rtd->acp5x_base + reg_val);
+ }
+
+ if (adata->capture_stream && adata->capture_stream->runtime) {
+- struct i2s_stream_instance *rtd =
+- adata->capture_stream->runtime->private_data;
++ rtd = adata->capture_stream->runtime->private_data;
+ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
+- switch (rtd->i2s_instance) {
+- case I2S_HS_INSTANCE:
+- reg_val = ACP_HSTDM_IRER;
+- frmt_val = ACP_HSTDM_RXFRMT;
+- break;
+- case I2S_SP_INSTANCE:
+- default:
+- reg_val = ACP_I2STDM_IRER;
+- frmt_val = ACP_I2STDM_RXFRMT;
++ acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_HSTDM_IRER);
++ if (adata->tdm_mode == TDM_ENABLE) {
++ acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_HSTDM_RXFRMT);
++ val = acp_readl(adata->acp5x_base + ACP_HSTDM_IRER);
++ acp_writel(val | 0x2, adata->acp5x_base + ACP_HSTDM_IRER);
+ }
+- acp_writel((rtd->xfer_resolution << 3),
+- rtd->acp5x_base + reg_val);
+ }
+- if (adata->tdm_mode == TDM_ENABLE) {
+- acp_writel(adata->tdm_fmt, adata->acp5x_base + frmt_val);
+- val = acp_readl(adata->acp5x_base + reg_val);
+- acp_writel(val | 0x2, adata->acp5x_base + reg_val);
++ if (adata->i2ssp_capture_stream && adata->i2ssp_capture_stream->runtime) {
++ rtd = adata->i2ssp_capture_stream->runtime->private_data;
++ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
++ acp_writel((rtd->xfer_resolution << 3), rtd->acp5x_base + ACP_I2STDM_IRER);
++ if (adata->tdm_mode == TDM_ENABLE) {
++ acp_writel(adata->tdm_fmt, adata->acp5x_base + ACP_I2STDM_RXFRMT);
++ val = acp_readl(adata->acp5x_base + ACP_I2STDM_IRER);
++ acp_writel(val | 0x2, adata->acp5x_base + ACP_I2STDM_IRER);
++ }
+ }
+ acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+ return 0;
+diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
+index 6a63e8797a0b6..97533412ce11e 100644
+--- a/sound/soc/atmel/atmel_ssc_dai.c
++++ b/sound/soc/atmel/atmel_ssc_dai.c
+@@ -280,7 +280,10 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
+
+ /* Enable PMC peripheral clock for this SSC */
+ pr_debug("atmel_ssc_dai: Starting clock\n");
+- clk_enable(ssc_p->ssc->clk);
++ ret = clk_enable(ssc_p->ssc->clk);
++ if (ret)
++ return ret;
++
+ ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
+
+ /* Reset the SSC unless initialized to keep it in a clean state */
+diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c
+index 0be7b4221c146..93d114f5b9e6a 100644
+--- a/sound/soc/atmel/mikroe-proto.c
++++ b/sound/soc/atmel/mikroe-proto.c
+@@ -115,7 +115,8 @@ static int snd_proto_probe(struct platform_device *pdev)
+ cpu_np = of_parse_phandle(np, "i2s-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "i2s-controller missing\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto put_codec_node;
+ }
+ dai->cpus->of_node = cpu_np;
+ dai->platforms->of_node = cpu_np;
+@@ -125,7 +126,8 @@ static int snd_proto_probe(struct platform_device *pdev)
+ &bitclkmaster, &framemaster);
+ if (bitclkmaster != framemaster) {
+ dev_err(&pdev->dev, "Must be the same bitclock and frame master\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto put_cpu_node;
+ }
+ if (bitclkmaster) {
+ if (codec_np == bitclkmaster)
+@@ -136,18 +138,20 @@ static int snd_proto_probe(struct platform_device *pdev)
+ dai_fmt |= snd_soc_daifmt_parse_clock_provider_as_flag(np, NULL);
+ }
+
+- of_node_put(bitclkmaster);
+- of_node_put(framemaster);
+- dai->dai_fmt = dai_fmt;
+-
+- of_node_put(codec_np);
+- of_node_put(cpu_np);
+
++ dai->dai_fmt = dai_fmt;
+ ret = snd_soc_register_card(&snd_proto);
+ if (ret && ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "snd_soc_register_card() failed: %d\n", ret);
+
++
++put_cpu_node:
++ of_node_put(bitclkmaster);
++ of_node_put(framemaster);
++ of_node_put(cpu_np);
++put_codec_node:
++ of_node_put(codec_np);
+ return ret;
+ }
+
+diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
+index ed1f69b570244..d243de5f23dc1 100644
+--- a/sound/soc/atmel/sam9g20_wm8731.c
++++ b/sound/soc/atmel/sam9g20_wm8731.c
+@@ -46,35 +46,6 @@
+ */
+ #undef ENABLE_MIC_INPUT
+
+-static struct clk *mclk;
+-
+-static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
+- struct snd_soc_dapm_context *dapm,
+- enum snd_soc_bias_level level)
+-{
+- static int mclk_on;
+- int ret = 0;
+-
+- switch (level) {
+- case SND_SOC_BIAS_ON:
+- case SND_SOC_BIAS_PREPARE:
+- if (!mclk_on)
+- ret = clk_enable(mclk);
+- if (ret == 0)
+- mclk_on = 1;
+- break;
+-
+- case SND_SOC_BIAS_OFF:
+- case SND_SOC_BIAS_STANDBY:
+- if (mclk_on)
+- clk_disable(mclk);
+- mclk_on = 0;
+- break;
+- }
+-
+- return ret;
+-}
+-
+ static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Int Mic", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+@@ -135,7 +106,6 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
+ .owner = THIS_MODULE,
+ .dai_link = &at91sam9g20ek_dai,
+ .num_links = 1,
+- .set_bias_level = at91sam9g20ek_set_bias_level,
+
+ .dapm_widgets = at91sam9g20ek_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
+@@ -148,7 +118,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
+ {
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *codec_np, *cpu_np;
+- struct clk *pllb;
+ struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
+ int ret;
+
+@@ -162,31 +131,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
+ return -EINVAL;
+ }
+
+- /*
+- * Codec MCLK is supplied by PCK0 - set it up.
+- */
+- mclk = clk_get(NULL, "pck0");
+- if (IS_ERR(mclk)) {
+- dev_err(&pdev->dev, "Failed to get MCLK\n");
+- ret = PTR_ERR(mclk);
+- goto err;
+- }
+-
+- pllb = clk_get(NULL, "pllb");
+- if (IS_ERR(pllb)) {
+- dev_err(&pdev->dev, "Failed to get PLLB\n");
+- ret = PTR_ERR(pllb);
+- goto err_mclk;
+- }
+- ret = clk_set_parent(mclk, pllb);
+- clk_put(pllb);
+- if (ret != 0) {
+- dev_err(&pdev->dev, "Failed to set MCLK parent\n");
+- goto err_mclk;
+- }
+-
+- clk_set_rate(mclk, MCLK_RATE);
+-
+ card->dev = &pdev->dev;
+
+ /* Parse device node info */
+@@ -214,6 +158,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
+ cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "dai and pcm info missing\n");
++ of_node_put(codec_np);
+ return -EINVAL;
+ }
+ at91sam9g20ek_dai.cpus->of_node = cpu_np;
+@@ -229,9 +174,6 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
+
+ return ret;
+
+-err_mclk:
+- clk_put(mclk);
+- mclk = NULL;
+ err:
+ atmel_ssc_put_audio(0);
+ return ret;
+@@ -241,8 +183,6 @@ static int at91sam9g20ek_audio_remove(struct platform_device *pdev)
+ {
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+- clk_disable(mclk);
+- mclk = NULL;
+ snd_soc_unregister_card(card);
+ atmel_ssc_put_audio(0);
+
+diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c
+index 7745250fd7438..529604a06c532 100644
+--- a/sound/soc/atmel/sam9x5_wm8731.c
++++ b/sound/soc/atmel/sam9x5_wm8731.c
+@@ -142,7 +142,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "atmel,ssc-controller node missing\n");
+ ret = -EINVAL;
+- goto out;
++ goto out_put_codec_np;
+ }
+ dai->cpus->of_node = cpu_np;
+ dai->platforms->of_node = cpu_np;
+@@ -153,12 +153,9 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to set SSC %d for audio: %d\n",
+ ret, priv->ssc_id);
+- goto out;
++ goto out_put_cpu_np;
+ }
+
+- of_node_put(codec_np);
+- of_node_put(cpu_np);
+-
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret) {
+ dev_err(&pdev->dev, "Platform device allocation failed\n");
+@@ -167,10 +164,14 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
+
+ dev_dbg(&pdev->dev, "%s ok\n", __func__);
+
+- return ret;
++ goto out_put_cpu_np;
+
+ out_put_audio:
+ atmel_ssc_put_audio(priv->ssc_id);
++out_put_cpu_np:
++ of_node_put(cpu_np);
++out_put_codec_np:
++ of_node_put(codec_np);
+ out:
+ return ret;
+ }
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
-index 216cea04ad704..f12c9b9426788 100644
+index 216cea04ad704..47e675e8bd006 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -235,8 +235,7 @@ config SND_SOC_ALL_CODECS
@@ -161796,6 +250605,34 @@ index 216cea04ad704..f12c9b9426788 100644
imply SND_SOC_LPASS_RX_MACRO
imply SND_SOC_LPASS_TX_MACRO
imply SND_SOC_WL1273
+@@ -691,6 +690,7 @@ config SND_SOC_CS4349
+
+ config SND_SOC_CS47L15
+ tristate
++ depends on MFD_CS47L15
+
+ config SND_SOC_CS47L24
+ tristate
+@@ -698,15 +698,19 @@ config SND_SOC_CS47L24
+
+ config SND_SOC_CS47L35
+ tristate
++ depends on MFD_CS47L35
+
+ config SND_SOC_CS47L85
+ tristate
++ depends on MFD_CS47L85
+
+ config SND_SOC_CS47L90
+ tristate
++ depends on MFD_CS47L90
+
+ config SND_SOC_CS47L92
+ tristate
++ depends on MFD_CS47L92
+
+ # Cirrus Logic Quad-Channel ADC
+ config SND_SOC_CS53L30
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index 05bbacd0d174d..f1c13f42e1c14 100644
--- a/sound/soc/codecs/cpcap.c
@@ -161908,6 +250745,42 @@ index 9a463ab54bddc..762d9de73dbc2 100644
dev_err(&i2c_client->dev,
"Failed to request IRQ: %d\n", ret);
+diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
+index 13009d08b09ac..c7493549a9a50 100644
+--- a/sound/soc/codecs/da7219.c
++++ b/sound/soc/codecs/da7219.c
+@@ -446,7 +446,7 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol,
+ struct soc_mixer_control *mixer_ctrl =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ unsigned int reg = mixer_ctrl->reg;
+- __le16 val;
++ __le16 val_new, val_old;
+ int ret;
+
+ /*
+@@ -454,13 +454,19 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol,
+ * Therefore we need to convert to little endian here to align with
+ * HW registers.
+ */
+- val = cpu_to_le16(ucontrol->value.integer.value[0]);
++ val_new = cpu_to_le16(ucontrol->value.integer.value[0]);
+
+ mutex_lock(&da7219->ctrl_lock);
+- ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val));
++ ret = regmap_raw_read(da7219->regmap, reg, &val_old, sizeof(val_old));
++ if (ret == 0 && (val_old != val_new))
++ ret = regmap_raw_write(da7219->regmap, reg,
++ &val_new, sizeof(val_new));
+ mutex_unlock(&da7219->ctrl_lock);
+
+- return ret;
++ if (ret < 0)
++ return ret;
++
++ return val_old != val_new;
+ }
+
+
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 067757d1d70a3..5fb02635c1406 100644
--- a/sound/soc/codecs/es8316.c
@@ -161941,10 +250814,21 @@ index b61f980cabdc0..b07607a9ecea4 100644
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
-index 196b06898eeb2..1c0409350e869 100644
+index 196b06898eeb2..23452900b9ae1 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
-@@ -2188,7 +2188,7 @@ static int rx_macro_config_classh(struct snd_soc_component *component,
+@@ -2039,6 +2039,10 @@ static int rx_macro_load_compander_coeff(struct snd_soc_component *component,
+ int i;
+ int hph_pwr_mode;
+
++ /* AUX does not have compander */
++ if (comp == INTERP_AUX)
++ return 0;
++
+ if (!rx->comp_enabled[comp])
+ return 0;
+
+@@ -2188,7 +2192,7 @@ static int rx_macro_config_classh(struct snd_soc_component *component,
snd_soc_component_update_bits(component,
CDC_RX_CLSH_DECAY_CTRL,
CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
@@ -161953,7 +250837,43 @@ index 196b06898eeb2..1c0409350e869 100644
CDC_RX_RX1_RX_PATH_CFG0,
CDC_RX_RXn_CLSH_EN_MASK, 0x1);
break;
-@@ -2688,8 +2688,8 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+@@ -2268,7 +2272,7 @@ static int rx_macro_mux_get(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+- ucontrol->value.integer.value[0] =
++ ucontrol->value.enumerated.item[0] =
+ rx->rx_port_value[widget->shift];
+ return 0;
+ }
+@@ -2280,7 +2284,7 @@ static int rx_macro_mux_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct snd_soc_dapm_update *update = NULL;
+- u32 rx_port_value = ucontrol->value.integer.value[0];
++ u32 rx_port_value = ucontrol->value.enumerated.item[0];
+ u32 aif_rst;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+@@ -2392,7 +2396,7 @@ static int rx_macro_get_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+- ucontrol->value.integer.value[0] = rx->hph_pwr_mode;
++ ucontrol->value.enumerated.item[0] = rx->hph_pwr_mode;
+ return 0;
+ }
+
+@@ -2402,7 +2406,7 @@ static int rx_macro_put_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+- rx->hph_pwr_mode = ucontrol->value.integer.value[0];
++ rx->hph_pwr_mode = ucontrol->value.enumerated.item[0];
+ return 0;
+ }
+
+@@ -2688,8 +2692,8 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
int reg, b2_reg;
/* Address does not automatically update if reading */
@@ -161964,7 +250884,7 @@ index 196b06898eeb2..1c0409350e869 100644
snd_soc_component_write(component, reg,
((band_idx * BAND_MAX + coeff_idx) *
-@@ -2718,7 +2718,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+@@ -2718,7 +2722,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
static void set_iir_band_coeff(struct snd_soc_component *component,
int iir_idx, int band_idx, uint32_t value)
{
@@ -161973,7 +250893,7 @@ index 196b06898eeb2..1c0409350e869 100644
snd_soc_component_write(component, reg, (value & 0xFF));
snd_soc_component_write(component, reg, (value >> 8) & 0xFF);
-@@ -2739,7 +2739,7 @@ static int rx_macro_put_iir_band_audio_mixer(
+@@ -2739,7 +2743,7 @@ static int rx_macro_put_iir_band_audio_mixer(
int iir_idx = ctl->iir_idx;
int band_idx = ctl->band_idx;
u32 coeff[BAND_MAX];
@@ -161982,6 +250902,63 @@ index 196b06898eeb2..1c0409350e869 100644
memcpy(&coeff[0], ucontrol->value.bytes.data, params->max);
+@@ -3542,6 +3546,8 @@ static int rx_macro_probe(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config);
++ if (IS_ERR(rx->regmap))
++ return PTR_ERR(rx->regmap);
+
+ dev_set_drvdata(dev, rx);
+
+diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
+index 27a0d5defd273..e4bbc6bd49252 100644
+--- a/sound/soc/codecs/lpass-tx-macro.c
++++ b/sound/soc/codecs/lpass-tx-macro.c
+@@ -1803,6 +1803,8 @@ static int tx_macro_probe(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ tx->regmap = devm_regmap_init_mmio(dev, base, &tx_regmap_config);
++ if (IS_ERR(tx->regmap))
++ return PTR_ERR(tx->regmap);
+
+ dev_set_drvdata(dev, tx);
+
+diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
+index 56c93f4465c9c..08702a21212c1 100644
+--- a/sound/soc/codecs/lpass-va-macro.c
++++ b/sound/soc/codecs/lpass-va-macro.c
+@@ -780,7 +780,7 @@ static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+
+- ucontrol->value.integer.value[0] = va->dec_mode[path];
++ ucontrol->value.enumerated.item[0] = va->dec_mode[path];
+
+ return 0;
+ }
+@@ -789,7 +789,7 @@ static int va_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+ struct va_macro *va = snd_soc_component_get_drvdata(comp);
+diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
+index d3ac318fd6b6a..dd1a8b7bc794c 100644
+--- a/sound/soc/codecs/lpass-wsa-macro.c
++++ b/sound/soc/codecs/lpass-wsa-macro.c
+@@ -2405,6 +2405,8 @@ static int wsa_macro_probe(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ wsa->regmap = devm_regmap_init_mmio(dev, base, &wsa_regmap_config);
++ if (IS_ERR(wsa->regmap))
++ return PTR_ERR(wsa->regmap);
+
+ dev_set_drvdata(dev, wsa);
+
diff --git a/sound/soc/codecs/max9759.c b/sound/soc/codecs/max9759.c
index 00e9d4fd1651f..0c261335c8a16 100644
--- a/sound/soc/codecs/max9759.c
@@ -161996,6 +250973,150 @@ index 00e9d4fd1651f..0c261335c8a16 100644
return -EINVAL;
priv->gain = ucontrol->value.integer.value[0];
+diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
+index b45ec35cd63c3..62b41ca050a20 100644
+--- a/sound/soc/codecs/max98090.c
++++ b/sound/soc/codecs/max98090.c
+@@ -413,6 +413,9 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
+
+ val = (val >> mc->shift) & mask;
+
++ if (sel < 0 || sel > mc->max)
++ return -EINVAL;
++
+ *select = sel;
+
+ /* Setting a volume is only valid if it is already On */
+@@ -427,7 +430,7 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
+ mask << mc->shift,
+ sel << mc->shift);
+
+- return 0;
++ return *select != val;
+ }
+
+ static const char *max98090_perf_pwr_text[] =
+diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
+index 3ddd822240e3a..971b8360b5b1b 100644
+--- a/sound/soc/codecs/msm8916-wcd-analog.c
++++ b/sound/soc/codecs/msm8916-wcd-analog.c
+@@ -1221,8 +1221,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
+ }
+
+ irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
+- if (irq < 0)
+- return irq;
++ if (irq < 0) {
++ ret = irq;
++ goto err_disable_clk;
++ }
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ pm8916_mbhc_switch_irq_handler,
+@@ -1234,8 +1236,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
+
+ if (priv->mbhc_btn_enabled) {
+ irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
+- if (irq < 0)
+- return irq;
++ if (irq < 0) {
++ ret = irq;
++ goto err_disable_clk;
++ }
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ mbhc_btn_press_irq_handler,
+@@ -1246,8 +1250,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
+ dev_err(dev, "cannot request mbhc button press irq\n");
+
+ irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
+- if (irq < 0)
+- return irq;
++ if (irq < 0) {
++ ret = irq;
++ goto err_disable_clk;
++ }
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ mbhc_btn_release_irq_handler,
+@@ -1264,6 +1270,10 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
+ return devm_snd_soc_register_component(dev, &pm8916_wcd_analog,
+ pm8916_wcd_analog_dai,
+ ARRAY_SIZE(pm8916_wcd_analog_dai));
++
++err_disable_clk:
++ clk_disable_unprepare(priv->mclk);
++ return ret;
+ }
+
+ static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev)
+diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c
+index fcc10c8bc6259..20a07c92b2fc2 100644
+--- a/sound/soc/codecs/msm8916-wcd-digital.c
++++ b/sound/soc/codecs/msm8916-wcd-digital.c
+@@ -1201,14 +1201,24 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable mclk %d\n", ret);
+- return ret;
++ goto err_clk;
+ }
+
+ dev_set_drvdata(dev, priv);
+
+- return devm_snd_soc_register_component(dev, &msm8916_wcd_digital,
++ ret = devm_snd_soc_register_component(dev, &msm8916_wcd_digital,
+ msm8916_wcd_digital_dai,
+ ARRAY_SIZE(msm8916_wcd_digital_dai));
++ if (ret)
++ goto err_mclk;
++
++ return 0;
++
++err_mclk:
++ clk_disable_unprepare(priv->mclk);
++err_clk:
++ clk_disable_unprepare(priv->ahbclk);
++ return ret;
+ }
+
+ static int msm8916_wcd_digital_remove(struct platform_device *pdev)
+diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c
+index 9b263a9a669dc..4c7b5d940799b 100644
+--- a/sound/soc/codecs/mt6358.c
++++ b/sound/soc/codecs/mt6358.c
+@@ -107,6 +107,7 @@ int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt,
+ priv->mtkaif_protocol = mtkaif_protocol;
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_protocol);
+
+ static void playback_gpio_set(struct mt6358_priv *priv)
+ {
+@@ -273,6 +274,7 @@ int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt)
+ 1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT);
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_enable);
+
+ int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt)
+ {
+@@ -296,6 +298,7 @@ int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt)
+ capture_gpio_reset(priv);
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_disable);
+
+ int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
+ int phase_1, int phase_2)
+@@ -310,6 +313,7 @@ int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt,
+ phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT);
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_calibration_phase);
+
+ /* dl pga gain */
+ enum {
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index f946ef65a4c19..f7018f2dd21fd 100644
--- a/sound/soc/codecs/nau8824.c
@@ -162069,10 +251190,36 @@ index f946ef65a4c19..f7018f2dd21fd 100644
ret = regmap_read(nau8824->regmap, NAU8824_REG_I2C_DEVICE_ID, &value);
diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c
-index 943d7d933e81b..03f24edfe4f64 100644
+index 943d7d933e81b..cce6f4e7992f5 100644
--- a/sound/soc/codecs/rk817_codec.c
+++ b/sound/soc/codecs/rk817_codec.c
-@@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver);
+@@ -489,7 +489,7 @@ static int rk817_platform_probe(struct platform_device *pdev)
+
+ rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data);
+
+- rk817_codec_data->mclk = clk_get(pdev->dev.parent, "mclk");
++ rk817_codec_data->mclk = devm_clk_get(pdev->dev.parent, "mclk");
+ if (IS_ERR(rk817_codec_data->mclk)) {
+ dev_dbg(&pdev->dev, "Unable to get mclk\n");
+ ret = -ENXIO;
+@@ -508,12 +508,14 @@ static int rk817_platform_probe(struct platform_device *pdev)
+ if (ret < 0) {
+ dev_err(&pdev->dev, "%s() register codec error %d\n",
+ __func__, ret);
+- goto err_;
++ goto err_clk;
+ }
+
+ return 0;
+-err_:
+
++err_clk:
++ clk_disable_unprepare(rk817_codec_data->mclk);
++err_:
+ return ret;
+ }
+
+@@ -539,3 +541,4 @@ module_platform_driver(rk817_codec_driver);
MODULE_DESCRIPTION("ASoC RK817 codec driver");
MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
MODULE_LICENSE("GPL v2");
@@ -162096,7 +251243,7 @@ index fc0c83b73f099..93820561b9f5d 100644
rt5651->irq, ret);
rt5651->irq = -ENXIO;
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c
-index be9fc58ff6812..ee09ccd448dcd 100644
+index be9fc58ff6812..4aba6e106ee46 100644
--- a/sound/soc/codecs/rt5663.c
+++ b/sound/soc/codecs/rt5663.c
@@ -3461,6 +3461,7 @@ static void rt5663_calibrate(struct rt5663_priv *rt5663)
@@ -162107,11 +251254,13 @@ index be9fc58ff6812..ee09ccd448dcd 100644
device_property_read_u32(dev, "realtek,dc_offset_l_manual",
&rt5663->pdata.dc_offset_l_manual);
-@@ -3477,9 +3478,11 @@ static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev)
+@@ -3477,9 +3478,13 @@ static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev)
table_size = sizeof(struct impedance_mapping_table) *
rt5663->pdata.impedance_sensing_num;
rt5663->imp_table = devm_kzalloc(dev, table_size, GFP_KERNEL);
- device_property_read_u32_array(dev,
++ if (!rt5663->imp_table)
++ return -ENOMEM;
+ ret = device_property_read_u32_array(dev,
"realtek,impedance_sensing_table",
(u32 *)rt5663->imp_table, table_size);
@@ -162120,7 +251269,7 @@ index be9fc58ff6812..ee09ccd448dcd 100644
}
return 0;
-@@ -3504,8 +3507,11 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
+@@ -3504,8 +3509,11 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5663->pdata = *pdata;
@@ -162441,10 +251590,50 @@ index d885ced34f606..bc5d68c53e5ab 100644
return PTR_ERR(wcd->clsh_ctrl);
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
-index c496b359f2f40..e63c6b723d76c 100644
+index c496b359f2f40..144046864d157 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
-@@ -1896,9 +1896,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream,
+@@ -1274,29 +1274,7 @@ static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
+ if (sido_src == wcd->sido_input_src)
+ return 0;
+
+- if (sido_src == SIDO_SOURCE_INTERNAL) {
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
+- WCD934X_ANA_BUCK_HI_ACCU_EN_MASK, 0);
+- usleep_range(100, 110);
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
+- WCD934X_ANA_BUCK_HI_ACCU_PRE_ENX_MASK, 0x0);
+- usleep_range(100, 110);
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
+- WCD934X_ANA_RCO_BG_EN_MASK, 0);
+- usleep_range(100, 110);
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
+- WCD934X_ANA_BUCK_PRE_EN1_MASK,
+- WCD934X_ANA_BUCK_PRE_EN1_ENABLE);
+- usleep_range(100, 110);
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
+- WCD934X_ANA_BUCK_PRE_EN2_MASK,
+- WCD934X_ANA_BUCK_PRE_EN2_ENABLE);
+- usleep_range(100, 110);
+- regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
+- WCD934X_ANA_BUCK_HI_ACCU_EN_MASK,
+- WCD934X_ANA_BUCK_HI_ACCU_ENABLE);
+- usleep_range(100, 110);
+- } else if (sido_src == SIDO_SOURCE_RCO_BG) {
++ if (sido_src == SIDO_SOURCE_RCO_BG) {
+ regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
+ WCD934X_ANA_RCO_BG_EN_MASK,
+ WCD934X_ANA_RCO_BG_ENABLE);
+@@ -1382,8 +1360,6 @@ static int wcd934x_disable_ana_bias_and_syclk(struct wcd934x_codec *wcd)
+ regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
+ WCD934X_EXT_CLK_BUF_EN_MASK |
+ WCD934X_MCLK_EN_MASK, 0x0);
+- wcd934x_set_sido_input_src(wcd, SIDO_SOURCE_INTERNAL);
+-
+ regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
+ WCD934X_ANA_BIAS_EN_MASK, 0);
+ regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
+@@ -1896,9 +1872,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream,
}
wcd->dai[dai->id].sconfig.rate = params_rate(params);
@@ -162455,7 +251644,25 @@ index c496b359f2f40..e63c6b723d76c 100644
}
static int wcd934x_hw_free(struct snd_pcm_substream *substream,
-@@ -3257,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
+@@ -3024,14 +2999,14 @@ static int wcd934x_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+ static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+- SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0,
+ wcd934x_get_hph_type, NULL),
+ };
+
+ static const struct snd_kcontrol_new impedance_detect_controls[] = {
+- SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0,
+ wcd934x_hph_impedance_get, NULL),
+- SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0,
+ wcd934x_hph_impedance_get, NULL),
+ };
+
+@@ -3257,6 +3232,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
int value = ucontrol->value.integer.value[0];
int sel;
@@ -162465,7 +251672,7 @@ index c496b359f2f40..e63c6b723d76c 100644
wcd->comp_enabled[comp] = value;
sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER :
WCD934X_HPH_GAIN_SRC_SEL_REGISTER;
-@@ -3280,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
+@@ -3280,10 +3258,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
case COMPANDER_8:
break;
default:
@@ -162478,7 +251685,25 @@ index c496b359f2f40..e63c6b723d76c 100644
}
static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc,
-@@ -3327,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc,
+@@ -3306,13 +3284,16 @@ static int wcd934x_rx_hph_mode_put(struct snd_kcontrol *kc,
+
+ mode_val = ucontrol->value.enumerated.item[0];
+
++ if (mode_val == wcd->hph_mode)
++ return 0;
++
+ if (mode_val == 0) {
+ dev_err(wcd->dev, "Invalid HPH Mode, default to ClSH HiFi\n");
+ mode_val = CLS_H_LOHIFI;
+ }
+ wcd->hph_mode = mode_val;
+
+- return 0;
++ return 1;
+ }
+
+ static int slim_rx_mux_get(struct snd_kcontrol *kc,
+@@ -3327,6 +3308,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc,
return 0;
}
@@ -162510,7 +251735,7 @@ index c496b359f2f40..e63c6b723d76c 100644
static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct snd_ctl_elem_value *ucontrol)
{
-@@ -3334,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
+@@ -3334,43 +3340,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);
struct soc_enum *e = (struct soc_enum *)kc->private_value;
struct snd_soc_dapm_update *update = NULL;
@@ -162593,7 +251818,7 @@ index c496b359f2f40..e63c6b723d76c 100644
err:
return -EINVAL;
}
-@@ -3816,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
+@@ -3816,6 +3838,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
struct soc_mixer_control *mixer =
(struct soc_mixer_control *)kc->private_value;
int enable = ucontrol->value.integer.value[0];
@@ -162601,7 +251826,7 @@ index c496b359f2f40..e63c6b723d76c 100644
int dai_id = widget->shift;
int port_id = mixer->shift;
-@@ -3823,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
+@@ -3823,17 +3846,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
if (enable == wcd->tx_port_value[port_id])
return 0;
@@ -162642,8 +251867,16 @@ index c496b359f2f40..e63c6b723d76c 100644
}
static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = {
+@@ -5826,6 +5864,7 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
+ }
+
+ wcd->sidev = of_slim_get_device(wcd->sdev->ctrl, ifc_dev_np);
++ of_node_put(ifc_dev_np);
+ if (!wcd->sidev) {
+ dev_err(dev, "Unable to get SLIM Interface device\n");
+ return -EINVAL;
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
-index 52de7d14b1398..bbc261ab2025b 100644
+index 52de7d14b1398..4480c118ed5d9 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -1174,6 +1174,9 @@ static bool wcd938x_readonly_register(struct device *dev, unsigned int reg)
@@ -162673,6 +251906,24 @@ index 52de7d14b1398..bbc261ab2025b 100644
enable);
}
+@@ -2505,7 +2504,7 @@ static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+
+- ucontrol->value.integer.value[0] = wcd938x->tx_mode[path];
++ ucontrol->value.enumerated.item[0] = wcd938x->tx_mode[path];
+
+ return 0;
+ }
+@@ -2529,7 +2528,7 @@ static int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+- ucontrol->value.integer.value[0] = wcd938x->hph_mode;
++ ucontrol->value.enumerated.item[0] = wcd938x->hph_mode;
+
+ return 0;
+ }
@@ -2560,7 +2559,7 @@ static int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol,
WCD938X_EAR_GAIN_MASK,
ucontrol->value.integer.value[0]);
@@ -162749,6 +252000,167 @@ index 52de7d14b1398..bbc261ab2025b 100644
}
+@@ -3571,14 +3577,14 @@ static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ }
+
+ static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+- SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0,
+ wcd938x_get_hph_type, NULL),
+ };
+
+ static const struct snd_kcontrol_new impedance_detect_controls[] = {
+- SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0,
+ wcd938x_hph_impedance_get, NULL),
+- SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
++ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0,
+ wcd938x_hph_impedance_get, NULL),
+ };
+
+diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
+index 15d42ce3b21d6..41504ce2a682f 100644
+--- a/sound/soc/codecs/wm8350.c
++++ b/sound/soc/codecs/wm8350.c
+@@ -1537,18 +1537,38 @@ static int wm8350_component_probe(struct snd_soc_component *component)
+ wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
+ WM8350_JDL_ENA | WM8350_JDR_ENA);
+
+- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
+ wm8350_hpl_jack_handler, 0, "Left jack detect",
+ priv);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
++ if (ret != 0)
++ goto err;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
+ wm8350_hpr_jack_handler, 0, "Right jack detect",
+ priv);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
++ if (ret != 0)
++ goto free_jck_det_l;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
+ wm8350_mic_handler, 0, "Microphone short", priv);
+- wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
++ if (ret != 0)
++ goto free_jck_det_r;
++
++ ret = wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
+ wm8350_mic_handler, 0, "Microphone detect", priv);
++ if (ret != 0)
++ goto free_micscd;
+
+ return 0;
++
++free_micscd:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv);
++free_jck_det_r:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
++free_jck_det_l:
++ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
++err:
++ return ret;
+ }
+
+ static void wm8350_component_remove(struct snd_soc_component *component)
+diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
+index dcee7b2bd3d79..859ebcec83838 100644
+--- a/sound/soc/codecs/wm8731.c
++++ b/sound/soc/codecs/wm8731.c
+@@ -602,7 +602,7 @@ static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731)
+ ret = wm8731_reset(wm8731->regmap);
+ if (ret < 0) {
+ dev_err(dev, "Failed to issue reset: %d\n", ret);
+- goto err_regulator_enable;
++ goto err;
+ }
+
+ /* Clear POWEROFF, keep everything else disabled */
+@@ -619,10 +619,7 @@ static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731)
+
+ regcache_mark_dirty(wm8731->regmap);
+
+-err_regulator_enable:
+- /* Regulators will be enabled by bias management */
+- regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
+-
++err:
+ return ret;
+ }
+
+@@ -766,21 +763,27 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
+ ret = PTR_ERR(wm8731->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+- return ret;
++ goto err_regulator_enable;
+ }
+
+ ret = wm8731_hw_init(&i2c->dev, wm8731);
+ if (ret != 0)
+- return ret;
++ goto err_regulator_enable;
+
+ ret = devm_snd_soc_register_component(&i2c->dev,
+ &soc_component_dev_wm8731, &wm8731_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+- return ret;
++ goto err_regulator_enable;
+ }
+
+ return 0;
++
++err_regulator_enable:
++ /* Regulators will be enabled by bias management */
++ regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
++
++ return ret;
+ }
+
+ static int wm8731_i2c_remove(struct i2c_client *client)
+diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
+index e4018ba3b19a2..7878c7a58ff10 100644
+--- a/sound/soc/codecs/wm8958-dsp2.c
++++ b/sound/soc/codecs/wm8958-dsp2.c
+@@ -530,7 +530,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
+
+ wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
+
+- return 0;
++ return 1;
+ }
+
+ #define WM8958_MBC_SWITCH(xname, xval) {\
+@@ -656,7 +656,7 @@ static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
+
+ wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
+
+- return 0;
++ return 1;
+ }
+
+
+@@ -730,7 +730,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
+
+ wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
+
+- return 0;
++ return 1;
+ }
+
+ #define WM8958_HPF_SWITCH(xname, xval) {\
+@@ -824,7 +824,7 @@ static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
+
+ wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
+
+- return 0;
++ return 1;
+ }
+
+ #define WM8958_ENH_EQ_SWITCH(xname, xval) {\
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index 2da4a5fa7a18d..564b78f3cdd0a 100644
--- a/sound/soc/codecs/wsa881x.c
@@ -162789,6 +252201,43 @@ index 2da4a5fa7a18d..564b78f3cdd0a 100644
}
static const char * const smart_boost_lvl_text[] = {
+diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
+index 33ce257ae1986..315ca5c4b057a 100644
+--- a/sound/soc/dwc/dwc-i2s.c
++++ b/sound/soc/dwc/dwc-i2s.c
+@@ -403,9 +403,13 @@ static int dw_i2s_runtime_suspend(struct device *dev)
+ static int dw_i2s_runtime_resume(struct device *dev)
+ {
+ struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
++ int ret;
+
+- if (dw_dev->capability & DW_I2S_MASTER)
+- clk_enable(dw_dev->clk);
++ if (dw_dev->capability & DW_I2S_MASTER) {
++ ret = clk_enable(dw_dev->clk);
++ if (ret)
++ return ret;
++ }
+ return 0;
+ }
+
+@@ -422,10 +426,13 @@ static int dw_i2s_resume(struct snd_soc_component *component)
+ {
+ struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component);
+ struct snd_soc_dai *dai;
+- int stream;
++ int stream, ret;
+
+- if (dev->capability & DW_I2S_MASTER)
+- clk_enable(dev->clk);
++ if (dev->capability & DW_I2S_MASTER) {
++ ret = clk_enable(dev->clk);
++ if (ret)
++ return ret;
++ }
+
+ for_each_component_dais(component, dai) {
+ for_each_pcm_streams(stream)
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 24b41881a68f8..d7d1536a4f377 100644
--- a/sound/soc/fsl/fsl_asrc.c
@@ -162928,6 +252377,19 @@ index 69aeb0e71844d..0d4efbed41dab 100644
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform: fsl-mqs");
+MODULE_ALIAS("platform:fsl-mqs");
+diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
+index 1c53719bb61e2..8b5c3ba48516c 100644
+--- a/sound/soc/fsl/fsl_spdif.c
++++ b/sound/soc/fsl/fsl_spdif.c
+@@ -598,6 +598,8 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
+ mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
+ SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
+ SCR_TXFIFO_FSEL_MASK;
++ /* Disable TX clock */
++ regmap_update_bits(regmap, REG_SPDIF_STC, STC_TXCLK_ALL_EN_MASK, 0);
+ } else {
+ scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO;
+ mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
index 58fd0639a0698..db947180617a6 100644
--- a/sound/soc/fsl/imx-card.c
@@ -163012,6 +252474,18 @@ index 58fd0639a0698..db947180617a6 100644
}
link->cpus->of_node = args.np;
+diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c
+index 1981dcd7e9305..a7fb53e0f96f8 100644
+--- a/sound/soc/fsl/imx-es8328.c
++++ b/sound/soc/fsl/imx-es8328.c
+@@ -87,6 +87,7 @@ static int imx_es8328_probe(struct platform_device *pdev)
+ if (int_port > MUX_PORT_MAX || int_port == 0) {
+ dev_err(dev, "mux-int-port: hardware only has %d mux ports\n",
+ MUX_PORT_MAX);
++ ret = -EINVAL;
+ goto fail;
+ }
+
diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c
index 34a0dceae6216..ef8d7a65ebc61 100644
--- a/sound/soc/fsl/imx-hdmi.c
@@ -163054,6 +252528,49 @@ index af3c3b90c0aca..83b4a22bf15ac 100644
}
static int pcm030_fabric_remove(struct platform_device *op)
+diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
+index 10c63b73900c6..ffda8a38de3ed 100644
+--- a/sound/soc/generic/simple-card-utils.c
++++ b/sound/soc/generic/simple-card-utils.c
+@@ -275,6 +275,7 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream,
+ mclk_fs = props->mclk_fs;
+
+ if (mclk_fs) {
++ struct snd_soc_component *component;
+ mclk = params_rate(params) * mclk_fs;
+
+ for_each_prop_dai_codec(props, i, pdai) {
+@@ -282,16 +283,30 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream,
+ if (ret < 0)
+ return ret;
+ }
++
+ for_each_prop_dai_cpu(props, i, pdai) {
+ ret = asoc_simple_set_clk_rate(pdai, mclk);
+ if (ret < 0)
+ return ret;
+ }
++
++ /* Ensure sysclk is set on all components in case any
++ * (such as platform components) are missed by calls to
++ * snd_soc_dai_set_sysclk.
++ */
++ for_each_rtd_components(rtd, i, component) {
++ ret = snd_soc_component_set_sysclk(component, 0, 0,
++ mclk, SND_SOC_CLOCK_IN);
++ if (ret && ret != -ENOTSUPP)
++ return ret;
++ }
++
+ for_each_rtd_codec_dais(rtd, i, sdai) {
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP)
+ return ret;
+ }
++
+ for_each_rtd_cpu_dais(rtd, i, sdai) {
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT);
+ if (ret && ret != -ENOTSUPP)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index a3a7990b5cb66..bc3e24c6a28a8 100644
--- a/sound/soc/generic/simple-card.c
@@ -163099,10 +252616,15 @@ index a3a7990b5cb66..bc3e24c6a28a8 100644
goto dai_link_of_err;
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
-index 6b06248a9327a..76759b2099064 100644
+index 6b06248a9327a..0bf3e56e1d580 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
-@@ -188,7 +188,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
+@@ -184,11 +184,11 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+- DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
SOF_SDW_PCH_DMIC |
@@ -163166,9 +252688,25 @@ index 9c5fd18f2600f..346bec0003066 100644
int catpt_dma_memcpy_todsp(struct catpt_dev *cdev, struct dma_chan *chan,
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
-index 785d5f5f8a9c9..11801b905ecc2 100644
+index 785d5f5f8a9c9..c93d8019b0e55 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+@@ -127,13 +127,13 @@ static const struct snd_soc_acpi_adr_device mx8373_1_adr[] = {
+ {
+ .adr = 0x000123019F837300ull,
+ .num_endpoints = 1,
+- .endpoints = &spk_l_endpoint,
++ .endpoints = &spk_r_endpoint,
+ .name_prefix = "Right"
+ },
+ {
+ .adr = 0x000127019F837300ull,
+ .num_endpoints = 1,
+- .endpoints = &spk_r_endpoint,
++ .endpoints = &spk_l_endpoint,
+ .name_prefix = "Left"
+ }
+ };
@@ -156,6 +156,15 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
}
};
@@ -163297,10 +252835,32 @@ index c28ebf891cb05..e168d31f44459 100644
}
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
-index a4d26a6fc8492..bda103211e0bd 100644
+index a4d26a6fc8492..0ab8b050b305f 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
-@@ -781,7 +781,11 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
+@@ -685,7 +685,6 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
+ struct snd_soc_dai_link *dai_link;
+ struct mt8183_da7219_max98357_priv *priv;
+ struct pinctrl *pinctrl;
+- const struct of_device_id *match;
+ int ret, i;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+@@ -695,11 +694,9 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
+ return -EINVAL;
+ }
+
+- match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+- if (!match || !match->data)
++ card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
++ if (!card)
+ return -EINVAL;
+-
+- card = (struct snd_soc_card *)match->data;
+ card->dev = &pdev->dev;
+
+ hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+@@ -781,7 +778,11 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
return ret;
}
@@ -163314,10 +252874,32 @@ index a4d26a6fc8492..bda103211e0bd 100644
#ifdef CONFIG_OF
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
-index 94dcbd36c8697..c7b10c48c6c22 100644
+index 94dcbd36c8697..a56c1e87d5642 100644
--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
-@@ -780,7 +780,12 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
+@@ -637,7 +637,6 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
+ struct device_node *platform_node, *ec_codec, *hdmi_codec;
+ struct snd_soc_dai_link *dai_link;
+ struct mt8183_mt6358_ts3a227_max98357_priv *priv;
+- const struct of_device_id *match;
+ int ret, i;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+@@ -647,11 +646,9 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
+ return -EINVAL;
+ }
+
+- match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+- if (!match || !match->data)
++ card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
++ if (!card)
+ return -EINVAL;
+-
+- card = (struct snd_soc_card *)match->data;
+ card->dev = &pdev->dev;
+
+ ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0);
+@@ -780,7 +777,12 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
__func__, ret);
}
@@ -163332,18 +252914,60 @@ index 94dcbd36c8697..c7b10c48c6c22 100644
#ifdef CONFIG_OF
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
-index a606133951b70..24a5d0adec1ba 100644
+index a606133951b70..c1d225b498513 100644
--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
+++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
-@@ -1172,7 +1172,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
- return ret;
+@@ -1106,7 +1106,6 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
+ struct device_node *platform_node, *hdmi_codec;
+ int ret, i;
+ struct snd_soc_dai_link *dai_link;
+- const struct of_device_id *match;
+ struct mt8192_mt6359_priv *priv;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+@@ -1116,11 +1115,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
+ return -EINVAL;
+ }
+
+- match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+- if (!match || !match->data)
+- return -EINVAL;
+-
+- card = (struct snd_soc_card *)match->data;
++ card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
++ if (!card) {
++ ret = -EINVAL;
++ goto put_platform_node;
++ }
+ card->dev = &pdev->dev;
+
+ hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+@@ -1162,17 +1161,25 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+- if (!priv)
+- return -ENOMEM;
++ if (!priv) {
++ ret = -ENOMEM;
++ goto put_hdmi_codec;
++ }
+ snd_soc_card_set_drvdata(card, priv);
+
+ ret = mt8192_afe_gpio_init(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "init gpio error %d\n", ret);
+- return ret;
++ goto put_hdmi_codec;
}
- return devm_snd_soc_register_card(&pdev->dev, card);
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+
-+ of_node_put(platform_node);
++put_hdmi_codec:
+ of_node_put(hdmi_codec);
++put_platform_node:
++ of_node_put(platform_node);
+ return ret;
}
@@ -163519,6 +253143,32 @@ index d06f9cf85a4ec..d3871353db415 100644
/* PCM_INTF_CON2 */
#define PCM_INTF_CON2_CLK_DOMAIN_SEL(x) (((x) & 0x3) << 23)
+diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c
+index 27a6d3259c50a..442c215936d97 100644
+--- a/sound/soc/meson/aiu-acodec-ctrl.c
++++ b/sound/soc/meson/aiu-acodec-ctrl.c
+@@ -58,7 +58,7 @@ static int aiu_acodec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+
+- return 0;
++ return 1;
+ }
+
+ static SOC_ENUM_SINGLE_DECL(aiu_acodec_ctrl_mux_enum, AIU_ACODEC_CTRL,
+diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c
+index c3ea733fce91f..c966fc60dc733 100644
+--- a/sound/soc/meson/aiu-codec-ctrl.c
++++ b/sound/soc/meson/aiu-codec-ctrl.c
+@@ -57,7 +57,7 @@ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+
+- return 0;
++ return 1;
+ }
+
+ static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL,
diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
index 9322245521463..67729de41a73e 100644
--- a/sound/soc/meson/aiu-encoder-i2s.c
@@ -163645,6 +253295,49 @@ index 4ad23267cace5..d67ff4cdabd5a 100644
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
card->dev, size, size);
+diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c
+index 9b2b59536ced0..6c99052feafd8 100644
+--- a/sound/soc/meson/g12a-tohdmitx.c
++++ b/sound/soc/meson/g12a-tohdmitx.c
+@@ -67,7 +67,7 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+
+- return 0;
++ return 1;
+ }
+
+ static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0,
+diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
+index 6a2d24d489647..879c1221a809b 100644
+--- a/sound/soc/mxs/mxs-saif.c
++++ b/sound/soc/mxs/mxs-saif.c
+@@ -455,7 +455,10 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
+ * basic clock which should be fast enough for the internal
+ * logic.
+ */
+- clk_enable(saif->clk);
++ ret = clk_enable(saif->clk);
++ if (ret)
++ return ret;
++
+ ret = clk_set_rate(saif->clk, 24000000);
+ clk_disable(saif->clk);
+ if (ret)
+diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
+index a6407f4388de7..fb721bc499496 100644
+--- a/sound/soc/mxs/mxs-sgtl5000.c
++++ b/sound/soc/mxs/mxs-sgtl5000.c
+@@ -118,6 +118,9 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev)
+ codec_np = of_parse_phandle(np, "audio-codec", 0);
+ if (!saif_np[0] || !saif_np[1] || !codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
++ of_node_put(codec_np);
++ of_node_put(saif_np[0]);
++ of_node_put(saif_np[1]);
+ return -EINVAL;
+ }
+
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index a59e9d20cb46b..4b1773c1fb95f 100644
--- a/sound/soc/qcom/lpass-platform.c
@@ -163751,6 +253444,48 @@ index 3390ebef9549d..18c90bb4922be 100644
session->port_id = -1;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
}
+diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
+index 7e89f5b0c237f..2880a05376469 100644
+--- a/sound/soc/rockchip/rockchip_i2s.c
++++ b/sound/soc/rockchip/rockchip_i2s.c
+@@ -717,19 +717,23 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
+ i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
+ if (IS_ERR(i2s->mclk)) {
+ dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
+- return PTR_ERR(i2s->mclk);
++ ret = PTR_ERR(i2s->mclk);
++ goto err_clk;
+ }
+
+ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+- if (IS_ERR(regs))
+- return PTR_ERR(regs);
++ if (IS_ERR(regs)) {
++ ret = PTR_ERR(regs);
++ goto err_clk;
++ }
+
+ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &rockchip_i2s_regmap_config);
+ if (IS_ERR(i2s->regmap)) {
+ dev_err(&pdev->dev,
+ "Failed to initialise managed register map\n");
+- return PTR_ERR(i2s->regmap);
++ ret = PTR_ERR(i2s->regmap);
++ goto err_clk;
+ }
+
+ i2s->bclk_ratio = 64;
+@@ -769,7 +773,8 @@ err_suspend:
+ i2s_runtime_suspend(&pdev->dev);
+ err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+-
++err_clk:
++ clk_disable_unprepare(i2s->hclk);
+ return ret;
+ }
+
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index 66bcc2f97544b..c3f1b054e2389 100644
--- a/sound/soc/samsung/idma.c
@@ -163764,6 +253499,41 @@ index 66bcc2f97544b..c3f1b054e2389 100644
return 0;
}
+diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
+index cdf3b7f69ba70..e9a1eb6bdf66a 100644
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -816,14 +816,27 @@ static int fsi_clk_enable(struct device *dev,
+ return ret;
+ }
+
+- clk_enable(clock->xck);
+- clk_enable(clock->ick);
+- clk_enable(clock->div);
++ ret = clk_enable(clock->xck);
++ if (ret)
++ goto err;
++ ret = clk_enable(clock->ick);
++ if (ret)
++ goto disable_xck;
++ ret = clk_enable(clock->div);
++ if (ret)
++ goto disable_ick;
+
+ clock->count++;
+ }
+
+ return ret;
++
++disable_ick:
++ clk_disable(clock->ick);
++disable_xck:
++ clk_disable(clock->xck);
++err:
++ return ret;
+ }
+
+ static int fsi_clk_disable(struct device *dev,
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 978bd0406729a..6a8fe0da7670b 100644
--- a/sound/soc/sh/rcar/core.c
@@ -163789,11 +253559,173 @@ index 16c6e0265749b..03e0d4eca7815 100644
return 0;
}
+diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
+index fa0cc08f70ec4..16de2633a8736 100644
+--- a/sound/soc/sh/rz-ssi.c
++++ b/sound/soc/sh/rz-ssi.c
+@@ -411,54 +411,56 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+ {
+ struct snd_pcm_substream *substream = strm->substream;
+ struct snd_pcm_runtime *runtime;
++ bool done = false;
+ u16 *buf;
+ int fifo_samples;
+ int frames_left;
+- int samples = 0;
++ int samples;
+ int i;
+
+ if (!rz_ssi_stream_is_valid(ssi, strm))
+ return -EINVAL;
+
+ runtime = substream->runtime;
+- /* frames left in this period */
+- frames_left = runtime->period_size - (strm->buffer_pos %
+- runtime->period_size);
+- if (frames_left == 0)
+- frames_left = runtime->period_size;
+
+- /* Samples in RX FIFO */
+- fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
+- SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
++ while (!done) {
++ /* frames left in this period */
++ frames_left = runtime->period_size -
++ (strm->buffer_pos % runtime->period_size);
++ if (!frames_left)
++ frames_left = runtime->period_size;
++
++ /* Samples in RX FIFO */
++ fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
++ SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
++
++ /* Only read full frames at a time */
++ samples = 0;
++ while (frames_left && (fifo_samples >= runtime->channels)) {
++ samples += runtime->channels;
++ fifo_samples -= runtime->channels;
++ frames_left--;
++ }
+
+- /* Only read full frames at a time */
+- while (frames_left && (fifo_samples >= runtime->channels)) {
+- samples += runtime->channels;
+- fifo_samples -= runtime->channels;
+- frames_left--;
+- }
++ /* not enough samples yet */
++ if (!samples)
++ break;
+
+- /* not enough samples yet */
+- if (samples == 0)
+- return 0;
++ /* calculate new buffer index */
++ buf = (u16 *)(runtime->dma_area);
++ buf += strm->buffer_pos * runtime->channels;
+
+- /* calculate new buffer index */
+- buf = (u16 *)(runtime->dma_area);
+- buf += strm->buffer_pos * runtime->channels;
+-
+- /* Note, only supports 16-bit samples */
+- for (i = 0; i < samples; i++)
+- *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
++ /* Note, only supports 16-bit samples */
++ for (i = 0; i < samples; i++)
++ *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
+
+- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+- rz_ssi_pointer_update(strm, samples / runtime->channels);
++ rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
++ rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+- /*
+- * If we finished this period, but there are more samples in
+- * the RX FIFO, call this function again
+- */
+- if (frames_left == 0 && fifo_samples >= runtime->channels)
+- rz_ssi_pio_recv(ssi, strm);
++ /* check if there are no more samples in the RX FIFO */
++ if (!(!frames_left && fifo_samples >= runtime->channels))
++ done = true;
++ }
+
+ return 0;
+ }
+@@ -975,6 +977,9 @@ static int rz_ssi_probe(struct platform_device *pdev)
+ ssi->playback.priv = ssi;
+ ssi->capture.priv = ssi;
+
++ spin_lock_init(&ssi->lock);
++ dev_set_drvdata(&pdev->dev, ssi);
++
+ /* Error Interrupt */
+ ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
+ if (ssi->irq_int < 0)
+@@ -1022,8 +1027,6 @@ static int rz_ssi_probe(struct platform_device *pdev)
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_resume_and_get(&pdev->dev);
+
+- spin_lock_init(&ssi->lock);
+- dev_set_drvdata(&pdev->dev, ssi);
+ ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
+ rz_ssi_soc_dai,
+ ARRAY_SIZE(rz_ssi_soc_dai));
+diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
+index 36060800e9bd9..2050728063a15 100644
+--- a/sound/soc/soc-compress.c
++++ b/sound/soc/soc-compress.c
+@@ -534,6 +534,11 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
+ return -EINVAL;
+ }
+
++ if (!codec_dai) {
++ dev_err(rtd->card->dev, "Missing codec\n");
++ return -EINVAL;
++ }
++
+ /* check client and interface hw capabilities */
+ if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+ snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 80ca260595fda..5da762807824d 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -3208,7 +3208,7 @@ int snd_soc_get_dai_name(const struct of_phandle_args *args,
+ for_each_component(pos) {
+ struct device_node *component_of_node = soc_component_to_node(pos);
+
+- if (component_of_node != args->np)
++ if (component_of_node != args->np || !pos->num_dai)
+ continue;
+
+ ret = snd_soc_component_of_xlate_dai_name(pos, args, dai_name);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
-index 59d07648a7e7f..0479bb0005abd 100644
+index 59d07648a7e7f..0b166e074457f 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
-@@ -2557,8 +2557,13 @@ static struct snd_soc_dapm_widget *dapm_find_widget(
+@@ -1685,8 +1685,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
+ switch (w->id) {
+ case snd_soc_dapm_pre:
+ if (!w->event)
+- list_for_each_entry_safe_continue(w, n, list,
+- power_list);
++ continue;
+
+ if (event == SND_SOC_DAPM_STREAM_START)
+ ret = w->event(w,
+@@ -1698,8 +1697,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
+
+ case snd_soc_dapm_post:
+ if (!w->event)
+- list_for_each_entry_safe_continue(w, n, list,
+- power_list);
++ continue;
+
+ if (event == SND_SOC_DAPM_STREAM_START)
+ ret = w->event(w,
+@@ -2557,8 +2555,13 @@ static struct snd_soc_dapm_widget *dapm_find_widget(
return NULL;
}
@@ -163809,7 +253741,7 @@ index 59d07648a7e7f..0479bb0005abd 100644
{
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
int ret = 0;
-@@ -2584,6 +2589,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
+@@ -2584,6 +2587,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
return ret;
}
@@ -163828,7 +253760,7 @@ index 59d07648a7e7f..0479bb0005abd 100644
/**
* snd_soc_dapm_sync_unlocked - scan and power dapm paths
* @dapm: DAPM context
-@@ -3587,10 +3604,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
+@@ -3587,10 +3602,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
const char *pin = (const char *)kcontrol->private_value;
int ret;
@@ -163844,7 +253776,7 @@ index 59d07648a7e7f..0479bb0005abd 100644
snd_soc_dapm_sync(&card->dapm);
return ret;
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
-index 08eaa9ddf191e..ee3782ecd7e3a 100644
+index 08eaa9ddf191e..f32ba64c5ddab 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -308,7 +308,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
@@ -163934,7 +253866,7 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
if (snd_soc_volsw_is_stereo(mc)) {
unsigned int val2;
-@@ -426,6 +455,11 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
+@@ -426,8 +455,13 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
err = snd_soc_component_update_bits(component, reg2, val_mask,
val2);
@@ -163944,18 +253876,29 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
+ ret = err;
+ }
}
- return err;
+- return err;
++ return ret;
}
-@@ -485,7 +519,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
+ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
+
+@@ -485,7 +519,15 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
unsigned int val, val_mask;
- int ret;
-+ int err, ret;
++ int err, ret, tmp;
++
++ tmp = ucontrol->value.integer.value[0];
++ if (tmp < 0)
++ return -EINVAL;
++ if (mc->platform_max && tmp > mc->platform_max)
++ return -EINVAL;
++ if (tmp > mc->max - mc->min + 1)
++ return -EINVAL;
if (invert)
val = (max - ucontrol->value.integer.value[0]) & mask;
-@@ -494,9 +528,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
+@@ -494,11 +536,20 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
val_mask = mask << shift;
val = val << shift;
@@ -163968,8 +253911,18 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
+ ret = err;
if (snd_soc_volsw_is_stereo(mc)) {
++ tmp = ucontrol->value.integer.value[1];
++ if (tmp < 0)
++ return -EINVAL;
++ if (mc->platform_max && tmp > mc->platform_max)
++ return -EINVAL;
++ if (tmp > mc->max - mc->min + 1)
++ return -EINVAL;
++
if (invert)
-@@ -506,8 +541,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
+ val = (max - ucontrol->value.integer.value[1]) & mask;
+ else
+@@ -506,8 +557,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
val_mask = mask << shift;
val = val << shift;
@@ -163983,7 +253936,7 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
}
return ret;
-@@ -856,8 +895,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
+@@ -856,8 +911,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
unsigned long mask = (1UL<<mc->nbits)-1;
long max = mc->max;
long val = ucontrol->value.integer.value[0];
@@ -163995,7 +253948,7 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
if (invert)
val = max - val;
val &= mask;
-@@ -868,9 +910,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
+@@ -868,9 +926,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
regmask, regval);
if (err < 0)
return err;
@@ -164009,10 +253962,35 @@ index 08eaa9ddf191e..ee3782ecd7e3a 100644
EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
-index f6e5ac3e03140..7459956d62b99 100644
+index f6e5ac3e03140..eff8d4f715611 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
-@@ -2674,6 +2674,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
+@@ -510,7 +510,8 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
+
+ if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES
+ && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
+- && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
++ && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ
++ || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+ && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ struct soc_bytes_ext *sbe;
+ struct snd_soc_tplg_bytes_control *be;
+@@ -1480,12 +1481,12 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
+ template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
+ kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL);
+ if (!kc)
+- goto err;
++ goto hdr_err;
+
+ kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!kcontrol_type)
+- goto err;
++ goto hdr_err;
+
+ for (i = 0; i < w->num_kcontrols; i++) {
+ control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
+@@ -2674,6 +2675,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
/* remove dynamic controls from the component driver */
int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
{
@@ -164020,7 +253998,7 @@ index f6e5ac3e03140..7459956d62b99 100644
struct snd_soc_dobj *dobj, *next_dobj;
int pass = SOC_TPLG_PASS_END;
-@@ -2681,6 +2682,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
+@@ -2681,6 +2683,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
while (pass >= SOC_TPLG_PASS_START) {
/* remove mixer controls */
@@ -164028,7 +254006,7 @@ index f6e5ac3e03140..7459956d62b99 100644
list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
list) {
-@@ -2719,6 +2721,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
+@@ -2719,6 +2722,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
break;
}
}
@@ -164036,6 +254014,30 @@ index f6e5ac3e03140..7459956d62b99 100644
pass--;
}
+diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c
+index 892e1482f97fa..b3d3edc36bb00 100644
+--- a/sound/soc/sof/imx/imx8m.c
++++ b/sound/soc/sof/imx/imx8m.c
+@@ -191,6 +191,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
+ }
+
+ ret = of_address_to_resource(res_node, 0, &res);
++ of_node_put(res_node);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get reserved region address\n");
+ goto exit_pdev_unregister;
+diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
+index 88b6176af021c..d83e1a36707af 100644
+--- a/sound/soc/sof/intel/Kconfig
++++ b/sound/soc/sof/intel/Kconfig
+@@ -84,6 +84,7 @@ if SND_SOC_SOF_PCI
+ config SND_SOC_SOF_MERRIFIELD
+ tristate "SOF support for Tangier/Merrifield"
+ default SND_SOC_SOF_PCI
++ select SND_SOC_SOF_PCI_DEV
+ select SND_SOC_SOF_INTEL_ATOM_HIFI_EP
+ help
+ This adds support for Sound Open Firmware for Intel(R) platforms
diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c
index 30025d3c16b6e..0862ff8b66273 100644
--- a/sound/soc/sof/intel/hda-bus.c
@@ -164120,8 +254122,61 @@ index 623cf291e2074..262a70791a8f8 100644
/* power down all hda link */
snd_hdac_ext_bus_link_power_down_all(bus);
+diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
+index 6f4771bf9de34..14469e087b00d 100644
+--- a/sound/soc/sof/intel/hda-loader.c
++++ b/sound/soc/sof/intel/hda-loader.c
+@@ -48,7 +48,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
+- goto error;
++ goto out_put;
+ }
+
+ hstream->period_bytes = 0;/* initialize period_bytes */
+@@ -59,22 +59,23 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
+ ret = hda_dsp_iccmax_stream_hw_params(sdev, dsp_stream, dmab, NULL);
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
+- goto error;
++ goto out_free;
+ }
+ } else {
+ ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
+- goto error;
++ goto out_free;
+ }
+ hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size);
+ }
+
+ return dsp_stream;
+
+-error:
+- hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
++out_free:
+ snd_dma_free_pages(dmab);
++out_put:
++ hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
+ return ERR_PTR(ret);
+ }
+
+diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
+index cc8ddef37f37b..d81e87e304e42 100644
+--- a/sound/soc/sof/intel/hda-pcm.c
++++ b/sound/soc/sof/intel/hda-pcm.c
+@@ -242,6 +242,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
+ runtime->hw.info &= ~SNDRV_PCM_INFO_PAUSE;
+
+ if (hda_always_enable_dmi_l1 ||
++ direction == SNDRV_PCM_STREAM_PLAYBACK ||
+ spcm->stream[substream->stream].d0i3_compatible)
+ flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
+
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
-index f60e2c57d3d0c..ef92cca7ae01e 100644
+index f60e2c57d3d0c..ddf70902e53c4 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -696,6 +696,20 @@ skip_soundwire:
@@ -164154,6 +254209,59 @@ index f60e2c57d3d0c..ef92cca7ae01e 100644
/* enable GIE interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
SOF_HDA_INTCTL,
+@@ -1056,7 +1072,7 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
+ struct hdac_bus *bus = sof_to_bus(sdev);
+ struct sdw_intel_slave_id *ids = sdw->ids;
+ int num_slaves = sdw->num_slaves;
+- unsigned int part_id, link_id, unique_id, mfg_id;
++ unsigned int part_id, link_id, unique_id, mfg_id, version;
+ int i, j, k;
+
+ for (i = 0; i < link->num_adr; i++) {
+@@ -1066,12 +1082,14 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
+ mfg_id = SDW_MFG_ID(adr);
+ part_id = SDW_PART_ID(adr);
+ link_id = SDW_DISCO_LINK_ID(adr);
++ version = SDW_VERSION(adr);
+
+ for (j = 0; j < num_slaves; j++) {
+ /* find out how many identical parts were reported on that link */
+ if (ids[j].link_id == link_id &&
+ ids[j].id.part_id == part_id &&
+- ids[j].id.mfg_id == mfg_id)
++ ids[j].id.mfg_id == mfg_id &&
++ ids[j].id.sdw_version == version)
+ reported_part_count++;
+ }
+
+@@ -1080,21 +1098,24 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
+
+ if (ids[j].link_id != link_id ||
+ ids[j].id.part_id != part_id ||
+- ids[j].id.mfg_id != mfg_id)
++ ids[j].id.mfg_id != mfg_id ||
++ ids[j].id.sdw_version != version)
+ continue;
+
+ /* find out how many identical parts are expected */
+ for (k = 0; k < link->num_adr; k++) {
+ u64 adr2 = link->adr_d[k].adr;
+- unsigned int part_id2, link_id2, mfg_id2;
++ unsigned int part_id2, link_id2, mfg_id2, version2;
+
+ mfg_id2 = SDW_MFG_ID(adr2);
+ part_id2 = SDW_PART_ID(adr2);
+ link_id2 = SDW_DISCO_LINK_ID(adr2);
++ version2 = SDW_VERSION(adr2);
+
+ if (link_id2 == link_id &&
+ part_id2 == part_id &&
+- mfg_id2 == mfg_id)
++ mfg_id2 == mfg_id &&
++ version2 == version)
+ expected_part_count++;
+ }
+
diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c
index d04ce84fe7cc2..beb2fb3cd0141 100644
--- a/sound/soc/sof/intel/pci-tgl.c
@@ -164171,6 +254279,22 @@ index d04ce84fe7cc2..beb2fb3cd0141 100644
{ 0, }
};
MODULE_DEVICE_TABLE(pci, sof_pci_ids);
+diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
+index bc9e707656789..b773289c928d4 100644
+--- a/sound/soc/sof/sof-pci-dev.c
++++ b/sound/soc/sof/sof-pci-dev.c
+@@ -129,6 +129,11 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+
+ dev_dbg(&pci->dev, "PCI DSP detected");
+
++ if (!desc) {
++ dev_err(dev, "error: no matching PCI descriptor\n");
++ return -ENODEV;
++ }
++
+ if (!desc->ops) {
+ dev_err(dev, "error: no matching PCI descriptor ops\n");
+ return -ENODEV;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index cc9585bfa4e9f..1bb2dcf37ffe9 100644
--- a/sound/soc/sof/topology.c
@@ -164191,6 +254315,50 @@ index cc9585bfa4e9f..1bb2dcf37ffe9 100644
ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core);
if (ret < 0)
dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n",
+diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
+index 2ed92c990b97c..dd9013c476649 100644
+--- a/sound/soc/sti/uniperif_player.c
++++ b/sound/soc/sti/uniperif_player.c
+@@ -91,7 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
+ SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
+
+ /* Stop the player */
+- snd_pcm_stop_xrun(player->substream);
++ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
+ }
+
+ ret = IRQ_HANDLED;
+@@ -105,7 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
+ SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
+
+ /* Stop the player */
+- snd_pcm_stop_xrun(player->substream);
++ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
+
+ ret = IRQ_HANDLED;
+ }
+@@ -138,7 +138,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
+ dev_err(player->dev, "Underflow recovery failed\n");
+
+ /* Stop the player */
+- snd_pcm_stop_xrun(player->substream);
++ snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
+
+ ret = IRQ_HANDLED;
+ }
+diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
+index 136059331211d..065c5f0d1f5f0 100644
+--- a/sound/soc/sti/uniperif_reader.c
++++ b/sound/soc/sti/uniperif_reader.c
+@@ -65,7 +65,7 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
+ if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
+ dev_err(reader->dev, "FIFO error detected\n");
+
+- snd_pcm_stop_xrun(reader->substream);
++ snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
+
+ ret = IRQ_HANDLED;
+ }
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 6254bacad6eb7..717f45a83445c 100644
--- a/sound/soc/stm/stm32_i2s.c
@@ -165342,6 +255510,29 @@ index 8ee0ec814f67c..6f795d7dff7c1 100644
struct snd_soc_card *card;
unsigned int mclk_id;
bool hp_jack_gpio_active_low;
+diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c
+index 6dca51862dd76..0363a088d2e00 100644
+--- a/sound/soc/ti/davinci-i2s.c
++++ b/sound/soc/ti/davinci-i2s.c
+@@ -708,7 +708,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
+ dev->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dev->clk))
+ return -ENODEV;
+- clk_enable(dev->clk);
++ ret = clk_enable(dev->clk);
++ if (ret)
++ goto err_put_clk;
+
+ dev->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, dev);
+@@ -730,6 +732,7 @@ err_unregister_component:
+ snd_soc_unregister_component(&pdev->dev);
+ err_release_clk:
+ clk_disable(dev->clk);
++err_put_clk:
+ clk_put(dev->clk);
+ return ret;
+ }
diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig
index aa3592ee1358b..ddfa6424c656b 100644
--- a/sound/soc/uniphier/Kconfig
@@ -165363,7 +255554,7 @@ index aa3592ee1358b..ddfa6424c656b 100644
This adds ASoC driver for Socionext UniPhier PXs2
input and output that can be used with other codecs.
diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c
-index 91afea9d5de67..ce19a6058b279 100644
+index 91afea9d5de67..5c4158069a5a8 100644
--- a/sound/soc/xilinx/xlnx_formatter_pcm.c
+++ b/sound/soc/xilinx/xlnx_formatter_pcm.c
@@ -37,6 +37,7 @@
@@ -165374,29 +255565,53 @@ index 91afea9d5de67..ce19a6058b279 100644
#define AUD_STS_IOC_IRQ_MASK BIT(31)
#define AUD_STS_CH_STS_MASK BIT(29)
-@@ -368,12 +369,32 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
+@@ -83,6 +84,7 @@ struct xlnx_pcm_drv_data {
+ struct snd_pcm_substream *play_stream;
+ struct snd_pcm_substream *capture_stream;
+ struct clk *axi_clk;
++ unsigned int sysclk;
+ };
+
+ /*
+@@ -313,6 +315,15 @@ static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
+ return IRQ_NONE;
+ }
+
++static int xlnx_formatter_set_sysclk(struct snd_soc_component *component,
++ int clk_id, int source, unsigned int freq, int dir)
++{
++ struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
++
++ adata->sysclk = freq;
++ return 0;
++}
++
+ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+ {
+@@ -368,12 +379,32 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
runtime->private_data = stream_data;
- /* Resize the period size divisible by 64 */
+ /* Resize the period bytes as divisible by 64 */
- err = snd_pcm_hw_constraint_step(runtime, 0,
-- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
++ err = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ XLNX_AUD_ALIGN_BYTES);
- if (err) {
- dev_err(component->dev,
-- "unable to set constraint on period bytes\n");
++ if (err) {
++ dev_err(component->dev,
+ "Unable to set constraint on period bytes\n");
+ return err;
+ }
+
+ /* Resize the buffer bytes as divisible by 64 */
-+ err = snd_pcm_hw_constraint_step(runtime, 0,
+ err = snd_pcm_hw_constraint_step(runtime, 0,
+- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ XLNX_AUD_ALIGN_BYTES);
-+ if (err) {
-+ dev_err(component->dev,
+ if (err) {
+ dev_err(component->dev,
+- "unable to set constraint on period bytes\n");
+ "Unable to set constraint on buffer bytes\n");
+ return err;
+ }
@@ -165410,6 +255625,107 @@ index 91afea9d5de67..ce19a6058b279 100644
return err;
}
+@@ -429,11 +460,25 @@ static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
+ u64 size;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
++ struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
+
+ active_ch = params_channels(params);
+ if (active_ch > stream_data->ch_limit)
+ return -EINVAL;
+
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
++ adata->sysclk) {
++ unsigned int mclk_fs = adata->sysclk / params_rate(params);
++
++ if (adata->sysclk % params_rate(params) != 0) {
++ dev_warn(component->dev, "sysclk %u not divisible by rate %u\n",
++ adata->sysclk, params_rate(params));
++ return -EINVAL;
++ }
++
++ writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER);
++ }
++
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+ stream_data->xfer_mode == AES_TO_PCM) {
+ val = readl(stream_data->mmio + XLNX_AUD_STS);
+@@ -531,6 +576,7 @@ static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
+
+ static const struct snd_soc_component_driver xlnx_asoc_component = {
+ .name = DRV_NAME,
++ .set_sysclk = xlnx_formatter_set_sysclk,
+ .open = xlnx_formatter_pcm_open,
+ .close = xlnx_formatter_pcm_close,
+ .hw_params = xlnx_formatter_pcm_hw_params,
+diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
+index 76c0e37a838cf..8a2da6b1012eb 100644
+--- a/sound/spi/at73c213.c
++++ b/sound/spi/at73c213.c
+@@ -218,7 +218,9 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
+ runtime->hw = snd_at73c213_playback_hw;
+ chip->substream = substream;
+
+- clk_enable(chip->ssc->clk);
++ err = clk_enable(chip->ssc->clk);
++ if (err)
++ return err;
+
+ return 0;
+ }
+@@ -776,7 +778,9 @@ static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
+ goto out;
+
+ /* Enable DAC master clock. */
+- clk_enable(chip->board->dac_clk);
++ retval = clk_enable(chip->board->dac_clk);
++ if (retval)
++ goto out;
+
+ /* Initialize at73c213 on SPI bus. */
+ retval = snd_at73c213_write_reg(chip, DAC_RST, 0x04);
+@@ -889,7 +893,9 @@ static int snd_at73c213_dev_init(struct snd_card *card,
+ chip->card = card;
+ chip->irq = -1;
+
+- clk_enable(chip->ssc->clk);
++ retval = clk_enable(chip->ssc->clk);
++ if (retval)
++ return retval;
+
+ retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip);
+ if (retval) {
+@@ -1008,7 +1014,9 @@ static int snd_at73c213_remove(struct spi_device *spi)
+ int retval;
+
+ /* Stop playback. */
+- clk_enable(chip->ssc->clk);
++ retval = clk_enable(chip->ssc->clk);
++ if (retval)
++ goto out;
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS));
+ clk_disable(chip->ssc->clk);
+
+@@ -1088,9 +1096,16 @@ static int snd_at73c213_resume(struct device *dev)
+ {
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct snd_at73c213 *chip = card->private_data;
++ int retval;
+
+- clk_enable(chip->board->dac_clk);
+- clk_enable(chip->ssc->clk);
++ retval = clk_enable(chip->board->dac_clk);
++ if (retval)
++ return retval;
++ retval = clk_enable(chip->ssc->clk);
++ if (retval) {
++ clk_disable(chip->board->dac_clk);
++ return retval;
++ }
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN));
+
+ return 0;
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 49d1976a132c0..5ed8e36d2e043 100644
--- a/sound/synth/emux/emux.c
@@ -166270,6 +256586,18 @@ index 4e5693c97aa42..e33df58740a91 100644
GFP_KERNEL);
if (ret) {
+diff --git a/sound/usb/midi.c b/sound/usb/midi.c
+index 2c01649c70f61..7c6ca2b433a53 100644
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -1194,6 +1194,7 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
+ } while (drain_urbs && timeout);
+ finish_wait(&ep->drain_wait, &wait);
+ }
++ port->active = 0;
+ spin_unlock_irq(&ep->buffer_lock);
+ }
+
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 5834d1dc317ef..4f6b20ed29dd7 100644
--- a/sound/usb/misc/ua101.c
@@ -166307,8 +256635,29 @@ index 8e030b1c061ab..567514832b0df 100644
return filter_error(cval, ret);
}
+diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
+index 55eea90ee993f..6ffd23f2ee65d 100644
+--- a/sound/usb/mixer_maps.c
++++ b/sound/usb/mixer_maps.c
+@@ -536,6 +536,16 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
+ .id = USB_ID(0x1b1c, 0x0a41),
+ .map = corsair_virtuoso_map,
+ },
++ {
++ /* Corsair Virtuoso SE Latest (wired mode) */
++ .id = USB_ID(0x1b1c, 0x0a3f),
++ .map = corsair_virtuoso_map,
++ },
++ {
++ /* Corsair Virtuoso SE Latest (wireless mode) */
++ .id = USB_ID(0x1b1c, 0x0a40),
++ .map = corsair_virtuoso_map,
++ },
+ {
+ /* Corsair Virtuoso (wireless mode) */
+ .id = USB_ID(0x1b1c, 0x0a42),
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index 46082dc57be09..d48729e6a3b0a 100644
+index 46082dc57be09..d12b87e52d22a 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -2795,6 +2795,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
@@ -166385,8 +256734,22 @@ index 46082dc57be09..d48729e6a3b0a 100644
case USB_ID(0x08e4, 0x0163): /* Pioneer DJ DJM-850 */
err = snd_djm_controls_create(mixer, SND_DJM_850_IDX);
break;
+@@ -3328,9 +3362,10 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+ if (unitid == 7 && cval->control == UAC_FU_VOLUME)
+ snd_dragonfly_quirk_db_scale(mixer, cval, kctl);
+ break;
+- /* lowest playback value is muted on C-Media devices */
+- case USB_ID(0x0d8c, 0x000c):
+- case USB_ID(0x0d8c, 0x0014):
++ /* lowest playback value is muted on some devices */
++ case USB_ID(0x0d8c, 0x000c): /* C-Media */
++ case USB_ID(0x0d8c, 0x0014): /* C-Media */
++ case USB_ID(0x19f7, 0x0003): /* RODE NT-USB */
+ if (strstr(kctl->id.name, "Playback"))
+ cval->min_mute = 1;
+ break;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
-index 5dc9266180e37..2e51fb031ae01 100644
+index 5dc9266180e37..729e26f5ac4c7 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -219,16 +219,16 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip,
@@ -166485,6 +256848,18 @@ index 5dc9266180e37..2e51fb031ae01 100644
ret = start_endpoints(subs);
unlock:
+@@ -648,9 +669,9 @@ static const struct snd_pcm_hardware snd_usb_hardware =
+ SNDRV_PCM_INFO_PAUSE,
+ .channels_min = 1,
+ .channels_max = 256,
+- .buffer_bytes_max = 1024 * 1024,
++ .buffer_bytes_max = INT_MAX, /* limited by BUFFER_TIME later */
+ .period_bytes_min = 64,
+- .period_bytes_max = 512 * 1024,
++ .period_bytes_max = INT_MAX, /* limited by PERIOD_TIME later */
+ .periods_min = 2,
+ .periods_max = 1024,
+ };
@@ -734,6 +755,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
@@ -166508,7 +256883,26 @@ index 5dc9266180e37..2e51fb031ae01 100644
if (fp->rate_table && fp->nr_rates) {
for (i = 0; i < fp->nr_rates; i++) {
r = fp->rate_table[i];
-@@ -1068,6 +1098,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
+@@ -1034,6 +1064,18 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
+ return err;
+ }
+
++ /* set max period and buffer sizes for 1 and 2 seconds, respectively */
++ err = snd_pcm_hw_constraint_minmax(runtime,
++ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
++ 0, 1000000);
++ if (err < 0)
++ return err;
++ err = snd_pcm_hw_constraint_minmax(runtime,
++ SNDRV_PCM_HW_PARAM_BUFFER_TIME,
++ 0, 2000000);
++ if (err < 0)
++ return err;
++
+ /* additional hw constraints for implicit fb */
+ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+ hw_rule_format_implicit_fb, subs,
+@@ -1068,6 +1110,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
int ret;
runtime->hw = snd_usb_hardware;
@@ -166519,7 +256913,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
runtime->private_data = subs;
subs->pcm_substream = substream;
/* runtime PM is also done there */
-@@ -1320,44 +1354,66 @@ static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs,
+@@ -1320,44 +1366,66 @@ static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs,
return bytes;
}
@@ -166599,7 +256993,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
}
i++;
if (i < ctx->packets) {
-@@ -1371,13 +1427,19 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
+@@ -1371,13 +1439,19 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
}
}
/* finish at the period boundary or after enough frames */
@@ -166622,7 +257016,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
subs->cur_audiofmt->dsd_dop)) {
fill_playback_urb_dsd_dop(subs, urb, bytes);
-@@ -1403,14 +1465,23 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
+@@ -1403,14 +1477,23 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->trigger_tstamp_pending_update = false;
}
@@ -166649,7 +257043,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
}
/*
-@@ -1442,6 +1513,27 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
+@@ -1442,6 +1525,27 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
snd_pcm_period_elapsed(subs->pcm_substream);
}
@@ -166677,7 +257071,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
-@@ -1457,8 +1549,10 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
+@@ -1457,8 +1561,10 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
prepare_playback_urb,
retire_playback_urb,
subs);
@@ -166689,7 +257083,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
err = start_endpoints(subs);
if (err < 0) {
snd_usb_endpoint_set_callback(subs->data_endpoint,
-@@ -1473,7 +1567,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
+@@ -1473,7 +1579,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
return 0;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
@@ -166698,7 +257092,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
snd_usb_endpoint_set_callback(subs->data_endpoint,
NULL, NULL, NULL);
subs->running = 0;
-@@ -1521,7 +1615,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
+@@ -1521,7 +1627,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
return 0;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
@@ -166707,7 +257101,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
snd_usb_endpoint_set_callback(subs->data_endpoint,
-@@ -1545,6 +1639,7 @@ static const struct snd_pcm_ops snd_usb_playback_ops = {
+@@ -1545,6 +1651,7 @@ static const struct snd_pcm_ops snd_usb_playback_ops = {
.trigger = snd_usb_substream_playback_trigger,
.sync_stop = snd_usb_pcm_sync_stop,
.pointer = snd_usb_pcm_pointer,
@@ -166716,7 +257110,7 @@ index 5dc9266180e37..2e51fb031ae01 100644
static const struct snd_pcm_ops snd_usb_capture_ops = {
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
-index 2af8c68fac275..0ea39565e6232 100644
+index 2af8c68fac275..40a5e3eb4ef26 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -84,7 +84,7 @@
@@ -166728,7 +257122,23 @@ index 2af8c68fac275..0ea39565e6232 100644
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
-@@ -3892,6 +3892,64 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+@@ -3235,6 +3235,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ },
+
++/* Rane SL-1 */
++{
++ USB_DEVICE(0x13e5, 0x0001),
++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE
++ }
++},
++
+ /* disabled due to regression for other devices;
+ * see https://bugzilla.kernel.org/show_bug.cgi?id=199905
+ */
+@@ -3892,6 +3901,64 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
@@ -166823,8 +257233,21 @@ index 8929d9abe8aa8..ab9f3da49941f 100644
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index 167834133b9bc..b8359a0aa008a 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -8,7 +8,7 @@
+ */
+
+ /* handling of USB vendor/product ID pairs as 32-bit numbers */
+-#define USB_ID(vendor, product) (((vendor) << 16) | (product))
++#define USB_ID(vendor, product) (((unsigned int)(vendor) << 16) | (product))
+ #define USB_ID_VENDOR(id) ((id) >> 16)
+ #define USB_ID_PRODUCT(id) ((u16)(id))
+
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
-index 378826312abe6..7aa9472749002 100644
+index 378826312abe6..42add5df37fda 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -1261,7 +1261,7 @@ static int had_pcm_mmap(struct snd_pcm_substream *substream,
@@ -166836,6 +257259,27 @@ index 378826312abe6..7aa9472749002 100644
vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
+@@ -1665,7 +1665,7 @@ static void hdmi_lpe_audio_free(struct snd_card *card)
+ * This function is called when the i915 driver creates the
+ * hdmi-lpe-audio platform device.
+ */
+-static int hdmi_lpe_audio_probe(struct platform_device *pdev)
++static int __hdmi_lpe_audio_probe(struct platform_device *pdev)
+ {
+ struct snd_card *card;
+ struct snd_intelhad_card *card_ctx;
+@@ -1826,6 +1826,11 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
+ return 0;
+ }
+
++static int hdmi_lpe_audio_probe(struct platform_device *pdev)
++{
++ return snd_card_free_on_error(&pdev->dev, __hdmi_lpe_audio_probe(pdev));
++}
++
+ static const struct dev_pm_ops hdmi_lpe_audio_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(hdmi_lpe_audio_suspend, hdmi_lpe_audio_resume)
+ };
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index d0ce5cfd3ac14..63d30dde20f94 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
@@ -166849,6 +257293,22 @@ index d0ce5cfd3ac14..63d30dde20f94 100644
#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
#define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */
#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */
+diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h
+index a7c413432b33d..66ae309840fef 100644
+--- a/tools/arch/x86/include/asm/msr-index.h
++++ b/tools/arch/x86/include/asm/msr-index.h
+@@ -128,9 +128,9 @@
+ #define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */
+ #define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */
+
+-/* SRBDS support */
+ #define MSR_IA32_MCU_OPT_CTRL 0x00000123
+-#define RNGDS_MITG_DIS BIT(0)
++#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
++#define RTM_ALLOW BIT(1) /* TSX development mode */
+
+ #define MSR_IA32_SYSENTER_CS 0x00000174
+ #define MSR_IA32_SYSENTER_ESP 0x00000175
diff --git a/tools/arch/x86/lib/insn.c b/tools/arch/x86/lib/insn.c
index 797699462cd8e..8fd63a067308a 100644
--- a/tools/arch/x86/lib/insn.c
@@ -166874,6 +257334,95 @@ index 797699462cd8e..8fd63a067308a 100644
#define get_next(t, insn) \
({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
+diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
+index 1cc9da6e29c79..59cf2343f3d90 100644
+--- a/tools/arch/x86/lib/memcpy_64.S
++++ b/tools/arch/x86/lib/memcpy_64.S
+@@ -39,7 +39,7 @@ SYM_FUNC_START_WEAK(memcpy)
+ rep movsq
+ movl %edx, %ecx
+ rep movsb
+- ret
++ RET
+ SYM_FUNC_END(memcpy)
+ SYM_FUNC_END_ALIAS(__memcpy)
+ EXPORT_SYMBOL(memcpy)
+@@ -53,7 +53,7 @@ SYM_FUNC_START_LOCAL(memcpy_erms)
+ movq %rdi, %rax
+ movq %rdx, %rcx
+ rep movsb
+- ret
++ RET
+ SYM_FUNC_END(memcpy_erms)
+
+ SYM_FUNC_START_LOCAL(memcpy_orig)
+@@ -137,7 +137,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movq %r9, 1*8(%rdi)
+ movq %r10, -2*8(%rdi, %rdx)
+ movq %r11, -1*8(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_16bytes:
+ cmpl $8, %edx
+@@ -149,7 +149,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movq -1*8(%rsi, %rdx), %r9
+ movq %r8, 0*8(%rdi)
+ movq %r9, -1*8(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_8bytes:
+ cmpl $4, %edx
+@@ -162,7 +162,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movl -4(%rsi, %rdx), %r8d
+ movl %ecx, (%rdi)
+ movl %r8d, -4(%rdi, %rdx)
+- retq
++ RET
+ .p2align 4
+ .Lless_3bytes:
+ subl $1, %edx
+@@ -180,7 +180,7 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
+ movb %cl, (%rdi)
+
+ .Lend:
+- retq
++ RET
+ SYM_FUNC_END(memcpy_orig)
+
+ .popsection
+diff --git a/tools/arch/x86/lib/memset_64.S b/tools/arch/x86/lib/memset_64.S
+index 9827ae267f96e..d624f2bc42f16 100644
+--- a/tools/arch/x86/lib/memset_64.S
++++ b/tools/arch/x86/lib/memset_64.S
+@@ -40,7 +40,7 @@ SYM_FUNC_START(__memset)
+ movl %edx,%ecx
+ rep stosb
+ movq %r9,%rax
+- ret
++ RET
+ SYM_FUNC_END(__memset)
+ SYM_FUNC_END_ALIAS(memset)
+ EXPORT_SYMBOL(memset)
+@@ -63,7 +63,7 @@ SYM_FUNC_START_LOCAL(memset_erms)
+ movq %rdx,%rcx
+ rep stosb
+ movq %r9,%rax
+- ret
++ RET
+ SYM_FUNC_END(memset_erms)
+
+ SYM_FUNC_START_LOCAL(memset_orig)
+@@ -125,7 +125,7 @@ SYM_FUNC_START_LOCAL(memset_orig)
+
+ .Lende:
+ movq %r10,%rax
+- ret
++ RET
+
+ .Lbad_alignment:
+ cmpq $7,%rdx
diff --git a/tools/bpf/bpftool/Documentation/Makefile b/tools/bpf/bpftool/Documentation/Makefile
index c49487905cebe..f89929c7038d5 100644
--- a/tools/bpf/bpftool/Documentation/Makefile
@@ -167010,6 +257559,26 @@ index d73232be1e991..cce52df3be064 100644
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
+index d40d92bbf0e48..07fa502a4ac15 100644
+--- a/tools/bpf/bpftool/gen.c
++++ b/tools/bpf/bpftool/gen.c
+@@ -870,7 +870,6 @@ static int do_skeleton(int argc, char **argv)
+ s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
+ if (!s) \n\
+ goto err; \n\
+- obj->skeleton = s; \n\
+ \n\
+ s->sz = sizeof(*s); \n\
+ s->name = \"%1$s\"; \n\
+@@ -955,6 +954,7 @@ static int do_skeleton(int argc, char **argv)
+ \n\
+ \"; \n\
+ \n\
++ obj->skeleton = s; \n\
+ return 0; \n\
+ err: \n\
+ bpf_object__destroy_skeleton(s); \n\
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 02eaaf065f651..d27ec4f852bbb 100644
--- a/tools/bpf/bpftool/main.c
@@ -167023,6 +257592,24 @@ index 02eaaf065f651..d27ec4f852bbb 100644
last_do_help = do_help;
pretty_output = false;
json_output = false;
+diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
+index 407071d54ab1c..72ef9ddae2609 100644
+--- a/tools/bpf/bpftool/map.c
++++ b/tools/bpf/bpftool/map.c
+@@ -1042,11 +1042,9 @@ static void print_key_value(struct bpf_map_info *info, void *key,
+ json_writer_t *btf_wtr;
+ struct btf *btf;
+
+- btf = btf__load_from_kernel_by_id(info->btf_id);
+- if (libbpf_get_error(btf)) {
+- p_err("failed to get btf");
++ btf = get_map_kv_btf(info);
++ if (libbpf_get_error(btf))
+ return;
+- }
+
+ if (json_output) {
+ print_entry_json(info, key, value, btf);
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 9c3e343b7d872..f8755beb3d9eb 100644
--- a/tools/bpf/bpftool/prog.c
@@ -167155,7 +257742,7 @@ index de6365b53c9ca..45e0d640618ac 100644
if (symbols_collect(&obj))
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
-index 3dd2f68366f95..88dd7db55d385 100644
+index 3dd2f68366f95..6abde487bba19 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -48,7 +48,6 @@ FEATURE_TESTS_BASIC := \
@@ -167166,8 +257753,16 @@ index 3dd2f68366f95..88dd7db55d385 100644
libslang \
libslang-include-subdir \
libtraceevent \
+@@ -98,6 +97,7 @@ FEATURE_TESTS_EXTRA := \
+ llvm-version \
+ clang \
+ libbpf \
++ libbpf-btf__load_from_kernel_by_id \
+ libpfm4 \
+ libdebuginfod \
+ clang-bpf-co-re
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
-index eff55d287db1f..e1e670014bd0c 100644
+index eff55d287db1f..69a43d9ea331f 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -32,7 +32,6 @@ FILES= \
@@ -167178,7 +257773,32 @@ index eff55d287db1f..e1e670014bd0c 100644
test-libslang.bin \
test-libslang-include-subdir.bin \
test-libtraceevent.bin \
-@@ -223,9 +222,6 @@ $(OUTPUT)test-libperl.bin:
+@@ -57,6 +56,7 @@ FILES= \
+ test-lzma.bin \
+ test-bpf.bin \
+ test-libbpf.bin \
++ test-libbpf-btf__load_from_kernel_by_id.bin \
+ test-get_cpuid.bin \
+ test-sdt.bin \
+ test-cxx.bin \
+@@ -214,18 +214,22 @@ strip-libs = $(filter-out -l%,$(1))
+ PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
+ PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
+ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
+-PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
++PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null)
+ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
+
++ifeq ($(CC_NO_CLANG), 0)
++ PERL_EMBED_LDOPTS := $(filter-out -specs=%,$(PERL_EMBED_LDOPTS))
++ PERL_EMBED_CCOPTS := $(filter-out -flto=auto -ffat-lto-objects, $(PERL_EMBED_CCOPTS))
++ PERL_EMBED_CCOPTS := $(filter-out -specs=%,$(PERL_EMBED_CCOPTS))
++ FLAGS_PERL_EMBED += -Wno-compound-token-split-by-macro
++endif
++
+ $(OUTPUT)test-libperl.bin:
+ $(BUILD) $(FLAGS_PERL_EMBED)
+
$(OUTPUT)test-libpython.bin:
$(BUILD) $(FLAGS_PYTHON_EMBED)
@@ -167188,6 +257808,16 @@ index eff55d287db1f..e1e670014bd0c 100644
$(OUTPUT)test-libbfd.bin:
$(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
+@@ -280,6 +284,9 @@ $(OUTPUT)test-bpf.bin:
+ $(OUTPUT)test-libbpf.bin:
+ $(BUILD) -lbpf
+
++$(OUTPUT)test-libbpf-btf__load_from_kernel_by_id.bin:
++ $(BUILD) -lbpf
++
+ $(OUTPUT)test-sdt.bin:
+ $(BUILD)
+
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index 9204395272912..5ffafb967b6e4 100644
--- a/tools/build/feature/test-all.c
@@ -167219,6 +257849,19 @@ index 9204395272912..5ffafb967b6e4 100644
main_test_zlib();
main_test_pthread_attr_setaffinity_np();
main_test_pthread_barrier();
+diff --git a/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c b/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c
+new file mode 100644
+index 0000000000000..f7c084428735a
+--- /dev/null
++++ b/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c
+@@ -0,0 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <bpf/libbpf.h>
++
++int main(void)
++{
++ return btf__load_from_kernel_by_id(20151128, NULL);
++}
diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c
deleted file mode 100644
index 47714b942d4d3..0000000000000
@@ -167361,6 +258004,21 @@ index 3430667b0d241..3e2c6f2ed587f 100644
"li a7, 93\n" // NR_exit == 93
"ecall\n"
"");
+diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
+index 791f31dd0abee..e2c8f946c5416 100644
+--- a/tools/include/uapi/linux/bpf.h
++++ b/tools/include/uapi/linux/bpf.h
+@@ -2276,8 +2276,8 @@ union bpf_attr {
+ * Return
+ * The return value depends on the result of the test, and can be:
+ *
+- * * 0, if current task belongs to the cgroup2.
+- * * 1, if current task does not belong to the cgroup2.
++ * * 1, if current task belongs to the cgroup2.
++ * * 0, if current task does not belong to the cgroup2.
+ * * A negative error code, if an error occurred.
+ *
+ * long bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags)
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h
index 5859ca0a1439b..93e40f91bd49a 100644
--- a/tools/include/uapi/sound/asound.h
@@ -167377,6 +258035,28 @@ index 5859ca0a1439b..93e40f91bd49a 100644
unsigned char subcode[147]; /* AES/IEC958 subcode bits */
unsigned char pad; /* nothing */
unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
+diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
+index 74c3b73a5fbe8..089b73b3cb379 100644
+--- a/tools/lib/bpf/Makefile
++++ b/tools/lib/bpf/Makefile
+@@ -126,7 +126,7 @@ GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
+ sort -u | wc -l)
+ VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+ sed 's/\[.*\]//' | \
+- awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
++ awk '/GLOBAL/ && /DEFAULT/ && !/UND|ABS/ {print $$NF}' | \
+ grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
+
+ CMD_TARGETS = $(LIB_TARGET) $(PC_FILE)
+@@ -195,7 +195,7 @@ check_abi: $(OUTPUT)libbpf.so $(VERSION_SCRIPT)
+ sort -u > $(OUTPUT)libbpf_global_syms.tmp; \
+ readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+ sed 's/\[.*\]//' | \
+- awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
++ awk '/GLOBAL/ && /DEFAULT/ && !/UND|ABS/ {print $$NF}'| \
+ grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | \
+ sort -u > $(OUTPUT)libbpf_versioned_syms.tmp; \
+ diff -u $(OUTPUT)libbpf_global_syms.tmp \
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 2401fad090c52..bfd1ce9fe2110 100644
--- a/tools/lib/bpf/bpf.c
@@ -167573,10 +258253,41 @@ index 4a711f990904b..b0ee338a0cc87 100644
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext,
__u32 *size);
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
-index e4b483f15fb99..8c9325802793b 100644
+index e4b483f15fb99..841cc68e3f427 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
-@@ -2186,7 +2186,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d,
+@@ -1481,6 +1481,11 @@ static const char *btf_dump_resolve_name(struct btf_dump *d, __u32 id,
+ if (s->name_resolved)
+ return *cached_name ? *cached_name : orig_name;
+
++ if (btf_is_fwd(t) || (btf_is_enum(t) && btf_vlen(t) == 0)) {
++ s->name_resolved = 1;
++ return orig_name;
++ }
++
+ dup_cnt = btf_dump_name_dups(d, name_map, orig_name);
+ if (dup_cnt > 1) {
+ const size_t max_len = 256;
+@@ -1829,14 +1834,16 @@ static int btf_dump_array_data(struct btf_dump *d,
+ {
+ const struct btf_array *array = btf_array(t);
+ const struct btf_type *elem_type;
+- __u32 i, elem_size = 0, elem_type_id;
++ __u32 i, elem_type_id;
++ __s64 elem_size;
+ bool is_array_member;
+
+ elem_type_id = array->type;
+ elem_type = skip_mods_and_typedefs(d->btf, elem_type_id, NULL);
+ elem_size = btf__resolve_size(d->btf, elem_type_id);
+ if (elem_size <= 0) {
+- pr_warn("unexpected elem size %d for array type [%u]\n", elem_size, id);
++ pr_warn("unexpected elem size %zd for array type [%u]\n",
++ (ssize_t)elem_size, id);
+ return -EINVAL;
+ }
+
+@@ -2186,7 +2193,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d,
__u8 bits_offset,
__u8 bit_sz)
{
@@ -167603,7 +258314,7 @@ index 8df718a6b142d..33c19590ee434 100644
/* remember prog_fd in the stack, if successful */
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
-index e4f83c304ec92..0ad29203cbfbf 100644
+index e4f83c304ec92..693e14799fb96 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2993,6 +2993,12 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -167640,6 +258351,16 @@ index e4f83c304ec92..0ad29203cbfbf 100644
map->inner_map_fd = fd;
return 0;
}
+@@ -10800,6 +10809,9 @@ void bpf_object__detach_skeleton(struct bpf_object_skeleton *s)
+
+ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s)
+ {
++ if (!s)
++ return;
++
+ if (s->progs)
+ bpf_object__detach_skeleton(s);
+ if (s->obj)
diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c
index 2df880cefdaee..6b2f59ddb6918 100644
--- a/tools/lib/bpf/linker.c
@@ -167671,6 +258392,120 @@ index 2df880cefdaee..6b2f59ddb6918 100644
/* shdr->sh_link points to SYMTAB */
dst_sec->shdr->sh_link = linker->symtab_sec_idx;
+diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
+index 39f25e09b51e2..fadde7d80a51c 100644
+--- a/tools/lib/bpf/netlink.c
++++ b/tools/lib/bpf/netlink.c
+@@ -87,29 +87,75 @@ enum {
+ NL_DONE,
+ };
+
++static int netlink_recvmsg(int sock, struct msghdr *mhdr, int flags)
++{
++ int len;
++
++ do {
++ len = recvmsg(sock, mhdr, flags);
++ } while (len < 0 && (errno == EINTR || errno == EAGAIN));
++
++ if (len < 0)
++ return -errno;
++ return len;
++}
++
++static int alloc_iov(struct iovec *iov, int len)
++{
++ void *nbuf;
++
++ nbuf = realloc(iov->iov_base, len);
++ if (!nbuf)
++ return -ENOMEM;
++
++ iov->iov_base = nbuf;
++ iov->iov_len = len;
++ return 0;
++}
++
+ static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq,
+ __dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn,
+ void *cookie)
+ {
++ struct iovec iov = {};
++ struct msghdr mhdr = {
++ .msg_iov = &iov,
++ .msg_iovlen = 1,
++ };
+ bool multipart = true;
+ struct nlmsgerr *err;
+ struct nlmsghdr *nh;
+- char buf[4096];
+ int len, ret;
+
++ ret = alloc_iov(&iov, 4096);
++ if (ret)
++ goto done;
++
+ while (multipart) {
+ start:
+ multipart = false;
+- len = recv(sock, buf, sizeof(buf), 0);
++ len = netlink_recvmsg(sock, &mhdr, MSG_PEEK | MSG_TRUNC);
++ if (len < 0) {
++ ret = len;
++ goto done;
++ }
++
++ if (len > iov.iov_len) {
++ ret = alloc_iov(&iov, len);
++ if (ret)
++ goto done;
++ }
++
++ len = netlink_recvmsg(sock, &mhdr, 0);
+ if (len < 0) {
+- ret = -errno;
++ ret = len;
+ goto done;
+ }
+
+ if (len == 0)
+ break;
+
+- for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
++ for (nh = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(nh, len);
+ nh = NLMSG_NEXT(nh, len)) {
+ if (nh->nlmsg_pid != nl_pid) {
+ ret = -LIBBPF_ERRNO__WRNGPID;
+@@ -130,7 +176,8 @@ start:
+ libbpf_nla_dump_errormsg(nh);
+ goto done;
+ case NLMSG_DONE:
+- return 0;
++ ret = 0;
++ goto done;
+ default:
+ break;
+ }
+@@ -142,15 +189,17 @@ start:
+ case NL_NEXT:
+ goto start;
+ case NL_DONE:
+- return 0;
++ ret = 0;
++ goto done;
+ default:
+- return ret;
++ goto done;
+ }
+ }
+ }
+ }
+ ret = 0;
+ done:
++ free(iov.iov_base);
+ return ret;
+ }
+
diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h
index b22b50c1b173e..9cf66702fa8dd 100644
--- a/tools/lib/bpf/skel_internal.h
@@ -167690,6 +258525,55 @@ index b22b50c1b173e..9cf66702fa8dd 100644
goto out;
}
err = 0;
+diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
+index e9b619aa0cdf3..a27b3141463ad 100644
+--- a/tools/lib/bpf/xsk.c
++++ b/tools/lib/bpf/xsk.c
+@@ -1210,12 +1210,23 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
+
+ int xsk_umem__delete(struct xsk_umem *umem)
+ {
++ struct xdp_mmap_offsets off;
++ int err;
++
+ if (!umem)
+ return 0;
+
+ if (umem->refcount)
+ return -EBUSY;
+
++ err = xsk_get_mmap_offsets(umem->fd, &off);
++ if (!err && umem->fill_save && umem->comp_save) {
++ munmap(umem->fill_save->ring - off.fr.desc,
++ off.fr.desc + umem->config.fill_size * sizeof(__u64));
++ munmap(umem->comp_save->ring - off.cr.desc,
++ off.cr.desc + umem->config.comp_size * sizeof(__u64));
++ }
++
+ close(umem->fd);
+ free(umem);
+
+diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
+index e37dfad31383f..5146ff0fa078c 100644
+--- a/tools/lib/perf/evlist.c
++++ b/tools/lib/perf/evlist.c
+@@ -577,7 +577,6 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
+ {
+ struct perf_evsel *evsel;
+ const struct perf_cpu_map *cpus = evlist->cpus;
+- const struct perf_thread_map *threads = evlist->threads;
+
+ if (!ops || !ops->get || !ops->mmap)
+ return -EINVAL;
+@@ -589,7 +588,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
+ perf_evlist__for_each_entry(evlist, evsel) {
+ if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+ evsel->sample_id == NULL &&
+- perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0)
++ perf_evsel__alloc_id(evsel, evsel->fd->max_x, evsel->fd->max_y) < 0)
+ return -ENOMEM;
+ }
+
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
index 794a375dad360..b2aec04fce8f6 100644
--- a/tools/lib/subcmd/subcmd-util.h
@@ -167713,10 +258597,22 @@ index 794a375dad360..b2aec04fce8f6 100644
}
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
-index 0893436cc09f8..77b51600e3e94 100644
+index 0893436cc09f8..63ffbc36dacc2 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
-@@ -659,6 +659,26 @@ const char *arch_nop_insn(int len)
+@@ -529,6 +529,11 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
+ }
+ break;
+
++ case 0xcc:
++ /* int3 */
++ *type = INSN_TRAP;
++ break;
++
+ case 0xe3:
+ /* jecxz/jrcxz */
+ *type = INSN_JUMP_CONDITIONAL;
+@@ -659,6 +664,26 @@ const char *arch_nop_insn(int len)
return nops[len-1];
}
@@ -167726,10 +258622,10 @@ index 0893436cc09f8..77b51600e3e94 100644
+{
+ static const char ret[5][5] = {
+ { BYTE_RET },
-+ { BYTE_RET, BYTES_NOP1 },
-+ { BYTE_RET, BYTES_NOP2 },
-+ { BYTE_RET, BYTES_NOP3 },
-+ { BYTE_RET, BYTES_NOP4 },
++ { BYTE_RET, 0xcc },
++ { BYTE_RET, 0xcc, BYTES_NOP1 },
++ { BYTE_RET, 0xcc, BYTES_NOP2 },
++ { BYTE_RET, 0xcc, BYTES_NOP3 },
+ };
+
+ if (len < 1 || len > 5) {
@@ -167743,8 +258639,29 @@ index 0893436cc09f8..77b51600e3e94 100644
/* asm/alternative.h ? */
#define ALTINSTR_FLAG_INV (1 << 15)
+diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
+index 8b38b5d6fec7b..38070f26105bd 100644
+--- a/tools/objtool/builtin-check.c
++++ b/tools/objtool/builtin-check.c
+@@ -20,7 +20,7 @@
+ #include <objtool/objtool.h>
+
+ bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats,
+- validate_dup, vmlinux, mcount, noinstr, backup;
++ validate_dup, vmlinux, mcount, noinstr, backup, sls;
+
+ static const char * const check_usage[] = {
+ "objtool check [<options>] file.o",
+@@ -45,6 +45,7 @@ const struct option check_options[] = {
+ OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"),
+ OPT_BOOLEAN('M', "mcount", &mcount, "generate __mcount_loc"),
+ OPT_BOOLEAN('B', "backup", &backup, "create .orig files before modification"),
++ OPT_BOOLEAN('S', "sls", &sls, "validate straight-line-speculation"),
+ OPT_END(),
+ };
+
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
-index 06b5c164ae931..81982948f981d 100644
+index 06b5c164ae931..66c7c13098b31 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -173,6 +173,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
@@ -167755,7 +258672,37 @@ index 06b5c164ae931..81982948f981d 100644
};
if (!func)
-@@ -828,6 +829,79 @@ static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *i
+@@ -392,12 +393,12 @@ static int add_dead_ends(struct objtool_file *file)
+ else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+ insn = find_last_insn(file, reloc->sym->sec);
+ if (!insn) {
+- WARN("can't find unreachable insn at %s+0x%x",
++ WARN("can't find unreachable insn at %s+0x%lx",
+ reloc->sym->sec->name, reloc->addend);
+ return -1;
+ }
+ } else {
+- WARN("can't find unreachable insn at %s+0x%x",
++ WARN("can't find unreachable insn at %s+0x%lx",
+ reloc->sym->sec->name, reloc->addend);
+ return -1;
+ }
+@@ -427,12 +428,12 @@ reachable:
+ else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+ insn = find_last_insn(file, reloc->sym->sec);
+ if (!insn) {
+- WARN("can't find reachable insn at %s+0x%x",
++ WARN("can't find reachable insn at %s+0x%lx",
+ reloc->sym->sec->name, reloc->addend);
+ return -1;
+ }
+ } else {
+- WARN("can't find reachable insn at %s+0x%x",
++ WARN("can't find reachable insn at %s+0x%lx",
+ reloc->sym->sec->name, reloc->addend);
+ return -1;
+ }
+@@ -828,6 +829,89 @@ static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *i
return insn->reloc;
}
@@ -167801,6 +258748,16 @@ index 06b5c164ae931..81982948f981d 100644
+ : arch_nop_insn(insn->len));
+
+ insn->type = sibling ? INSN_RETURN : INSN_NOP;
++
++ if (sibling) {
++ /*
++ * We've replaced the tail-call JMP insn by two new
++ * insn: RET; INT3, except we only have a single struct
++ * insn here. Mark it retpoline_safe to avoid the SLS
++ * warning, instead of adding another insn.
++ */
++ insn->retpoline_safe = true;
++ }
+ }
+
+ if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) {
@@ -167835,7 +258792,7 @@ index 06b5c164ae931..81982948f981d 100644
/*
* Find the destination instructions for all jumps.
*/
-@@ -866,11 +940,7 @@ static int add_jump_destinations(struct objtool_file *file)
+@@ -866,11 +950,7 @@ static int add_jump_destinations(struct objtool_file *file)
continue;
} else if (insn->func) {
/* internal or external sibling call (with reloc) */
@@ -167848,7 +258805,7 @@ index 06b5c164ae931..81982948f981d 100644
continue;
} else if (reloc->sym->sec->idx) {
dest_sec = reloc->sym->sec;
-@@ -926,13 +996,8 @@ static int add_jump_destinations(struct objtool_file *file)
+@@ -926,13 +1006,8 @@ static int add_jump_destinations(struct objtool_file *file)
} else if (insn->jump_dest->func->pfunc != insn->func->pfunc &&
insn->jump_dest->offset == insn->jump_dest->func->offset) {
@@ -167863,7 +258820,7 @@ index 06b5c164ae931..81982948f981d 100644
}
}
}
-@@ -940,16 +1005,6 @@ static int add_jump_destinations(struct objtool_file *file)
+@@ -940,16 +1015,6 @@ static int add_jump_destinations(struct objtool_file *file)
return 0;
}
@@ -167880,7 +258837,7 @@ index 06b5c164ae931..81982948f981d 100644
static struct symbol *find_call_destination(struct section *sec, unsigned long offset)
{
struct symbol *call_dest;
-@@ -968,6 +1023,7 @@ static int add_call_destinations(struct objtool_file *file)
+@@ -968,6 +1033,7 @@ static int add_call_destinations(struct objtool_file *file)
{
struct instruction *insn;
unsigned long dest_off;
@@ -167888,7 +258845,7 @@ index 06b5c164ae931..81982948f981d 100644
struct reloc *reloc;
for_each_insn(file, insn) {
-@@ -977,7 +1033,9 @@ static int add_call_destinations(struct objtool_file *file)
+@@ -977,7 +1043,9 @@ static int add_call_destinations(struct objtool_file *file)
reloc = insn_reloc(file, insn);
if (!reloc) {
dest_off = arch_jump_destination(insn);
@@ -167899,7 +258856,7 @@ index 06b5c164ae931..81982948f981d 100644
if (insn->ignore)
continue;
-@@ -995,9 +1053,8 @@ static int add_call_destinations(struct objtool_file *file)
+@@ -995,9 +1063,8 @@ static int add_call_destinations(struct objtool_file *file)
} else if (reloc->sym->type == STT_SECTION) {
dest_off = arch_dest_reloc_offset(reloc->addend);
@@ -167911,7 +258868,7 @@ index 06b5c164ae931..81982948f981d 100644
WARN_FUNC("can't find call dest symbol at %s+0x%lx",
insn->sec, insn->offset,
reloc->sym->sec->name,
-@@ -1005,6 +1062,8 @@ static int add_call_destinations(struct objtool_file *file)
+@@ -1005,6 +1072,8 @@ static int add_call_destinations(struct objtool_file *file)
return -1;
}
@@ -167920,7 +258877,7 @@ index 06b5c164ae931..81982948f981d 100644
} else if (arch_is_retpoline(reloc->sym)) {
/*
* Retpoline calls are really dynamic calls in
-@@ -1020,55 +1079,7 @@ static int add_call_destinations(struct objtool_file *file)
+@@ -1020,55 +1089,7 @@ static int add_call_destinations(struct objtool_file *file)
continue;
} else
@@ -167977,11 +258934,263 @@ index 06b5c164ae931..81982948f981d 100644
}
return 0;
+@@ -2765,6 +2786,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ switch (insn->type) {
+
+ case INSN_RETURN:
++ if (next_insn && next_insn->type == INSN_TRAP) {
++ next_insn->ignore = true;
++ } else if (sls && !insn->retpoline_safe) {
++ WARN_FUNC("missing int3 after ret",
++ insn->sec, insn->offset);
++ }
+ return validate_return(func, insn, &state);
+
+ case INSN_CALL:
+@@ -2808,6 +2835,14 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ break;
+
+ case INSN_JUMP_DYNAMIC:
++ if (next_insn && next_insn->type == INSN_TRAP) {
++ next_insn->ignore = true;
++ } else if (sls && !insn->retpoline_safe) {
++ WARN_FUNC("missing int3 after indirect jump",
++ insn->sec, insn->offset);
++ }
++
++ /* fallthrough */
+ case INSN_JUMP_DYNAMIC_CONDITIONAL:
+ if (is_sibling_call(insn)) {
+ ret = validate_sibling_call(insn, &state);
+diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
+index fee03b744a6ea..a3395467c3161 100644
+--- a/tools/objtool/elf.c
++++ b/tools/objtool/elf.c
+@@ -485,7 +485,7 @@ static struct section *elf_create_reloc_section(struct elf *elf,
+ int reltype);
+
+ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
+- unsigned int type, struct symbol *sym, int addend)
++ unsigned int type, struct symbol *sym, long addend)
+ {
+ struct reloc *reloc;
+
+@@ -514,37 +514,180 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
+ return 0;
+ }
+
+-int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
+- unsigned long offset, unsigned int type,
+- struct section *insn_sec, unsigned long insn_off)
++/*
++ * Ensure that any reloc section containing references to @sym is marked
++ * changed such that it will get re-generated in elf_rebuild_reloc_sections()
++ * with the new symbol index.
++ */
++static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym)
++{
++ struct section *sec;
++
++ list_for_each_entry(sec, &elf->sections, list) {
++ struct reloc *reloc;
++
++ if (sec->changed)
++ continue;
++
++ list_for_each_entry(reloc, &sec->reloc_list, list) {
++ if (reloc->sym == sym) {
++ sec->changed = true;
++ break;
++ }
++ }
++ }
++}
++
++/*
++ * Move the first global symbol, as per sh_info, into a new, higher symbol
++ * index. This fees up the shndx for a new local symbol.
++ */
++static int elf_move_global_symbol(struct elf *elf, struct section *symtab,
++ struct section *symtab_shndx)
+ {
++ Elf_Data *data, *shndx_data = NULL;
++ Elf32_Word first_non_local;
+ struct symbol *sym;
+- int addend;
++ Elf_Scn *s;
+
+- if (insn_sec->sym) {
+- sym = insn_sec->sym;
+- addend = insn_off;
++ first_non_local = symtab->sh.sh_info;
+
+- } else {
+- /*
+- * The Clang assembler strips section symbols, so we have to
+- * reference the function symbol instead:
+- */
+- sym = find_symbol_containing(insn_sec, insn_off);
+- if (!sym) {
+- /*
+- * Hack alert. This happens when we need to reference
+- * the NOP pad insn immediately after the function.
+- */
+- sym = find_symbol_containing(insn_sec, insn_off - 1);
++ sym = find_symbol_by_index(elf, first_non_local);
++ if (!sym) {
++ WARN("no non-local symbols !?");
++ return first_non_local;
++ }
++
++ s = elf_getscn(elf->elf, symtab->idx);
++ if (!s) {
++ WARN_ELF("elf_getscn");
++ return -1;
++ }
++
++ data = elf_newdata(s);
++ if (!data) {
++ WARN_ELF("elf_newdata");
++ return -1;
++ }
++
++ data->d_buf = &sym->sym;
++ data->d_size = sizeof(sym->sym);
++ data->d_align = 1;
++ data->d_type = ELF_T_SYM;
++
++ sym->idx = symtab->sh.sh_size / sizeof(sym->sym);
++ elf_dirty_reloc_sym(elf, sym);
++
++ symtab->sh.sh_info += 1;
++ symtab->sh.sh_size += data->d_size;
++ symtab->changed = true;
++
++ if (symtab_shndx) {
++ s = elf_getscn(elf->elf, symtab_shndx->idx);
++ if (!s) {
++ WARN_ELF("elf_getscn");
++ return -1;
+ }
+
+- if (!sym) {
+- WARN("can't find symbol containing %s+0x%lx", insn_sec->name, insn_off);
++ shndx_data = elf_newdata(s);
++ if (!shndx_data) {
++ WARN_ELF("elf_newshndx_data");
+ return -1;
+ }
+
+- addend = insn_off - sym->offset;
++ shndx_data->d_buf = &sym->sec->idx;
++ shndx_data->d_size = sizeof(Elf32_Word);
++ shndx_data->d_align = 4;
++ shndx_data->d_type = ELF_T_WORD;
++
++ symtab_shndx->sh.sh_size += 4;
++ symtab_shndx->changed = true;
++ }
++
++ return first_non_local;
++}
++
++static struct symbol *
++elf_create_section_symbol(struct elf *elf, struct section *sec)
++{
++ struct section *symtab, *symtab_shndx;
++ Elf_Data *shndx_data = NULL;
++ struct symbol *sym;
++ Elf32_Word shndx;
++
++ symtab = find_section_by_name(elf, ".symtab");
++ if (symtab) {
++ symtab_shndx = find_section_by_name(elf, ".symtab_shndx");
++ if (symtab_shndx)
++ shndx_data = symtab_shndx->data;
++ } else {
++ WARN("no .symtab");
++ return NULL;
++ }
++
++ sym = malloc(sizeof(*sym));
++ if (!sym) {
++ perror("malloc");
++ return NULL;
++ }
++ memset(sym, 0, sizeof(*sym));
++
++ sym->idx = elf_move_global_symbol(elf, symtab, symtab_shndx);
++ if (sym->idx < 0) {
++ WARN("elf_move_global_symbol");
++ return NULL;
++ }
++
++ sym->name = sec->name;
++ sym->sec = sec;
++
++ // st_name 0
++ sym->sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
++ // st_other 0
++ // st_value 0
++ // st_size 0
++ shndx = sec->idx;
++ if (shndx >= SHN_UNDEF && shndx < SHN_LORESERVE) {
++ sym->sym.st_shndx = shndx;
++ if (!shndx_data)
++ shndx = 0;
++ } else {
++ sym->sym.st_shndx = SHN_XINDEX;
++ if (!shndx_data) {
++ WARN("no .symtab_shndx");
++ return NULL;
++ }
++ }
++
++ if (!gelf_update_symshndx(symtab->data, shndx_data, sym->idx, &sym->sym, shndx)) {
++ WARN_ELF("gelf_update_symshndx");
++ return NULL;
++ }
++
++ elf_add_symbol(elf, sym);
++
++ return sym;
++}
++
++int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
++ unsigned long offset, unsigned int type,
++ struct section *insn_sec, unsigned long insn_off)
++{
++ struct symbol *sym = insn_sec->sym;
++ int addend = insn_off;
++
++ if (!sym) {
++ /*
++ * Due to how weak functions work, we must use section based
++ * relocations. Symbol based relocations would result in the
++ * weak and non-weak function annotations being overlaid on the
++ * non-weak function after linking.
++ */
++ sym = elf_create_section_symbol(elf, insn_sec);
++ if (!sym)
++ return -1;
++
++ insn_sec->sym = sym;
+ }
+
+ return elf_add_reloc(elf, sec, offset, type, sym, addend);
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
-index 062bb6e9b8658..478e054fcdf71 100644
+index 062bb6e9b8658..9ca08d95e78ee 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
-@@ -82,6 +82,7 @@ unsigned long arch_jump_destination(struct instruction *insn);
+@@ -26,6 +26,7 @@ enum insn_type {
+ INSN_CLAC,
+ INSN_STD,
+ INSN_CLD,
++ INSN_TRAP,
+ INSN_OTHER,
+ };
+
+@@ -82,6 +83,7 @@ unsigned long arch_jump_destination(struct instruction *insn);
unsigned long arch_dest_reloc_offset(int addend);
const char *arch_nop_insn(int len);
@@ -167989,8 +259198,43 @@ index 062bb6e9b8658..478e054fcdf71 100644
int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg);
+diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h
+index 15ac0b7d3d6a3..89ba869ed08fe 100644
+--- a/tools/objtool/include/objtool/builtin.h
++++ b/tools/objtool/include/objtool/builtin.h
+@@ -9,7 +9,7 @@
+
+ extern const struct option check_options[];
+ extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats,
+- validate_dup, vmlinux, mcount, noinstr, backup;
++ validate_dup, vmlinux, mcount, noinstr, backup, sls;
+
+ extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]);
+
+diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
+index 075d8291b8546..b4d01f8fd09b8 100644
+--- a/tools/objtool/include/objtool/elf.h
++++ b/tools/objtool/include/objtool/elf.h
+@@ -69,7 +69,7 @@ struct reloc {
+ struct symbol *sym;
+ unsigned long offset;
+ unsigned int type;
+- int addend;
++ long addend;
+ int idx;
+ bool jump_table_start;
+ };
+@@ -131,7 +131,7 @@ struct elf *elf_open_read(const char *name, int flags);
+ struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
+
+ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
+- unsigned int type, struct symbol *sym, int addend);
++ unsigned int type, struct symbol *sym, long addend);
+ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
+ unsigned long offset, unsigned int type,
+ struct section *insn_sec, unsigned long insn_off);
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
-index 14e3e8d702a02..71772b20ea737 100644
+index 14e3e8d702a02..e0660bc76b7b4 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -143,7 +143,10 @@ FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto
@@ -168005,7 +259249,14 @@ index 14e3e8d702a02..71772b20ea737 100644
ifdef CSLIBS
LIBOPENCSD_LDFLAGS := -L$(CSLIBS)
endif
-@@ -271,8 +274,6 @@ endif
+@@ -267,12 +270,13 @@ ifdef PYTHON_CONFIG
+ PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
+ PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --includes 2>/dev/null)
+ FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
++ ifeq ($(CC_NO_CLANG), 0)
++ PYTHON_EMBED_CCOPTS := $(filter-out -ffat-lto-objects, $(PYTHON_EMBED_CCOPTS))
++ endif
+ endif
FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
@@ -168014,6 +259265,195 @@ index 14e3e8d702a02..71772b20ea737 100644
FEATURE_CHECK_LDFLAGS-libaio = -lrt
+@@ -544,9 +548,16 @@ ifndef NO_LIBELF
+ ifeq ($(feature-libbpf), 1)
+ EXTLIBS += -lbpf
+ $(call detected,CONFIG_LIBBPF_DYNAMIC)
++
++ $(call feature_check,libbpf-btf__load_from_kernel_by_id)
++ ifeq ($(feature-libbpf-btf__load_from_kernel_by_id), 1)
++ CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID
++ endif
+ else
+ dummy := $(error Error: No libbpf devel library found, please install libbpf-devel);
+ endif
++ else
++ CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID
+ endif
+ endif
+
+@@ -784,6 +795,9 @@ else
+ LDFLAGS += $(PERL_EMBED_LDFLAGS)
+ EXTLIBS += $(PERL_EMBED_LIBADD)
+ CFLAGS += -DHAVE_LIBPERL_SUPPORT
++ ifeq ($(CC_NO_CLANG), 0)
++ CFLAGS += -Wno-compound-token-split-by-macro
++ endif
+ $(call detected,CONFIG_LIBPERL)
+ endif
+ endif
+diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
+index 9fcb4e68add93..78dfc282e5e2b 100644
+--- a/tools/perf/arch/arm64/util/Build
++++ b/tools/perf/arch/arm64/util/Build
+@@ -1,5 +1,4 @@
+ perf-y += header.o
+-perf-y += machine.o
+ perf-y += perf_regs.o
+ perf-y += tsc.o
+ perf-y += pmu.o
+diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c
+index a4420d4df5033..7d589a705fc89 100644
+--- a/tools/perf/arch/arm64/util/arm-spe.c
++++ b/tools/perf/arch/arm64/util/arm-spe.c
+@@ -154,6 +154,12 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
+ arm_spe_set_timestamp(itr, arm_spe_evsel);
+ }
+
++ /*
++ * Set this only so that perf report knows that SPE generates memory info. It has no effect
++ * on the opening of the event or the SPE data produced.
++ */
++ evsel__set_sample_bit(arm_spe_evsel, DATA_SRC);
++
+ /* Add dummy event to keep tracking */
+ err = parse_events(evlist, "dummy:u", NULL);
+ if (err)
+diff --git a/tools/perf/arch/arm64/util/machine.c b/tools/perf/arch/arm64/util/machine.c
+deleted file mode 100644
+index 7e7714290a873..0000000000000
+--- a/tools/perf/arch/arm64/util/machine.c
++++ /dev/null
+@@ -1,28 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-
+-#include <inttypes.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include "debug.h"
+-#include "symbol.h"
+-
+-/* On arm64, kernel text segment starts at high memory address,
+- * for example 0xffff 0000 8xxx xxxx. Modules start at a low memory
+- * address, like 0xffff 0000 00ax xxxx. When only small amount of
+- * memory is used by modules, gap between end of module's text segment
+- * and start of kernel text segment may reach 2G.
+- * Therefore do not fill this gap and do not assign it to the kernel dso map.
+- */
+-
+-#define SYMBOL_LIMIT (1 << 12) /* 4K */
+-
+-void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+-{
+- if ((strchr(p->name, '[') && strchr(c->name, '[') == NULL) ||
+- (strchr(p->name, '[') == NULL && strchr(c->name, '[')))
+- /* Limit range of last symbol in module and kernel */
+- p->end += SYMBOL_LIMIT;
+- else
+- p->end = c->start;
+- pr_debug4("%s sym:%s end:%#" PRIx64 "\n", __func__, p->name, p->end);
+-}
+diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
+index 8a79c4126e5b4..0115f31665684 100644
+--- a/tools/perf/arch/powerpc/util/Build
++++ b/tools/perf/arch/powerpc/util/Build
+@@ -1,5 +1,4 @@
+ perf-y += header.o
+-perf-y += machine.o
+ perf-y += kvm-stat.o
+ perf-y += perf_regs.o
+ perf-y += mem-events.o
+diff --git a/tools/perf/arch/powerpc/util/machine.c b/tools/perf/arch/powerpc/util/machine.c
+deleted file mode 100644
+index e652a1aa81322..0000000000000
+--- a/tools/perf/arch/powerpc/util/machine.c
++++ /dev/null
+@@ -1,25 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-
+-#include <inttypes.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include <internal/lib.h> // page_size
+-#include "debug.h"
+-#include "symbol.h"
+-
+-/* On powerpc kernel text segment start at memory addresses, 0xc000000000000000
+- * whereas the modules are located at very high memory addresses,
+- * for example 0xc00800000xxxxxxx. The gap between end of kernel text segment
+- * and beginning of first module's text segment is very high.
+- * Therefore do not fill this gap and do not assign it to the kernel dso map.
+- */
+-
+-void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+-{
+- if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
+- /* Limit the range of last kernel symbol */
+- p->end += page_size;
+- else
+- p->end = c->start;
+- pr_debug4("%s sym:%s end:%#" PRIx64 "\n", __func__, p->name, p->end);
+-}
+diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c
+index 7644a4f6d4a40..98bc3f39d5f35 100644
+--- a/tools/perf/arch/s390/util/machine.c
++++ b/tools/perf/arch/s390/util/machine.c
+@@ -35,19 +35,3 @@ int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
+
+ return 0;
+ }
+-
+-/* On s390 kernel text segment start is located at very low memory addresses,
+- * for example 0x10000. Modules are located at very high memory addresses,
+- * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment
+- * and beginning of first module's text segment is very big.
+- * Therefore do not fill this gap and do not assign it to the kernel dso map.
+- */
+-void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+-{
+- if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
+- /* Last kernel symbol mapped to end of page */
+- p->end = roundup(p->end, page_size);
+- else
+- p->end = c->start;
+- pr_debug4("%s sym:%s end:%#" PRIx64 "\n", __func__, p->name, p->end);
+-}
+diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
+index 207c56805c551..0ed177991ad05 100644
+--- a/tools/perf/arch/x86/util/perf_regs.c
++++ b/tools/perf/arch/x86/util/perf_regs.c
+@@ -9,6 +9,8 @@
+ #include "../../../util/perf_regs.h"
+ #include "../../../util/debug.h"
+ #include "../../../util/event.h"
++#include "../../../util/pmu.h"
++#include "../../../util/pmu-hybrid.h"
+
+ const struct sample_reg sample_reg_masks[] = {
+ SMPL_REG(AX, PERF_REG_X86_AX),
+@@ -284,12 +286,22 @@ uint64_t arch__intr_reg_mask(void)
+ .disabled = 1,
+ .exclude_kernel = 1,
+ };
++ struct perf_pmu *pmu;
+ int fd;
+ /*
+ * In an unnamed union, init it here to build on older gcc versions
+ */
+ attr.sample_period = 1;
+
++ if (perf_pmu__has_hybrid()) {
++ /*
++ * The same register set is supported among different hybrid PMUs.
++ * Only check the first available one.
++ */
++ pmu = list_first_entry(&perf_pmu__hybrid_pmus, typeof(*pmu), hybrid_list);
++ attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT;
++ }
++
+ event_attr_init(&attr);
+
+ fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 5d1fe9c35807a..137890f78e17a 100644
--- a/tools/perf/bench/futex-lock-pi.c
@@ -168061,6 +259501,19 @@ index 77f058a477903..2226a475e782b 100644
+ perf_cpu_map__put(cpu);
return ret;
}
+diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
+index f2640179ada9e..c2c81567afa50 100644
+--- a/tools/perf/bench/numa.c
++++ b/tools/perf/bench/numa.c
+@@ -1672,7 +1672,7 @@ static int __bench_numa(const char *name)
+ "GB/sec,", "total-speed", "GB/sec total speed");
+
+ if (g->p.show_details >= 2) {
+- char tname[14 + 2 * 10 + 1];
++ char tname[14 + 2 * 11 + 1];
+ struct thread_data *td;
+ for (p = 0; p < g->p.nr_proc; p++) {
+ for (t = 0; t < g->p.nr_threads; t++) {
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6ad191e731fc9..50c2e6892b3e9 100644
--- a/tools/perf/builtin-inject.c
@@ -168113,10 +259566,38 @@ index 6ad191e731fc9..50c2e6892b3e9 100644
return ret;
}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
-index a0316ce910db6..997e0a4b0902a 100644
+index a0316ce910db6..6583ad9cc7deb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
-@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep)
+@@ -349,6 +349,7 @@ static int report__setup_sample_type(struct report *rep)
+ struct perf_session *session = rep->session;
+ u64 sample_type = evlist__combined_sample_type(session->evlist);
+ bool is_pipe = perf_data__is_pipe(session->data);
++ struct evsel *evsel;
+
+ if (session->itrace_synth_opts->callchain ||
+ session->itrace_synth_opts->add_callchain ||
+@@ -403,6 +404,19 @@ static int report__setup_sample_type(struct report *rep)
+ }
+
+ if (sort__mode == SORT_MODE__MEMORY) {
++ /*
++ * FIXUP: prior to kernel 5.18, Arm SPE missed to set
++ * PERF_SAMPLE_DATA_SRC bit in sample type. For backward
++ * compatibility, set the bit if it's an old perf data file.
++ */
++ evlist__for_each_entry(session->evlist, evsel) {
++ if (strstr(evsel->name, "arm_spe") &&
++ !(sample_type & PERF_SAMPLE_DATA_SRC)) {
++ evsel->core.attr.sample_type |= PERF_SAMPLE_DATA_SRC;
++ sample_type |= PERF_SAMPLE_DATA_SRC;
++ }
++ }
++
+ if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
+ ui__error("Selected --mem-mode but no mem data. "
+ "Did you call perf record without -d?\n");
+@@ -619,14 +633,17 @@ static int report__browse_hists(struct report *rep)
int ret;
struct perf_session *session = rep->session;
struct evlist *evlist = session->evlist;
@@ -168139,7 +259620,7 @@ index a0316ce910db6..997e0a4b0902a 100644
switch (use_browser) {
case 1:
-@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep)
+@@ -651,7 +668,7 @@ static int report__browse_hists(struct report *rep)
ret = evlist__tty_browse_hists(evlist, rep, help);
break;
}
@@ -168149,9 +259630,18 @@ index a0316ce910db6..997e0a4b0902a 100644
}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
-index c32c2eb16d7df..18b56256bb6ff 100644
+index c32c2eb16d7df..cb3d81adf5ca8 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
+@@ -455,7 +455,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
+ return -EINVAL;
+
+ if (PRINT_FIELD(DATA_SRC) &&
+- evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC))
++ evsel__do_check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC, allow_user_set))
+ return -EINVAL;
+
+ if (PRINT_FIELD(WEIGHT) &&
@@ -2463,7 +2463,7 @@ static int process_switch_event(struct perf_tool *tool,
if (perf_event__process_switch(tool, event, sample, machine) < 0)
return -1;
@@ -168161,6 +259651,1794 @@ index c32c2eb16d7df..18b56256bb6ff 100644
scripting_ops->process_switch(event, sample, machine);
if (!script->show_switch_events)
+diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
+index f0ecfda34eceb..1a194edb54520 100644
+--- a/tools/perf/builtin-stat.c
++++ b/tools/perf/builtin-stat.c
+@@ -956,10 +956,10 @@ try_again_reset:
+ * Enable counters and exec the command:
+ */
+ if (forks) {
+- evlist__start_workload(evsel_list);
+ err = enable_counters();
+ if (err)
+ return -1;
++ evlist__start_workload(evsel_list);
+
+ t0 = rdclock();
+ clock_gettime(CLOCK_MONOTONIC, &ref_time);
+diff --git a/tools/perf/perf.c b/tools/perf/perf.c
+index 2f6b67189b426..6aae7b6c376b4 100644
+--- a/tools/perf/perf.c
++++ b/tools/perf/perf.c
+@@ -434,7 +434,7 @@ void pthread__unblock_sigwinch(void)
+ static int libperf_print(enum libperf_print_level level,
+ const char *fmt, va_list ap)
+ {
+- return eprintf(level, verbose, fmt, ap);
++ return veprintf(level, verbose, fmt, ap);
+ }
+
+ int main(int argc, const char **argv)
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/cache.json b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
+index 9ff67206ade4e..821d2f2a8f251 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/cache.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
+@@ -314,6 +314,19 @@
+ "SampleAfterValue": "2000003",
+ "UMask": "0x82"
+ },
++ {
++ "BriefDescription": "All retired memory instructions.",
++ "Counter": "0,1,2,3",
++ "CounterHTOff": "0,1,2,3",
++ "Data_LA": "1",
++ "EventCode": "0xD0",
++ "EventName": "MEM_INST_RETIRED.ANY",
++ "L1_Hit_Indication": "1",
++ "PEBS": "1",
++ "PublicDescription": "Counts all retired memory instructions - loads and stores.",
++ "SampleAfterValue": "2000003",
++ "UMask": "0x83"
++ },
+ {
+ "BriefDescription": "Retired load instructions with locked access.",
+ "Counter": "0,1,2,3",
+@@ -358,6 +371,7 @@
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "PEBS": "1",
++ "PublicDescription": "Number of retired load instructions that (start a) miss in the 2nd-level TLB (STLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x11"
+ },
+@@ -370,6 +384,7 @@
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
++ "PublicDescription": "Number of retired store instructions that (start a) miss in the 2nd-level TLB (STLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x12"
+ },
+@@ -733,7 +748,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010491",
++ "MSRValue": "0x10491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -772,7 +787,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0491",
++ "MSRValue": "0x4003C0491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -785,7 +800,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0491",
++ "MSRValue": "0x1003C0491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -798,7 +813,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0491",
++ "MSRValue": "0x8003C0491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -811,7 +826,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010490",
++ "MSRValue": "0x10490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -850,7 +865,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0490",
++ "MSRValue": "0x4003C0490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -863,7 +878,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0490",
++ "MSRValue": "0x1003C0490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -876,7 +891,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0490",
++ "MSRValue": "0x8003C0490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -889,7 +904,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010120",
++ "MSRValue": "0x10120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -928,7 +943,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0120",
++ "MSRValue": "0x4003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -941,7 +956,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0120",
++ "MSRValue": "0x1003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -954,7 +969,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0120",
++ "MSRValue": "0x8003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -967,7 +982,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010122",
++ "MSRValue": "0x10122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1006,7 +1021,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0122",
++ "MSRValue": "0x4003C0122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1019,7 +1034,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0122",
++ "MSRValue": "0x1003C0122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1032,7 +1047,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0122",
++ "MSRValue": "0x8003C0122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1045,7 +1060,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010004",
++ "MSRValue": "0x10004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1084,7 +1099,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0004",
++ "MSRValue": "0x4003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1097,7 +1112,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0004",
++ "MSRValue": "0x1003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1110,7 +1125,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0004",
++ "MSRValue": "0x8003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1123,7 +1138,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010001",
++ "MSRValue": "0x10001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1162,7 +1177,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0001",
++ "MSRValue": "0x4003C0001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1175,7 +1190,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0001",
++ "MSRValue": "0x1003C0001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1188,7 +1203,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0001",
++ "MSRValue": "0x8003C0001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1201,7 +1216,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010002",
++ "MSRValue": "0x10002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1240,7 +1255,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0002",
++ "MSRValue": "0x4003C0002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1253,7 +1268,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0002",
++ "MSRValue": "0x1003C0002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1266,7 +1281,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0002",
++ "MSRValue": "0x8003C0002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1279,7 +1294,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010400",
++ "MSRValue": "0x10400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1318,7 +1333,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0400",
++ "MSRValue": "0x4003C0400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1331,7 +1346,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0400",
++ "MSRValue": "0x1003C0400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1344,7 +1359,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0400",
++ "MSRValue": "0x8003C0400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1357,7 +1372,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010010",
++ "MSRValue": "0x10010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1396,7 +1411,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0010",
++ "MSRValue": "0x4003C0010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1409,7 +1424,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0010",
++ "MSRValue": "0x1003C0010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1422,7 +1437,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0010",
++ "MSRValue": "0x8003C0010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1435,7 +1450,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010020",
++ "MSRValue": "0x10020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1474,7 +1489,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0020",
++ "MSRValue": "0x4003C0020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1487,7 +1502,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0020",
++ "MSRValue": "0x1003C0020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1500,7 +1515,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0020",
++ "MSRValue": "0x8003C0020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1513,7 +1528,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010080",
++ "MSRValue": "0x10080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1552,7 +1567,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0080",
++ "MSRValue": "0x4003C0080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1565,7 +1580,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0080",
++ "MSRValue": "0x1003C0080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1578,7 +1593,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0080",
++ "MSRValue": "0x8003C0080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1591,7 +1606,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0000010100",
++ "MSRValue": "0x10100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1630,7 +1645,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x04003C0100",
++ "MSRValue": "0x4003C0100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1643,7 +1658,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x01003C0100",
++ "MSRValue": "0x1003C0100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1656,7 +1671,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x08003C0100",
++ "MSRValue": "0x8003C0100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
+index 503737ed3a83c..9e873ab224502 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
+@@ -1,73 +1,81 @@
+ [
+ {
+- "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT14 RCP14 DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD 128-bit packed computational double precision floating-point instructions retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
++ "PublicDescription": "Counts once for most SIMD 128-bit packed computational double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD 128-bit packed computational single precision floating-point instruction retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
++ "PublicDescription": "Counts once for most SIMD 128-bit packed computational single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD 256-bit packed double computational precision floating-point instructions retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
++ "PublicDescription": "Counts once for most SIMD 256-bit packed double computational precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD 256-bit packed single computational precision floating-point instructions retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
++ "PublicDescription": "Counts once for most SIMD 256-bit packed single computational precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 8 calculations per element.",
++ "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
++ "PublicDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 16 calculations per element.",
++ "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
++ "PublicDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD scalar computational double precision floating-point instructions retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
++ "PublicDescription": "Counts once for most SIMD scalar computational double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SIMD scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+- "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
++ "BriefDescription": "Counts once for most SIMD scalar computational single precision floating-point instructions retired. Counts twice for DPP and FM(N)ADD/SUB instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
++ "PublicDescription": "Counts once for most SIMD scalar computational single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SIMD scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/frontend.json b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
+index 078706a500919..ecce4273ae52c 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
+@@ -30,7 +30,21 @@
+ "UMask": "0x2"
+ },
+ {
+- "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
++ "BriefDescription": "Retired Instructions who experienced DSB miss.",
++ "Counter": "0,1,2,3",
++ "CounterHTOff": "0,1,2,3",
++ "EventCode": "0xC6",
++ "EventName": "FRONTEND_RETIRED.ANY_DSB_MISS",
++ "MSRIndex": "0x3F7",
++ "MSRValue": "0x1",
++ "PEBS": "1",
++ "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
++ "SampleAfterValue": "100007",
++ "TakenAlone": "1",
++ "UMask": "0x1"
++ },
++ {
++ "BriefDescription": "Retired Instructions who experienced a critical DSB miss.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+@@ -38,7 +52,7 @@
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x11",
+ "PEBS": "1",
+- "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
++ "PublicDescription": "Number of retired Instructions that experienced a critical DSB (Decode stream buffer i.e. the decoded instruction-cache) miss. Critical means stalls were exposed to the back-end as a result of the DSB miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/memory.json b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
+index 6f29b02fa320c..60c286b4fe54c 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/memory.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
+@@ -299,7 +299,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00491",
++ "MSRValue": "0x83FC00491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -312,7 +312,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00491",
++ "MSRValue": "0x63FC00491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -325,7 +325,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000491",
++ "MSRValue": "0x604000491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -338,7 +338,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800491",
++ "MSRValue": "0x63B800491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -377,7 +377,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00490",
++ "MSRValue": "0x83FC00490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -390,7 +390,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00490",
++ "MSRValue": "0x63FC00490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -403,7 +403,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000490",
++ "MSRValue": "0x604000490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -416,7 +416,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800490",
++ "MSRValue": "0x63B800490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -455,7 +455,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00120",
++ "MSRValue": "0x83FC00120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -468,7 +468,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00120",
++ "MSRValue": "0x63FC00120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -481,7 +481,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000120",
++ "MSRValue": "0x604000120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -494,7 +494,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800120",
++ "MSRValue": "0x63B800120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -533,7 +533,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00122",
++ "MSRValue": "0x83FC00122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -546,7 +546,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00122",
++ "MSRValue": "0x63FC00122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -559,7 +559,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000122",
++ "MSRValue": "0x604000122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -572,7 +572,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800122",
++ "MSRValue": "0x63B800122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -611,7 +611,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00004",
++ "MSRValue": "0x83FC00004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -624,7 +624,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00004",
++ "MSRValue": "0x63FC00004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -637,7 +637,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000004",
++ "MSRValue": "0x604000004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -650,7 +650,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800004",
++ "MSRValue": "0x63B800004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -689,7 +689,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00001",
++ "MSRValue": "0x83FC00001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -702,7 +702,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00001",
++ "MSRValue": "0x63FC00001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -715,7 +715,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000001",
++ "MSRValue": "0x604000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -728,7 +728,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800001",
++ "MSRValue": "0x63B800001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -767,7 +767,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00002",
++ "MSRValue": "0x83FC00002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -780,7 +780,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00002",
++ "MSRValue": "0x63FC00002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -793,7 +793,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000002",
++ "MSRValue": "0x604000002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -806,7 +806,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800002",
++ "MSRValue": "0x63B800002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -845,7 +845,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00400",
++ "MSRValue": "0x83FC00400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -858,7 +858,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00400",
++ "MSRValue": "0x63FC00400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -871,7 +871,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000400",
++ "MSRValue": "0x604000400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -884,7 +884,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800400",
++ "MSRValue": "0x63B800400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -923,7 +923,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00010",
++ "MSRValue": "0x83FC00010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -936,7 +936,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00010",
++ "MSRValue": "0x63FC00010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -949,7 +949,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000010",
++ "MSRValue": "0x604000010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -962,7 +962,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800010",
++ "MSRValue": "0x63B800010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1001,7 +1001,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00020",
++ "MSRValue": "0x83FC00020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1014,7 +1014,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00020",
++ "MSRValue": "0x63FC00020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1027,7 +1027,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000020",
++ "MSRValue": "0x604000020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1040,7 +1040,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800020",
++ "MSRValue": "0x63B800020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1079,7 +1079,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00080",
++ "MSRValue": "0x83FC00080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1092,7 +1092,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00080",
++ "MSRValue": "0x63FC00080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1105,7 +1105,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000080",
++ "MSRValue": "0x604000080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1118,7 +1118,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800080",
++ "MSRValue": "0x63B800080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1157,7 +1157,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x083FC00100",
++ "MSRValue": "0x83FC00100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1170,7 +1170,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063FC00100",
++ "MSRValue": "0x63FC00100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1183,7 +1183,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x0604000100",
++ "MSRValue": "0x604000100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+@@ -1196,7 +1196,7 @@
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+- "MSRValue": "0x063B800100",
++ "MSRValue": "0x63B800100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
+index ca57481206660..12eabae3e2242 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
+@@ -435,6 +435,17 @@
+ "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "SampleAfterValue": "2000003"
+ },
++ {
++ "BriefDescription": "Number of all retired NOP instructions.",
++ "Counter": "0,1,2,3",
++ "CounterHTOff": "0,1,2,3,4,5,6,7",
++ "Errata": "SKL091, SKL044",
++ "EventCode": "0xC0",
++ "EventName": "INST_RETIRED.NOP",
++ "PEBS": "1",
++ "SampleAfterValue": "2000003",
++ "UMask": "0x2"
++ },
+ {
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "Counter": "1",
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
+index 863c9e103969e..b016f7d1ff3de 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
+@@ -1,26 +1,167 @@
+ [
++ {
++ "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend",
++ "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)",
++ "MetricGroup": "TopdownL1",
++ "MetricName": "Frontend_Bound",
++ "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
++ "MetricGroup": "TopdownL1_SMT",
++ "MetricName": "Frontend_Bound_SMT",
++ "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations",
++ "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD)",
++ "MetricGroup": "TopdownL1",
++ "MetricName": "Bad_Speculation",
++ "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
++ "MetricGroup": "TopdownL1_SMT",
++ "MetricName": "Bad_Speculation_SMT",
++ "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend",
++ "MetricConstraint": "NO_NMI_WATCHDOG",
++ "MetricExpr": "1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD)",
++ "MetricGroup": "TopdownL1",
++ "MetricName": "Backend_Bound",
++ "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
++ "MetricGroup": "TopdownL1_SMT",
++ "MetricName": "Backend_Bound_SMT",
++ "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired",
++ "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)",
++ "MetricGroup": "TopdownL1",
++ "MetricName": "Retiring",
++ "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved. Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. "
++ },
++ {
++ "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
++ "MetricGroup": "TopdownL1_SMT",
++ "MetricName": "Retiring_SMT",
++ "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved. Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Branch Misprediction related bottlenecks",
++ "MetricExpr": "100 * ( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) + (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) )",
++ "MetricGroup": "Bad;BadSpec;BrMispredicts",
++ "MetricName": "Mispredictions"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Branch Misprediction related bottlenecks",
++ "MetricExpr": "100 * ( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) + (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) )",
++ "MetricGroup": "Bad;BadSpec;BrMispredicts_SMT",
++ "MetricName": "Mispredictions_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of (external) Memory Bandwidth related bottlenecks",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) * ( ( (CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (min( CPU_CLK_UNHALTED.THREAD , cpu@OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD\\,cmask\\=4@ ) / CPU_CLK_UNHALTED.THREAD) / #(CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) ) + ( (( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (OFFCORE_REQUESTS_BUFFER.SQ_FULL / CPU_CLK_UNHALTED.THREAD) / #(( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) ) ) + ( (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( ((L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )) * cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ / CPU_CLK_UNHALTED.THREAD) / #(max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) ) ",
++ "MetricGroup": "Mem;MemoryBW;Offcore",
++ "MetricName": "Memory_Bandwidth"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of (external) Memory Bandwidth related bottlenecks",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) * ( ( (CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (min( CPU_CLK_UNHALTED.THREAD , cpu@OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD\\,cmask\\=4@ ) / CPU_CLK_UNHALTED.THREAD) / #(CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) ) + ( (( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (( OFFCORE_REQUESTS_BUFFER.SQ_FULL / 2 ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )) / #(( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) ) ) + ( (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( ((L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )) * cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ / CPU_CLK_UNHALTED.THREAD) / #(max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) ) ",
++ "MetricGroup": "Mem;MemoryBW;Offcore_SMT",
++ "MetricName": "Memory_Bandwidth_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Memory Latency related bottlenecks (external memory and off-core caches)",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) * ( ( (CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (min( CPU_CLK_UNHALTED.THREAD , OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD ) / CPU_CLK_UNHALTED.THREAD - (min( CPU_CLK_UNHALTED.THREAD , cpu@OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD\\,cmask\\=4@ ) / CPU_CLK_UNHALTED.THREAD)) / #(CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) ) + ( (( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (( (20.5 * ((CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time)) - (3.5 * ((CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time)) ) * MEM_LOAD_RETIRED.L3_HIT * (1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) / 2) / CPU_CLK_UNHALTED.THREAD) / #(( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) ) + ( (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD)) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) )",
++ "MetricGroup": "Mem;MemoryLat;Offcore",
++ "MetricName": "Memory_Latency"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Memory Latency related bottlenecks (external memory and off-core caches)",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) * ( ( (CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (min( CPU_CLK_UNHALTED.THREAD , OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD ) / CPU_CLK_UNHALTED.THREAD - (min( CPU_CLK_UNHALTED.THREAD , cpu@OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD\\,cmask\\=4@ ) / CPU_CLK_UNHALTED.THREAD)) / #(CYCLE_ACTIVITY.STALLS_L3_MISS / CPU_CLK_UNHALTED.THREAD + (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD) - (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD))) ) + ( (( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (( (20.5 * ((CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time)) - (3.5 * ((CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time)) ) * MEM_LOAD_RETIRED.L3_HIT * (1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) / 2) / CPU_CLK_UNHALTED.THREAD) / #(( CYCLE_ACTIVITY.STALLS_L2_MISS - CYCLE_ACTIVITY.STALLS_L3_MISS ) / CPU_CLK_UNHALTED.THREAD) ) + ( (( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) / ( (MEM_LOAD_RETIRED.L2_HIT * ( 1 + (MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS) )) + cpu@L1D_PEND_MISS.FB_FULL\\,cmask\\=1@ ) ) * (( CYCLE_ACTIVITY.STALLS_L1D_MISS - CYCLE_ACTIVITY.STALLS_L2_MISS ) / CPU_CLK_UNHALTED.THREAD)) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) )",
++ "MetricGroup": "Mem;MemoryLat;Offcore_SMT",
++ "MetricName": "Memory_Latency_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Memory Address Translation related bottlenecks (data-side TLBs)",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) * ( ( (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) / ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (min( 9 * cpu@DTLB_LOAD_MISSES.STLB_HIT\\,cmask\\=1@ + DTLB_LOAD_MISSES.WALK_ACTIVE , max( CYCLE_ACTIVITY.CYCLES_MEM_ANY - CYCLE_ACTIVITY.CYCLES_L1D_MISS , 0 ) ) / CPU_CLK_UNHALTED.THREAD) / (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) ) + ( (EXE_ACTIVITY.BOUND_ON_STORES / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * CPU_CLK_UNHALTED.THREAD)) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - ( UOPS_ISSUED.ANY + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) ) * ( (( 9 * cpu@DTLB_STORE_MISSES.STLB_HIT\\,cmask\\=1@ + DTLB_STORE_MISSES.WALK_ACTIVE ) / CPU_CLK_UNHALTED.THREAD) / #(EXE_ACTIVITY.BOUND_ON_STORES / CPU_CLK_UNHALTED.THREAD) ) ) ",
++ "MetricGroup": "Mem;MemoryTLB",
++ "MetricName": "Memory_Data_TLBs"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of Memory Address Translation related bottlenecks (data-side TLBs)",
++ "MetricExpr": "100 * ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) * ( ( (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) / ((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (min( 9 * cpu@DTLB_LOAD_MISSES.STLB_HIT\\,cmask\\=1@ + DTLB_LOAD_MISSES.WALK_ACTIVE , max( CYCLE_ACTIVITY.CYCLES_MEM_ANY - CYCLE_ACTIVITY.CYCLES_L1D_MISS , 0 ) ) / CPU_CLK_UNHALTED.THREAD) / (max( ( CYCLE_ACTIVITY.STALLS_MEM_ANY - CYCLE_ACTIVITY.STALLS_L1D_MISS ) / CPU_CLK_UNHALTED.THREAD , 0 )) ) + ( (EXE_ACTIVITY.BOUND_ON_STORES / CPU_CLK_UNHALTED.THREAD) / #((( CYCLE_ACTIVITY.STALLS_MEM_ANY + EXE_ACTIVITY.BOUND_ON_STORES ) / (CYCLE_ACTIVITY.STALLS_TOTAL + (EXE_ACTIVITY.1_PORTS_UTIL + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * EXE_ACTIVITY.2_PORTS_UTIL) + EXE_ACTIVITY.BOUND_ON_STORES)) * (1 - (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - ( UOPS_ISSUED.ANY + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) ) * ( (( 9 * cpu@DTLB_STORE_MISSES.STLB_HIT\\,cmask\\=1@ + DTLB_STORE_MISSES.WALK_ACTIVE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )) / #(EXE_ACTIVITY.BOUND_ON_STORES / CPU_CLK_UNHALTED.THREAD) ) ) ",
++ "MetricGroup": "Mem;MemoryTLB;_SMT",
++ "MetricName": "Memory_Data_TLBs_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of branch related instructions (used for program control-flow including function calls)",
++ "MetricExpr": "100 * (( BR_INST_RETIRED.CONDITIONAL + 3 * BR_INST_RETIRED.NEAR_CALL + (BR_INST_RETIRED.NEAR_TAKEN - ( BR_INST_RETIRED.CONDITIONAL - BR_INST_RETIRED.NOT_TAKEN ) - 2 * BR_INST_RETIRED.NEAR_CALL) ) / (4 * CPU_CLK_UNHALTED.THREAD))",
++ "MetricGroup": "Ret",
++ "MetricName": "Branching_Overhead"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of branch related instructions (used for program control-flow including function calls)",
++ "MetricExpr": "100 * (( BR_INST_RETIRED.CONDITIONAL + 3 * BR_INST_RETIRED.NEAR_CALL + (BR_INST_RETIRED.NEAR_TAKEN - ( BR_INST_RETIRED.CONDITIONAL - BR_INST_RETIRED.NOT_TAKEN ) - 2 * BR_INST_RETIRED.NEAR_CALL) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))",
++ "MetricGroup": "Ret_SMT",
++ "MetricName": "Branching_Overhead_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of instruction fetch related bottlenecks by large code footprint programs (i-side cache; TLB and BTB misses)",
++ "MetricExpr": "100 * (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * ( (ICACHE_64B.IFTAG_STALL / CPU_CLK_UNHALTED.THREAD) + (( ICACHE_16B.IFDATA_STALL + 2 * cpu@ICACHE_16B.IFDATA_STALL\\,cmask\\=1\\,edge@ ) / CPU_CLK_UNHALTED.THREAD) + (9 * BACLEARS.ANY / CPU_CLK_UNHALTED.THREAD) ) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD))",
++ "MetricGroup": "BigFoot;Fed;Frontend;IcMiss;MemoryTLB",
++ "MetricName": "Big_Code"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of instruction fetch related bottlenecks by large code footprint programs (i-side cache; TLB and BTB misses)",
++ "MetricExpr": "100 * (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * ( (ICACHE_64B.IFTAG_STALL / CPU_CLK_UNHALTED.THREAD) + (( ICACHE_16B.IFDATA_STALL + 2 * cpu@ICACHE_16B.IFDATA_STALL\\,cmask\\=1\\,edge@ ) / CPU_CLK_UNHALTED.THREAD) + (9 * BACLEARS.ANY / CPU_CLK_UNHALTED.THREAD) ) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))",
++ "MetricGroup": "BigFoot;Fed;Frontend;IcMiss;MemoryTLB_SMT",
++ "MetricName": "Big_Code_SMT"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of instruction fetch bandwidth related bottlenecks",
++ "MetricExpr": "100 * ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) ) - (100 * (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * ( (ICACHE_64B.IFTAG_STALL / CPU_CLK_UNHALTED.THREAD) + (( ICACHE_16B.IFDATA_STALL + 2 * cpu@ICACHE_16B.IFDATA_STALL\\,cmask\\=1\\,edge@ ) / CPU_CLK_UNHALTED.THREAD) + (9 * BACLEARS.ANY / CPU_CLK_UNHALTED.THREAD) ) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)))",
++ "MetricGroup": "Fed;FetchBW;Frontend",
++ "MetricName": "Instruction_Fetch_BW"
++ },
++ {
++ "BriefDescription": "Total pipeline cost of instruction fetch bandwidth related bottlenecks",
++ "MetricExpr": "100 * ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) ) - (100 * (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * ( (ICACHE_64B.IFTAG_STALL / CPU_CLK_UNHALTED.THREAD) + (( ICACHE_16B.IFDATA_STALL + 2 * cpu@ICACHE_16B.IFDATA_STALL\\,cmask\\=1\\,edge@ ) / CPU_CLK_UNHALTED.THREAD) + (9 * BACLEARS.ANY / CPU_CLK_UNHALTED.THREAD) ) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))))",
++ "MetricGroup": "Fed;FetchBW;Frontend_SMT",
++ "MetricName": "Instruction_Fetch_BW_SMT"
++ },
+ {
+ "BriefDescription": "Instructions Per Cycle (per Logical Processor)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+- "MetricGroup": "Summary",
++ "MetricGroup": "Ret;Summary",
+ "MetricName": "IPC"
+ },
+ {
+ "BriefDescription": "Uops Per Instruction",
+ "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
+- "MetricGroup": "Pipeline;Retire",
++ "MetricGroup": "Pipeline;Ret;Retire",
+ "MetricName": "UPI"
+ },
+ {
+ "BriefDescription": "Instruction per taken branch",
+- "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
+- "MetricGroup": "Branches;FetchBW;PGO",
+- "MetricName": "IpTB"
++ "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / BR_INST_RETIRED.NEAR_TAKEN",
++ "MetricGroup": "Branches;Fed;FetchBW",
++ "MetricName": "UpTB"
+ },
+ {
+ "BriefDescription": "Cycles Per Instruction (per Logical Processor)",
+ "MetricExpr": "1 / (INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD)",
+- "MetricGroup": "Pipeline",
++ "MetricGroup": "Pipeline;Mem",
+ "MetricName": "CPI"
+ },
+ {
+@@ -30,39 +171,84 @@
+ "MetricName": "CLKS"
+ },
+ {
+- "BriefDescription": "Instructions Per Cycle (per physical core)",
++ "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
++ "MetricExpr": "4 * CPU_CLK_UNHALTED.THREAD",
++ "MetricGroup": "TmaL1",
++ "MetricName": "SLOTS"
++ },
++ {
++ "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
++ "MetricExpr": "4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
++ "MetricGroup": "TmaL1_SMT",
++ "MetricName": "SLOTS_SMT"
++ },
++ {
++ "BriefDescription": "The ratio of Executed- by Issued-Uops",
++ "MetricExpr": "UOPS_EXECUTED.THREAD / UOPS_ISSUED.ANY",
++ "MetricGroup": "Cor;Pipeline",
++ "MetricName": "Execute_per_Issue",
++ "PublicDescription": "The ratio of Executed- by Issued-Uops. Ratio > 1 suggests high rate of uop micro-fusions. Ratio < 1 suggest high rate of \"execute\" at rename stage."
++ },
++ {
++ "BriefDescription": "Instructions Per Cycle across hyper-threads (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+- "MetricGroup": "SMT;TmaL1",
++ "MetricGroup": "Ret;SMT;TmaL1",
+ "MetricName": "CoreIPC"
+ },
+ {
+- "BriefDescription": "Instructions Per Cycle (per physical core)",
++ "BriefDescription": "Instructions Per Cycle across hyper-threads (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+- "MetricGroup": "SMT;TmaL1",
++ "MetricGroup": "Ret;SMT;TmaL1_SMT",
+ "MetricName": "CoreIPC_SMT"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / CPU_CLK_UNHALTED.THREAD",
+- "MetricGroup": "Flops",
++ "MetricGroup": "Ret;Flops",
+ "MetricName": "FLOPc"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+- "MetricGroup": "Flops_SMT",
++ "MetricGroup": "Ret;Flops_SMT",
+ "MetricName": "FLOPc_SMT"
+ },
++ {
++ "BriefDescription": "Actual per-core usage of the Floating Point execution units (regardless of the vector width)",
++ "MetricExpr": "( (FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE) + (FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE) ) / ( 2 * CPU_CLK_UNHALTED.THREAD )",
++ "MetricGroup": "Cor;Flops;HPC",
++ "MetricName": "FP_Arith_Utilization",
++ "PublicDescription": "Actual per-core usage of the Floating Point execution units (regardless of the vector width). Values > 1 are possible due to Fused-Multiply Add (FMA) counting."
++ },
++ {
++ "BriefDescription": "Actual per-core usage of the Floating Point execution units (regardless of the vector width). SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "( (FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE) + (FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE) ) / ( 2 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ) )",
++ "MetricGroup": "Cor;Flops;HPC_SMT",
++ "MetricName": "FP_Arith_Utilization_SMT",
++ "PublicDescription": "Actual per-core usage of the Floating Point execution units (regardless of the vector width). Values > 1 are possible due to Fused-Multiply Add (FMA) counting. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
+ {
+ "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
+ "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 ) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
+- "MetricGroup": "Pipeline;PortsUtil",
++ "MetricGroup": "Backend;Cor;Pipeline;PortsUtil",
+ "MetricName": "ILP"
+ },
++ {
++ "BriefDescription": "Branch Misprediction Cost: Fraction of TMA slots wasted per non-speculative branch misprediction (retired JEClear)",
++ "MetricExpr": " ( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * CPU_CLK_UNHALTED.THREAD))) + (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) ) * (4 * CPU_CLK_UNHALTED.THREAD) / BR_MISP_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;BrMispredicts",
++ "MetricName": "Branch_Misprediction_Cost"
++ },
++ {
++ "BriefDescription": "Branch Misprediction Cost: Fraction of TMA slots wasted per non-speculative branch misprediction (retired JEClear)",
++ "MetricExpr": " ( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) + (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * INT_MISC.CLEAR_RESTEER_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) ) * (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )) / BR_MISP_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;BrMispredicts_SMT",
++ "MetricName": "Branch_Misprediction_Cost_SMT"
++ },
+ {
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+- "MetricGroup": "BrMispredicts",
++ "MetricGroup": "Bad;BadSpec;BrMispredicts",
+ "MetricName": "IpMispredict"
+ },
+ {
+@@ -86,122 +272,249 @@
+ {
+ "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
+- "MetricGroup": "Branches;InsType",
++ "MetricGroup": "Branches;Fed;InsType",
+ "MetricName": "IpBranch"
+ },
+ {
+ "BriefDescription": "Instructions per (near) call (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_CALL",
+- "MetricGroup": "Branches",
++ "MetricGroup": "Branches;Fed;PGO",
+ "MetricName": "IpCall"
+ },
++ {
++ "BriefDescription": "Instruction per taken branch",
++ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
++ "MetricGroup": "Branches;Fed;FetchBW;Frontend;PGO",
++ "MetricName": "IpTB"
++ },
+ {
+ "BriefDescription": "Branch instructions per taken branch. ",
+ "MetricExpr": "BR_INST_RETIRED.ALL_BRANCHES / BR_INST_RETIRED.NEAR_TAKEN",
+- "MetricGroup": "Branches;PGO",
++ "MetricGroup": "Branches;Fed;PGO",
+ "MetricName": "BpTkBranch"
+ },
+ {
+ "BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
+- "MetricGroup": "Flops;FpArith;InsType",
++ "MetricGroup": "Flops;InsType",
+ "MetricName": "IpFLOP"
+ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / ( (FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE) + (FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE) )",
++ "MetricGroup": "Flops;InsType",
++ "MetricName": "IpArith",
++ "PublicDescription": "Instructions per FP Arithmetic instruction (lower number means higher occurrence rate). May undercount due to FMA double counting. Approximated prior to BDW."
++ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic Scalar Single-Precision instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
++ "MetricGroup": "Flops;FpScalar;InsType",
++ "MetricName": "IpArith_Scalar_SP",
++ "PublicDescription": "Instructions per FP Arithmetic Scalar Single-Precision instruction (lower number means higher occurrence rate). May undercount due to FMA double counting."
++ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic Scalar Double-Precision instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
++ "MetricGroup": "Flops;FpScalar;InsType",
++ "MetricName": "IpArith_Scalar_DP",
++ "PublicDescription": "Instructions per FP Arithmetic Scalar Double-Precision instruction (lower number means higher occurrence rate). May undercount due to FMA double counting."
++ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic AVX/SSE 128-bit instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / ( FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE )",
++ "MetricGroup": "Flops;FpVector;InsType",
++ "MetricName": "IpArith_AVX128",
++ "PublicDescription": "Instructions per FP Arithmetic AVX/SSE 128-bit instruction (lower number means higher occurrence rate). May undercount due to FMA double counting."
++ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic AVX* 256-bit instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / ( FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE )",
++ "MetricGroup": "Flops;FpVector;InsType",
++ "MetricName": "IpArith_AVX256",
++ "PublicDescription": "Instructions per FP Arithmetic AVX* 256-bit instruction (lower number means higher occurrence rate). May undercount due to FMA double counting."
++ },
++ {
++ "BriefDescription": "Instructions per FP Arithmetic AVX 512-bit instruction (lower number means higher occurrence rate)",
++ "MetricExpr": "INST_RETIRED.ANY / ( FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE + FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
++ "MetricGroup": "Flops;FpVector;InsType",
++ "MetricName": "IpArith_AVX512",
++ "PublicDescription": "Instructions per FP Arithmetic AVX 512-bit instruction (lower number means higher occurrence rate). May undercount due to FMA double counting."
++ },
+ {
+ "BriefDescription": "Total number of retired Instructions, Sample with: INST_RETIRED.PREC_DIST",
+ "MetricExpr": "INST_RETIRED.ANY",
+ "MetricGroup": "Summary;TmaL1",
+ "MetricName": "Instructions"
+ },
++ {
++ "BriefDescription": "Average number of Uops issued by front-end when it issued something",
++ "MetricExpr": "UOPS_ISSUED.ANY / cpu@UOPS_ISSUED.ANY\\,cmask\\=1@",
++ "MetricGroup": "Fed;FetchBW",
++ "MetricName": "Fetch_UpC"
++ },
+ {
+ "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)",
+ "MetricExpr": "IDQ.DSB_UOPS / (IDQ.DSB_UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
+- "MetricGroup": "DSB;FetchBW",
++ "MetricGroup": "DSB;Fed;FetchBW",
+ "MetricName": "DSB_Coverage"
+ },
+ {
+- "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads (in core cycles)",
++ "BriefDescription": "Total penalty related to DSB (uop cache) misses - subset/see of/the Instruction_Fetch_BW Bottleneck.",
++ "MetricExpr": "(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) * (DSB2MITE_SWITCHES.PENALTY_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) + ((IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD))) * (( IDQ.ALL_MITE_CYCLES_ANY_UOPS - IDQ.ALL_MITE_CYCLES_4_UOPS ) / CPU_CLK_UNHALTED.THREAD / 2) / #((IDQ_UOPS_NOT_DELIVERED.CORE / (4 * CPU_CLK_UNHALTED.THREAD)) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * CPU_CLK_UNHALTED.THREAD)))",
++ "MetricGroup": "DSBmiss;Fed",
++ "MetricName": "DSB_Misses_Cost"
++ },
++ {
++ "BriefDescription": "Total penalty related to DSB (uop cache) misses - subset/see of/the Instruction_Fetch_BW Bottleneck.",
++ "MetricExpr": "(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * (DSB2MITE_SWITCHES.PENALTY_CYCLES / CPU_CLK_UNHALTED.THREAD) / #(4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) + ((IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) * (( IDQ.ALL_MITE_CYCLES_ANY_UOPS - IDQ.ALL_MITE_CYCLES_4_UOPS ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ) / 2) / #((IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) - (4 * IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))))",
++ "MetricGroup": "DSBmiss;Fed_SMT",
++ "MetricName": "DSB_Misses_Cost_SMT"
++ },
++ {
++ "BriefDescription": "Number of Instructions per non-speculative DSB miss",
++ "MetricExpr": "INST_RETIRED.ANY / FRONTEND_RETIRED.ANY_DSB_MISS",
++ "MetricGroup": "DSBmiss;Fed",
++ "MetricName": "IpDSB_Miss_Ret"
++ },
++ {
++ "BriefDescription": "Fraction of branches that are non-taken conditionals",
++ "MetricExpr": "BR_INST_RETIRED.NOT_TAKEN / BR_INST_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;Branches;CodeGen;PGO",
++ "MetricName": "Cond_NT"
++ },
++ {
++ "BriefDescription": "Fraction of branches that are taken conditionals",
++ "MetricExpr": "( BR_INST_RETIRED.CONDITIONAL - BR_INST_RETIRED.NOT_TAKEN ) / BR_INST_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;Branches;CodeGen;PGO",
++ "MetricName": "Cond_TK"
++ },
++ {
++ "BriefDescription": "Fraction of branches that are CALL or RET",
++ "MetricExpr": "( BR_INST_RETIRED.NEAR_CALL + BR_INST_RETIRED.NEAR_RETURN ) / BR_INST_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;Branches",
++ "MetricName": "CallRet"
++ },
++ {
++ "BriefDescription": "Fraction of branches that are unconditional (direct or indirect) jumps",
++ "MetricExpr": "(BR_INST_RETIRED.NEAR_TAKEN - ( BR_INST_RETIRED.CONDITIONAL - BR_INST_RETIRED.NOT_TAKEN ) - 2 * BR_INST_RETIRED.NEAR_CALL) / BR_INST_RETIRED.ALL_BRANCHES",
++ "MetricGroup": "Bad;Branches",
++ "MetricName": "Jump"
++ },
++ {
++ "BriefDescription": "Actual Average Latency for L1 data-cache miss demand load instructions (in core cycles)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )",
+- "MetricGroup": "MemoryBound;MemoryLat",
+- "MetricName": "Load_Miss_Real_Latency"
++ "MetricGroup": "Mem;MemoryBound;MemoryLat",
++ "MetricName": "Load_Miss_Real_Latency",
++ "PublicDescription": "Actual Average Latency for L1 data-cache miss demand load instructions (in core cycles). Latency may be overestimated for multi-load instructions - e.g. repeat strings."
+ },
+ {
+ "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES",
+- "MetricGroup": "MemoryBound;MemoryBW",
++ "MetricGroup": "Mem;MemoryBound;MemoryBW",
+ "MetricName": "MLP"
+ },
+- {
+- "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
+- "MetricConstraint": "NO_NMI_WATCHDOG",
+- "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * CORE_CLKS )",
+- "MetricGroup": "MemoryTLB",
+- "MetricName": "Page_Walks_Utilization"
+- },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L1 data cache [GB / sec]",
+ "MetricExpr": "64 * L1D.REPLACEMENT / 1000000000 / duration_time",
+- "MetricGroup": "MemoryBW",
++ "MetricGroup": "Mem;MemoryBW",
+ "MetricName": "L1D_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L2 cache [GB / sec]",
+ "MetricExpr": "64 * L2_LINES_IN.ALL / 1000000000 / duration_time",
+- "MetricGroup": "MemoryBW",
++ "MetricGroup": "Mem;MemoryBW",
+ "MetricName": "L2_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
+ "MetricExpr": "64 * LONGEST_LAT_CACHE.MISS / 1000000000 / duration_time",
+- "MetricGroup": "MemoryBW",
++ "MetricGroup": "Mem;MemoryBW",
+ "MetricName": "L3_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average per-core data access bandwidth to the L3 cache [GB / sec]",
+ "MetricExpr": "64 * OFFCORE_REQUESTS.ALL_REQUESTS / 1000000000 / duration_time",
+- "MetricGroup": "MemoryBW;Offcore",
++ "MetricGroup": "Mem;MemoryBW;Offcore",
+ "MetricName": "L3_Cache_Access_BW"
+ },
+ {
+ "BriefDescription": "L1 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L1_MISS / INST_RETIRED.ANY",
+- "MetricGroup": "CacheMisses",
++ "MetricGroup": "Mem;CacheMisses",
+ "MetricName": "L1MPKI"
+ },
++ {
++ "BriefDescription": "L1 cache true misses per kilo instruction for all demand loads (including speculative)",
++ "MetricExpr": "1000 * L2_RQSTS.ALL_DEMAND_DATA_RD / INST_RETIRED.ANY",
++ "MetricGroup": "Mem;CacheMisses",
++ "MetricName": "L1MPKI_Load"
++ },
+ {
+ "BriefDescription": "L2 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L2_MISS / INST_RETIRED.ANY",
+- "MetricGroup": "CacheMisses",
++ "MetricGroup": "Mem;Backend;CacheMisses",
+ "MetricName": "L2MPKI"
+ },
+ {
+ "BriefDescription": "L2 cache misses per kilo instruction for all request types (including speculative)",
+ "MetricExpr": "1000 * L2_RQSTS.MISS / INST_RETIRED.ANY",
+- "MetricGroup": "CacheMisses;Offcore",
++ "MetricGroup": "Mem;CacheMisses;Offcore",
+ "MetricName": "L2MPKI_All"
+ },
++ {
++ "BriefDescription": "L2 cache misses per kilo instruction for all demand loads (including speculative)",
++ "MetricExpr": "1000 * L2_RQSTS.DEMAND_DATA_RD_MISS / INST_RETIRED.ANY",
++ "MetricGroup": "Mem;CacheMisses",
++ "MetricName": "L2MPKI_Load"
++ },
+ {
+ "BriefDescription": "L2 cache hits per kilo instruction for all request types (including speculative)",
+ "MetricExpr": "1000 * ( L2_RQSTS.REFERENCES - L2_RQSTS.MISS ) / INST_RETIRED.ANY",
+- "MetricGroup": "CacheMisses",
++ "MetricGroup": "Mem;CacheMisses",
+ "MetricName": "L2HPKI_All"
+ },
++ {
++ "BriefDescription": "L2 cache hits per kilo instruction for all demand loads (including speculative)",
++ "MetricExpr": "1000 * L2_RQSTS.DEMAND_DATA_RD_HIT / INST_RETIRED.ANY",
++ "MetricGroup": "Mem;CacheMisses",
++ "MetricName": "L2HPKI_Load"
++ },
+ {
+ "BriefDescription": "L3 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L3_MISS / INST_RETIRED.ANY",
+- "MetricGroup": "CacheMisses",
++ "MetricGroup": "Mem;CacheMisses",
+ "MetricName": "L3MPKI"
+ },
++ {
++ "BriefDescription": "Fill Buffer (FB) true hits per kilo instructions for retired demand loads",
++ "MetricExpr": "1000 * MEM_LOAD_RETIRED.FB_HIT / INST_RETIRED.ANY",
++ "MetricGroup": "Mem;CacheMisses",
++ "MetricName": "FB_HPKI"
++ },
++ {
++ "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
++ "MetricConstraint": "NO_NMI_WATCHDOG",
++ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * CPU_CLK_UNHALTED.THREAD )",
++ "MetricGroup": "Mem;MemoryTLB",
++ "MetricName": "Page_Walks_Utilization"
++ },
++ {
++ "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
++ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ) )",
++ "MetricGroup": "Mem;MemoryTLB_SMT",
++ "MetricName": "Page_Walks_Utilization_SMT"
++ },
+ {
+ "BriefDescription": "Rate of silent evictions from the L2 cache per Kilo instruction where the evicted lines are dropped (no writeback to L3 or memory)",
+ "MetricExpr": "1000 * L2_LINES_OUT.SILENT / INST_RETIRED.ANY",
+- "MetricGroup": "L2Evicts;Server",
++ "MetricGroup": "L2Evicts;Mem;Server",
+ "MetricName": "L2_Evictions_Silent_PKI"
+ },
+ {
+ "BriefDescription": "Rate of non silent evictions from the L2 cache per Kilo instruction",
+ "MetricExpr": "1000 * L2_LINES_OUT.NON_SILENT / INST_RETIRED.ANY",
+- "MetricGroup": "L2Evicts;Server",
++ "MetricGroup": "L2Evicts;Mem;Server",
+ "MetricName": "L2_Evictions_NonSilent_PKI"
+ },
+ {
+@@ -219,7 +532,7 @@
+ {
+ "BriefDescription": "Giga Floating Point Operations Per Second",
+ "MetricExpr": "( ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / 1000000000 ) / duration_time",
+- "MetricGroup": "Flops;HPC",
++ "MetricGroup": "Cor;Flops;HPC",
+ "MetricName": "GFLOPs"
+ },
+ {
+@@ -228,6 +541,48 @@
+ "MetricGroup": "Power",
+ "MetricName": "Turbo_Utilization"
+ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for baseline license level 0",
++ "MetricExpr": "CORE_POWER.LVL0_TURBO_LICENSE / CPU_CLK_UNHALTED.THREAD",
++ "MetricGroup": "Power",
++ "MetricName": "Power_License0_Utilization",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes."
++ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for baseline license level 0. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "CORE_POWER.LVL0_TURBO_LICENSE / 2 / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
++ "MetricGroup": "Power_SMT",
++ "MetricName": "Power_License0_Utilization_SMT",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 1",
++ "MetricExpr": "CORE_POWER.LVL1_TURBO_LICENSE / CPU_CLK_UNHALTED.THREAD",
++ "MetricGroup": "Power",
++ "MetricName": "Power_License1_Utilization",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions."
++ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 1. SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "CORE_POWER.LVL1_TURBO_LICENSE / 2 / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
++ "MetricGroup": "Power_SMT",
++ "MetricName": "Power_License1_Utilization_SMT",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 2 (introduced in SKX)",
++ "MetricExpr": "CORE_POWER.LVL2_TURBO_LICENSE / CPU_CLK_UNHALTED.THREAD",
++ "MetricGroup": "Power",
++ "MetricName": "Power_License2_Utilization",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 2 (introduced in SKX). This includes high current AVX 512-bit instructions."
++ },
++ {
++ "BriefDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 2 (introduced in SKX). SMT version; use when SMT is enabled and measuring per logical CPU.",
++ "MetricExpr": "CORE_POWER.LVL2_TURBO_LICENSE / 2 / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
++ "MetricGroup": "Power_SMT",
++ "MetricName": "Power_License2_Utilization_SMT",
++ "PublicDescription": "Fraction of Core cycles where the core was running with power-delivery for license level 2 (introduced in SKX). This includes high current AVX 512-bit instructions. SMT version; use when SMT is enabled and measuring per logical CPU."
++ },
+ {
+ "BriefDescription": "Fraction of cycles where both hardware Logical Processors were active",
+ "MetricExpr": "1 - CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
+@@ -240,34 +595,46 @@
+ "MetricGroup": "OS",
+ "MetricName": "Kernel_Utilization"
+ },
++ {
++ "BriefDescription": "Cycles Per Instruction for the Operating System (OS) Kernel mode",
++ "MetricExpr": "CPU_CLK_UNHALTED.THREAD_P:k / INST_RETIRED.ANY_P:k",
++ "MetricGroup": "OS",
++ "MetricName": "Kernel_CPI"
++ },
+ {
+ "BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
+ "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+- "MetricGroup": "HPC;MemoryBW;SoC",
++ "MetricGroup": "HPC;Mem;MemoryBW;SoC",
+ "MetricName": "DRAM_BW_Use"
+ },
+ {
+ "BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
+ "MetricExpr": "1000000000 * ( cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x35\\,umask\\=0x21\\,config\\=0x40433@ ) / ( cha_0@event\\=0x0@ / duration_time )",
+- "MetricGroup": "MemoryLat;SoC",
++ "MetricGroup": "Mem;MemoryLat;SoC",
+ "MetricName": "MEM_Read_Latency"
+ },
+ {
+ "BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
+ "MetricExpr": "cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433\\,thresh\\=1@",
+- "MetricGroup": "MemoryBW;SoC",
++ "MetricGroup": "Mem;MemoryBW;SoC",
+ "MetricName": "MEM_Parallel_Reads"
+ },
++ {
++ "BriefDescription": "Average latency of data read request to external DRAM memory [in nanoseconds]. Accounts for demand loads and L1/L2 data-read prefetches",
++ "MetricExpr": "1000000000 * ( UNC_M_RPQ_OCCUPANCY / UNC_M_RPQ_INSERTS ) / imc_0@event\\=0x0@",
++ "MetricGroup": "Mem;MemoryLat;SoC;Server",
++ "MetricName": "MEM_DRAM_Read_Latency"
++ },
+ {
+ "BriefDescription": "Average IO (network or disk) Bandwidth Use for Writes [GB / sec]",
+ "MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3 ) * 4 / 1000000000 / duration_time",
+- "MetricGroup": "IoBW;SoC;Server",
++ "MetricGroup": "IoBW;Mem;SoC;Server",
+ "MetricName": "IO_Write_BW"
+ },
+ {
+ "BriefDescription": "Average IO (network or disk) Bandwidth Use for Reads [GB / sec]",
+ "MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3 ) * 4 / 1000000000 / duration_time",
+- "MetricGroup": "IoBW;SoC;Server",
++ "MetricGroup": "IoBW;Mem;SoC;Server",
+ "MetricName": "IO_Read_BW"
+ },
+ {
+diff --git a/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
+index 6ed92bc5c129b..06c5ca26ca3f3 100644
+--- a/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
++++ b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
+@@ -537,6 +537,18 @@
+ "PublicDescription": "Counts clockticks of the 1GHz trafiic controller clock in the IIO unit.",
+ "Unit": "IIO"
+ },
++ {
++ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0-3",
++ "Counter": "0,1,2,3",
++ "EventCode": "0xC2",
++ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.ALL_PARTS",
++ "FCMask": "0x4",
++ "PerPkg": "1",
++ "PortMask": "0x0f",
++ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0-3",
++ "UMask": "0x03",
++ "Unit": "IIO"
++ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0",
+ "Counter": "0,1,2,3",
+@@ -585,6 +597,17 @@
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
++ {
++ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0-3",
++ "Counter": "2,3",
++ "EventCode": "0xD5",
++ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.ALL_PARTS",
++ "FCMask": "0x04",
++ "PerPkg": "1",
++ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0-3",
++ "UMask": "0x0f",
++ "Unit": "IIO"
++ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0",
+ "Counter": "2,3",
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py
index 1d3a189a9a547..66452a8ec3586 100644
--- a/tools/perf/scripts/python/intel-pt-events.py
@@ -168346,7 +261624,7 @@ index c1f24d0048527..5075ecead5f3d 100644
{
struct perf_hpp_fmt *fmt, *tmp;
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
-index 58b7069c5a5f8..7054f23150e1b 100644
+index 58b7069c5a5f8..235549bb28b94 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -51,6 +51,7 @@ struct arm_spe {
@@ -168383,7 +261661,15 @@ index 58b7069c5a5f8..7054f23150e1b 100644
ret = perf_session__deliver_synth_event(spe->session, event, sample);
if (ret)
pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
-@@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
+@@ -914,12 +927,15 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
+ attr.type = PERF_TYPE_HARDWARE;
+ attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
+ attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
+- PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC;
++ PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC |
++ PERF_SAMPLE_ADDR;
+ if (spe->timeless_decoding)
+ attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
else
attr.sample_type |= PERF_SAMPLE_TIME;
@@ -168393,10 +261679,28 @@ index 58b7069c5a5f8..7054f23150e1b 100644
attr.exclude_kernel = evsel->core.attr.exclude_kernel;
attr.exclude_hv = evsel->core.attr.exclude_hv;
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
-index 1a7112a87736a..16ad0e6e9e9c5 100644
+index 1a7112a87736a..cf1b9f6ec0dbe 100644
--- a/tools/perf/util/bpf-event.c
+++ b/tools/perf/util/bpf-event.c
-@@ -120,7 +120,11 @@ static int perf_env__fetch_btf(struct perf_env *env,
+@@ -21,7 +21,8 @@
+ #include "record.h"
+ #include "util/synthetic-events.h"
+
+-struct btf * __weak btf__load_from_kernel_by_id(__u32 id)
++#ifndef HAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID
++struct btf *btf__load_from_kernel_by_id(__u32 id)
+ {
+ struct btf *btf;
+ #pragma GCC diagnostic push
+@@ -31,6 +32,7 @@ struct btf * __weak btf__load_from_kernel_by_id(__u32 id)
+
+ return err ? ERR_PTR(err) : btf;
+ }
++#endif
+
+ #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
+
+@@ -120,7 +122,11 @@ static int perf_env__fetch_btf(struct perf_env *env,
node->data_size = data_size;
memcpy(node->data, data, data_size);
@@ -168409,7 +261713,7 @@ index 1a7112a87736a..16ad0e6e9e9c5 100644
return 0;
}
-@@ -576,7 +580,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
+@@ -576,7 +582,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, 0);
fprintf(fp, "# bpf_prog_info %u: %s addr 0x%llx size %u\n",
info->id, name, prog_addrs[0], prog_lens[0]);
@@ -168418,7 +261722,7 @@ index 1a7112a87736a..16ad0e6e9e9c5 100644
}
fprintf(fp, "# bpf_prog_info %u:\n", info->id);
-@@ -586,4 +590,6 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
+@@ -586,4 +592,6 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
fprintf(fp, "# \tsub_prog %u: %s addr 0x%llx size %u\n",
i, name, prog_addrs[i], prog_lens[i]);
}
@@ -169012,6 +262316,29 @@ index 6f852b305e92b..c3ceac1388106 100644
while (1) {
vmcs = strtoull(p, &p, 0);
if (errno)
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index 51a2219df6015..3bfe099d86438 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -1529,7 +1529,9 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
+ bool use_uncore_alias;
+ LIST_HEAD(config_terms);
+
+- if (verbose > 1) {
++ pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
++
++ if (verbose > 1 && !(pmu && pmu->selectable)) {
+ fprintf(stderr, "Attempting to add event pmu '%s' with '",
+ name);
+ if (head_config) {
+@@ -1542,7 +1544,6 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
+ fprintf(stderr, "' that may result in non-fatal errors\n");
+ }
+
+- pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
+ if (!pmu) {
+ char *err_str;
+
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index b2a02c9ab8ea9..a834918a0a0d3 100644
--- a/tools/perf/util/probe-event.c
@@ -169026,6 +262353,75 @@ index b2a02c9ab8ea9..a834918a0a0d3 100644
/* There can be duplicated symbols in the map */
for (i = 0; i < j; i++)
if (sym->start == syms[i]->start) {
+diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
+index 352f16076e01f..562e9b8080272 100644
+--- a/tools/perf/util/session.c
++++ b/tools/perf/util/session.c
+@@ -2076,6 +2076,7 @@ prefetch_event(char *buf, u64 head, size_t mmap_size,
+ bool needs_swap, union perf_event *error)
+ {
+ union perf_event *event;
++ u16 event_size;
+
+ /*
+ * Ensure we have enough space remaining to read
+@@ -2088,15 +2089,23 @@ prefetch_event(char *buf, u64 head, size_t mmap_size,
+ if (needs_swap)
+ perf_event_header__bswap(&event->header);
+
+- if (head + event->header.size <= mmap_size)
++ event_size = event->header.size;
++ if (head + event_size <= mmap_size)
+ return event;
+
+ /* We're not fetching the event so swap back again */
+ if (needs_swap)
+ perf_event_header__bswap(&event->header);
+
+- pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx:"
+- " fuzzed or compressed perf.data?\n",__func__, head, event->header.size, mmap_size);
++ /* Check if the event fits into the next mmapped buf. */
++ if (event_size <= mmap_size - head % page_size) {
++ /* Remap buf and fetch again. */
++ return NULL;
++ }
++
++ /* Invalid input. Event size should never exceed mmap_size. */
++ pr_debug("%s: head=%#" PRIx64 " event->header.size=%#x, mmap_size=%#zx:"
++ " fuzzed or compressed perf.data?\n", __func__, head, event_size, mmap_size);
+
+ return error;
+ }
+diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
+index 483f05004e682..c255a2c90cd67 100644
+--- a/tools/perf/util/setup.py
++++ b/tools/perf/util/setup.py
+@@ -1,12 +1,14 @@
+-from os import getenv
++from os import getenv, path
+ from subprocess import Popen, PIPE
+ from re import sub
+
+ cc = getenv("CC")
+ cc_is_clang = b"clang version" in Popen([cc.split()[0], "-v"], stderr=PIPE).stderr.readline()
++src_feature_tests = getenv('srctree') + '/tools/build/feature'
+
+ def clang_has_option(option):
+- return [o for o in Popen([cc, option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ]
++ cc_output = Popen([cc, option, path.join(src_feature_tests, "test-hello.c") ], stderr=PIPE).stderr.readlines()
++ return [o for o in cc_output if ((b"unknown argument" in o) or (b"is not supported" in o))] == [ ]
+
+ if cc_is_clang:
+ from distutils.sysconfig import get_config_vars
+@@ -23,6 +25,8 @@ if cc_is_clang:
+ vars[var] = sub("-fstack-protector-strong", "", vars[var])
+ if not clang_has_option("-fno-semantic-interposition"):
+ vars[var] = sub("-fno-semantic-interposition", "", vars[var])
++ if not clang_has_option("-ffat-lto-objects"):
++ vars[var] = sub("-ffat-lto-objects", "", vars[var])
+
+ from distutils.core import setup, Extension
+
diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c
index 20bacd5972ade..34f1b1b1176c7 100644
--- a/tools/perf/util/smt.c
@@ -169216,6 +262612,116 @@ index 588601000f3f9..db00ca6a67deb 100644
}
}
+diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
+index 31cd59a2b66e6..ecd377938eea8 100644
+--- a/tools/perf/util/symbol-elf.c
++++ b/tools/perf/util/symbol-elf.c
+@@ -1290,7 +1290,7 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss,
+ * For misannotated, zeroed, ASM function sizes.
+ */
+ if (nr > 0) {
+- symbols__fixup_end(&dso->symbols);
++ symbols__fixup_end(&dso->symbols, false);
+ symbols__fixup_duplicate(&dso->symbols);
+ if (kmap) {
+ /*
+diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
+index 0fc9a54107399..b1e5fd99e38af 100644
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -101,11 +101,6 @@ static int prefix_underscores_count(const char *str)
+ return tail - str;
+ }
+
+-void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+-{
+- p->end = c->start;
+-}
+-
+ const char * __weak arch__normalize_symbol_name(const char *name)
+ {
+ return name;
+@@ -217,7 +212,8 @@ again:
+ }
+ }
+
+-void symbols__fixup_end(struct rb_root_cached *symbols)
++/* Update zero-sized symbols using the address of the next symbol */
++void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms)
+ {
+ struct rb_node *nd, *prevnd = rb_first_cached(symbols);
+ struct symbol *curr, *prev;
+@@ -231,8 +227,29 @@ void symbols__fixup_end(struct rb_root_cached *symbols)
+ prev = curr;
+ curr = rb_entry(nd, struct symbol, rb_node);
+
+- if (prev->end == prev->start && prev->end != curr->start)
+- arch__symbols__fixup_end(prev, curr);
++ /*
++ * On some architecture kernel text segment start is located at
++ * some low memory address, while modules are located at high
++ * memory addresses (or vice versa). The gap between end of
++ * kernel text segment and beginning of first module's text
++ * segment is very big. Therefore do not fill this gap and do
++ * not assign it to the kernel dso map (kallsyms).
++ *
++ * In kallsyms, it determines module symbols using '[' character
++ * like in:
++ * ffffffffc1937000 T hdmi_driver_init [snd_hda_codec_hdmi]
++ */
++ if (prev->end == prev->start) {
++ /* Last kernel/module symbol mapped to end of page */
++ if (is_kallsyms && (!strchr(prev->name, '[') !=
++ !strchr(curr->name, '[')))
++ prev->end = roundup(prev->end + 4096, 4096);
++ else
++ prev->end = curr->start;
++
++ pr_debug4("%s sym:%s end:%#" PRIx64 "\n",
++ __func__, prev->name, prev->end);
++ }
+ }
+
+ /* Last entry */
+@@ -1456,7 +1473,7 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
+ if (kallsyms__delta(kmap, filename, &delta))
+ return -1;
+
+- symbols__fixup_end(&dso->symbols);
++ symbols__fixup_end(&dso->symbols, true);
+ symbols__fixup_duplicate(&dso->symbols);
+
+ if (dso->kernel == DSO_SPACE__KERNEL_GUEST)
+@@ -1648,7 +1665,7 @@ int dso__load_bfd_symbols(struct dso *dso, const char *debugfile)
+ #undef bfd_asymbol_section
+ #endif
+
+- symbols__fixup_end(&dso->symbols);
++ symbols__fixup_end(&dso->symbols, false);
+ symbols__fixup_duplicate(&dso->symbols);
+ dso->adjust_symbols = 1;
+
+diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
+index 954d6a049ee23..28721d761d91e 100644
+--- a/tools/perf/util/symbol.h
++++ b/tools/perf/util/symbol.h
+@@ -192,7 +192,7 @@ void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym,
+ bool kernel);
+ void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym);
+ void symbols__fixup_duplicate(struct rb_root_cached *symbols);
+-void symbols__fixup_end(struct rb_root_cached *symbols);
++void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms);
+ void maps__fixup_end(struct maps *maps);
+
+ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
+@@ -230,7 +230,6 @@ const char *arch__normalize_symbol_name(const char *name);
+ #define SYMBOL_A 0
+ #define SYMBOL_B 1
+
+-void arch__symbols__fixup_end(struct symbol *p, struct symbol *c);
+ int arch__compare_symbol_names(const char *namea, const char *nameb);
+ int arch__compare_symbol_names_n(const char *namea, const char *nameb,
+ unsigned int n);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 37a9492edb3eb..df3c4671be72a 100644
--- a/tools/perf/util/util.c
@@ -169315,6 +262821,48 @@ index b692e6ead9b55..0a4ad7cb2c200 100644
+ fclose(buf_file);
+ return NULL;
}
+diff --git a/tools/testing/selftests/bpf/prog_tests/bind_perm.c b/tools/testing/selftests/bpf/prog_tests/bind_perm.c
+index d0f06e40c16d0..eac71fbb24ce2 100644
+--- a/tools/testing/selftests/bpf/prog_tests/bind_perm.c
++++ b/tools/testing/selftests/bpf/prog_tests/bind_perm.c
+@@ -1,13 +1,24 @@
+ // SPDX-License-Identifier: GPL-2.0
+-#include <test_progs.h>
+-#include "bind_perm.skel.h"
+-
++#define _GNU_SOURCE
++#include <sched.h>
++#include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/capability.h>
+
++#include "test_progs.h"
++#include "bind_perm.skel.h"
++
+ static int duration;
+
++static int create_netns(void)
++{
++ if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
++ return -1;
++
++ return 0;
++}
++
+ void try_bind(int family, int port, int expected_errno)
+ {
+ struct sockaddr_storage addr = {};
+@@ -75,6 +86,9 @@ void test_bind_perm(void)
+ struct bind_perm *skel;
+ int cgroup_fd;
+
++ if (create_netns())
++ return;
++
+ cgroup_fd = test__join_cgroup("/bind_perm");
+ if (CHECK(cgroup_fd < 0, "cg-join", "errno %d", errno))
+ return;
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index 77ac24b191d4c..dc18e5ae0febc 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -169395,6 +262943,43 @@ index 762f6a9da8b5e..664ffc0364f4f 100644
}
struct test {
+diff --git a/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c b/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c
+index cf3acfa5a91d5..69455fe90ac3e 100644
+--- a/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c
++++ b/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c
+@@ -7,6 +7,7 @@
+ #include "test_ksyms_btf.skel.h"
+ #include "test_ksyms_btf_null_check.skel.h"
+ #include "test_ksyms_weak.skel.h"
++#include "test_ksyms_btf_write_check.skel.h"
+
+ static int duration;
+
+@@ -109,6 +110,16 @@ cleanup:
+ test_ksyms_weak__destroy(skel);
+ }
+
++static void test_write_check(void)
++{
++ struct test_ksyms_btf_write_check *skel;
++
++ skel = test_ksyms_btf_write_check__open_and_load();
++ ASSERT_ERR_PTR(skel, "unexpected load of a prog writing to ksym memory\n");
++
++ test_ksyms_btf_write_check__destroy(skel);
++}
++
+ void test_ksyms_btf(void)
+ {
+ int percpu_datasec;
+@@ -136,4 +147,7 @@ void test_ksyms_btf(void)
+
+ if (test__start_subtest("weak_ksyms"))
+ test_weak_syms();
++
++ if (test__start_subtest("write_check"))
++ test_write_check();
+ }
diff --git a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
index 59adb4715394f..3c85247f96f95 100644
--- a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
@@ -169496,6 +263081,44 @@ index 0252f61d611a9..97d8a6f84f4ab 100644
+ ring_buffer__free(ringbuf);
ima__destroy(skel);
}
+diff --git a/tools/testing/selftests/bpf/prog_tests/timer_crash.c b/tools/testing/selftests/bpf/prog_tests/timer_crash.c
+new file mode 100644
+index 0000000000000..f74b82305da8c
+--- /dev/null
++++ b/tools/testing/selftests/bpf/prog_tests/timer_crash.c
+@@ -0,0 +1,32 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <test_progs.h>
++#include "timer_crash.skel.h"
++
++enum {
++ MODE_ARRAY,
++ MODE_HASH,
++};
++
++static void test_timer_crash_mode(int mode)
++{
++ struct timer_crash *skel;
++
++ skel = timer_crash__open_and_load();
++ if (!ASSERT_OK_PTR(skel, "timer_crash__open_and_load"))
++ return;
++ skel->bss->pid = getpid();
++ skel->bss->crash_map = mode;
++ if (!ASSERT_OK(timer_crash__attach(skel), "timer_crash__attach"))
++ goto end;
++ usleep(1);
++end:
++ timer_crash__destroy(skel);
++}
++
++void test_timer_crash(void)
++{
++ if (test__start_subtest("array"))
++ test_timer_crash_mode(MODE_ARRAY);
++ if (test__start_subtest("hash"))
++ test_timer_crash_mode(MODE_HASH);
++}
diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h
index 7de534f38c3f1..60c93aee2f4ad 100644
--- a/tools/testing/selftests/bpf/progs/strobemeta.h
@@ -169518,6 +263141,81 @@ index 7de534f38c3f1..60c93aee2f4ad 100644
int i;
descr->tag_len = 0; /* presume no tag is set */
+diff --git a/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c b/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c
+new file mode 100644
+index 0000000000000..2180c41cd890f
+--- /dev/null
++++ b/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c
+@@ -0,0 +1,29 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright (c) 2021 Google */
++
++#include "vmlinux.h"
++
++#include <bpf/bpf_helpers.h>
++
++extern const int bpf_prog_active __ksym; /* int type global var. */
++
++SEC("raw_tp/sys_enter")
++int handler(const void *ctx)
++{
++ int *active;
++ __u32 cpu;
++
++ cpu = bpf_get_smp_processor_id();
++ active = (int *)bpf_per_cpu_ptr(&bpf_prog_active, cpu);
++ if (active) {
++ /* Kernel memory obtained from bpf_{per,this}_cpu_ptr
++ * is read-only, should _not_ pass verification.
++ */
++ /* WRITE_ONCE */
++ *(volatile int *)active = -1;
++ }
++
++ return 0;
++}
++
++char _license[] SEC("license") = "GPL";
+diff --git a/tools/testing/selftests/bpf/progs/test_map_in_map.c b/tools/testing/selftests/bpf/progs/test_map_in_map.c
+index 1cfeb940cf9fb..5f0e0bfc151e5 100644
+--- a/tools/testing/selftests/bpf/progs/test_map_in_map.c
++++ b/tools/testing/selftests/bpf/progs/test_map_in_map.c
+@@ -23,7 +23,7 @@ struct {
+ __uint(value_size, sizeof(__u32));
+ } mim_hash SEC(".maps");
+
+-SEC("xdp_mimtest")
++SEC("xdp")
+ int xdp_mimtest0(struct xdp_md *ctx)
+ {
+ int value = 123;
+diff --git a/tools/testing/selftests/bpf/progs/test_sk_lookup.c b/tools/testing/selftests/bpf/progs/test_sk_lookup.c
+index ac6f7f205e25d..cb0aa46b20d19 100644
+--- a/tools/testing/selftests/bpf/progs/test_sk_lookup.c
++++ b/tools/testing/selftests/bpf/progs/test_sk_lookup.c
+@@ -404,8 +404,7 @@ int ctx_narrow_access(struct bpf_sk_lookup *ctx)
+
+ /* Narrow loads from remote_port field. Expect SRC_PORT. */
+ if (LSB(ctx->remote_port, 0) != ((SRC_PORT >> 0) & 0xff) ||
+- LSB(ctx->remote_port, 1) != ((SRC_PORT >> 8) & 0xff) ||
+- LSB(ctx->remote_port, 2) != 0 || LSB(ctx->remote_port, 3) != 0)
++ LSB(ctx->remote_port, 1) != ((SRC_PORT >> 8) & 0xff))
+ return SK_DROP;
+ if (LSW(ctx->remote_port, 0) != SRC_PORT)
+ return SK_DROP;
+diff --git a/tools/testing/selftests/bpf/progs/test_sock_fields.c b/tools/testing/selftests/bpf/progs/test_sock_fields.c
+index 81b57b9aaaeae..7967348b11af6 100644
+--- a/tools/testing/selftests/bpf/progs/test_sock_fields.c
++++ b/tools/testing/selftests/bpf/progs/test_sock_fields.c
+@@ -113,7 +113,7 @@ static void tpcpy(struct bpf_tcp_sock *dst,
+
+ #define RET_LOG() ({ \
+ linum = __LINE__; \
+- bpf_map_update_elem(&linum_map, &linum_idx, &linum, BPF_NOEXIST); \
++ bpf_map_update_elem(&linum_map, &linum_idx, &linum, BPF_ANY); \
+ return CG_OK; \
+ })
+
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_kern.h b/tools/testing/selftests/bpf/progs/test_sockmap_kern.h
index 1858435de7aaf..5cb90ca292186 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_kern.h
@@ -169590,6 +263288,335 @@ index 1858435de7aaf..5cb90ca292186 100644
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop)
+diff --git a/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c b/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
+index 47cbe2eeae431..fac7ef99f9a67 100644
+--- a/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
++++ b/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
+@@ -156,7 +156,7 @@ int check_syncookie_clsact(struct __sk_buff *skb)
+ return TC_ACT_OK;
+ }
+
+-SEC("xdp/check_syncookie")
++SEC("xdp")
+ int check_syncookie_xdp(struct xdp_md *ctx)
+ {
+ check_syncookie(ctx, (void *)(long)ctx->data,
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp.c b/tools/testing/selftests/bpf/progs/test_xdp.c
+index 31f9bce37491a..e6aa2fc6ce6bd 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp.c
+@@ -210,7 +210,7 @@ static __always_inline int handle_ipv6(struct xdp_md *xdp)
+ return XDP_TX;
+ }
+
+-SEC("xdp_tx_iptunnel")
++SEC("xdp")
+ int _xdp_tx_iptunnel(struct xdp_md *xdp)
+ {
+ void *data_end = (void *)(long)xdp->data_end;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
+index 3d66599eee2ec..199c61b7d0628 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
+@@ -2,7 +2,7 @@
+ #include <linux/bpf.h>
+ #include <bpf/bpf_helpers.h>
+
+-SEC("xdp_adjust_tail_grow")
++SEC("xdp")
+ int _xdp_adjust_tail_grow(struct xdp_md *xdp)
+ {
+ void *data_end = (void *)(long)xdp->data_end;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
+index 22065a9cfb254..b7448253d1359 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
+@@ -9,9 +9,7 @@
+ #include <linux/if_ether.h>
+ #include <bpf/bpf_helpers.h>
+
+-int _version SEC("version") = 1;
+-
+-SEC("xdp_adjust_tail_shrink")
++SEC("xdp")
+ int _xdp_adjust_tail_shrink(struct xdp_md *xdp)
+ {
+ void *data_end = (void *)(long)xdp->data_end;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_devmap_helpers.c b/tools/testing/selftests/bpf/progs/test_xdp_devmap_helpers.c
+index b360ba2bd4411..807bf895f42ca 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_devmap_helpers.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_devmap_helpers.c
+@@ -5,7 +5,7 @@
+ #include <linux/bpf.h>
+ #include <bpf/bpf_helpers.h>
+
+-SEC("xdp_dm_log")
++SEC("xdp")
+ int xdpdm_devlog(struct xdp_md *ctx)
+ {
+ char fmt[] = "devmap redirect: dev %u -> dev %u len %u\n";
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_link.c b/tools/testing/selftests/bpf/progs/test_xdp_link.c
+index eb93ea95d1d8f..ee7d6ac0f6151 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_link.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_link.c
+@@ -5,7 +5,7 @@
+
+ char LICENSE[] SEC("license") = "GPL";
+
+-SEC("xdp/handler")
++SEC("xdp")
+ int xdp_handler(struct xdp_md *xdp)
+ {
+ return 0;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_loop.c b/tools/testing/selftests/bpf/progs/test_xdp_loop.c
+index fcabcda30ba32..27eb52dda92c2 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_loop.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_loop.c
+@@ -206,7 +206,7 @@ static __always_inline int handle_ipv6(struct xdp_md *xdp)
+ return XDP_TX;
+ }
+
+-SEC("xdp_tx_iptunnel")
++SEC("xdp")
+ int _xdp_tx_iptunnel(struct xdp_md *xdp)
+ {
+ void *data_end = (void *)(long)xdp->data_end;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_noinline.c b/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
+index 3a67921f62b52..596c4e71bf3ac 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
+@@ -797,7 +797,7 @@ out:
+ return XDP_DROP;
+ }
+
+-SEC("xdp-test-v4")
++SEC("xdp")
+ int balancer_ingress_v4(struct xdp_md *ctx)
+ {
+ void *data = (void *)(long)ctx->data;
+@@ -816,7 +816,7 @@ int balancer_ingress_v4(struct xdp_md *ctx)
+ return XDP_DROP;
+ }
+
+-SEC("xdp-test-v6")
++SEC("xdp")
+ int balancer_ingress_v6(struct xdp_md *ctx)
+ {
+ void *data = (void *)(long)ctx->data;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c b/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c
+index 59ee4f182ff80..532025057711e 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c
+@@ -12,13 +12,13 @@ struct {
+ __uint(max_entries, 4);
+ } cpu_map SEC(".maps");
+
+-SEC("xdp_redir")
++SEC("xdp")
+ int xdp_redir_prog(struct xdp_md *ctx)
+ {
+ return bpf_redirect_map(&cpu_map, 1, 0);
+ }
+
+-SEC("xdp_dummy")
++SEC("xdp")
+ int xdp_dummy_prog(struct xdp_md *ctx)
+ {
+ return XDP_PASS;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_with_devmap_helpers.c b/tools/testing/selftests/bpf/progs/test_xdp_with_devmap_helpers.c
+index 0ac0864977222..1e6b9c38ea6d9 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_with_devmap_helpers.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_with_devmap_helpers.c
+@@ -9,7 +9,7 @@ struct {
+ __uint(max_entries, 4);
+ } dm_ports SEC(".maps");
+
+-SEC("xdp_redir")
++SEC("xdp")
+ int xdp_redir_prog(struct xdp_md *ctx)
+ {
+ return bpf_redirect_map(&dm_ports, 1, 0);
+@@ -18,7 +18,7 @@ int xdp_redir_prog(struct xdp_md *ctx)
+ /* invalid program on DEVMAP entry;
+ * SEC name means expected attach type not set
+ */
+-SEC("xdp_dummy")
++SEC("xdp")
+ int xdp_dummy_prog(struct xdp_md *ctx)
+ {
+ return XDP_PASS;
+diff --git a/tools/testing/selftests/bpf/progs/timer_crash.c b/tools/testing/selftests/bpf/progs/timer_crash.c
+new file mode 100644
+index 0000000000000..f8f7944e70dae
+--- /dev/null
++++ b/tools/testing/selftests/bpf/progs/timer_crash.c
+@@ -0,0 +1,54 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <vmlinux.h>
++#include <bpf/bpf_tracing.h>
++#include <bpf/bpf_helpers.h>
++
++struct map_elem {
++ struct bpf_timer timer;
++ struct bpf_spin_lock lock;
++};
++
++struct {
++ __uint(type, BPF_MAP_TYPE_ARRAY);
++ __uint(max_entries, 1);
++ __type(key, int);
++ __type(value, struct map_elem);
++} amap SEC(".maps");
++
++struct {
++ __uint(type, BPF_MAP_TYPE_HASH);
++ __uint(max_entries, 1);
++ __type(key, int);
++ __type(value, struct map_elem);
++} hmap SEC(".maps");
++
++int pid = 0;
++int crash_map = 0; /* 0 for amap, 1 for hmap */
++
++SEC("fentry/do_nanosleep")
++int sys_enter(void *ctx)
++{
++ struct map_elem *e, value = {};
++ void *map = crash_map ? (void *)&hmap : (void *)&amap;
++
++ if (bpf_get_current_task_btf()->tgid != pid)
++ return 0;
++
++ *(void **)&value = (void *)0xdeadcaf3;
++
++ bpf_map_update_elem(map, &(int){0}, &value, 0);
++ /* For array map, doing bpf_map_update_elem will do a
++ * check_and_free_timer_in_array, which will trigger the crash if timer
++ * pointer was overwritten, for hmap we need to use bpf_timer_cancel.
++ */
++ if (crash_map == 1) {
++ e = bpf_map_lookup_elem(map, &(int){0});
++ if (!e)
++ return 0;
++ bpf_timer_cancel(&e->timer);
++ }
++ return 0;
++}
++
++char _license[] SEC("license") = "GPL";
+diff --git a/tools/testing/selftests/bpf/progs/xdp_dummy.c b/tools/testing/selftests/bpf/progs/xdp_dummy.c
+index ea25e88819928..d988b2e0cee84 100644
+--- a/tools/testing/selftests/bpf/progs/xdp_dummy.c
++++ b/tools/testing/selftests/bpf/progs/xdp_dummy.c
+@@ -4,7 +4,7 @@
+ #include <linux/bpf.h>
+ #include <bpf/bpf_helpers.h>
+
+-SEC("xdp_dummy")
++SEC("xdp")
+ int xdp_dummy_prog(struct xdp_md *ctx)
+ {
+ return XDP_PASS;
+diff --git a/tools/testing/selftests/bpf/progs/xdp_redirect_multi_kern.c b/tools/testing/selftests/bpf/progs/xdp_redirect_multi_kern.c
+index 880debcbcd65d..8395782b6e0a3 100644
+--- a/tools/testing/selftests/bpf/progs/xdp_redirect_multi_kern.c
++++ b/tools/testing/selftests/bpf/progs/xdp_redirect_multi_kern.c
+@@ -34,7 +34,7 @@ struct {
+ __uint(max_entries, 128);
+ } mac_map SEC(".maps");
+
+-SEC("xdp_redirect_map_multi")
++SEC("xdp")
+ int xdp_redirect_map_multi_prog(struct xdp_md *ctx)
+ {
+ void *data_end = (void *)(long)ctx->data_end;
+@@ -63,7 +63,7 @@ int xdp_redirect_map_multi_prog(struct xdp_md *ctx)
+ }
+
+ /* The following 2 progs are for 2nd devmap prog testing */
+-SEC("xdp_redirect_map_ingress")
++SEC("xdp")
+ int xdp_redirect_map_all_prog(struct xdp_md *ctx)
+ {
+ return bpf_redirect_map(&map_egress, 0,
+diff --git a/tools/testing/selftests/bpf/progs/xdping_kern.c b/tools/testing/selftests/bpf/progs/xdping_kern.c
+index 6b9ca40bd1f4f..4ad73847b8a5d 100644
+--- a/tools/testing/selftests/bpf/progs/xdping_kern.c
++++ b/tools/testing/selftests/bpf/progs/xdping_kern.c
+@@ -86,7 +86,7 @@ static __always_inline int icmp_check(struct xdp_md *ctx, int type)
+ return XDP_TX;
+ }
+
+-SEC("xdpclient")
++SEC("xdp")
+ int xdping_client(struct xdp_md *ctx)
+ {
+ void *data_end = (void *)(long)ctx->data_end;
+@@ -150,7 +150,7 @@ int xdping_client(struct xdp_md *ctx)
+ return XDP_TX;
+ }
+
+-SEC("xdpserver")
++SEC("xdp")
+ int xdping_server(struct xdp_md *ctx)
+ {
+ void *data_end = (void *)(long)ctx->data_end;
+diff --git a/tools/testing/selftests/bpf/test_lirc_mode2.sh b/tools/testing/selftests/bpf/test_lirc_mode2.sh
+index ec4e15948e406..5252b91f48a18 100755
+--- a/tools/testing/selftests/bpf/test_lirc_mode2.sh
++++ b/tools/testing/selftests/bpf/test_lirc_mode2.sh
+@@ -3,6 +3,7 @@
+
+ # Kselftest framework requirement - SKIP code is 4.
+ ksft_skip=4
++ret=$ksft_skip
+
+ msg="skip all tests:"
+ if [ $UID != 0 ]; then
+@@ -25,7 +26,7 @@ do
+ fi
+ done
+
+-if [ -n $LIRCDEV ];
++if [ -n "$LIRCDEV" ];
+ then
+ TYPE=lirc_mode2
+ ./test_lirc_mode2_user $LIRCDEV $INPUTDEV
+@@ -36,3 +37,5 @@ then
+ echo -e ${GREEN}"PASS: $TYPE"${NC}
+ fi
+ fi
++
++exit $ret
+diff --git a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
+index b497bb85b667f..6c69c42b1d607 100755
+--- a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
++++ b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
+@@ -120,6 +120,14 @@ setup()
+ ip netns exec ${NS2} sysctl -wq net.ipv4.conf.default.rp_filter=0
+ ip netns exec ${NS3} sysctl -wq net.ipv4.conf.default.rp_filter=0
+
++ # disable IPv6 DAD because it sometimes takes too long and fails tests
++ ip netns exec ${NS1} sysctl -wq net.ipv6.conf.all.accept_dad=0
++ ip netns exec ${NS2} sysctl -wq net.ipv6.conf.all.accept_dad=0
++ ip netns exec ${NS3} sysctl -wq net.ipv6.conf.all.accept_dad=0
++ ip netns exec ${NS1} sysctl -wq net.ipv6.conf.default.accept_dad=0
++ ip netns exec ${NS2} sysctl -wq net.ipv6.conf.default.accept_dad=0
++ ip netns exec ${NS3} sysctl -wq net.ipv6.conf.default.accept_dad=0
++
+ ip link add veth1 type veth peer name veth2
+ ip link add veth3 type veth peer name veth4
+ ip link add veth5 type veth peer name veth6
+@@ -289,7 +297,7 @@ test_ping()
+ ip netns exec ${NS1} ping -c 1 -W 1 -I veth1 ${IPv4_DST} 2>&1 > /dev/null
+ RET=$?
+ elif [ "${PROTO}" == "IPv6" ] ; then
+- ip netns exec ${NS1} ping6 -c 1 -W 6 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
++ ip netns exec ${NS1} ping6 -c 1 -W 1 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
+ RET=$?
+ else
+ echo " test_ping: unknown PROTO: ${PROTO}"
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index cc1cd240445d2..e3fea6f281e4b 100644
--- a/tools/testing/selftests/bpf/test_progs.c
@@ -169612,8 +263639,36 @@ index cc1cd240445d2..e3fea6f281e4b 100644
return -1;
}
+diff --git a/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh b/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh
+index 9b3617d770a52..fed765157c53c 100755
+--- a/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh
++++ b/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh
+@@ -77,7 +77,7 @@ TEST_IF=lo
+ MAX_PING_TRIES=5
+ BPF_PROG_OBJ="${DIR}/test_tcp_check_syncookie_kern.o"
+ CLSACT_SECTION="clsact/check_syncookie"
+-XDP_SECTION="xdp/check_syncookie"
++XDP_SECTION="xdp"
+ BPF_PROG_ID=0
+ PROG="${DIR}/test_tcp_check_syncookie_user"
+
+diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.sh b/tools/testing/selftests/bpf/test_xdp_redirect.sh
+index c033850886f44..57c8db9972a65 100755
+--- a/tools/testing/selftests/bpf/test_xdp_redirect.sh
++++ b/tools/testing/selftests/bpf/test_xdp_redirect.sh
+@@ -52,8 +52,8 @@ test_xdp_redirect()
+ return 0
+ fi
+
+- ip -n ns1 link set veth11 $xdpmode obj xdp_dummy.o sec xdp_dummy &> /dev/null
+- ip -n ns2 link set veth22 $xdpmode obj xdp_dummy.o sec xdp_dummy &> /dev/null
++ ip -n ns1 link set veth11 $xdpmode obj xdp_dummy.o sec xdp &> /dev/null
++ ip -n ns2 link set veth22 $xdpmode obj xdp_dummy.o sec xdp &> /dev/null
+ ip link set dev veth1 $xdpmode obj test_xdp_redirect.o sec redirect_to_222 &> /dev/null
+ ip link set dev veth2 $xdpmode obj test_xdp_redirect.o sec redirect_to_111 &> /dev/null
+
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh
-index 1538373157e3c..bedff7aa7023f 100755
+index 1538373157e3c..cc57cb87e65f6 100755
--- a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh
+++ b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh
@@ -2,11 +2,11 @@
@@ -169631,56 +263686,75 @@ index 1538373157e3c..bedff7aa7023f 100755
# --------- --------- ---------
# ns1 ns2 ns3
#
-@@ -31,6 +31,7 @@ IFACES=""
+@@ -31,6 +31,12 @@ IFACES=""
DRV_MODE="xdpgeneric xdpdrv xdpegress"
PASS=0
FAIL=0
+LOG_DIR=$(mktemp -d)
++declare -a NS
++NS[0]="ns0-$(mktemp -u XXXXXX)"
++NS[1]="ns1-$(mktemp -u XXXXXX)"
++NS[2]="ns2-$(mktemp -u XXXXXX)"
++NS[3]="ns3-$(mktemp -u XXXXXX)"
test_pass()
{
-@@ -50,6 +51,7 @@ clean_up()
- ip link del veth$i 2> /dev/null
- ip netns del ns$i 2> /dev/null
+@@ -46,9 +52,8 @@ test_fail()
+
+ clean_up()
+ {
+- for i in $(seq $NUM); do
+- ip link del veth$i 2> /dev/null
+- ip netns del ns$i 2> /dev/null
++ for i in $(seq 0 $NUM); do
++ ip netns del ${NS[$i]} 2> /dev/null
done
-+ ip netns del ns0 2> /dev/null
}
- # Kselftest framework requirement - SKIP code is 4.
-@@ -77,10 +79,12 @@ setup_ns()
+@@ -77,21 +82,22 @@ setup_ns()
mode="xdpdrv"
fi
-+ ip netns add ns0
++ ip netns add ${NS[0]}
for i in $(seq $NUM); do
- ip netns add ns$i
+- ip netns add ns$i
- ip link add veth$i type veth peer name veth0 netns ns$i
- ip link set veth$i up
-+ ip -n ns$i link add veth0 index 2 type veth \
-+ peer name veth$i netns ns0 index $((1 + $i))
-+ ip -n ns0 link set veth$i up
- ip -n ns$i link set veth0 up
-
- ip -n ns$i addr add 192.0.2.$i/24 dev veth0
-@@ -91,7 +95,7 @@ setup_ns()
- xdp_dummy.o sec xdp_dummy &> /dev/null || \
+- ip -n ns$i link set veth0 up
++ ip netns add ${NS[$i]}
++ ip -n ${NS[$i]} link add veth0 type veth peer name veth$i netns ${NS[0]}
++ ip -n ${NS[$i]} link set veth0 up
++ ip -n ${NS[0]} link set veth$i up
+
+- ip -n ns$i addr add 192.0.2.$i/24 dev veth0
+- ip -n ns$i addr add 2001:db8::$i/64 dev veth0
++ ip -n ${NS[$i]} addr add 192.0.2.$i/24 dev veth0
++ ip -n ${NS[$i]} addr add 2001:db8::$i/64 dev veth0
+ # Add a neigh entry for IPv4 ping test
+- ip -n ns$i neigh add 192.0.2.253 lladdr 00:00:00:00:00:01 dev veth0
+- ip -n ns$i link set veth0 $mode obj \
+- xdp_dummy.o sec xdp_dummy &> /dev/null || \
++ ip -n ${NS[$i]} neigh add 192.0.2.253 lladdr 00:00:00:00:00:01 dev veth0
++ ip -n ${NS[$i]} link set veth0 $mode obj \
++ xdp_dummy.o sec xdp &> /dev/null || \
{ test_fail "Unable to load dummy xdp" && exit 1; }
IFACES="$IFACES veth$i"
- veth_mac[$i]=$(ip link show veth$i | awk '/link\/ether/ {print $2}')
-+ veth_mac[$i]=$(ip -n ns0 link show veth$i | awk '/link\/ether/ {print $2}')
++ veth_mac[$i]=$(ip -n ${NS[0]} link show veth$i | awk '/link\/ether/ {print $2}')
done
}
-@@ -100,17 +104,17 @@ do_egress_tests()
+@@ -100,17 +106,17 @@ do_egress_tests()
local mode=$1
# mac test
- ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-2_${mode}.log &
- ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-3_${mode}.log &
-+ ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log &
-+ ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log &
++ ip netns exec ${NS[2]} tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log &
++ ip netns exec ${NS[3]} tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log &
sleep 0.5
- ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
+- ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
++ ip netns exec ${NS[1]} ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
sleep 0.5
- pkill -9 tcpdump
+ pkill tcpdump
@@ -169694,24 +263768,29 @@ index 1538373157e3c..bedff7aa7023f 100755
test_pass "$mode mac ns1-3" || test_fail "$mode mac ns1-3"
}
-@@ -121,46 +125,46 @@ do_ping_tests()
+@@ -119,48 +125,48 @@ do_ping_tests()
+ local mode=$1
+
# ping6 test: echo request should be redirect back to itself, not others
- ip netns exec ns1 ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02
+- ip netns exec ns1 ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02
++ ip netns exec ${NS[1]} ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02
- ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ns1-1_${mode}.log &
- ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ns1-2_${mode}.log &
- ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ns1-3_${mode}.log &
-+ ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log &
-+ ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log &
-+ ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log &
++ ip netns exec ${NS[1]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log &
++ ip netns exec ${NS[2]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log &
++ ip netns exec ${NS[3]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log &
sleep 0.5
# ARP test
- ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
-+ ip netns exec ns1 arping -q -c 2 -I veth0 192.0.2.254
++ ip netns exec ${NS[1]} arping -q -c 2 -I veth0 192.0.2.254
# IPv4 test
- ip netns exec ns1 ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null
+- ip netns exec ns1 ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null
++ ip netns exec ${NS[1]} ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null
# IPv6 test
- ip netns exec ns1 ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null
+- ip netns exec ns1 ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null
++ ip netns exec ${NS[1]} ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null
sleep 0.5
- pkill -9 tcpdump
+ pkill tcpdump
@@ -169754,12 +263833,12 @@ index 1538373157e3c..bedff7aa7023f 100755
test_pass "$mode IPv6 (no flags) ns1-2" || \
test_fail "$mode IPv6 (no flags) ns1-2"
}
-@@ -176,9 +180,13 @@ do_tests()
+@@ -176,9 +182,13 @@ do_tests()
xdpgeneric) drv_p="-S";;
esac
- ./xdp_redirect_multi $drv_p $IFACES &> xdp_redirect_${mode}.log &
-+ ip netns exec ns0 ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log &
++ ip netns exec ${NS[0]} ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log &
xdp_pid=$!
sleep 1
+ if ! ps -p $xdp_pid > /dev/null; then
@@ -169769,15 +263848,16 @@ index 1538373157e3c..bedff7aa7023f 100755
if [ "$mode" = "xdpegress" ]; then
do_egress_tests $mode
-@@ -189,16 +197,16 @@ do_tests()
+@@ -189,16 +199,16 @@ do_tests()
kill $xdp_pid
}
-trap clean_up 0 2 3 6 9
-+trap clean_up EXIT
-
+-
check_env
-rm -f xdp_redirect_*.log ns*.log mac_ns*.log
++
++trap clean_up EXIT
for mode in ${DRV_MODE}; do
setup_ns $mode
@@ -169788,6 +263868,22 @@ index 1538373157e3c..bedff7aa7023f 100755
echo "Summary: PASS $PASS, FAIL $FAIL"
[ $FAIL -eq 0 ] && exit 0 || exit 1
+diff --git a/tools/testing/selftests/bpf/test_xdp_veth.sh b/tools/testing/selftests/bpf/test_xdp_veth.sh
+index 995278e684b6e..a3a1eaee26ea6 100755
+--- a/tools/testing/selftests/bpf/test_xdp_veth.sh
++++ b/tools/testing/selftests/bpf/test_xdp_veth.sh
+@@ -107,9 +107,9 @@ ip link set dev veth1 xdp pinned $BPF_DIR/progs/redirect_map_0
+ ip link set dev veth2 xdp pinned $BPF_DIR/progs/redirect_map_1
+ ip link set dev veth3 xdp pinned $BPF_DIR/progs/redirect_map_2
+
+-ip -n ns1 link set dev veth11 xdp obj xdp_dummy.o sec xdp_dummy
++ip -n ns1 link set dev veth11 xdp obj xdp_dummy.o sec xdp
+ ip -n ns2 link set dev veth22 xdp obj xdp_tx.o sec xdp
+-ip -n ns3 link set dev veth33 xdp obj xdp_dummy.o sec xdp_dummy
++ip -n ns3 link set dev veth33 xdp obj xdp_dummy.o sec xdp
+
+ trap cleanup EXIT
+
diff --git a/tools/testing/selftests/bpf/verifier/array_access.c b/tools/testing/selftests/bpf/verifier/array_access.c
index 1b1c798e92489..1b138cd2b187d 100644
--- a/tools/testing/selftests/bpf/verifier/array_access.c
@@ -169903,6 +263999,36 @@ index 6e52dfc644153..6fb52d8cfd889 100644
+ .errstr = "R0 invalid mem access",
+ .errstr_unpriv = "R10 partial copy of pointer",
},
+diff --git a/tools/testing/selftests/bpf/verifier/calls.c b/tools/testing/selftests/bpf/verifier/calls.c
+index 336a749673d19..2e701e7f69680 100644
+--- a/tools/testing/selftests/bpf/verifier/calls.c
++++ b/tools/testing/selftests/bpf/verifier/calls.c
+@@ -107,6 +107,25 @@
+ .result = REJECT,
+ .errstr = "R0 min value is outside of the allowed memory range",
+ },
++{
++ "calls: trigger reg2btf_ids[reg->type] for reg->type > __BPF_REG_TYPE_MAX",
++ .insns = {
++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
++ BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 0),
++ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
++ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
++ BPF_EXIT_INSN(),
++ },
++ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
++ .result = REJECT,
++ .errstr = "arg#0 pointer type STRUCT prog_test_ref_kfunc must point",
++ .fixup_kfunc_btf_id = {
++ { "bpf_kfunc_call_test_acquire", 3 },
++ { "bpf_kfunc_call_test_release", 5 },
++ },
++},
+ {
+ "calls: overlapping caller/callee",
+ .insns = {
diff --git a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c
index 2debba4e8a3a8..4d347bc53aa28 100644
--- a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c
@@ -170819,6 +264945,230 @@ index 3696a8f32c235..f5ffba341c174 100644
goto err_out;
}
printf(" %d", ifaces[i]);
+diff --git a/tools/testing/selftests/bpf/xdping.c b/tools/testing/selftests/bpf/xdping.c
+index 842d9155d36c5..79a3453dab255 100644
+--- a/tools/testing/selftests/bpf/xdping.c
++++ b/tools/testing/selftests/bpf/xdping.c
+@@ -178,9 +178,8 @@ int main(int argc, char **argv)
+ return 1;
+ }
+
+- main_prog = bpf_object__find_program_by_title(obj,
+- server ? "xdpserver" :
+- "xdpclient");
++ main_prog = bpf_object__find_program_by_name(obj,
++ server ? "xdping_server" : "xdping_client");
+ if (main_prog)
+ prog_fd = bpf_program__fd(main_prog);
+ if (!main_prog || prog_fd < 0) {
+diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c
+index 623cec04ad422..0cf7e90c0052e 100644
+--- a/tools/testing/selftests/cgroup/cgroup_util.c
++++ b/tools/testing/selftests/cgroup/cgroup_util.c
+@@ -221,7 +221,7 @@ int cg_find_unified_root(char *root, size_t len)
+
+ int cg_create(const char *cgroup)
+ {
+- return mkdir(cgroup, 0644);
++ return mkdir(cgroup, 0755);
+ }
+
+ int cg_wait_for_proc_count(const char *cgroup, int count)
+diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
+index 3df648c378765..6001235030631 100644
+--- a/tools/testing/selftests/cgroup/test_core.c
++++ b/tools/testing/selftests/cgroup/test_core.c
+@@ -1,11 +1,14 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+
++#define _GNU_SOURCE
+ #include <linux/limits.h>
++#include <linux/sched.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <fcntl.h>
++#include <sched.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <signal.h>
+@@ -674,6 +677,166 @@ cleanup:
+ return ret;
+ }
+
++/*
++ * cgroup migration permission check should be performed based on the
++ * credentials at the time of open instead of write.
++ */
++static int test_cgcore_lesser_euid_open(const char *root)
++{
++ const uid_t test_euid = 65534; /* usually nobody, any !root is fine */
++ int ret = KSFT_FAIL;
++ char *cg_test_a = NULL, *cg_test_b = NULL;
++ char *cg_test_a_procs = NULL, *cg_test_b_procs = NULL;
++ int cg_test_b_procs_fd = -1;
++ uid_t saved_uid;
++
++ cg_test_a = cg_name(root, "cg_test_a");
++ cg_test_b = cg_name(root, "cg_test_b");
++
++ if (!cg_test_a || !cg_test_b)
++ goto cleanup;
++
++ cg_test_a_procs = cg_name(cg_test_a, "cgroup.procs");
++ cg_test_b_procs = cg_name(cg_test_b, "cgroup.procs");
++
++ if (!cg_test_a_procs || !cg_test_b_procs)
++ goto cleanup;
++
++ if (cg_create(cg_test_a) || cg_create(cg_test_b))
++ goto cleanup;
++
++ if (cg_enter_current(cg_test_a))
++ goto cleanup;
++
++ if (chown(cg_test_a_procs, test_euid, -1) ||
++ chown(cg_test_b_procs, test_euid, -1))
++ goto cleanup;
++
++ saved_uid = geteuid();
++ if (seteuid(test_euid))
++ goto cleanup;
++
++ cg_test_b_procs_fd = open(cg_test_b_procs, O_RDWR);
++
++ if (seteuid(saved_uid))
++ goto cleanup;
++
++ if (cg_test_b_procs_fd < 0)
++ goto cleanup;
++
++ if (write(cg_test_b_procs_fd, "0", 1) >= 0 || errno != EACCES)
++ goto cleanup;
++
++ ret = KSFT_PASS;
++
++cleanup:
++ cg_enter_current(root);
++ if (cg_test_b_procs_fd >= 0)
++ close(cg_test_b_procs_fd);
++ if (cg_test_b)
++ cg_destroy(cg_test_b);
++ if (cg_test_a)
++ cg_destroy(cg_test_a);
++ free(cg_test_b_procs);
++ free(cg_test_a_procs);
++ free(cg_test_b);
++ free(cg_test_a);
++ return ret;
++}
++
++struct lesser_ns_open_thread_arg {
++ const char *path;
++ int fd;
++ int err;
++};
++
++static int lesser_ns_open_thread_fn(void *arg)
++{
++ struct lesser_ns_open_thread_arg *targ = arg;
++
++ targ->fd = open(targ->path, O_RDWR);
++ targ->err = errno;
++ return 0;
++}
++
++/*
++ * cgroup migration permission check should be performed based on the cgroup
++ * namespace at the time of open instead of write.
++ */
++static int test_cgcore_lesser_ns_open(const char *root)
++{
++ static char stack[65536];
++ const uid_t test_euid = 65534; /* usually nobody, any !root is fine */
++ int ret = KSFT_FAIL;
++ char *cg_test_a = NULL, *cg_test_b = NULL;
++ char *cg_test_a_procs = NULL, *cg_test_b_procs = NULL;
++ int cg_test_b_procs_fd = -1;
++ struct lesser_ns_open_thread_arg targ = { .fd = -1 };
++ pid_t pid;
++ int status;
++
++ cg_test_a = cg_name(root, "cg_test_a");
++ cg_test_b = cg_name(root, "cg_test_b");
++
++ if (!cg_test_a || !cg_test_b)
++ goto cleanup;
++
++ cg_test_a_procs = cg_name(cg_test_a, "cgroup.procs");
++ cg_test_b_procs = cg_name(cg_test_b, "cgroup.procs");
++
++ if (!cg_test_a_procs || !cg_test_b_procs)
++ goto cleanup;
++
++ if (cg_create(cg_test_a) || cg_create(cg_test_b))
++ goto cleanup;
++
++ if (cg_enter_current(cg_test_b))
++ goto cleanup;
++
++ if (chown(cg_test_a_procs, test_euid, -1) ||
++ chown(cg_test_b_procs, test_euid, -1))
++ goto cleanup;
++
++ targ.path = cg_test_b_procs;
++ pid = clone(lesser_ns_open_thread_fn, stack + sizeof(stack),
++ CLONE_NEWCGROUP | CLONE_FILES | CLONE_VM | SIGCHLD,
++ &targ);
++ if (pid < 0)
++ goto cleanup;
++
++ if (waitpid(pid, &status, 0) < 0)
++ goto cleanup;
++
++ if (!WIFEXITED(status))
++ goto cleanup;
++
++ cg_test_b_procs_fd = targ.fd;
++ if (cg_test_b_procs_fd < 0)
++ goto cleanup;
++
++ if (cg_enter_current(cg_test_a))
++ goto cleanup;
++
++ if ((status = write(cg_test_b_procs_fd, "0", 1)) >= 0 || errno != ENOENT)
++ goto cleanup;
++
++ ret = KSFT_PASS;
++
++cleanup:
++ cg_enter_current(root);
++ if (cg_test_b_procs_fd >= 0)
++ close(cg_test_b_procs_fd);
++ if (cg_test_b)
++ cg_destroy(cg_test_b);
++ if (cg_test_a)
++ cg_destroy(cg_test_a);
++ free(cg_test_b_procs);
++ free(cg_test_a_procs);
++ free(cg_test_b);
++ free(cg_test_a);
++ return ret;
++}
++
+ #define T(x) { x, #x }
+ struct corecg_test {
+ int (*fn)(const char *root);
+@@ -689,6 +852,8 @@ struct corecg_test {
+ T(test_cgcore_proc_migration),
+ T(test_cgcore_thread_migration),
+ T(test_cgcore_destroy),
++ T(test_cgcore_lesser_euid_open),
++ T(test_cgcore_lesser_ns_open),
+ };
+ #undef T
+
diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c
index 42be3b9258301..cd4582129c7d6 100644
--- a/tools/testing/selftests/clone3/clone3.c
@@ -170979,6 +265329,54 @@ index 3e3e06ea5703c..86e787895f78b 100644
((offload_count == count))
check_err_fail $should_fail $? "tc police offload count"
}
+diff --git a/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh b/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh
+index fedcb7b35af9f..af5ea50ed5c0e 100755
+--- a/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh
++++ b/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh
+@@ -172,6 +172,17 @@ flooding_filters_add()
+ local lsb
+ local i
+
++ # Prevent unwanted packets from entering the bridge and interfering
++ # with the test.
++ tc qdisc add dev br0 clsact
++ tc filter add dev br0 egress protocol all pref 1 handle 1 \
++ matchall skip_hw action drop
++ tc qdisc add dev $h1 clsact
++ tc filter add dev $h1 egress protocol all pref 1 handle 1 \
++ flower skip_hw dst_mac de:ad:be:ef:13:37 action pass
++ tc filter add dev $h1 egress protocol all pref 2 handle 2 \
++ matchall skip_hw action drop
++
+ tc qdisc add dev $rp2 clsact
+
+ for i in $(eval echo {1..$num_remotes}); do
+@@ -194,6 +205,12 @@ flooding_filters_del()
+ done
+
+ tc qdisc del dev $rp2 clsact
++
++ tc filter del dev $h1 egress protocol all pref 2 handle 2 matchall
++ tc filter del dev $h1 egress protocol all pref 1 handle 1 flower
++ tc qdisc del dev $h1 clsact
++ tc filter del dev br0 egress protocol all pref 1 handle 1 matchall
++ tc qdisc del dev br0 clsact
+ }
+
+ flooding_check_packets()
+diff --git a/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh b/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh
+index f7d84549cc3e3..79f751259098d 100755
+--- a/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh
++++ b/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh
+@@ -185,7 +185,7 @@ setup_prepare()
+
+ tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \
+ protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \
+- action police rate 50mbit burst 64k \
++ action police rate 50mbit burst 64k conform-exceed drop/pipe \
+ action goto chain $(IS2 1 0)
+ }
+
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index dd61118df66ed..2d7fca446c7f7 100644
--- a/tools/testing/selftests/exec/Makefile
@@ -171096,6 +265494,32 @@ index 010b59b139176..1876d148ea0ae 100644
uint64_t vm_get_max_gfn(struct kvm_vm *vm);
int vm_get_fd(struct kvm_vm *vm);
+diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
+index 05e65ca1c30cd..23861c8faa61c 100644
+--- a/tools/testing/selftests/kvm/include/x86_64/processor.h
++++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
+@@ -58,6 +58,21 @@
+ /* CPUID.0x8000_0001.EDX */
+ #define CPUID_GBPAGES (1ul << 26)
+
++/* Page table bitfield declarations */
++#define PTE_PRESENT_MASK BIT_ULL(0)
++#define PTE_WRITABLE_MASK BIT_ULL(1)
++#define PTE_USER_MASK BIT_ULL(2)
++#define PTE_ACCESSED_MASK BIT_ULL(5)
++#define PTE_DIRTY_MASK BIT_ULL(6)
++#define PTE_LARGE_MASK BIT_ULL(7)
++#define PTE_GLOBAL_MASK BIT_ULL(8)
++#define PTE_NX_MASK BIT_ULL(63)
++
++#define PAGE_SHIFT 12
++
++#define PHYSICAL_PAGE_MASK GENMASK_ULL(51, 12)
++#define PTE_GET_PFN(pte) (((pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
++
+ /* General Registers in 64-Bit Mode */
+ struct gpr64_regs {
+ u64 rax;
diff --git a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c
index 0299cd81b8ba2..aa3795cd7bd3d 100644
--- a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c
@@ -171148,6 +265572,19 @@ index 0299cd81b8ba2..aa3795cd7bd3d 100644
/*
* Upstream KVM prior to 4.8 does not support KVM_CAP_MAX_VCPU_ID.
* Userspace is supposed to use KVM_CAP_MAX_VCPUS as the maximum ID
+diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/testing/selftests/kvm/kvm_page_table_test.c
+index 36407cb0ec85d..f1ddfe4c4a031 100644
+--- a/tools/testing/selftests/kvm/kvm_page_table_test.c
++++ b/tools/testing/selftests/kvm/kvm_page_table_test.c
+@@ -278,7 +278,7 @@ static struct kvm_vm *pre_init_before_test(enum vm_guest_mode mode, void *arg)
+ else
+ guest_test_phys_mem = p->phys_offset;
+ #ifdef __s390x__
+- alignment = max(0x100000, alignment);
++ alignment = max(0x100000UL, alignment);
+ #endif
+ guest_test_phys_mem &= ~(alignment - 1);
+
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 10a8ed691c669..e9d0ab9567fbf 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -171174,10 +265611,354 @@ index 10a8ed691c669..e9d0ab9567fbf 100644
{
return vm->max_gfn;
diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
-index 28cb881f440d0..da73b97e1e6dc 100644
+index 28cb881f440d0..46057079d8bba 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
-@@ -1433,3 +1433,71 @@ struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vm *vm, uint32_t vcpui
+@@ -19,38 +19,6 @@
+
+ vm_vaddr_t exception_handlers;
+
+-/* Virtual translation table structure declarations */
+-struct pageUpperEntry {
+- uint64_t present:1;
+- uint64_t writable:1;
+- uint64_t user:1;
+- uint64_t write_through:1;
+- uint64_t cache_disable:1;
+- uint64_t accessed:1;
+- uint64_t ignored_06:1;
+- uint64_t page_size:1;
+- uint64_t ignored_11_08:4;
+- uint64_t pfn:40;
+- uint64_t ignored_62_52:11;
+- uint64_t execute_disable:1;
+-};
+-
+-struct pageTableEntry {
+- uint64_t present:1;
+- uint64_t writable:1;
+- uint64_t user:1;
+- uint64_t write_through:1;
+- uint64_t cache_disable:1;
+- uint64_t accessed:1;
+- uint64_t dirty:1;
+- uint64_t reserved_07:1;
+- uint64_t global:1;
+- uint64_t ignored_11_09:3;
+- uint64_t pfn:40;
+- uint64_t ignored_62_52:11;
+- uint64_t execute_disable:1;
+-};
+-
+ void regs_dump(FILE *stream, struct kvm_regs *regs,
+ uint8_t indent)
+ {
+@@ -195,23 +163,21 @@ static void *virt_get_pte(struct kvm_vm *vm, uint64_t pt_pfn, uint64_t vaddr,
+ return &page_table[index];
+ }
+
+-static struct pageUpperEntry *virt_create_upper_pte(struct kvm_vm *vm,
+- uint64_t pt_pfn,
+- uint64_t vaddr,
+- uint64_t paddr,
+- int level,
+- enum x86_page_size page_size)
++static uint64_t *virt_create_upper_pte(struct kvm_vm *vm,
++ uint64_t pt_pfn,
++ uint64_t vaddr,
++ uint64_t paddr,
++ int level,
++ enum x86_page_size page_size)
+ {
+- struct pageUpperEntry *pte = virt_get_pte(vm, pt_pfn, vaddr, level);
+-
+- if (!pte->present) {
+- pte->writable = true;
+- pte->present = true;
+- pte->page_size = (level == page_size);
+- if (pte->page_size)
+- pte->pfn = paddr >> vm->page_shift;
++ uint64_t *pte = virt_get_pte(vm, pt_pfn, vaddr, level);
++
++ if (!(*pte & PTE_PRESENT_MASK)) {
++ *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK;
++ if (level == page_size)
++ *pte |= PTE_LARGE_MASK | (paddr & PHYSICAL_PAGE_MASK);
+ else
+- pte->pfn = vm_alloc_page_table(vm) >> vm->page_shift;
++ *pte |= vm_alloc_page_table(vm) & PHYSICAL_PAGE_MASK;
+ } else {
+ /*
+ * Entry already present. Assert that the caller doesn't want
+@@ -221,7 +187,7 @@ static struct pageUpperEntry *virt_create_upper_pte(struct kvm_vm *vm,
+ TEST_ASSERT(level != page_size,
+ "Cannot create hugepage at level: %u, vaddr: 0x%lx\n",
+ page_size, vaddr);
+- TEST_ASSERT(!pte->page_size,
++ TEST_ASSERT(!(*pte & PTE_LARGE_MASK),
+ "Cannot create page table at level: %u, vaddr: 0x%lx\n",
+ level, vaddr);
+ }
+@@ -232,8 +198,8 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
+ enum x86_page_size page_size)
+ {
+ const uint64_t pg_size = 1ull << ((page_size * 9) + 12);
+- struct pageUpperEntry *pml4e, *pdpe, *pde;
+- struct pageTableEntry *pte;
++ uint64_t *pml4e, *pdpe, *pde;
++ uint64_t *pte;
+
+ TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K,
+ "Unknown or unsupported guest mode, mode: 0x%x", vm->mode);
+@@ -257,24 +223,22 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
+ */
+ pml4e = virt_create_upper_pte(vm, vm->pgd >> vm->page_shift,
+ vaddr, paddr, 3, page_size);
+- if (pml4e->page_size)
++ if (*pml4e & PTE_LARGE_MASK)
+ return;
+
+- pdpe = virt_create_upper_pte(vm, pml4e->pfn, vaddr, paddr, 2, page_size);
+- if (pdpe->page_size)
++ pdpe = virt_create_upper_pte(vm, PTE_GET_PFN(*pml4e), vaddr, paddr, 2, page_size);
++ if (*pdpe & PTE_LARGE_MASK)
+ return;
+
+- pde = virt_create_upper_pte(vm, pdpe->pfn, vaddr, paddr, 1, page_size);
+- if (pde->page_size)
++ pde = virt_create_upper_pte(vm, PTE_GET_PFN(*pdpe), vaddr, paddr, 1, page_size);
++ if (*pde & PTE_LARGE_MASK)
+ return;
+
+ /* Fill in page table entry. */
+- pte = virt_get_pte(vm, pde->pfn, vaddr, 0);
+- TEST_ASSERT(!pte->present,
++ pte = virt_get_pte(vm, PTE_GET_PFN(*pde), vaddr, 0);
++ TEST_ASSERT(!(*pte & PTE_PRESENT_MASK),
+ "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr);
+- pte->pfn = paddr >> vm->page_shift;
+- pte->writable = true;
+- pte->present = 1;
++ *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK);
+ }
+
+ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
+@@ -282,12 +246,12 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
+ __virt_pg_map(vm, vaddr, paddr, X86_PAGE_SIZE_4K);
+ }
+
+-static struct pageTableEntry *_vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid,
++static uint64_t *_vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid,
+ uint64_t vaddr)
+ {
+ uint16_t index[4];
+- struct pageUpperEntry *pml4e, *pdpe, *pde;
+- struct pageTableEntry *pte;
++ uint64_t *pml4e, *pdpe, *pde;
++ uint64_t *pte;
+ struct kvm_cpuid_entry2 *entry;
+ struct kvm_sregs sregs;
+ int max_phy_addr;
+@@ -329,30 +293,29 @@ static struct pageTableEntry *_vm_get_page_table_entry(struct kvm_vm *vm, int vc
+ index[3] = (vaddr >> 39) & 0x1ffu;
+
+ pml4e = addr_gpa2hva(vm, vm->pgd);
+- TEST_ASSERT(pml4e[index[3]].present,
++ TEST_ASSERT(pml4e[index[3]] & PTE_PRESENT_MASK,
+ "Expected pml4e to be present for gva: 0x%08lx", vaddr);
+- TEST_ASSERT((*(uint64_t*)(&pml4e[index[3]]) &
+- (rsvd_mask | (1ull << 7))) == 0,
++ TEST_ASSERT((pml4e[index[3]] & (rsvd_mask | PTE_LARGE_MASK)) == 0,
+ "Unexpected reserved bits set.");
+
+- pdpe = addr_gpa2hva(vm, pml4e[index[3]].pfn * vm->page_size);
+- TEST_ASSERT(pdpe[index[2]].present,
++ pdpe = addr_gpa2hva(vm, PTE_GET_PFN(pml4e[index[3]]) * vm->page_size);
++ TEST_ASSERT(pdpe[index[2]] & PTE_PRESENT_MASK,
+ "Expected pdpe to be present for gva: 0x%08lx", vaddr);
+- TEST_ASSERT(pdpe[index[2]].page_size == 0,
++ TEST_ASSERT(!(pdpe[index[2]] & PTE_LARGE_MASK),
+ "Expected pdpe to map a pde not a 1-GByte page.");
+- TEST_ASSERT((*(uint64_t*)(&pdpe[index[2]]) & rsvd_mask) == 0,
++ TEST_ASSERT((pdpe[index[2]] & rsvd_mask) == 0,
+ "Unexpected reserved bits set.");
+
+- pde = addr_gpa2hva(vm, pdpe[index[2]].pfn * vm->page_size);
+- TEST_ASSERT(pde[index[1]].present,
++ pde = addr_gpa2hva(vm, PTE_GET_PFN(pdpe[index[2]]) * vm->page_size);
++ TEST_ASSERT(pde[index[1]] & PTE_PRESENT_MASK,
+ "Expected pde to be present for gva: 0x%08lx", vaddr);
+- TEST_ASSERT(pde[index[1]].page_size == 0,
++ TEST_ASSERT(!(pde[index[1]] & PTE_LARGE_MASK),
+ "Expected pde to map a pte not a 2-MByte page.");
+- TEST_ASSERT((*(uint64_t*)(&pde[index[1]]) & rsvd_mask) == 0,
++ TEST_ASSERT((pde[index[1]] & rsvd_mask) == 0,
+ "Unexpected reserved bits set.");
+
+- pte = addr_gpa2hva(vm, pde[index[1]].pfn * vm->page_size);
+- TEST_ASSERT(pte[index[0]].present,
++ pte = addr_gpa2hva(vm, PTE_GET_PFN(pde[index[1]]) * vm->page_size);
++ TEST_ASSERT(pte[index[0]] & PTE_PRESENT_MASK,
+ "Expected pte to be present for gva: 0x%08lx", vaddr);
+
+ return &pte[index[0]];
+@@ -360,7 +323,7 @@ static struct pageTableEntry *_vm_get_page_table_entry(struct kvm_vm *vm, int vc
+
+ uint64_t vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr)
+ {
+- struct pageTableEntry *pte = _vm_get_page_table_entry(vm, vcpuid, vaddr);
++ uint64_t *pte = _vm_get_page_table_entry(vm, vcpuid, vaddr);
+
+ return *(uint64_t *)pte;
+ }
+@@ -368,18 +331,17 @@ uint64_t vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr)
+ void vm_set_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr,
+ uint64_t pte)
+ {
+- struct pageTableEntry *new_pte = _vm_get_page_table_entry(vm, vcpuid,
+- vaddr);
++ uint64_t *new_pte = _vm_get_page_table_entry(vm, vcpuid, vaddr);
+
+ *(uint64_t *)new_pte = pte;
+ }
+
+ void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+ {
+- struct pageUpperEntry *pml4e, *pml4e_start;
+- struct pageUpperEntry *pdpe, *pdpe_start;
+- struct pageUpperEntry *pde, *pde_start;
+- struct pageTableEntry *pte, *pte_start;
++ uint64_t *pml4e, *pml4e_start;
++ uint64_t *pdpe, *pdpe_start;
++ uint64_t *pde, *pde_start;
++ uint64_t *pte, *pte_start;
+
+ if (!vm->pgd_created)
+ return;
+@@ -389,58 +351,58 @@ void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+ fprintf(stream, "%*s index hvaddr gpaddr "
+ "addr w exec dirty\n",
+ indent, "");
+- pml4e_start = (struct pageUpperEntry *) addr_gpa2hva(vm, vm->pgd);
++ pml4e_start = (uint64_t *) addr_gpa2hva(vm, vm->pgd);
+ for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) {
+ pml4e = &pml4e_start[n1];
+- if (!pml4e->present)
++ if (!(*pml4e & PTE_PRESENT_MASK))
+ continue;
+- fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u "
++ fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10llx %u "
+ " %u\n",
+ indent, "",
+ pml4e - pml4e_start, pml4e,
+- addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->pfn,
+- pml4e->writable, pml4e->execute_disable);
++ addr_hva2gpa(vm, pml4e), PTE_GET_PFN(*pml4e),
++ !!(*pml4e & PTE_WRITABLE_MASK), !!(*pml4e & PTE_NX_MASK));
+
+- pdpe_start = addr_gpa2hva(vm, pml4e->pfn * vm->page_size);
++ pdpe_start = addr_gpa2hva(vm, *pml4e & PHYSICAL_PAGE_MASK);
+ for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) {
+ pdpe = &pdpe_start[n2];
+- if (!pdpe->present)
++ if (!(*pdpe & PTE_PRESENT_MASK))
+ continue;
+- fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10lx "
++ fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10llx "
+ "%u %u\n",
+ indent, "",
+ pdpe - pdpe_start, pdpe,
+ addr_hva2gpa(vm, pdpe),
+- (uint64_t) pdpe->pfn, pdpe->writable,
+- pdpe->execute_disable);
++ PTE_GET_PFN(*pdpe), !!(*pdpe & PTE_WRITABLE_MASK),
++ !!(*pdpe & PTE_NX_MASK));
+
+- pde_start = addr_gpa2hva(vm, pdpe->pfn * vm->page_size);
++ pde_start = addr_gpa2hva(vm, *pdpe & PHYSICAL_PAGE_MASK);
+ for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) {
+ pde = &pde_start[n3];
+- if (!pde->present)
++ if (!(*pde & PTE_PRESENT_MASK))
+ continue;
+ fprintf(stream, "%*spde 0x%-3zx %p "
+- "0x%-12lx 0x%-10lx %u %u\n",
++ "0x%-12lx 0x%-10llx %u %u\n",
+ indent, "", pde - pde_start, pde,
+ addr_hva2gpa(vm, pde),
+- (uint64_t) pde->pfn, pde->writable,
+- pde->execute_disable);
++ PTE_GET_PFN(*pde), !!(*pde & PTE_WRITABLE_MASK),
++ !!(*pde & PTE_NX_MASK));
+
+- pte_start = addr_gpa2hva(vm, pde->pfn * vm->page_size);
++ pte_start = addr_gpa2hva(vm, *pde & PHYSICAL_PAGE_MASK);
+ for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) {
+ pte = &pte_start[n4];
+- if (!pte->present)
++ if (!(*pte & PTE_PRESENT_MASK))
+ continue;
+ fprintf(stream, "%*spte 0x%-3zx %p "
+- "0x%-12lx 0x%-10lx %u %u "
++ "0x%-12lx 0x%-10llx %u %u "
+ " %u 0x%-10lx\n",
+ indent, "",
+ pte - pte_start, pte,
+ addr_hva2gpa(vm, pte),
+- (uint64_t) pte->pfn,
+- pte->writable,
+- pte->execute_disable,
+- pte->dirty,
++ PTE_GET_PFN(*pte),
++ !!(*pte & PTE_WRITABLE_MASK),
++ !!(*pte & PTE_NX_MASK),
++ !!(*pte & PTE_DIRTY_MASK),
+ ((uint64_t) n1 << 27)
+ | ((uint64_t) n2 << 18)
+ | ((uint64_t) n3 << 9)
+@@ -558,8 +520,8 @@ static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
+ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
+ {
+ uint16_t index[4];
+- struct pageUpperEntry *pml4e, *pdpe, *pde;
+- struct pageTableEntry *pte;
++ uint64_t *pml4e, *pdpe, *pde;
++ uint64_t *pte;
+
+ TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
+ "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
+@@ -572,22 +534,22 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
+ if (!vm->pgd_created)
+ goto unmapped_gva;
+ pml4e = addr_gpa2hva(vm, vm->pgd);
+- if (!pml4e[index[3]].present)
++ if (!(pml4e[index[3]] & PTE_PRESENT_MASK))
+ goto unmapped_gva;
+
+- pdpe = addr_gpa2hva(vm, pml4e[index[3]].pfn * vm->page_size);
+- if (!pdpe[index[2]].present)
++ pdpe = addr_gpa2hva(vm, PTE_GET_PFN(pml4e[index[3]]) * vm->page_size);
++ if (!(pdpe[index[2]] & PTE_PRESENT_MASK))
+ goto unmapped_gva;
+
+- pde = addr_gpa2hva(vm, pdpe[index[2]].pfn * vm->page_size);
+- if (!pde[index[1]].present)
++ pde = addr_gpa2hva(vm, PTE_GET_PFN(pdpe[index[2]]) * vm->page_size);
++ if (!(pde[index[1]] & PTE_PRESENT_MASK))
+ goto unmapped_gva;
+
+- pte = addr_gpa2hva(vm, pde[index[1]].pfn * vm->page_size);
+- if (!pte[index[0]].present)
++ pte = addr_gpa2hva(vm, PTE_GET_PFN(pde[index[1]]) * vm->page_size);
++ if (!(pte[index[0]] & PTE_PRESENT_MASK))
+ goto unmapped_gva;
+
+- return (pte[index[0]].pfn * vm->page_size) + (gva & 0xfffu);
++ return (PTE_GET_PFN(pte[index[0]]) * vm->page_size) + (gva & 0xfffu);
+
+ unmapped_gva:
+ TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva);
+@@ -1433,3 +1395,71 @@ struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vm *vm, uint32_t vcpui
return cpuid;
}
@@ -171306,6 +266087,29 @@ index d0fe2fdce58c4..db2a17559c3d5 100644
run_guest(svm->vmcb, svm->vmcb_gpa);
} else {
vmlaunch();
+diff --git a/tools/testing/selftests/lkdtm/config b/tools/testing/selftests/lkdtm/config
+index 38edea25631bc..b642411ceb6c3 100644
+--- a/tools/testing/selftests/lkdtm/config
++++ b/tools/testing/selftests/lkdtm/config
+@@ -6,5 +6,6 @@ CONFIG_HARDENED_USERCOPY=y
+ # CONFIG_HARDENED_USERCOPY_FALLBACK is not set
+ CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
+ CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
++CONFIG_UBSAN=y
+ CONFIG_UBSAN_BOUNDS=y
+ CONFIG_UBSAN_TRAP=y
+diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
+index 192a2899bae8f..94df2692e6e4a 100644
+--- a/tools/testing/selftests/memfd/memfd_test.c
++++ b/tools/testing/selftests/memfd/memfd_test.c
+@@ -455,6 +455,7 @@ static void mfd_fail_write(int fd)
+ printf("mmap()+mprotect() didn't fail as expected\n");
+ abort();
+ }
++ munmap(p, mfd_def_size);
+ }
+
+ /* verify PUNCH_HOLE fails */
diff --git a/tools/testing/selftests/mincore/mincore_selftest.c b/tools/testing/selftests/mincore/mincore_selftest.c
index e54106643337b..4c88238fc8f05 100644
--- a/tools/testing/selftests/mincore/mincore_selftest.c
@@ -171370,6 +266174,80 @@ index f31205f04ee05..8c5fea68ae677 100644
ASSERT_EQ(close(attr.userns_fd), 0);
ASSERT_EQ(close(open_tree_fd), 0);
}
+diff --git a/tools/testing/selftests/mqueue/mq_perf_tests.c b/tools/testing/selftests/mqueue/mq_perf_tests.c
+index b019e0b8221c7..84fda3b490735 100644
+--- a/tools/testing/selftests/mqueue/mq_perf_tests.c
++++ b/tools/testing/selftests/mqueue/mq_perf_tests.c
+@@ -180,6 +180,9 @@ void shutdown(int exit_val, char *err_cause, int line_no)
+ if (in_shutdown++)
+ return;
+
++ /* Free the cpu_set allocated using CPU_ALLOC in main function */
++ CPU_FREE(cpu_set);
++
+ for (i = 0; i < num_cpus_to_pin; i++)
+ if (cpu_threads[i]) {
+ pthread_kill(cpu_threads[i], SIGUSR1);
+@@ -551,6 +554,12 @@ int main(int argc, char *argv[])
+ perror("sysconf(_SC_NPROCESSORS_ONLN)");
+ exit(1);
+ }
++
++ if (getuid() != 0)
++ ksft_exit_skip("Not running as root, but almost all tests "
++ "require root in order to modify\nsystem settings. "
++ "Exiting.\n");
++
+ cpus_online = min(MAX_CPUS, sysconf(_SC_NPROCESSORS_ONLN));
+ cpu_set = CPU_ALLOC(cpus_online);
+ if (cpu_set == NULL) {
+@@ -589,7 +598,7 @@ int main(int argc, char *argv[])
+ cpu_set)) {
+ fprintf(stderr, "Any given CPU may "
+ "only be given once.\n");
+- exit(1);
++ goto err_code;
+ } else
+ CPU_SET_S(cpus_to_pin[cpu],
+ cpu_set_size, cpu_set);
+@@ -607,7 +616,7 @@ int main(int argc, char *argv[])
+ queue_path = malloc(strlen(option) + 2);
+ if (!queue_path) {
+ perror("malloc()");
+- exit(1);
++ goto err_code;
+ }
+ queue_path[0] = '/';
+ queue_path[1] = 0;
+@@ -622,17 +631,12 @@ int main(int argc, char *argv[])
+ fprintf(stderr, "Must pass at least one CPU to continuous "
+ "mode.\n");
+ poptPrintUsage(popt_context, stderr, 0);
+- exit(1);
++ goto err_code;
+ } else if (!continuous_mode) {
+ num_cpus_to_pin = 1;
+ cpus_to_pin[0] = cpus_online - 1;
+ }
+
+- if (getuid() != 0)
+- ksft_exit_skip("Not running as root, but almost all tests "
+- "require root in order to modify\nsystem settings. "
+- "Exiting.\n");
+-
+ max_msgs = fopen(MAX_MSGS, "r+");
+ max_msgsize = fopen(MAX_MSGSIZE, "r+");
+ if (!max_msgs)
+@@ -740,4 +744,9 @@ int main(int argc, char *argv[])
+ sleep(1);
+ }
+ shutdown(0, "", 0);
++
++err_code:
++ CPU_FREE(cpu_set);
++ exit(1);
++
+ }
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 492b273743b4e..6a953ec793ced 100644
--- a/tools/testing/selftests/net/Makefile
@@ -171397,8 +266275,26 @@ index 492b273743b4e..6a953ec793ced 100644
TEST_GEN_FILES = socket nettest
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite
+diff --git a/tools/testing/selftests/net/af_unix/test_unix_oob.c b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+index 3dece8b292536..b57e91e1c3f28 100644
+--- a/tools/testing/selftests/net/af_unix/test_unix_oob.c
++++ b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+@@ -218,10 +218,10 @@ main(int argc, char **argv)
+
+ /* Test 1:
+ * veriyf that SIGURG is
+- * delivered and 63 bytes are
+- * read and oob is '@'
++ * delivered, 63 bytes are
++ * read, oob is '@', and POLLPRI works.
+ */
+- wait_for_data(pfd, POLLIN | POLLPRI);
++ wait_for_data(pfd, POLLPRI);
+ read_oob(pfd, &oob);
+ len = read_data(pfd, buf, 1024);
+ if (!signal_recvd || len != 63 || oob != '@') {
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
-index 3313566ce9062..aec9e784d0b46 100755
+index 3313566ce9062..91f54112167f1 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -455,6 +455,22 @@ cleanup()
@@ -171437,7 +266333,24 @@ index 3313566ce9062..aec9e784d0b46 100755
else
ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV}
ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV}
-@@ -1240,7 +1250,9 @@ ipv4_tcp_vrf()
+@@ -793,10 +803,16 @@ ipv4_ping()
+ setup
+ set_sysctl net.ipv4.raw_l3mdev_accept=1 2>/dev/null
+ ipv4_ping_novrf
++ setup
++ set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
++ ipv4_ping_novrf
+
+ log_subsection "With VRF"
+ setup "yes"
+ ipv4_ping_vrf
++ setup "yes"
++ set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
++ ipv4_ping_vrf
+ }
+
+ ################################################################################
+@@ -1240,7 +1256,9 @@ ipv4_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
@@ -171447,7 +266360,7 @@ index 3313566ce9062..aec9e784d0b46 100755
#
# enable VRF global server
-@@ -1798,8 +1810,9 @@ ipv4_addr_bind_vrf()
+@@ -1798,8 +1816,9 @@ ipv4_addr_bind_vrf()
for a in ${NSA_IP} ${VRF_IP}
do
log_start
@@ -171458,7 +266371,7 @@ index 3313566ce9062..aec9e784d0b46 100755
log_start
run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b
-@@ -2191,7 +2204,7 @@ ipv6_ping_vrf()
+@@ -2191,7 +2210,7 @@ ipv6_ping_vrf()
log_start
show_hint "Fails since VRF device does not support linklocal or multicast"
run_cmd ${ping6} -c1 -w1 ${a}
@@ -171467,7 +266380,24 @@ index 3313566ce9062..aec9e784d0b46 100755
done
for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV}
-@@ -2719,7 +2732,9 @@ ipv6_tcp_vrf()
+@@ -2311,10 +2330,16 @@ ipv6_ping()
+ log_subsection "No VRF"
+ setup
+ ipv6_ping_novrf
++ setup
++ set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
++ ipv6_ping_novrf
+
+ log_subsection "With VRF"
+ setup "yes"
+ ipv6_ping_vrf
++ setup "yes"
++ set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
++ ipv6_ping_vrf
+ }
+
+ ################################################################################
+@@ -2719,7 +2744,9 @@ ipv6_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
@@ -171477,7 +266407,7 @@ index 3313566ce9062..aec9e784d0b46 100755
#
# enable VRF global server
-@@ -3414,11 +3429,14 @@ ipv6_addr_bind_novrf()
+@@ -3414,11 +3441,14 @@ ipv6_addr_bind_novrf()
run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b
log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind"
@@ -171494,7 +266424,7 @@ index 3313566ce9062..aec9e784d0b46 100755
}
ipv6_addr_bind_vrf()
-@@ -3459,10 +3477,15 @@ ipv6_addr_bind_vrf()
+@@ -3459,10 +3489,15 @@ ipv6_addr_bind_vrf()
run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b
log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind"
@@ -171511,7 +266441,7 @@ index 3313566ce9062..aec9e784d0b46 100755
a=${NSA_LO_IP6}
log_start
-@@ -4002,8 +4025,8 @@ EOF
+@@ -4002,8 +4037,8 @@ EOF
################################################################################
# main
@@ -171689,6 +266619,23 @@ index e5e2fbeca22ec..e51def39fd801 100644
# Port that does not have a cable connected.
NETIF_NO_CABLE=eth8
+diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
+index a3402cd8d5b68..9ff22f28032dd 100755
+--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
++++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
+@@ -61,9 +61,12 @@ setup_prepare()
+
+ vrf_prepare
+ mirror_gre_topo_create
++ # Avoid changing br1's PVID while it is operational as a L3 interface.
++ ip link set dev br1 down
+
+ ip link set dev $swp3 master br1
+ bridge vlan add dev br1 vid 555 pvid untagged self
++ ip link set dev br1 up
+ ip address add dev br1 192.0.2.129/28
+ ip address add dev br1 2001:db8:2::1/64
+
diff --git a/tools/testing/selftests/net/gre_gso.sh b/tools/testing/selftests/net/gre_gso.sh
index facbb0c804439..3224651db97b8 100755
--- a/tools/testing/selftests/net/gre_gso.sh
@@ -171838,6 +266785,43 @@ index 2674ba20d5249..ff821025d3096 100755
for I in `seq 1 $NR_CLIENTS`; do
echo "b" | \
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+index 559173a8e387b..d75fa97609c15 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+@@ -445,6 +445,8 @@ do_transfer()
+ local stat_ackrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
+ local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent")
+ local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv")
++ local stat_csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
++ local stat_csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
+
+ timeout ${timeout_test} \
+ ip netns exec ${listener_ns} \
+@@ -537,6 +539,23 @@ do_transfer()
+ fi
+ fi
+
++ if $checksum; then
++ local csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
++ local csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
++
++ local csum_err_s_nr=$((csum_err_s - stat_csum_err_s))
++ if [ $csum_err_s_nr -gt 0 ]; then
++ printf "[ FAIL ]\nserver got $csum_err_s_nr data checksum error[s]"
++ rets=1
++ fi
++
++ local csum_err_c_nr=$((csum_err_c - stat_csum_err_c))
++ if [ $csum_err_c_nr -gt 0 ]; then
++ printf "[ FAIL ]\nclient got $csum_err_c_nr data checksum error[s]"
++ retc=1
++ fi
++ fi
++
+ if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then
+ printf "[ OK ]"
+ fi
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 255793c5ac4ff..3be615ab1588b 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -171909,6 +266893,125 @@ index 255793c5ac4ff..3be615ab1588b 100755
run_tests $ns1 $ns2 dead:beef:1::1 0 -1 -1 slow
chk_join_nr "remove subflow and signal IPv6" 2 2 2
chk_add_nr 1 1
+diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh
+index 543ad7513a8e9..694732e4b3448 100755
+--- a/tools/testing/selftests/net/pmtu.sh
++++ b/tools/testing/selftests/net/pmtu.sh
+@@ -374,6 +374,16 @@ run_cmd() {
+ return $rc
+ }
+
++run_cmd_bg() {
++ cmd="$*"
++
++ if [ "$VERBOSE" = "1" ]; then
++ printf " COMMAND: %s &\n" "${cmd}"
++ fi
++
++ $cmd 2>&1 &
++}
++
+ # Find the auto-generated name for this namespace
+ nsname() {
+ eval echo \$NS_$1
+@@ -670,10 +680,10 @@ setup_nettest_xfrm() {
+ [ ${1} -eq 6 ] && proto="-6" || proto=""
+ port=${2}
+
+- run_cmd ${ns_a} nettest ${proto} -q -D -s -x -p ${port} -t 5 &
++ run_cmd_bg "${ns_a}" nettest "${proto}" -q -D -s -x -p "${port}" -t 5
+ nettest_pids="${nettest_pids} $!"
+
+- run_cmd ${ns_b} nettest ${proto} -q -D -s -x -p ${port} -t 5 &
++ run_cmd_bg "${ns_b}" nettest "${proto}" -q -D -s -x -p "${port}" -t 5
+ nettest_pids="${nettest_pids} $!"
+ }
+
+@@ -865,7 +875,6 @@ setup_ovs_bridge() {
+ setup() {
+ [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip
+
+- cleanup
+ for arg do
+ eval setup_${arg} || { echo " ${arg} not supported"; return 1; }
+ done
+@@ -876,7 +885,7 @@ trace() {
+
+ for arg do
+ [ "${ns_cmd}" = "" ] && ns_cmd="${arg}" && continue
+- ${ns_cmd} tcpdump -s 0 -i "${arg}" -w "${name}_${arg}.pcap" 2> /dev/null &
++ ${ns_cmd} tcpdump --immediate-mode -s 0 -i "${arg}" -w "${name}_${arg}.pcap" 2> /dev/null &
+ tcpdump_pids="${tcpdump_pids} $!"
+ ns_cmd=
+ done
+@@ -1836,6 +1845,10 @@ run_test() {
+
+ unset IFS
+
++ # Since cleanup() relies on variables modified by this subshell, it
++ # has to run in this context.
++ trap cleanup EXIT
++
+ if [ "$VERBOSE" = "1" ]; then
+ printf "\n##########################################################################\n\n"
+ fi
+diff --git a/tools/testing/selftests/net/so_txtime.c b/tools/testing/selftests/net/so_txtime.c
+index 59067f64b7753..2672ac0b6d1f3 100644
+--- a/tools/testing/selftests/net/so_txtime.c
++++ b/tools/testing/selftests/net/so_txtime.c
+@@ -421,7 +421,7 @@ static void usage(const char *progname)
+ "Options:\n"
+ " -4 only IPv4\n"
+ " -6 only IPv6\n"
+- " -c <clock> monotonic (default) or tai\n"
++ " -c <clock> monotonic or tai (default)\n"
+ " -D <addr> destination IP address (server)\n"
+ " -S <addr> source IP address (client)\n"
+ " -r run rx mode\n"
+@@ -475,7 +475,7 @@ static void parse_opts(int argc, char **argv)
+ cfg_rx = true;
+ break;
+ case 't':
+- cfg_start_time_ns = strtol(optarg, NULL, 0);
++ cfg_start_time_ns = strtoll(optarg, NULL, 0);
+ break;
+ case 'm':
+ cfg_mark = strtol(optarg, NULL, 0);
+diff --git a/tools/testing/selftests/net/test_vxlan_under_vrf.sh b/tools/testing/selftests/net/test_vxlan_under_vrf.sh
+index 534c8b7699ab9..6fadc8e2f116a 100755
+--- a/tools/testing/selftests/net/test_vxlan_under_vrf.sh
++++ b/tools/testing/selftests/net/test_vxlan_under_vrf.sh
+@@ -118,11 +118,11 @@ echo "[ OK ]"
+
+ # Move the underlay to a non-default VRF
+ ip -netns hv-1 link set veth0 vrf vrf-underlay
+-ip -netns hv-1 link set veth0 down
+-ip -netns hv-1 link set veth0 up
++ip -netns hv-1 link set vxlan0 down
++ip -netns hv-1 link set vxlan0 up
+ ip -netns hv-2 link set veth0 vrf vrf-underlay
+-ip -netns hv-2 link set veth0 down
+-ip -netns hv-2 link set veth0 up
++ip -netns hv-2 link set vxlan0 down
++ip -netns hv-2 link set vxlan0 up
+
+ echo -n "Check VM connectivity through VXLAN (underlay in a VRF) "
+ ip netns exec vm-1 ping -c 1 -W 1 10.0.0.2 &> /dev/null || (echo "[FAIL]"; false)
+diff --git a/tools/testing/selftests/net/timestamping.c b/tools/testing/selftests/net/timestamping.c
+index aee631c5284eb..044bc0e9ed81a 100644
+--- a/tools/testing/selftests/net/timestamping.c
++++ b/tools/testing/selftests/net/timestamping.c
+@@ -325,8 +325,8 @@ int main(int argc, char **argv)
+ struct ifreq device;
+ struct ifreq hwtstamp;
+ struct hwtstamp_config hwconfig, hwconfig_requested;
+- struct so_timestamping so_timestamping_get = { 0, -1 };
+- struct so_timestamping so_timestamping = { 0, -1 };
++ struct so_timestamping so_timestamping_get = { 0, 0 };
++ struct so_timestamping so_timestamping = { 0, 0 };
+ struct sockaddr_in addr;
+ struct ip_mreq imr;
+ struct in_addr iaddr;
diff --git a/tools/testing/selftests/net/toeplitz.c b/tools/testing/selftests/net/toeplitz.c
index 710ac956bdb33..c5489341cfb80 100644
--- a/tools/testing/selftests/net/toeplitz.c
@@ -173021,6 +268124,21 @@ index 0000000000000..0a1b6e591eeed
+{
+ return test_harness(test_sigreturn_kernel, "sigreturn_kernel");
+}
+diff --git a/tools/testing/selftests/rcutorture/bin/torture.sh b/tools/testing/selftests/rcutorture/bin/torture.sh
+index 363f56081eff3..66f0f724a1a6d 100755
+--- a/tools/testing/selftests/rcutorture/bin/torture.sh
++++ b/tools/testing/selftests/rcutorture/bin/torture.sh
+@@ -71,8 +71,8 @@ usage () {
+ echo " --configs-rcutorture \"config-file list w/ repeat factor (3*TINY01)\""
+ echo " --configs-locktorture \"config-file list w/ repeat factor (10*LOCK01)\""
+ echo " --configs-scftorture \"config-file list w/ repeat factor (2*CFLIST)\""
+- echo " --doall"
+- echo " --doallmodconfig / --do-no-allmodconfig"
++ echo " --do-all"
++ echo " --do-allmodconfig / --do-no-allmodconfig"
+ echo " --do-clocksourcewd / --do-no-clocksourcewd"
+ echo " --do-kasan / --do-no-kasan"
+ echo " --do-kcsan / --do-no-kcsan"
diff --git a/tools/testing/selftests/rtc/settings b/tools/testing/selftests/rtc/settings
index ba4d85f74cd6b..a953c96aa16e1 100644
--- a/tools/testing/selftests/rtc/settings
@@ -173109,6 +268227,68 @@ index 0ebfe8b0e147f..585f7a0c10cbe 100644
LDFLAGS += -lpthread
TEST_GEN_PROGS := seccomp_bpf seccomp_benchmark
+diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
+index 1d64891e64923..34ebd1fe5eed2 100644
+--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
++++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
+@@ -955,7 +955,7 @@ TEST(ERRNO_valid)
+ ASSERT_EQ(0, ret);
+
+ EXPECT_EQ(parent, syscall(__NR_getppid));
+- EXPECT_EQ(-1, read(0, NULL, 0));
++ EXPECT_EQ(-1, read(-1, NULL, 0));
+ EXPECT_EQ(E2BIG, errno);
+ }
+
+@@ -974,7 +974,7 @@ TEST(ERRNO_zero)
+
+ EXPECT_EQ(parent, syscall(__NR_getppid));
+ /* "errno" of 0 is ok. */
+- EXPECT_EQ(0, read(0, NULL, 0));
++ EXPECT_EQ(0, read(-1, NULL, 0));
+ }
+
+ /*
+@@ -995,7 +995,7 @@ TEST(ERRNO_capped)
+ ASSERT_EQ(0, ret);
+
+ EXPECT_EQ(parent, syscall(__NR_getppid));
+- EXPECT_EQ(-1, read(0, NULL, 0));
++ EXPECT_EQ(-1, read(-1, NULL, 0));
+ EXPECT_EQ(4095, errno);
+ }
+
+@@ -1026,7 +1026,7 @@ TEST(ERRNO_order)
+ ASSERT_EQ(0, ret);
+
+ EXPECT_EQ(parent, syscall(__NR_getppid));
+- EXPECT_EQ(-1, read(0, NULL, 0));
++ EXPECT_EQ(-1, read(-1, NULL, 0));
+ EXPECT_EQ(12, errno);
+ }
+
+@@ -2579,7 +2579,7 @@ void *tsync_sibling(void *data)
+ ret = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
+ if (!ret)
+ return (void *)SIBLING_EXIT_NEWPRIVS;
+- read(0, NULL, 0);
++ read(-1, NULL, 0);
+ return (void *)SIBLING_EXIT_UNKILLED;
+ }
+
+diff --git a/tools/testing/selftests/sgx/Makefile b/tools/testing/selftests/sgx/Makefile
+index 7f12d55b97f86..472b27ccd7dcb 100644
+--- a/tools/testing/selftests/sgx/Makefile
++++ b/tools/testing/selftests/sgx/Makefile
+@@ -4,7 +4,7 @@ include ../lib.mk
+
+ .PHONY: all clean
+
+-CAN_BUILD_X86_64 := $(shell ../x86/check_cc.sh $(CC) \
++CAN_BUILD_X86_64 := $(shell ../x86/check_cc.sh "$(CC)" \
+ ../x86/trivial_64bit_program.c)
+
+ ifndef OBJCOPY
diff --git a/tools/testing/selftests/vDSO/vdso_test_abi.c b/tools/testing/selftests/vDSO/vdso_test_abi.c
index 3d603f1394af4..883ca85424bc5 100644
--- a/tools/testing/selftests/vDSO/vdso_test_abi.c
@@ -173368,6 +268548,68 @@ index 3d603f1394af4..883ca85424bc5 100644
+ ksft_print_cnts();
+ return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
}
+diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
+index d9605bd10f2de..d8ae7cc012749 100644
+--- a/tools/testing/selftests/vm/Makefile
++++ b/tools/testing/selftests/vm/Makefile
+@@ -1,6 +1,8 @@
+ # SPDX-License-Identifier: GPL-2.0
+ # Makefile for vm selftests
+
++LOCAL_HDRS += $(selfdir)/vm/local_config.h $(top_srcdir)/mm/gup_test.h
++
+ include local_config.mk
+
+ uname_M := $(shell uname -m 2>/dev/null || echo not)
+@@ -48,13 +50,13 @@ TEST_GEN_FILES += split_huge_page_test
+ TEST_GEN_FILES += ksm_tests
+
+ ifeq ($(MACHINE),x86_64)
+-CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_32bit_program.c -m32)
+-CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_64bit_program.c)
+-CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_program.c -no-pie)
++CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_32bit_program.c -m32)
++CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_64bit_program.c)
++CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_program.c -no-pie)
+
+-TARGETS := protection_keys
+-BINARIES_32 := $(TARGETS:%=%_32)
+-BINARIES_64 := $(TARGETS:%=%_64)
++VMTARGETS := protection_keys
++BINARIES_32 := $(VMTARGETS:%=%_32)
++BINARIES_64 := $(VMTARGETS:%=%_64)
+
+ ifeq ($(CAN_BUILD_WITH_NOPIE),1)
+ CFLAGS += -no-pie
+@@ -107,7 +109,7 @@ $(BINARIES_32): CFLAGS += -m32 -mxsave
+ $(BINARIES_32): LDLIBS += -lrt -ldl -lm
+ $(BINARIES_32): $(OUTPUT)/%_32: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+-$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-32,$(t))))
++$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-32,$(t))))
+ endif
+
+ ifeq ($(CAN_BUILD_X86_64),1)
+@@ -115,7 +117,7 @@ $(BINARIES_64): CFLAGS += -m64 -mxsave
+ $(BINARIES_64): LDLIBS += -lrt -ldl
+ $(BINARIES_64): $(OUTPUT)/%_64: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+-$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-64,$(t))))
++$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-64,$(t))))
+ endif
+
+ # x86_64 users should be encouraged to install 32-bit libraries
+@@ -139,10 +141,6 @@ endif
+
+ $(OUTPUT)/mlock-random-test $(OUTPUT)/memfd_secret: LDLIBS += -lcap
+
+-$(OUTPUT)/gup_test: ../../../../mm/gup_test.h
+-
+-$(OUTPUT)/hmm-tests: local_config.h
+-
+ # HMM_EXTRA_LIBS may get set in local_config.mk, or it may be left empty.
+ $(OUTPUT)/hmm-tests: LDLIBS += $(HMM_EXTRA_LIBS)
+
diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
index fe8fcfb334e06..a5cb4b09a46c4 100644
--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
@@ -173532,11 +268774,337 @@ index 4a9a3afe9fd4d..bf2d2a684edfd 100644
function get_machine_hugepage_size() {
hpz=$(grep -i hugepagesize /proc/meminfo)
+diff --git a/tools/testing/selftests/vm/map_fixed_noreplace.c b/tools/testing/selftests/vm/map_fixed_noreplace.c
+index d91bde5112686..eed44322d1a63 100644
+--- a/tools/testing/selftests/vm/map_fixed_noreplace.c
++++ b/tools/testing/selftests/vm/map_fixed_noreplace.c
+@@ -17,9 +17,6 @@
+ #define MAP_FIXED_NOREPLACE 0x100000
+ #endif
+
+-#define BASE_ADDRESS (256ul * 1024 * 1024)
+-
+-
+ static void dump_maps(void)
+ {
+ char cmd[32];
+@@ -28,18 +25,46 @@ static void dump_maps(void)
+ system(cmd);
+ }
+
++static unsigned long find_base_addr(unsigned long size)
++{
++ void *addr;
++ unsigned long flags;
++
++ flags = MAP_PRIVATE | MAP_ANONYMOUS;
++ addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
++ if (addr == MAP_FAILED) {
++ printf("Error: couldn't map the space we need for the test\n");
++ return 0;
++ }
++
++ if (munmap(addr, size) != 0) {
++ printf("Error: couldn't map the space we need for the test\n");
++ return 0;
++ }
++ return (unsigned long)addr;
++}
++
+ int main(void)
+ {
++ unsigned long base_addr;
+ unsigned long flags, addr, size, page_size;
+ char *p;
+
+ page_size = sysconf(_SC_PAGE_SIZE);
+
++ //let's find a base addr that is free before we start the tests
++ size = 5 * page_size;
++ base_addr = find_base_addr(size);
++ if (!base_addr) {
++ printf("Error: couldn't map the space we need for the test\n");
++ return 1;
++ }
++
+ flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
+
+ // Check we can map all the areas we need below
+ errno = 0;
+- addr = BASE_ADDRESS;
++ addr = base_addr;
+ size = 5 * page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+
+@@ -60,7 +85,7 @@ int main(void)
+ printf("unmap() successful\n");
+
+ errno = 0;
+- addr = BASE_ADDRESS + page_size;
++ addr = base_addr + page_size;
+ size = 3 * page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -80,7 +105,7 @@ int main(void)
+ * +4 | free | new
+ */
+ errno = 0;
+- addr = BASE_ADDRESS;
++ addr = base_addr;
+ size = 5 * page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -101,7 +126,7 @@ int main(void)
+ * +4 | free |
+ */
+ errno = 0;
+- addr = BASE_ADDRESS + (2 * page_size);
++ addr = base_addr + (2 * page_size);
+ size = page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -121,7 +146,7 @@ int main(void)
+ * +4 | free | new
+ */
+ errno = 0;
+- addr = BASE_ADDRESS + (3 * page_size);
++ addr = base_addr + (3 * page_size);
+ size = 2 * page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -141,7 +166,7 @@ int main(void)
+ * +4 | free |
+ */
+ errno = 0;
+- addr = BASE_ADDRESS;
++ addr = base_addr;
+ size = 2 * page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -161,7 +186,7 @@ int main(void)
+ * +4 | free |
+ */
+ errno = 0;
+- addr = BASE_ADDRESS;
++ addr = base_addr;
+ size = page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -181,7 +206,7 @@ int main(void)
+ * +4 | free | new
+ */
+ errno = 0;
+- addr = BASE_ADDRESS + (4 * page_size);
++ addr = base_addr + (4 * page_size);
+ size = page_size;
+ p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
+ printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
+@@ -192,7 +217,7 @@ int main(void)
+ return 1;
+ }
+
+- addr = BASE_ADDRESS;
++ addr = base_addr;
+ size = 5 * page_size;
+ if (munmap((void *)addr, size) != 0) {
+ dump_maps();
+diff --git a/tools/testing/selftests/vm/mremap_test.c b/tools/testing/selftests/vm/mremap_test.c
+index 0624d1bd71b53..8f4dbbd60c09c 100644
+--- a/tools/testing/selftests/vm/mremap_test.c
++++ b/tools/testing/selftests/vm/mremap_test.c
+@@ -6,9 +6,11 @@
+
+ #include <errno.h>
+ #include <stdlib.h>
++#include <stdio.h>
+ #include <string.h>
+ #include <sys/mman.h>
+ #include <time.h>
++#include <stdbool.h>
+
+ #include "../kselftest.h"
+
+@@ -64,6 +66,112 @@ enum {
+ .expect_failure = should_fail \
+ }
+
++/*
++ * Returns false if the requested remap region overlaps with an
++ * existing mapping (e.g text, stack) else returns true.
++ */
++static bool is_remap_region_valid(void *addr, unsigned long long size)
++{
++ void *remap_addr = NULL;
++ bool ret = true;
++
++ /* Use MAP_FIXED_NOREPLACE flag to ensure region is not mapped */
++ remap_addr = mmap(addr, size, PROT_READ | PROT_WRITE,
++ MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED,
++ -1, 0);
++
++ if (remap_addr == MAP_FAILED) {
++ if (errno == EEXIST)
++ ret = false;
++ } else {
++ munmap(remap_addr, size);
++ }
++
++ return ret;
++}
++
++/* Returns mmap_min_addr sysctl tunable from procfs */
++static unsigned long long get_mmap_min_addr(void)
++{
++ FILE *fp;
++ int n_matched;
++ static unsigned long long addr;
++
++ if (addr)
++ return addr;
++
++ fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
++ if (fp == NULL) {
++ ksft_print_msg("Failed to open /proc/sys/vm/mmap_min_addr: %s\n",
++ strerror(errno));
++ exit(KSFT_SKIP);
++ }
++
++ n_matched = fscanf(fp, "%llu", &addr);
++ if (n_matched != 1) {
++ ksft_print_msg("Failed to read /proc/sys/vm/mmap_min_addr: %s\n",
++ strerror(errno));
++ fclose(fp);
++ exit(KSFT_SKIP);
++ }
++
++ fclose(fp);
++ return addr;
++}
++
++/*
++ * Returns false if the requested remap region overlaps with an
++ * existing mapping (e.g text, stack) else returns true.
++ */
++static bool is_remap_region_valid(void *addr, unsigned long long size)
++{
++ void *remap_addr = NULL;
++ bool ret = true;
++
++ /* Use MAP_FIXED_NOREPLACE flag to ensure region is not mapped */
++ remap_addr = mmap(addr, size, PROT_READ | PROT_WRITE,
++ MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED,
++ -1, 0);
++
++ if (remap_addr == MAP_FAILED) {
++ if (errno == EEXIST)
++ ret = false;
++ } else {
++ munmap(remap_addr, size);
++ }
++
++ return ret;
++}
++
++/* Returns mmap_min_addr sysctl tunable from procfs */
++static unsigned long long get_mmap_min_addr(void)
++{
++ FILE *fp;
++ int n_matched;
++ static unsigned long long addr;
++
++ if (addr)
++ return addr;
++
++ fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
++ if (fp == NULL) {
++ ksft_print_msg("Failed to open /proc/sys/vm/mmap_min_addr: %s\n",
++ strerror(errno));
++ exit(KSFT_SKIP);
++ }
++
++ n_matched = fscanf(fp, "%llu", &addr);
++ if (n_matched != 1) {
++ ksft_print_msg("Failed to read /proc/sys/vm/mmap_min_addr: %s\n",
++ strerror(errno));
++ fclose(fp);
++ exit(KSFT_SKIP);
++ }
++
++ fclose(fp);
++ return addr;
++}
++
+ /*
+ * Returns the start address of the mapping on success, else returns
+ * NULL on failure.
+@@ -72,11 +180,18 @@ static void *get_source_mapping(struct config c)
+ {
+ unsigned long long addr = 0ULL;
+ void *src_addr = NULL;
++ unsigned long long mmap_min_addr;
++
++ mmap_min_addr = get_mmap_min_addr();
++
+ retry:
+ addr += c.src_alignment;
++ if (addr < mmap_min_addr)
++ goto retry;
++
+ src_addr = mmap((void *) addr, c.region_size, PROT_READ | PROT_WRITE,
+- MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED,
+- -1, 0);
++ MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED,
++ -1, 0);
+ if (src_addr == MAP_FAILED) {
+ if (errno == EPERM || errno == EEXIST)
+ goto retry;
+@@ -91,8 +206,10 @@ retry:
+ * alignment in the tests.
+ */
+ if (((unsigned long long) src_addr & (c.src_alignment - 1)) ||
+- !((unsigned long long) src_addr & c.src_alignment))
++ !((unsigned long long) src_addr & c.src_alignment)) {
++ munmap(src_addr, c.region_size);
+ goto retry;
++ }
+
+ if (!src_addr)
+ goto error;
+@@ -141,9 +258,20 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
+ if (!((unsigned long long) addr & c.dest_alignment))
+ addr = (void *) ((unsigned long long) addr | c.dest_alignment);
+
++ /* Don't destroy existing mappings unless expected to overlap */
++ while (!is_remap_region_valid(addr, c.region_size) && !c.overlapping) {
++ /* Check for unsigned overflow */
++ if (addr + c.dest_alignment < addr) {
++ ksft_print_msg("Couldn't find a valid region to remap to\n");
++ ret = -1;
++ goto out;
++ }
++ addr += c.dest_alignment;
++ }
++
+ clock_gettime(CLOCK_MONOTONIC, &t_start);
+ dest_addr = mremap(src_addr, c.region_size, c.region_size,
+- MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr);
++ MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr);
+ clock_gettime(CLOCK_MONOTONIC, &t_end);
+
+ if (dest_addr == MAP_FAILED) {
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
-index 60aa1a4fc69b6..81690f1737c80 100644
+index 60aa1a4fc69b6..138b011c667e2 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
-@@ -86,7 +86,7 @@ static bool test_uffdio_minor = false;
+@@ -46,6 +46,7 @@
+ #include <signal.h>
+ #include <poll.h>
+ #include <string.h>
++#include <linux/mman.h>
+ #include <sys/mman.h>
+ #include <sys/syscall.h>
+ #include <sys/ioctl.h>
+@@ -86,7 +87,7 @@ static bool test_uffdio_minor = false;
static bool map_shared;
static int shm_fd;
@@ -173545,7 +269113,7 @@ index 60aa1a4fc69b6..81690f1737c80 100644
static char *huge_fd_off0;
static unsigned long long *count_verify;
static int uffd = -1;
-@@ -222,6 +222,9 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
+@@ -222,6 +223,9 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
static void hugetlb_release_pages(char *rel_area)
{
@@ -173555,7 +269123,7 @@ index 60aa1a4fc69b6..81690f1737c80 100644
if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
rel_area == huge_fd_off0 ? 0 : nr_pages * page_size,
nr_pages * page_size))
-@@ -234,16 +237,17 @@ static void hugetlb_allocate_area(void **alloc_area)
+@@ -234,16 +238,17 @@ static void hugetlb_allocate_area(void **alloc_area)
char **alloc_area_alias;
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
@@ -173671,6 +269239,36 @@ index 74db83a0aedd8..a9b5a520a1d22 100644
CONFIG_PRINTK_TIME=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_LEGACY_VSYSCALL_NONE=y
+diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
+index b4142cd1c5c23..02a77056bca3f 100644
+--- a/tools/testing/selftests/x86/Makefile
++++ b/tools/testing/selftests/x86/Makefile
+@@ -6,9 +6,9 @@ include ../lib.mk
+ .PHONY: all all_32 all_64 warn_32bit_failure clean
+
+ UNAME_M := $(shell uname -m)
+-CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
+-CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
+-CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie)
++CAN_BUILD_I386 := $(shell ./check_cc.sh "$(CC)" trivial_32bit_program.c -m32)
++CAN_BUILD_X86_64 := $(shell ./check_cc.sh "$(CC)" trivial_64bit_program.c)
++CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh "$(CC)" trivial_program.c -no-pie)
+
+ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
+ check_initial_reg_state sigreturn iopl ioperm \
+diff --git a/tools/testing/selftests/x86/check_cc.sh b/tools/testing/selftests/x86/check_cc.sh
+index 3e2089c8cf549..8c669c0d662ee 100755
+--- a/tools/testing/selftests/x86/check_cc.sh
++++ b/tools/testing/selftests/x86/check_cc.sh
+@@ -7,7 +7,7 @@ CC="$1"
+ TESTPROG="$2"
+ shift 2
+
+-if "$CC" -o /dev/null "$TESTPROG" -O0 "$@" 2>/dev/null; then
++if [ -n "$CC" ] && $CC -o /dev/null "$TESTPROG" -O0 "$@" 2>/dev/null; then
+ echo 1
+ else
+ echo 0
diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c
index bab2f6e06b63d..7e3e09c1abac6 100644
--- a/tools/testing/selftests/x86/iopl.c
@@ -174190,6 +269788,32 @@ index 3a2e6bb781a8c..59a7f2346eab4 100644
mutex_unlock(&print_mtx);
}
modified--;
+diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
+index 0d7bbe49359d8..1b25cc7c64bbd 100644
+--- a/tools/virtio/Makefile
++++ b/tools/virtio/Makefile
+@@ -5,7 +5,8 @@ virtio_test: virtio_ring.o virtio_test.o
+ vringh_test: vringh_test.o vringh.o virtio_ring.o
+
+ CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
+-LDFLAGS += -lpthread
++CFLAGS += -pthread
++LDFLAGS += -pthread
+ vpath %.c ../../drivers/virtio ../../drivers/vhost
+ mod:
+ ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
+diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
+index cb3f29c09aff3..23f142af544ad 100644
+--- a/tools/virtio/virtio_test.c
++++ b/tools/virtio/virtio_test.c
+@@ -130,6 +130,7 @@ static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
+ memset(dev, 0, sizeof *dev);
+ dev->vdev.features = features;
+ INIT_LIST_HEAD(&dev->vdev.vqs);
++ spin_lock_init(&dev->vdev.vqs_list_lock);
+ dev->buf_size = 1024;
+ dev->buf = malloc(dev->buf_size);
+ assert(dev->buf);
diff --git a/usr/include/Makefile b/usr/include/Makefile
index 1c2ae1368079d..adc6cb2587369 100644
--- a/usr/include/Makefile
@@ -174236,10 +269860,54 @@ index e996989cd580e..5b874e7ba36fd 100644
kian->irq_acked(kian);
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
-index 7851f3a1b5f7c..f8b42e19bc775 100644
+index 7851f3a1b5f7c..fefdf3a6dae35 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
-@@ -1523,11 +1523,10 @@ static struct kvm_memslots *kvm_dup_memslots(struct kvm_memslots *old,
+@@ -117,6 +117,8 @@ EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
+
+ static const struct file_operations stat_fops_per_vm;
+
++static struct file_operations kvm_chardev_ops;
++
+ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
+ unsigned long arg);
+ #ifdef CONFIG_KVM_COMPAT
+@@ -429,8 +431,8 @@ static void kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
+
+ void kvm_vcpu_destroy(struct kvm_vcpu *vcpu)
+ {
+- kvm_dirty_ring_free(&vcpu->dirty_ring);
+ kvm_arch_vcpu_destroy(vcpu);
++ kvm_dirty_ring_free(&vcpu->dirty_ring);
+
+ /*
+ * No need for rcu_read_lock as VCPU_RUN is the only place that changes
+@@ -1099,6 +1101,16 @@ static struct kvm *kvm_create_vm(unsigned long type)
+ preempt_notifier_inc();
+ kvm_init_pm_notifier(kvm);
+
++ /*
++ * When the fd passed to this ioctl() is opened it pins the module,
++ * but try_module_get() also prevents getting a reference if the module
++ * is in MODULE_STATE_GOING (e.g. if someone ran "rmmod --wait").
++ */
++ if (!try_module_get(kvm_chardev_ops.owner)) {
++ r = -ENODEV;
++ goto out_err;
++ }
++
+ return kvm;
+
+ out_err:
+@@ -1188,6 +1200,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
+ preempt_notifier_dec();
+ hardware_disable_all();
+ mmdrop(mm);
++ module_put(kvm_chardev_ops.owner);
+ }
+
+ void kvm_get_kvm(struct kvm *kvm)
+@@ -1523,11 +1536,10 @@ static struct kvm_memslots *kvm_dup_memslots(struct kvm_memslots *old,
static int kvm_set_memslot(struct kvm *kvm,
const struct kvm_userspace_memory_region *mem,
@@ -174252,7 +269920,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
struct kvm_memslots *slots;
int r;
-@@ -1558,7 +1557,7 @@ static int kvm_set_memslot(struct kvm *kvm,
+@@ -1558,7 +1570,7 @@ static int kvm_set_memslot(struct kvm *kvm,
* Note, the INVALID flag needs to be in the appropriate entry
* in the freshly allocated memslots, not in @old or @new.
*/
@@ -174261,7 +269929,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
slot->flags |= KVM_MEMSLOT_INVALID;
/*
-@@ -1589,6 +1588,26 @@ static int kvm_set_memslot(struct kvm *kvm,
+@@ -1589,6 +1601,26 @@ static int kvm_set_memslot(struct kvm *kvm,
kvm_copy_memslots(slots, __kvm_memslots(kvm, as_id));
}
@@ -174288,7 +269956,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
r = kvm_arch_prepare_memory_region(kvm, new, mem, change);
if (r)
goto out_slots;
-@@ -1596,14 +1615,18 @@ static int kvm_set_memslot(struct kvm *kvm,
+@@ -1596,14 +1628,18 @@ static int kvm_set_memslot(struct kvm *kvm,
update_memslots(slots, new, change);
slots = install_new_memslots(kvm, as_id, slots);
@@ -174309,7 +269977,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
slot->flags &= ~KVM_MEMSLOT_INVALID;
slots = install_new_memslots(kvm, as_id, slots);
} else {
-@@ -1618,7 +1641,6 @@ static int kvm_delete_memslot(struct kvm *kvm,
+@@ -1618,7 +1654,6 @@ static int kvm_delete_memslot(struct kvm *kvm,
struct kvm_memory_slot *old, int as_id)
{
struct kvm_memory_slot new;
@@ -174317,7 +269985,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
if (!old->npages)
return -EINVAL;
-@@ -1631,12 +1653,7 @@ static int kvm_delete_memslot(struct kvm *kvm,
+@@ -1631,12 +1666,7 @@ static int kvm_delete_memslot(struct kvm *kvm,
*/
new.as_id = as_id;
@@ -174331,7 +269999,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
}
/*
-@@ -1664,7 +1681,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
+@@ -1664,7 +1694,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
id = (u16)mem->slot;
/* General sanity checks */
@@ -174341,7 +270009,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
return -EINVAL;
if (mem->guest_phys_addr & (PAGE_SIZE - 1))
return -EINVAL;
-@@ -1710,7 +1728,6 @@ int __kvm_set_memory_region(struct kvm *kvm,
+@@ -1710,7 +1741,6 @@ int __kvm_set_memory_region(struct kvm *kvm,
if (!old.npages) {
change = KVM_MR_CREATE;
new.dirty_bitmap = NULL;
@@ -174349,7 +270017,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
} else { /* Modify an existing slot. */
if ((new.userspace_addr != old.userspace_addr) ||
(new.npages != old.npages) ||
-@@ -1724,9 +1741,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
+@@ -1724,9 +1754,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
else /* Nothing to change. */
return 0;
@@ -174360,7 +270028,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
}
if ((change == KVM_MR_CREATE) || (change == KVM_MR_MOVE)) {
-@@ -1752,7 +1768,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
+@@ -1752,7 +1781,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
bitmap_set(new.dirty_bitmap, 0, new.npages);
}
@@ -174369,7 +270037,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
if (r)
goto out_bitmap;
-@@ -2088,7 +2104,6 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
+@@ -2088,7 +2117,6 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
return NULL;
}
@@ -174377,7 +270045,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
{
-@@ -2985,7 +3000,8 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+@@ -2985,7 +3013,8 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
int r;
gpa_t gpa = ghc->gpa + offset;
@@ -174387,7 +270055,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
if (slots->generation != ghc->generation) {
if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len))
-@@ -3022,7 +3038,8 @@ int kvm_read_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+@@ -3022,7 +3051,8 @@ int kvm_read_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
int r;
gpa_t gpa = ghc->gpa + offset;
@@ -174397,7 +270065,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
if (slots->generation != ghc->generation) {
if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len))
-@@ -3205,6 +3222,7 @@ update_halt_poll_stats(struct kvm_vcpu *vcpu, u64 poll_ns, bool waited)
+@@ -3205,6 +3235,7 @@ update_halt_poll_stats(struct kvm_vcpu *vcpu, u64 poll_ns, bool waited)
*/
void kvm_vcpu_block(struct kvm_vcpu *vcpu)
{
@@ -174405,7 +270073,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
ktime_t start, cur, poll_end;
bool waited = false;
u64 block_ns;
-@@ -3212,7 +3230,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
+@@ -3212,7 +3243,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
kvm_arch_vcpu_blocking(vcpu);
start = cur = poll_end = ktime_get();
@@ -174414,7 +270082,7 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
++vcpu->stat.generic.halt_attempted_poll;
-@@ -3267,7 +3285,7 @@ out:
+@@ -3267,7 +3298,7 @@ out:
update_halt_poll_stats(
vcpu, ktime_to_ns(ktime_sub(poll_end, start)), waited);
@@ -174423,3 +270091,14 @@ index 7851f3a1b5f7c..f8b42e19bc775 100644
if (!vcpu_valid_wakeup(vcpu)) {
shrink_halt_poll_ns(vcpu);
} else if (vcpu->kvm->max_halt_poll_ns) {
+@@ -5399,9 +5430,7 @@ static int kvm_suspend(void)
+ static void kvm_resume(void)
+ {
+ if (kvm_usage_count) {
+-#ifdef CONFIG_LOCKDEP
+- WARN_ON(lockdep_is_held(&kvm_count_lock));
+-#endif
++ lockdep_assert_not_held(&kvm_count_lock);
+ hardware_enable_nolock(NULL);
+ }
+ }
diff --git a/system/easy-kernel/0130-lrng.patch b/system/easy-kernel/0130-lrng.patch
deleted file mode 100644
index 89d06d84c..000000000
--- a/system/easy-kernel/0130-lrng.patch
+++ /dev/null
@@ -1,28362 +0,0 @@
-diff -urN linux-5.15/MAINTAINERS linux-5.15-lrng/MAINTAINERS
---- linux-5.15/MAINTAINERS 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/MAINTAINERS 2021-11-29 12:36:52.113279174 +1100
-@@ -10830,6 +10830,13 @@
- F: Documentation/memory-barriers.txt
- F: tools/memory-model/
-
-+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
-+M: Stephan Mueller <smueller@chronox.de>
-+S: Maintained
-+W: https://www.chronox.de/lrng.html
-+F: drivers/char/lrng/*
-+F: include/linux/lrng.h
-+
- LIS3LV02D ACCELEROMETER DRIVER
- M: Eric Piel <eric.piel@tremplin-utc.net>
- S: Maintained
-diff -urN linux-5.15/MAINTAINERS.orig linux-5.15-lrng/MAINTAINERS.orig
---- linux-5.15/MAINTAINERS.orig 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/MAINTAINERS.orig 2021-11-29 12:32:21.653280206 +1100
-@@ -0,0 +1,20816 @@
-+List of maintainers and how to submit kernel changes
-+====================================================
-+
-+Please try to follow the guidelines below. This will make things
-+easier on the maintainers. Not all of these guidelines matter for every
-+trivial patch so apply some common sense.
-+
-+Tips for patch submitters
-+-------------------------
-+
-+1. Always *test* your changes, however small, on at least 4 or
-+ 5 people, preferably many more.
-+
-+2. Try to release a few ALPHA test versions to the net. Announce
-+ them onto the kernel channel and await results. This is especially
-+ important for device drivers, because often that's the only way
-+ you will find things like the fact version 3 firmware needs
-+ a magic fix you didn't know about, or some clown changed the
-+ chips on a board and not its name. (Don't laugh! Look at the
-+ SMC etherpower for that.)
-+
-+3. Make sure your changes compile correctly in multiple
-+ configurations. In particular check that changes work both as a
-+ module and built into the kernel.
-+
-+4. When you are happy with a change make it generally available for
-+ testing and await feedback.
-+
-+5. Make a patch available to the relevant maintainer in the list. Use
-+ ``diff -u`` to make the patch easy to merge. Be prepared to get your
-+ changes sent back with seemingly silly requests about formatting
-+ and variable names. These aren't as silly as they seem. One
-+ job the maintainers (and especially Linus) do is to keep things
-+ looking the same. Sometimes this means that the clever hack in
-+ your driver to get around a problem actually needs to become a
-+ generalized kernel feature ready for next time.
-+
-+ PLEASE check your patch with the automated style checker
-+ (scripts/checkpatch.pl) to catch trivial style violations.
-+ See Documentation/process/coding-style.rst for guidance here.
-+
-+ PLEASE CC: the maintainers and mailing lists that are generated
-+ by ``scripts/get_maintainer.pl.`` The results returned by the
-+ script will be best if you have git installed and are making
-+ your changes in a branch derived from Linus' latest git tree.
-+ See Documentation/process/submitting-patches.rst for details.
-+
-+ PLEASE try to include any credit lines you want added with the
-+ patch. It avoids people being missed off by mistake and makes
-+ it easier to know who wants adding and who doesn't.
-+
-+ PLEASE document known bugs. If it doesn't work for everything
-+ or does something very odd once a month document it.
-+
-+ PLEASE remember that submissions must be made under the terms
-+ of the Linux Foundation certificate of contribution and should
-+ include a Signed-off-by: line. The current version of this
-+ "Developer's Certificate of Origin" (DCO) is listed in the file
-+ Documentation/process/submitting-patches.rst.
-+
-+6. Make sure you have the right to send any changes you make. If you
-+ do changes at work you may find your employer owns the patch
-+ not you.
-+
-+7. When sending security related changes or reports to a maintainer
-+ please Cc: security@kernel.org, especially if the maintainer
-+ does not respond. Please keep in mind that the security team is
-+ a small set of people who can be efficient only when working on
-+ verified bugs. Please only Cc: this list when you have identified
-+ that the bug would present a short-term risk to other users if it
-+ were publicly disclosed. For example, reports of address leaks do
-+ not represent an immediate threat and are better handled publicly,
-+ and ideally, should come with a patch proposal. Please do not send
-+ automated reports to this list either. Such bugs will be handled
-+ better and faster in the usual public places. See
-+ Documentation/admin-guide/security-bugs.rst for details.
-+
-+8. Happy hacking.
-+
-+Descriptions of section entries and preferred order
-+---------------------------------------------------
-+
-+ M: *Mail* patches to: FullName <address@domain>
-+ R: Designated *Reviewer*: FullName <address@domain>
-+ These reviewers should be CCed on patches.
-+ L: *Mailing list* that is relevant to this area
-+ S: *Status*, one of the following:
-+ Supported: Someone is actually paid to look after this.
-+ Maintained: Someone actually looks after it.
-+ Odd Fixes: It has a maintainer but they don't have time to do
-+ much other than throw the odd patch in. See below..
-+ Orphan: No current maintainer [but maybe you could take the
-+ role as you write your new code].
-+ Obsolete: Old code. Something tagged obsolete generally means
-+ it has been replaced by a better system and you
-+ should be using that.
-+ W: *Web-page* with status/info
-+ Q: *Patchwork* web based patch tracking system site
-+ B: URI for where to file *bugs*. A web-page with detailed bug
-+ filing info, a direct bug tracker link, or a mailto: URI.
-+ C: URI for *chat* protocol, server and channel where developers
-+ usually hang out, for example irc://server/channel.
-+ P: Subsystem Profile document for more details submitting
-+ patches to the given subsystem. This is either an in-tree file,
-+ or a URI. See Documentation/maintainer/maintainer-entry-profile.rst
-+ for details.
-+ T: *SCM* tree type and location.
-+ Type is one of: git, hg, quilt, stgit, topgit
-+ F: *Files* and directories wildcard patterns.
-+ A trailing slash includes all files and subdirectory files.
-+ F: drivers/net/ all files in and below drivers/net
-+ F: drivers/net/* all files in drivers/net, but not below
-+ F: */net/* all files in "any top level directory"/net
-+ One pattern per line. Multiple F: lines acceptable.
-+ X: *Excluded* files and directories that are NOT maintained, same
-+ rules as F:. Files exclusions are tested before file matches.
-+ Can be useful for excluding a specific subdirectory, for instance:
-+ F: net/
-+ X: net/ipv6/
-+ matches all files in and below net excluding net/ipv6/
-+ N: Files and directories *Regex* patterns.
-+ N: [^a-z]tegra all files whose path contains tegra
-+ (not including files like integrator)
-+ One pattern per line. Multiple N: lines acceptable.
-+ scripts/get_maintainer.pl has different behavior for files that
-+ match F: pattern and matches of N: patterns. By default,
-+ get_maintainer will not look at git log history when an F: pattern
-+ match occurs. When an N: match occurs, git log history is used
-+ to also notify the people that have git commit signatures.
-+ K: *Content regex* (perl extended) pattern match in a patch or file.
-+ For instance:
-+ K: of_get_profile
-+ matches patches or files that contain "of_get_profile"
-+ K: \b(printk|pr_(info|err))\b
-+ matches patches or files that contain one or more of the words
-+ printk, pr_info or pr_err
-+ One regex pattern per line. Multiple K: lines acceptable.
-+
-+Maintainers List
-+----------------
-+
-+.. note:: When reading this list, please look for the most precise areas
-+ first. When adding to this list, please keep the entries in
-+ alphabetical order.
-+
-+3C59X NETWORK DRIVER
-+M: Steffen Klassert <klassert@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Odd Fixes
-+F: Documentation/networking/device_drivers/ethernet/3com/vortex.rst
-+F: drivers/net/ethernet/3com/3c59x.c
-+
-+3CR990 NETWORK DRIVER
-+M: David Dillow <dave@thedillows.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/3com/typhoon*
-+
-+3WARE SAS/SATA-RAID SCSI DRIVERS (3W-XXXX, 3W-9XXX, 3W-SAS)
-+M: Adam Radford <aradford@gmail.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.lsi.com
-+F: drivers/scsi/3w-*
-+
-+53C700 AND 53C700-66 SCSI DRIVER
-+M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/53c700*
-+
-+6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
-+M: Alexander Aring <alex.aring@gmail.com>
-+M: Jukka Rissanen <jukka.rissanen@linux.intel.com>
-+L: linux-bluetooth@vger.kernel.org
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/6lowpan.rst
-+F: include/net/6lowpan.h
-+F: net/6lowpan/
-+
-+6PACK NETWORK DRIVER FOR AX.25
-+M: Andreas Koensgen <ajk@comnets.uni-bremen.de>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+F: drivers/net/hamradio/6pack.c
-+
-+802.11 (including CFG80211/NL80211)
-+M: Johannes Berg <johannes@sipsolutions.net>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
-+F: Documentation/driver-api/80211/cfg80211.rst
-+F: Documentation/networking/regulatory.rst
-+F: include/linux/ieee80211.h
-+F: include/net/cfg80211.h
-+F: include/net/ieee80211_radiotap.h
-+F: include/net/iw_handler.h
-+F: include/net/wext.h
-+F: include/uapi/linux/nl80211.h
-+F: net/wireless/
-+
-+8169 10/100/1000 GIGABIT ETHERNET DRIVER
-+M: Heiner Kallweit <hkallweit1@gmail.com>
-+M: nic_swsd@realtek.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/realtek/r8169*
-+
-+8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-serial@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
-+F: drivers/tty/serial/8250*
-+F: include/linux/serial_8250.h
-+
-+8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
-+L: netdev@vger.kernel.org
-+S: Orphan / Obsolete
-+F: drivers/net/ethernet/8390/
-+
-+9P FILE SYSTEM
-+M: Eric Van Hensbergen <ericvh@gmail.com>
-+M: Latchesar Ionkov <lucho@ionkov.net>
-+M: Dominique Martinet <asmadeus@codewreck.org>
-+L: v9fs-developer@lists.sourceforge.net
-+S: Maintained
-+W: http://swik.net/v9fs
-+Q: http://patchwork.kernel.org/project/v9fs-devel/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
-+T: git git://github.com/martinetd/linux.git
-+F: Documentation/filesystems/9p.rst
-+F: fs/9p/
-+F: include/net/9p/
-+F: include/trace/events/9p.h
-+F: include/uapi/linux/virtio_9p.h
-+F: net/9p/
-+
-+A8293 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/a8293*
-+
-+AACRAID SCSI RAID DRIVER
-+M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.adaptec.com/
-+F: Documentation/scsi/aacraid.rst
-+F: drivers/scsi/aacraid/
-+
-+ABI/API
-+L: linux-api@vger.kernel.org
-+F: include/linux/syscalls.h
-+F: kernel/sys_ni.c
-+X: include/uapi/
-+X: arch/*/include/uapi/
-+
-+ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/abituguru.c
-+
-+ABIT UGURU 3 HARDWARE MONITOR DRIVER
-+M: Alistair John Strachan <alistair@devzero.co.uk>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/abituguru3.c
-+
-+ACCES 104-DIO-48E GPIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-104-dio-48e.c
-+
-+ACCES 104-IDI-48 GPIO DRIVER
-+M: "William Breathitt Gray" <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-104-idi-48.c
-+
-+ACCES 104-IDIO-16 GPIO DRIVER
-+M: "William Breathitt Gray" <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-104-idio-16.c
-+
-+ACCES 104-QUAD-8 DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+M: Syed Nayyar Waris <syednwaris@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/counter/104-quad-8.c
-+
-+ACCES PCI-IDIO-16 GPIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-pci-idio-16.c
-+
-+ACCES PCIe-IDIO-24 GPIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-pcie-idio-24.c
-+
-+ACENIC DRIVER
-+M: Jes Sorensen <jes@trained-monkey.org>
-+L: linux-acenic@sunsite.dk
-+S: Maintained
-+F: drivers/net/ethernet/alteon/acenic*
-+
-+ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
-+M: Peter Kaestle <peter@piie.net>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://piie.net/?section=acerhdf
-+F: drivers/platform/x86/acerhdf.c
-+
-+ACER WMI LAPTOP EXTRAS
-+M: "Lee, Chun-Yi" <jlee@suse.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/acer-wmi.c
-+
-+ACPI
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Len Brown <lenb@kernel.org>
-+L: linux-acpi@vger.kernel.org
-+S: Supported
-+W: https://01.org/linux-acpi
-+Q: https://patchwork.kernel.org/project/linux-acpi/list/
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-+F: Documentation/ABI/testing/configfs-acpi
-+F: Documentation/ABI/testing/sysfs-bus-acpi
-+F: Documentation/firmware-guide/acpi/
-+F: drivers/acpi/
-+F: drivers/pci/*/*acpi*
-+F: drivers/pci/*acpi*
-+F: drivers/pnp/pnpacpi/
-+F: include/acpi/
-+F: include/linux/acpi.h
-+F: include/linux/fwnode.h
-+F: tools/power/acpi/
-+
-+ACPI APEI
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Len Brown <lenb@kernel.org>
-+R: James Morse <james.morse@arm.com>
-+R: Tony Luck <tony.luck@intel.com>
-+R: Borislav Petkov <bp@alien8.de>
-+L: linux-acpi@vger.kernel.org
-+F: drivers/acpi/apei/
-+
-+ACPI COMPONENT ARCHITECTURE (ACPICA)
-+M: Robert Moore <robert.moore@intel.com>
-+M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
-+L: linux-acpi@vger.kernel.org
-+L: devel@acpica.org
-+S: Supported
-+W: https://acpica.org/
-+W: https://github.com/acpica/acpica/
-+Q: https://patchwork.kernel.org/project/linux-acpi/list/
-+B: https://bugzilla.kernel.org
-+B: https://bugs.acpica.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-+F: drivers/acpi/acpica/
-+F: include/acpi/
-+F: tools/power/acpi/
-+
-+ACPI FAN DRIVER
-+M: Zhang Rui <rui.zhang@intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Supported
-+W: https://01.org/linux-acpi
-+B: https://bugzilla.kernel.org
-+F: drivers/acpi/fan.c
-+
-+ACPI FOR ARM64 (ACPI/arm64)
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+M: Hanjun Guo <guohanjun@huawei.com>
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-acpi@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/acpi/arm64
-+
-+ACPI I2C MULTI INSTANTIATE DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/i2c-multi-instantiate.c
-+
-+ACPI PMIC DRIVERS
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Len Brown <lenb@kernel.org>
-+R: Andy Shevchenko <andy@kernel.org>
-+R: Mika Westerberg <mika.westerberg@linux.intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-acpi/list/
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-+F: drivers/acpi/pmic/
-+
-+ACPI THERMAL DRIVER
-+M: Rafael J. Wysocki <rafael@kernel.org>
-+R: Zhang Rui <rui.zhang@intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Supported
-+W: https://01.org/linux-acpi
-+B: https://bugzilla.kernel.org
-+F: drivers/acpi/*thermal*
-+
-+ACPI VIDEO DRIVER
-+M: Zhang Rui <rui.zhang@intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Supported
-+W: https://01.org/linux-acpi
-+B: https://bugzilla.kernel.org
-+F: drivers/acpi/acpi_video.c
-+
-+ACPI VIOT DRIVER
-+M: Jean-Philippe Brucker <jean-philippe@linaro.org>
-+L: linux-acpi@vger.kernel.org
-+L: iommu@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/acpi/viot.c
-+F: include/linux/acpi_viot.h
-+
-+ACPI WMI DRIVER
-+L: platform-driver-x86@vger.kernel.org
-+S: Orphan
-+F: drivers/platform/x86/wmi.c
-+F: include/uapi/linux/wmi.h
-+
-+ACRN HYPERVISOR SERVICE MODULE
-+M: Fei Li <fei1.li@intel.com>
-+L: acrn-dev@lists.projectacrn.org (subscribers-only)
-+S: Supported
-+W: https://projectacrn.org
-+F: Documentation/virt/acrn/
-+F: drivers/virt/acrn/
-+F: include/uapi/linux/acrn.h
-+
-+AD1889 ALSA SOUND DRIVER
-+L: linux-parisc@vger.kernel.org
-+S: Maintained
-+W: https://parisc.wiki.kernel.org/index.php/AD1889
-+F: sound/pci/ad1889.*
-+
-+AD5110 ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
-+M: Mugilraj Dhavachelvan <dmugil2000@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: drivers/iio/potentiometer/ad5110.c
-+
-+AD525X ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/AD5254
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/misc/ad525x_dpot.c
-+
-+AD5398 CURRENT REGULATOR DRIVER (AD5398/AD5821)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/AD5398
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/regulator/ad5398.c
-+
-+AD714X CAPACITANCE TOUCH SENSOR DRIVER (AD7142/3/7/8/7A)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/AD7142
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/input/misc/ad714x.c
-+
-+AD7877 TOUCHSCREEN DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/AD7877
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/input/touchscreen/ad7877.c
-+
-+AD7879 TOUCHSCREEN DRIVER (AD7879/AD7889)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/AD7879
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/input/touchscreen/ad7879.c
-+
-+ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
-+M: Jiri Kosina <jikos@kernel.org>
-+S: Maintained
-+
-+ADF7242 IEEE 802.15.4 RADIO DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+L: linux-wpan@vger.kernel.org
-+S: Supported
-+W: https://wiki.analog.com/ADF7242
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/net/ieee802154/adf7242.txt
-+F: drivers/net/ieee802154/adf7242.c
-+
-+ADM1025 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/adm1025.rst
-+F: drivers/hwmon/adm1025.c
-+
-+ADM1029 HARDWARE MONITOR DRIVER
-+M: Corentin Labbe <clabbe.montjoie@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/adm1029.c
-+
-+ADM8211 WIRELESS DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+W: https://wireless.wiki.kernel.org/
-+F: drivers/net/wireless/admtek/adm8211.*
-+
-+ADP1653 FLASH CONTROLLER DRIVER
-+M: Sakari Ailus <sakari.ailus@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/adp1653.c
-+F: include/media/i2c/adp1653.h
-+
-+ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/ADP5520
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/gpio/gpio-adp5520.c
-+F: drivers/input/keyboard/adp5520-keys.c
-+F: drivers/leds/leds-adp5520.c
-+F: drivers/mfd/adp5520.c
-+F: drivers/video/backlight/adp5520_bl.c
-+
-+ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/ADP5588
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/gpio/gpio-adp5588.c
-+F: drivers/input/keyboard/adp5588-keys.c
-+
-+ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/ADP8860
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/video/backlight/adp8860_bl.c
-+
-+ADT746X FAN DRIVER
-+M: Colin Leroy <colin@colino.net>
-+S: Maintained
-+F: drivers/macintosh/therm_adt746x.c
-+
-+ADT7475 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/adt7475.rst
-+F: drivers/hwmon/adt7475.c
-+
-+ADVANSYS SCSI DRIVER
-+M: Matthew Wilcox <willy@infradead.org>
-+M: Hannes Reinecke <hare@suse.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: Documentation/scsi/advansys.rst
-+F: drivers/scsi/advansys.c
-+
-+ADVANTECH SWBTN DRIVER
-+M: Andrea Ho <Andrea.Ho@advantech.com.tw>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/adv_swbutton.c
-+
-+ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/ADXL345
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
-+F: drivers/input/misc/adxl34x.c
-+
-+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
-+F: drivers/iio/accel/adxl372.c
-+F: drivers/iio/accel/adxl372_i2c.c
-+F: drivers/iio/accel/adxl372_spi.c
-+
-+AF9013 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/af9013*
-+
-+AF9033 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/af9033*
-+
-+AFFS FILE SYSTEM
-+M: David Sterba <dsterba@suse.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Odd Fixes
-+F: Documentation/filesystems/affs.rst
-+F: fs/affs/
-+
-+AFS FILESYSTEM
-+M: David Howells <dhowells@redhat.com>
-+M: Marc Dionne <marc.dionne@auristor.com>
-+L: linux-afs@lists.infradead.org
-+S: Supported
-+W: https://www.infradead.org/~dhowells/kafs/
-+F: Documentation/filesystems/afs.rst
-+F: fs/afs/
-+F: include/trace/events/afs.h
-+
-+AGPGART DRIVER
-+M: David Airlie <airlied@linux.ie>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm
-+F: drivers/char/agp/
-+F: include/linux/agp*
-+F: include/uapi/linux/agp*
-+
-+AHA152X SCSI DRIVER
-+M: "Juergen E. Fischer" <fischer@norbit.de>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/aha152x*
-+F: drivers/scsi/pcmcia/aha152x*
-+
-+AIC7XXX / AIC79XX SCSI DRIVER
-+M: Hannes Reinecke <hare@suse.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/aic7xxx/
-+
-+AIMSLAB FM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-aimslab*
-+
-+AIO
-+M: Benjamin LaHaise <bcrl@kvack.org>
-+L: linux-aio@kvack.org
-+S: Supported
-+F: fs/aio.c
-+F: include/linux/*aio*.h
-+
-+AIRSPY MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/airspy/
-+
-+ALACRITECH GIGABIT ETHERNET DRIVER
-+M: Lino Sanfilippo <LinoSanfilippo@gmx.de>
-+S: Maintained
-+F: drivers/net/ethernet/alacritech/*
-+
-+ALCATEL SPEEDTOUCH USB DRIVER
-+M: Duncan Sands <duncan.sands@free.fr>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-usb.org/SpeedTouch/
-+F: drivers/usb/atm/speedtch.c
-+F: drivers/usb/atm/usbatm.c
-+
-+ALCHEMY AU1XX0 MMC DRIVER
-+M: Manuel Lauss <manuel.lauss@gmail.com>
-+S: Maintained
-+F: drivers/mmc/host/au1xmmc.c
-+
-+ALI1563 I2C DRIVER
-+M: Rudolf Marek <r.marek@assembler.cz>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/i2c/busses/i2c-ali1563.rst
-+F: drivers/i2c/busses/i2c-ali1563.c
-+
-+ALIENWARE WMI DRIVER
-+L: Dell.Client.Kernel@dell.com
-+S: Maintained
-+F: drivers/platform/x86/dell/alienware-wmi.c
-+
-+ALL SENSORS DLH SERIES PRESSURE SENSORS DRIVER
-+M: Tomislav Denis <tomislav.denis@avl.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+W: http://www.allsensors.com/
-+F: Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml
-+F: drivers/iio/pressure/dlhl60d.c
-+
-+ALLEGRO DVT VIDEO IP CORE DRIVER
-+M: Michael Tretter <m.tretter@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/allegro,al5e.yaml
-+F: drivers/media/platform/allegro-dvt/
-+
-+ALLWINNER A10 CSI DRIVER
-+M: Maxime Ripard <mripard@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
-+F: drivers/media/platform/sunxi/sun4i-csi/
-+
-+ALLWINNER CPUFREQ DRIVER
-+M: Yangtao Li <tiny.windzz@gmail.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
-+F: drivers/cpufreq/sun50i-cpufreq-nvmem.c
-+
-+ALLWINNER CRYPTO DRIVERS
-+M: Corentin Labbe <clabbe.montjoie@gmail.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/allwinner/
-+
-+ALLWINNER HARDWARE SPINLOCK SUPPORT
-+M: Wilken Gottwalt <wilken.gottwalt@posteo.net>
-+S: Maintained
-+F: Documentation/devicetree/bindings/hwlock/allwinner,sun6i-hwspinlock.yaml
-+F: drivers/hwspinlock/sun6i_hwspinlock.c
-+
-+ALLWINNER THERMAL DRIVER
-+M: Vasily Khoruzhick <anarsoul@gmail.com>
-+M: Yangtao Li <tiny.windzz@gmail.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
-+F: drivers/thermal/sun8i_thermal.c
-+
-+ALLWINNER VPU DRIVER
-+M: Maxime Ripard <mripard@kernel.org>
-+M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/staging/media/sunxi/cedrus/
-+
-+ALPHA PORT
-+M: Richard Henderson <rth@twiddle.net>
-+M: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
-+M: Matt Turner <mattst88@gmail.com>
-+L: linux-alpha@vger.kernel.org
-+S: Odd Fixes
-+F: arch/alpha/
-+
-+ALPS PS/2 TOUCHPAD DRIVER
-+R: Pali Rohár <pali@kernel.org>
-+F: drivers/input/mouse/alps.*
-+
-+ALTERA I2C CONTROLLER DRIVER
-+M: Thor Thayer <thor.thayer@linux.intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-altera.txt
-+F: drivers/i2c/busses/i2c-altera.c
-+
-+ALTERA MAILBOX DRIVER
-+M: Joyce Ooi <joyce.ooi@intel.com>
-+S: Maintained
-+F: drivers/mailbox/mailbox-altera.c
-+
-+ALTERA MSGDMA IP CORE DRIVER
-+M: Olivier Dautricourt <olivier.dautricourt@orolia.com>
-+R: Stefan Roese <sr@denx.de>
-+L: dmaengine@vger.kernel.org
-+S: Odd Fixes
-+F: Documentation/devicetree/bindings/dma/altr,msgdma.yaml
-+F: drivers/dma/altera-msgdma.c
-+
-+ALTERA PIO DRIVER
-+M: Mun Yew Tham <mun.yew.tham@intel.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-altera.c
-+
-+ALTERA SYSTEM MANAGER DRIVER
-+M: Thor Thayer <thor.thayer@linux.intel.com>
-+S: Maintained
-+F: drivers/mfd/altera-sysmgr.c
-+F: include/linux/mfd/altera-sysmgr.h
-+
-+ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT
-+M: Thor Thayer <thor.thayer@linux.intel.com>
-+S: Maintained
-+F: drivers/gpio/gpio-altera-a10sr.c
-+F: drivers/mfd/altera-a10sr.c
-+F: drivers/reset/reset-a10sr.c
-+F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
-+F: include/linux/mfd/altera-a10sr.h
-+
-+ALTERA TRIPLE SPEED ETHERNET DRIVER
-+M: Joyce Ooi <joyce.ooi@intel.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/altera/
-+
-+ALTERA UART/JTAG UART SERIAL DRIVERS
-+M: Tobias Klauser <tklauser@distanz.ch>
-+L: linux-serial@vger.kernel.org
-+S: Maintained
-+F: drivers/tty/serial/altera_jtaguart.c
-+F: drivers/tty/serial/altera_uart.c
-+F: include/linux/altera_jtaguart.h
-+F: include/linux/altera_uart.h
-+
-+AMAZON ANNAPURNA LABS FIC DRIVER
-+M: Talel Shenhar <talel@amazon.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
-+F: drivers/irqchip/irq-al-fic.c
-+
-+AMAZON ANNAPURNA LABS MEMORY CONTROLLER EDAC
-+M: Talel Shenhar <talel@amazon.com>
-+M: Talel Shenhar <talelshenhar@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml
-+F: drivers/edac/al_mc_edac.c
-+
-+AMAZON ANNAPURNA LABS THERMAL MMIO DRIVER
-+M: Talel Shenhar <talel@amazon.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
-+F: drivers/thermal/thermal_mmio.c
-+
-+AMAZON ETHERNET DRIVERS
-+M: Netanel Belgazal <netanel@amazon.com>
-+M: Arthur Kiyanovski <akiyano@amazon.com>
-+R: Guy Tzalik <gtzalik@amazon.com>
-+R: Saeed Bishara <saeedb@amazon.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/ethernet/amazon/ena.rst
-+F: drivers/net/ethernet/amazon/
-+
-+AMAZON RDMA EFA DRIVER
-+M: Gal Pressman <galpress@amazon.com>
-+R: Yossi Leybovich <sleybo@amazon.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/hw/efa/
-+F: include/uapi/rdma/efa-abi.h
-+
-+AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER
-+M: Tom Lendacky <thomas.lendacky@amd.com>
-+M: John Allen <john.allen@amd.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+F: drivers/crypto/ccp/
-+F: include/linux/ccp.h
-+
-+AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER - SEV SUPPORT
-+M: Brijesh Singh <brijesh.singh@amd.com>
-+M: Tom Lendacky <thomas.lendacky@amd.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+F: drivers/crypto/ccp/sev*
-+F: include/uapi/linux/psp-sev.h
-+
-+AMD DISPLAY CORE
-+M: Harry Wentland <harry.wentland@amd.com>
-+M: Leo Li <sunpeng.li@amd.com>
-+L: amd-gfx@lists.freedesktop.org
-+S: Supported
-+T: git https://gitlab.freedesktop.org/agd5f/linux.git
-+F: drivers/gpu/drm/amd/display/
-+
-+AMD FAM15H PROCESSOR POWER MONITORING DRIVER
-+M: Huang Rui <ray.huang@amd.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+F: Documentation/hwmon/fam15h_power.rst
-+F: drivers/hwmon/fam15h_power.c
-+
-+AMD FCH GPIO DRIVER
-+M: Enrico Weigelt, metux IT consult <info@metux.net>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-amd-fch.c
-+F: include/linux/platform_data/gpio/gpio-amd-fch.h
-+
-+AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
-+L: linux-geode@lists.infradead.org (moderated for non-subscribers)
-+S: Orphan
-+F: drivers/usb/gadget/udc/amd5536udc.*
-+
-+AMD GEODE PROCESSOR/CHIPSET SUPPORT
-+M: Andres Salomon <dilinger@queued.net>
-+L: linux-geode@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
-+F: arch/x86/include/asm/geode.h
-+F: drivers/char/hw_random/geode-rng.c
-+F: drivers/crypto/geode*
-+F: drivers/video/fbdev/geode/
-+
-+AMD IOMMU (AMD-VI)
-+M: Joerg Roedel <joro@8bytes.org>
-+R: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
-+L: iommu@lists.linux-foundation.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-+F: drivers/iommu/amd/
-+F: include/linux/amd-iommu.h
-+
-+AMD KFD
-+M: Felix Kuehling <Felix.Kuehling@amd.com>
-+L: amd-gfx@lists.freedesktop.org
-+S: Supported
-+T: git https://gitlab.freedesktop.org/agd5f/linux.git
-+F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd*.[ch]
-+F: drivers/gpu/drm/amd/amdkfd/
-+F: drivers/gpu/drm/amd/include/cik_structs.h
-+F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h
-+F: drivers/gpu/drm/amd/include/v9_structs.h
-+F: drivers/gpu/drm/amd/include/vi_structs.h
-+F: include/uapi/linux/kfd_ioctl.h
-+
-+AMD SPI DRIVER
-+M: Sanjay R Mehta <sanju.mehta@amd.com>
-+S: Maintained
-+F: drivers/spi/spi-amd.c
-+
-+AMD MP2 I2C DRIVER
-+M: Elie Morisse <syniurge@gmail.com>
-+M: Nehal Shah <nehal-bakulchandra.shah@amd.com>
-+M: Shyam Sundar S K <shyam-sundar.s-k@amd.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-amd-mp2*
-+
-+AMD PMC DRIVER
-+M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/amd-pmc.*
-+
-+AMD POWERPLAY AND SWSMU
-+M: Evan Quan <evan.quan@amd.com>
-+L: amd-gfx@lists.freedesktop.org
-+S: Supported
-+T: git https://gitlab.freedesktop.org/agd5f/linux.git
-+F: drivers/gpu/drm/amd/pm/
-+
-+AMD PTDMA DRIVER
-+M: Sanjay R Mehta <sanju.mehta@amd.com>
-+L: dmaengine@vger.kernel.org
-+S: Maintained
-+F: drivers/dma/ptdma/
-+
-+AMD SEATTLE DEVICE TREE SUPPORT
-+M: Brijesh Singh <brijeshkumar.singh@amd.com>
-+M: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
-+M: Tom Lendacky <thomas.lendacky@amd.com>
-+S: Supported
-+F: arch/arm64/boot/dts/amd/
-+
-+AMD XGBE DRIVER
-+M: Tom Lendacky <thomas.lendacky@amd.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
-+F: drivers/net/ethernet/amd/xgbe/
-+
-+AMD SENSOR FUSION HUB DRIVER
-+M: Nehal Shah <nehal-bakulchandra.shah@amd.com>
-+M: Basavaraj Natikar <basavaraj.natikar@amd.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/hid/amd-sfh*
-+F: drivers/hid/amd-sfh-hid/
-+
-+AMS AS73211 DRIVER
-+M: Christian Eggers <ceggers@arri.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/light/ams,as73211.yaml
-+F: drivers/iio/light/as73211.c
-+
-+ANALOG DEVICES INC AD7192 DRIVER
-+M: Alexandru Tachici <alexandru.tachici@analog.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml
-+F: drivers/iio/adc/ad7192.c
-+
-+ANALOG DEVICES INC AD7292 DRIVER
-+M: Marcelo Schmitt <marcelo.schmitt1@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
-+F: drivers/iio/adc/ad7292.c
-+
-+ANALOG DEVICES INC AD7768-1 DRIVER
-+M: Michael Hennerich <Michael.Hennerich@analog.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
-+F: drivers/iio/adc/ad7768-1.c
-+
-+ANALOG DEVICES INC AD7780 DRIVER
-+M: Michael Hennerich <Michael.Hennerich@analog.com>
-+M: Renato Lui Geh <renatogeh@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
-+F: drivers/iio/adc/ad7780.c
-+
-+ANALOG DEVICES INC AD9389B DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/ad9389b*
-+
-+ANALOG DEVICES INC ADGS1408 DRIVER
-+M: Mircea Caprioru <mircea.caprioru@analog.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/mux/adi,adgs1408.txt
-+F: drivers/mux/adgs1408.c
-+
-+ANALOG DEVICES INC ADIN DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/net/adi,adin.yaml
-+F: drivers/net/phy/adin.c
-+
-+ANALOG DEVICES INC ADIS DRIVER LIBRARY
-+M: Nuno Sa <nuno.sa@analog.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: drivers/iio/imu/adis.c
-+F: include/linux/iio/imu/adis.h
-+
-+ANALOG DEVICES INC ADIS16460 DRIVER
-+M: Dragos Bogdan <dragos.bogdan@analog.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
-+F: drivers/iio/imu/adis16460.c
-+
-+ANALOG DEVICES INC ADIS16475 DRIVER
-+M: Nuno Sa <nuno.sa@analog.com>
-+L: linux-iio@vger.kernel.org
-+W: http://ez.analog.com/community/linux-device-drivers
-+S: Supported
-+F: drivers/iio/imu/adis16475.c
-+F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
-+
-+ANALOG DEVICES INC ADM1177 DRIVER
-+M: Michael Hennerich <Michael.Hennerich@analog.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml
-+F: drivers/hwmon/adm1177.c
-+
-+ANALOG DEVICES INC ADP5061 DRIVER
-+M: Michael Hennerich <Michael.Hennerich@analog.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/power/supply/adp5061.c
-+
-+ANALOG DEVICES INC ADV7180 DRIVER
-+M: Lars-Peter Clausen <lars@metafoo.de>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/media/i2c/adv7180.c
-+F: Documentation/devicetree/bindings/media/i2c/adv7180.yaml
-+
-+ANALOG DEVICES INC ADV748X DRIVER
-+M: Kieran Bingham <kieran.bingham@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/adv748x/*
-+
-+ANALOG DEVICES INC ADV7511 DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/adv7511*
-+
-+ANALOG DEVICES INC ADV7604 DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/adv7604*
-+F: Documentation/devicetree/bindings/media/i2c/adv7604.yaml
-+
-+ANALOG DEVICES INC ADV7842 DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/adv7842*
-+
-+ANALOG DEVICES INC ADXRS290 DRIVER
-+M: Nishant Malpani <nish.malpani25@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: drivers/iio/gyro/adxrs290.c
-+F: Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml
-+
-+ANALOG DEVICES INC ASOC CODEC DRIVERS
-+M: Lars-Peter Clausen <lars@metafoo.de>
-+M: Nuno Sá <nuno.sa@analog.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+W: http://wiki.analog.com/
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: sound/soc/codecs/ad1*
-+F: sound/soc/codecs/ad7*
-+F: sound/soc/codecs/adau*
-+F: sound/soc/codecs/adav*
-+F: sound/soc/codecs/sigmadsp.*
-+F: sound/soc/codecs/ssm*
-+
-+ANALOG DEVICES INC DMA DRIVERS
-+M: Lars-Peter Clausen <lars@metafoo.de>
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: drivers/dma/dma-axi-dmac.c
-+
-+ANALOG DEVICES INC IIO DRIVERS
-+M: Lars-Peter Clausen <lars@metafoo.de>
-+M: Michael Hennerich <Michael.Hennerich@analog.com>
-+S: Supported
-+W: http://wiki.analog.com/
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
-+F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
-+F: Documentation/devicetree/bindings/iio/*/adi,*
-+F: Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml
-+F: drivers/iio/*/ad*
-+F: drivers/iio/adc/ltc249*
-+F: drivers/iio/amplifiers/hmc425a.c
-+F: drivers/staging/iio/*/ad*
-+X: drivers/iio/*/adjd*
-+
-+ANALOGBITS PLL LIBRARIES
-+M: Paul Walmsley <paul.walmsley@sifive.com>
-+S: Supported
-+F: drivers/clk/analogbits/*
-+F: include/linux/clk/analogbits*
-+
-+ANDES ARCHITECTURE
-+M: Nick Hu <nickhu@andestech.com>
-+M: Greentime Hu <green.hu@gmail.com>
-+M: Vincent Chen <deanbo422@gmail.com>
-+S: Supported
-+T: git https://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux.git
-+F: Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
-+F: Documentation/devicetree/bindings/nds32/
-+F: arch/nds32/
-+N: nds32
-+K: nds32
-+
-+ANDROID CONFIG FRAGMENTS
-+M: Rob Herring <robh@kernel.org>
-+S: Supported
-+F: kernel/configs/android*
-+
-+ANDROID DRIVERS
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+M: Arve Hjønnevåg <arve@android.com>
-+M: Todd Kjos <tkjos@android.com>
-+M: Martijn Coenen <maco@android.com>
-+M: Joel Fernandes <joel@joelfernandes.org>
-+M: Christian Brauner <christian@brauner.io>
-+M: Hridya Valsaraju <hridya@google.com>
-+M: Suren Baghdasaryan <surenb@google.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
-+F: drivers/android/
-+F: drivers/staging/android/
-+
-+ANDROID GOLDFISH PIC DRIVER
-+M: Miodrag Dinic <miodrag.dinic@mips.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt
-+F: drivers/irqchip/irq-goldfish-pic.c
-+
-+ANDROID GOLDFISH RTC DRIVER
-+M: Jiaxun Yang <jiaxun.yang@flygoat.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt
-+F: drivers/rtc/rtc-goldfish.c
-+
-+AOA (Apple Onboard Audio) ALSA DRIVER
-+M: Johannes Berg <johannes@sipsolutions.net>
-+L: linuxppc-dev@lists.ozlabs.org
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: sound/aoa/
-+
-+APEX EMBEDDED SYSTEMS STX104 IIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/iio/adc/stx104.c
-+
-+APM DRIVER
-+M: Jiri Kosina <jikos@kernel.org>
-+S: Odd fixes
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git
-+F: arch/x86/kernel/apm_32.c
-+F: drivers/char/apm-emulation.c
-+F: include/linux/apm_bios.h
-+F: include/uapi/linux/apm_bios.h
-+
-+APPARMOR SECURITY MODULE
-+M: John Johansen <john.johansen@canonical.com>
-+L: apparmor@lists.ubuntu.com (subscribers-only, general discussion)
-+S: Supported
-+W: wiki.apparmor.net
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
-+F: Documentation/admin-guide/LSM/apparmor.rst
-+F: security/apparmor/
-+
-+APPLE BCM5974 MULTITOUCH DRIVER
-+M: Henrik Rydberg <rydberg@bitmath.org>
-+L: linux-input@vger.kernel.org
-+S: Odd fixes
-+F: drivers/input/mouse/bcm5974.c
-+
-+APPLE DART IOMMU DRIVER
-+M: Sven Peter <sven@svenpeter.dev>
-+R: Alyssa Rosenzweig <alyssa@rosenzweig.io>
-+L: iommu@lists.linux-foundation.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iommu/apple,dart.yaml
-+F: drivers/iommu/apple-dart.c
-+
-+APPLE SMC DRIVER
-+M: Henrik Rydberg <rydberg@bitmath.org>
-+L: linux-hwmon@vger.kernel.org
-+S: Odd fixes
-+F: drivers/hwmon/applesmc.c
-+
-+APPLETALK NETWORK LAYER
-+L: netdev@vger.kernel.org
-+S: Odd fixes
-+F: drivers/net/appletalk/
-+F: include/linux/atalk.h
-+F: include/uapi/linux/atalk.h
-+F: net/appletalk/
-+
-+APPLIED MICRO (APM) X-GENE DEVICE TREE SUPPORT
-+M: Khuong Dinh <khuong@os.amperecomputing.com>
-+S: Supported
-+F: arch/arm64/boot/dts/apm/
-+
-+APPLIED MICRO (APM) X-GENE SOC EDAC
-+M: Khuong Dinh <khuong@os.amperecomputing.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/edac/apm-xgene-edac.txt
-+F: drivers/edac/xgene_edac.c
-+
-+APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
-+M: Iyappan Subramanian <iyappan@os.amperecomputing.com>
-+M: Keyur Chudgar <keyur@os.amperecomputing.com>
-+S: Supported
-+F: drivers/net/ethernet/apm/xgene-v2/
-+
-+APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER
-+M: Iyappan Subramanian <iyappan@os.amperecomputing.com>
-+M: Keyur Chudgar <keyur@os.amperecomputing.com>
-+M: Quan Nguyen <quan@os.amperecomputing.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
-+F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
-+F: drivers/net/ethernet/apm/xgene/
-+F: drivers/net/mdio/mdio-xgene.c
-+
-+APPLIED MICRO (APM) X-GENE SOC PMU
-+M: Khuong Dinh <khuong@os.amperecomputing.com>
-+S: Supported
-+F: Documentation/admin-guide/perf/xgene-pmu.rst
-+F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
-+F: drivers/perf/xgene_pmu.c
-+
-+APTINA CAMERA SENSOR PLL
-+M: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/aptina-pll.*
-+
-+AQUACOMPUTER D5 NEXT PUMP SENSOR DRIVER
-+M: Aleksa Savic <savicaleksa83@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/aquacomputer_d5next.rst
-+F: drivers/hwmon/aquacomputer_d5next.c
-+
-+AQUANTIA ETHERNET DRIVER (atlantic)
-+M: Igor Russkikh <irusskikh@marvell.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: https://www.marvell.com/
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: Documentation/networking/device_drivers/ethernet/aquantia/atlantic.rst
-+F: drivers/net/ethernet/aquantia/atlantic/
-+
-+AQUANTIA ETHERNET DRIVER PTP SUBSYSTEM
-+M: Egor Pomozov <epomozov@marvell.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.aquantia.com
-+F: drivers/net/ethernet/aquantia/atlantic/aq_ptp*
-+
-+ARASAN NAND CONTROLLER DRIVER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+M: Naga Sureshkumar Relli <nagasure@xilinx.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
-+F: drivers/mtd/nand/raw/arasan-nand-controller.c
-+
-+ARC FRAMEBUFFER DRIVER
-+M: Jaya Kumar <jayalk@intworks.biz>
-+S: Maintained
-+F: drivers/video/fbdev/arcfb.c
-+F: drivers/video/fbdev/core/fb_defio.c
-+
-+ARC PGU DRM DRIVER
-+M: Alexey Brodkin <abrodkin@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/display/snps,arcpgu.txt
-+F: drivers/gpu/drm/tiny/arcpgu.c
-+
-+ARCNET NETWORK LAYER
-+M: Michael Grzeschik <m.grzeschik@pengutronix.de>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/arcnet/
-+F: include/uapi/linux/if_arcnet.h
-+
-+ARM ARCHITECTED TIMER DRIVER
-+M: Mark Rutland <mark.rutland@arm.com>
-+M: Marc Zyngier <maz@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/include/asm/arch_timer.h
-+F: arch/arm64/include/asm/arch_timer.h
-+F: drivers/clocksource/arm_arch_timer.c
-+
-+ARM HDLCD DRM DRIVER
-+M: Liviu Dudau <liviu.dudau@arm.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/display/arm,hdlcd.txt
-+F: drivers/gpu/drm/arm/hdlcd_*
-+
-+ARM INTEGRATOR, VERSATILE AND REALVIEW SUPPORT
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/arm,integrator.yaml
-+F: Documentation/devicetree/bindings/arm/arm,realview.yaml
-+F: Documentation/devicetree/bindings/arm/arm,versatile.yaml
-+F: Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
-+F: Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
-+F: Documentation/devicetree/bindings/clock/arm,syscon-icst.yaml
-+F: Documentation/devicetree/bindings/i2c/i2c-versatile.txt
-+F: Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
-+F: Documentation/devicetree/bindings/mtd/arm-versatile.txt
-+F: arch/arm/boot/dts/arm-realview-*
-+F: arch/arm/boot/dts/integrator*
-+F: arch/arm/boot/dts/versatile*
-+F: arch/arm/mach-integrator/
-+F: arch/arm/mach-realview/
-+F: arch/arm/mach-versatile/
-+F: arch/arm/plat-versatile/
-+F: drivers/bus/arm-integrator-lm.c
-+F: drivers/clk/versatile/
-+F: drivers/i2c/busses/i2c-versatile.c
-+F: drivers/irqchip/irq-versatile-fpga.c
-+F: drivers/mtd/maps/physmap-versatile.*
-+F: drivers/power/reset/arm-versatile-reboot.c
-+F: drivers/soc/versatile/
-+
-+ARM KOMEDA DRM-KMS DRIVER
-+M: James (Qian) Wang <james.qian.wang@arm.com>
-+M: Liviu Dudau <liviu.dudau@arm.com>
-+M: Mihail Atanassov <mihail.atanassov@arm.com>
-+L: Mali DP Maintainers <malidp@foss.arm.com>
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/arm,komeda.txt
-+F: Documentation/gpu/komeda-kms.rst
-+F: drivers/gpu/drm/arm/display/include/
-+F: drivers/gpu/drm/arm/display/komeda/
-+
-+ARM MALI PANFROST DRM DRIVER
-+M: Rob Herring <robh@kernel.org>
-+M: Tomeu Vizoso <tomeu.vizoso@collabora.com>
-+R: Steven Price <steven.price@arm.com>
-+R: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/panfrost/
-+F: include/uapi/drm/panfrost_drm.h
-+
-+ARM MALI-DP DRM DRIVER
-+M: Liviu Dudau <liviu.dudau@arm.com>
-+M: Brian Starkey <brian.starkey@arm.com>
-+L: Mali DP Maintainers <malidp@foss.arm.com>
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/arm,malidp.txt
-+F: Documentation/gpu/afbc.rst
-+F: drivers/gpu/drm/arm/
-+
-+ARM MFM AND FLOPPY DRIVERS
-+M: Ian Molton <spyro@f2s.com>
-+S: Maintained
-+F: arch/arm/include/asm/floppy.h
-+F: arch/arm/mach-rpc/floppydma.S
-+
-+ARM PMU PROFILING AND DEBUGGING
-+M: Will Deacon <will@kernel.org>
-+M: Mark Rutland <mark.rutland@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/pmu.yaml
-+F: Documentation/devicetree/bindings/perf/
-+F: arch/arm*/include/asm/hw_breakpoint.h
-+F: arch/arm*/include/asm/perf_event.h
-+F: arch/arm*/kernel/hw_breakpoint.c
-+F: arch/arm*/kernel/perf_*
-+F: drivers/perf/
-+F: include/linux/perf/arm_pmu.h
-+
-+ARM PORT
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Odd Fixes
-+W: http://www.armlinux.org.uk/
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git
-+F: arch/arm/
-+X: arch/arm/boot/dts/
-+
-+ARM PRIMECELL AACI PL041 DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: sound/arm/aaci.*
-+
-+ARM PRIMECELL BUS SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: drivers/amba/
-+F: include/linux/amba/bus.h
-+
-+ARM PRIMECELL PL35X NAND CONTROLLER DRIVER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+M: Naga Sureshkumar Relli <nagasure@xilinx.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
-+F: drivers/mtd/nand/raw/pl35x-nand-controller.c
-+
-+ARM PRIMECELL PL35X SMC DRIVER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+M: Naga Sureshkumar Relli <nagasure@xilinx.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml
-+F: drivers/memory/pl353-smc.c
-+
-+ARM PRIMECELL CLCD PL110 DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: drivers/video/fbdev/amba-clcd.*
-+
-+ARM PRIMECELL KMI PL050 DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: drivers/input/serio/ambakmi.*
-+F: include/linux/amba/kmi.h
-+
-+ARM PRIMECELL MMCI PL180/1 DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: drivers/mmc/host/mmci.*
-+F: include/linux/amba/mmci.h
-+
-+ARM PRIMECELL SSP PL022 SPI DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/spi-pl022.yaml
-+F: drivers/spi/spi-pl022.c
-+
-+ARM PRIMECELL UART PL010 AND PL011 DRIVERS
-+M: Russell King <linux@armlinux.org.uk>
-+S: Odd Fixes
-+F: drivers/tty/serial/amba-pl01*.c
-+F: include/linux/amba/serial.h
-+
-+ARM PRIMECELL VIC PL190/PL192 DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/interrupt-controller/arm,vic.txt
-+F: drivers/irqchip/irq-vic.c
-+
-+ARM SMC WATCHDOG DRIVER
-+M: Julius Werner <jwerner@chromium.org>
-+R: Evan Benn <evanbenn@chromium.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/watchdog/arm-smc-wdt.yaml
-+F: drivers/watchdog/arm_smc_wdt.c
-+
-+ARM SMMU DRIVERS
-+M: Will Deacon <will@kernel.org>
-+R: Robin Murphy <robin.murphy@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/iommu/arm,smmu*
-+F: drivers/iommu/arm/
-+F: drivers/iommu/io-pgtable-arm*
-+
-+ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS)
-+M: Arnd Bergmann <arnd@arndb.de>
-+M: Olof Johansson <olof@lixom.net>
-+M: soc@kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git
-+F: arch/arm/boot/dts/Makefile
-+F: arch/arm64/boot/dts/Makefile
-+
-+ARM SUB-ARCHITECTURES
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git
-+F: arch/arm/mach-*/
-+F: arch/arm/plat-*/
-+
-+ARM/ACTIONS SEMI ARCHITECTURE
-+M: Andreas Färber <afaerber@suse.de>
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-actions@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/actions.yaml
-+F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
-+F: Documentation/devicetree/bindings/dma/owl-dma.yaml
-+F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml
-+F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml
-+F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml
-+F: Documentation/devicetree/bindings/net/actions,owl-emac.yaml
-+F: Documentation/devicetree/bindings/pinctrl/actions,*
-+F: Documentation/devicetree/bindings/power/actions,owl-sps.txt
-+F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt
-+F: arch/arm/boot/dts/owl-*
-+F: arch/arm/mach-actions/
-+F: arch/arm64/boot/dts/actions/
-+F: drivers/clk/actions/
-+F: drivers/clocksource/timer-owl*
-+F: drivers/dma/owl-dma.c
-+F: drivers/i2c/busses/i2c-owl.c
-+F: drivers/irqchip/irq-owl-sirq.c
-+F: drivers/mmc/host/owl-mmc.c
-+F: drivers/net/ethernet/actions/
-+F: drivers/pinctrl/actions/*
-+F: drivers/soc/actions/
-+F: include/dt-bindings/power/owl-*
-+F: include/dt-bindings/reset/actions,*
-+F: include/linux/soc/actions/
-+N: owl
-+
-+ARM/ADS SPHERE MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/AFEB9260 MACHINE SUPPORT
-+M: Sergey Lapin <slapin@ossfans.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/AJECO 1ARM MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/Allwinner SoC Clock Support
-+M: Emilio López <emilio@elopez.com.ar>
-+S: Maintained
-+F: drivers/clk/sunxi/
-+
-+ARM/Allwinner sunXi SoC support
-+M: Maxime Ripard <mripard@kernel.org>
-+M: Chen-Yu Tsai <wens@csie.org>
-+R: Jernej Skrabec <jernej.skrabec@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git
-+L: linux-sunxi@lists.linux.dev
-+F: arch/arm/mach-sunxi/
-+F: arch/arm64/boot/dts/allwinner/
-+F: drivers/clk/sunxi-ng/
-+F: drivers/pinctrl/sunxi/
-+F: drivers/soc/sunxi/
-+N: allwinner
-+N: sun[x456789]i
-+N: sun50i
-+
-+ARM/Amlogic Meson SoC CLOCK FRAMEWORK
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+M: Jerome Brunet <jbrunet@baylibre.com>
-+L: linux-amlogic@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/clock/amlogic*
-+F: drivers/clk/meson/
-+F: include/dt-bindings/clock/gxbb*
-+F: include/dt-bindings/clock/meson*
-+
-+ARM/Amlogic Meson SoC Crypto Drivers
-+M: Corentin Labbe <clabbe@baylibre.com>
-+L: linux-crypto@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/crypto/amlogic*
-+F: drivers/crypto/amlogic/
-+
-+ARM/Amlogic Meson SoC Sound Drivers
-+M: Jerome Brunet <jbrunet@baylibre.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/amlogic*
-+F: sound/soc/meson/
-+
-+ARM/Amlogic Meson SoC support
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+M: Kevin Hilman <khilman@baylibre.com>
-+R: Jerome Brunet <jbrunet@baylibre.com>
-+R: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-amlogic@lists.infradead.org
-+S: Maintained
-+W: http://linux-meson.com/
-+F: arch/arm/boot/dts/meson*
-+F: arch/arm/mach-meson/
-+F: arch/arm64/boot/dts/amlogic/
-+F: drivers/mmc/host/meson*
-+F: drivers/pinctrl/meson/
-+F: drivers/rtc/rtc-meson*
-+F: drivers/soc/amlogic/
-+N: meson
-+
-+ARM/Annapurna Labs ALPINE ARCHITECTURE
-+M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
-+M: Antoine Tenart <atenart@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/alpine*
-+F: arch/arm/mach-alpine/
-+F: arch/arm64/boot/dts/amazon/
-+F: drivers/*/*alpine*
-+
-+ARM/APPLE MACHINE SUPPORT
-+M: Hector Martin <marcan@marcan.st>
-+M: Sven Peter <sven@svenpeter.dev>
-+R: Alyssa Rosenzweig <alyssa@rosenzweig.io>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: https://asahilinux.org
-+B: https://github.com/AsahiLinux/linux/issues
-+C: irc://irc.oftc.net/asahi-dev
-+T: git https://github.com/AsahiLinux/linux.git
-+F: Documentation/devicetree/bindings/arm/apple.yaml
-+F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
-+F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
-+F: arch/arm64/boot/dts/apple/
-+F: drivers/irqchip/irq-apple-aic.c
-+F: include/dt-bindings/interrupt-controller/apple-aic.h
-+F: include/dt-bindings/pinctrl/apple.h
-+
-+ARM/ARTPEC MACHINE SUPPORT
-+M: Jesper Nilsson <jesper.nilsson@axis.com>
-+M: Lars Persson <lars.persson@axis.com>
-+L: linux-arm-kernel@axis.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt
-+F: arch/arm/boot/dts/artpec6*
-+F: arch/arm/mach-artpec
-+F: drivers/clk/axis
-+F: drivers/crypto/axis
-+F: drivers/mmc/host/usdhi6rol0.c
-+F: drivers/pinctrl/pinctrl-artpec*
-+
-+ARM/ASPEED I2C DRIVER
-+M: Brendan Higgins <brendanhiggins@google.com>
-+R: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-+R: Joel Stanley <joel@jms.id.au>
-+L: linux-i2c@vger.kernel.org
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
-+F: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-i2c-ic.txt
-+F: drivers/i2c/busses/i2c-aspeed.c
-+F: drivers/irqchip/irq-aspeed-i2c-ic.c
-+
-+ARM/ASPEED MACHINE SUPPORT
-+M: Joel Stanley <joel@jms.id.au>
-+R: Andrew Jeffery <andrew@aj.id.au>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-+S: Supported
-+Q: https://patchwork.ozlabs.org/project/linux-aspeed/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed.git
-+F: arch/arm/boot/dts/aspeed-*
-+F: arch/arm/mach-aspeed/
-+N: aspeed
-+
-+ARM/BITMAIN ARCHITECTURE
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/bitmain.yaml
-+F: Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml
-+F: Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt
-+F: arch/arm64/boot/dts/bitmain/
-+F: drivers/clk/clk-bm1880.c
-+F: drivers/pinctrl/pinctrl-bm1880.c
-+
-+ARM/CALXEDA HIGHBANK ARCHITECTURE
-+M: Andre Przywara <andre.przywara@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/ecx-*.dts*
-+F: arch/arm/boot/dts/highbank.dts
-+F: arch/arm/mach-highbank/
-+
-+ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT
-+M: Krzysztof Halasa <khalasa@piap.pl>
-+S: Maintained
-+F: arch/arm/mach-cns3xxx/
-+
-+ARM/CAVIUM THUNDER NETWORK DRIVER
-+M: Sunil Goutham <sgoutham@marvell.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/net/ethernet/cavium/thunder/
-+
-+ARM/CIRRUS LOGIC BK3 MACHINE SUPPORT
-+M: Lukasz Majewski <lukma@denx.de>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-ep93xx/ts72xx.c
-+
-+ARM/CIRRUS LOGIC CLPS711X ARM ARCHITECTURE
-+M: Alexander Shiyan <shc_work@mail.ru>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Odd Fixes
-+N: clps711x
-+
-+ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
-+M: Hartley Sweeten <hsweeten@visionengravers.com>
-+M: Alexander Sverdlin <alexander.sverdlin@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-ep93xx/
-+F: arch/arm/mach-ep93xx/include/mach/
-+
-+ARM/CLKDEV SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git clkdev
-+F: drivers/clk/clkdev.c
-+
-+ARM/CONEXANT DIGICOLOR MACHINE SUPPORT
-+M: Baruch Siach <baruch@tkos.co.il>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/cx92755*
-+N: digicolor
-+
-+ARM/CONTEC MICRO9 MACHINE SUPPORT
-+M: Hubert Feurstein <hubert.feurstein@contec.at>
-+S: Maintained
-+F: arch/arm/mach-ep93xx/micro9.c
-+
-+ARM/CORESIGHT FRAMEWORK AND DRIVERS
-+M: Mathieu Poirier <mathieu.poirier@linaro.org>
-+M: Suzuki K Poulose <suzuki.poulose@arm.com>
-+R: Mike Leach <mike.leach@linaro.org>
-+R: Leo Yan <leo.yan@linaro.org>
-+L: coresight@lists.linaro.org (moderated for non-subscribers)
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git
-+F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
-+F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
-+F: Documentation/devicetree/bindings/arm/coresight-cti.yaml
-+F: Documentation/devicetree/bindings/arm/coresight.txt
-+F: Documentation/devicetree/bindings/arm/ete.yaml
-+F: Documentation/devicetree/bindings/arm/trbe.yaml
-+F: Documentation/trace/coresight/*
-+F: drivers/hwtracing/coresight/*
-+F: include/dt-bindings/arm/coresight-cti-dt.h
-+F: include/linux/coresight*
-+F: tools/perf/arch/arm/util/auxtrace.c
-+F: tools/perf/arch/arm/util/cs-etm.c
-+F: tools/perf/arch/arm/util/cs-etm.h
-+F: tools/perf/arch/arm/util/pmu.c
-+F: tools/perf/util/cs-etm-decoder/*
-+F: tools/perf/util/cs-etm.*
-+
-+ARM/CORGI MACHINE SUPPORT
-+M: Richard Purdie <rpurdie@rpsys.net>
-+S: Maintained
-+
-+ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
-+M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/ulli-kroll/linux.git
-+F: Documentation/devicetree/bindings/arm/gemini.txt
-+F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt
-+F: Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
-+F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.txt
-+F: arch/arm/boot/dts/gemini*
-+F: arch/arm/mach-gemini/
-+F: drivers/crypto/gemini/
-+F: drivers/net/ethernet/cortina/
-+F: drivers/pinctrl/pinctrl-gemini.c
-+F: drivers/rtc/rtc-ftrtc010.c
-+
-+ARM/CZ.NIC TURRIS SUPPORT
-+M: Marek Behún <kabel@kernel.org>
-+S: Maintained
-+W: https://www.turris.cz/
-+F: Documentation/ABI/testing/debugfs-moxtet
-+F: Documentation/ABI/testing/sysfs-bus-moxtet-devices
-+F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
-+F: Documentation/devicetree/bindings/bus/moxtet.txt
-+F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
-+F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
-+F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
-+F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
-+F: drivers/bus/moxtet.c
-+F: drivers/firmware/turris-mox-rwtm.c
-+F: drivers/leds/leds-turris-omnia.c
-+F: drivers/mailbox/armada-37xx-rwtm-mailbox.c
-+F: drivers/gpio/gpio-moxtet.c
-+F: drivers/watchdog/armada_37xx_wdt.c
-+F: include/dt-bindings/bus/moxtet.h
-+F: include/linux/armada-37xx-rwtm-mailbox.h
-+F: include/linux/moxtet.h
-+
-+ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/ezx.c
-+
-+ARM/FARADAY FA526 PORT
-+M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.berlios.de/gemini-board
-+F: arch/arm/mm/*-fa*
-+
-+ARM/FOOTBRIDGE ARCHITECTURE
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.armlinux.org.uk/
-+F: arch/arm/include/asm/hardware/dec21285.h
-+F: arch/arm/mach-footbridge/
-+
-+ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
-+M: Shawn Guo <shawnguo@kernel.org>
-+M: Sascha Hauer <s.hauer@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+R: Fabio Estevam <festevam@gmail.com>
-+R: NXP Linux Team <linux-imx@nxp.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
-+X: drivers/media/i2c/
-+N: imx
-+N: mxs
-+
-+ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
-+M: Shawn Guo <shawnguo@kernel.org>
-+M: Li Yang <leoyang.li@nxp.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
-+F: arch/arm/boot/dts/ls1021a*
-+F: arch/arm64/boot/dts/freescale/fsl-*
-+F: arch/arm64/boot/dts/freescale/qoriq-*
-+
-+ARM/FREESCALE VYBRID ARM ARCHITECTURE
-+M: Shawn Guo <shawnguo@kernel.org>
-+M: Sascha Hauer <s.hauer@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+R: Stefan Agner <stefan@agner.ch>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
-+F: arch/arm/boot/dts/vf*
-+F: arch/arm/mach-imx/*vf610*
-+
-+ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/GUMSTIX MACHINE SUPPORT
-+M: Steve Sakoman <sakoman@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT
-+M: Philipp Zabel <philipp.zabel@gmail.com>
-+M: Paul Parsons <lost.distance@yahoo.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/hx4700.c
-+F: arch/arm/mach-pxa/include/mach/hx4700.h
-+F: sound/soc/pxa/hx4700.c
-+
-+ARM/HISILICON SOC SUPPORT
-+M: Wei Xu <xuwei5@hisilicon.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+W: http://www.hisilicon.com
-+T: git git://github.com/hisilicon/linux-hisi.git
-+F: arch/arm/boot/dts/hi3*
-+F: arch/arm/boot/dts/hip*
-+F: arch/arm/boot/dts/hisi*
-+F: arch/arm/mach-hisi/
-+F: arch/arm64/boot/dts/hisilicon/
-+
-+ARM/HP JORNADA 7XX MACHINE SUPPORT
-+M: Kristoffer Ericson <kristoffer.ericson@gmail.com>
-+S: Maintained
-+W: www.jlime.com
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
-+F: arch/arm/mach-sa1100/include/mach/jornada720.h
-+F: arch/arm/mach-sa1100/jornada720.c
-+
-+ARM/IGEP MACHINE SUPPORT
-+M: Enric Balletbo i Serra <eballetbo@gmail.com>
-+M: Javier Martinez Canillas <javier@dowhile0.org>
-+L: linux-omap@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/omap3-igep*
-+
-+ARM/INCOME PXA270 SUPPORT
-+M: Marek Vasut <marek.vasut@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/colibri-pxa270-income.c
-+
-+ARM/INTEL IOP32X ARM ARCHITECTURE
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/INTEL IQ81342EX MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/INTEL IXDP2850 MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/INTEL IXP4XX ARM ARCHITECTURE
-+M: Linus Walleij <linusw@kernel.org>
-+M: Imre Kaloz <kaloz@openwrt.org>
-+M: Krzysztof Halasa <khalasa@piap.pl>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
-+F: Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml
-+F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
-+F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
-+F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
-+F: arch/arm/mach-ixp4xx/
-+F: drivers/bus/intel-ixp4xx-eb.c
-+F: drivers/clocksource/timer-ixp4xx.c
-+F: drivers/crypto/ixp4xx_crypto.c
-+F: drivers/gpio/gpio-ixp4xx.c
-+F: drivers/irqchip/irq-ixp4xx.c
-+F: include/linux/irqchip/irq-ixp4xx.h
-+F: include/linux/platform_data/timer-ixp4xx.h
-+
-+ARM/INTEL KEEMBAY ARCHITECTURE
-+M: Paul J. Murphy <paul.j.murphy@intel.com>
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/intel,keembay.yaml
-+F: arch/arm64/boot/dts/intel/keembay-evm.dts
-+F: arch/arm64/boot/dts/intel/keembay-soc.dtsi
-+
-+ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
-+M: Jonathan Cameron <jic23@cam.ac.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/stargate2.c
-+F: drivers/pcmcia/pxa2xx_stargate2.c
-+
-+ARM/INTEL XSC3 (MANZANO) ARM CORE
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/LG1K ARCHITECTURE
-+M: Chanho Min <chanho.min@lge.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm64/boot/dts/lg/
-+
-+ARM/LOGICPD PXA270 MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/LPC18XX ARCHITECTURE
-+M: Vladimir Zapolskiy <vz@mleia.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt
-+F: arch/arm/boot/dts/lpc43*
-+F: drivers/i2c/busses/i2c-lpc2k.c
-+F: drivers/memory/pl172.c
-+F: drivers/mtd/spi-nor/controllers/nxp-spifi.c
-+F: drivers/rtc/rtc-lpc24xx.c
-+N: lpc18xx
-+
-+ARM/LPC32XX SOC SUPPORT
-+M: Vladimir Zapolskiy <vz@mleia.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/vzapolskiy/linux-lpc32xx.git
-+F: Documentation/devicetree/bindings/i2c/i2c-pnx.txt
-+F: arch/arm/boot/dts/lpc32*
-+F: arch/arm/mach-lpc32xx/
-+F: drivers/i2c/busses/i2c-pnx.c
-+F: drivers/net/ethernet/nxp/lpc_eth.c
-+F: drivers/usb/host/ohci-nxp.c
-+F: drivers/watchdog/pnx4008_wdt.c
-+N: lpc32xx
-+
-+ARM/MAGICIAN MACHINE SUPPORT
-+M: Philipp Zabel <philipp.zabel@gmail.com>
-+S: Maintained
-+
-+ARM/Marvell Dove/MV78xx0/Orion SOC support
-+M: Andrew Lunn <andrew@lunn.ch>
-+M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
-+M: Gregory Clement <gregory.clement@bootlin.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git
-+F: Documentation/devicetree/bindings/soc/dove/
-+F: arch/arm/boot/dts/dove*
-+F: arch/arm/boot/dts/orion5x*
-+F: arch/arm/mach-dove/
-+F: arch/arm/mach-mv78xx0/
-+F: arch/arm/mach-orion5x/
-+F: arch/arm/plat-orion/
-+F: drivers/soc/dove/
-+
-+ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K, CN9130 SOC support
-+M: Andrew Lunn <andrew@lunn.ch>
-+M: Gregory Clement <gregory.clement@bootlin.com>
-+M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git
-+F: arch/arm/boot/dts/armada*
-+F: arch/arm/boot/dts/kirkwood*
-+F: arch/arm/configs/mvebu_*_defconfig
-+F: arch/arm/mach-mvebu/
-+F: arch/arm64/boot/dts/marvell/armada*
-+F: arch/arm64/boot/dts/marvell/cn913*
-+F: drivers/cpufreq/armada-37xx-cpufreq.c
-+F: drivers/cpufreq/armada-8k-cpufreq.c
-+F: drivers/cpufreq/mvebu-cpufreq.c
-+F: drivers/irqchip/irq-armada-370-xp.c
-+F: drivers/irqchip/irq-mvebu-*
-+F: drivers/pinctrl/mvebu/
-+F: drivers/rtc/rtc-armada38x.c
-+
-+ARM/Mediatek RTC DRIVER
-+M: Eddie Huang <eddie.huang@mediatek.com>
-+M: Sean Wang <sean.wang@mediatek.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/rtc/rtc-mt2712.txt
-+F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
-+F: drivers/rtc/rtc-mt2712.c
-+F: drivers/rtc/rtc-mt6397.c
-+F: drivers/rtc/rtc-mt7622.c
-+
-+ARM/Mediatek SoC support
-+M: Matthias Brugger <matthias.bgg@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: https://mtk.wiki.kernel.org/
-+C: irc://chat.freenode.net/linux-mediatek
-+F: arch/arm/boot/dts/mt6*
-+F: arch/arm/boot/dts/mt7*
-+F: arch/arm/boot/dts/mt8*
-+F: arch/arm/mach-mediatek/
-+F: arch/arm64/boot/dts/mediatek/
-+F: drivers/soc/mediatek/
-+N: mtk
-+N: mt[678]
-+K: mediatek
-+
-+ARM/Mediatek USB3 PHY DRIVER
-+M: Chunfeng Yun <chunfeng.yun@mediatek.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/mediatek,*
-+F: drivers/phy/mediatek/
-+
-+ARM/Microchip (AT91) SoC support
-+M: Nicolas Ferre <nicolas.ferre@microchip.com>
-+M: Alexandre Belloni <alexandre.belloni@bootlin.com>
-+M: Ludovic Desroches <ludovic.desroches@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+W: http://www.linux4sam.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git
-+F: arch/arm/boot/dts/at91*.dts
-+F: arch/arm/boot/dts/at91*.dtsi
-+F: arch/arm/boot/dts/sama*.dts
-+F: arch/arm/boot/dts/sama*.dtsi
-+F: arch/arm/include/debug/at91.S
-+F: arch/arm/mach-at91/
-+F: drivers/memory/atmel*
-+F: drivers/watchdog/sama5d4_wdt.c
-+F: include/soc/at91/
-+X: drivers/input/touchscreen/atmel_mxt_ts.c
-+X: drivers/net/wireless/atmel/
-+N: at91
-+N: atmel
-+
-+ARM/Microchip Sparx5 SoC support
-+M: Lars Povlsen <lars.povlsen@microchip.com>
-+M: Steen Hegelund <Steen.Hegelund@microchip.com>
-+M: UNGLinuxDriver@microchip.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://github.com/microchip-ung/linux-upstream.git
-+F: arch/arm64/boot/dts/microchip/
-+F: drivers/pinctrl/pinctrl-microchip-sgpio.c
-+N: sparx5
-+
-+Microchip Timer Counter Block (TCB) Capture Driver
-+M: Kamel Bouhara <kamel.bouhara@bootlin.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/counter/microchip-tcb-capture.c
-+
-+ARM/MIOA701 MACHINE SUPPORT
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/mioa701.c
-+
-+ARM/MStar/Sigmastar Armv7 SoC support
-+M: Daniel Palmer <daniel@thingy.jp>
-+M: Romain Perier <romain.perier@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://linux-chenxing.org/
-+T: git git://github.com/linux-chenxing/linux.git
-+F: Documentation/devicetree/bindings/arm/mstar/*
-+F: Documentation/devicetree/bindings/clock/mstar,msc313-mpll.yaml
-+F: Documentation/devicetree/bindings/gpio/mstar,msc313-gpio.yaml
-+F: arch/arm/boot/dts/mstar-*
-+F: arch/arm/mach-mstar/
-+F: drivers/clk/mstar/
-+F: drivers/gpio/gpio-msc313.c
-+F: drivers/watchdog/msc313e_wdt.c
-+F: include/dt-bindings/clock/mstar-*
-+F: include/dt-bindings/gpio/msc313-gpio.h
-+
-+ARM/NEC MOBILEPRO 900/c MACHINE SUPPORT
-+M: Michael Petchkovsky <mkpetch@internode.on.net>
-+S: Maintained
-+
-+ARM/NOMADIK/Ux500 ARCHITECTURES
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
-+F: Documentation/devicetree/bindings/arm/ste-*
-+F: Documentation/devicetree/bindings/arm/ux500.yaml
-+F: Documentation/devicetree/bindings/arm/ux500/
-+F: Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
-+F: arch/arm/boot/dts/ste-*
-+F: arch/arm/mach-nomadik/
-+F: arch/arm/mach-ux500/
-+F: drivers/clk/clk-nomadik.c
-+F: drivers/clocksource/clksrc-dbx500-prcmu.c
-+F: drivers/dma/ste_dma40*
-+F: drivers/hwspinlock/u8500_hsem.c
-+F: drivers/i2c/busses/i2c-nomadik.c
-+F: drivers/iio/adc/ab8500-gpadc.c
-+F: drivers/mfd/ab8500*
-+F: drivers/mfd/abx500*
-+F: drivers/mfd/db8500*
-+F: drivers/pinctrl/nomadik/
-+F: drivers/rtc/rtc-ab8500.c
-+F: drivers/rtc/rtc-pl031.c
-+F: drivers/soc/ux500/
-+
-+ARM/NUVOTON NPCM ARCHITECTURE
-+M: Avi Fishman <avifishman70@gmail.com>
-+M: Tomer Maimon <tmaimon77@gmail.com>
-+M: Tali Perry <tali.perry1@gmail.com>
-+R: Patrick Venture <venture@google.com>
-+R: Nancy Yuen <yuenn@google.com>
-+R: Benjamin Fair <benjaminfair@google.com>
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/*/*/*npcm*
-+F: Documentation/devicetree/bindings/*/*npcm*
-+F: arch/arm/boot/dts/nuvoton-npcm*
-+F: arch/arm/mach-npcm/
-+F: drivers/*/*npcm*
-+F: drivers/*/*/*npcm*
-+F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
-+
-+ARM/NUVOTON WPCM450 ARCHITECTURE
-+M: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/*/*wpcm*
-+F: arch/arm/boot/dts/nuvoton-wpcm450*
-+F: arch/arm/mach-npcm/wpcm450.c
-+F: drivers/*/*wpcm*
-+
-+ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
-+L: openmoko-kernel@lists.openmoko.org (subscribers-only)
-+S: Orphan
-+W: http://wiki.openmoko.org/wiki/Neo_FreeRunner
-+F: arch/arm/mach-s3c/gta02.h
-+F: arch/arm/mach-s3c/mach-gta02.c
-+
-+ARM/Orion SoC/Technologic Systems TS-78xx platform support
-+M: Alexander Clouter <alex@digriz.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.digriz.org.uk/ts78xx/kernel
-+F: arch/arm/mach-orion5x/ts78xx-*
-+
-+ARM/OXNAS platform support
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-oxnas@groups.io (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/ox8*.dts*
-+F: arch/arm/mach-oxnas/
-+F: drivers/power/reset/oxnas-restart.c
-+N: oxnas
-+
-+ARM/PALM TREO SUPPORT
-+M: Tomas Cech <sleep_walker@suse.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://hackndev.com
-+F: arch/arm/mach-pxa/palmtreo.*
-+
-+ARM/PALMTX,PALMT5,PALMLD,PALMTE2,PALMTC SUPPORT
-+M: Marek Vasut <marek.vasut@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://hackndev.com
-+F: arch/arm/mach-pxa/include/mach/palmld.h
-+F: arch/arm/mach-pxa/include/mach/palmtc.h
-+F: arch/arm/mach-pxa/include/mach/palmtx.h
-+F: arch/arm/mach-pxa/palmld.c
-+F: arch/arm/mach-pxa/palmt5.*
-+F: arch/arm/mach-pxa/palmtc.c
-+F: arch/arm/mach-pxa/palmte2.*
-+F: arch/arm/mach-pxa/palmtx.c
-+
-+ARM/PALMZ72 SUPPORT
-+M: Sergey Lapin <slapin@ossfans.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://hackndev.com
-+F: arch/arm/mach-pxa/palmz72.*
-+
-+ARM/PLEB SUPPORT
-+M: Peter Chubb <pleb@gelato.unsw.edu.au>
-+S: Maintained
-+W: http://www.disy.cse.unsw.edu.au/Hardware/PLEB
-+
-+ARM/PT DIGITAL BOARD PORT
-+M: Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.armlinux.org.uk/
-+
-+ARM/QUALCOMM SUPPORT
-+M: Andy Gross <agross@kernel.org>
-+M: Bjorn Andersson <bjorn.andersson@linaro.org>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
-+F: Documentation/devicetree/bindings/*/qcom*
-+F: Documentation/devicetree/bindings/soc/qcom/
-+F: arch/arm/boot/dts/qcom-*.dts
-+F: arch/arm/boot/dts/qcom-*.dtsi
-+F: arch/arm/mach-qcom/
-+F: arch/arm64/boot/dts/qcom/
-+F: drivers/*/*/qcom*
-+F: drivers/*/*/qcom/
-+F: drivers/*/pm8???-*
-+F: drivers/*/qcom*
-+F: drivers/*/qcom/
-+F: drivers/bluetooth/btqcomsmd.c
-+F: drivers/clocksource/timer-qcom.c
-+F: drivers/cpuidle/cpuidle-qcom-spm.c
-+F: drivers/extcon/extcon-qcom*
-+F: drivers/i2c/busses/i2c-qcom-geni.c
-+F: drivers/i2c/busses/i2c-qup.c
-+F: drivers/iommu/msm*
-+F: drivers/mfd/ssbi.c
-+F: drivers/mmc/host/mmci_qcom*
-+F: drivers/mmc/host/sdhci-msm.c
-+F: drivers/pci/controller/dwc/pcie-qcom.c
-+F: drivers/phy/qualcomm/
-+F: drivers/power/*/msm*
-+F: drivers/reset/reset-qcom-*
-+F: drivers/scsi/ufs/ufs-qcom*
-+F: drivers/spi/spi-geni-qcom.c
-+F: drivers/spi/spi-qcom-qspi.c
-+F: drivers/spi/spi-qup.c
-+F: drivers/tty/serial/msm_serial.c
-+F: drivers/usb/dwc3/dwc3-qcom.c
-+F: include/dt-bindings/*/qcom*
-+F: include/linux/*/qcom*
-+F: include/linux/soc/qcom/
-+
-+ARM/RADISYS ENP2611 MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/RDA MICRO ARCHITECTURE
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-unisoc@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/rda.yaml
-+F: Documentation/devicetree/bindings/gpio/gpio-rda.yaml
-+F: Documentation/devicetree/bindings/interrupt-controller/rda,8810pl-intc.txt
-+F: Documentation/devicetree/bindings/serial/rda,8810pl-uart.txt
-+F: Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt
-+F: arch/arm/boot/dts/rda8810pl-*
-+F: drivers/clocksource/timer-rda.c
-+F: drivers/gpio/gpio-rda.c
-+F: drivers/irqchip/irq-rda-intc.c
-+F: drivers/tty/serial/rda-uart.c
-+
-+ARM/REALTEK ARCHITECTURE
-+M: Andreas Färber <afaerber@suse.de>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/realtek.yaml
-+F: arch/arm/boot/dts/rtd*
-+F: arch/arm/mach-realtek/
-+F: arch/arm64/boot/dts/realtek/
-+
-+ARM/RENESAS ARM64 ARCHITECTURE
-+M: Geert Uytterhoeven <geert+renesas@glider.be>
-+M: Magnus Damm <magnus.damm@gmail.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
-+F: Documentation/devicetree/bindings/arm/renesas.yaml
-+F: arch/arm64/boot/dts/renesas/
-+F: drivers/soc/renesas/
-+F: include/linux/soc/renesas/
-+
-+ARM/RISCPC ARCHITECTURE
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.armlinux.org.uk/
-+F: arch/arm/include/asm/hardware/entry-macro-iomd.S
-+F: arch/arm/include/asm/hardware/ioc.h
-+F: arch/arm/include/asm/hardware/iomd.h
-+F: arch/arm/include/asm/hardware/memc.h
-+F: arch/arm/mach-rpc/
-+F: drivers/net/ethernet/8390/etherh.c
-+F: drivers/net/ethernet/i825xx/ether1*
-+F: drivers/net/ethernet/seeq/ether3*
-+F: drivers/scsi/arm/
-+
-+ARM/Rockchip SoC support
-+M: Heiko Stuebner <heiko@sntech.de>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git
-+F: Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
-+F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
-+F: Documentation/devicetree/bindings/spi/spi-rockchip.yaml
-+F: arch/arm/boot/dts/rk3*
-+F: arch/arm/boot/dts/rv1108*
-+F: arch/arm/mach-rockchip/
-+F: drivers/*/*/*rockchip*
-+F: drivers/*/*rockchip*
-+F: drivers/clk/rockchip/
-+F: drivers/i2c/busses/i2c-rk3x.c
-+F: sound/soc/rockchip/
-+N: rockchip
-+
-+ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/
-+F: Documentation/arm/samsung/
-+F: Documentation/devicetree/bindings/arm/samsung/
-+F: Documentation/devicetree/bindings/power/pd-samsung.yaml
-+F: arch/arm/boot/dts/exynos*
-+F: arch/arm/boot/dts/s3c*
-+F: arch/arm/boot/dts/s5p*
-+F: arch/arm/mach-exynos*/
-+F: arch/arm/mach-s3c/
-+F: arch/arm/mach-s5p*/
-+F: arch/arm64/boot/dts/exynos/
-+F: drivers/*/*/*s3c24*
-+F: drivers/*/*s3c24*
-+F: drivers/*/*s3c64xx*
-+F: drivers/*/*s5pv210*
-+F: drivers/clocksource/samsung_pwm_timer.c
-+F: drivers/memory/samsung/
-+F: drivers/pwm/pwm-samsung.c
-+F: drivers/soc/samsung/
-+F: drivers/tty/serial/samsung*
-+F: include/clocksource/samsung_pwm.h
-+F: include/linux/platform_data/*s3c*
-+F: include/linux/serial_s3c.h
-+F: include/linux/soc/samsung/
-+N: exynos
-+N: s3c2410
-+N: s3c64xx
-+N: s5pv210
-+
-+ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
-+M: Andrzej Hajda <a.hajda@samsung.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/s5p-g2d/
-+
-+ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
-+M: Marek Szyprowski <m.szyprowski@samsung.com>
-+L: linux-samsung-soc@vger.kernel.org
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/s5p-cec.txt
-+F: drivers/media/cec/platform/s5p/
-+
-+ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
-+M: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
-+M: Jacek Anaszewski <jacek.anaszewski@gmail.com>
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/s5p-jpeg/
-+
-+ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
-+M: Andrzej Hajda <a.hajda@samsung.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/s5p-mfc/
-+
-+ARM/SHMOBILE ARM ARCHITECTURE
-+M: Geert Uytterhoeven <geert+renesas@glider.be>
-+M: Magnus Damm <magnus.damm@gmail.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
-+F: Documentation/devicetree/bindings/arm/renesas.yaml
-+F: arch/arm/boot/dts/emev2*
-+F: arch/arm/boot/dts/gr-peach*
-+F: arch/arm/boot/dts/iwg20d-q7*
-+F: arch/arm/boot/dts/r7s*
-+F: arch/arm/boot/dts/r8a*
-+F: arch/arm/boot/dts/r9a*
-+F: arch/arm/boot/dts/sh*
-+F: arch/arm/configs/shmobile_defconfig
-+F: arch/arm/include/debug/renesas-scif.S
-+F: arch/arm/mach-shmobile/
-+F: drivers/soc/renesas/
-+F: include/linux/soc/renesas/
-+
-+ARM/SOCFPGA ARCHITECTURE
-+M: Dinh Nguyen <dinguyen@kernel.org>
-+S: Maintained
-+W: http://www.rocketboards.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
-+F: arch/arm/boot/dts/socfpga*
-+F: arch/arm/configs/socfpga_defconfig
-+F: arch/arm/mach-socfpga/
-+F: arch/arm64/boot/dts/altera/
-+F: arch/arm64/boot/dts/intel/
-+
-+ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
-+M: Dinh Nguyen <dinguyen@kernel.org>
-+S: Maintained
-+F: drivers/clk/socfpga/
-+
-+ARM/SOCFPGA EDAC SUPPORT
-+M: Dinh Nguyen <dinguyen@kernel.org>
-+S: Maintained
-+F: drivers/edac/altera_edac.[ch]
-+
-+ARM/SPREADTRUM SoC SUPPORT
-+M: Orson Zhai <orsonzhai@gmail.com>
-+M: Baolin Wang <baolin.wang7@gmail.com>
-+M: Chunyan Zhang <zhang.lyra@gmail.com>
-+S: Maintained
-+F: arch/arm64/boot/dts/sprd
-+N: sprd
-+N: sc27xx
-+N: sc2731
-+
-+ARM/STI ARCHITECTURE
-+M: Patrice Chotard <patrice.chotard@foss.st.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.stlinux.com
-+F: Documentation/devicetree/bindings/i2c/i2c-st.txt
-+F: arch/arm/boot/dts/sti*
-+F: arch/arm/mach-sti/
-+F: drivers/ata/ahci_st.c
-+F: drivers/char/hw_random/st-rng.c
-+F: drivers/clocksource/arm_global_timer.c
-+F: drivers/clocksource/clksrc_st_lpc.c
-+F: drivers/cpufreq/sti-cpufreq.c
-+F: drivers/dma/st_fdma*
-+F: drivers/i2c/busses/i2c-st.c
-+F: drivers/media/platform/sti/c8sectpfe/
-+F: drivers/media/rc/st_rc.c
-+F: drivers/mmc/host/sdhci-st.c
-+F: drivers/phy/st/phy-miphy28lp.c
-+F: drivers/phy/st/phy-stih407-usb.c
-+F: drivers/pinctrl/pinctrl-st.c
-+F: drivers/remoteproc/st_remoteproc.c
-+F: drivers/remoteproc/st_slim_rproc.c
-+F: drivers/reset/sti/
-+F: drivers/rtc/rtc-st-lpc.c
-+F: drivers/tty/serial/st-asc.c
-+F: drivers/usb/dwc3/dwc3-st.c
-+F: drivers/usb/host/ehci-st.c
-+F: drivers/usb/host/ohci-st.c
-+F: drivers/watchdog/st_lpc_wdt.c
-+F: include/linux/remoteproc/st_slim_rproc.h
-+
-+ARM/STM32 ARCHITECTURE
-+M: Maxime Coquelin <mcoquelin.stm32@gmail.com>
-+M: Alexandre Torgue <alexandre.torgue@foss.st.com>
-+L: linux-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/atorgue/stm32.git stm32-next
-+F: arch/arm/boot/dts/stm32*
-+F: arch/arm/mach-stm32/
-+F: drivers/clocksource/armv7m_systick.c
-+N: stm32
-+N: stm
-+
-+ARM/Synaptics SoC support
-+M: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
-+M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/berlin*
-+F: arch/arm/mach-berlin/
-+F: arch/arm64/boot/dts/synaptics/
-+
-+ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-tegra@vger.kernel.org
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/tegra-cec.txt
-+F: drivers/media/cec/platform/tegra/
-+
-+ARM/TETON BGA MACHINE SUPPORT
-+M: "Mark F. Brown" <mark.brown314@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/TEXAS INSTRUMENT AEMIF/EMIF DRIVERS
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/memory/*emif*
-+
-+ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
-+F: arch/arm/boot/dts/keystone-*
-+F: arch/arm/mach-keystone/
-+
-+ARM/TEXAS INSTRUMENT KEYSTONE CLOCK FRAMEWORK
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/clk/keystone/
-+
-+ARM/TEXAS INSTRUMENT KEYSTONE CLOCKSOURCE
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/clocksource/timer-keystone.c
-+
-+ARM/TEXAS INSTRUMENT KEYSTONE RESET DRIVER
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/power/reset/keystone-reset.c
-+
-+ARM/TEXAS INSTRUMENTS K3 ARCHITECTURE
-+M: Nishanth Menon <nm@ti.com>
-+M: Vignesh Raghavendra <vigneshr@ti.com>
-+M: Tero Kristo <kristo@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/arm/ti/k3.yaml
-+F: arch/arm64/boot/dts/ti/Makefile
-+F: arch/arm64/boot/dts/ti/k3-*
-+F: include/dt-bindings/pinctrl/k3.h
-+
-+ARM/THECUS N2100 MACHINE SUPPORT
-+M: Lennert Buytenhek <kernel@wantstofly.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+
-+ARM/TOSA MACHINE SUPPORT
-+M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-+M: Dirk Opfer <dirk@opfer-online.de>
-+S: Maintained
-+
-+ARM/TOSHIBA VISCONTI ARCHITECTURE
-+M: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwamatsu/linux-visconti.git
-+F: Documentation/devicetree/bindings/arm/toshiba.yaml
-+F: Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
-+F: Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
-+F: Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
-+F: Documentation/devicetree/bindings/pinctrl/toshiba,tmpv7700-pinctrl.yaml
-+F: Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
-+F: arch/arm64/boot/dts/toshiba/
-+F: drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
-+F: drivers/gpio/gpio-visconti.c
-+F: drivers/pci/controller/dwc/pcie-visconti.c
-+F: drivers/pinctrl/visconti/
-+F: drivers/watchdog/visconti_wdt.c
-+N: visconti
-+
-+ARM/UNIPHIER ARCHITECTURE
-+M: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
-+M: Masami Hiramatsu <mhiramat@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
-+F: Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml
-+F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml
-+F: arch/arm/boot/dts/uniphier*
-+F: arch/arm/include/asm/hardware/cache-uniphier.h
-+F: arch/arm/mach-uniphier/
-+F: arch/arm/mm/cache-uniphier.c
-+F: arch/arm64/boot/dts/socionext/uniphier*
-+F: drivers/bus/uniphier-system-bus.c
-+F: drivers/clk/uniphier/
-+F: drivers/dma/uniphier-mdmac.c
-+F: drivers/gpio/gpio-uniphier.c
-+F: drivers/i2c/busses/i2c-uniphier*
-+F: drivers/irqchip/irq-uniphier-aidet.c
-+F: drivers/mmc/host/uniphier-sd.c
-+F: drivers/pinctrl/uniphier/
-+F: drivers/reset/reset-uniphier.c
-+F: drivers/tty/serial/8250/8250_uniphier.c
-+N: uniphier
-+
-+ARM/VERSATILE EXPRESS PLATFORM
-+M: Liviu Dudau <liviu.dudau@arm.com>
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: */*/*/vexpress*
-+F: */*/vexpress*
-+F: arch/arm/boot/dts/vexpress*
-+F: arch/arm/mach-vexpress/
-+F: arch/arm64/boot/dts/arm/
-+F: drivers/clk/versatile/clk-vexpress-osc.c
-+F: drivers/clocksource/timer-versatile.c
-+N: mps2
-+
-+ARM/VFP SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.armlinux.org.uk/
-+F: arch/arm/vfp/
-+
-+ARM/VOIPAC PXA270 SUPPORT
-+M: Marek Vasut <marek.vasut@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/include/mach/vpac270.h
-+F: arch/arm/mach-pxa/vpac270.c
-+
-+ARM/VT8500 ARM ARCHITECTURE
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Orphan
-+F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt
-+F: arch/arm/mach-vt8500/
-+F: drivers/clocksource/timer-vt8500.c
-+F: drivers/i2c/busses/i2c-wmt.c
-+F: drivers/mmc/host/wmt-sdmmc.c
-+F: drivers/pwm/pwm-vt8500.c
-+F: drivers/rtc/rtc-vt8500.c
-+F: drivers/tty/serial/vt8500_serial.c
-+F: drivers/usb/host/ehci-platform.c
-+F: drivers/usb/host/uhci-platform.c
-+F: drivers/video/fbdev/vt8500lcdfb.*
-+F: drivers/video/fbdev/wm8505fb*
-+F: drivers/video/fbdev/wmt_ge_rops.*
-+
-+ARM/ZIPIT Z2 SUPPORT
-+M: Marek Vasut <marek.vasut@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/mach-pxa/include/mach/z2.h
-+F: arch/arm/mach-pxa/z2.c
-+
-+ARM/ZYNQ ARCHITECTURE
-+M: Michal Simek <michal.simek@xilinx.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+W: http://wiki.xilinx.com
-+T: git https://github.com/Xilinx/linux-xlnx.git
-+F: Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
-+F: Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
-+F: Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml
-+F: arch/arm/mach-zynq/
-+F: drivers/clocksource/timer-cadence-ttc.c
-+F: drivers/cpuidle/cpuidle-zynq.c
-+F: drivers/edac/synopsys_edac.c
-+F: drivers/i2c/busses/i2c-cadence.c
-+F: drivers/i2c/busses/i2c-xiic.c
-+F: drivers/mmc/host/sdhci-of-arasan.c
-+N: zynq
-+N: xilinx
-+
-+ARM64 PORT (AARCH64 ARCHITECTURE)
-+M: Catalin Marinas <catalin.marinas@arm.com>
-+M: Will Deacon <will@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
-+F: Documentation/arm64/
-+F: arch/arm64/
-+F: tools/testing/selftests/arm64/
-+X: arch/arm64/boot/dts/
-+
-+ARROW SPEEDCHIPS XRS7000 SERIES ETHERNET SWITCH DRIVER
-+M: George McCollister <george.mccollister@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/arrow,xrs700x.yaml
-+F: drivers/net/dsa/xrs700x/*
-+F: net/dsa/tag_xrs700x.c
-+
-+AS3645A LED FLASH CONTROLLER DRIVER
-+M: Sakari Ailus <sakari.ailus@iki.fi>
-+L: linux-leds@vger.kernel.org
-+S: Maintained
-+F: drivers/leds/flash/leds-as3645a.c
-+
-+ASAHI KASEI AK7375 LENS VOICE COIL DRIVER
-+M: Tianshu Qiu <tian.shu.qiu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ak7375.txt
-+F: drivers/media/i2c/ak7375.c
-+
-+ASAHI KASEI AK8974 DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://www.akm.com/
-+F: drivers/iio/magnetometer/ak8974.c
-+
-+ASC7621 HARDWARE MONITOR DRIVER
-+M: George Joseph <george.joseph@fairview5.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/asc7621.rst
-+F: drivers/hwmon/asc7621.c
-+
-+ASPEED PINCTRL DRIVERS
-+M: Andrew Jeffery <andrew@aj.id.au>
-+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pinctrl/aspeed,*
-+F: drivers/pinctrl/aspeed/
-+
-+ASPEED SCU INTERRUPT CONTROLLER DRIVER
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
-+F: drivers/irqchip/irq-aspeed-scu-ic.c
-+F: include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
-+
-+ASPEED SD/MMC DRIVER
-+M: Andrew Jeffery <andrew@aj.id.au>
-+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
-+F: drivers/mmc/host/sdhci-of-aspeed*
-+
-+ASPEED VIDEO ENGINE DRIVER
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-media@vger.kernel.org
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/aspeed-video.txt
-+F: drivers/media/platform/aspeed-video.c
-+
-+ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
-+M: Corentin Chary <corentin.chary@gmail.com>
-+L: acpi4asus-user@lists.sourceforge.net
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://acpi4asus.sf.net
-+F: drivers/platform/x86/asus*.c
-+F: drivers/platform/x86/eeepc*.c
-+
-+ASUS WIRELESS RADIO CONTROL DRIVER
-+M: João Paulo Rechi Vita <jprvita@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/asus-wireless.c
-+
-+ASYMMETRIC KEYS
-+M: David Howells <dhowells@redhat.com>
-+L: keyrings@vger.kernel.org
-+S: Maintained
-+F: Documentation/crypto/asymmetric-keys.rst
-+F: crypto/asymmetric_keys/
-+F: include/crypto/pkcs7.h
-+F: include/crypto/public_key.h
-+F: include/linux/verification.h
-+
-+ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
-+R: Dan Williams <dan.j.williams@intel.com>
-+S: Odd fixes
-+W: http://sourceforge.net/projects/xscaleiop
-+F: Documentation/crypto/async-tx-api.rst
-+F: crypto/async_tx/
-+F: include/linux/async_tx.h
-+
-+AT24 EEPROM DRIVER
-+M: Bartosz Golaszewski <brgl@bgdev.pl>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
-+F: Documentation/devicetree/bindings/eeprom/at24.yaml
-+F: drivers/misc/eeprom/at24.c
-+
-+ATA OVER ETHERNET (AOE) DRIVER
-+M: "Justin Sanders" <justin@coraid.com>
-+S: Supported
-+W: http://www.openaoe.org/
-+F: Documentation/admin-guide/aoe/
-+F: drivers/block/aoe/
-+
-+ATC260X PMIC MFD DRIVER
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+M: Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
-+L: linux-actions@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/actions,atc260x.yaml
-+F: drivers/input/misc/atc260x-onkey.c
-+F: drivers/mfd/atc260*
-+F: drivers/power/reset/atc260x-poweroff.c
-+F: drivers/regulator/atc260x-regulator.c
-+F: include/linux/mfd/atc260x/*
-+
-+ATHEROS 71XX/9XXX GPIO DRIVER
-+M: Alban Bedel <albeu@free.fr>
-+S: Maintained
-+W: https://github.com/AlbanBedel/linux
-+T: git git://github.com/AlbanBedel/linux
-+F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt
-+F: drivers/gpio/gpio-ath79.c
-+
-+ATHEROS 71XX/9XXX USB PHY DRIVER
-+M: Alban Bedel <albeu@free.fr>
-+S: Maintained
-+W: https://github.com/AlbanBedel/linux
-+T: git git://github.com/AlbanBedel/linux
-+F: Documentation/devicetree/bindings/phy/phy-ath79-usb.txt
-+F: drivers/phy/qualcomm/phy-ath79-usb.c
-+
-+ATHEROS ATH GENERIC UTILITIES
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+F: drivers/net/wireless/ath/*
-+
-+ATHEROS ATH5K WIRELESS DRIVER
-+M: Jiri Slaby <jirislaby@kernel.org>
-+M: Nick Kossifidis <mickflemm@gmail.com>
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/ath5k
-+F: drivers/net/wireless/ath/ath5k/
-+
-+ATHEROS ATH6KL WIRELESS DRIVER
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/ath6kl
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
-+F: drivers/net/wireless/ath/ath6kl/
-+
-+ATI_REMOTE2 DRIVER
-+M: Ville Syrjala <syrjala@sci.fi>
-+S: Maintained
-+F: drivers/input/misc/ati_remote2.c
-+
-+ATK0110 HWMON DRIVER
-+M: Luca Tettamanti <kronos.it@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/asus_atk0110.c
-+
-+ATLX ETHERNET DRIVERS
-+M: Chris Snook <chris.snook@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://sourceforge.net/projects/atl1
-+W: http://atl1.sourceforge.net
-+F: drivers/net/ethernet/atheros/
-+
-+ATM
-+M: Chas Williams <3chas3@gmail.com>
-+L: linux-atm-general@lists.sourceforge.net (moderated for non-subscribers)
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://linux-atm.sourceforge.net
-+F: drivers/atm/
-+F: include/linux/atm*
-+F: include/uapi/linux/atm*
-+
-+ATMEL MACB ETHERNET DRIVER
-+M: Nicolas Ferre <nicolas.ferre@microchip.com>
-+M: Claudiu Beznea <claudiu.beznea@microchip.com>
-+S: Supported
-+F: drivers/net/ethernet/cadence/
-+
-+ATMEL MAXTOUCH DRIVER
-+M: Nick Dyer <nick@shmanahar.org>
-+S: Maintained
-+T: git git://github.com/ndyer/linux.git
-+F: Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
-+F: drivers/input/touchscreen/atmel_mxt_ts.c
-+
-+ATMEL WIRELESS DRIVER
-+M: Simon Kelley <simon@thekelleys.org.uk>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: http://www.thekelleys.org.uk/atmel
-+W: http://atmelwlandriver.sourceforge.net/
-+F: drivers/net/wireless/atmel/atmel*
-+
-+ATOMIC INFRASTRUCTURE
-+M: Will Deacon <will@kernel.org>
-+M: Peter Zijlstra <peterz@infradead.org>
-+R: Boqun Feng <boqun.feng@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: arch/*/include/asm/atomic*.h
-+F: include/*/atomic*.h
-+F: include/linux/refcount.h
-+F: Documentation/atomic_*.txt
-+F: scripts/atomic/
-+
-+ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
-+M: Bradley Grove <linuxdrivers@attotech.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.attotech.com
-+F: drivers/scsi/esas2r
-+
-+ATUSB IEEE 802.15.4 RADIO DRIVER
-+M: Stefan Schmidt <stefan@datenfreihafen.org>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ieee802154/at86rf230.h
-+F: drivers/net/ieee802154/atusb.c
-+F: drivers/net/ieee802154/atusb.h
-+
-+AUDIT SUBSYSTEM
-+M: Paul Moore <paul@paul-moore.com>
-+M: Eric Paris <eparis@redhat.com>
-+L: linux-audit@redhat.com (moderated for non-subscribers)
-+S: Supported
-+W: https://github.com/linux-audit
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git
-+F: include/asm-generic/audit_*.h
-+F: include/linux/audit.h
-+F: include/uapi/linux/audit.h
-+F: kernel/audit*
-+F: lib/*audit.c
-+
-+AUXILIARY DISPLAY DRIVERS
-+M: Miguel Ojeda <ojeda@kernel.org>
-+S: Maintained
-+F: drivers/auxdisplay/
-+F: include/linux/cfag12864b.h
-+
-+AVIA HX711 ANALOG DIGITAL CONVERTER IIO DRIVER
-+M: Andreas Klinger <ak@it-klinger.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
-+F: drivers/iio/adc/hx711.c
-+
-+AX.25 NETWORK LAYER
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-ax25.org/
-+F: include/net/ax25.h
-+F: include/uapi/linux/ax25.h
-+F: net/ax25/
-+
-+AXENTIA ARM DEVICES
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/at91-linea.dtsi
-+F: arch/arm/boot/dts/at91-natte.dtsi
-+F: arch/arm/boot/dts/at91-nattis-2-natte-2.dts
-+F: arch/arm/boot/dts/at91-tse850-3.dts
-+
-+AXENTIA ASOC DRIVERS
-+M: Peter Rosin <peda@axentia.se>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/axentia,*
-+F: sound/soc/atmel/tse850-pcm5142.c
-+
-+AXI-FAN-CONTROL HARDWARE MONITOR DRIVER
-+M: Nuno Sá <nuno.sa@analog.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/hwmon/adi,axi-fan-control.yaml
-+F: drivers/hwmon/axi-fan-control.c
-+
-+AXXIA I2C CONTROLLER
-+M: Krzysztof Adamski <krzysztof.adamski@nokia.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-axxia.txt
-+F: drivers/i2c/busses/i2c-axxia.c
-+
-+AZ6007 DVB DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/az6007.c
-+
-+AZTECH FM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-aztech*
-+
-+B43 WIRELESS DRIVER
-+L: linux-wireless@vger.kernel.org
-+L: b43-dev@lists.infradead.org
-+S: Odd Fixes
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/b43
-+F: drivers/net/wireless/broadcom/b43/
-+
-+B43LEGACY WIRELESS DRIVER
-+M: Larry Finger <Larry.Finger@lwfinger.net>
-+L: linux-wireless@vger.kernel.org
-+L: b43-dev@lists.infradead.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/b43
-+F: drivers/net/wireless/broadcom/b43legacy/
-+
-+BACKLIGHT CLASS/SUBSYSTEM
-+M: Lee Jones <lee.jones@linaro.org>
-+M: Daniel Thompson <daniel.thompson@linaro.org>
-+M: Jingoo Han <jingoohan1@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight.git
-+F: Documentation/ABI/stable/sysfs-class-backlight
-+F: Documentation/ABI/testing/sysfs-class-backlight
-+F: Documentation/devicetree/bindings/leds/backlight
-+F: drivers/video/backlight/
-+F: include/linux/backlight.h
-+F: include/linux/pwm_backlight.h
-+
-+BATMAN ADVANCED
-+M: Marek Lindner <mareklindner@neomailbox.ch>
-+M: Simon Wunderlich <sw@simonwunderlich.de>
-+M: Antonio Quartulli <a@unstable.cc>
-+M: Sven Eckelmann <sven@narfation.org>
-+L: b.a.t.m.a.n@lists.open-mesh.org (moderated for non-subscribers)
-+S: Maintained
-+W: https://www.open-mesh.org/
-+Q: https://patchwork.open-mesh.org/project/batman/list/
-+B: https://www.open-mesh.org/projects/batman-adv/issues
-+C: ircs://irc.hackint.org/batadv
-+T: git https://git.open-mesh.org/linux-merge.git
-+F: Documentation/networking/batman-adv.rst
-+F: include/uapi/linux/batadv_packet.h
-+F: include/uapi/linux/batman_adv.h
-+F: net/batman-adv/
-+
-+BAYCOM/HDLCDRV DRIVERS FOR AX.25
-+M: Thomas Sailer <t.sailer@alumni.ethz.ch>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://www.baycom.org/~tom/ham/ham.html
-+F: drivers/net/hamradio/baycom*
-+
-+BCACHE (BLOCK LAYER CACHE)
-+M: Coly Li <colyli@suse.de>
-+M: Kent Overstreet <kent.overstreet@gmail.com>
-+L: linux-bcache@vger.kernel.org
-+S: Maintained
-+W: http://bcache.evilpiepirate.org
-+C: irc://irc.oftc.net/bcache
-+F: drivers/md/bcache/
-+
-+BDISP ST MEDIA DRIVER
-+M: Fabien Dessenne <fabien.dessenne@foss.st.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/platform/sti/bdisp
-+
-+BECKHOFF CX5020 ETHERCAT MASTER DRIVER
-+M: Dariusz Marcinkiewicz <reksio@newterm.pl>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/ec_bhf.c
-+
-+BEFS FILE SYSTEM
-+M: Luis de Bethencourt <luisbg@kernel.org>
-+M: Salah Triki <salah.triki@gmail.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/luisbg/linux-befs.git
-+F: Documentation/filesystems/befs.rst
-+F: fs/befs/
-+
-+BFQ I/O SCHEDULER
-+M: Paolo Valente <paolo.valente@linaro.org>
-+M: Jens Axboe <axboe@kernel.dk>
-+L: linux-block@vger.kernel.org
-+S: Maintained
-+F: Documentation/block/bfq-iosched.rst
-+F: block/bfq-*
-+
-+BFS FILE SYSTEM
-+M: "Tigran A. Aivazian" <aivazian.tigran@gmail.com>
-+S: Maintained
-+F: Documentation/filesystems/bfs.rst
-+F: fs/bfs/
-+F: include/uapi/linux/bfs_fs.h
-+
-+BITMAP API
-+M: Yury Norov <yury.norov@gmail.com>
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
-+S: Maintained
-+F: include/asm-generic/bitops/find.h
-+F: include/linux/bitmap.h
-+F: lib/bitmap.c
-+F: lib/find_bit.c
-+F: lib/find_bit_benchmark.c
-+F: lib/test_bitmap.c
-+F: tools/include/asm-generic/bitops/find.h
-+F: tools/include/linux/bitmap.h
-+F: tools/lib/bitmap.c
-+F: tools/lib/find_bit.c
-+
-+BLINKM RGB LED DRIVER
-+M: Jan-Simon Moeller <jansimon.moeller@gmx.de>
-+S: Maintained
-+F: drivers/leds/leds-blinkm.c
-+
-+BLOCK LAYER
-+M: Jens Axboe <axboe@kernel.dk>
-+L: linux-block@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
-+F: block/
-+F: drivers/block/
-+F: include/linux/blk*
-+F: kernel/trace/blktrace.c
-+F: lib/sbitmap.c
-+
-+BLOCK2MTD DRIVER
-+M: Joern Engel <joern@lazybastard.org>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: drivers/mtd/devices/block2mtd.c
-+
-+BLUETOOTH DRIVERS
-+M: Marcel Holtmann <marcel@holtmann.org>
-+M: Johan Hedberg <johan.hedberg@gmail.com>
-+M: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
-+L: linux-bluetooth@vger.kernel.org
-+S: Supported
-+W: http://www.bluez.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
-+F: drivers/bluetooth/
-+
-+BLUETOOTH SUBSYSTEM
-+M: Marcel Holtmann <marcel@holtmann.org>
-+M: Johan Hedberg <johan.hedberg@gmail.com>
-+M: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
-+L: linux-bluetooth@vger.kernel.org
-+S: Supported
-+W: http://www.bluez.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
-+F: include/net/bluetooth/
-+F: net/bluetooth/
-+
-+BONDING DRIVER
-+M: Jay Vosburgh <j.vosburgh@gmail.com>
-+M: Veaceslav Falico <vfalico@gmail.com>
-+M: Andy Gospodarek <andy@greyhouse.net>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://sourceforge.net/projects/bonding/
-+F: drivers/net/bonding/
-+F: include/net/bonding.h
-+F: include/uapi/linux/if_bonding.h
-+
-+BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
-+M: Dan Robertson <dan@dlrobertson.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
-+F: drivers/iio/accel/bma400*
-+
-+BPF (Safe dynamic programs and tools)
-+M: Alexei Starovoitov <ast@kernel.org>
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+M: Andrii Nakryiko <andrii@kernel.org>
-+R: Martin KaFai Lau <kafai@fb.com>
-+R: Song Liu <songliubraving@fb.com>
-+R: Yonghong Song <yhs@fb.com>
-+R: John Fastabend <john.fastabend@gmail.com>
-+R: KP Singh <kpsingh@kernel.org>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Supported
-+W: https://bpf.io/
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/?delegate=121173
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
-+F: Documentation/bpf/
-+F: Documentation/networking/filter.rst
-+F: Documentation/userspace-api/ebpf/
-+F: arch/*/net/*
-+F: include/linux/bpf*
-+F: include/linux/btf*
-+F: include/linux/filter.h
-+F: include/trace/events/xdp.h
-+F: include/uapi/linux/bpf*
-+F: include/uapi/linux/btf*
-+F: include/uapi/linux/filter.h
-+F: kernel/bpf/
-+F: kernel/trace/bpf_trace.c
-+F: lib/test_bpf.c
-+F: net/bpf/
-+F: net/core/filter.c
-+F: net/sched/act_bpf.c
-+F: net/sched/cls_bpf.c
-+F: samples/bpf/
-+F: scripts/bpf_doc.py
-+F: tools/bpf/
-+F: tools/lib/bpf/
-+F: tools/testing/selftests/bpf/
-+N: bpf
-+K: bpf
-+
-+BPF JIT for ARM
-+M: Shubham Bansal <illusionist.neo@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/arm/net/
-+
-+BPF JIT for ARM64
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+M: Alexei Starovoitov <ast@kernel.org>
-+M: Zi Shen Lim <zlim.lnx@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Supported
-+F: arch/arm64/net/
-+
-+BPF JIT for MIPS (32-BIT AND 64-BIT)
-+M: Paul Burton <paulburton@kernel.org>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/mips/net/
-+
-+BPF JIT for NFP NICs
-+M: Jakub Kicinski <kuba@kernel.org>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/netronome/nfp/bpf/
-+
-+BPF JIT for POWERPC (32-BIT AND 64-BIT)
-+M: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/powerpc/net/
-+
-+BPF JIT for RISC-V (32-bit)
-+M: Luke Nelson <luke.r.nels@gmail.com>
-+M: Xi Wang <xi.wang@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/riscv/net/
-+X: arch/riscv/net/bpf_jit_comp64.c
-+
-+BPF JIT for RISC-V (64-bit)
-+M: Björn Töpel <bjorn@kernel.org>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/riscv/net/
-+X: arch/riscv/net/bpf_jit_comp32.c
-+
-+BPF JIT for S390
-+M: Ilya Leoshkevich <iii@linux.ibm.com>
-+M: Heiko Carstens <hca@linux.ibm.com>
-+M: Vasily Gorbik <gor@linux.ibm.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/s390/net/
-+X: arch/s390/net/pnet.c
-+
-+BPF JIT for SPARC (32-BIT AND 64-BIT)
-+M: David S. Miller <davem@davemloft.net>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/sparc/net/
-+
-+BPF JIT for X86 32-BIT
-+M: Wang YanQing <udknight@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: arch/x86/net/bpf_jit_comp32.c
-+
-+BPF JIT for X86 64-BIT
-+M: Alexei Starovoitov <ast@kernel.org>
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Supported
-+F: arch/x86/net/
-+X: arch/x86/net/bpf_jit_comp32.c
-+
-+BPF LSM (Security Audit and Enforcement using BPF)
-+M: KP Singh <kpsingh@kernel.org>
-+R: Florent Revest <revest@chromium.org>
-+R: Brendan Jackman <jackmanb@chromium.org>
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: Documentation/bpf/bpf_lsm.rst
-+F: include/linux/bpf_lsm.h
-+F: kernel/bpf/bpf_lsm.c
-+F: security/bpf/
-+
-+BROADCOM B44 10/100 ETHERNET DRIVER
-+M: Michael Chan <michael.chan@broadcom.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/b44.*
-+
-+BROADCOM B53 ETHERNET SWITCH DRIVER
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: netdev@vger.kernel.org
-+L: openwrt-devel@lists.openwrt.org (subscribers-only)
-+S: Supported
-+F: Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml
-+F: drivers/net/dsa/b53/*
-+F: include/linux/dsa/brcm.h
-+F: include/linux/platform_data/b53.h
-+
-+BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE
-+M: Nicolas Saenz Julienne <nsaenz@kernel.org>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsaenz/linux-rpi.git
-+F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-+F: drivers/pci/controller/pcie-brcmstb.c
-+F: drivers/staging/vc04_services
-+N: bcm2711
-+N: bcm283*
-+
-+BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: Ray Jui <rjui@broadcom.com>
-+M: Scott Branden <sbranden@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+T: git git://github.com/broadcom/mach-bcm
-+F: arch/arm/mach-bcm/
-+N: bcm281*
-+N: bcm113*
-+N: bcm216*
-+N: kona
-+
-+BROADCOM BCM47XX MIPS ARCHITECTURE
-+M: Hauke Mehrtens <hauke@hauke-m.de>
-+M: Rafał Miłecki <zajec5@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mips/brcm/
-+F: arch/mips/bcm47xx/*
-+F: arch/mips/include/asm/mach-bcm47xx/*
-+
-+BROADCOM BCM4908 ETHERNET DRIVER
-+M: Rafał Miłecki <rafal@milecki.pl>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml
-+F: drivers/net/ethernet/broadcom/bcm4908_enet.*
-+F: drivers/net/ethernet/broadcom/unimac.h
-+
-+BROADCOM BCM5301X ARM ARCHITECTURE
-+M: Hauke Mehrtens <hauke@hauke-m.de>
-+M: Rafał Miłecki <zajec5@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/bcm470*
-+F: arch/arm/boot/dts/bcm5301*
-+F: arch/arm/boot/dts/bcm953012*
-+F: arch/arm/mach-bcm/bcm_5301x.c
-+
-+BROADCOM BCM53573 ARM ARCHITECTURE
-+M: Rafał Miłecki <rafal@milecki.pl>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/boot/dts/bcm47189*
-+F: arch/arm/boot/dts/bcm53573*
-+
-+BROADCOM BCM63XX ARM ARCHITECTURE
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/broadcom/stblinux.git
-+N: bcm63xx
-+
-+BROADCOM BCM63XX/BCM33XX UDC DRIVER
-+M: Kevin Cernekee <cernekee@gmail.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/gadget/udc/bcm63xx_udc.*
-+
-+BROADCOM BCM7XXX ARM ARCHITECTURE
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/broadcom/stblinux.git
-+F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-+F: arch/arm/boot/dts/bcm7*.dts*
-+F: arch/arm/include/asm/hardware/cache-b15-rac.h
-+F: arch/arm/mach-bcm/*brcmstb*
-+F: arch/arm/mm/cache-b15-rac.c
-+F: drivers/bus/brcmstb_gisb.c
-+F: drivers/pci/controller/pcie-brcmstb.c
-+N: brcmstb
-+
-+BROADCOM BDC DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-usb@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/usb/brcm,bdc.txt
-+F: drivers/usb/gadget/udc/bdc/
-+
-+BROADCOM BMIPS CPUFREQ DRIVER
-+M: Markus Mayer <mmayer@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: drivers/cpufreq/bmips-cpufreq.c
-+
-+BROADCOM BMIPS MIPS ARCHITECTURE
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+T: git git://github.com/broadcom/stblinux.git
-+F: arch/mips/bmips/*
-+F: arch/mips/boot/dts/brcm/bcm*.dts*
-+F: arch/mips/include/asm/mach-bmips/*
-+F: arch/mips/kernel/*bmips*
-+F: drivers/soc/bcm/bcm63xx
-+F: drivers/irqchip/irq-bcm63*
-+F: drivers/irqchip/irq-bcm7*
-+F: drivers/irqchip/irq-brcmstb*
-+F: include/linux/bcm963xx_nvram.h
-+F: include/linux/bcm963xx_tag.h
-+
-+BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-+M: Rasesh Mody <rmody@marvell.com>
-+M: GR-Linux-NIC-Dev@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/bnx2.*
-+F: drivers/net/ethernet/broadcom/bnx2_*
-+
-+BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
-+M: Saurav Kashyap <skashyap@marvell.com>
-+M: Javed Hasan <jhasan@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/bnx2fc/
-+
-+BROADCOM BNX2I 1/10 GIGABIT iSCSI DRIVER
-+M: Nilesh Javali <njavali@marvell.com>
-+M: Manish Rangankar <mrangankar@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/bnx2i/
-+
-+BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-+M: Ariel Elior <aelior@marvell.com>
-+M: Sudarsana Kalluru <skalluru@marvell.com>
-+M: GR-everest-linux-l2@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/bnx2x/
-+
-+BROADCOM BNXT_EN 50 GIGABIT ETHERNET DRIVER
-+M: Michael Chan <michael.chan@broadcom.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/bnxt/
-+
-+BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
-+M: Arend van Spriel <aspriel@gmail.com>
-+M: Franky Lin <franky.lin@broadcom.com>
-+M: Hante Meuleman <hante.meuleman@broadcom.com>
-+M: Chi-hsien Lin <chi-hsien.lin@infineon.com>
-+M: Wright Feng <wright.feng@infineon.com>
-+M: Chung-hsien Hsu <chung-hsien.hsu@infineon.com>
-+L: linux-wireless@vger.kernel.org
-+L: brcm80211-dev-list.pdl@broadcom.com
-+L: SHA-cyfmac-dev-list@infineon.com
-+S: Supported
-+F: drivers/net/wireless/broadcom/brcm80211/
-+
-+BROADCOM BRCMSTB GPIO DRIVER
-+M: Gregory Fong <gregory.0xf0@gmail.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Supported
-+F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
-+F: drivers/gpio/gpio-brcmstb.c
-+
-+BROADCOM BRCMSTB I2C DRIVER
-+M: Kamal Dasu <kdasu.kdev@gmail.com>
-+L: linux-i2c@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Supported
-+F: Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml
-+F: drivers/i2c/busses/i2c-brcmstb.c
-+
-+BROADCOM BRCMSTB UART DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-serial@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
-+F: drivers/tty/serial/8250/8250_bcm7271.c
-+
-+BROADCOM BRCMSTB USB EHCI DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-usb@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml
-+F: drivers/usb/host/ehci-brcm.*
-+
-+BROADCOM BRCMSTB USB PIN MAP DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-usb@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml
-+F: drivers/usb/misc/brcmstb-usb-pinmap.c
-+
-+BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: drivers/phy/broadcom/phy-brcm-usb*
-+
-+BROADCOM ETHERNET PHY DRIVERS
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/net/broadcom-bcm87xx.txt
-+F: drivers/net/phy/bcm*.[ch]
-+F: drivers/net/phy/broadcom.c
-+F: include/linux/brcmphy.h
-+
-+BROADCOM GENET ETHERNET DRIVER
-+M: Doug Berger <opendmb@gmail.com>
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/net/brcm,bcmgenet.txt
-+F: Documentation/devicetree/bindings/net/brcm,unimac-mdio.txt
-+F: drivers/net/ethernet/broadcom/genet/
-+F: drivers/net/ethernet/broadcom/unimac.h
-+F: drivers/net/mdio/mdio-bcm-unimac.c
-+F: include/linux/platform_data/bcmgenet.h
-+F: include/linux/platform_data/mdio-bcm-unimac.h
-+
-+BROADCOM IPROC ARM ARCHITECTURE
-+M: Ray Jui <rjui@broadcom.com>
-+M: Scott Branden <sbranden@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/broadcom/cygnus-linux.git
-+F: arch/arm64/boot/dts/broadcom/northstar2/*
-+F: arch/arm64/boot/dts/broadcom/stingray/*
-+F: drivers/clk/bcm/clk-ns*
-+F: drivers/clk/bcm/clk-sr*
-+F: drivers/pinctrl/bcm/pinctrl-ns*
-+F: include/dt-bindings/clock/bcm-sr*
-+N: iproc
-+N: cygnus
-+N: bcm[-_]nsp
-+N: bcm9113*
-+N: bcm9583*
-+N: bcm9585*
-+N: bcm9586*
-+N: bcm988312
-+N: bcm113*
-+N: bcm583*
-+N: bcm585*
-+N: bcm586*
-+N: bcm88312
-+N: hr2
-+N: stingray
-+
-+BROADCOM IPROC GBIT ETHERNET DRIVER
-+M: Rafał Miłecki <rafal@milecki.pl>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/brcm,amac.txt
-+F: drivers/net/ethernet/broadcom/bgmac*
-+F: drivers/net/ethernet/broadcom/unimac.h
-+
-+BROADCOM KONA GPIO DRIVER
-+M: Ray Jui <rjui@broadcom.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Supported
-+F: Documentation/devicetree/bindings/gpio/brcm,kona-gpio.txt
-+F: drivers/gpio/gpio-bcm-kona.c
-+
-+BROADCOM MPI3 STORAGE CONTROLLER DRIVER
-+M: Sathya Prakash Veerichetty <sathya.prakash@broadcom.com>
-+M: Kashyap Desai <kashyap.desai@broadcom.com>
-+M: Sumit Saxena <sumit.saxena@broadcom.com>
-+M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
-+L: mpi3mr-linuxdrv.pdl@broadcom.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: https://www.broadcom.com/support/storage
-+F: drivers/scsi/mpi3mr/
-+
-+BROADCOM NETXTREME-E ROCE DRIVER
-+M: Selvin Xavier <selvin.xavier@broadcom.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.broadcom.com
-+F: drivers/infiniband/hw/bnxt_re/
-+F: include/uapi/rdma/bnxt_re-abi.h
-+
-+BROADCOM NVRAM DRIVER
-+M: Rafał Miłecki <zajec5@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: drivers/firmware/broadcom/*
-+
-+BROADCOM PMB (POWER MANAGEMENT BUS) DRIVER
-+M: Rafał Miłecki <rafal@milecki.pl>
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://github.com/broadcom/stblinux.git
-+F: drivers/soc/bcm/bcm63xx/bcm-pmb.c
-+F: include/dt-bindings/soc/bcm-pmb.h
-+
-+BROADCOM SPECIFIC AMBA DRIVER (BCMA)
-+M: Rafał Miłecki <zajec5@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/bcma/
-+F: include/linux/bcma/
-+
-+BROADCOM SPI DRIVER
-+M: Kamal Dasu <kdasu.kdev@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml
-+F: drivers/spi/spi-bcm-qspi.*
-+F: drivers/spi/spi-brcmstb-qspi.c
-+F: drivers/spi/spi-iproc-qspi.c
-+
-+BROADCOM STB AVS CPUFREQ DRIVER
-+M: Markus Mayer <mmayer@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
-+F: drivers/cpufreq/brcmstb*
-+
-+BROADCOM STB AVS TMON DRIVER
-+M: Markus Mayer <mmayer@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt
-+F: drivers/thermal/broadcom/brcmstb*
-+
-+BROADCOM STB DPFE DRIVER
-+M: Markus Mayer <mmayer@broadcom.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml
-+F: drivers/memory/brcmstb_dpfe.c
-+
-+BROADCOM STB NAND FLASH DRIVER
-+M: Brian Norris <computersforpeace@gmail.com>
-+M: Kamal Dasu <kdasu.kdev@gmail.com>
-+L: linux-mtd@lists.infradead.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: drivers/mtd/nand/raw/brcmnand/
-+
-+BROADCOM STB PCIE DRIVER
-+M: Jim Quinlan <jim2101024@gmail.com>
-+M: Nicolas Saenz Julienne <nsaenz@kernel.org>
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: bcm-kernel-feedback-list@broadcom.com
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-+F: drivers/pci/controller/pcie-brcmstb.c
-+
-+BROADCOM SYSTEMPORT ETHERNET DRIVER
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/bcmsysport.*
-+F: drivers/net/ethernet/broadcom/unimac.h
-+
-+BROADCOM TG3 GIGABIT ETHERNET DRIVER
-+M: Siva Reddy Kallam <siva.kallam@broadcom.com>
-+M: Prashant Sreedharan <prashant@broadcom.com>
-+M: Michael Chan <mchan@broadcom.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/broadcom/tg3.*
-+
-+BROADCOM VK DRIVER
-+M: Scott Branden <scott.branden@broadcom.com>
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Supported
-+F: drivers/misc/bcm-vk/
-+F: include/uapi/linux/misc/bcm_vk.h
-+
-+BROCADE BFA FC SCSI DRIVER
-+M: Anil Gurumurthy <anil.gurumurthy@qlogic.com>
-+M: Sudarsana Kalluru <sudarsana.kalluru@qlogic.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/bfa/
-+
-+BROCADE BNA 10 GIGABIT ETHERNET DRIVER
-+M: Rasesh Mody <rmody@marvell.com>
-+M: Sudarsana Kalluru <skalluru@marvell.com>
-+M: GR-Linux-NIC-Dev@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/brocade/bna/
-+
-+BSG (block layer generic sg v4 driver)
-+M: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: block/bsg.c
-+F: include/linux/bsg.h
-+F: include/uapi/linux/bsg.h
-+
-+BT87X AUDIO DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: Documentation/sound/cards/bt87x.rst
-+F: sound/pci/bt87x.c
-+
-+BT8XXGPIO DRIVER
-+M: Michael Buesch <m@bues.ch>
-+S: Maintained
-+W: http://bu3sch.de/btgpio.php
-+F: drivers/gpio/gpio-bt8xx.c
-+
-+BTRFS FILE SYSTEM
-+M: Chris Mason <clm@fb.com>
-+M: Josef Bacik <josef@toxicpanda.com>
-+M: David Sterba <dsterba@suse.com>
-+L: linux-btrfs@vger.kernel.org
-+S: Maintained
-+W: http://btrfs.wiki.kernel.org/
-+Q: http://patchwork.kernel.org/project/linux-btrfs/list/
-+C: irc://irc.libera.chat/btrfs
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
-+F: Documentation/filesystems/btrfs.rst
-+F: fs/btrfs/
-+F: include/linux/btrfs*
-+F: include/uapi/linux/btrfs*
-+
-+BTTV VIDEO4LINUX DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/driver-api/media/drivers/bttv*
-+F: drivers/media/pci/bt8xx/bttv*
-+
-+BUS FREQUENCY DRIVER FOR SAMSUNG EXYNOS
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
-+F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt
-+F: drivers/devfreq/exynos-bus.c
-+
-+BUSLOGIC SCSI DRIVER
-+M: Khalid Aziz <khalid@gonehiking.org>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/BusLogic.*
-+F: drivers/scsi/FlashPoint.*
-+
-+C-MEDIA CMI8788 DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: sound/pci/oxygen/
-+
-+C-SKY ARCHITECTURE
-+M: Guo Ren <guoren@kernel.org>
-+L: linux-csky@vger.kernel.org
-+S: Supported
-+T: git https://github.com/c-sky/csky-linux.git
-+F: Documentation/devicetree/bindings/csky/
-+F: Documentation/devicetree/bindings/interrupt-controller/csky,*
-+F: Documentation/devicetree/bindings/timer/csky,*
-+F: arch/csky/
-+F: drivers/clocksource/timer-gx6605s.c
-+F: drivers/clocksource/timer-mp-csky.c
-+F: drivers/irqchip/irq-csky-*
-+N: csky
-+K: csky
-+
-+CA8210 IEEE-802.15.4 RADIO DRIVER
-+M: Harry Morris <h.morris@cascoda.com>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+W: https://github.com/Cascoda/ca8210-linux.git
-+F: Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
-+F: drivers/net/ieee802154/ca8210.c
-+
-+CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
-+M: Damien Le Moal <damien.lemoal@wdc.com>
-+L: linux-riscv@lists.infradead.org
-+L: linux-gpio@vger.kernel.org (pinctrl driver)
-+F: Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
-+F: drivers/pinctrl/pinctrl-k210.c
-+
-+CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
-+M: Damien Le Moal <damien.lemoal@wdc.com>
-+L: linux-kernel@vger.kernel.org
-+L: linux-riscv@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/reset/canaan,k210-rst.yaml
-+F: drivers/reset/reset-k210.c
-+
-+CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER
-+M: Damien Le Moal <damien.lemoal@wdc.com>
-+L: linux-riscv@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
-+F: drivers/soc/canaan/
-+F: include/soc/canaan/
-+
-+CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
-+M: David Howells <dhowells@redhat.com>
-+L: linux-cachefs@redhat.com (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/filesystems/caching/cachefiles.rst
-+F: fs/cachefiles/
-+
-+CADENCE MIPI-CSI2 BRIDGES
-+M: Maxime Ripard <mripard@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/cdns,*.txt
-+F: drivers/media/platform/cadence/cdns-csi2*
-+
-+CADENCE NAND DRIVER
-+L: linux-mtd@lists.infradead.org
-+S: Orphan
-+F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
-+F: drivers/mtd/nand/raw/cadence-nand-controller.c
-+
-+CADENCE USB3 DRD IP DRIVER
-+M: Peter Chen <peter.chen@kernel.org>
-+M: Pawel Laszczak <pawell@cadence.com>
-+R: Roger Quadros <rogerq@kernel.org>
-+R: Aswath Govindraju <a-govindraju@ti.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
-+F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml
-+F: drivers/usb/cdns3/
-+X: drivers/usb/cdns3/cdnsp*
-+
-+CADENCE USBSSP DRD IP DRIVER
-+M: Pawel Laszczak <pawell@cadence.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
-+F: drivers/usb/cdns3/
-+X: drivers/usb/cdns3/cdns3*
-+
-+CADET FM/AM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-cadet*
-+
-+CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/cafe_ccic*
-+F: drivers/media/platform/marvell-ccic/
-+
-+CAIF NETWORK LAYER
-+L: netdev@vger.kernel.org
-+S: Orphan
-+F: Documentation/networking/caif/
-+F: drivers/net/caif/
-+F: include/net/caif/
-+F: include/uapi/linux/caif/
-+F: net/caif/
-+
-+CAKE QDISC
-+M: Toke Høiland-Jørgensen <toke@toke.dk>
-+L: cake@lists.bufferbloat.net (moderated for non-subscribers)
-+S: Maintained
-+F: net/sched/sch_cake.c
-+
-+CAN NETWORK DRIVERS
-+M: Wolfgang Grandegger <wg@grandegger.com>
-+M: Marc Kleine-Budde <mkl@pengutronix.de>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+W: https://github.com/linux-can
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
-+F: Documentation/devicetree/bindings/net/can/
-+F: Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
-+F: drivers/net/can/
-+F: drivers/phy/phy-can-transceiver.c
-+F: include/linux/can/bittiming.h
-+F: include/linux/can/dev.h
-+F: include/linux/can/led.h
-+F: include/linux/can/length.h
-+F: include/linux/can/platform/
-+F: include/linux/can/rx-offload.h
-+F: include/uapi/linux/can/error.h
-+F: include/uapi/linux/can/netlink.h
-+F: include/uapi/linux/can/vxcan.h
-+
-+CAN NETWORK LAYER
-+M: Oliver Hartkopp <socketcan@hartkopp.net>
-+M: Marc Kleine-Budde <mkl@pengutronix.de>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+W: https://github.com/linux-can
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
-+F: Documentation/networking/can.rst
-+F: include/linux/can/can-ml.h
-+F: include/linux/can/core.h
-+F: include/linux/can/skb.h
-+F: include/net/netns/can.h
-+F: include/uapi/linux/can.h
-+F: include/uapi/linux/can/bcm.h
-+F: include/uapi/linux/can/gw.h
-+F: include/uapi/linux/can/isotp.h
-+F: include/uapi/linux/can/raw.h
-+F: net/can/
-+
-+CAN-J1939 NETWORK LAYER
-+M: Robin van der Gracht <robin@protonic.nl>
-+M: Oleksij Rempel <o.rempel@pengutronix.de>
-+R: kernel@pengutronix.de
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/j1939.rst
-+F: include/uapi/linux/can/j1939.h
-+F: net/can/j1939/
-+
-+CAPABILITIES
-+M: Serge Hallyn <serge@hallyn.com>
-+L: linux-security-module@vger.kernel.org
-+S: Supported
-+F: include/linux/capability.h
-+F: include/uapi/linux/capability.h
-+F: kernel/capability.c
-+F: security/commoncap.c
-+
-+CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER
-+M: Kevin Tsai <ktsai@capellamicro.com>
-+S: Maintained
-+F: drivers/iio/light/cm*
-+
-+CARL9170 LINUX COMMUNITY WIRELESS DRIVER
-+M: Christian Lamparter <chunkeey@googlemail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/carl9170
-+F: drivers/net/wireless/ath/carl9170/
-+
-+CAVIUM I2C DRIVER
-+M: Robert Richter <rric@kernel.org>
-+S: Odd Fixes
-+W: http://www.marvell.com
-+F: drivers/i2c/busses/i2c-octeon*
-+F: drivers/i2c/busses/i2c-thunderx*
-+
-+CAVIUM LIQUIDIO NETWORK DRIVER
-+M: Derek Chickles <dchickles@marvell.com>
-+M: Satanand Burla <sburla@marvell.com>
-+M: Felix Manlunas <fmanlunas@marvell.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.marvell.com
-+F: drivers/net/ethernet/cavium/liquidio/
-+
-+CAVIUM MMC DRIVER
-+M: Robert Richter <rric@kernel.org>
-+S: Odd Fixes
-+W: http://www.marvell.com
-+F: drivers/mmc/host/cavium*
-+
-+CAVIUM OCTEON-TX CRYPTO DRIVER
-+M: George Cherian <gcherian@marvell.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+W: http://www.marvell.com
-+F: drivers/crypto/cavium/cpt/
-+
-+CAVIUM THUNDERX2 ARM64 SOC
-+M: Robert Richter <rric@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Odd Fixes
-+F: Documentation/devicetree/bindings/arm/cavium-thunder2.txt
-+F: arch/arm64/boot/dts/cavium/thunder2-99xx*
-+
-+CBS/ETF/TAPRIO QDISCS
-+M: Vinicius Costa Gomes <vinicius.gomes@intel.com>
-+S: Maintained
-+L: netdev@vger.kernel.org
-+F: net/sched/sch_cbs.c
-+F: net/sched/sch_etf.c
-+F: net/sched/sch_taprio.c
-+
-+CC2520 IEEE-802.15.4 RADIO DRIVER
-+M: Varka Bhadram <varkabhadram@gmail.com>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
-+F: drivers/net/ieee802154/cc2520.c
-+F: include/linux/spi/cc2520.h
-+
-+CCREE ARM TRUSTZONE CRYPTOCELL REE DRIVER
-+M: Gilad Ben-Yossef <gilad@benyossef.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
-+F: drivers/crypto/ccree/
-+
-+CCTRNG ARM TRUSTZONE CRYPTOCELL TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
-+M: Hadar Gat <hadar.gat@arm.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+F: drivers/char/hw_random/cctrng.c
-+F: drivers/char/hw_random/cctrng.h
-+F: Documentation/devicetree/bindings/rng/arm-cctrng.yaml
-+W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
-+
-+CEC FRAMEWORK
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: http://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/ABI/testing/debugfs-cec-error-inj
-+F: Documentation/devicetree/bindings/media/cec.txt
-+F: Documentation/driver-api/media/cec-core.rst
-+F: Documentation/userspace-api/media/cec
-+F: drivers/media/cec/
-+F: drivers/media/rc/keymaps/rc-cec.c
-+F: include/media/cec-notifier.h
-+F: include/media/cec.h
-+F: include/uapi/linux/cec-funcs.h
-+F: include/uapi/linux/cec.h
-+
-+CEC GPIO DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: http://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/cec-gpio.txt
-+F: drivers/media/cec/platform/cec-gpio/
-+
-+CELL BROADBAND ENGINE ARCHITECTURE
-+M: Arnd Bergmann <arnd@arndb.de>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/power/cell/
-+F: arch/powerpc/include/asm/cell*.h
-+F: arch/powerpc/include/asm/spu*.h
-+F: arch/powerpc/include/uapi/asm/spu*.h
-+F: arch/powerpc/platforms/cell/
-+
-+CELLWISE CW2015 BATTERY DRIVER
-+M: Tobias Schrammm <t.schramm@manjaro.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/power/supply/cw2015_battery.yaml
-+F: drivers/power/supply/cw2015_battery.c
-+
-+CEPH COMMON CODE (LIBCEPH)
-+M: Ilya Dryomov <idryomov@gmail.com>
-+M: Jeff Layton <jlayton@kernel.org>
-+L: ceph-devel@vger.kernel.org
-+S: Supported
-+W: http://ceph.com/
-+T: git git://github.com/ceph/ceph-client.git
-+F: include/linux/ceph/
-+F: include/linux/crush/
-+F: net/ceph/
-+
-+CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)
-+M: Jeff Layton <jlayton@kernel.org>
-+M: Ilya Dryomov <idryomov@gmail.com>
-+L: ceph-devel@vger.kernel.org
-+S: Supported
-+W: http://ceph.com/
-+T: git git://github.com/ceph/ceph-client.git
-+F: Documentation/filesystems/ceph.rst
-+F: fs/ceph/
-+
-+CERTIFICATE HANDLING
-+M: David Howells <dhowells@redhat.com>
-+M: David Woodhouse <dwmw2@infradead.org>
-+L: keyrings@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/module-signing.rst
-+F: certs/
-+F: scripts/extract-cert.c
-+F: scripts/sign-file.c
-+
-+CFAG12864B LCD DRIVER
-+M: Miguel Ojeda <ojeda@kernel.org>
-+S: Maintained
-+F: drivers/auxdisplay/cfag12864b.c
-+F: include/linux/cfag12864b.h
-+
-+CFAG12864BFB LCD FRAMEBUFFER DRIVER
-+M: Miguel Ojeda <ojeda@kernel.org>
-+S: Maintained
-+F: drivers/auxdisplay/cfag12864bfb.c
-+F: include/linux/cfag12864b.h
-+
-+CHAR and MISC DRIVERS
-+M: Arnd Bergmann <arnd@arndb.de>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-+F: drivers/char/
-+F: drivers/misc/
-+F: include/linux/miscdevice.h
-+X: drivers/char/agp/
-+X: drivers/char/hw_random/
-+X: drivers/char/ipmi/
-+X: drivers/char/random.c
-+X: drivers/char/tpm/
-+
-+CHECKPATCH
-+M: Andy Whitcroft <apw@canonical.com>
-+M: Joe Perches <joe@perches.com>
-+R: Dwaipayan Ray <dwaipayanray1@gmail.com>
-+R: Lukas Bulwahn <lukas.bulwahn@gmail.com>
-+S: Maintained
-+F: scripts/checkpatch.pl
-+
-+CHECKPATCH DOCUMENTATION
-+M: Dwaipayan Ray <dwaipayanray1@gmail.com>
-+M: Lukas Bulwahn <lukas.bulwahn@gmail.com>
-+R: Joe Perches <joe@perches.com>
-+S: Maintained
-+F: Documentation/dev-tools/checkpatch.rst
-+
-+CHINESE DOCUMENTATION
-+M: Alex Shi <alexs@kernel.org>
-+S: Maintained
-+F: Documentation/translations/zh_CN/
-+
-+CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
-+M: Peter Chen <peter.chen@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
-+F: drivers/usb/chipidea/
-+
-+CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/input/touchscreen/chipone_icn8318.txt
-+F: drivers/input/touchscreen/chipone_icn8318.c
-+
-+CHIPONE ICN8505 I2C TOUCHSCREEN DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/chipone_icn8505.c
-+
-+CHROME HARDWARE PLATFORM SUPPORT
-+M: Benson Leung <bleung@chromium.org>
-+M: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git
-+F: drivers/platform/chrome/
-+
-+CHROMEOS EC CODEC DRIVER
-+M: Cheng-Yi Chiang <cychiang@chromium.org>
-+R: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-+R: Guenter Roeck <groeck@chromium.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
-+F: sound/soc/codecs/cros_ec_codec.*
-+
-+CHROMEOS EC SUBDRIVERS
-+M: Benson Leung <bleung@chromium.org>
-+M: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-+R: Guenter Roeck <groeck@chromium.org>
-+S: Maintained
-+F: drivers/power/supply/cros_usbpd-charger.c
-+N: cros_ec
-+N: cros-ec
-+
-+CHRONTEL CH7322 CEC DRIVER
-+M: Jeff Chase <jnchase@google.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml
-+F: drivers/media/cec/i2c/ch7322.c
-+
-+CIRRUS LOGIC AUDIO CODEC DRIVERS
-+M: James Schulman <james.schulman@cirrus.com>
-+M: David Rhodes <david.rhodes@cirrus.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+L: patches@opensource.cirrus.com
-+S: Maintained
-+F: sound/soc/codecs/cs*
-+
-+CIRRUS LOGIC EP93XX ETHERNET DRIVER
-+M: Hartley Sweeten <hsweeten@visionengravers.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/cirrus/ep93xx_eth.c
-+
-+CIRRUS LOGIC LOCHNAGAR DRIVER
-+M: Charles Keepax <ckeepax@opensource.cirrus.com>
-+M: Richard Fitzgerald <rf@opensource.cirrus.com>
-+L: patches@opensource.cirrus.com
-+S: Supported
-+F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml
-+F: Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml
-+F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
-+F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml
-+F: Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
-+F: Documentation/hwmon/lochnagar.rst
-+F: drivers/clk/clk-lochnagar.c
-+F: drivers/hwmon/lochnagar-hwmon.c
-+F: drivers/mfd/lochnagar-i2c.c
-+F: drivers/pinctrl/cirrus/pinctrl-lochnagar.c
-+F: drivers/regulator/lochnagar-regulator.c
-+F: include/dt-bindings/clk/lochnagar.h
-+F: include/dt-bindings/pinctrl/lochnagar.h
-+F: include/linux/mfd/lochnagar*
-+F: sound/soc/codecs/lochnagar-sc.c
-+
-+CIRRUS LOGIC MADERA CODEC DRIVERS
-+M: Charles Keepax <ckeepax@opensource.cirrus.com>
-+M: Richard Fitzgerald <rf@opensource.cirrus.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+L: patches@opensource.cirrus.com
-+S: Supported
-+W: https://github.com/CirrusLogic/linux-drivers/wiki
-+T: git https://github.com/CirrusLogic/linux-drivers.git
-+F: Documentation/devicetree/bindings/mfd/cirrus,madera.yaml
-+F: Documentation/devicetree/bindings/pinctrl/cirrus,madera.yaml
-+F: Documentation/devicetree/bindings/sound/cirrus,madera.yaml
-+F: drivers/gpio/gpio-madera*
-+F: drivers/irqchip/irq-madera*
-+F: drivers/mfd/cs47l*
-+F: drivers/mfd/madera*
-+F: drivers/pinctrl/cirrus/*
-+F: include/dt-bindings/sound/madera*
-+F: include/linux/irqchip/irq-madera*
-+F: include/linux/mfd/madera/*
-+F: include/sound/madera*
-+F: sound/soc/codecs/cs47l*
-+F: sound/soc/codecs/madera*
-+
-+CISCO FCOE HBA DRIVER
-+M: Satish Kharat <satishkh@cisco.com>
-+M: Sesidhar Baddela <sebaddel@cisco.com>
-+M: Karan Tilak Kumar <kartilak@cisco.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/fnic/
-+
-+CISCO SCSI HBA DRIVER
-+M: Karan Tilak Kumar <kartilak@cisco.com>
-+M: Sesidhar Baddela <sebaddel@cisco.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/snic/
-+
-+CISCO VIC ETHERNET NIC DRIVER
-+M: Christian Benvenuti <benve@cisco.com>
-+M: Govindarajulu Varadarajan <_govind@gmx.com>
-+S: Supported
-+F: drivers/net/ethernet/cisco/enic/
-+
-+CISCO VIC LOW LATENCY NIC DRIVER
-+M: Christian Benvenuti <benve@cisco.com>
-+M: Nelson Escobar <neescoba@cisco.com>
-+S: Supported
-+F: drivers/infiniband/hw/usnic/
-+
-+CLANG-FORMAT FILE
-+M: Miguel Ojeda <ojeda@kernel.org>
-+S: Maintained
-+F: .clang-format
-+
-+CLANG/LLVM BUILD SUPPORT
-+M: Nathan Chancellor <nathan@kernel.org>
-+M: Nick Desaulniers <ndesaulniers@google.com>
-+L: llvm@lists.linux.dev
-+S: Supported
-+W: https://clangbuiltlinux.github.io/
-+B: https://github.com/ClangBuiltLinux/linux/issues
-+C: irc://irc.libera.chat/clangbuiltlinux
-+F: Documentation/kbuild/llvm.rst
-+F: include/linux/compiler-clang.h
-+F: scripts/Makefile.clang
-+F: scripts/clang-tools/
-+K: \b(?i:clang|llvm)\b
-+
-+CLANG CONTROL FLOW INTEGRITY SUPPORT
-+M: Sami Tolvanen <samitolvanen@google.com>
-+M: Kees Cook <keescook@chromium.org>
-+R: Nathan Chancellor <nathan@kernel.org>
-+R: Nick Desaulniers <ndesaulniers@google.com>
-+L: llvm@lists.linux.dev
-+S: Supported
-+B: https://github.com/ClangBuiltLinux/linux/issues
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/clang/features
-+F: include/linux/cfi.h
-+F: kernel/cfi.c
-+
-+CLEANCACHE API
-+M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: include/linux/cleancache.h
-+F: mm/cleancache.c
-+
-+CLK API
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-clk@vger.kernel.org
-+S: Maintained
-+F: include/linux/clk.h
-+
-+CLOCKSOURCE, CLOCKEVENT DRIVERS
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+M: Thomas Gleixner <tglx@linutronix.de>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
-+F: Documentation/devicetree/bindings/timer/
-+F: drivers/clocksource/
-+
-+CMPC ACPI DRIVER
-+M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
-+M: Daniel Oliveira Nascimento <don@syst.com.br>
-+L: platform-driver-x86@vger.kernel.org
-+S: Supported
-+F: drivers/platform/x86/classmate-laptop.c
-+
-+COBALT MEDIA DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/cobalt/
-+
-+COCCINELLE/Semantic Patches (SmPL)
-+M: Julia Lawall <Julia.Lawall@inria.fr>
-+M: Gilles Muller <Gilles.Muller@inria.fr>
-+M: Nicolas Palix <nicolas.palix@imag.fr>
-+M: Michal Marek <michal.lkml@markovi.net>
-+L: cocci@systeme.lip6.fr (moderated for non-subscribers)
-+S: Supported
-+W: http://coccinelle.lip6.fr/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git misc
-+F: Documentation/dev-tools/coccinelle.rst
-+F: scripts/coccicheck
-+F: scripts/coccinelle/
-+
-+CODA FILE SYSTEM
-+M: Jan Harkes <jaharkes@cs.cmu.edu>
-+M: coda@cs.cmu.edu
-+L: codalist@coda.cs.cmu.edu
-+S: Maintained
-+W: http://www.coda.cs.cmu.edu/
-+F: Documentation/filesystems/coda.rst
-+F: fs/coda/
-+F: include/linux/coda*.h
-+F: include/uapi/linux/coda*.h
-+
-+CODA V4L2 MEM2MEM DRIVER
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/coda.yaml
-+F: drivers/media/platform/coda/
-+
-+CODE OF CONDUCT
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+S: Supported
-+F: Documentation/process/code-of-conduct-interpretation.rst
-+F: Documentation/process/code-of-conduct.rst
-+
-+COMEDI DRIVERS
-+M: Ian Abbott <abbotti@mev.co.uk>
-+M: H Hartley Sweeten <hsweeten@visionengravers.com>
-+S: Odd Fixes
-+F: drivers/comedi/
-+
-+COMMON CLK FRAMEWORK
-+M: Michael Turquette <mturquette@baylibre.com>
-+M: Stephen Boyd <sboyd@kernel.org>
-+L: linux-clk@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-clk/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
-+F: Documentation/devicetree/bindings/clock/
-+F: drivers/clk/
-+F: include/linux/clk-pr*
-+F: include/linux/clk/
-+F: include/linux/of_clk.h
-+X: drivers/clk/clkdev.c
-+
-+COMMON INTERNET FILE SYSTEM CLIENT (CIFS)
-+M: Steve French <sfrench@samba.org>
-+L: linux-cifs@vger.kernel.org
-+L: samba-technical@lists.samba.org (moderated for non-subscribers)
-+S: Supported
-+W: http://linux-cifs.samba.org/
-+T: git git://git.samba.org/sfrench/cifs-2.6.git
-+F: Documentation/admin-guide/cifs/
-+F: fs/cifs/
-+F: fs/smbfs_common/
-+
-+COMPACTPCI HOTPLUG CORE
-+M: Scott Murray <scott@spiteful.org>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/hotplug/cpci_hotplug*
-+
-+COMPACTPCI HOTPLUG GENERIC DRIVER
-+M: Scott Murray <scott@spiteful.org>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/hotplug/cpcihp_generic.c
-+
-+COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
-+M: Scott Murray <scott@spiteful.org>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/hotplug/cpcihp_zt5550.*
-+
-+COMPAL LAPTOP SUPPORT
-+M: Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/compal-laptop.c
-+
-+COMPILER ATTRIBUTES
-+M: Miguel Ojeda <ojeda@kernel.org>
-+R: Nick Desaulniers <ndesaulniers@google.com>
-+S: Maintained
-+F: include/linux/compiler_attributes.h
-+
-+COMPUTE EXPRESS LINK (CXL)
-+M: Alison Schofield <alison.schofield@intel.com>
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Ira Weiny <ira.weiny@intel.com>
-+M: Ben Widawsky <ben.widawsky@intel.com>
-+M: Dan Williams <dan.j.williams@intel.com>
-+L: linux-cxl@vger.kernel.org
-+S: Maintained
-+F: drivers/cxl/
-+F: include/uapi/linux/cxl_mem.h
-+
-+CONEXANT ACCESSRUNNER USB DRIVER
-+L: accessrunner-general@lists.sourceforge.net
-+S: Orphan
-+W: http://accessrunner.sourceforge.net/
-+F: drivers/usb/atm/cxacru.c
-+
-+CONFIGFS
-+M: Joel Becker <jlbec@evilplan.org>
-+M: Christoph Hellwig <hch@lst.de>
-+S: Supported
-+T: git git://git.infradead.org/users/hch/configfs.git
-+F: fs/configfs/
-+F: include/linux/configfs.h
-+F: samples/configfs/
-+
-+CONSOLE SUBSYSTEM
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+S: Supported
-+F: drivers/video/console/
-+F: include/linux/console*
-+
-+CONTEXT TRACKING
-+M: Frederic Weisbecker <frederic@kernel.org>
-+S: Maintained
-+F: kernel/context_tracking.c
-+F: include/linux/context_tracking*
-+
-+CONTROL GROUP (CGROUP)
-+M: Tejun Heo <tj@kernel.org>
-+M: Zefan Li <lizefan.x@bytedance.com>
-+M: Johannes Weiner <hannes@cmpxchg.org>
-+L: cgroups@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
-+F: Documentation/admin-guide/cgroup-v1/
-+F: Documentation/admin-guide/cgroup-v2.rst
-+F: include/linux/cgroup*
-+F: kernel/cgroup/
-+
-+CONTROL GROUP - BLOCK IO CONTROLLER (BLKIO)
-+M: Tejun Heo <tj@kernel.org>
-+M: Jens Axboe <axboe@kernel.dk>
-+L: cgroups@vger.kernel.org
-+L: linux-block@vger.kernel.org
-+T: git git://git.kernel.dk/linux-block
-+F: Documentation/admin-guide/cgroup-v1/blkio-controller.rst
-+F: block/bfq-cgroup.c
-+F: block/blk-cgroup.c
-+F: block/blk-iolatency.c
-+F: block/blk-throttle.c
-+F: include/linux/blk-cgroup.h
-+
-+CONTROL GROUP - CPUSET
-+M: Zefan Li <lizefan.x@bytedance.com>
-+L: cgroups@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
-+F: Documentation/admin-guide/cgroup-v1/cpusets.rst
-+F: include/linux/cpuset.h
-+F: kernel/cgroup/cpuset.c
-+
-+CONTROL GROUP - MEMORY RESOURCE CONTROLLER (MEMCG)
-+M: Johannes Weiner <hannes@cmpxchg.org>
-+M: Michal Hocko <mhocko@kernel.org>
-+M: Vladimir Davydov <vdavydov.dev@gmail.com>
-+L: cgroups@vger.kernel.org
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: mm/memcontrol.c
-+F: mm/swap_cgroup.c
-+
-+CORETEMP HARDWARE MONITORING DRIVER
-+M: Fenghua Yu <fenghua.yu@intel.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/coretemp.rst
-+F: drivers/hwmon/coretemp.c
-+
-+CORSAIR-CPRO HARDWARE MONITOR DRIVER
-+M: Marius Zachmann <mail@mariuszachmann.de>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/corsair-cpro.c
-+
-+CORSAIR-PSU HARDWARE MONITOR DRIVER
-+M: Wilken Gottwalt <wilken.gottwalt@posteo.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/corsair-psu.rst
-+F: drivers/hwmon/corsair-psu.c
-+
-+COSA/SRP SYNC SERIAL DRIVER
-+M: Jan "Yenya" Kasprzak <kas@fi.muni.cz>
-+S: Maintained
-+W: http://www.fi.muni.cz/~kas/cosa/
-+F: drivers/net/wan/cosa*
-+
-+COUNTER SUBSYSTEM
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-counter
-+F: Documentation/driver-api/generic-counter.rst
-+F: drivers/counter/
-+F: include/linux/counter.h
-+F: include/linux/counter_enum.h
-+
-+CP2615 I2C DRIVER
-+M: Bence Csókás <bence98@sch.bme.hu>
-+S: Maintained
-+F: drivers/i2c/busses/i2c-cp2615.c
-+
-+CPMAC ETHERNET DRIVER
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/ti/cpmac.c
-+
-+CPU FREQUENCY DRIVERS - VEXPRESS SPC ARM BIG LITTLE
-+M: Viresh Kumar <viresh.kumar@linaro.org>
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php
-+F: drivers/cpufreq/vexpress-spc-cpufreq.c
-+
-+CPU FREQUENCY SCALING FRAMEWORK
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Viresh Kumar <viresh.kumar@linaro.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git (For ARM Updates)
-+F: Documentation/admin-guide/pm/cpufreq.rst
-+F: Documentation/admin-guide/pm/intel_pstate.rst
-+F: Documentation/cpu-freq/
-+F: Documentation/devicetree/bindings/cpufreq/
-+F: drivers/cpufreq/
-+F: include/linux/cpufreq.h
-+F: include/linux/sched/cpufreq.h
-+F: kernel/sched/cpufreq*.c
-+F: tools/testing/selftests/cpufreq/
-+
-+CPU IDLE TIME MANAGEMENT FRAMEWORK
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
-+F: Documentation/admin-guide/pm/cpuidle.rst
-+F: Documentation/driver-api/pm/cpuidle.rst
-+F: drivers/cpuidle/
-+F: include/linux/cpuidle.h
-+
-+CPU POWER MONITORING SUBSYSTEM
-+M: Thomas Renninger <trenn@suse.com>
-+M: Shuah Khan <shuah@kernel.org>
-+M: Shuah Khan <skhan@linuxfoundation.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: tools/power/cpupower/
-+
-+CPUID/MSR DRIVER
-+M: "H. Peter Anvin" <hpa@zytor.com>
-+S: Maintained
-+F: arch/x86/kernel/cpuid.c
-+F: arch/x86/kernel/msr.c
-+
-+CPUIDLE DRIVER - ARM BIG LITTLE
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+L: linux-pm@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
-+F: drivers/cpuidle/cpuidle-big_little.c
-+
-+CPUIDLE DRIVER - ARM EXYNOS
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+M: Kukjin Kim <kgene@kernel.org>
-+L: linux-pm@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Supported
-+F: arch/arm/mach-exynos/pm.c
-+F: drivers/cpuidle/cpuidle-exynos.c
-+F: include/linux/platform_data/cpuidle-exynos.h
-+
-+CPUIDLE DRIVER - ARM PSCI
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/cpuidle/cpuidle-psci.c
-+
-+CPUIDLE DRIVER - ARM PSCI PM DOMAIN
-+M: Ulf Hansson <ulf.hansson@linaro.org>
-+L: linux-pm@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/cpuidle/cpuidle-psci.h
-+F: drivers/cpuidle/cpuidle-psci-domain.c
-+
-+CRAMFS FILESYSTEM
-+M: Nicolas Pitre <nico@fluxnic.net>
-+S: Maintained
-+F: Documentation/filesystems/cramfs.rst
-+F: fs/cramfs/
-+
-+CREATIVE SB0540
-+M: Bastien Nocera <hadess@hadess.net>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-creative-sb0540.c
-+
-+CRYPTO API
-+M: Herbert Xu <herbert@gondor.apana.org.au>
-+M: "David S. Miller" <davem@davemloft.net>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
-+F: Documentation/crypto/
-+F: Documentation/devicetree/bindings/crypto/
-+F: arch/*/crypto/
-+F: crypto/
-+F: drivers/crypto/
-+F: include/crypto/
-+F: include/linux/crypto*
-+F: lib/crypto/
-+
-+CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
-+M: Neil Horman <nhorman@tuxdriver.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: crypto/ansi_cprng.c
-+F: crypto/rng.c
-+
-+CS3308 MEDIA DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: http://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/cs3308.c
-+
-+CS5535 Audio ALSA driver
-+M: Jaya Kumar <jayakumar.alsa@gmail.com>
-+S: Maintained
-+F: sound/pci/cs5535audio/
-+
-+CSI DRIVERS FOR ALLWINNER V3s
-+M: Yong Deng <yong.deng@magewell.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
-+F: drivers/media/platform/sunxi/sun6i-csi/
-+
-+CW1200 WLAN driver
-+M: Solomon Peachy <pizza@shaftnet.org>
-+S: Maintained
-+F: drivers/net/wireless/st/cw1200/
-+
-+CX18 VIDEO4LINUX DRIVER
-+M: Andy Walls <awalls@md.metrocast.net>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/cx18/
-+F: include/uapi/linux/ivtv*
-+
-+CX2341X MPEG ENCODER HELPER MODULE
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/common/cx2341x*
-+F: include/media/drv-intf/cx2341x.h
-+
-+CX24120 MEDIA DRIVER
-+M: Jemma Denson <jdenson@gmail.com>
-+M: Patrick Boettcher <patrick.boettcher@posteo.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/cx24120*
-+
-+CX88 VIDEO4LINUX DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/driver-api/media/drivers/cx88*
-+F: drivers/media/pci/cx88/
-+
-+CXD2820R MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/cxd2820r*
-+
-+CXGB3 ETHERNET DRIVER (CXGB3)
-+M: Raju Rangoju <rajur@chelsio.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/net/ethernet/chelsio/cxgb3/
-+
-+CXGB3 ISCSI DRIVER (CXGB3I)
-+M: Karen Xie <kxie@chelsio.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/scsi/cxgbi/cxgb3i
-+
-+CXGB4 CRYPTO DRIVER (chcr)
-+M: Ayush Sawal <ayush.sawal@chelsio.com>
-+M: Vinay Kumar Yadav <vinay.yadav@chelsio.com>
-+M: Rohit Maheshwari <rohitm@chelsio.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/crypto/chelsio
-+
-+CXGB4 INLINE CRYPTO DRIVER
-+M: Ayush Sawal <ayush.sawal@chelsio.com>
-+M: Vinay Kumar Yadav <vinay.yadav@chelsio.com>
-+M: Rohit Maheshwari <rohitm@chelsio.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/net/ethernet/chelsio/inline_crypto/
-+
-+CXGB4 ETHERNET DRIVER (CXGB4)
-+M: Raju Rangoju <rajur@chelsio.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/net/ethernet/chelsio/cxgb4/
-+
-+CXGB4 ISCSI DRIVER (CXGB4I)
-+M: Karen Xie <kxie@chelsio.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/scsi/cxgbi/cxgb4i
-+
-+CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
-+M: Potnuri Bharat Teja <bharat@chelsio.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.openfabrics.org
-+F: drivers/infiniband/hw/cxgb4/
-+F: include/uapi/rdma/cxgb4-abi.h
-+
-+CXGB4VF ETHERNET DRIVER (CXGB4VF)
-+M: Raju Rangoju <rajur@chelsio.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.chelsio.com
-+F: drivers/net/ethernet/chelsio/cxgb4vf/
-+
-+CXL (IBM Coherent Accelerator Processor Interface CAPI) DRIVER
-+M: Frederic Barrat <fbarrat@linux.ibm.com>
-+M: Andrew Donnellan <ajd@linux.ibm.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: Documentation/ABI/testing/sysfs-class-cxl
-+F: Documentation/powerpc/cxl.rst
-+F: arch/powerpc/platforms/powernv/pci-cxl.c
-+F: drivers/misc/cxl/
-+F: include/misc/cxl*
-+F: include/uapi/misc/cxl.h
-+
-+CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
-+M: Manoj N. Kumar <manoj@linux.ibm.com>
-+M: Matthew R. Ochs <mrochs@linux.ibm.com>
-+M: Uma Krishnan <ukrishn@linux.ibm.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: Documentation/powerpc/cxlflash.rst
-+F: drivers/scsi/cxlflash/
-+F: include/uapi/scsi/cxlflash_ioctl.h
-+
-+CYBERPRO FB DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.armlinux.org.uk/
-+F: drivers/video/fbdev/cyber2000fb.*
-+
-+CYCLADES PC300 DRIVER
-+S: Orphan
-+F: drivers/net/wan/pc300*
-+
-+CYPRESS_FIRMWARE MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/common/cypress_firmware*
-+
-+CYPRESS CY8CTMA140 TOUCHSCREEN DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/cy8ctma140.c
-+
-+CYTTSP TOUCHSCREEN DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/cyttsp*
-+
-+D-LINK DIR-685 TOUCHKEYS DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-input@vger.kernel.org
-+S: Supported
-+F: drivers/input/keyboard/dlink-dir685-touchkeys.c
-+
-+DALLAS/MAXIM DS1685-FAMILY REAL TIME CLOCK
-+M: Joshua Kinard <kumba@gentoo.org>
-+S: Maintained
-+F: drivers/rtc/rtc-ds1685.c
-+F: include/linux/rtc/ds1685.h
-+
-+DAMA SLAVE for AX.25
-+M: Joerg Reuter <jreuter@yaina.de>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://yaina.de/jreuter/
-+W: http://www.qsl.net/dl1bke/
-+F: net/ax25/af_ax25.c
-+F: net/ax25/ax25_dev.c
-+F: net/ax25/ax25_ds_*
-+F: net/ax25/ax25_in.c
-+F: net/ax25/ax25_out.c
-+F: net/ax25/ax25_timer.c
-+F: net/ax25/sysctl_net_ax25.c
-+
-+DATA ACCESS MONITOR
-+M: SeongJae Park <sjpark@amazon.de>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: Documentation/admin-guide/mm/damon/
-+F: Documentation/vm/damon/
-+F: include/linux/damon.h
-+F: include/trace/events/damon.h
-+F: mm/damon/
-+F: tools/testing/selftests/damon/
-+
-+DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
-+L: netdev@vger.kernel.org
-+S: Orphan
-+F: Documentation/networking/device_drivers/ethernet/dec/dmfe.rst
-+F: drivers/net/ethernet/dec/tulip/dmfe.c
-+
-+DC390/AM53C974 SCSI driver
-+M: Hannes Reinecke <hare@suse.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/am53c974.c
-+
-+DC395x SCSI driver
-+M: Oliver Neukum <oliver@neukum.org>
-+M: Ali Akcaagac <aliakc@web.de>
-+M: Jamie Lenehan <lenehan@twibble.org>
-+L: dc395x@twibble.org
-+S: Maintained
-+W: http://twibble.org/dist/dc395x/
-+W: http://lists.twibble.org/mailman/listinfo/dc395x/
-+F: Documentation/scsi/dc395x.rst
-+F: drivers/scsi/dc395x.*
-+
-+DCCP PROTOCOL
-+L: dccp@vger.kernel.org
-+S: Orphan
-+W: http://www.linuxfoundation.org/collaborate/workgroups/networking/dccp
-+F: include/linux/dccp.h
-+F: include/linux/tfrc.h
-+F: include/uapi/linux/dccp.h
-+F: net/dccp/
-+
-+DECnet NETWORK LAYER
-+L: linux-decnet-user@lists.sourceforge.net
-+S: Orphan
-+W: http://linux-decnet.sourceforge.net
-+F: Documentation/networking/decnet.rst
-+F: net/decnet/
-+
-+DECSTATION PLATFORM SUPPORT
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-mips.org/wiki/DECstation
-+F: arch/mips/dec/
-+F: arch/mips/include/asm/dec/
-+F: arch/mips/include/asm/mach-dec/
-+
-+DEFXX FDDI NETWORK DRIVER
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+S: Maintained
-+F: drivers/net/fddi/defxx.*
-+
-+DEFZA FDDI NETWORK DRIVER
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+S: Maintained
-+F: drivers/net/fddi/defza.*
-+
-+DEINTERLACE DRIVERS FOR ALLWINNER H3
-+M: Jernej Skrabec <jernej.skrabec@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
-+F: drivers/media/platform/sunxi/sun8i-di/
-+
-+DELL LAPTOP DRIVER
-+M: Matthew Garrett <mjg59@srcf.ucam.org>
-+M: Pali Rohár <pali@kernel.org>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-laptop.c
-+
-+DELL LAPTOP FREEFALL DRIVER
-+M: Pali Rohár <pali@kernel.org>
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-smo8800.c
-+
-+DELL LAPTOP RBTN DRIVER
-+M: Pali Rohár <pali@kernel.org>
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-rbtn.*
-+
-+DELL LAPTOP SMM DRIVER
-+M: Pali Rohár <pali@kernel.org>
-+S: Maintained
-+F: drivers/hwmon/dell-smm-hwmon.c
-+F: include/uapi/linux/i8k.h
-+
-+DELL REMOTE BIOS UPDATE DRIVER
-+M: Stuart Hayes <stuart.w.hayes@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell_rbu.c
-+
-+DELL SMBIOS DRIVER
-+M: Pali Rohár <pali@kernel.org>
-+L: Dell.Client.Kernel@dell.com
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-smbios.*
-+
-+DELL SMBIOS SMM DRIVER
-+L: Dell.Client.Kernel@dell.com
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-smbios-smm.c
-+
-+DELL SMBIOS WMI DRIVER
-+L: Dell.Client.Kernel@dell.com
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-smbios-wmi.c
-+F: tools/wmi/dell-smbios-example.c
-+
-+DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
-+M: Stuart Hayes <stuart.w.hayes@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/driver-api/dcdbas.rst
-+F: drivers/platform/x86/dell/dcdbas.*
-+
-+DELL WMI DESCRIPTOR DRIVER
-+L: Dell.Client.Kernel@dell.com
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-wmi-descriptor.c
-+
-+DELL WMI SYSMAN DRIVER
-+M: Divya Bharathi <divya.bharathi@dell.com>
-+M: Prasanth Ksr <prasanth.ksr@dell.com>
-+L: Dell.Client.Kernel@dell.com
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-firmware-attributes
-+F: drivers/platform/x86/dell/dell-wmi-sysman/
-+
-+DELL WMI NOTIFICATIONS DRIVER
-+M: Matthew Garrett <mjg59@srcf.ucam.org>
-+M: Pali Rohár <pali@kernel.org>
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-wmi-base.c
-+
-+DELL WMI HARDWARE PRIVACY SUPPORT
-+M: Perry Yuan <Perry.Yuan@dell.com>
-+L: Dell.Client.Kernel@dell.com
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/dell/dell-wmi-privacy.c
-+
-+DELTA ST MEDIA DRIVER
-+M: Hugues Fruchet <hugues.fruchet@foss.st.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/platform/sti/delta
-+
-+DELTA DPS920AB PSU DRIVER
-+M: Robert Marko <robert.marko@sartura.hr>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/dps920ab.rst
-+F: drivers/hwmon/pmbus/dps920ab.c
-+
-+DENALI NAND DRIVER
-+L: linux-mtd@lists.infradead.org
-+S: Orphan
-+F: drivers/mtd/nand/raw/denali*
-+
-+DESIGNWARE EDMA CORE IP DRIVER
-+M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
-+L: dmaengine@vger.kernel.org
-+S: Maintained
-+F: drivers/dma/dw-edma/
-+F: include/linux/dma/edma.h
-+
-+DESIGNWARE XDATA IP DRIVER
-+M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/misc-devices/dw-xdata-pcie.rst
-+F: drivers/misc/dw-xdata-pcie.c
-+
-+DESIGNWARE USB2 DRD IP DRIVER
-+M: Minas Harutyunyan <hminas@synopsys.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-+F: drivers/usb/dwc2/
-+
-+DESIGNWARE USB3 DRD IP DRIVER
-+M: Felipe Balbi <balbi@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-+F: drivers/usb/dwc3/
-+
-+DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
-+M: Andreas Klinger <ak@it-klinger.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-iio-distance-srf08
-+F: drivers/iio/proximity/srf*.c
-+
-+DEVICE COREDUMP (DEV_COREDUMP)
-+M: Johannes Berg <johannes@sipsolutions.net>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/base/devcoredump.c
-+F: include/linux/devcoredump.h
-+
-+DEVICE DEPENDENCY HELPER SCRIPT
-+M: Saravana Kannan <saravanak@google.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: scripts/dev-needs.sh
-+
-+DEVICE DIRECT ACCESS (DAX)
-+M: Dan Williams <dan.j.williams@intel.com>
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+F: drivers/dax/
-+
-+DEVICE FREQUENCY (DEVFREQ)
-+M: MyungJoo Ham <myungjoo.ham@samsung.com>
-+M: Kyungmin Park <kyungmin.park@samsung.com>
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
-+F: Documentation/devicetree/bindings/devfreq/
-+F: drivers/devfreq/
-+F: include/linux/devfreq.h
-+F: include/trace/events/devfreq.h
-+
-+DEVICE FREQUENCY EVENT (DEVFREQ-EVENT)
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
-+F: Documentation/devicetree/bindings/devfreq/event/
-+F: drivers/devfreq/devfreq-event.c
-+F: drivers/devfreq/event/
-+F: include/dt-bindings/pmu/exynos_ppmu.h
-+F: include/linux/devfreq-event.h
-+
-+DEVICE NUMBER REGISTRY
-+M: Torben Mathiasen <device@lanana.org>
-+S: Maintained
-+W: http://lanana.org/docs/device-list/index.html
-+
-+DEVICE RESOURCE MANAGEMENT HELPERS
-+M: Hans de Goede <hdegoede@redhat.com>
-+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
-+S: Maintained
-+F: include/linux/devm-helpers.h
-+
-+DEVICE-MAPPER (LVM)
-+M: Alasdair Kergon <agk@redhat.com>
-+M: Mike Snitzer <snitzer@redhat.com>
-+M: dm-devel@redhat.com
-+L: dm-devel@redhat.com
-+S: Maintained
-+W: http://sources.redhat.com/dm
-+Q: http://patchwork.kernel.org/project/dm-devel/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git
-+T: quilt http://people.redhat.com/agk/patches/linux/editing/
-+F: Documentation/admin-guide/device-mapper/
-+F: drivers/md/Kconfig
-+F: drivers/md/Makefile
-+F: drivers/md/dm*
-+F: drivers/md/persistent-data/
-+F: include/linux/device-mapper.h
-+F: include/linux/dm-*.h
-+F: include/uapi/linux/dm-*.h
-+
-+DEVLINK
-+M: Jiri Pirko <jiri@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/devlink
-+F: include/net/devlink.h
-+F: include/uapi/linux/devlink.h
-+F: net/core/devlink.c
-+
-+DH ELECTRONICS IMX6 DHCOM BOARD SUPPORT
-+M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
-+L: kernel@dh-electronics.com
-+S: Maintained
-+F: arch/arm/boot/dts/imx6*-dhcom-*
-+
-+DH ELECTRONICS STM32MP1 DHCOM/DHCOR BOARD SUPPORT
-+M: Marek Vasut <marex@denx.de>
-+L: kernel@dh-electronics.com
-+S: Maintained
-+F: arch/arm/boot/dts/stm32mp1*-dhcom-*
-+F: arch/arm/boot/dts/stm32mp1*-dhcor-*
-+
-+DIALOG SEMICONDUCTOR DRIVERS
-+M: Support Opensource <support.opensource@diasemi.com>
-+S: Supported
-+W: http://www.dialog-semiconductor.com/products
-+F: Documentation/devicetree/bindings/input/da90??-onkey.txt
-+F: Documentation/devicetree/bindings/input/dlg,da72??.txt
-+F: Documentation/devicetree/bindings/mfd/da90*.txt
-+F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
-+F: Documentation/devicetree/bindings/regulator/da92*.txt
-+F: Documentation/devicetree/bindings/regulator/slg51000.txt
-+F: Documentation/devicetree/bindings/sound/da[79]*.txt
-+F: Documentation/devicetree/bindings/thermal/da90??-thermal.txt
-+F: Documentation/devicetree/bindings/watchdog/da90??-wdt.txt
-+F: Documentation/hwmon/da90??.rst
-+F: drivers/gpio/gpio-da90??.c
-+F: drivers/hwmon/da90??-hwmon.c
-+F: drivers/iio/adc/da91??-*.c
-+F: drivers/input/misc/da72??.[ch]
-+F: drivers/input/misc/da90??_onkey.c
-+F: drivers/input/touchscreen/da9052_tsi.c
-+F: drivers/leds/leds-da90??.c
-+F: drivers/mfd/da903x.c
-+F: drivers/mfd/da90??-*.c
-+F: drivers/mfd/da91??-*.c
-+F: drivers/pinctrl/pinctrl-da90??.c
-+F: drivers/power/supply/da9052-battery.c
-+F: drivers/power/supply/da91??-*.c
-+F: drivers/regulator/da9???-regulator.[ch]
-+F: drivers/regulator/slg51000-regulator.[ch]
-+F: drivers/rtc/rtc-da90??.c
-+F: drivers/thermal/da90??-thermal.c
-+F: drivers/video/backlight/da90??_bl.c
-+F: drivers/watchdog/da90??_wdt.c
-+F: include/dt-bindings/regulator/dlg,da9*-regulator.h
-+F: include/linux/mfd/da903x.h
-+F: include/linux/mfd/da9052/
-+F: include/linux/mfd/da9055/
-+F: include/linux/mfd/da9062/
-+F: include/linux/mfd/da9063/
-+F: include/linux/mfd/da9150/
-+F: include/linux/regulator/da9211.h
-+F: include/sound/da[79]*.h
-+F: sound/soc/codecs/da[79]*.[ch]
-+
-+DIAMOND SYSTEMS GPIO-MM GPIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-gpio-mm.c
-+
-+DIOLAN U2C-12 I2C DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-diolan-u2c.c
-+
-+DIRECTORY NOTIFICATION (DNOTIFY)
-+M: Jan Kara <jack@suse.cz>
-+R: Amir Goldstein <amir73il@gmail.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: Documentation/filesystems/dnotify.rst
-+F: fs/notify/dnotify/
-+F: include/linux/dnotify.h
-+
-+DISK GEOMETRY AND PARTITION HANDLING
-+M: Andries Brouwer <aeb@cwi.nl>
-+S: Maintained
-+W: http://www.win.tue.nl/~aeb/linux/Large-Disk.html
-+W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
-+W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
-+
-+DISKQUOTA
-+M: Jan Kara <jack@suse.com>
-+S: Maintained
-+F: Documentation/filesystems/quota.rst
-+F: fs/quota/
-+F: include/linux/quota*.h
-+F: include/uapi/linux/quota*.h
-+
-+DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB)
-+M: Bernie Thompson <bernie@plugable.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+W: http://plugable.com/category/projects/udlfb/
-+F: Documentation/fb/udlfb.rst
-+F: drivers/video/fbdev/udlfb.c
-+F: include/video/udlfb.h
-+
-+DISTRIBUTED LOCK MANAGER (DLM)
-+M: Christine Caulfield <ccaulfie@redhat.com>
-+M: David Teigland <teigland@redhat.com>
-+L: cluster-devel@redhat.com
-+S: Supported
-+W: http://sources.redhat.com/cluster/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git
-+F: fs/dlm/
-+
-+DMA BUFFER SHARING FRAMEWORK
-+M: Sumit Semwal <sumit.semwal@linaro.org>
-+M: Christian König <christian.koenig@amd.com>
-+L: linux-media@vger.kernel.org
-+L: dri-devel@lists.freedesktop.org
-+L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/driver-api/dma-buf.rst
-+F: drivers/dma-buf/
-+F: include/linux/*fence.h
-+F: include/linux/dma-buf*
-+F: include/linux/dma-resv.h
-+K: \bdma_(?:buf|fence|resv)\b
-+
-+DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
-+M: Vinod Koul <vkoul@kernel.org>
-+L: dmaengine@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git
-+F: Documentation/devicetree/bindings/dma/
-+F: Documentation/driver-api/dmaengine/
-+F: drivers/dma/
-+F: include/linux/dma/
-+F: include/linux/dmaengine.h
-+F: include/linux/of_dma.h
-+
-+DMA MAPPING HELPERS
-+M: Christoph Hellwig <hch@lst.de>
-+M: Marek Szyprowski <m.szyprowski@samsung.com>
-+R: Robin Murphy <robin.murphy@arm.com>
-+L: iommu@lists.linux-foundation.org
-+S: Supported
-+W: http://git.infradead.org/users/hch/dma-mapping.git
-+T: git git://git.infradead.org/users/hch/dma-mapping.git
-+F: include/asm-generic/dma-mapping.h
-+F: include/linux/dma-direct.h
-+F: include/linux/dma-mapping.h
-+F: include/linux/dma-map-ops.h
-+F: kernel/dma/
-+
-+DMA MAPPING BENCHMARK
-+M: Barry Song <song.bao.hua@hisilicon.com>
-+L: iommu@lists.linux-foundation.org
-+F: kernel/dma/map_benchmark.c
-+F: tools/testing/selftests/dma/
-+
-+DMA-BUF HEAPS FRAMEWORK
-+M: Sumit Semwal <sumit.semwal@linaro.org>
-+R: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-+R: Liam Mark <lmark@codeaurora.org>
-+R: Laura Abbott <labbott@redhat.com>
-+R: Brian Starkey <Brian.Starkey@arm.com>
-+R: John Stultz <john.stultz@linaro.org>
-+L: linux-media@vger.kernel.org
-+L: dri-devel@lists.freedesktop.org
-+L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/dma-buf/dma-heap.c
-+F: drivers/dma-buf/heaps/*
-+F: include/linux/dma-heap.h
-+F: include/uapi/linux/dma-heap.h
-+
-+DMC FREQUENCY DRIVER FOR SAMSUNG EXYNOS5422
-+M: Lukasz Luba <lukasz.luba@arm.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
-+F: drivers/memory/samsung/exynos5422-dmc.c
-+
-+DME1737 HARDWARE MONITOR DRIVER
-+M: Juerg Haefliger <juergh@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/dme1737.rst
-+F: drivers/hwmon/dme1737.c
-+
-+DMI/SMBIOS SUPPORT
-+M: Jean Delvare <jdelvare@suse.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging.git dmi-for-next
-+F: Documentation/ABI/testing/sysfs-firmware-dmi-tables
-+F: drivers/firmware/dmi-id.c
-+F: drivers/firmware/dmi_scan.c
-+F: include/linux/dmi.h
-+
-+DOCUMENTATION
-+M: Jonathan Corbet <corbet@lwn.net>
-+L: linux-doc@vger.kernel.org
-+S: Maintained
-+P: Documentation/doc-guide/maintainer-profile.rst
-+T: git git://git.lwn.net/linux.git docs-next
-+F: Documentation/
-+F: scripts/documentation-file-ref-check
-+F: scripts/kernel-doc
-+F: scripts/sphinx-pre-install
-+X: Documentation/ABI/
-+X: Documentation/admin-guide/media/
-+X: Documentation/devicetree/
-+X: Documentation/driver-api/media/
-+X: Documentation/firmware-guide/acpi/
-+X: Documentation/i2c/
-+X: Documentation/power/
-+X: Documentation/spi/
-+X: Documentation/userspace-api/media/
-+
-+DOCUMENTATION REPORTING ISSUES
-+M: Thorsten Leemhuis <linux@leemhuis.info>
-+L: linux-doc@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/reporting-issues.rst
-+
-+DOCUMENTATION SCRIPTS
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-doc@vger.kernel.org
-+S: Maintained
-+F: Documentation/sphinx/parse-headers.pl
-+F: scripts/documentation-file-ref-check
-+F: scripts/sphinx-pre-install
-+
-+DOCUMENTATION/ITALIAN
-+M: Federico Vaga <federico.vaga@vaga.pv.it>
-+L: linux-doc@vger.kernel.org
-+S: Maintained
-+F: Documentation/translations/it_IT
-+
-+DONGWOON DW9714 LENS VOICE COIL DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt
-+F: drivers/media/i2c/dw9714.c
-+
-+DONGWOON DW9768 LENS VOICE COIL DRIVER
-+M: Dongchun Zhu <dongchun.zhu@mediatek.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml
-+F: drivers/media/i2c/dw9768.c
-+
-+DONGWOON DW9807 LENS VOICE COIL DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt
-+F: drivers/media/i2c/dw9807-vcm.c
-+
-+DOUBLETALK DRIVER
-+M: "James R. Van Zandt" <jrv@vanzandt.mv.com>
-+L: blinux-list@redhat.com
-+S: Maintained
-+F: drivers/char/dtlk.c
-+F: include/linux/dtlk.h
-+
-+DPAA2 DATAPATH I/O (DPIO) DRIVER
-+M: Roy Pledge <Roy.Pledge@nxp.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/soc/fsl/dpio
-+
-+DPAA2 ETHERNET DRIVER
-+M: Ioana Ciornei <ioana.ciornei@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/ethernet-driver.rst
-+F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support.rst
-+F: drivers/net/ethernet/freescale/dpaa2/Kconfig
-+F: drivers/net/ethernet/freescale/dpaa2/Makefile
-+F: drivers/net/ethernet/freescale/dpaa2/dpaa2-eth*
-+F: drivers/net/ethernet/freescale/dpaa2/dpaa2-mac*
-+F: drivers/net/ethernet/freescale/dpaa2/dpkg.h
-+F: drivers/net/ethernet/freescale/dpaa2/dpmac*
-+F: drivers/net/ethernet/freescale/dpaa2/dpni*
-+
-+DPAA2 ETHERNET SWITCH DRIVER
-+M: Ioana Ciornei <ioana.ciornei@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-driver.rst
-+F: drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
-+F: drivers/net/ethernet/freescale/dpaa2/dpsw*
-+
-+DPT_I2O SCSI RAID DRIVER
-+M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+W: http://www.adaptec.com/
-+F: drivers/scsi/dpt*
-+F: drivers/scsi/dpt/
-+
-+DRBD DRIVER
-+M: Philipp Reisner <philipp.reisner@linbit.com>
-+M: Lars Ellenberg <lars.ellenberg@linbit.com>
-+L: drbd-dev@lists.linbit.com
-+S: Supported
-+W: http://www.drbd.org
-+T: git git://git.linbit.com/linux-drbd.git
-+T: git git://git.linbit.com/drbd-8.4.git
-+F: Documentation/admin-guide/blockdev/
-+F: drivers/block/drbd/
-+F: lib/lru_cache.c
-+
-+DRIVER COMPONENT FRAMEWORK
-+L: dri-devel@lists.freedesktop.org
-+F: drivers/base/component.c
-+F: include/linux/component.h
-+
-+DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+R: "Rafael J. Wysocki" <rafael@kernel.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
-+F: Documentation/core-api/kobject.rst
-+F: drivers/base/
-+F: fs/debugfs/
-+F: fs/sysfs/
-+F: include/linux/debugfs.h
-+F: include/linux/kobj*
-+F: lib/kobj*
-+
-+DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
-+M: Nishanth Menon <nm@ti.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: drivers/soc/ti/smartreflex.c
-+F: include/linux/power/smartreflex.h
-+
-+DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
-+M: Maxime Ripard <mripard@kernel.org>
-+M: Chen-Yu Tsai <wens@csie.org>
-+R: Jernej Skrabec <jernej.skrabec@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/sun4i/sun8i*
-+
-+DRM DRIVER FOR ARM PL111 CLCD
-+M: Emma Anholt <emma@anholt.net>
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/pl111/
-+
-+DRM DRIVER FOR ARM VERSATILE TFT PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
-+F: drivers/gpu/drm/panel/panel-arm-versatile.c
-+
-+DRM DRIVER FOR ASPEED BMC GFX
-+M: Joel Stanley <joel@jms.id.au>
-+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/gpu/aspeed-gfx.txt
-+F: drivers/gpu/drm/aspeed/
-+
-+DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
-+M: Dave Airlie <airlied@redhat.com>
-+R: Thomas Zimmermann <tzimmermann@suse.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/ast/
-+
-+DRM DRIVER FOR BOCHS VIRTUAL GPU
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/tiny/bochs.c
-+
-+DRM DRIVER FOR BOE HIMAX8279D PANELS
-+M: Jerry Han <hanxu5@huaqin.corp-partner.google.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/boe,himax8279d.yaml
-+F: drivers/gpu/drm/panel/panel-boe-himax8279d.c
-+
-+DRM DRIVER FOR CHIPONE ICN6211 MIPI-DSI to RGB CONVERTER BRIDGE
-+M: Jagan Teki <jagan@amarulasolutions.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml
-+F: drivers/gpu/drm/bridge/chipone-icn6211.c
-+
-+DRM DRIVER FOR FARADAY TVE200 TV ENCODER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/tve200/
-+
-+DRM DRIVER FOR FEIXIN K101 IM2BA02 MIPI-DSI LCD PANELS
-+M: Icenowy Zheng <icenowy@aosc.io>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/feixin,k101-im2ba02.yaml
-+F: drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c
-+
-+DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS
-+M: Jagan Teki <jagan@amarulasolutions.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml
-+F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
-+
-+DRM DRIVER FOR GENERIC USB DISPLAY
-+M: Noralf Trønnes <noralf@tronnes.org>
-+S: Maintained
-+W: https://github.com/notro/gud/wiki
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/gud/
-+F: include/drm/gud.h
-+
-+DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS
-+M: Hans de Goede <hdegoede@redhat.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/tiny/gm12u320.c
-+
-+DRM DRIVER FOR HX8357D PANELS
-+M: Emma Anholt <emma@anholt.net>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/himax,hx8357d.txt
-+F: drivers/gpu/drm/tiny/hx8357d.c
-+
-+DRM DRIVER FOR ILITEK ILI9225 PANELS
-+M: David Lechner <david@lechnology.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/ilitek,ili9225.txt
-+F: drivers/gpu/drm/tiny/ili9225.c
-+
-+DRM DRIVER FOR ILITEK ILI9486 PANELS
-+M: Kamlesh Gurudasani <kamlesh.gurudasani@gmail.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
-+F: drivers/gpu/drm/tiny/ili9486.c
-+
-+DRM DRIVER FOR INTEL I810 VIDEO CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/i810/
-+F: include/uapi/drm/i810_drm.h
-+
-+DRM DRIVER FOR LVDS PANELS
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: dri-devel@lists.freedesktop.org
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+S: Maintained
-+F: drivers/gpu/drm/panel/panel-lvds.c
-+F: Documentation/devicetree/bindings/display/panel/lvds.yaml
-+
-+DRM DRIVER FOR MANTIX MLAF057WE51 PANELS
-+M: Guido Günther <agx@sigxcpu.org>
-+R: Purism Kernel Team <kernel@puri.sm>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml
-+F: drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
-+
-+DRM DRIVER FOR MATROX G200/G400 GRAPHICS CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/mga/
-+F: include/uapi/drm/mga_drm.h
-+
-+DRM DRIVER FOR MGA G200 GRAPHICS CHIPS
-+M: Dave Airlie <airlied@redhat.com>
-+R: Thomas Zimmermann <tzimmermann@suse.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/mgag200/
-+
-+DRM DRIVER FOR MI0283QT
-+M: Noralf Trønnes <noralf@tronnes.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
-+F: drivers/gpu/drm/tiny/mi0283qt.c
-+
-+DRM DRIVER FOR MSM ADRENO GPU
-+M: Rob Clark <robdclark@gmail.com>
-+M: Sean Paul <sean@poorly.run>
-+L: linux-arm-msm@vger.kernel.org
-+L: dri-devel@lists.freedesktop.org
-+L: freedreno@lists.freedesktop.org
-+S: Maintained
-+T: git https://gitlab.freedesktop.org/drm/msm.git
-+F: Documentation/devicetree/bindings/display/msm/
-+F: drivers/gpu/drm/msm/
-+F: include/uapi/drm/msm_drm.h
-+
-+DRM DRIVER FOR NOVATEK NT35510 PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
-+F: drivers/gpu/drm/panel/panel-novatek-nt35510.c
-+
-+DRM DRIVER FOR NOVATEK NT36672A PANELS
-+M: Sumit Semwal <sumit.semwal@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
-+F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
-+
-+DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
-+M: Ben Skeggs <bskeggs@redhat.com>
-+L: dri-devel@lists.freedesktop.org
-+L: nouveau@lists.freedesktop.org
-+S: Supported
-+T: git git://github.com/skeggsb/linux
-+F: drivers/gpu/drm/nouveau/
-+F: include/uapi/drm/nouveau_drm.h
-+
-+DRM DRIVER FOR OLIMEX LCD-OLINUXINO PANELS
-+M: Stefan Mavrodiev <stefan@olimex.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino.yaml
-+F: drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
-+
-+DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS
-+M: Noralf Trønnes <noralf@tronnes.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/repaper.txt
-+F: drivers/gpu/drm/tiny/repaper.c
-+
-+DRM DRIVER FOR QEMU'S CIRRUS DEVICE
-+M: Dave Airlie <airlied@redhat.com>
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Obsolete
-+W: https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/tiny/cirrus.c
-+
-+DRM DRIVER FOR QXL VIRTUAL GPU
-+M: Dave Airlie <airlied@redhat.com>
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+L: spice-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/qxl/
-+F: include/uapi/drm/qxl_drm.h
-+
-+DRM DRIVER FOR RAGE 128 VIDEO CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/r128/
-+F: include/uapi/drm/r128_drm.h
-+
-+DRM DRIVER FOR RAYDIUM RM67191 PANELS
-+M: Robert Chiras <robert.chiras@nxp.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml
-+F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
-+
-+DRM DRIVER FOR SAMSUNG DB7430 PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
-+F: drivers/gpu/drm/panel/panel-samsung-db7430.c
-+
-+DRM DRIVER FOR SITRONIX ST7703 PANELS
-+M: Guido Günther <agx@sigxcpu.org>
-+R: Purism Kernel Team <kernel@puri.sm>
-+R: Ondrej Jirman <megous@megous.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
-+F: drivers/gpu/drm/panel/panel-sitronix-st7703.c
-+
-+DRM DRIVER FOR SAVAGE VIDEO CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/savage/
-+F: include/uapi/drm/savage_drm.h
-+
-+DRM DRIVER FOR SIMPLE FRAMEBUFFERS
-+M: Thomas Zimmermann <tzimmermann@suse.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/tiny/simpledrm.c
-+
-+DRM DRIVER FOR SIS VIDEO CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/sis/
-+F: include/uapi/drm/sis_drm.h
-+
-+DRM DRIVER FOR SITRONIX ST7586 PANELS
-+M: David Lechner <david@lechnology.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/sitronix,st7586.txt
-+F: drivers/gpu/drm/tiny/st7586.c
-+
-+DRM DRIVER FOR SITRONIX ST7701 PANELS
-+M: Jagan Teki <jagan@amarulasolutions.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
-+F: drivers/gpu/drm/panel/panel-sitronix-st7701.c
-+
-+DRM DRIVER FOR SITRONIX ST7735R PANELS
-+M: David Lechner <david@lechnology.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
-+F: drivers/gpu/drm/tiny/st7735r.c
-+
-+DRM DRIVER FOR SONY ACX424AKP PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/panel/panel-sony-acx424akp.c
-+
-+DRM DRIVER FOR ST-ERICSSON MCDE
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/ste,mcde.yaml
-+F: drivers/gpu/drm/mcde/
-+
-+DRM DRIVER FOR TDFX VIDEO CARDS
-+S: Orphan / Obsolete
-+F: drivers/gpu/drm/tdfx/
-+
-+DRM DRIVER FOR TPO TPG110 PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
-+F: drivers/gpu/drm/panel/panel-tpo-tpg110.c
-+
-+DRM DRIVER FOR USB DISPLAYLINK VIDEO ADAPTERS
-+M: Dave Airlie <airlied@redhat.com>
-+R: Sean Paul <sean@poorly.run>
-+R: Thomas Zimmermann <tzimmermann@suse.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/udl/
-+
-+DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
-+M: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com>
-+M: Melissa Wen <melissa.srw@gmail.com>
-+R: Haneen Mohammed <hamohammed.sa@gmail.com>
-+R: Daniel Vetter <daniel@ffwll.ch>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/gpu/vkms.rst
-+F: drivers/gpu/drm/vkms/
-+
-+DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/vboxvideo/
-+
-+DRM DRIVER FOR VMWARE VIRTUAL GPU
-+M: "VMware Graphics" <linux-graphics-maintainer@vmware.com>
-+M: Zack Rusin <zackr@vmware.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/vmwgfx/
-+F: include/uapi/drm/vmwgfx_drm.h
-+
-+DRM DRIVER FOR WIDECHIPS WS2401 PANELS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
-+F: drivers/gpu/drm/panel/panel-widechips-ws2401.c
-+
-+DRM DRIVERS
-+M: David Airlie <airlied@linux.ie>
-+M: Daniel Vetter <daniel@ffwll.ch>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+B: https://gitlab.freedesktop.org/drm
-+C: irc://irc.oftc.net/dri-devel
-+T: git git://anongit.freedesktop.org/drm/drm
-+F: Documentation/devicetree/bindings/display/
-+F: Documentation/devicetree/bindings/gpu/
-+F: Documentation/gpu/
-+F: drivers/gpu/
-+F: include/drm/
-+F: include/linux/vga*
-+F: include/uapi/drm/
-+
-+DRM DRIVERS AND MISC GPU PATCHES
-+M: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-+M: Maxime Ripard <mripard@kernel.org>
-+M: Thomas Zimmermann <tzimmermann@suse.de>
-+S: Maintained
-+W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/gpu/
-+F: drivers/gpu/drm/*
-+F: drivers/gpu/vga/
-+F: include/drm/drm*
-+F: include/linux/vga*
-+F: include/uapi/drm/drm*
-+
-+DRM DRIVERS FOR ALLWINNER A10
-+M: Maxime Ripard <mripard@kernel.org>
-+M: Chen-Yu Tsai <wens@csie.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/allwinner*
-+F: drivers/gpu/drm/sun4i/
-+
-+DRM DRIVERS FOR AMLOGIC SOCS
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: dri-devel@lists.freedesktop.org
-+L: linux-amlogic@lists.infradead.org
-+S: Supported
-+W: http://linux-meson.com/
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
-+F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
-+F: Documentation/gpu/meson.rst
-+F: drivers/gpu/drm/meson/
-+
-+DRM DRIVERS FOR ATMEL HLCDC
-+M: Sam Ravnborg <sam@ravnborg.org>
-+M: Boris Brezillon <bbrezillon@kernel.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/atmel/
-+F: drivers/gpu/drm/atmel-hlcdc/
-+
-+DRM DRIVERS FOR BRIDGE CHIPS
-+M: Andrzej Hajda <a.hajda@samsung.com>
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+M: Robert Foss <robert.foss@linaro.org>
-+R: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
-+R: Jonas Karlman <jonas@kwiboo.se>
-+R: Jernej Skrabec <jernej.skrabec@gmail.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/bridge/
-+
-+DRM DRIVERS FOR EXYNOS
-+M: Inki Dae <inki.dae@samsung.com>
-+M: Joonyoung Shim <jy0922.shim@samsung.com>
-+M: Seung-Woo Kim <sw0312.kim@samsung.com>
-+M: Kyungmin Park <kyungmin.park@samsung.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
-+F: Documentation/devicetree/bindings/display/exynos/
-+F: drivers/gpu/drm/exynos/
-+F: include/uapi/drm/exynos_drm.h
-+
-+DRM DRIVERS FOR FREESCALE DCU
-+M: Stefan Agner <stefan@agner.ch>
-+M: Alison Wang <alison.wang@nxp.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/fsl,dcu.txt
-+F: Documentation/devicetree/bindings/display/fsl,tcon.txt
-+F: drivers/gpu/drm/fsl-dcu/
-+
-+DRM DRIVERS FOR FREESCALE IMX
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/imx/
-+F: drivers/gpu/drm/imx/
-+F: drivers/gpu/ipu-v3/
-+
-+DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
-+M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://github.com/patjak/drm-gma500
-+F: drivers/gpu/drm/gma500/
-+
-+DRM DRIVERS FOR HISILICON
-+M: Xinliang Liu <xinliang.liu@linaro.org>
-+M: Tian Tao <tiantao6@hisilicon.com>
-+R: John Stultz <john.stultz@linaro.org>
-+R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
-+R: Chen Feng <puck.chen@hisilicon.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/hisilicon/
-+F: drivers/gpu/drm/hisilicon/
-+
-+DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE
-+M: Deepak Rawat <drawat.floss@gmail.com>
-+L: linux-hyperv@vger.kernel.org
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/hyperv
-+
-+DRM DRIVERS FOR LIMA
-+M: Qiang Yu <yuq825@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+L: lima@lists.freedesktop.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/lima/
-+F: include/uapi/drm/lima_drm.h
-+
-+DRM DRIVERS FOR MEDIATEK
-+M: Chun-Kuang Hu <chunkuang.hu@kernel.org>
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: dri-devel@lists.freedesktop.org
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/display/mediatek/
-+F: drivers/gpu/drm/mediatek/
-+F: drivers/phy/mediatek/phy-mtk-hdmi*
-+F: drivers/phy/mediatek/phy-mtk-mipi*
-+
-+DRM DRIVERS FOR NVIDIA TEGRA
-+M: Thierry Reding <thierry.reding@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+L: linux-tegra@vger.kernel.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/tegra/linux.git
-+F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
-+F: drivers/gpu/drm/tegra/
-+F: drivers/gpu/host1x/
-+F: include/linux/host1x.h
-+F: include/uapi/drm/tegra_drm.h
-+
-+DRM DRIVERS FOR RENESAS
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+L: dri-devel@lists.freedesktop.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/pinchartl/media drm/du/next
-+F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
-+F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
-+F: Documentation/devicetree/bindings/display/renesas,du.yaml
-+F: drivers/gpu/drm/rcar-du/
-+F: drivers/gpu/drm/shmobile/
-+F: include/linux/platform_data/shmob_drm.h
-+
-+DRM DRIVERS FOR ROCKCHIP
-+M: Sandy Huang <hjc@rock-chips.com>
-+M: Heiko Stübner <heiko@sntech.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/rockchip/
-+F: drivers/gpu/drm/rockchip/
-+
-+DRM DRIVERS FOR STI
-+M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/st,stih4xx.txt
-+F: drivers/gpu/drm/sti
-+
-+DRM DRIVERS FOR STM
-+M: Yannick Fertre <yannick.fertre@foss.st.com>
-+M: Philippe Cornu <philippe.cornu@foss.st.com>
-+M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
-+F: drivers/gpu/drm/stm
-+
-+DRM DRIVERS FOR TI KEYSTONE
-+M: Jyri Sarha <jyri.sarha@iki.fi>
-+M: Tomi Valkeinen <tomba@kernel.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
-+F: Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
-+F: Documentation/devicetree/bindings/display/ti/ti,k2g-dss.yaml
-+F: drivers/gpu/drm/tidss/
-+
-+DRM DRIVERS FOR TI LCDC
-+M: Jyri Sarha <jyri.sarha@iki.fi>
-+R: Tomi Valkeinen <tomba@kernel.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/tilcdc/
-+F: drivers/gpu/drm/tilcdc/
-+
-+DRM DRIVERS FOR TI OMAP
-+M: Tomi Valkeinen <tomba@kernel.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/ti/
-+F: drivers/gpu/drm/omapdrm/
-+
-+DRM DRIVERS FOR V3D
-+M: Emma Anholt <emma@anholt.net>
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml
-+F: drivers/gpu/drm/v3d/
-+F: include/uapi/drm/v3d_drm.h
-+
-+DRM DRIVERS FOR VC4
-+M: Emma Anholt <emma@anholt.net>
-+M: Maxime Ripard <mripard@kernel.org>
-+S: Supported
-+T: git git://github.com/anholt/linux
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml
-+F: drivers/gpu/drm/vc4/
-+F: include/uapi/drm/vc4_drm.h
-+
-+DRM DRIVERS FOR VIVANTE GPU IP
-+M: Lucas Stach <l.stach@pengutronix.de>
-+R: Russell King <linux+etnaviv@armlinux.org.uk>
-+R: Christian Gmeiner <christian.gmeiner@gmail.com>
-+L: etnaviv@lists.freedesktop.org (moderated for non-subscribers)
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpu/vivante,gc.yaml
-+F: drivers/gpu/drm/etnaviv/
-+F: include/uapi/drm/etnaviv_drm.h
-+
-+DRM DRIVERS FOR XEN
-+M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
-+L: dri-devel@lists.freedesktop.org
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/gpu/xen-front.rst
-+F: drivers/gpu/drm/xen/
-+
-+DRM DRIVERS FOR XILINX
-+M: Hyun Kwon <hyun.kwon@xilinx.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/xlnx/
-+F: drivers/gpu/drm/xlnx/
-+
-+DRM PANEL DRIVERS
-+M: Thierry Reding <thierry.reding@gmail.com>
-+R: Sam Ravnborg <sam@ravnborg.org>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/panel/
-+F: drivers/gpu/drm/drm_panel.c
-+F: drivers/gpu/drm/panel/
-+F: include/drm/drm_panel.h
-+
-+DRM TTM SUBSYSTEM
-+M: Christian Koenig <christian.koenig@amd.com>
-+M: Huang Rui <ray.huang@amd.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/ttm/
-+F: include/drm/ttm/
-+
-+DSBR100 USB FM RADIO DRIVER
-+M: Alexey Klimov <klimov.linux@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/dsbr100.c
-+
-+DT3155 MEDIA DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/dt3155/
-+
-+DVB_USB_AF9015 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/af9015*
-+
-+DVB_USB_AF9035 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/af9035*
-+
-+DVB_USB_ANYSEE MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/anysee*
-+
-+DVB_USB_AU6610 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/au6610*
-+
-+DVB_USB_CE6230 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/ce6230*
-+
-+DVB_USB_CXUSB MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/dvb-usb/cxusb*
-+
-+DVB_USB_EC168 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/ec168*
-+
-+DVB_USB_GL861 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/gl861*
-+
-+DVB_USB_MXL111SF MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/mxl111sf.git
-+F: drivers/media/usb/dvb-usb-v2/mxl111sf*
-+
-+DVB_USB_RTL28XXU MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/rtl28xxu*
-+
-+DVB_USB_V2 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/dvb-usb-v2/dvb_usb*
-+F: drivers/media/usb/dvb-usb-v2/usb_urb.c
-+
-+DYNAMIC DEBUG
-+M: Jason Baron <jbaron@akamai.com>
-+S: Maintained
-+F: include/linux/dynamic_debug.h
-+F: lib/dynamic_debug.c
-+
-+DYNAMIC INTERRUPT MODERATION
-+M: Tal Gilboa <talgi@nvidia.com>
-+S: Maintained
-+F: Documentation/networking/net_dim.rst
-+F: include/linux/dim.h
-+F: lib/dim/
-+
-+DZ DECSTATION DZ11 SERIAL DRIVER
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+S: Maintained
-+F: drivers/tty/serial/dz.*
-+
-+E3X0 POWER BUTTON DRIVER
-+M: Moritz Fischer <moritz.fischer@ettus.com>
-+L: usrp-users@lists.ettus.com
-+S: Supported
-+W: http://www.ettus.com
-+F: Documentation/devicetree/bindings/input/e3x0-button.txt
-+F: drivers/input/misc/e3x0-button.c
-+
-+E4000 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/e4000*
-+
-+EARTH_PT1 MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/pci/pt1/
-+
-+EARTH_PT3 MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/pci/pt3/
-+
-+EC100 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/ec100*
-+
-+ECRYPT FILE SYSTEM
-+M: Tyler Hicks <code@tyhicks.com>
-+L: ecryptfs@vger.kernel.org
-+S: Odd Fixes
-+W: http://ecryptfs.org
-+W: https://launchpad.net/ecryptfs
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git
-+F: Documentation/filesystems/ecryptfs.rst
-+F: fs/ecryptfs/
-+
-+EDAC-AMD64
-+M: Yazen Ghannam <yazen.ghannam@amd.com>
-+L: linux-edac@vger.kernel.org
-+S: Supported
-+F: drivers/edac/amd64_edac*
-+F: drivers/edac/mce_amd*
-+
-+EDAC-ARMADA
-+M: Jan Luebbe <jlu@pengutronix.de>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml
-+F: drivers/edac/armada_xp_*
-+
-+EDAC-AST2500
-+M: Stefan Schaeckeler <sschaeck@cisco.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt
-+F: drivers/edac/aspeed_edac.c
-+
-+EDAC-BLUEFIELD
-+M: Shravan Kumar Ramani <shravankr@nvidia.com>
-+S: Supported
-+F: drivers/edac/bluefield_edac.c
-+
-+EDAC-CALXEDA
-+M: Andre Przywara <andre.przywara@arm.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/highbank*
-+
-+EDAC-CAVIUM OCTEON
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-edac@vger.kernel.org
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: drivers/edac/octeon_edac*
-+
-+EDAC-CAVIUM THUNDERX
-+M: Robert Richter <rric@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/edac/thunderx_edac*
-+
-+EDAC-CORE
-+M: Borislav Petkov <bp@alien8.de>
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+M: Tony Luck <tony.luck@intel.com>
-+R: James Morse <james.morse@arm.com>
-+R: Robert Richter <rric@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras.git edac-for-next
-+F: Documentation/admin-guide/ras.rst
-+F: Documentation/driver-api/edac.rst
-+F: drivers/edac/
-+F: include/linux/edac.h
-+
-+EDAC-DMC520
-+M: Lei Wang <lewan@microsoft.com>
-+L: linux-edac@vger.kernel.org
-+S: Supported
-+F: drivers/edac/dmc520_edac.c
-+
-+EDAC-E752X
-+M: Mark Gross <mark.gross@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/e752x_edac.c
-+
-+EDAC-E7XXX
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/e7xxx_edac.c
-+
-+EDAC-FSL_DDR
-+M: York Sun <york.sun@nxp.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/fsl_ddr_edac.*
-+
-+EDAC-GHES
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/ghes_edac.c
-+
-+EDAC-I10NM
-+M: Tony Luck <tony.luck@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i10nm_base.c
-+
-+EDAC-I3000
-+L: linux-edac@vger.kernel.org
-+S: Orphan
-+F: drivers/edac/i3000_edac.c
-+
-+EDAC-I5000
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i5000_edac.c
-+
-+EDAC-I5400
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i5400_edac.c
-+
-+EDAC-I7300
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i7300_edac.c
-+
-+EDAC-I7CORE
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i7core_edac.c
-+
-+EDAC-I82443BXGX
-+M: Tim Small <tim@buttersideup.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i82443bxgx_edac.c
-+
-+EDAC-I82975X
-+M: "Arvind R." <arvino55@gmail.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/i82975x_edac.c
-+
-+EDAC-IE31200
-+M: Jason Baron <jbaron@akamai.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/ie31200_edac.c
-+
-+EDAC-IGEN6
-+M: Tony Luck <tony.luck@intel.com>
-+R: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/igen6_edac.c
-+
-+EDAC-MPC85XX
-+M: Johannes Thumshirn <morbidrsa@gmail.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/mpc85xx_edac.[ch]
-+
-+EDAC-PASEMI
-+M: Egor Martovetsky <egor@pasemi.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/pasemi_edac.c
-+
-+EDAC-PND2
-+M: Tony Luck <tony.luck@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/pnd2_edac.[ch]
-+
-+EDAC-QCOM
-+M: Channagoud Kadabi <ckadabi@codeaurora.org>
-+M: Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org>
-+L: linux-arm-msm@vger.kernel.org
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/qcom_edac.c
-+
-+EDAC-R82600
-+M: Tim Small <tim@buttersideup.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/r82600_edac.c
-+
-+EDAC-SBRIDGE
-+M: Tony Luck <tony.luck@intel.com>
-+R: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/sb_edac.c
-+
-+EDAC-SIFIVE
-+M: Yash Shah <yash.shah@sifive.com>
-+L: linux-edac@vger.kernel.org
-+S: Supported
-+F: drivers/edac/sifive_edac.c
-+
-+EDAC-SKYLAKE
-+M: Tony Luck <tony.luck@intel.com>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: drivers/edac/skx_*.[ch]
-+
-+EDAC-TI
-+M: Tero Kristo <kristo@kernel.org>
-+L: linux-edac@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/edac/ti_edac.c
-+
-+EDIROL UA-101/UA-1000 DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: sound/usb/misc/ua101.c
-+
-+EFI TEST DRIVER
-+M: Ivan Hu <ivan.hu@canonical.com>
-+M: Ard Biesheuvel <ardb@kernel.org>
-+L: linux-efi@vger.kernel.org
-+S: Maintained
-+F: drivers/firmware/efi/test/
-+
-+EFI VARIABLE FILESYSTEM
-+M: Matthew Garrett <matthew.garrett@nebula.com>
-+M: Jeremy Kerr <jk@ozlabs.org>
-+M: Ard Biesheuvel <ardb@kernel.org>
-+L: linux-efi@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
-+F: fs/efivarfs/
-+
-+EFIFB FRAMEBUFFER DRIVER
-+M: Peter Jones <pjones@redhat.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/efifb.c
-+
-+EFS FILESYSTEM
-+S: Orphan
-+W: http://aeschi.ch.eu.org/efs/
-+F: fs/efs/
-+
-+EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
-+M: Douglas Miller <dougmill@linux.ibm.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/ibm/ehea/
-+
-+EM28XX VIDEO4LINUX DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/em28xx*
-+F: drivers/media/usb/em28xx/
-+
-+EMBEDDED LINUX
-+M: Matt Mackall <mpm@selenic.com>
-+M: David Woodhouse <dwmw2@infradead.org>
-+L: linux-embedded@vger.kernel.org
-+S: Maintained
-+
-+EMMC CMDQ HOST CONTROLLER INTERFACE (CQHCI) DRIVER
-+M: Adrian Hunter <adrian.hunter@intel.com>
-+M: Ritesh Harjani <riteshh@codeaurora.org>
-+M: Asutosh Das <asutoshd@codeaurora.org>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/cqhci*
-+
-+EMULEX 10Gbps iSCSI - OneConnect DRIVER
-+M: Subbu Seetharaman <subbu.seetharaman@broadcom.com>
-+M: Ketan Mukadam <ketan.mukadam@broadcom.com>
-+M: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.broadcom.com
-+F: drivers/scsi/be2iscsi/
-+
-+EMULEX 10Gbps NIC BE2, BE3-R, Lancer, Skyhawk-R DRIVER (be2net)
-+M: Ajit Khaparde <ajit.khaparde@broadcom.com>
-+M: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
-+M: Somnath Kotur <somnath.kotur@broadcom.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.emulex.com
-+F: drivers/net/ethernet/emulex/benet/
-+
-+EMULEX ONECONNECT ROCE DRIVER
-+M: Selvin Xavier <selvin.xavier@broadcom.com>
-+L: linux-rdma@vger.kernel.org
-+S: Odd Fixes
-+W: http://www.broadcom.com
-+F: drivers/infiniband/hw/ocrdma/
-+F: include/uapi/rdma/ocrdma-abi.h
-+
-+EMULEX/BROADCOM LPFC FC/FCOE SCSI DRIVER
-+M: James Smart <james.smart@broadcom.com>
-+M: Dick Kennedy <dick.kennedy@broadcom.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.broadcom.com
-+F: drivers/scsi/lpfc/
-+
-+EMULEX/BROADCOM EFCT FC/FCOE SCSI TARGET DRIVER
-+M: James Smart <james.smart@broadcom.com>
-+M: Ram Vegesna <ram.vegesna@broadcom.com>
-+L: linux-scsi@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+W: http://www.broadcom.com
-+F: drivers/scsi/elx/
-+
-+ENE CB710 FLASH CARD READER DRIVER
-+M: Michał Mirosław <mirq-linux@rere.qmqm.pl>
-+S: Maintained
-+F: drivers/misc/cb710/
-+F: drivers/mmc/host/cb710-mmc.*
-+F: include/linux/cb710.h
-+
-+ENE KB2426 (ENE0100/ENE020XX) INFRARED RECEIVER
-+M: Maxim Levitsky <maximlevitsky@gmail.com>
-+S: Maintained
-+F: drivers/media/rc/ene_ir.*
-+
-+EPAPR HYPERVISOR BYTE CHANNEL DEVICE DRIVER
-+M: Laurentiu Tudor <laurentiu.tudor@nxp.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/tty/ehv_bytechan.c
-+
-+EPSON S1D13XXX FRAMEBUFFER DRIVER
-+M: Kristoffer Ericson <kristoffer.ericson@gmail.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
-+F: drivers/video/fbdev/s1d13xxxfb.c
-+F: include/video/s1d13xxxfb.h
-+
-+EROFS FILE SYSTEM
-+M: Gao Xiang <xiang@kernel.org>
-+M: Chao Yu <chao@kernel.org>
-+L: linux-erofs@lists.ozlabs.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
-+F: Documentation/filesystems/erofs.rst
-+F: fs/erofs/
-+F: include/trace/events/erofs.h
-+
-+ERRSEQ ERROR TRACKING INFRASTRUCTURE
-+M: Jeff Layton <jlayton@kernel.org>
-+S: Maintained
-+F: include/linux/errseq.h
-+F: lib/errseq.c
-+
-+ET131X NETWORK DRIVER
-+M: Mark Einon <mark.einon@gmail.com>
-+S: Odd Fixes
-+F: drivers/net/ethernet/agere/
-+
-+ETAS ES58X CAN/USB DRIVER
-+M: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: drivers/net/can/usb/etas_es58x/
-+
-+ETHERNET BRIDGE
-+M: Roopa Prabhu <roopa@nvidia.com>
-+M: Nikolay Aleksandrov <nikolay@nvidia.com>
-+L: bridge@lists.linux-foundation.org (moderated for non-subscribers)
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.linuxfoundation.org/en/Net:Bridge
-+F: include/linux/netfilter_bridge/
-+F: net/bridge/
-+
-+ETHERNET PHY LIBRARY
-+M: Andrew Lunn <andrew@lunn.ch>
-+M: Heiner Kallweit <hkallweit1@gmail.com>
-+R: Russell King <linux@armlinux.org.uk>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-net-phydev
-+F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
-+F: Documentation/devicetree/bindings/net/mdio*
-+F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
-+F: Documentation/networking/phy.rst
-+F: drivers/net/mdio/
-+F: drivers/net/mdio/acpi_mdio.c
-+F: drivers/net/mdio/fwnode_mdio.c
-+F: drivers/net/mdio/of_mdio.c
-+F: drivers/net/pcs/
-+F: drivers/net/phy/
-+F: drivers/of/of_net.c
-+F: include/dt-bindings/net/qca-ar803x.h
-+F: include/linux/*mdio*.h
-+F: include/linux/mdio/*.h
-+F: include/linux/of_net.h
-+F: include/linux/phy.h
-+F: include/linux/phy_fixed.h
-+F: include/linux/platform_data/mdio-bcm-unimac.h
-+F: include/linux/platform_data/mdio-gpio.h
-+F: include/trace/events/mdio.h
-+F: include/uapi/linux/mdio.h
-+F: include/uapi/linux/mii.h
-+
-+EXFAT FILE SYSTEM
-+M: Namjae Jeon <linkinjeon@kernel.org>
-+M: Sungjong Seo <sj1557.seo@samsung.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/exfat/
-+
-+EXT2 FILE SYSTEM
-+M: Jan Kara <jack@suse.com>
-+L: linux-ext4@vger.kernel.org
-+S: Maintained
-+F: Documentation/filesystems/ext2.rst
-+F: fs/ext2/
-+F: include/linux/ext2*
-+
-+EXT4 FILE SYSTEM
-+M: "Theodore Ts'o" <tytso@mit.edu>
-+M: Andreas Dilger <adilger.kernel@dilger.ca>
-+L: linux-ext4@vger.kernel.org
-+S: Maintained
-+W: http://ext4.wiki.kernel.org
-+Q: http://patchwork.ozlabs.org/project/linux-ext4/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git
-+F: Documentation/filesystems/ext4/
-+F: fs/ext4/
-+F: include/trace/events/ext4.h
-+
-+Extended Verification Module (EVM)
-+M: Mimi Zohar <zohar@linux.ibm.com>
-+L: linux-integrity@vger.kernel.org
-+S: Supported
-+F: security/integrity/evm/
-+
-+EXTENSIBLE FIRMWARE INTERFACE (EFI)
-+M: Ard Biesheuvel <ardb@kernel.org>
-+L: linux-efi@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
-+F: Documentation/admin-guide/efi-stub.rst
-+F: arch/*/include/asm/efi.h
-+F: arch/*/kernel/efi.c
-+F: arch/arm/boot/compressed/efi-header.S
-+F: arch/arm64/kernel/efi-entry.S
-+F: arch/x86/platform/efi/
-+F: drivers/firmware/efi/
-+F: include/linux/efi*.h
-+
-+EXTERNAL CONNECTOR SUBSYSTEM (EXTCON)
-+M: MyungJoo Ham <myungjoo.ham@samsung.com>
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git
-+F: Documentation/devicetree/bindings/extcon/
-+F: Documentation/firmware-guide/acpi/extcon-intel-int3496.rst
-+F: drivers/extcon/
-+F: include/linux/extcon.h
-+F: include/linux/extcon/
-+
-+EXTRA BOOT CONFIG
-+M: Masami Hiramatsu <mhiramat@kernel.org>
-+S: Maintained
-+F: Documentation/admin-guide/bootconfig.rst
-+F: fs/proc/bootconfig.c
-+F: include/linux/bootconfig.h
-+F: lib/bootconfig.c
-+F: tools/bootconfig/*
-+F: tools/bootconfig/scripts/*
-+
-+EXYNOS DP DRIVER
-+M: Jingoo Han <jingoohan1@gmail.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: drivers/gpu/drm/exynos/exynos_dp*
-+
-+EXYNOS SYSMMU (IOMMU) driver
-+M: Marek Szyprowski <m.szyprowski@samsung.com>
-+L: iommu@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/iommu/exynos-iommu.c
-+
-+F2FS FILE SYSTEM
-+M: Jaegeuk Kim <jaegeuk@kernel.org>
-+M: Chao Yu <chao@kernel.org>
-+L: linux-f2fs-devel@lists.sourceforge.net
-+S: Maintained
-+W: https://f2fs.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
-+F: Documentation/ABI/testing/sysfs-fs-f2fs
-+F: Documentation/filesystems/f2fs.rst
-+F: fs/f2fs/
-+F: include/linux/f2fs_fs.h
-+F: include/trace/events/f2fs.h
-+F: include/uapi/linux/f2fs.h
-+
-+F71805F HARDWARE MONITORING DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/f71805f.rst
-+F: drivers/hwmon/f71805f.c
-+
-+FADDR2LINE
-+M: Josh Poimboeuf <jpoimboe@redhat.com>
-+S: Maintained
-+F: scripts/faddr2line
-+
-+FAILOVER MODULE
-+M: Sridhar Samudrala <sridhar.samudrala@intel.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/failover.rst
-+F: include/net/failover.h
-+F: net/core/failover.c
-+
-+FANOTIFY
-+M: Jan Kara <jack@suse.cz>
-+R: Amir Goldstein <amir73il@gmail.com>
-+R: Matthew Bobrowski <repnop@google.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/notify/fanotify/
-+F: include/linux/fanotify.h
-+F: include/uapi/linux/fanotify.h
-+
-+FARSYNC SYNCHRONOUS DRIVER
-+M: Kevin Curtis <kevin.curtis@farsite.co.uk>
-+S: Supported
-+W: http://www.farsite.co.uk/
-+F: drivers/net/wan/farsync.*
-+
-+FAULT INJECTION SUPPORT
-+M: Akinobu Mita <akinobu.mita@gmail.com>
-+S: Supported
-+F: Documentation/fault-injection/
-+F: lib/fault-inject.c
-+
-+FBTFT Framebuffer drivers
-+L: dri-devel@lists.freedesktop.org
-+L: linux-fbdev@vger.kernel.org
-+S: Orphan
-+F: drivers/staging/fbtft/
-+
-+FC0011 TUNER DRIVER
-+M: Michael Buesch <m@bues.ch>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/tuners/fc0011.c
-+F: drivers/media/tuners/fc0011.h
-+
-+FC2580 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/fc2580*
-+
-+FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
-+M: Hannes Reinecke <hare@suse.de>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: www.Open-FCoE.org
-+F: drivers/scsi/fcoe/
-+F: drivers/scsi/libfc/
-+F: include/scsi/fc/
-+F: include/scsi/libfc.h
-+F: include/scsi/libfcoe.h
-+F: include/uapi/scsi/fc/
-+
-+FILE LOCKING (flock() and fcntl()/lockf())
-+M: Jeff Layton <jlayton@kernel.org>
-+M: "J. Bruce Fields" <bfields@fieldses.org>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/fcntl.c
-+F: fs/locks.c
-+F: include/linux/fcntl.h
-+F: include/uapi/linux/fcntl.h
-+
-+FILESYSTEM DIRECT ACCESS (DAX)
-+M: Dan Williams <dan.j.williams@intel.com>
-+R: Matthew Wilcox <willy@infradead.org>
-+R: Jan Kara <jack@suse.cz>
-+L: linux-fsdevel@vger.kernel.org
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+F: fs/dax.c
-+F: include/linux/dax.h
-+F: include/trace/events/fs_dax.h
-+
-+FILESYSTEMS (VFS and infrastructure)
-+M: Alexander Viro <viro@zeniv.linux.org.uk>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/*
-+F: include/linux/fs.h
-+F: include/linux/fs_types.h
-+F: include/uapi/linux/fs.h
-+F: include/uapi/linux/openat2.h
-+X: fs/io-wq.c
-+X: fs/io-wq.h
-+X: fs/io_uring.c
-+
-+FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-+M: Riku Voipio <riku.voipio@iki.fi>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/f75375s.c
-+F: include/linux/f75375s.h
-+
-+FIREWIRE AUDIO DRIVERS and IEC 61883-1/6 PACKET STREAMING ENGINE
-+M: Clemens Ladisch <clemens@ladisch.de>
-+M: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: include/uapi/sound/firewire.h
-+F: sound/firewire/
-+
-+FIREWIRE MEDIA DRIVERS (firedtv)
-+M: Stefan Richter <stefanr@s5r6.in-berlin.de>
-+L: linux-media@vger.kernel.org
-+L: linux1394-devel@lists.sourceforge.net
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-+F: drivers/media/firewire/
-+
-+FIREWIRE SBP-2 TARGET
-+M: Chris Boot <bootc@bootc.net>
-+L: linux-scsi@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+L: linux1394-devel@lists.sourceforge.net
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core-2.6.git master
-+F: drivers/target/sbp/
-+
-+FIREWIRE SUBSYSTEM
-+M: Stefan Richter <stefanr@s5r6.in-berlin.de>
-+L: linux1394-devel@lists.sourceforge.net
-+S: Maintained
-+W: http://ieee1394.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git
-+F: drivers/firewire/
-+F: include/linux/firewire.h
-+F: include/uapi/linux/firewire*.h
-+F: tools/firewire/
-+
-+FIRMWARE FRAMEWORK FOR ARMV8-A
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/firmware/arm_ffa/
-+F: include/linux/arm_ffa.h
-+
-+FIRMWARE LOADER (request_firmware)
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/firmware_class/
-+F: drivers/base/firmware_loader/
-+F: include/linux/firmware.h
-+
-+FLASH ADAPTER DRIVER (IBM Flash Adapter 900GB Full Height PCI Flash Card)
-+M: Joshua Morris <josh.h.morris@us.ibm.com>
-+M: Philip Kelleher <pjk1939@linux.ibm.com>
-+S: Maintained
-+F: drivers/block/rsxx/
-+
-+FLEXTIMER FTM-QUADDEC DRIVER
-+M: Patrick Havelange <patrick.havelange@essensium.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt
-+F: drivers/counter/ftm-quaddec.c
-+
-+FLOPPY DRIVER
-+M: Denis Efremov <efremov@linux.com>
-+L: linux-block@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/block/floppy.c
-+
-+FLYSKY FSIA6B RC RECEIVER
-+M: Markus Koch <markus@notsyncing.net>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/joystick/fsia6b.c
-+
-+FOCUSRITE SCARLETT GEN 2/3 MIXER DRIVER
-+M: Geoffrey D. Bennett <g@b4.vu>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: sound/usb/mixer_scarlett_gen2.c
-+
-+FORCEDETH GIGABIT ETHERNET DRIVER
-+M: Rain River <rain.1986.08.12@gmail.com>
-+M: Zhu Yanjun <zyjzyj2000@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/nvidia/*
-+
-+FPGA DFL DRIVERS
-+M: Wu Hao <hao.wu@intel.com>
-+R: Tom Rix <trix@redhat.com>
-+L: linux-fpga@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-dfl*
-+F: Documentation/fpga/dfl.rst
-+F: drivers/fpga/dfl*
-+F: drivers/uio/uio_dfl.c
-+F: include/linux/dfl.h
-+F: include/uapi/linux/fpga-dfl.h
-+
-+FPGA MANAGER FRAMEWORK
-+M: Moritz Fischer <mdf@kernel.org>
-+M: Wu Hao <hao.wu@intel.com>
-+M: Xu Yilun <yilun.xu@intel.com>
-+R: Tom Rix <trix@redhat.com>
-+L: linux-fpga@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-fpga/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
-+F: Documentation/devicetree/bindings/fpga/
-+F: Documentation/driver-api/fpga/
-+F: Documentation/fpga/
-+F: drivers/fpga/
-+F: include/linux/fpga/
-+
-+FPU EMULATOR
-+M: Bill Metzenthen <billm@melbpc.org.au>
-+S: Maintained
-+W: http://floatingpoint.sourceforge.net/emulator/index.html
-+F: arch/x86/math-emu/
-+
-+FRAMEBUFFER LAYER
-+L: dri-devel@lists.freedesktop.org
-+L: linux-fbdev@vger.kernel.org
-+S: Orphan
-+Q: http://patchwork.kernel.org/project/linux-fbdev/list/
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/fb/
-+F: drivers/video/
-+F: include/linux/fb.h
-+F: include/uapi/linux/fb.h
-+F: include/uapi/video/
-+F: include/video/
-+
-+FREESCALE CAAM (Cryptographic Acceleration and Assurance Module) DRIVER
-+M: Horia Geantă <horia.geanta@nxp.com>
-+M: Pankaj Gupta <pankaj.gupta@nxp.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/crypto/fsl-sec4.txt
-+F: drivers/crypto/caam/
-+
-+FREESCALE COLDFIRE M5441X MMC DRIVER
-+M: Angelo Dureghello <angelo.dureghello@timesys.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci-esdhc-mcf.c
-+F: include/linux/platform_data/mmc-esdhc-mcf.h
-+
-+FREESCALE DIU FRAMEBUFFER DRIVER
-+M: Timur Tabi <timur@kernel.org>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/fsl-diu-fb.*
-+
-+FREESCALE DMA DRIVER
-+M: Li Yang <leoyang.li@nxp.com>
-+M: Zhang Wei <zw@zh-kernel.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/dma/fsldma.*
-+
-+FREESCALE DSPI DRIVER
-+M: Vladimir Oltean <olteanv@gmail.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
-+F: drivers/spi/spi-fsl-dspi.c
-+F: include/linux/spi/spi-fsl-dspi.h
-+
-+FREESCALE ENETC ETHERNET DRIVERS
-+M: Claudiu Manoil <claudiu.manoil@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/freescale/enetc/
-+
-+FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
-+M: Claudiu Manoil <claudiu.manoil@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
-+F: drivers/net/ethernet/freescale/gianfar*
-+
-+FREESCALE GPMI NAND DRIVER
-+M: Han Xu <han.xu@nxp.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: drivers/mtd/nand/raw/gpmi-nand/*
-+
-+FREESCALE I2C CPM DRIVER
-+M: Jochen Friedrich <jochen@scram.de>
-+L: linuxppc-dev@lists.ozlabs.org
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-cpm.c
-+
-+FREESCALE IMX / MXC FEC DRIVER
-+M: Joakim Zhang <qiangqing.zhang@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/fsl,fec.yaml
-+F: drivers/net/ethernet/freescale/fec.h
-+F: drivers/net/ethernet/freescale/fec_main.c
-+F: drivers/net/ethernet/freescale/fec_ptp.c
-+
-+FREESCALE IMX / MXC FRAMEBUFFER DRIVER
-+M: Sascha Hauer <s.hauer@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+L: linux-fbdev@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/video/fbdev/imxfb.c
-+F: include/linux/platform_data/video-imxfb.h
-+
-+FREESCALE IMX DDR PMU DRIVER
-+M: Frank Li <Frank.li@nxp.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/admin-guide/perf/imx-ddr.rst
-+F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
-+F: drivers/perf/fsl_imx8_ddr_perf.c
-+
-+FREESCALE IMX I2C DRIVER
-+M: Oleksij Rempel <o.rempel@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-imx.yaml
-+F: drivers/i2c/busses/i2c-imx.c
-+
-+FREESCALE IMX LPI2C DRIVER
-+M: Dong Aisheng <aisheng.dong@nxp.com>
-+L: linux-i2c@vger.kernel.org
-+L: linux-imx@nxp.com
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
-+F: drivers/i2c/busses/i2c-imx-lpi2c.c
-+
-+FREESCALE MPC I2C DRIVER
-+M: Chris Packham <chris.packham@alliedtelesis.co.nz>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-mpc.yaml
-+F: drivers/i2c/busses/i2c-mpc.c
-+
-+FREESCALE QORIQ DPAA ETHERNET DRIVER
-+M: Madalin Bucur <madalin.bucur@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/freescale/dpaa
-+
-+FREESCALE QORIQ DPAA FMAN DRIVER
-+M: Madalin Bucur <madalin.bucur@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/fsl-fman.txt
-+F: drivers/net/ethernet/freescale/fman
-+
-+FREESCALE QORIQ PTP CLOCK DRIVER
-+M: Yangbo Lu <yangbo.lu@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
-+F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
-+F: drivers/net/ethernet/freescale/dpaa2/dprtc*
-+F: drivers/net/ethernet/freescale/enetc/enetc_ptp.c
-+F: drivers/ptp/ptp_qoriq.c
-+F: drivers/ptp/ptp_qoriq_debugfs.c
-+F: include/linux/fsl/ptp_qoriq.h
-+
-+FREESCALE QUAD SPI DRIVER
-+M: Han Xu <han.xu@nxp.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml
-+F: drivers/spi/spi-fsl-qspi.c
-+
-+FREESCALE QUICC ENGINE LIBRARY
-+M: Qiang Zhao <qiang.zhao@nxp.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/soc/fsl/qe/
-+F: include/soc/fsl/*qe*.h
-+F: include/soc/fsl/*ucc*.h
-+
-+FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
-+M: Li Yang <leoyang.li@nxp.com>
-+L: netdev@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/net/ethernet/freescale/ucc_geth*
-+
-+FREESCALE QUICC ENGINE UCC HDLC DRIVER
-+M: Zhao Qiang <qiang.zhao@nxp.com>
-+L: netdev@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/net/wan/fsl_ucc_hdlc*
-+
-+FREESCALE QUICC ENGINE UCC UART DRIVER
-+M: Timur Tabi <timur@kernel.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/tty/serial/ucc_uart.c
-+
-+FREESCALE SOC DRIVERS
-+M: Li Yang <leoyang.li@nxp.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
-+F: Documentation/devicetree/bindings/soc/fsl/
-+F: drivers/soc/fsl/
-+F: include/linux/fsl/
-+
-+FREESCALE SOC FS_ENET DRIVER
-+M: Pantelis Antoniou <pantelis.antoniou@gmail.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/freescale/fs_enet/
-+F: include/linux/fs_enet_pd.h
-+
-+FREESCALE SOC SOUND DRIVERS
-+M: Nicolin Chen <nicoleotsuka@gmail.com>
-+M: Xiubo Li <Xiubo.Lee@gmail.com>
-+R: Fabio Estevam <festevam@gmail.com>
-+R: Shengjiu Wang <shengjiu.wang@gmail.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: sound/soc/fsl/fsl*
-+F: sound/soc/fsl/imx*
-+F: sound/soc/fsl/mpc8610_hpcd.c
-+
-+FREESCALE USB PERIPHERAL DRIVERS
-+M: Li Yang <leoyang.li@nxp.com>
-+L: linux-usb@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/usb/gadget/udc/fsl*
-+
-+FREESCALE USB PHY DRIVER
-+M: Ran Wang <ran.wang_1@nxp.com>
-+L: linux-usb@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/usb/phy/phy-fsl-usb*
-+
-+FREEVXFS FILESYSTEM
-+M: Christoph Hellwig <hch@infradead.org>
-+S: Maintained
-+W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
-+F: fs/freevxfs/
-+
-+FREEZER
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Pavel Machek <pavel@ucw.cz>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+F: Documentation/power/freezing-of-tasks.rst
-+F: include/linux/freezer.h
-+F: kernel/freezer.c
-+
-+FRONTSWAP API
-+M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: include/linux/frontswap.h
-+F: mm/frontswap.c
-+
-+FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
-+M: David Howells <dhowells@redhat.com>
-+L: linux-cachefs@redhat.com (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/filesystems/caching/
-+F: fs/fscache/
-+F: include/linux/fscache*.h
-+
-+FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
-+M: Theodore Y. Ts'o <tytso@mit.edu>
-+M: Jaegeuk Kim <jaegeuk@kernel.org>
-+M: Eric Biggers <ebiggers@kernel.org>
-+L: linux-fscrypt@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-fscrypt/list/
-+T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git
-+F: Documentation/filesystems/fscrypt.rst
-+F: fs/crypto/
-+F: include/linux/fscrypt*.h
-+F: include/uapi/linux/fscrypt.h
-+
-+FSI SUBSYSTEM
-+M: Jeremy Kerr <jk@ozlabs.org>
-+M: Joel Stanley <joel@jms.id.au>
-+R: Alistar Popple <alistair@popple.id.au>
-+R: Eddie James <eajames@linux.ibm.com>
-+L: linux-fsi@lists.ozlabs.org
-+S: Supported
-+Q: http://patchwork.ozlabs.org/project/linux-fsi/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi.git
-+F: drivers/fsi/
-+F: include/linux/fsi*.h
-+F: include/trace/events/fsi*.h
-+
-+FSI-ATTACHED I2C DRIVER
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-i2c@vger.kernel.org
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-fsi.txt
-+F: drivers/i2c/busses/i2c-fsi.c
-+
-+FSI-ATTACHED SPI DRIVER
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
-+F: drivers/spi/spi-fsi.c
-+
-+FSNOTIFY: FILESYSTEM NOTIFICATION INFRASTRUCTURE
-+M: Jan Kara <jack@suse.cz>
-+R: Amir Goldstein <amir73il@gmail.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git fsnotify
-+F: fs/notify/
-+F: include/linux/fsnotify*.h
-+
-+FSVERITY: READ-ONLY FILE-BASED AUTHENTICITY PROTECTION
-+M: Eric Biggers <ebiggers@kernel.org>
-+M: Theodore Y. Ts'o <tytso@mit.edu>
-+L: linux-fscrypt@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-fscrypt/list/
-+T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git fsverity
-+F: Documentation/filesystems/fsverity.rst
-+F: fs/verity/
-+F: include/linux/fsverity.h
-+F: include/uapi/linux/fsverity.h
-+
-+FT260 FTDI USB-HID TO I2C BRIDGE DRIVER
-+M: Michael Zaidman <michael.zaidman@gmail.com>
-+L: linux-i2c@vger.kernel.org
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-ft260.c
-+
-+FUJITSU LAPTOP EXTRAS
-+M: Jonathan Woithe <jwoithe@just42.net>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/fujitsu-laptop.c
-+
-+FUJITSU M-5MO LS CAMERA ISP DRIVER
-+M: Kyungmin Park <kyungmin.park@samsung.com>
-+M: Heungjun Kim <riverful.kim@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/m5mols/
-+F: include/media/i2c/m5mols.h
-+
-+FUJITSU TABLET EXTRAS
-+M: Robert Gerlach <khnz@gmx.de>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/fujitsu-tablet.c
-+
-+FUSE: FILESYSTEM IN USERSPACE
-+M: Miklos Szeredi <miklos@szeredi.hu>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+W: https://github.com/libfuse/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git
-+F: Documentation/filesystems/fuse.rst
-+F: fs/fuse/
-+F: include/uapi/linux/fuse.h
-+
-+FUTEX SUBSYSTEM
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Ingo Molnar <mingo@redhat.com>
-+R: Peter Zijlstra <peterz@infradead.org>
-+R: Darren Hart <dvhart@infradead.org>
-+R: Davidlohr Bueso <dave@stgolabs.net>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
-+F: Documentation/locking/*futex*
-+F: include/asm-generic/futex.h
-+F: include/linux/futex.h
-+F: include/uapi/linux/futex.h
-+F: kernel/futex.c
-+F: tools/perf/bench/futex*
-+F: tools/testing/selftests/futex/
-+
-+GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER
-+M: Tim Harvey <tharvey@gateworks.com>
-+M: Robert Jones <rjones@gateworks.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
-+F: drivers/mfd/gateworks-gsc.c
-+F: include/linux/mfd/gsc.h
-+F: Documentation/hwmon/gsc-hwmon.rst
-+F: drivers/hwmon/gsc-hwmon.c
-+F: include/linux/platform_data/gsc_hwmon.h
-+
-+GCC PLUGINS
-+M: Kees Cook <keescook@chromium.org>
-+L: linux-hardening@vger.kernel.org
-+S: Maintained
-+F: Documentation/kbuild/gcc-plugins.rst
-+F: scripts/Makefile.gcc-plugins
-+F: scripts/gcc-plugins/
-+
-+GCOV BASED KERNEL PROFILING
-+M: Peter Oberparleiter <oberpar@linux.ibm.com>
-+S: Maintained
-+F: Documentation/dev-tools/gcov.rst
-+F: kernel/gcov/
-+
-+GDB KERNEL DEBUGGING HELPER SCRIPTS
-+M: Jan Kiszka <jan.kiszka@siemens.com>
-+M: Kieran Bingham <kbingham@kernel.org>
-+S: Supported
-+F: scripts/gdb/
-+
-+GEMINI CRYPTO DRIVER
-+M: Corentin Labbe <clabbe@baylibre.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/gemini/
-+
-+GEMTEK FM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-gemtek*
-+
-+GENERIC ARCHITECTURE TOPOLOGY
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/base/arch_topology.c
-+F: include/linux/arch_topology.h
-+
-+GENERIC ENTRY CODE
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Andy Lutomirski <luto@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/entry
-+F: include/linux/entry-common.h
-+F: include/linux/entry-kvm.h
-+F: kernel/entry/
-+
-+GENERIC GPIO I2C DRIVER
-+M: Wolfram Sang <wsa+renesas@sang-engineering.com>
-+S: Supported
-+F: drivers/i2c/busses/i2c-gpio.c
-+F: include/linux/platform_data/i2c-gpio.h
-+
-+GENERIC GPIO I2C MULTIPLEXER DRIVER
-+M: Peter Korsgaard <peter.korsgaard@barco.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+F: Documentation/i2c/muxes/i2c-mux-gpio.rst
-+F: drivers/i2c/muxes/i2c-mux-gpio.c
-+F: include/linux/platform_data/i2c-mux-gpio.h
-+
-+GENERIC HDLC (WAN) DRIVERS
-+M: Krzysztof Halasa <khc@pm.waw.pl>
-+S: Maintained
-+W: http://www.kernel.org/pub/linux/utils/net/hdlc/
-+F: drivers/net/wan/c101.c
-+F: drivers/net/wan/hd6457*
-+F: drivers/net/wan/hdlc*
-+F: drivers/net/wan/n2.c
-+F: drivers/net/wan/pc300too.c
-+F: drivers/net/wan/pci200syn.c
-+F: drivers/net/wan/wanxl*
-+
-+GENERIC INCLUDE/ASM HEADER FILES
-+M: Arnd Bergmann <arnd@arndb.de>
-+L: linux-arch@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
-+F: include/asm-generic/
-+F: include/uapi/asm-generic/
-+
-+GENERIC PHY FRAMEWORK
-+M: Kishon Vijay Abraham I <kishon@ti.com>
-+M: Vinod Koul <vkoul@kernel.org>
-+L: linux-phy@lists.infradead.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-phy/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
-+F: Documentation/devicetree/bindings/phy/
-+F: drivers/phy/
-+F: include/linux/phy/
-+
-+GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER
-+M: Wolfram Sang <wsa+renesas@sang-engineering.com>
-+S: Supported
-+F: drivers/i2c/muxes/i2c-demux-pinctrl.c
-+
-+GENERIC PM DOMAINS
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Kevin Hilman <khilman@kernel.org>
-+M: Ulf Hansson <ulf.hansson@linaro.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/power/power?domain*
-+F: drivers/base/power/domain*.c
-+F: include/linux/pm_domain.h
-+
-+GENERIC RESISTIVE TOUCHSCREEN ADC DRIVER
-+M: Eugen Hristev <eugen.hristev@microchip.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/resistive-adc-touch.c
-+
-+GENERIC STRING LIBRARY
-+R: Andy Shevchenko <andy@kernel.org>
-+S: Maintained
-+F: lib/string.c
-+F: lib/string_helpers.c
-+F: lib/test_string.c
-+F: lib/test-string_helpers.c
-+
-+GENERIC UIO DRIVER FOR PCI DEVICES
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+L: kvm@vger.kernel.org
-+S: Supported
-+F: drivers/uio/uio_pci_generic.c
-+
-+GENERIC VDSO LIBRARY
-+M: Andy Lutomirski <luto@kernel.org>
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Vincenzo Frascino <vincenzo.frascino@arm.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/vdso
-+F: include/asm-generic/vdso/vsyscall.h
-+F: include/vdso/
-+F: kernel/time/vsyscall.c
-+F: lib/vdso/
-+
-+GENWQE (IBM Generic Workqueue Card)
-+M: Frank Haverkamp <haver@linux.ibm.com>
-+S: Supported
-+F: drivers/misc/genwqe/
-+
-+GET_MAINTAINER SCRIPT
-+M: Joe Perches <joe@perches.com>
-+S: Maintained
-+F: scripts/get_maintainer.pl
-+
-+GFS2 FILE SYSTEM
-+M: Bob Peterson <rpeterso@redhat.com>
-+M: Andreas Gruenbacher <agruenba@redhat.com>
-+L: cluster-devel@redhat.com
-+S: Supported
-+B: https://bugzilla.kernel.org/enter_bug.cgi?product=File%20System&component=gfs2
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
-+F: Documentation/filesystems/gfs2*
-+F: fs/gfs2/
-+F: include/uapi/linux/gfs2_ondisk.h
-+
-+GIGABYTE WMI DRIVER
-+M: Thomas Weißschuh <thomas@weissschuh.net>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/gigabyte-wmi.c
-+
-+GNSS SUBSYSTEM
-+M: Johan Hovold <johan@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss.git
-+F: Documentation/ABI/testing/sysfs-class-gnss
-+F: Documentation/devicetree/bindings/gnss/
-+F: drivers/gnss/
-+F: include/linux/gnss.h
-+
-+GO7007 MPEG CODEC
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/usb/go7007/
-+
-+GOODIX TOUCHSCREEN
-+M: Bastien Nocera <hadess@hadess.net>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/goodix.c
-+
-+GOOGLE ETHERNET DRIVERS
-+M: Jeroen de Borst <jeroendb@google.com>
-+R: Catherine Sullivan <csully@google.com>
-+R: David Awogbemila <awogbemila@google.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/ethernet/google/gve.rst
-+F: drivers/net/ethernet/google
-+
-+GPD POCKET FAN DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/gpd-pocket-fan.c
-+
-+GPIO ACPI SUPPORT
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+L: linux-gpio@vger.kernel.org
-+L: linux-acpi@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
-+F: Documentation/firmware-guide/acpi/gpio-properties.rst
-+F: drivers/gpio/gpiolib-acpi.c
-+F: drivers/gpio/gpiolib-acpi.h
-+
-+GPIO AGGREGATOR
-+M: Geert Uytterhoeven <geert+renesas@glider.be>
-+L: linux-gpio@vger.kernel.org
-+S: Supported
-+F: Documentation/admin-guide/gpio/gpio-aggregator.rst
-+F: drivers/gpio/gpio-aggregator.c
-+
-+GPIO IR Transmitter
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/gpio-ir-tx.c
-+
-+GPIO MOCKUP DRIVER
-+M: Bamvor Jian Zhang <bamv2005@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-mockup.c
-+F: tools/testing/selftests/gpio/
-+
-+GPIO REGMAP
-+R: Michael Walle <michael@walle.cc>
-+S: Maintained
-+F: drivers/gpio/gpio-regmap.c
-+F: include/linux/gpio/regmap.h
-+
-+GPIO SUBSYSTEM
-+M: Linus Walleij <linus.walleij@linaro.org>
-+M: Bartosz Golaszewski <brgl@bgdev.pl>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
-+F: Documentation/ABI/obsolete/sysfs-gpio
-+F: Documentation/ABI/testing/gpio-cdev
-+F: Documentation/admin-guide/gpio/
-+F: Documentation/devicetree/bindings/gpio/
-+F: Documentation/driver-api/gpio/
-+F: drivers/gpio/
-+F: include/asm-generic/gpio.h
-+F: include/linux/gpio.h
-+F: include/linux/gpio/
-+F: include/linux/of_gpio.h
-+F: include/uapi/linux/gpio.h
-+F: tools/gpio/
-+
-+GRE DEMULTIPLEXER DRIVER
-+M: Dmitry Kozlov <xeb@mail.ru>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/net/gre.h
-+F: net/ipv4/gre_demux.c
-+F: net/ipv4/gre_offload.c
-+
-+GRETH 10/100/1G Ethernet MAC device driver
-+M: Andreas Larsson <andreas@gaisler.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/aeroflex/
-+
-+GREYBUS AUDIO PROTOCOLS DRIVERS
-+M: Vaibhav Agarwal <vaibhav.sr@gmail.com>
-+M: Mark Greer <mgreer@animalcreek.com>
-+S: Maintained
-+F: drivers/staging/greybus/audio_apbridgea.c
-+F: drivers/staging/greybus/audio_apbridgea.h
-+F: drivers/staging/greybus/audio_codec.c
-+F: drivers/staging/greybus/audio_codec.h
-+F: drivers/staging/greybus/audio_gb.c
-+F: drivers/staging/greybus/audio_manager.c
-+F: drivers/staging/greybus/audio_manager.h
-+F: drivers/staging/greybus/audio_manager_module.c
-+F: drivers/staging/greybus/audio_manager_private.h
-+F: drivers/staging/greybus/audio_manager_sysfs.c
-+F: drivers/staging/greybus/audio_module.c
-+F: drivers/staging/greybus/audio_topology.c
-+
-+GREYBUS FW/HID/SPI PROTOCOLS DRIVERS
-+M: Viresh Kumar <vireshk@kernel.org>
-+S: Maintained
-+F: drivers/staging/greybus/authentication.c
-+F: drivers/staging/greybus/bootrom.c
-+F: drivers/staging/greybus/firmware.h
-+F: drivers/staging/greybus/fw-core.c
-+F: drivers/staging/greybus/fw-download.c
-+F: drivers/staging/greybus/fw-management.c
-+F: drivers/staging/greybus/greybus_authentication.h
-+F: drivers/staging/greybus/greybus_firmware.h
-+F: drivers/staging/greybus/hid.c
-+F: drivers/staging/greybus/i2c.c
-+F: drivers/staging/greybus/spi.c
-+F: drivers/staging/greybus/spilib.c
-+F: drivers/staging/greybus/spilib.h
-+
-+GREYBUS LOOPBACK DRIVER
-+M: Bryan O'Donoghue <pure.logic@nexus-software.ie>
-+S: Maintained
-+F: drivers/staging/greybus/loopback.c
-+
-+GREYBUS PLATFORM DRIVERS
-+M: Vaibhav Hiremath <hvaibhav.linux@gmail.com>
-+S: Maintained
-+F: drivers/staging/greybus/arche-apb-ctrl.c
-+F: drivers/staging/greybus/arche-platform.c
-+F: drivers/staging/greybus/arche_platform.h
-+
-+GREYBUS SDIO/GPIO/SPI PROTOCOLS DRIVERS
-+M: Rui Miguel Silva <rmfrfs@gmail.com>
-+S: Maintained
-+F: drivers/staging/greybus/gpio.c
-+F: drivers/staging/greybus/light.c
-+F: drivers/staging/greybus/power_supply.c
-+F: drivers/staging/greybus/sdio.c
-+F: drivers/staging/greybus/spi.c
-+F: drivers/staging/greybus/spilib.c
-+
-+GREYBUS SUBSYSTEM
-+M: Johan Hovold <johan@kernel.org>
-+M: Alex Elder <elder@kernel.org>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: greybus-dev@lists.linaro.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/greybus/
-+F: drivers/staging/greybus/
-+F: include/linux/greybus.h
-+F: include/linux/greybus/
-+
-+GREYBUS UART PROTOCOLS DRIVERS
-+M: David Lin <dtwlin@gmail.com>
-+S: Maintained
-+F: drivers/staging/greybus/log.c
-+F: drivers/staging/greybus/uart.c
-+
-+GS1662 VIDEO SERIALIZER
-+M: Charles-Antoine Couret <charles-antoine.couret@nexvision.fr>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/spi/gs1662.c
-+
-+GSPCA FINEPIX SUBDRIVER
-+M: Frank Zago <frank@zago.net>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/finepix.c
-+
-+GSPCA GL860 SUBDRIVER
-+M: Olivier Lorin <o.lorin@laposte.net>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/gl860/
-+
-+GSPCA M5602 SUBDRIVER
-+M: Erik Andren <erik.andren@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/m5602/
-+
-+GSPCA PAC207 SONIXB SUBDRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/pac207.c
-+
-+GSPCA SN9C20X SUBDRIVER
-+M: Brian Johnson <brijohn@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/sn9c20x.c
-+
-+GSPCA T613 SUBDRIVER
-+M: Leandro Costantino <lcostantino@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/t613.c
-+
-+GSPCA USB WEBCAM DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/gspca/
-+
-+GTP (GPRS Tunneling Protocol)
-+M: Pablo Neira Ayuso <pablo@netfilter.org>
-+M: Harald Welte <laforge@gnumonks.org>
-+L: osmocom-net-gprs@lists.osmocom.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/gtp.git
-+F: drivers/net/gtp.c
-+
-+GUID PARTITION TABLE (GPT)
-+M: Davidlohr Bueso <dave@stgolabs.net>
-+L: linux-efi@vger.kernel.org
-+S: Maintained
-+F: block/partitions/efi.*
-+
-+H8/300 ARCHITECTURE
-+M: Yoshinori Sato <ysato@users.sourceforge.jp>
-+L: uclinux-h8-devel@lists.sourceforge.jp (moderated for non-subscribers)
-+S: Maintained
-+W: http://uclinux-h8.sourceforge.jp
-+T: git git://git.sourceforge.jp/gitroot/uclinux-h8/linux.git
-+F: arch/h8300/
-+F: drivers/clk/h8300/
-+F: drivers/clocksource/h8300_*.c
-+F: drivers/irqchip/irq-renesas-h8*.c
-+
-+HABANALABS PCI DRIVER
-+M: Oded Gabbay <ogabbay@kernel.org>
-+S: Supported
-+T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux.git
-+F: Documentation/ABI/testing/debugfs-driver-habanalabs
-+F: Documentation/ABI/testing/sysfs-driver-habanalabs
-+F: drivers/misc/habanalabs/
-+F: include/uapi/misc/habanalabs.h
-+
-+HACKRF MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/hackrf/
-+
-+HANTRO VPU CODEC DRIVER
-+M: Ezequiel Garcia <ezequiel@collabora.com>
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml
-+F: Documentation/devicetree/bindings/media/rockchip-vpu.yaml
-+F: drivers/staging/media/hantro/
-+
-+HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
-+M: Frank Seidel <frank@f-seidel.de>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
-+F: drivers/platform/x86/hdaps.c
-+
-+HARDWARE MONITORING
-+M: Jean Delvare <jdelvare@suse.com>
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+W: http://hwmon.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
-+F: Documentation/devicetree/bindings/hwmon/
-+F: Documentation/hwmon/
-+F: drivers/hwmon/
-+F: include/linux/hwmon*.h
-+F: include/trace/events/hwmon*.h
-+K: (devm_)?hwmon_device_(un)?register(|_with_groups|_with_info)
-+
-+HARDWARE RANDOM NUMBER GENERATOR CORE
-+M: Matt Mackall <mpm@selenic.com>
-+M: Herbert Xu <herbert@gondor.apana.org.au>
-+L: linux-crypto@vger.kernel.org
-+S: Odd fixes
-+F: Documentation/admin-guide/hw_random.rst
-+F: Documentation/devicetree/bindings/rng/
-+F: drivers/char/hw_random/
-+F: include/linux/hw_random.h
-+
-+HARDWARE SPINLOCK CORE
-+M: Ohad Ben-Cohen <ohad@wizery.com>
-+M: Bjorn Andersson <bjorn.andersson@linaro.org>
-+R: Baolin Wang <baolin.wang7@gmail.com>
-+L: linux-remoteproc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git hwspinlock-next
-+F: Documentation/devicetree/bindings/hwlock/
-+F: Documentation/locking/hwspinlock.rst
-+F: drivers/hwspinlock/
-+F: include/linux/hwspinlock.h
-+
-+HARDWARE TRACING FACILITIES
-+M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-+S: Maintained
-+F: drivers/hwtracing/
-+
-+HARMONY SOUND DRIVER
-+L: linux-parisc@vger.kernel.org
-+S: Maintained
-+F: sound/parisc/harmony.*
-+
-+HDPVR USB VIDEO ENCODER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/hdpvr/
-+
-+HEWLETT PACKARD ENTERPRISE ILO CHIF DRIVER
-+M: Matt Hsiao <matt.hsiao@hpe.com>
-+S: Supported
-+F: drivers/misc/hpilo.[ch]
-+
-+HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
-+M: Jerry Hoemann <jerry.hoemann@hpe.com>
-+S: Supported
-+F: Documentation/watchdog/hpwdt.rst
-+F: drivers/watchdog/hpwdt.c
-+
-+HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
-+M: Don Brace <don.brace@microchip.com>
-+L: storagedev@microchip.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: Documentation/scsi/hpsa.rst
-+F: drivers/scsi/hpsa*.[ch]
-+F: include/linux/cciss*.h
-+F: include/uapi/linux/cciss*.h
-+
-+HFI1 DRIVER
-+M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
-+M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/hw/hfi1
-+
-+HFS FILESYSTEM
-+L: linux-fsdevel@vger.kernel.org
-+S: Orphan
-+F: Documentation/filesystems/hfs.rst
-+F: fs/hfs/
-+
-+HFSPLUS FILESYSTEM
-+L: linux-fsdevel@vger.kernel.org
-+S: Orphan
-+F: Documentation/filesystems/hfsplus.rst
-+F: fs/hfsplus/
-+
-+HGA FRAMEBUFFER DRIVER
-+M: Ferenc Bakonyi <fero@drama.obuda.kando.hu>
-+L: linux-nvidia@lists.surfsouth.com
-+S: Maintained
-+W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
-+F: drivers/video/fbdev/hgafb.c
-+
-+HIBERNATION (aka Software Suspend, aka swsusp)
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Pavel Machek <pavel@ucw.cz>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+B: https://bugzilla.kernel.org
-+F: arch/*/include/asm/suspend*.h
-+F: arch/x86/power/
-+F: drivers/base/power/
-+F: include/linux/freezer.h
-+F: include/linux/pm.h
-+F: include/linux/suspend.h
-+F: kernel/power/
-+
-+HID CORE LAYER
-+M: Jiri Kosina <jikos@kernel.org>
-+M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
-+F: drivers/hid/
-+F: include/linux/hid*
-+F: include/uapi/linux/hid*
-+
-+HID PLAYSTATION DRIVER
-+M: Roderick Colenbrander <roderick.colenbrander@sony.com>
-+L: linux-input@vger.kernel.org
-+S: Supported
-+F: drivers/hid/hid-playstation.c
-+
-+HID SENSOR HUB DRIVERS
-+M: Jiri Kosina <jikos@kernel.org>
-+M: Jonathan Cameron <jic23@kernel.org>
-+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
-+L: linux-input@vger.kernel.org
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/hid/hid-sensor*
-+F: drivers/hid/hid-sensor-*
-+F: drivers/iio/*/hid-*
-+F: include/linux/hid-sensor-*
-+
-+HIGH-RESOLUTION TIMERS, CLOCKEVENTS
-+M: Thomas Gleixner <tglx@linutronix.de>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
-+F: Documentation/timers/
-+F: include/linux/clockchips.h
-+F: include/linux/hrtimer.h
-+F: kernel/time/clockevents.c
-+F: kernel/time/hrtimer.c
-+F: kernel/time/timer_*.c
-+
-+HIGH-SPEED SCC DRIVER FOR AX.25
-+L: linux-hams@vger.kernel.org
-+S: Orphan
-+F: drivers/net/hamradio/dmascc.c
-+F: drivers/net/hamradio/scc.c
-+
-+HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
-+M: HighPoint Linux Team <linux@highpoint-tech.com>
-+S: Supported
-+W: http://www.highpoint-tech.com
-+F: Documentation/scsi/hptiop.rst
-+F: drivers/scsi/hptiop.c
-+
-+HIPPI
-+M: Jes Sorensen <jes@trained-monkey.org>
-+L: linux-hippi@sunsite.dk
-+S: Maintained
-+F: drivers/net/hippi/
-+F: include/linux/hippidevice.h
-+F: include/uapi/linux/if_hippi.h
-+F: net/802/hippi.c
-+
-+HIRSCHMANN HELLCREEK ETHERNET SWITCH DRIVER
-+M: Kurt Kanzenbach <kurt@linutronix.de>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/hirschmann,hellcreek.yaml
-+F: drivers/net/dsa/hirschmann/*
-+F: include/linux/platform_data/hirschmann-hellcreek.h
-+F: net/dsa/tag_hellcreek.c
-+
-+HISILICON DMA DRIVER
-+M: Zhou Wang <wangzhou1@hisilicon.com>
-+L: dmaengine@vger.kernel.org
-+S: Maintained
-+F: drivers/dma/hisi_dma.c
-+
-+HISILICON GPIO DRIVER
-+M: Luo Jiaxing <luojiaxing@huawei.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-hisi.c
-+
-+HISILICON HIGH PERFORMANCE RSA ENGINE DRIVER (HPRE)
-+M: Zaibo Xu <xuzaibo@huawei.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/debugfs-hisi-hpre
-+F: drivers/crypto/hisilicon/hpre/hpre.h
-+F: drivers/crypto/hisilicon/hpre/hpre_crypto.c
-+F: drivers/crypto/hisilicon/hpre/hpre_main.c
-+
-+HISILICON I2C CONTROLLER DRIVER
-+M: Yicong Yang <yangyicong@hisilicon.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+W: https://www.hisilicon.com
-+F: drivers/i2c/busses/i2c-hisi.c
-+
-+HISILICON LPC BUS DRIVER
-+M: john.garry@huawei.com
-+S: Maintained
-+W: http://www.hisilicon.com
-+F: Documentation/devicetree/bindings/arm/hisilicon/low-pin-count.yaml
-+F: drivers/bus/hisi_lpc.c
-+
-+HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
-+M: Yisen Zhuang <yisen.zhuang@huawei.com>
-+M: Salil Mehta <salil.mehta@huawei.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.hisilicon.com
-+F: drivers/net/ethernet/hisilicon/hns3/
-+
-+HISILICON NETWORK SUBSYSTEM DRIVER
-+M: Yisen Zhuang <yisen.zhuang@huawei.com>
-+M: Salil Mehta <salil.mehta@huawei.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.hisilicon.com
-+F: Documentation/devicetree/bindings/net/hisilicon*.txt
-+F: drivers/net/ethernet/hisilicon/
-+
-+HIKEY960 ONBOARD USB GPIO HUB DRIVER
-+M: John Stultz <john.stultz@linaro.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/misc/hisi_hikey_usb.c
-+F: Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.yaml
-+
-+HISILICON PMU DRIVER
-+M: Shaokun Zhang <zhangshaokun@hisilicon.com>
-+S: Supported
-+W: http://www.hisilicon.com
-+F: Documentation/admin-guide/perf/hisi-pmu.rst
-+F: drivers/perf/hisilicon
-+
-+HISILICON QM AND ZIP Controller DRIVER
-+M: Zhou Wang <wangzhou1@hisilicon.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/debugfs-hisi-zip
-+F: drivers/crypto/hisilicon/qm.c
-+F: drivers/crypto/hisilicon/qm.h
-+F: drivers/crypto/hisilicon/sgl.c
-+F: drivers/crypto/hisilicon/zip/
-+
-+HISILICON ROCE DRIVER
-+M: Wenpeng Liang <liangwenpeng@huawei.com>
-+M: Weihang Li <liweihang@huawei.com>
-+L: linux-rdma@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt
-+F: drivers/infiniband/hw/hns/
-+
-+HISILICON SAS Controller
-+M: John Garry <john.garry@huawei.com>
-+S: Supported
-+W: http://www.hisilicon.com
-+F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
-+F: drivers/scsi/hisi_sas/
-+
-+HISILICON SECURITY ENGINE V2 DRIVER (SEC2)
-+M: Zaibo Xu <xuzaibo@huawei.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/debugfs-hisi-sec
-+F: drivers/crypto/hisilicon/sec2/sec.h
-+F: drivers/crypto/hisilicon/sec2/sec_crypto.c
-+F: drivers/crypto/hisilicon/sec2/sec_crypto.h
-+F: drivers/crypto/hisilicon/sec2/sec_main.c
-+
-+HISILICON SPI Controller DRIVER FOR KUNPENG SOCS
-+M: Jay Fang <f.fangjian@huawei.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+W: http://www.hisilicon.com
-+F: drivers/spi/spi-hisi-kunpeng.c
-+
-+HISILICON SPMI CONTROLLER DRIVER FOR HIKEY 970
-+M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
-+F: drivers/spmi/hisi-spmi-controller.c
-+
-+HISILICON SPMI PMIC DRIVER FOR HIKEY 6421v600
-+M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
-+F: drivers/mfd/hi6421-spmi-pmic.c
-+
-+HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
-+M: Zaibo Xu <xuzaibo@huawei.com>
-+S: Maintained
-+F: drivers/crypto/hisilicon/trng/trng.c
-+
-+HISILICON V3XX SPI NOR FLASH Controller Driver
-+M: John Garry <john.garry@huawei.com>
-+S: Maintained
-+W: http://www.hisilicon.com
-+F: drivers/spi/spi-hisi-sfc-v3xx.c
-+
-+HMM - Heterogeneous Memory Management
-+M: Jérôme Glisse <jglisse@redhat.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: Documentation/vm/hmm.rst
-+F: include/linux/hmm*
-+F: lib/test_hmm*
-+F: mm/hmm*
-+F: tools/testing/selftests/vm/*hmm*
-+
-+HOST AP DRIVER
-+M: Jouni Malinen <j@w1.fi>
-+L: linux-wireless@vger.kernel.org
-+S: Obsolete
-+W: http://w1.fi/hostap-driver.html
-+F: drivers/net/wireless/intersil/hostap/
-+
-+HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
-+L: platform-driver-x86@vger.kernel.org
-+S: Orphan
-+F: drivers/platform/x86/tc1100-wmi.c
-+
-+HPET: High Precision Event Timers driver
-+M: Clemens Ladisch <clemens@ladisch.de>
-+S: Maintained
-+F: Documentation/timers/hpet.rst
-+F: drivers/char/hpet.c
-+F: include/linux/hpet.h
-+F: include/uapi/linux/hpet.h
-+
-+HPET: x86
-+S: Orphan
-+F: arch/x86/include/asm/hpet.h
-+F: arch/x86/kernel/hpet.c
-+
-+HPFS FILESYSTEM
-+M: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
-+S: Maintained
-+W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
-+F: fs/hpfs/
-+
-+HSI SUBSYSTEM
-+M: Sebastian Reichel <sre@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi.git
-+F: Documentation/ABI/testing/sysfs-bus-hsi
-+F: Documentation/driver-api/hsi.rst
-+F: drivers/hsi/
-+F: include/linux/hsi/
-+F: include/uapi/linux/hsi/
-+
-+HSO 3G MODEM DRIVER
-+L: linux-usb@vger.kernel.org
-+S: Orphan
-+F: drivers/net/usb/hso.c
-+
-+HSR NETWORK PROTOCOL
-+L: netdev@vger.kernel.org
-+S: Orphan
-+F: net/hsr/
-+
-+HT16K33 LED CONTROLLER DRIVER
-+M: Robin van der Gracht <robin@protonic.nl>
-+S: Maintained
-+F: Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml
-+F: drivers/auxdisplay/ht16k33.c
-+
-+HTCPEN TOUCHSCREEN DRIVER
-+M: Pau Oliva Fora <pof@eslack.org>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/htcpen.c
-+
-+HTS221 TEMPERATURE-HUMIDITY IIO DRIVER
-+M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+W: http://www.st.com/
-+F: Documentation/devicetree/bindings/iio/humidity/st,hts221.yaml
-+F: drivers/iio/humidity/hts221*
-+
-+HUAWEI ETHERNET DRIVER
-+L: netdev@vger.kernel.org
-+S: Orphan
-+F: Documentation/networking/device_drivers/ethernet/huawei/hinic.rst
-+F: drivers/net/ethernet/huawei/hinic/
-+
-+HUGETLB FILESYSTEM
-+M: Mike Kravetz <mike.kravetz@oracle.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-kernel-mm-hugepages
-+F: Documentation/admin-guide/mm/hugetlbpage.rst
-+F: Documentation/vm/hugetlbfs_reserv.rst
-+F: fs/hugetlbfs/
-+F: include/linux/hugetlb.h
-+F: mm/hugetlb.c
-+
-+HVA ST MEDIA DRIVER
-+M: Jean-Christophe Trotin <jean-christophe.trotin@foss.st.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/platform/sti/hva
-+
-+HWPOISON MEMORY FAILURE HANDLING
-+M: Naoya Horiguchi <naoya.horiguchi@nec.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: mm/hwpoison-inject.c
-+F: mm/memory-failure.c
-+
-+HYCON HY46XX TOUCHSCREEN SUPPORT
-+M: Giulio Benetti <giulio.benetti@benettiengineering.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/input/touchscreen/hycon,hy46xx.yaml
-+F: drivers/input/touchscreen/hycon-hy46xx.c
-+
-+HYGON PROCESSOR SUPPORT
-+M: Pu Wen <puwen@hygon.cn>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: arch/x86/kernel/cpu/hygon.c
-+
-+HYNIX HI556 SENSOR DRIVER
-+M: Shawn Tu <shawnx.tu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/hi556.c
-+
-+Hyper-V/Azure CORE AND DRIVERS
-+M: "K. Y. Srinivasan" <kys@microsoft.com>
-+M: Haiyang Zhang <haiyangz@microsoft.com>
-+M: Stephen Hemminger <sthemmin@microsoft.com>
-+M: Wei Liu <wei.liu@kernel.org>
-+M: Dexuan Cui <decui@microsoft.com>
-+L: linux-hyperv@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
-+F: Documentation/ABI/stable/sysfs-bus-vmbus
-+F: Documentation/ABI/testing/debugfs-hyperv
-+F: Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
-+F: arch/arm64/hyperv
-+F: arch/arm64/include/asm/hyperv-tlfs.h
-+F: arch/arm64/include/asm/mshyperv.h
-+F: arch/x86/hyperv
-+F: arch/x86/include/asm/hyperv-tlfs.h
-+F: arch/x86/include/asm/mshyperv.h
-+F: arch/x86/include/asm/trace/hyperv.h
-+F: arch/x86/kernel/cpu/mshyperv.c
-+F: drivers/clocksource/hyperv_timer.c
-+F: drivers/hid/hid-hyperv.c
-+F: drivers/hv/
-+F: drivers/input/serio/hyperv-keyboard.c
-+F: drivers/iommu/hyperv-iommu.c
-+F: drivers/net/ethernet/microsoft/
-+F: drivers/net/hyperv/
-+F: drivers/pci/controller/pci-hyperv-intf.c
-+F: drivers/pci/controller/pci-hyperv.c
-+F: drivers/scsi/storvsc_drv.c
-+F: drivers/uio/uio_hv_generic.c
-+F: drivers/video/fbdev/hyperv_fb.c
-+F: include/asm-generic/hyperv-tlfs.h
-+F: include/asm-generic/mshyperv.h
-+F: include/clocksource/hyperv_timer.h
-+F: include/linux/hyperv.h
-+F: include/uapi/linux/hyperv.h
-+F: net/vmw_vsock/hyperv_transport.c
-+F: tools/hv/
-+
-+HYPERBUS SUPPORT
-+M: Vignesh Raghavendra <vigneshr@ti.com>
-+L: linux-mtd@lists.infradead.org
-+S: Supported
-+Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
-+C: irc://irc.oftc.net/mtd
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git cfi/next
-+F: Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt
-+F: Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt
-+F: drivers/mtd/hyperbus/
-+F: include/linux/mtd/hyperbus.h
-+
-+HYPERVISOR VIRTUAL CONSOLE DRIVER
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Odd Fixes
-+F: drivers/tty/hvc/
-+
-+I2C ACPI SUPPORT
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+L: linux-i2c@vger.kernel.org
-+L: linux-acpi@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/i2c-core-acpi.c
-+
-+I2C CONTROLLER DRIVER FOR NVIDIA GPU
-+M: Ajay Gupta <ajayg@nvidia.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/i2c/busses/i2c-nvidia-gpu.rst
-+F: drivers/i2c/busses/i2c-nvidia-gpu.c
-+
-+I2C MUXES
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-arb*
-+F: Documentation/devicetree/bindings/i2c/i2c-gate*
-+F: Documentation/devicetree/bindings/i2c/i2c-mux*
-+F: Documentation/i2c/i2c-topology.rst
-+F: Documentation/i2c/muxes/
-+F: drivers/i2c/i2c-mux.c
-+F: drivers/i2c/muxes/
-+F: include/linux/i2c-mux.h
-+
-+I2C MV64XXX MARVELL AND ALLWINNER DRIVER
-+M: Gregory CLEMENT <gregory.clement@bootlin.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
-+F: drivers/i2c/busses/i2c-mv64xxx.c
-+
-+I2C OVER PARALLEL PORT
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/i2c/busses/i2c-parport.rst
-+F: drivers/i2c/busses/i2c-parport.c
-+
-+I2C SUBSYSTEM
-+M: Wolfram Sang <wsa@kernel.org>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+W: https://i2c.wiki.kernel.org/
-+Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
-+F: Documentation/devicetree/bindings/i2c/i2c.txt
-+F: Documentation/i2c/
-+F: drivers/i2c/*
-+F: include/linux/i2c-dev.h
-+F: include/linux/i2c-smbus.h
-+F: include/linux/i2c.h
-+F: include/uapi/linux/i2c-*.h
-+F: include/uapi/linux/i2c.h
-+
-+I2C SUBSYSTEM HOST DRIVERS
-+L: linux-i2c@vger.kernel.org
-+S: Odd Fixes
-+W: https://i2c.wiki.kernel.org/
-+Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
-+F: Documentation/devicetree/bindings/i2c/
-+F: drivers/i2c/algos/
-+F: drivers/i2c/busses/
-+
-+I2C-TAOS-EVM DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/i2c/busses/i2c-taos-evm.rst
-+F: drivers/i2c/busses/i2c-taos-evm.c
-+
-+I2C-TINY-USB DRIVER
-+M: Till Harbaum <till@harbaum.org>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+W: http://www.harbaum.org/till/i2c_tiny_usb
-+F: drivers/i2c/busses/i2c-tiny-usb.c
-+
-+I2C/SMBUS CONTROLLER DRIVERS FOR PC
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/i2c/busses/i2c-ali1535.rst
-+F: Documentation/i2c/busses/i2c-ali1563.rst
-+F: Documentation/i2c/busses/i2c-ali15x3.rst
-+F: Documentation/i2c/busses/i2c-amd756.rst
-+F: Documentation/i2c/busses/i2c-amd8111.rst
-+F: Documentation/i2c/busses/i2c-i801.rst
-+F: Documentation/i2c/busses/i2c-nforce2.rst
-+F: Documentation/i2c/busses/i2c-piix4.rst
-+F: Documentation/i2c/busses/i2c-sis5595.rst
-+F: Documentation/i2c/busses/i2c-sis630.rst
-+F: Documentation/i2c/busses/i2c-sis96x.rst
-+F: Documentation/i2c/busses/i2c-via.rst
-+F: Documentation/i2c/busses/i2c-viapro.rst
-+F: drivers/i2c/busses/i2c-ali1535.c
-+F: drivers/i2c/busses/i2c-ali1563.c
-+F: drivers/i2c/busses/i2c-ali15x3.c
-+F: drivers/i2c/busses/i2c-amd756-s4882.c
-+F: drivers/i2c/busses/i2c-amd756.c
-+F: drivers/i2c/busses/i2c-amd8111.c
-+F: drivers/i2c/busses/i2c-i801.c
-+F: drivers/i2c/busses/i2c-isch.c
-+F: drivers/i2c/busses/i2c-nforce2-s4985.c
-+F: drivers/i2c/busses/i2c-nforce2.c
-+F: drivers/i2c/busses/i2c-piix4.c
-+F: drivers/i2c/busses/i2c-sis5595.c
-+F: drivers/i2c/busses/i2c-sis630.c
-+F: drivers/i2c/busses/i2c-sis96x.c
-+F: drivers/i2c/busses/i2c-via.c
-+F: drivers/i2c/busses/i2c-viapro.c
-+
-+I2C/SMBUS INTEL CHT WHISKEY COVE PMIC DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-cht-wc.c
-+
-+I2C/SMBUS ISMT DRIVER
-+M: Seth Heasley <seth.heasley@intel.com>
-+M: Neil Horman <nhorman@tuxdriver.com>
-+L: linux-i2c@vger.kernel.org
-+F: Documentation/i2c/busses/i2c-ismt.rst
-+F: drivers/i2c/busses/i2c-ismt.c
-+
-+I2C/SMBUS STUB DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/i2c-stub.c
-+
-+I3C DRIVER FOR CADENCE I3C MASTER IP
-+M: Przemysław Gaj <pgaj@cadence.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/i3c/cdns,i3c-master.txt
-+F: drivers/i3c/master/i3c-master-cdns.c
-+
-+I3C DRIVER FOR SYNOPSYS DESIGNWARE
-+M: Vitor Soares <vitor.soares@synopsys.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.txt
-+F: drivers/i3c/master/dw*
-+
-+I3C SUBSYSTEM
-+M: Alexandre Belloni <alexandre.belloni@bootlin.com>
-+L: linux-i3c@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+C: irc://chat.freenode.net/linux-i3c
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux.git
-+F: Documentation/ABI/testing/sysfs-bus-i3c
-+F: Documentation/devicetree/bindings/i3c/
-+F: Documentation/driver-api/i3c
-+F: drivers/i3c/
-+F: include/linux/i3c/
-+
-+IA64 (Itanium) PLATFORM
-+L: linux-ia64@vger.kernel.org
-+S: Orphan
-+F: Documentation/ia64/
-+F: arch/ia64/
-+
-+IBM Power 842 compression accelerator
-+M: Haren Myneni <haren@us.ibm.com>
-+S: Supported
-+F: crypto/842.c
-+F: drivers/crypto/nx/Kconfig
-+F: drivers/crypto/nx/Makefile
-+F: drivers/crypto/nx/nx-842*
-+F: include/linux/sw842.h
-+F: lib/842/
-+
-+IBM Power in-Nest Crypto Acceleration
-+M: Breno Leitão <leitao@debian.org>
-+M: Nayna Jain <nayna@linux.ibm.com>
-+M: Paulo Flabiano Smorigo <pfsmorigo@gmail.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+F: drivers/crypto/nx/Kconfig
-+F: drivers/crypto/nx/Makefile
-+F: drivers/crypto/nx/nx-aes*
-+F: drivers/crypto/nx/nx-sha*
-+F: drivers/crypto/nx/nx.*
-+F: drivers/crypto/nx/nx_csbcpb.h
-+F: drivers/crypto/nx/nx_debugfs.c
-+
-+IBM Power IO DLPAR Driver for RPA-compliant PPC64 platform
-+M: Tyrel Datwyler <tyreld@linux.ibm.com>
-+L: linux-pci@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: drivers/pci/hotplug/rpadlpar*
-+
-+IBM Power Linux RAID adapter
-+M: Brian King <brking@us.ibm.com>
-+S: Supported
-+F: drivers/scsi/ipr.*
-+
-+IBM Power PCI Hotplug Driver for RPA-compliant PPC64 platform
-+M: Tyrel Datwyler <tyreld@linux.ibm.com>
-+L: linux-pci@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: drivers/pci/hotplug/rpaphp*
-+
-+IBM Power SRIOV Virtual NIC Device Driver
-+M: Dany Madden <drt@linux.ibm.com>
-+M: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
-+R: Thomas Falcon <tlfalcon@linux.ibm.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/ibm/ibmvnic.*
-+
-+IBM Power Virtual Accelerator Switchboard
-+M: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: arch/powerpc/include/asm/vas.h
-+F: arch/powerpc/platforms/powernv/copy-paste.h
-+F: arch/powerpc/platforms/powernv/vas*
-+
-+IBM Power Virtual Ethernet Device Driver
-+M: Cristobal Forno <cforno12@linux.ibm.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/ibm/ibmveth.*
-+
-+IBM Power Virtual FC Device Drivers
-+M: Tyrel Datwyler <tyreld@linux.ibm.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/ibmvscsi/ibmvfc*
-+
-+IBM Power Virtual Management Channel Driver
-+M: Brad Warrum <bwarrum@linux.ibm.com>
-+M: Ritu Agarwal <rituagar@linux.ibm.com>
-+S: Supported
-+F: drivers/misc/ibmvmc.*
-+
-+IBM Power Virtual SCSI Device Drivers
-+M: Tyrel Datwyler <tyreld@linux.ibm.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/ibmvscsi/ibmvscsi*
-+F: include/scsi/viosrp.h
-+
-+IBM Power Virtual SCSI Device Target Driver
-+M: Michael Cyr <mikecyr@linux.ibm.com>
-+L: linux-scsi@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/ibmvscsi_tgt/
-+
-+IBM Power VMX Cryptographic instructions
-+M: Breno Leitão <leitao@debian.org>
-+M: Nayna Jain <nayna@linux.ibm.com>
-+M: Paulo Flabiano Smorigo <pfsmorigo@gmail.com>
-+L: linux-crypto@vger.kernel.org
-+S: Supported
-+F: drivers/crypto/vmx/Kconfig
-+F: drivers/crypto/vmx/Makefile
-+F: drivers/crypto/vmx/aes*
-+F: drivers/crypto/vmx/ghash*
-+F: drivers/crypto/vmx/ppc-xlate.pl
-+F: drivers/crypto/vmx/vmx.c
-+
-+IBM ServeRAID RAID DRIVER
-+S: Orphan
-+F: drivers/scsi/ips.*
-+
-+ICH LPC AND GPIO DRIVER
-+M: Peter Tyser <ptyser@xes-inc.com>
-+S: Maintained
-+F: drivers/gpio/gpio-ich.c
-+F: drivers/mfd/lpc_ich.c
-+
-+ICY I2C DRIVER
-+M: Max Staudt <max@enpas.org>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-icy.c
-+
-+IDEAPAD LAPTOP EXTRAS DRIVER
-+M: Ike Panhc <ike.pan@canonical.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://launchpad.net/ideapad-laptop
-+F: drivers/platform/x86/ideapad-laptop.c
-+
-+IDEAPAD LAPTOP SLIDEBAR DRIVER
-+M: Andrey Moiseev <o2g.org.ru@gmail.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+W: https://github.com/o2genum/ideapad-slidebar
-+F: drivers/input/misc/ideapad_slidebar.c
-+
-+IDT VersaClock 5 CLOCK DRIVER
-+M: Luca Ceresoli <luca@lucaceresoli.net>
-+S: Maintained
-+F: Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
-+F: drivers/clk/clk-versaclock5.c
-+
-+IEEE 802.15.4 SUBSYSTEM
-+M: Alexander Aring <alex.aring@gmail.com>
-+M: Stefan Schmidt <stefan@datenfreihafen.org>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+W: https://linux-wpan.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
-+F: Documentation/networking/ieee802154.rst
-+F: drivers/net/ieee802154/
-+F: include/linux/ieee802154.h
-+F: include/linux/nl802154.h
-+F: include/net/af_ieee802154.h
-+F: include/net/cfg802154.h
-+F: include/net/ieee802154_netdev.h
-+F: include/net/mac802154.h
-+F: include/net/nl802154.h
-+F: net/ieee802154/
-+F: net/mac802154/
-+
-+IFE PROTOCOL
-+M: Yotam Gigi <yotam.gi@gmail.com>
-+M: Jamal Hadi Salim <jhs@mojatatu.com>
-+F: include/net/ife.h
-+F: include/uapi/linux/ife.h
-+F: net/ife
-+
-+IGORPLUG-USB IR RECEIVER
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/igorplugusb.c
-+
-+IGUANAWORKS USB IR TRANSCEIVER
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/iguanair.c
-+
-+IIO DIGITAL POTENTIOMETER DAC
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
-+F: Documentation/devicetree/bindings/iio/dac/dpot-dac.yaml
-+F: drivers/iio/dac/dpot-dac.c
-+
-+IIO ENVELOPE DETECTOR
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
-+F: Documentation/devicetree/bindings/iio/adc/envelope-detector.yaml
-+F: drivers/iio/adc/envelope-detector.c
-+
-+IIO MULTIPLEXER
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml
-+F: drivers/iio/multiplexer/iio-mux.c
-+
-+IIO SCMI BASED DRIVER
-+M: Jyoti Bhayana <jbhayana@google.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/iio/common/scmi_sensors/scmi_iio.c
-+
-+IIO SUBSYSTEM AND DRIVERS
-+M: Jonathan Cameron <jic23@kernel.org>
-+R: Lars-Peter Clausen <lars@metafoo.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
-+F: Documentation/ABI/testing/configfs-iio*
-+F: Documentation/ABI/testing/sysfs-bus-iio*
-+F: Documentation/devicetree/bindings/iio/
-+F: drivers/iio/
-+F: drivers/staging/iio/
-+F: include/linux/iio/
-+F: tools/iio/
-+
-+IIO UNIT CONVERTER
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.yaml
-+F: Documentation/devicetree/bindings/iio/afe/current-sense-shunt.yaml
-+F: Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml
-+F: drivers/iio/afe/iio-rescale.c
-+
-+IKANOS/ADI EAGLE ADSL USB DRIVER
-+M: Matthieu Castet <castet.matthieu@free.fr>
-+M: Stanislaw Gruszka <stf_xl@wp.pl>
-+S: Maintained
-+F: drivers/usb/atm/ueagle-atm.c
-+
-+IMGTEC ASCII LCD DRIVER
-+M: Paul Burton <paulburton@kernel.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
-+F: drivers/auxdisplay/img-ascii-lcd.c
-+
-+IMGTEC IR DECODER DRIVER
-+S: Orphan
-+F: drivers/media/rc/img-ir/
-+
-+IMON SOUNDGRAPH USB IR RECEIVER
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/imon.c
-+F: drivers/media/rc/imon_raw.c
-+
-+IMS TWINTURBO FRAMEBUFFER DRIVER
-+L: linux-fbdev@vger.kernel.org
-+S: Orphan
-+F: drivers/video/fbdev/imsttfb.c
-+
-+INA209 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
-+F: Documentation/hwmon/ina209.rst
-+F: drivers/hwmon/ina209.c
-+
-+INA2XX HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/ina2xx.rst
-+F: drivers/hwmon/ina2xx.c
-+F: include/linux/platform_data/ina2xx.h
-+
-+INDUSTRY PACK SUBSYSTEM (IPACK)
-+M: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
-+M: Jens Taprogge <jens.taprogge@taprogge.org>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: industrypack-devel@lists.sourceforge.net
-+S: Maintained
-+W: http://industrypack.sourceforge.net
-+F: drivers/ipack/
-+
-+INFINEON DPS310 Driver
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/iio/pressure/dps310.c
-+
-+INFINIBAND SUBSYSTEM
-+M: Doug Ledford <dledford@redhat.com>
-+M: Jason Gunthorpe <jgg@nvidia.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: https://github.com/linux-rdma/rdma-core
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git
-+F: Documentation/devicetree/bindings/infiniband/
-+F: Documentation/infiniband/
-+F: drivers/infiniband/
-+F: include/rdma/
-+F: include/trace/events/ib_mad.h
-+F: include/trace/events/ib_umad.h
-+F: include/uapi/linux/if_infiniband.h
-+F: include/uapi/rdma/
-+F: samples/bpf/ibumad_kern.c
-+F: samples/bpf/ibumad_user.c
-+
-+INGENIC JZ4780 NAND DRIVER
-+M: Harvey Hunt <harveyhuntnexus@gmail.com>
-+L: linux-mtd@lists.infradead.org
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: drivers/mtd/nand/raw/ingenic/
-+
-+INGENIC JZ47xx SoCs
-+M: Paul Cercueil <paul@crapouillou.net>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/boot/dts/ingenic/
-+F: arch/mips/generic/board-ingenic.c
-+F: arch/mips/include/asm/mach-ingenic/
-+F: arch/mips/ingenic/Kconfig
-+F: drivers/clk/ingenic/
-+F: drivers/dma/dma-jz4780.c
-+F: drivers/gpu/drm/ingenic/
-+F: drivers/i2c/busses/i2c-jz4780.c
-+F: drivers/iio/adc/ingenic-adc.c
-+F: drivers/irqchip/irq-ingenic.c
-+F: drivers/memory/jz4780-nemc.c
-+F: drivers/mmc/host/jz4740_mmc.c
-+F: drivers/mtd/nand/raw/ingenic/
-+F: drivers/pinctrl/pinctrl-ingenic.c
-+F: drivers/power/supply/ingenic-battery.c
-+F: drivers/pwm/pwm-jz4740.c
-+F: drivers/remoteproc/ingenic_rproc.c
-+F: drivers/rtc/rtc-jz4740.c
-+F: drivers/tty/serial/8250/8250_ingenic.c
-+F: drivers/usb/musb/jz4740.c
-+F: drivers/watchdog/jz4740_wdt.c
-+F: include/dt-bindings/iio/adc/ingenic,adc.h
-+F: include/linux/mfd/ingenic-tcu.h
-+F: sound/soc/codecs/jz47*
-+F: sound/soc/jz4740/
-+
-+INOTIFY
-+M: Jan Kara <jack@suse.cz>
-+R: Amir Goldstein <amir73il@gmail.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: Documentation/filesystems/inotify.rst
-+F: fs/notify/inotify/
-+F: include/linux/inotify.h
-+F: include/uapi/linux/inotify.h
-+
-+INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
-+M: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-input/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
-+F: Documentation/devicetree/bindings/input/
-+F: Documentation/devicetree/bindings/serio/
-+F: Documentation/input/
-+F: drivers/input/
-+F: include/linux/input.h
-+F: include/linux/input/
-+F: include/uapi/linux/input-event-codes.h
-+F: include/uapi/linux/input.h
-+
-+INPUT MULTITOUCH (MT) PROTOCOL
-+M: Henrik Rydberg <rydberg@bitmath.org>
-+L: linux-input@vger.kernel.org
-+S: Odd fixes
-+F: Documentation/input/multi-touch-protocol.rst
-+F: drivers/input/input-mt.c
-+K: \b(ABS|SYN)_MT_
-+
-+INSIDE SECURE CRYPTO DRIVER
-+M: Antoine Tenart <atenart@kernel.org>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/inside-secure/
-+
-+INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
-+M: Mimi Zohar <zohar@linux.ibm.com>
-+M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
-+L: linux-integrity@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
-+F: security/integrity/ima/
-+
-+INTEL 810/815 FRAMEBUFFER DRIVER
-+M: Antonino Daplas <adaplas@gmail.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/i810/
-+
-+INTEL ASoC DRIVERS
-+M: Cezary Rojewski <cezary.rojewski@intel.com>
-+M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
-+M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
-+M: Jie Yang <yang.jie@linux.intel.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+F: sound/soc/intel/
-+
-+INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/atomisp2/pm.c
-+
-+INTEL ATOMISP2 LED DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/atomisp2/led.c
-+
-+INTEL BIOS SAR INT1092 DRIVER
-+M: Shravan Sudhakar <s.shravan@intel.com>
-+M: Intel Corporation <linuxwwan@intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/int1092/
-+
-+INTEL BROXTON PMC DRIVER
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+M: Zha Qipeng <qipeng.zha@intel.com>
-+S: Maintained
-+F: drivers/mfd/intel_pmc_bxt.c
-+F: include/linux/mfd/intel_pmc_bxt.h
-+
-+INTEL C600 SERIES SAS CONTROLLER DRIVER
-+M: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+T: git git://git.code.sf.net/p/intel-sas/isci
-+F: drivers/scsi/isci/
-+
-+INTEL CPU family model numbers
-+M: Tony Luck <tony.luck@intel.com>
-+M: x86@kernel.org
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: arch/x86/include/asm/intel-family.h
-+
-+INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
-+M: Jani Nikula <jani.nikula@linux.intel.com>
-+M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
-+M: Rodrigo Vivi <rodrigo.vivi@intel.com>
-+L: intel-gfx@lists.freedesktop.org
-+S: Supported
-+W: https://01.org/linuxgraphics/
-+Q: http://patchwork.freedesktop.org/project/intel-gfx/
-+B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
-+C: irc://irc.oftc.net/intel-gfx
-+T: git git://anongit.freedesktop.org/drm-intel
-+F: Documentation/gpu/i915.rst
-+F: drivers/gpu/drm/i915/
-+F: include/drm/i915*
-+F: include/uapi/drm/i915_drm.h
-+
-+INTEL ETHERNET DRIVERS
-+M: Jesse Brandeburg <jesse.brandeburg@intel.com>
-+M: Tony Nguyen <anthony.l.nguyen@intel.com>
-+L: intel-wired-lan@lists.osuosl.org (moderated for non-subscribers)
-+S: Supported
-+W: http://www.intel.com/support/feedback.htm
-+W: http://e1000.sourceforge.net/
-+Q: http://patchwork.ozlabs.org/project/intel-wired-lan/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git
-+F: Documentation/networking/device_drivers/ethernet/intel/
-+F: drivers/net/ethernet/intel/
-+F: drivers/net/ethernet/intel/*/
-+F: include/linux/avf/virtchnl.h
-+F: include/linux/net/intel/iidc.h
-+
-+INTEL ETHERNET PROTOCOL DRIVER FOR RDMA
-+M: Mustafa Ismail <mustafa.ismail@intel.com>
-+M: Shiraz Saleem <shiraz.saleem@intel.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/hw/irdma/
-+F: include/uapi/rdma/irdma-abi.h
-+
-+INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
-+M: Maik Broemme <mbroemme@libmpq.org>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/fb/intelfb.rst
-+F: drivers/video/fbdev/intelfb/
-+
-+INTEL GPIO DRIVERS
-+M: Andy Shevchenko <andy@kernel.org>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
-+F: drivers/gpio/gpio-ich.c
-+F: drivers/gpio/gpio-merrifield.c
-+F: drivers/gpio/gpio-ml-ioh.c
-+F: drivers/gpio/gpio-pch.c
-+F: drivers/gpio/gpio-sch.c
-+F: drivers/gpio/gpio-sodaville.c
-+
-+INTEL GVT-g DRIVERS (Intel GPU Virtualization)
-+M: Zhenyu Wang <zhenyuw@linux.intel.com>
-+M: Zhi Wang <zhi.a.wang@intel.com>
-+L: intel-gvt-dev@lists.freedesktop.org
-+L: intel-gfx@lists.freedesktop.org
-+S: Supported
-+W: https://01.org/igvt-g
-+T: git https://github.com/intel/gvt-linux.git
-+F: drivers/gpu/drm/i915/gvt/
-+
-+INTEL HID EVENT DRIVER
-+M: Alex Hung <alex.hung@canonical.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/hid.c
-+
-+INTEL I/OAT DMA DRIVER
-+M: Dave Jiang <dave.jiang@intel.com>
-+R: Dan Williams <dan.j.williams@intel.com>
-+L: dmaengine@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
-+F: drivers/dma/ioat*
-+
-+INTEL IADX DRIVER
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: dmaengine@vger.kernel.org
-+S: Supported
-+F: drivers/dma/idxd/*
-+F: include/uapi/linux/idxd.h
-+
-+INTEL IDLE DRIVER
-+M: Jacob Pan <jacob.jun.pan@linux.intel.com>
-+M: Len Brown <lenb@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git
-+F: drivers/idle/intel_idle.c
-+
-+INTEL INTEGRATED SENSOR HUB DRIVER
-+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
-+M: Jiri Kosina <jikos@kernel.org>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/intel-ish-hid/
-+
-+INTEL IOMMU (VT-d)
-+M: David Woodhouse <dwmw2@infradead.org>
-+M: Lu Baolu <baolu.lu@linux.intel.com>
-+L: iommu@lists.linux-foundation.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-+F: drivers/iommu/intel/
-+F: include/linux/intel-iommu.h
-+F: include/linux/intel-svm.h
-+
-+INTEL IOP-ADMA DMA DRIVER
-+R: Dan Williams <dan.j.williams@intel.com>
-+S: Odd fixes
-+F: drivers/dma/iop-adma.c
-+
-+INTEL IPU3 CSI-2 CIO2 DRIVER
-+M: Yong Zhi <yong.zhi@intel.com>
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+M: Bingbu Cao <bingbu.cao@intel.com>
-+M: Dan Scally <djrscally@gmail.com>
-+R: Tianshu Qiu <tian.shu.qiu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
-+F: drivers/media/pci/intel/ipu3/
-+
-+INTEL IPU3 CSI-2 IMGU DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+R: Bingbu Cao <bingbu.cao@intel.com>
-+R: Tianshu Qiu <tian.shu.qiu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/media/ipu3.rst
-+F: Documentation/admin-guide/media/ipu3_rcb.svg
-+F: Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst
-+F: drivers/staging/media/ipu3/
-+
-+INTEL IXP4XX CRYPTO SUPPORT
-+M: Corentin Labbe <clabbe@baylibre.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/ixp4xx_crypto.c
-+
-+INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
-+M: Krzysztof Halasa <khalasa@piap.pl>
-+S: Maintained
-+F: drivers/net/ethernet/xscale/ixp4xx_eth.c
-+F: drivers/net/wan/ixp4xx_hss.c
-+F: drivers/soc/ixp4xx/ixp4xx-npe.c
-+F: drivers/soc/ixp4xx/ixp4xx-qmgr.c
-+F: include/linux/soc/ixp4xx/npe.h
-+F: include/linux/soc/ixp4xx/qmgr.h
-+
-+INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
-+M: Deepak Saxena <dsaxena@plexity.net>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/intel,ixp46x-rng.yaml
-+F: drivers/char/hw_random/ixp4xx-rng.c
-+
-+INTEL KEEM BAY DRM DRIVER
-+M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
-+M: Edmund Dea <edmund.j.dea@intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/intel,kmb_display.yaml
-+F: drivers/gpu/drm/kmb/
-+
-+INTEL KEEM BAY OCS AES/SM4 CRYPTO DRIVER
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/crypto/intel,keembay-ocs-aes.yaml
-+F: drivers/crypto/keembay/Kconfig
-+F: drivers/crypto/keembay/Makefile
-+F: drivers/crypto/keembay/keembay-ocs-aes-core.c
-+F: drivers/crypto/keembay/ocs-aes.c
-+F: drivers/crypto/keembay/ocs-aes.h
-+
-+INTEL KEEM BAY OCS HCU CRYPTO DRIVER
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+M: Declan Murphy <declan.murphy@intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/crypto/intel,keembay-ocs-hcu.yaml
-+F: drivers/crypto/keembay/Kconfig
-+F: drivers/crypto/keembay/Makefile
-+F: drivers/crypto/keembay/keembay-ocs-hcu-core.c
-+F: drivers/crypto/keembay/ocs-hcu.c
-+F: drivers/crypto/keembay/ocs-hcu.h
-+
-+INTEL MANAGEMENT ENGINE (mei)
-+M: Tomas Winkler <tomas.winkler@intel.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/driver-api/mei/*
-+F: drivers/misc/mei/
-+F: drivers/watchdog/mei_wdt.c
-+F: include/linux/mei_cl_bus.h
-+F: include/uapi/linux/mei.h
-+F: samples/mei/*
-+
-+INTEL MAX 10 BMC MFD DRIVER
-+M: Xu Yilun <yilun.xu@intel.com>
-+R: Tom Rix <trix@redhat.com>
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
-+F: Documentation/hwmon/intel-m10-bmc-hwmon.rst
-+F: drivers/hwmon/intel-m10-bmc-hwmon.c
-+F: drivers/mfd/intel-m10-bmc.c
-+F: include/linux/mfd/intel-m10-bmc.h
-+
-+INTEL MENLOW THERMAL DRIVER
-+M: Sujith Thomas <sujith.thomas@intel.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+W: https://01.org/linux-acpi
-+F: drivers/thermal/intel/intel_menlow.c
-+
-+INTEL P-Unit IPC DRIVER
-+M: Zha Qipeng <qipeng.zha@intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: arch/x86/include/asm/intel_punit_ipc.h
-+F: drivers/platform/x86/intel/punit_ipc.c
-+
-+INTEL PMC CORE DRIVER
-+M: Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>
-+M: David E Box <david.e.box@intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
-+F: drivers/platform/x86/intel/pmc/
-+
-+INTEL PMIC GPIO DRIVERS
-+M: Andy Shevchenko <andy@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
-+F: drivers/gpio/gpio-*cove.c
-+
-+INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
-+M: Andy Shevchenko <andy@kernel.org>
-+S: Maintained
-+F: drivers/mfd/intel_soc_pmic*
-+F: include/linux/mfd/intel_soc_pmic*
-+
-+INTEL PMT DRIVER
-+M: "David E. Box" <david.e.box@linux.intel.com>
-+S: Maintained
-+F: drivers/mfd/intel_pmt.c
-+F: drivers/platform/x86/intel/pmt/
-+
-+INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
-+M: Stanislav Yakovlev <stas.yakovlev@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/device_drivers/wifi/intel/ipw2100.rst
-+F: Documentation/networking/device_drivers/wifi/intel/ipw2200.rst
-+F: drivers/net/wireless/intel/ipw2x00/
-+
-+INTEL PSTATE DRIVER
-+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
-+M: Len Brown <lenb@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+F: drivers/cpufreq/intel_pstate.c
-+
-+INTEL QUADRATURE ENCODER PERIPHERAL DRIVER
-+M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
-+L: linux-iio@vger.kernel.org
-+F: drivers/counter/intel-qep.c
-+
-+INTEL SCU DRIVERS
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+S: Maintained
-+F: arch/x86/include/asm/intel_scu_ipc.h
-+F: drivers/platform/x86/intel_scu_*
-+
-+INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER
-+M: Daniel Scally <djrscally@gmail.com>
-+S: Maintained
-+F: drivers/platform/x86/intel/int3472/
-+
-+INTEL SPEED SELECT TECHNOLOGY
-+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/speed_select_if/
-+F: include/uapi/linux/isst_if.h
-+F: tools/power/x86/intel-speed-select/
-+
-+INTEL STRATIX10 FIRMWARE DRIVERS
-+M: Dinh Nguyen <dinguyen@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
-+F: Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
-+F: drivers/firmware/stratix10-rsu.c
-+F: drivers/firmware/stratix10-svc.c
-+F: include/linux/firmware/intel/stratix10-smc.h
-+F: include/linux/firmware/intel/stratix10-svc-client.h
-+
-+INTEL TELEMETRY DRIVER
-+M: Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>
-+M: "David E. Box" <david.e.box@linux.intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: arch/x86/include/asm/intel_telemetry.h
-+F: drivers/platform/x86/intel/telemetry/
-+
-+INTEL UNCORE FREQUENCY CONTROL
-+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/uncore-frequency.c
-+
-+INTEL VIRTUAL BUTTON DRIVER
-+M: AceLan Kao <acelan.kao@canonical.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/intel/vbtn.c
-+
-+INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
-+M: Stanislaw Gruszka <stf_xl@wp.pl>
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+F: drivers/net/wireless/intel/iwlegacy/
-+
-+INTEL WIRELESS WIFI LINK (iwlwifi)
-+M: Luca Coelho <luciano.coelho@intel.com>
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
-+F: drivers/net/wireless/intel/iwlwifi/
-+
-+INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
-+M: Jithu Joseph <jithu.joseph@intel.com>
-+R: Maurice Ma <maurice.ma@intel.com>
-+S: Maintained
-+W: https://slimbootloader.github.io/security/firmware-update.html
-+F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
-+
-+INTEL WMI THUNDERBOLT FORCE POWER DRIVER
-+L: Dell.Client.Kernel@dell.com
-+S: Maintained
-+F: drivers/platform/x86/intel/wmi/thunderbolt.c
-+
-+INTEL WWAN IOSM DRIVER
-+M: M Chetan Kumar <m.chetan.kumar@intel.com>
-+M: Intel Corporation <linuxwwan@intel.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wwan/iosm/
-+
-+INTEL(R) TRACE HUB
-+M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-+S: Supported
-+F: Documentation/trace/intel_th.rst
-+F: drivers/hwtracing/intel_th/
-+F: include/linux/intel_th.h
-+
-+INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
-+M: Ning Sun <ning.sun@intel.com>
-+L: tboot-devel@lists.sourceforge.net
-+S: Supported
-+W: http://tboot.sourceforge.net
-+T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
-+F: Documentation/x86/intel_txt.rst
-+F: arch/x86/kernel/tboot.c
-+F: include/linux/tboot.h
-+
-+INTEL SGX
-+M: Jarkko Sakkinen <jarkko@kernel.org>
-+R: Dave Hansen <dave.hansen@linux.intel.com>
-+L: linux-sgx@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/intel-sgx/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/sgx
-+F: Documentation/x86/sgx.rst
-+F: arch/x86/entry/vdso/vsgx.S
-+F: arch/x86/include/asm/sgx.h
-+F: arch/x86/include/uapi/asm/sgx.h
-+F: arch/x86/kernel/cpu/sgx/*
-+F: tools/testing/selftests/sgx/*
-+K: \bSGX_
-+
-+INTERCONNECT API
-+M: Georgi Djakov <djakov@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc.git
-+F: Documentation/devicetree/bindings/interconnect/
-+F: Documentation/driver-api/interconnect.rst
-+F: drivers/interconnect/
-+F: include/dt-bindings/interconnect/
-+F: include/linux/interconnect-provider.h
-+F: include/linux/interconnect.h
-+
-+INTERRUPT COUNTER DRIVER
-+M: Oleksij Rempel <o.rempel@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+L: linux-iio@vger.kernel.org
-+F: Documentation/devicetree/bindings/counter/interrupt-counter.yaml
-+F: drivers/counter/interrupt-cnt.c
-+
-+INVENSENSE ICM-426xx IMU DRIVER
-+M: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+W: https://invensense.tdk.com/
-+F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
-+F: drivers/iio/imu/inv_icm42600/
-+
-+INVENSENSE MPU-3050 GYROSCOPE DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
-+F: drivers/iio/gyro/mpu3050*
-+
-+IOC3 ETHERNET DRIVER
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/sgi/ioc3-eth.c
-+
-+IOMAP FILESYSTEM LIBRARY
-+M: Christoph Hellwig <hch@infradead.org>
-+M: Darrick J. Wong <djwong@kernel.org>
-+M: linux-xfs@vger.kernel.org
-+M: linux-fsdevel@vger.kernel.org
-+L: linux-xfs@vger.kernel.org
-+L: linux-fsdevel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
-+F: fs/iomap/
-+F: include/linux/iomap.h
-+
-+IOMMU DRIVERS
-+M: Joerg Roedel <joro@8bytes.org>
-+M: Will Deacon <will@kernel.org>
-+L: iommu@lists.linux-foundation.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-+F: Documentation/devicetree/bindings/iommu/
-+F: Documentation/userspace-api/iommu.rst
-+F: drivers/iommu/
-+F: include/linux/iommu.h
-+F: include/linux/iova.h
-+F: include/linux/of_iommu.h
-+F: include/uapi/linux/iommu.h
-+
-+IO_URING
-+M: Jens Axboe <axboe@kernel.dk>
-+R: Pavel Begunkov <asml.silence@gmail.com>
-+L: io-uring@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.dk/linux-block
-+T: git git://git.kernel.dk/liburing
-+F: fs/io-wq.c
-+F: fs/io-wq.h
-+F: fs/io_uring.c
-+F: include/linux/io_uring.h
-+F: include/uapi/linux/io_uring.h
-+F: tools/io_uring/
-+
-+IPMI SUBSYSTEM
-+M: Corey Minyard <minyard@acm.org>
-+L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
-+S: Supported
-+W: http://openipmi.sourceforge.net/
-+F: Documentation/driver-api/ipmi.rst
-+F: Documentation/devicetree/bindings/ipmi/
-+F: drivers/char/ipmi/
-+F: include/linux/ipmi*
-+F: include/uapi/linux/ipmi*
-+
-+IPS SCSI RAID DRIVER
-+M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+W: http://www.adaptec.com/
-+F: drivers/scsi/ips*
-+
-+IPVS
-+M: Simon Horman <horms@verge.net.au>
-+M: Julian Anastasov <ja@ssi.bg>
-+L: netdev@vger.kernel.org
-+L: lvs-devel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs-next.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git
-+F: Documentation/networking/ipvs-sysctl.rst
-+F: include/net/ip_vs.h
-+F: include/uapi/linux/ip_vs.h
-+F: net/netfilter/ipvs/
-+
-+IPWIRELESS DRIVER
-+M: Jiri Kosina <jikos@kernel.org>
-+M: David Sterba <dsterba@suse.com>
-+S: Odd Fixes
-+F: drivers/tty/ipwireless/
-+
-+IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-+M: Marc Zyngier <maz@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
-+F: Documentation/core-api/irq/irq-domain.rst
-+F: include/linux/irqdomain.h
-+F: kernel/irq/irqdomain.c
-+F: kernel/irq/msi.c
-+
-+IRQ SUBSYSTEM
-+M: Thomas Gleixner <tglx@linutronix.de>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
-+F: kernel/irq/
-+
-+IRQCHIP DRIVERS
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Marc Zyngier <maz@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
-+F: Documentation/devicetree/bindings/interrupt-controller/
-+F: drivers/irqchip/
-+
-+ISA
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+S: Maintained
-+F: Documentation/driver-api/isa.rst
-+F: drivers/base/isa.c
-+F: include/linux/isa.h
-+
-+ISA RADIO MODULE
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-isa*
-+
-+ISAPNP
-+M: Jaroslav Kysela <perex@perex.cz>
-+S: Maintained
-+F: Documentation/driver-api/isapnp.rst
-+F: drivers/pnp/isapnp/
-+F: include/linux/isapnp.h
-+
-+ISCSI
-+M: Lee Duncan <lduncan@suse.com>
-+M: Chris Leech <cleech@redhat.com>
-+L: open-iscsi@googlegroups.com
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+W: www.open-iscsi.com
-+F: drivers/scsi/*iscsi*
-+F: include/scsi/*iscsi*
-+
-+iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
-+M: Peter Jones <pjones@redhat.com>
-+M: Konrad Rzeszutek Wilk <konrad@kernel.org>
-+S: Maintained
-+F: drivers/firmware/iscsi_ibft*
-+
-+ISCSI EXTENSIONS FOR RDMA (ISER) INITIATOR
-+M: Sagi Grimberg <sagi@grimberg.me>
-+M: Max Gurtovoy <mgurtovoy@nvidia.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.openfabrics.org
-+W: www.open-iscsi.org
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/ulp/iser/
-+
-+ISCSI EXTENSIONS FOR RDMA (ISER) TARGET
-+M: Sagi Grimberg <sagi@grimberg.me>
-+L: linux-rdma@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+W: http://www.linux-iscsi.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
-+F: drivers/infiniband/ulp/isert
-+
-+ISDN/CMTP OVER BLUETOOTH
-+M: Karsten Keil <isdn@linux-pingi.de>
-+L: isdn4linux@listserv.isdn4linux.de (subscribers-only)
-+L: netdev@vger.kernel.org
-+S: Odd Fixes
-+W: http://www.isdn4linux.de
-+F: Documentation/isdn/
-+F: drivers/isdn/capi/
-+F: include/linux/isdn/
-+F: include/uapi/linux/isdn/
-+F: net/bluetooth/cmtp/
-+
-+ISDN/mISDN SUBSYSTEM
-+M: Karsten Keil <isdn@linux-pingi.de>
-+L: isdn4linux@listserv.isdn4linux.de (subscribers-only)
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.isdn4linux.de
-+F: drivers/isdn/Kconfig
-+F: drivers/isdn/Makefile
-+F: drivers/isdn/hardware/
-+F: drivers/isdn/mISDN/
-+
-+IT87 HARDWARE MONITORING DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/it87.rst
-+F: drivers/hwmon/it87.c
-+
-+IT913X MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/it913x*
-+
-+ITE IT66121 HDMI BRIDGE DRIVER
-+M: Phong LE <ple@baylibre.com>
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
-+F: drivers/gpu/drm/bridge/ite-it66121.c
-+
-+IVTV VIDEO4LINUX DRIVER
-+M: Andy Walls <awalls@md.metrocast.net>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/ivtv*
-+F: drivers/media/pci/ivtv/
-+F: include/uapi/linux/ivtv*
-+
-+IX2505V MEDIA DRIVER
-+M: Malcolm Priestley <tvboxspy@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/ix2505v*
-+
-+JAILHOUSE HYPERVISOR INTERFACE
-+M: Jan Kiszka <jan.kiszka@siemens.com>
-+L: jailhouse-dev@googlegroups.com
-+S: Maintained
-+F: arch/x86/include/asm/jailhouse_para.h
-+F: arch/x86/kernel/jailhouse.c
-+
-+JC42.4 TEMPERATURE SENSOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/jc42.rst
-+F: drivers/hwmon/jc42.c
-+
-+JFS FILESYSTEM
-+M: Dave Kleikamp <shaggy@kernel.org>
-+L: jfs-discussion@lists.sourceforge.net
-+S: Maintained
-+W: http://jfs.sourceforge.net/
-+T: git git://github.com/kleikamp/linux-shaggy.git
-+F: Documentation/admin-guide/jfs.rst
-+F: fs/jfs/
-+
-+JME NETWORK DRIVER
-+M: Guo-Fu Tseng <cooldavid@cooldavid.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/jme.*
-+
-+JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
-+M: David Woodhouse <dwmw2@infradead.org>
-+M: Richard Weinberger <richard@nod.at>
-+L: linux-mtd@lists.infradead.org
-+S: Odd Fixes
-+W: http://www.linux-mtd.infradead.org/doc/jffs2.html
-+T: git git://git.infradead.org/ubifs-2.6.git
-+F: fs/jffs2/
-+F: include/uapi/linux/jffs2.h
-+
-+JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
-+M: "Theodore Ts'o" <tytso@mit.edu>
-+M: Jan Kara <jack@suse.com>
-+L: linux-ext4@vger.kernel.org
-+S: Maintained
-+F: fs/jbd2/
-+F: include/linux/jbd2.h
-+
-+JPU V4L2 MEM2MEM DRIVER FOR RENESAS
-+M: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/rcar_jpu.c
-+
-+JSM Neo PCI based serial card
-+L: linux-serial@vger.kernel.org
-+S: Orphan
-+F: drivers/tty/serial/jsm/
-+
-+K10TEMP HARDWARE MONITORING DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/k10temp.rst
-+F: drivers/hwmon/k10temp.c
-+
-+K8TEMP HARDWARE MONITORING DRIVER
-+M: Rudolf Marek <r.marek@assembler.cz>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/k8temp.rst
-+F: drivers/hwmon/k8temp.c
-+
-+KASAN
-+M: Andrey Ryabinin <ryabinin.a.a@gmail.com>
-+R: Alexander Potapenko <glider@google.com>
-+R: Andrey Konovalov <andreyknvl@gmail.com>
-+R: Dmitry Vyukov <dvyukov@google.com>
-+L: kasan-dev@googlegroups.com
-+S: Maintained
-+F: Documentation/dev-tools/kasan.rst
-+F: arch/*/include/asm/*kasan.h
-+F: arch/*/mm/kasan_init*
-+F: include/linux/kasan*.h
-+F: lib/Kconfig.kasan
-+F: lib/test_kasan*.c
-+F: mm/kasan/
-+F: scripts/Makefile.kasan
-+
-+KCONFIG
-+M: Masahiro Yamada <masahiroy@kernel.org>
-+L: linux-kbuild@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kconfig
-+F: Documentation/kbuild/kconfig*
-+F: scripts/Kconfig.include
-+F: scripts/kconfig/
-+
-+KCOV
-+R: Dmitry Vyukov <dvyukov@google.com>
-+R: Andrey Konovalov <andreyknvl@gmail.com>
-+L: kasan-dev@googlegroups.com
-+S: Maintained
-+F: Documentation/dev-tools/kcov.rst
-+F: include/linux/kcov.h
-+F: include/uapi/linux/kcov.h
-+F: kernel/kcov.c
-+F: scripts/Makefile.kcov
-+
-+KCSAN
-+M: Marco Elver <elver@google.com>
-+R: Dmitry Vyukov <dvyukov@google.com>
-+L: kasan-dev@googlegroups.com
-+S: Maintained
-+F: Documentation/dev-tools/kcsan.rst
-+F: include/linux/kcsan*.h
-+F: kernel/kcsan/
-+F: lib/Kconfig.kcsan
-+F: scripts/Makefile.kcsan
-+
-+KDUMP
-+M: Dave Young <dyoung@redhat.com>
-+M: Baoquan He <bhe@redhat.com>
-+R: Vivek Goyal <vgoyal@redhat.com>
-+L: kexec@lists.infradead.org
-+S: Maintained
-+W: http://lse.sourceforge.net/kdump/
-+F: Documentation/admin-guide/kdump/
-+F: fs/proc/vmcore.c
-+F: include/linux/crash_core.h
-+F: include/linux/crash_dump.h
-+F: include/uapi/linux/vmcore.h
-+F: kernel/crash_*.c
-+
-+KEENE FM RADIO TRANSMITTER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-keene*
-+
-+KERNEL AUTOMOUNTER
-+M: Ian Kent <raven@themaw.net>
-+L: autofs@vger.kernel.org
-+S: Maintained
-+F: fs/autofs/
-+
-+KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
-+M: Masahiro Yamada <masahiroy@kernel.org>
-+M: Michal Marek <michal.lkml@markovi.net>
-+R: Nick Desaulniers <ndesaulniers@google.com>
-+L: linux-kbuild@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git
-+F: Documentation/kbuild/
-+F: Makefile
-+F: scripts/*vmlinux*
-+F: scripts/Kbuild*
-+F: scripts/Makefile*
-+F: scripts/basic/
-+F: scripts/dummy-tools/
-+F: scripts/mk*
-+F: scripts/mod/
-+F: scripts/package/
-+
-+KERNEL JANITORS
-+L: kernel-janitors@vger.kernel.org
-+S: Odd Fixes
-+W: http://kernelnewbies.org/KernelJanitors
-+
-+KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
-+M: "J. Bruce Fields" <bfields@fieldses.org>
-+M: Chuck Lever <chuck.lever@oracle.com>
-+L: linux-nfs@vger.kernel.org
-+S: Supported
-+W: http://nfs.sourceforge.net/
-+T: git git://linux-nfs.org/~bfields/linux.git
-+F: fs/lockd/
-+F: fs/nfs_common/
-+F: fs/nfsd/
-+F: include/linux/lockd/
-+F: include/linux/sunrpc/
-+F: include/uapi/linux/nfsd/
-+F: include/uapi/linux/sunrpc/
-+F: net/sunrpc/
-+F: Documentation/filesystems/nfs/
-+
-+KERNEL REGRESSIONS
-+M: Thorsten Leemhuis <linux@leemhuis.info>
-+L: regressions@lists.linux.dev
-+S: Supported
-+
-+KERNEL SELFTEST FRAMEWORK
-+M: Shuah Khan <shuah@kernel.org>
-+M: Shuah Khan <skhan@linuxfoundation.org>
-+L: linux-kselftest@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/linux-kselftest/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
-+F: Documentation/dev-tools/kselftest*
-+F: tools/testing/selftests/
-+
-+KERNEL SMB3 SERVER (KSMBD)
-+M: Namjae Jeon <linkinjeon@kernel.org>
-+M: Sergey Senozhatsky <senozhatsky@chromium.org>
-+M: Steve French <sfrench@samba.org>
-+M: Hyunchul Lee <hyc.lee@gmail.com>
-+L: linux-cifs@vger.kernel.org
-+S: Maintained
-+T: git git://git.samba.org/ksmbd.git
-+F: fs/ksmbd/
-+F: fs/smbfs_common/
-+
-+KERNEL UNIT TESTING FRAMEWORK (KUnit)
-+M: Brendan Higgins <brendanhiggins@google.com>
-+L: linux-kselftest@vger.kernel.org
-+L: kunit-dev@googlegroups.com
-+S: Maintained
-+W: https://google.github.io/kunit-docs/third_party/kernel/docs/
-+F: Documentation/dev-tools/kunit/
-+F: include/kunit/
-+F: lib/kunit/
-+F: tools/testing/kunit/
-+
-+KERNEL USERMODE HELPER
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: include/linux/umh.h
-+F: kernel/umh.c
-+
-+KERNEL VIRTUAL MACHINE (KVM)
-+M: Paolo Bonzini <pbonzini@redhat.com>
-+L: kvm@vger.kernel.org
-+S: Supported
-+W: http://www.linux-kvm.org
-+T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-+F: Documentation/virt/kvm/
-+F: include/asm-generic/kvm*
-+F: include/kvm/iodev.h
-+F: include/linux/kvm*
-+F: include/trace/events/kvm.h
-+F: include/uapi/asm-generic/kvm*
-+F: include/uapi/linux/kvm*
-+F: tools/kvm/
-+F: tools/testing/selftests/kvm/
-+F: virt/kvm/*
-+
-+KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
-+M: Marc Zyngier <maz@kernel.org>
-+R: James Morse <james.morse@arm.com>
-+R: Alexandru Elisei <alexandru.elisei@arm.com>
-+R: Suzuki K Poulose <suzuki.poulose@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: kvmarm@lists.cs.columbia.edu (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
-+F: arch/arm64/include/asm/kvm*
-+F: arch/arm64/include/uapi/asm/kvm*
-+F: arch/arm64/kvm/
-+F: include/kvm/arm_*
-+F: tools/testing/selftests/kvm/*/aarch64/
-+F: tools/testing/selftests/kvm/aarch64/
-+
-+KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
-+M: Huacai Chen <chenhuacai@kernel.org>
-+M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
-+L: linux-mips@vger.kernel.org
-+L: kvm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-+F: arch/mips/include/asm/kvm*
-+F: arch/mips/include/uapi/asm/kvm*
-+F: arch/mips/kvm/
-+
-+KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc)
-+M: Paul Mackerras <paulus@ozlabs.org>
-+L: kvm-ppc@vger.kernel.org
-+S: Supported
-+W: http://www.linux-kvm.org/
-+T: git git://github.com/agraf/linux-2.6.git
-+F: arch/powerpc/include/asm/kvm*
-+F: arch/powerpc/include/uapi/asm/kvm*
-+F: arch/powerpc/kernel/kvm*
-+F: arch/powerpc/kvm/
-+
-+KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
-+M: Christian Borntraeger <borntraeger@de.ibm.com>
-+M: Janosch Frank <frankja@linux.ibm.com>
-+R: David Hildenbrand <david@redhat.com>
-+R: Claudio Imbrenda <imbrenda@linux.ibm.com>
-+L: kvm@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
-+F: Documentation/virt/kvm/s390*
-+F: arch/s390/include/asm/gmap.h
-+F: arch/s390/include/asm/kvm*
-+F: arch/s390/include/uapi/asm/kvm*
-+F: arch/s390/kernel/uv.c
-+F: arch/s390/kvm/
-+F: arch/s390/mm/gmap.c
-+F: tools/testing/selftests/kvm/*/s390x/
-+F: tools/testing/selftests/kvm/s390x/
-+
-+KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
-+M: Paolo Bonzini <pbonzini@redhat.com>
-+R: Sean Christopherson <seanjc@google.com>
-+R: Vitaly Kuznetsov <vkuznets@redhat.com>
-+R: Wanpeng Li <wanpengli@tencent.com>
-+R: Jim Mattson <jmattson@google.com>
-+R: Joerg Roedel <joro@8bytes.org>
-+L: kvm@vger.kernel.org
-+S: Supported
-+W: http://www.linux-kvm.org
-+T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-+F: arch/x86/include/asm/kvm*
-+F: arch/x86/include/asm/pvclock-abi.h
-+F: arch/x86/include/asm/svm.h
-+F: arch/x86/include/asm/vmx*.h
-+F: arch/x86/include/uapi/asm/kvm*
-+F: arch/x86/include/uapi/asm/svm.h
-+F: arch/x86/include/uapi/asm/vmx.h
-+F: arch/x86/kernel/kvm.c
-+F: arch/x86/kernel/kvmclock.c
-+F: arch/x86/kvm/
-+F: arch/x86/kvm/*/
-+
-+KERNFS
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+M: Tejun Heo <tj@kernel.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
-+F: fs/kernfs/
-+F: include/linux/kernfs.h
-+
-+KEXEC
-+M: Eric Biederman <ebiederm@xmission.com>
-+L: kexec@lists.infradead.org
-+S: Maintained
-+W: http://kernel.org/pub/linux/utils/kernel/kexec/
-+F: include/linux/kexec.h
-+F: include/uapi/linux/kexec.h
-+F: kernel/kexec*
-+
-+KEYS-ENCRYPTED
-+M: Mimi Zohar <zohar@linux.ibm.com>
-+L: linux-integrity@vger.kernel.org
-+L: keyrings@vger.kernel.org
-+S: Supported
-+F: Documentation/security/keys/trusted-encrypted.rst
-+F: include/keys/encrypted-type.h
-+F: security/keys/encrypted-keys/
-+
-+KEYS-TRUSTED
-+M: James Bottomley <jejb@linux.ibm.com>
-+M: Jarkko Sakkinen <jarkko@kernel.org>
-+M: Mimi Zohar <zohar@linux.ibm.com>
-+L: linux-integrity@vger.kernel.org
-+L: keyrings@vger.kernel.org
-+S: Supported
-+F: Documentation/security/keys/trusted-encrypted.rst
-+F: include/keys/trusted-type.h
-+F: include/keys/trusted_tpm.h
-+F: security/keys/trusted-keys/
-+
-+KEYS-TRUSTED-TEE
-+M: Sumit Garg <sumit.garg@linaro.org>
-+L: linux-integrity@vger.kernel.org
-+L: keyrings@vger.kernel.org
-+S: Supported
-+F: include/keys/trusted_tee.h
-+F: security/keys/trusted-keys/trusted_tee.c
-+
-+KEYS/KEYRINGS
-+M: David Howells <dhowells@redhat.com>
-+M: Jarkko Sakkinen <jarkko@kernel.org>
-+L: keyrings@vger.kernel.org
-+S: Maintained
-+F: Documentation/security/keys/core.rst
-+F: include/keys/
-+F: include/linux/key-type.h
-+F: include/linux/key.h
-+F: include/linux/keyctl.h
-+F: include/uapi/linux/keyctl.h
-+F: security/keys/
-+
-+KFENCE
-+M: Alexander Potapenko <glider@google.com>
-+M: Marco Elver <elver@google.com>
-+R: Dmitry Vyukov <dvyukov@google.com>
-+L: kasan-dev@googlegroups.com
-+S: Maintained
-+F: Documentation/dev-tools/kfence.rst
-+F: arch/*/include/asm/kfence.h
-+F: include/linux/kfence.h
-+F: lib/Kconfig.kfence
-+F: mm/kfence/
-+
-+KFIFO
-+M: Stefani Seibold <stefani@seibold.net>
-+S: Maintained
-+F: include/linux/kfifo.h
-+F: lib/kfifo.c
-+F: samples/kfifo/
-+
-+KGDB / KDB /debug_core
-+M: Jason Wessel <jason.wessel@windriver.com>
-+M: Daniel Thompson <daniel.thompson@linaro.org>
-+R: Douglas Anderson <dianders@chromium.org>
-+L: kgdb-bugreport@lists.sourceforge.net
-+S: Maintained
-+W: http://kgdb.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git
-+F: Documentation/dev-tools/kgdb.rst
-+F: drivers/misc/kgdbts.c
-+F: drivers/tty/serial/kgdboc.c
-+F: include/linux/kdb.h
-+F: include/linux/kgdb.h
-+F: kernel/debug/
-+
-+KHADAS MCU MFD DRIVER
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: linux-amlogic@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
-+F: drivers/mfd/khadas-mcu.c
-+F: include/linux/mfd/khadas-mcu.h
-+F: drivers/thermal/khadas_mcu_fan.c
-+
-+KMEMLEAK
-+M: Catalin Marinas <catalin.marinas@arm.com>
-+S: Maintained
-+F: Documentation/dev-tools/kmemleak.rst
-+F: include/linux/kmemleak.h
-+F: mm/kmemleak.c
-+F: samples/kmemleak/kmemleak-test.c
-+
-+KMOD KERNEL MODULE LOADER - USERMODE HELPER
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: include/linux/kmod.h
-+F: kernel/kmod.c
-+F: lib/test_kmod.c
-+F: tools/testing/selftests/kmod/
-+
-+KPROBES
-+M: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
-+M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
-+M: "David S. Miller" <davem@davemloft.net>
-+M: Masami Hiramatsu <mhiramat@kernel.org>
-+S: Maintained
-+F: Documentation/trace/kprobes.rst
-+F: include/asm-generic/kprobes.h
-+F: include/linux/kprobes.h
-+F: kernel/kprobes.c
-+
-+KS0108 LCD CONTROLLER DRIVER
-+M: Miguel Ojeda <ojeda@kernel.org>
-+S: Maintained
-+F: Documentation/admin-guide/auxdisplay/ks0108.rst
-+F: drivers/auxdisplay/ks0108.c
-+F: include/linux/ks0108.h
-+
-+KTD253 BACKLIGHT DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml
-+F: drivers/video/backlight/ktd253-backlight.c
-+
-+KTEST
-+M: Steven Rostedt <rostedt@goodmis.org>
-+M: John Hawley <warthog9@eaglescrag.net>
-+S: Maintained
-+F: tools/testing/ktest
-+
-+L3MDEV
-+M: David Ahern <dsahern@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/net/l3mdev.h
-+F: net/l3mdev
-+
-+L7 BPF FRAMEWORK
-+M: John Fastabend <john.fastabend@gmail.com>
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+M: Jakub Sitnicki <jakub@cloudflare.com>
-+M: Lorenz Bauer <lmb@cloudflare.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: include/linux/skmsg.h
-+F: net/core/skmsg.c
-+F: net/core/sock_map.c
-+F: net/ipv4/tcp_bpf.c
-+F: net/ipv4/udp_bpf.c
-+F: net/unix/unix_bpf.c
-+
-+LANDLOCK SECURITY MODULE
-+M: Mickaël Salaün <mic@digikod.net>
-+L: linux-security-module@vger.kernel.org
-+S: Supported
-+W: https://landlock.io
-+T: git https://github.com/landlock-lsm/linux.git
-+F: Documentation/security/landlock.rst
-+F: Documentation/userspace-api/landlock.rst
-+F: include/uapi/linux/landlock.h
-+F: samples/landlock/
-+F: security/landlock/
-+F: tools/testing/selftests/landlock/
-+K: landlock
-+K: LANDLOCK
-+
-+LANTIQ / INTEL Ethernet drivers
-+M: Hauke Mehrtens <hauke@hauke-m.de>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/dsa/lantiq_gswip.c
-+F: drivers/net/dsa/lantiq_pce.h
-+F: drivers/net/ethernet/lantiq_xrx200.c
-+F: net/dsa/tag_gswip.c
-+
-+LANTIQ MIPS ARCHITECTURE
-+M: John Crispin <john@phrozen.org>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/lantiq
-+F: drivers/soc/lantiq
-+
-+LASI 53c700 driver for PARISC
-+M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: Documentation/scsi/53c700.rst
-+F: drivers/scsi/53c700*
-+
-+LEAKING_ADDRESSES
-+M: Tobin C. Harding <me@tobin.cc>
-+M: Tycho Andersen <tycho@tycho.pizza>
-+L: linux-hardening@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tobin/leaks.git
-+F: scripts/leaking_addresses.pl
-+
-+LED SUBSYSTEM
-+M: Pavel Machek <pavel@ucw.cz>
-+L: linux-leds@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds.git
-+F: Documentation/devicetree/bindings/leds/
-+F: drivers/leds/
-+F: include/linux/leds.h
-+
-+LEGACY EEPROM DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+S: Maintained
-+F: Documentation/misc-devices/eeprom.rst
-+F: drivers/misc/eeprom/eeprom.c
-+
-+LEGO MINDSTORMS EV3
-+R: David Lechner <david@lechnology.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/power/supply/lego,ev3-battery.yaml
-+F: arch/arm/boot/dts/da850-lego-ev3.dts
-+F: drivers/power/supply/lego_ev3_battery.c
-+
-+LEGO USB Tower driver
-+M: Juergen Stuber <starblue@users.sourceforge.net>
-+L: legousb-devel@lists.sourceforge.net
-+S: Maintained
-+W: http://legousb.sourceforge.net/
-+F: drivers/usb/misc/legousbtower.c
-+
-+LG LAPTOP EXTRAS
-+M: Matan Ziv-Av <matan@svgalib.org>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-platform-lg-laptop
-+F: Documentation/admin-guide/laptops/lg-laptop.rst
-+F: drivers/platform/x86/lg-laptop.c
-+
-+LG2160 MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/dvb-frontends/lg2160.*
-+
-+LGDT3305 MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/dvb-frontends/lgdt3305.*
-+
-+LIBATA PATA ARASAN COMPACT FLASH CONTROLLER
-+M: Viresh Kumar <vireshk@kernel.org>
-+L: linux-ide@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
-+F: drivers/ata/pata_arasan_cf.c
-+F: include/linux/pata_arasan_cf_data.h
-+
-+LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-ide@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
-+F: drivers/ata/pata_ftide010.c
-+F: drivers/ata/sata_gemini.c
-+F: drivers/ata/sata_gemini.h
-+
-+LIBATA SATA AHCI PLATFORM devices support
-+M: Hans de Goede <hdegoede@redhat.com>
-+M: Jens Axboe <axboe@kernel.dk>
-+L: linux-ide@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
-+F: drivers/ata/ahci_platform.c
-+F: drivers/ata/libahci_platform.c
-+F: include/linux/ahci_platform.h
-+
-+LIBATA SATA PROMISE TX2/TX4 CONTROLLER DRIVER
-+M: Mikael Pettersson <mikpelinux@gmail.com>
-+L: linux-ide@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
-+F: drivers/ata/sata_promise.*
-+
-+LIBATA SUBSYSTEM (Serial and Parallel ATA drivers)
-+M: Damien Le Moal <damien.lemoal@opensource.wdc.com>
-+L: linux-ide@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata.git
-+F: Documentation/devicetree/bindings/ata/
-+F: drivers/ata/
-+F: include/linux/ata.h
-+F: include/linux/libata.h
-+
-+LIBLOCKDEP
-+M: Sasha Levin <alexander.levin@microsoft.com>
-+S: Maintained
-+F: tools/lib/lockdep/
-+
-+LIBNVDIMM BLK: MMIO-APERTURE DRIVER
-+M: Dan Williams <dan.j.williams@intel.com>
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
-+P: Documentation/nvdimm/maintainer-entry-profile.rst
-+F: drivers/nvdimm/blk.c
-+F: drivers/nvdimm/region_devs.c
-+
-+LIBNVDIMM BTT: BLOCK TRANSLATION TABLE
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Dan Williams <dan.j.williams@intel.com>
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
-+P: Documentation/nvdimm/maintainer-entry-profile.rst
-+F: drivers/nvdimm/btt*
-+
-+LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER
-+M: Dan Williams <dan.j.williams@intel.com>
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
-+P: Documentation/nvdimm/maintainer-entry-profile.rst
-+F: drivers/nvdimm/pmem*
-+
-+LIBNVDIMM: DEVICETREE BINDINGS
-+M: Oliver O'Halloran <oohall@gmail.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
-+F: Documentation/devicetree/bindings/pmem/pmem-region.txt
-+F: drivers/nvdimm/of_pmem.c
-+
-+LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
-+M: Dan Williams <dan.j.williams@intel.com>
-+M: Vishal Verma <vishal.l.verma@intel.com>
-+M: Dave Jiang <dave.jiang@intel.com>
-+M: Ira Weiny <ira.weiny@intel.com>
-+L: nvdimm@lists.linux.dev
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
-+P: Documentation/nvdimm/maintainer-entry-profile.rst
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git
-+F: drivers/acpi/nfit/*
-+F: drivers/nvdimm/*
-+F: include/linux/libnvdimm.h
-+F: include/linux/nd.h
-+F: include/uapi/linux/ndctl.h
-+F: tools/testing/nvdimm/
-+
-+LICENSES and SPDX stuff
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-spdx@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/spdx.git
-+F: COPYING
-+F: Documentation/process/license-rules.rst
-+F: LICENSES/
-+F: scripts/spdxcheck-test.sh
-+F: scripts/spdxcheck.py
-+
-+LINEAR RANGES HELPERS
-+M: Mark Brown <broonie@kernel.org>
-+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
-+F: lib/linear_ranges.c
-+F: lib/test_linear_ranges.c
-+F: include/linux/linear_range.h
-+
-+LINUX FOR POWER MACINTOSH
-+M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Odd Fixes
-+F: arch/powerpc/platforms/powermac/
-+F: drivers/macintosh/
-+
-+LINUX FOR POWERPC (32-BIT AND 64-BIT)
-+M: Michael Ellerman <mpe@ellerman.id.au>
-+R: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-+R: Paul Mackerras <paulus@samba.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+W: https://github.com/linuxppc/wiki/wiki
-+Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git
-+F: Documentation/ABI/stable/sysfs-firmware-opal-*
-+F: Documentation/devicetree/bindings/i2c/i2c-opal.txt
-+F: Documentation/devicetree/bindings/powerpc/
-+F: Documentation/devicetree/bindings/rtc/rtc-opal.txt
-+F: Documentation/powerpc/
-+F: arch/powerpc/
-+F: drivers/*/*/*pasemi*
-+F: drivers/*/*pasemi*
-+F: drivers/char/tpm/tpm_ibmvtpm*
-+F: drivers/crypto/nx/
-+F: drivers/crypto/vmx/
-+F: drivers/i2c/busses/i2c-opal.c
-+F: drivers/net/ethernet/ibm/ibmveth.*
-+F: drivers/net/ethernet/ibm/ibmvnic.*
-+F: drivers/pci/hotplug/pnv_php.c
-+F: drivers/pci/hotplug/rpa*
-+F: drivers/rtc/rtc-opal.c
-+F: drivers/scsi/ibmvscsi/
-+F: drivers/tty/hvc/hvc_opal.c
-+F: drivers/watchdog/wdrtas.c
-+F: tools/testing/selftests/powerpc
-+N: /pmac
-+N: powermac
-+N: powernv
-+N: [^a-z0-9]ps3
-+N: pseries
-+
-+LINUX FOR POWERPC EMBEDDED MPC5XXX
-+M: Anatolij Gustschin <agust@denx.de>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Odd Fixes
-+F: arch/powerpc/platforms/512x/
-+F: arch/powerpc/platforms/52xx/
-+
-+LINUX FOR POWERPC EMBEDDED PPC4XX
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Orphan
-+F: arch/powerpc/platforms/40x/
-+F: arch/powerpc/platforms/44x/
-+
-+LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
-+M: Scott Wood <oss@buserror.net>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Odd fixes
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
-+F: Documentation/devicetree/bindings/powerpc/fsl/
-+F: arch/powerpc/platforms/83xx/
-+F: arch/powerpc/platforms/85xx/
-+
-+LINUX FOR POWERPC EMBEDDED PPC8XX
-+M: Christophe Leroy <christophe.leroy@csgroup.eu>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: arch/powerpc/platforms/8xx/
-+
-+LINUX KERNEL DUMP TEST MODULE (LKDTM)
-+M: Kees Cook <keescook@chromium.org>
-+S: Maintained
-+F: drivers/misc/lkdtm/*
-+F: tools/testing/selftests/lkdtm/*
-+
-+LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM)
-+M: Alan Stern <stern@rowland.harvard.edu>
-+M: Andrea Parri <parri.andrea@gmail.com>
-+M: Will Deacon <will@kernel.org>
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Boqun Feng <boqun.feng@gmail.com>
-+M: Nicholas Piggin <npiggin@gmail.com>
-+M: David Howells <dhowells@redhat.com>
-+M: Jade Alglave <j.alglave@ucl.ac.uk>
-+M: Luc Maranget <luc.maranget@inria.fr>
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+R: Akira Yokosawa <akiyks@gmail.com>
-+R: Daniel Lustig <dlustig@nvidia.com>
-+R: Joel Fernandes <joel@joelfernandes.org>
-+L: linux-kernel@vger.kernel.org
-+L: linux-arch@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
-+F: Documentation/atomic_bitops.txt
-+F: Documentation/atomic_t.txt
-+F: Documentation/core-api/refcount-vs-atomic.rst
-+F: Documentation/litmus-tests/
-+F: Documentation/memory-barriers.txt
-+F: tools/memory-model/
-+
-+LIS3LV02D ACCELEROMETER DRIVER
-+M: Eric Piel <eric.piel@tremplin-utc.net>
-+S: Maintained
-+F: Documentation/misc-devices/lis3lv02d.rst
-+F: drivers/misc/lis3lv02d/
-+F: drivers/platform/x86/hp_accel.c
-+
-+LIST KUNIT TEST
-+M: David Gow <davidgow@google.com>
-+L: linux-kselftest@vger.kernel.org
-+L: kunit-dev@googlegroups.com
-+S: Maintained
-+F: lib/list-test.c
-+
-+LITEX PLATFORM
-+M: Karol Gugala <kgugala@antmicro.com>
-+M: Mateusz Holenko <mholenko@antmicro.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/*/litex,*.yaml
-+F: arch/openrisc/boot/dts/or1klitex.dts
-+F: drivers/soc/litex/litex_soc_ctrl.c
-+F: drivers/tty/serial/liteuart.c
-+F: include/linux/litex.h
-+
-+LIVE PATCHING
-+M: Josh Poimboeuf <jpoimboe@redhat.com>
-+M: Jiri Kosina <jikos@kernel.org>
-+M: Miroslav Benes <mbenes@suse.cz>
-+M: Petr Mladek <pmladek@suse.com>
-+R: Joe Lawrence <joe.lawrence@redhat.com>
-+L: live-patching@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching.git
-+F: Documentation/ABI/testing/sysfs-kernel-livepatch
-+F: Documentation/livepatch/
-+F: arch/powerpc/include/asm/livepatch.h
-+F: arch/s390/include/asm/livepatch.h
-+F: arch/x86/include/asm/livepatch.h
-+F: include/linux/livepatch.h
-+F: kernel/livepatch/
-+F: lib/livepatch/
-+F: samples/livepatch/
-+F: tools/testing/selftests/livepatch/
-+
-+LLC (802.2)
-+L: netdev@vger.kernel.org
-+S: Odd fixes
-+F: include/linux/llc.h
-+F: include/net/llc*
-+F: include/uapi/linux/llc.h
-+F: net/llc/
-+
-+LM73 HARDWARE MONITOR DRIVER
-+M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/lm73.c
-+
-+LM78 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/lm78.rst
-+F: drivers/hwmon/lm78.c
-+
-+LM83 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/lm83.rst
-+F: drivers/hwmon/lm83.c
-+
-+LM90 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/hwmon/lm90.txt
-+F: Documentation/hwmon/lm90.rst
-+F: drivers/hwmon/lm90.c
-+F: include/dt-bindings/thermal/lm90.h
-+
-+LM95234 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/lm95234.rst
-+F: drivers/hwmon/lm95234.c
-+
-+LME2510 MEDIA DRIVER
-+M: Malcolm Priestley <tvboxspy@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/usb/dvb-usb-v2/lmedm04*
-+
-+LOADPIN SECURITY MODULE
-+M: Kees Cook <keescook@chromium.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git lsm/loadpin
-+F: Documentation/admin-guide/LSM/LoadPin.rst
-+F: security/loadpin/
-+
-+LOCKING PRIMITIVES
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Ingo Molnar <mingo@redhat.com>
-+M: Will Deacon <will@kernel.org>
-+R: Waiman Long <longman@redhat.com>
-+R: Boqun Feng <boqun.feng@gmail.com> (LOCKDEP)
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
-+F: Documentation/locking/
-+F: arch/*/include/asm/spinlock*.h
-+F: include/linux/lockdep.h
-+F: include/linux/mutex*.h
-+F: include/linux/rwlock*.h
-+F: include/linux/rwsem*.h
-+F: include/linux/seqlock.h
-+F: include/linux/spinlock*.h
-+F: kernel/locking/
-+F: lib/locking*.[ch]
-+X: kernel/locking/locktorture.c
-+
-+LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
-+M: "Richard Russon (FlatCap)" <ldm@flatcap.org>
-+L: linux-ntfs-dev@lists.sourceforge.net
-+S: Maintained
-+W: http://www.linux-ntfs.org/content/view/19/37/
-+F: Documentation/admin-guide/ldm.rst
-+F: block/partitions/ldm.*
-+
-+LOGITECH HID GAMING KEYBOARDS
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
-+F: drivers/hid/hid-lg-g15.c
-+
-+LONTIUM LT8912B MIPI TO HDMI BRIDGE
-+M: Adrien Grassein <adrien.grassein@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
-+F: drivers/gpu/drm/bridge/lontium-lt8912b.c
-+
-+LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
-+M: Sathya Prakash <sathya.prakash@broadcom.com>
-+M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
-+M: Suganath Prabu Subramani <suganath-prabu.subramani@broadcom.com>
-+L: MPT-FusionLinux.pdl@broadcom.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+W: http://www.avagotech.com/support/
-+F: drivers/message/fusion/
-+F: drivers/scsi/mpt3sas/
-+
-+LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
-+M: Matthew Wilcox <willy@infradead.org>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/sym53c8xx_2/
-+
-+LTC1660 DAC DRIVER
-+M: Marcus Folkesson <marcus.folkesson@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml
-+F: drivers/iio/dac/ltc1660.c
-+
-+LTC2947 HARDWARE MONITOR DRIVER
-+M: Nuno Sá <nuno.sa@analog.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/hwmon/adi,ltc2947.yaml
-+F: drivers/hwmon/ltc2947-core.c
-+F: drivers/hwmon/ltc2947-i2c.c
-+F: drivers/hwmon/ltc2947-spi.c
-+F: drivers/hwmon/ltc2947.h
-+
-+LTC2983 IIO TEMPERATURE DRIVER
-+M: Nuno Sá <nuno.sa@analog.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
-+F: drivers/iio/temperature/ltc2983.c
-+
-+LTC4261 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/ltc4261.rst
-+F: drivers/hwmon/ltc4261.c
-+
-+LTC4306 I2C MULTIPLEXER DRIVER
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+W: http://ez.analog.com/community/linux-device-drivers
-+F: Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt
-+F: drivers/i2c/muxes/i2c-mux-ltc4306.c
-+
-+LTP (Linux Test Project)
-+M: Mike Frysinger <vapier@gentoo.org>
-+M: Cyril Hrubis <chrubis@suse.cz>
-+M: Wanlong Gao <wanlong.gao@gmail.com>
-+M: Jan Stancek <jstancek@redhat.com>
-+M: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
-+M: Alexey Kodanev <alexey.kodanev@oracle.com>
-+L: ltp@lists.linux.it (subscribers-only)
-+S: Maintained
-+W: http://linux-test-project.github.io/
-+T: git git://github.com/linux-test-project/ltp.git
-+
-+LYNX PCS MODULE
-+M: Ioana Ciornei <ioana.ciornei@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/pcs/pcs-lynx.c
-+F: include/linux/pcs-lynx.h
-+
-+M68K ARCHITECTURE
-+M: Geert Uytterhoeven <geert@linux-m68k.org>
-+L: linux-m68k@lists.linux-m68k.org
-+S: Maintained
-+W: http://www.linux-m68k.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
-+F: arch/m68k/
-+F: drivers/zorro/
-+
-+M68K ON APPLE MACINTOSH
-+M: Joshua Thompson <funaho@jurai.org>
-+L: linux-m68k@lists.linux-m68k.org
-+S: Maintained
-+W: http://www.mac.linux-m68k.org/
-+F: arch/m68k/mac/
-+F: drivers/macintosh/adb-iop.c
-+F: drivers/macintosh/via-macii.c
-+
-+M68K ON HP9000/300
-+M: Philip Blundell <philb@gnu.org>
-+S: Maintained
-+W: http://www.tazenda.demon.co.uk/phil/linux-hp
-+F: arch/m68k/hp300/
-+
-+M88DS3103 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/m88ds3103*
-+
-+M88RS2000 MEDIA DRIVER
-+M: Malcolm Priestley <tvboxspy@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/m88rs2000*
-+
-+MA901 MASTERKIT USB FM RADIO DRIVER
-+M: Alexey Klimov <klimov.linux@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-ma901.c
-+
-+MAC80211
-+M: Johannes Berg <johannes@sipsolutions.net>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
-+F: Documentation/networking/mac80211-injection.rst
-+F: Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst
-+F: drivers/net/wireless/mac80211_hwsim.[ch]
-+F: include/net/mac80211.h
-+F: net/mac80211/
-+
-+MAILBOX API
-+M: Jassi Brar <jassisinghbrar@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/mailbox/
-+F: include/linux/mailbox_client.h
-+F: include/linux/mailbox_controller.h
-+F: include/dt-bindings/mailbox/
-+F: Documentation/devicetree/bindings/mailbox/
-+
-+MAILBOX ARM MHUv2
-+M: Viresh Kumar <viresh.kumar@linaro.org>
-+M: Tushar Khandelwal <Tushar.Khandelwal@arm.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/mailbox/arm_mhuv2.c
-+F: include/linux/mailbox/arm_mhuv2_message.h
-+F: Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
-+
-+MANAGEMENT COMPONENT TRANSPORT PROTOCOL (MCTP)
-+M: Jeremy Kerr <jk@codeconstruct.com.au>
-+M: Matt Johnston <matt@codeconstruct.com.au>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/mctp.rst
-+F: drivers/net/mctp/
-+F: include/net/mctp.h
-+F: include/net/mctpdevice.h
-+F: include/net/netns/mctp.h
-+F: net/mctp/
-+
-+MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
-+M: Michael Kerrisk <mtk.manpages@gmail.com>
-+L: linux-man@vger.kernel.org
-+S: Maintained
-+W: http://www.kernel.org/doc/man-pages
-+
-+MARDUK (CREATOR CI40) DEVICE TREE SUPPORT
-+M: Rahul Bedarkar <rahulbedarkar89@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/boot/dts/img/pistachio*
-+
-+MARVELL 88E6XXX ETHERNET SWITCH FABRIC DRIVER
-+M: Andrew Lunn <andrew@lunn.ch>
-+M: Vivien Didelot <vivien.didelot@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/marvell.txt
-+F: Documentation/networking/devlink/mv88e6xxx.rst
-+F: drivers/net/dsa/mv88e6xxx/
-+F: include/linux/dsa/mv88e6xxx.h
-+F: include/linux/platform_data/mv88e6xxx.h
-+
-+MARVELL ARMADA 3700 PHY DRIVERS
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
-+F: Documentation/devicetree/bindings/phy/marvell,armada-3700-utmi-phy.yaml
-+F: drivers/phy/marvell/phy-mvebu-a3700-comphy.c
-+F: drivers/phy/marvell/phy-mvebu-a3700-utmi.c
-+
-+MARVELL ARMADA DRM SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+S: Maintained
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-armada-devel
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-armada-fixes
-+F: Documentation/devicetree/bindings/display/armada/
-+F: drivers/gpu/drm/armada/
-+F: include/uapi/drm/armada_drm.h
-+
-+MARVELL CRYPTO DRIVER
-+M: Boris Brezillon <bbrezillon@kernel.org>
-+M: Arnaud Ebalard <arno@natisbad.org>
-+M: Srujana Challa <schalla@marvell.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/marvell/
-+F: include/linux/soc/marvell/octeontx2/
-+
-+MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
-+M: Mirko Lindner <mlindner@marvell.com>
-+M: Stephen Hemminger <stephen@networkplumber.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/marvell/sk*
-+
-+MARVELL LIBERTAS WIRELESS DRIVER
-+L: libertas-dev@lists.infradead.org
-+S: Orphan
-+F: drivers/net/wireless/marvell/libertas/
-+
-+MARVELL MACCHIATOBIN SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
-+
-+MARVELL MV643XX ETHERNET DRIVER
-+M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/marvell/mv643xx_eth.*
-+F: include/linux/mv643xx.h
-+
-+MARVELL MV88X3310 PHY DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+M: Marek Behún <kabel@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/phy/marvell10g.c
-+
-+MARVELL MVEBU THERMAL DRIVER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+S: Maintained
-+F: drivers/thermal/armada_thermal.c
-+
-+MARVELL MVNETA ETHERNET DRIVER
-+M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/marvell/mvneta.*
-+
-+MARVELL MVPP2 ETHERNET DRIVER
-+M: Marcin Wojtas <mw@semihalf.com>
-+M: Russell King <linux@armlinux.org.uk>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/marvell-pp2.txt
-+F: drivers/net/ethernet/marvell/mvpp2/
-+
-+MARVELL MWIFIEX WIRELESS DRIVER
-+M: Amitkumar Karwar <amitkarwar@gmail.com>
-+M: Ganapathi Bhat <ganapathi017@gmail.com>
-+M: Sharvari Harisangam <sharvari.harisangam@nxp.com>
-+M: Xinming Hu <huxinming820@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/marvell/mwifiex/
-+
-+MARVELL MWL8K WIRELESS DRIVER
-+M: Lennert Buytenhek <buytenh@wantstofly.org>
-+L: linux-wireless@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/net/wireless/marvell/mwl8k.c
-+
-+MARVELL NAND CONTROLLER DRIVER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mtd/marvell-nand.txt
-+F: drivers/mtd/nand/raw/marvell_nand.c
-+
-+MARVELL OCTEONTX2 PHYSICAL FUNCTION DRIVER
-+M: Sunil Goutham <sgoutham@marvell.com>
-+M: Geetha sowjanya <gakula@marvell.com>
-+M: Subbaraya Sundeep <sbhatta@marvell.com>
-+M: hariprasad <hkelam@marvell.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/marvell/octeontx2/nic/
-+F: include/linux/soc/marvell/octeontx2/
-+
-+MARVELL OCTEONTX2 RVU ADMIN FUNCTION DRIVER
-+M: Sunil Goutham <sgoutham@marvell.com>
-+M: Linu Cherian <lcherian@marvell.com>
-+M: Geetha sowjanya <gakula@marvell.com>
-+M: Jerin Jacob <jerinj@marvell.com>
-+M: hariprasad <hkelam@marvell.com>
-+M: Subbaraya Sundeep <sbhatta@marvell.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
-+F: drivers/net/ethernet/marvell/octeontx2/af/
-+
-+MARVELL PRESTERA ETHERNET SWITCH DRIVER
-+M: Taras Chornyi <tchornyi@marvell.com>
-+S: Supported
-+W: https://github.com/Marvell-switching/switchdev-prestera
-+F: drivers/net/ethernet/marvell/prestera/
-+
-+MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
-+M: Nicolas Pitre <nico@fluxnic.net>
-+S: Odd Fixes
-+F: drivers/mmc/host/mvsdio.*
-+
-+MARVELL USB MDIO CONTROLLER DRIVER
-+M: Tobias Waldekranz <tobias@waldekranz.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/marvell,mvusb.yaml
-+F: drivers/net/mdio/mdio-mvusb.c
-+
-+MARVELL XENON MMC/SD/SDIO HOST CONTROLLER DRIVER
-+M: Hu Ziji <huziji@marvell.com>
-+L: linux-mmc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
-+F: drivers/mmc/host/sdhci-xenon*
-+
-+MATROX FRAMEBUFFER DRIVER
-+L: linux-fbdev@vger.kernel.org
-+S: Orphan
-+F: drivers/video/fbdev/matrox/matroxfb_*
-+F: include/uapi/linux/matroxfb.h
-+
-+MAX15301 DRIVER
-+M: Daniel Nilsson <daniel.nilsson@flex.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/max15301.rst
-+F: drivers/hwmon/pmbus/max15301.c
-+
-+MAX16065 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/max16065.rst
-+F: drivers/hwmon/max16065.c
-+
-+MAX2175 SDR TUNER DRIVER
-+M: Ramesh Shanmugasundaram <rashanmu@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/max2175.txt
-+F: Documentation/userspace-api/media/drivers/max2175.rst
-+F: drivers/media/i2c/max2175*
-+F: include/uapi/linux/max2175.h
-+
-+MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-+L: linux-hwmon@vger.kernel.org
-+S: Orphan
-+F: Documentation/hwmon/max6650.rst
-+F: drivers/hwmon/max6650.c
-+
-+MAX6697 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/hwmon/max6697.txt
-+F: Documentation/hwmon/max6697.rst
-+F: drivers/hwmon/max6697.c
-+F: include/linux/platform_data/max6697.h
-+
-+MAX9286 QUAD GMSL DESERIALIZER DRIVER
-+M: Jacopo Mondi <jacopo+renesas@jmondi.org>
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-+M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
-+F: drivers/media/i2c/max9286.c
-+
-+MAX9860 MONO AUDIO VOICE CODEC DRIVER
-+M: Peter Rosin <peda@axentia.se>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/max9860.txt
-+F: sound/soc/codecs/max9860.*
-+
-+MAXBOTIX ULTRASONIC RANGER IIO DRIVER
-+M: Andreas Klinger <ak@it-klinger.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml
-+F: drivers/iio/proximity/mb1232.c
-+
-+MAXIM MAX77650 PMIC MFD DRIVER
-+M: Bartosz Golaszewski <brgl@bgdev.pl>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/*/*max77650.yaml
-+F: Documentation/devicetree/bindings/*/max77650*.yaml
-+F: drivers/gpio/gpio-max77650.c
-+F: drivers/input/misc/max77650-onkey.c
-+F: drivers/leds/leds-max77650.c
-+F: drivers/mfd/max77650.c
-+F: drivers/power/supply/max77650-charger.c
-+F: drivers/regulator/max77650-regulator.c
-+F: include/linux/mfd/max77650.h
-+
-+MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
-+M: Javier Martinez Canillas <javier@dowhile0.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/*/*max77802.txt
-+F: drivers/regulator/max77802-regulator.c
-+F: include/dt-bindings/*/*max77802.h
-+
-+MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+F: drivers/power/supply/max14577_charger.c
-+F: drivers/power/supply/max77693_charger.c
-+
-+MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/*/max77686.txt
-+F: Documentation/devicetree/bindings/clock/maxim,max77686.txt
-+F: Documentation/devicetree/bindings/mfd/max14577.txt
-+F: Documentation/devicetree/bindings/mfd/max77693.txt
-+F: drivers/*/max14577*.c
-+F: drivers/*/max77686*.c
-+F: drivers/*/max77693*.c
-+F: drivers/clk/clk-max77686.c
-+F: drivers/extcon/extcon-max14577.c
-+F: drivers/extcon/extcon-max77693.c
-+F: drivers/rtc/rtc-max77686.c
-+F: include/linux/mfd/max14577*.h
-+F: include/linux/mfd/max77686*.h
-+F: include/linux/mfd/max77693*.h
-+
-+MAXIRADIO FM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-maxiradio*
-+
-+MAXLINEAR ETHERNET PHY DRIVER
-+M: Xu Liang <lxu@maxlinear.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/phy/mxl-gpy.c
-+
-+MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
-+R: Yasushi SHOJI <yashi@spacecubics.com>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: drivers/net/can/usb/mcba_usb.c
-+
-+MCAN MMIO DEVICE DRIVER
-+M: Chandrasekar Ramakrishnan <rcsekar@samsung.com>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
-+F: drivers/net/can/m_can/m_can.c
-+F: drivers/net/can/m_can/m_can.h
-+F: drivers/net/can/m_can/m_can_platform.c
-+
-+MCP2221A MICROCHIP USB-HID TO I2C BRIDGE DRIVER
-+M: Rishi Gupta <gupt21@gmail.com>
-+L: linux-i2c@vger.kernel.org
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-mcp2221.c
-+
-+MCP251XFD SPI-CAN NETWORK DRIVER
-+M: Marc Kleine-Budde <mkl@pengutronix.de>
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+R: Thomas Kopp <thomas.kopp@microchip.com>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
-+F: drivers/net/can/spi/mcp251xfd/
-+
-+MCP4018 AND MCP4531 MICROCHIP DIGITAL POTENTIOMETER DRIVERS
-+M: Peter Rosin <peda@axentia.se>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
-+F: drivers/iio/potentiometer/mcp4018.c
-+F: drivers/iio/potentiometer/mcp4531.c
-+
-+MCR20A IEEE-802.15.4 RADIO DRIVER
-+M: Xue Liu <liuxuenetmail@gmail.com>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+W: https://github.com/xueliu/mcr20a-linux
-+F: Documentation/devicetree/bindings/net/ieee802154/mcr20a.txt
-+F: drivers/net/ieee802154/mcr20a.c
-+F: drivers/net/ieee802154/mcr20a.h
-+
-+MEASUREMENT COMPUTING CIO-DAC IIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: drivers/iio/dac/cio-dac.c
-+
-+MEDIA CONTROLLER FRAMEWORK
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://www.linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/mc/
-+F: include/media/media-*.h
-+F: include/uapi/linux/media.h
-+
-+MEDIA DRIVER FOR FREESCALE IMX PXP
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/platform/imx-pxp.[ch]
-+
-+MEDIA DRIVERS FOR ASCOT2E
-+M: Sergey Kozlov <serjk@netup.ru>
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/ascot2e*
-+
-+MEDIA DRIVERS FOR CXD2099AR CI CONTROLLERS
-+M: Jasmin Jessich <jasmin@anw.at>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/cxd2099*
-+
-+MEDIA DRIVERS FOR CXD2841ER
-+M: Sergey Kozlov <serjk@netup.ru>
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/cxd2841er*
-+
-+MEDIA DRIVERS FOR CXD2880
-+M: Yasunari Takiguchi <Yasunari.Takiguchi@sony.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: http://linuxtv.org/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/cxd2880/*
-+F: drivers/media/spi/cxd2880*
-+
-+MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/ddbridge/*
-+
-+MEDIA DRIVERS FOR FREESCALE IMX
-+M: Steve Longerbeam <slongerbeam@gmail.com>
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/imx.rst
-+F: Documentation/devicetree/bindings/media/imx.txt
-+F: drivers/staging/media/imx/
-+F: include/linux/imx-media.h
-+F: include/media/imx.h
-+
-+MEDIA DRIVERS FOR FREESCALE IMX7
-+M: Rui Miguel Silva <rmfrfs@gmail.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/imx7.rst
-+F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
-+F: Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml
-+F: drivers/staging/media/imx/imx7-media-csi.c
-+F: drivers/staging/media/imx/imx7-mipi-csis.c
-+
-+MEDIA DRIVERS FOR HELENE
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/helene*
-+
-+MEDIA DRIVERS FOR HORUS3A
-+M: Sergey Kozlov <serjk@netup.ru>
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/horus3a*
-+
-+MEDIA DRIVERS FOR LNBH25
-+M: Sergey Kozlov <serjk@netup.ru>
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/lnbh25*
-+
-+MEDIA DRIVERS FOR MXL5XX TUNER DEMODULATORS
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/mxl5xx*
-+
-+MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
-+M: Sergey Kozlov <serjk@netup.ru>
-+M: Abylay Ospan <aospan@netup.ru>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+W: https://linuxtv.org
-+W: http://netup.tv/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/netup_unidvb/*
-+
-+MEDIA DRIVERS FOR NVIDIA TEGRA - VDE
-+M: Dmitry Osipenko <digetx@gmail.com>
-+L: linux-media@vger.kernel.org
-+L: linux-tegra@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
-+F: drivers/staging/media/tegra-vde/
-+
-+MEDIA DRIVERS FOR RENESAS - CEU
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,ceu.yaml
-+F: drivers/media/platform/renesas-ceu.c
-+F: include/media/drv-intf/renesas-ceu.h
-+
-+MEDIA DRIVERS FOR RENESAS - DRIF
-+M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,drif.yaml
-+F: drivers/media/platform/rcar_drif.c
-+
-+MEDIA DRIVERS FOR RENESAS - FCP
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,fcp.yaml
-+F: drivers/media/platform/rcar-fcp.c
-+F: include/media/rcar-fcp.h
-+
-+MEDIA DRIVERS FOR RENESAS - FDP1
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,fdp1.yaml
-+F: drivers/media/platform/rcar_fdp1.c
-+
-+MEDIA DRIVERS FOR RENESAS - VIN
-+M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,csi2.yaml
-+F: Documentation/devicetree/bindings/media/renesas,isp.yaml
-+F: Documentation/devicetree/bindings/media/renesas,vin.yaml
-+F: drivers/media/platform/rcar-vin/
-+
-+MEDIA DRIVERS FOR RENESAS - VSP1
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/renesas,vsp1.yaml
-+F: drivers/media/platform/vsp1/
-+
-+MEDIA DRIVERS FOR ST STV0910 DEMODULATOR ICs
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/stv0910*
-+
-+MEDIA DRIVERS FOR ST STV6111 TUNER ICs
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/dvb-frontends/stv6111*
-+
-+MEDIA DRIVERS FOR STM32 - DCMI
-+M: Hugues Fruchet <hugues.fruchet@foss.st.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
-+F: drivers/media/platform/stm32/stm32-dcmi.c
-+
-+MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.kernel.org/project/linux-media/list/
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/
-+F: Documentation/devicetree/bindings/media/
-+F: Documentation/driver-api/media/
-+F: Documentation/userspace-api/media/
-+F: drivers/media/
-+F: drivers/staging/media/
-+F: include/linux/platform_data/media/
-+F: include/media/
-+F: include/uapi/linux/dvb/
-+F: include/uapi/linux/ivtv*
-+F: include/uapi/linux/media.h
-+F: include/uapi/linux/meye.h
-+F: include/uapi/linux/uvcvideo.h
-+F: include/uapi/linux/v4l2-*
-+F: include/uapi/linux/videodev2.h
-+
-+MEDIATEK BLUETOOTH DRIVER
-+M: Sean Wang <sean.wang@mediatek.com>
-+L: linux-bluetooth@vger.kernel.org
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/mediatek-bluetooth.txt
-+F: drivers/bluetooth/btmtkuart.c
-+
-+MEDIATEK BOARD LEVEL SHUTDOWN DRIVERS
-+M: Sean Wang <sean.wang@mediatek.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
-+F: drivers/power/reset/mt6323-poweroff.c
-+
-+MEDIATEK CIR DRIVER
-+M: Sean Wang <sean.wang@mediatek.com>
-+S: Maintained
-+F: drivers/media/rc/mtk-cir.c
-+
-+MEDIATEK DMA DRIVER
-+M: Sean Wang <sean.wang@mediatek.com>
-+L: dmaengine@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/dma/mtk-*
-+F: drivers/dma/mediatek/
-+
-+MEDIATEK ETHERNET DRIVER
-+M: Felix Fietkau <nbd@nbd.name>
-+M: John Crispin <john@phrozen.org>
-+M: Sean Wang <sean.wang@mediatek.com>
-+M: Mark Lee <Mark-MC.Lee@mediatek.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/mediatek/
-+
-+MEDIATEK I2C CONTROLLER DRIVER
-+M: Qii Wang <qii.wang@mediatek.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
-+F: drivers/i2c/busses/i2c-mt65xx.c
-+
-+MEDIATEK IOMMU DRIVER
-+M: Yong Wu <yong.wu@mediatek.com>
-+L: iommu@lists.linux-foundation.org
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/iommu/mediatek*
-+F: drivers/iommu/mtk_iommu*
-+F: include/dt-bindings/memory/mt*-port.h
-+
-+MEDIATEK JPEG DRIVER
-+M: Rick Chang <rick.chang@mediatek.com>
-+M: Bin Liu <bin.liu@mediatek.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.txt
-+F: drivers/media/platform/mtk-jpeg/
-+
-+MEDIATEK MDP DRIVER
-+M: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
-+M: Houlong Wei <houlong.wei@mediatek.com>
-+M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/media/mediatek-mdp.txt
-+F: drivers/media/platform/mtk-mdp/
-+F: drivers/media/platform/mtk-vpu/
-+
-+MEDIATEK MEDIA DRIVER
-+M: Tiffany Lin <tiffany.lin@mediatek.com>
-+M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/media/mediatek-vcodec.txt
-+F: Documentation/devicetree/bindings/media/mediatek-vpu.txt
-+F: drivers/media/platform/mtk-vcodec/
-+F: drivers/media/platform/mtk-vpu/
-+
-+MEDIATEK MMC/SD/SDIO DRIVER
-+M: Chaotian Jing <chaotian.jing@mediatek.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mmc/mtk-sd.yaml
-+F: drivers/mmc/host/mtk-sd.c
-+
-+MEDIATEK MT76 WIRELESS LAN DRIVER
-+M: Felix Fietkau <nbd@nbd.name>
-+M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
-+R: Ryder Lee <ryder.lee@mediatek.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/mediatek/mt76/
-+
-+MEDIATEK MT7601U WIRELESS LAN DRIVER
-+M: Jakub Kicinski <kubakici@wp.pl>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/mediatek/mt7601u/
-+
-+MEDIATEK MT7621 CLOCK DRIVER
-+M: Sergio Paracuellos <sergio.paracuellos@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml
-+F: drivers/clk/ralink/clk-mt7621.c
-+
-+MEDIATEK MT7621/28/88 I2C DRIVER
-+M: Stefan Roese <sr@denx.de>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-mt7621.txt
-+F: drivers/i2c/busses/i2c-mt7621.c
-+
-+MEDIATEK MT7621 PHY PCI DRIVER
-+M: Sergio Paracuellos <sergio.paracuellos@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/mediatek,mt7621-pci-phy.yaml
-+F: drivers/phy/ralink/phy-mt7621-pci.c
-+
-+MEDIATEK NAND CONTROLLER DRIVER
-+L: linux-mtd@lists.infradead.org
-+S: Orphan
-+F: Documentation/devicetree/bindings/mtd/mtk-nand.txt
-+F: drivers/mtd/nand/raw/mtk_*
-+
-+MEDIATEK PMIC LED DRIVER
-+M: Sean Wang <sean.wang@mediatek.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/leds/leds-mt6323.txt
-+F: drivers/leds/leds-mt6323.c
-+
-+MEDIATEK RANDOM NUMBER GENERATOR SUPPORT
-+M: Sean Wang <sean.wang@mediatek.com>
-+S: Maintained
-+F: drivers/char/hw_random/mtk-rng.c
-+
-+MEDIATEK SWITCH DRIVER
-+M: Sean Wang <sean.wang@mediatek.com>
-+M: Landen Chao <Landen.Chao@mediatek.com>
-+M: DENG Qingfang <dqfext@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/dsa/mt7530.*
-+F: net/dsa/tag_mtk.c
-+
-+MEDIATEK USB3 DRD IP DRIVER
-+M: Chunfeng Yun <chunfeng.yun@mediatek.com>
-+L: linux-usb@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/usb/mediatek,*
-+F: drivers/usb/host/xhci-mtk*
-+F: drivers/usb/mtu3/
-+
-+MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
-+M: Peter Senna Tschudin <peter.senna@gmail.com>
-+M: Martin Donnelly <martin.donnelly@ge.com>
-+M: Martyn Welch <martyn.welch@collabora.co.uk>
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
-+F: drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
-+
-+MEGARAID SCSI/SAS DRIVERS
-+M: Kashyap Desai <kashyap.desai@broadcom.com>
-+M: Sumit Saxena <sumit.saxena@broadcom.com>
-+M: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
-+L: megaraidlinux.pdl@broadcom.com
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+W: http://www.avagotech.com/support/
-+F: Documentation/scsi/megaraid.rst
-+F: drivers/scsi/megaraid.*
-+F: drivers/scsi/megaraid/
-+
-+MELEXIS MLX90614 DRIVER
-+M: Crt Mori <cmo@melexis.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://www.melexis.com
-+F: drivers/iio/temperature/mlx90614.c
-+
-+MELEXIS MLX90632 DRIVER
-+M: Crt Mori <cmo@melexis.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+W: http://www.melexis.com
-+F: drivers/iio/temperature/mlx90632.c
-+
-+MELFAS MIP4 TOUCHSCREEN DRIVER
-+M: Sangwon Jee <jeesw@melfas.com>
-+S: Supported
-+W: http://www.melfas.com
-+F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt
-+F: drivers/input/touchscreen/melfas_mip4.c
-+
-+MELLANOX BLUEFIELD I2C DRIVER
-+M: Khalil Blaiech <kblaiech@nvidia.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml
-+F: drivers/i2c/busses/i2c-mlxbf.c
-+
-+MELLANOX ETHERNET DRIVER (mlx4_en)
-+M: Tariq Toukan <tariqt@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlx4/en_*
-+
-+MELLANOX ETHERNET DRIVER (mlx5e)
-+M: Saeed Mahameed <saeedm@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlx5/core/en_*
-+
-+MELLANOX ETHERNET INNOVA DRIVERS
-+R: Boris Pismenny <borisp@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlx5/core/accel/*
-+F: drivers/net/ethernet/mellanox/mlx5/core/en_accel/*
-+F: drivers/net/ethernet/mellanox/mlx5/core/fpga/*
-+F: include/linux/mlx5/mlx5_ifc_fpga.h
-+
-+MELLANOX ETHERNET SWITCH DRIVERS
-+M: Jiri Pirko <jiri@nvidia.com>
-+M: Ido Schimmel <idosch@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlxsw/
-+F: tools/testing/selftests/drivers/net/mlxsw/
-+
-+MELLANOX FIRMWARE FLASH LIBRARY (mlxfw)
-+M: mlxsw@nvidia.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlxfw/
-+
-+MELLANOX HARDWARE PLATFORM SUPPORT
-+M: Hans de Goede <hdegoede@redhat.com>
-+M: Mark Gross <mgross@linux.intel.com>
-+M: Vadim Pasternak <vadimp@nvidia.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Supported
-+F: Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
-+F: drivers/platform/mellanox/
-+F: include/linux/platform_data/mlxreg.h
-+
-+MELLANOX MLX4 core VPI driver
-+M: Tariq Toukan <tariqt@nvidia.com>
-+L: netdev@vger.kernel.org
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: drivers/net/ethernet/mellanox/mlx4/
-+F: include/linux/mlx4/
-+
-+MELLANOX MLX4 IB driver
-+M: Yishai Hadas <yishaih@nvidia.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/hw/mlx4/
-+F: include/linux/mlx4/
-+F: include/uapi/rdma/mlx4-abi.h
-+
-+MELLANOX MLX5 core VPI driver
-+M: Saeed Mahameed <saeedm@nvidia.com>
-+M: Leon Romanovsky <leonro@nvidia.com>
-+L: netdev@vger.kernel.org
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+F: Documentation/networking/device_drivers/ethernet/mellanox/
-+F: drivers/net/ethernet/mellanox/mlx5/core/
-+F: include/linux/mlx5/
-+
-+MELLANOX MLX5 IB driver
-+M: Leon Romanovsky <leonro@nvidia.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+W: http://www.mellanox.com
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/hw/mlx5/
-+F: include/linux/mlx5/
-+F: include/uapi/rdma/mlx5-abi.h
-+
-+MELLANOX MLXCPLD I2C AND MUX DRIVER
-+M: Vadim Pasternak <vadimp@nvidia.com>
-+M: Michael Shych <michaelsh@nvidia.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+F: Documentation/i2c/busses/i2c-mlxcpld.rst
-+F: drivers/i2c/busses/i2c-mlxcpld.c
-+F: drivers/i2c/muxes/i2c-mux-mlxcpld.c
-+
-+MELLANOX MLXCPLD LED DRIVER
-+M: Vadim Pasternak <vadimp@nvidia.com>
-+L: linux-leds@vger.kernel.org
-+S: Supported
-+F: Documentation/leds/leds-mlxcpld.rst
-+F: drivers/leds/leds-mlxcpld.c
-+F: drivers/leds/leds-mlxreg.c
-+
-+MELLANOX PLATFORM DRIVER
-+M: Vadim Pasternak <vadimp@nvidia.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Supported
-+F: drivers/platform/x86/mlx-platform.c
-+
-+MEMBARRIER SUPPORT
-+M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: arch/powerpc/include/asm/membarrier.h
-+F: include/uapi/linux/membarrier.h
-+F: kernel/sched/membarrier.c
-+
-+MEMBLOCK
-+M: Mike Rapoport <rppt@linux.ibm.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: Documentation/core-api/boot-time-mm.rst
-+F: include/linux/memblock.h
-+F: mm/memblock.c
-+
-+MEMORY CONTROLLER DRIVERS
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl.git
-+F: Documentation/devicetree/bindings/memory-controllers/
-+F: drivers/memory/
-+F: include/dt-bindings/memory/
-+F: include/memory/
-+
-+MEMORY FREQUENCY SCALING DRIVERS FOR NVIDIA TEGRA
-+M: Dmitry Osipenko <digetx@gmail.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-tegra@vger.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
-+S: Maintained
-+F: drivers/devfreq/tegra30-devfreq.c
-+
-+MEMORY MANAGEMENT
-+M: Andrew Morton <akpm@linux-foundation.org>
-+L: linux-mm@kvack.org
-+S: Maintained
-+W: http://www.linux-mm.org
-+T: quilt https://ozlabs.org/~akpm/mmotm/
-+T: quilt https://ozlabs.org/~akpm/mmots/
-+T: git git://github.com/hnaz/linux-mm.git
-+F: include/linux/gfp.h
-+F: include/linux/memory_hotplug.h
-+F: include/linux/mm.h
-+F: include/linux/mmzone.h
-+F: include/linux/pagewalk.h
-+F: include/linux/vmalloc.h
-+F: mm/
-+F: tools/testing/selftests/vm/
-+
-+MEMORY TECHNOLOGY DEVICES (MTD)
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+M: Richard Weinberger <richard@nod.at>
-+M: Vignesh Raghavendra <vigneshr@ti.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+W: http://www.linux-mtd.infradead.org/
-+Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
-+C: irc://irc.oftc.net/mtd
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/fixes
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
-+F: Documentation/devicetree/bindings/mtd/
-+F: drivers/mtd/
-+F: include/linux/mtd/
-+F: include/uapi/mtd/
-+
-+MEN A21 WATCHDOG DRIVER
-+M: Johannes Thumshirn <morbidrsa@gmail.com>
-+L: linux-watchdog@vger.kernel.org
-+S: Maintained
-+F: drivers/watchdog/mena21_wdt.c
-+
-+MEN CHAMELEON BUS (mcb)
-+M: Johannes Thumshirn <morbidrsa@gmail.com>
-+S: Maintained
-+F: Documentation/driver-api/men-chameleon-bus.rst
-+F: drivers/mcb/
-+F: include/linux/mcb.h
-+
-+MEN F21BMC (Board Management Controller)
-+M: Andreas Werner <andreas.werner@men.de>
-+S: Supported
-+F: Documentation/hwmon/menf21bmc.rst
-+F: drivers/hwmon/menf21bmc_hwmon.c
-+F: drivers/leds/leds-menf21bmc.c
-+F: drivers/mfd/menf21bmc.c
-+F: drivers/watchdog/menf21bmc_wdt.c
-+
-+MEN Z069 WATCHDOG DRIVER
-+M: Johannes Thumshirn <jth@kernel.org>
-+L: linux-watchdog@vger.kernel.org
-+S: Maintained
-+F: drivers/watchdog/menz69_wdt.c
-+
-+MESON AO CEC DRIVER FOR AMLOGIC SOCS
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: linux-media@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Supported
-+W: http://linux-meson.com/
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/amlogic,meson-gx-ao-cec.yaml
-+F: drivers/media/cec/platform/meson/ao-cec-g12a.c
-+F: drivers/media/cec/platform/meson/ao-cec.c
-+
-+MESON GE2D DRIVER FOR AMLOGIC SOCS
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: linux-media@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
-+F: drivers/media/platform/meson/ge2d/
-+
-+MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS
-+M: Liang Yang <liang.yang@amlogic.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
-+F: drivers/mtd/nand/raw/meson_*
-+
-+MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
-+M: Neil Armstrong <narmstrong@baylibre.com>
-+L: linux-media@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
-+F: drivers/staging/media/meson/vdec/
-+
-+METHODE UDPU SUPPORT
-+M: Vladimir Vid <vladimir.vid@sartura.hr>
-+S: Maintained
-+F: arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts
-+
-+MHI BUS
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+M: Hemant Kumar <hemantk@codeaurora.org>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git
-+F: Documentation/ABI/stable/sysfs-bus-mhi
-+F: Documentation/mhi/
-+F: drivers/bus/mhi/
-+F: include/linux/mhi.h
-+
-+MICROBLAZE ARCHITECTURE
-+M: Michal Simek <monstr@monstr.eu>
-+S: Supported
-+W: http://www.monstr.eu/fdt/
-+T: git git://git.monstr.eu/linux-2.6-microblaze.git
-+F: arch/microblaze/
-+
-+MICROCHIP AT91 DMA DRIVERS
-+M: Ludovic Desroches <ludovic.desroches@microchip.com>
-+M: Tudor Ambarus <tudor.ambarus@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: dmaengine@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/dma/atmel-dma.txt
-+F: drivers/dma/at_hdmac.c
-+F: drivers/dma/at_hdmac_regs.h
-+F: drivers/dma/at_xdmac.c
-+F: include/dt-bindings/dma/at91.h
-+
-+MICROCHIP AT91 SERIAL DRIVER
-+M: Richard Genoud <richard.genoud@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/atmel-usart.txt
-+F: drivers/tty/serial/atmel_serial.c
-+F: drivers/tty/serial/atmel_serial.h
-+
-+MICROCHIP AT91 USART MFD DRIVER
-+M: Radu Pirea <radu_nicolae.pirea@upb.ro>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mfd/atmel-usart.txt
-+F: drivers/mfd/at91-usart.c
-+F: include/dt-bindings/mfd/at91-usart.h
-+
-+MICROCHIP AT91 USART SPI DRIVER
-+M: Radu Pirea <radu_nicolae.pirea@upb.ro>
-+L: linux-spi@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mfd/atmel-usart.txt
-+F: drivers/spi/spi-at91-usart.c
-+
-+MICROCHIP AUDIO ASOC DRIVERS
-+M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+F: sound/soc/atmel
-+
-+MICROCHIP ECC DRIVER
-+M: Tudor Ambarus <tudor.ambarus@microchip.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/atmel-ecc.*
-+
-+MICROCHIP I2C DRIVER
-+M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+F: drivers/i2c/busses/i2c-at91-*.c
-+F: drivers/i2c/busses/i2c-at91.h
-+
-+MICROCHIP ISC DRIVER
-+M: Eugen Hristev <eugen.hristev@microchip.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/media/atmel,isc.yaml
-+F: Documentation/devicetree/bindings/media/microchip,xisc.yaml
-+F: drivers/media/platform/atmel/atmel-isc-base.c
-+F: drivers/media/platform/atmel/atmel-isc-regs.h
-+F: drivers/media/platform/atmel/atmel-isc.h
-+F: drivers/media/platform/atmel/atmel-sama5d2-isc.c
-+F: drivers/media/platform/atmel/atmel-sama7g5-isc.c
-+F: include/linux/atmel-isc-media.h
-+
-+MICROCHIP ISI DRIVER
-+M: Eugen Hristev <eugen.hristev@microchip.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/platform/atmel/atmel-isi.c
-+F: drivers/media/platform/atmel/atmel-isi.h
-+
-+MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER
-+M: Woojung Huh <woojung.huh@microchip.com>
-+M: UNGLinuxDriver@microchip.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
-+F: drivers/net/dsa/microchip/*
-+F: include/linux/platform_data/microchip-ksz.h
-+F: net/dsa/tag_ksz.c
-+
-+MICROCHIP LAN743X ETHERNET DRIVER
-+M: Bryan Whitehead <bryan.whitehead@microchip.com>
-+M: UNGLinuxDriver@microchip.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/microchip/lan743x_*
-+
-+MICROCHIP LCDFB DRIVER
-+M: Nicolas Ferre <nicolas.ferre@microchip.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/atmel_lcdfb.c
-+F: include/video/atmel_lcdc.h
-+
-+MICROCHIP MCP16502 PMIC DRIVER
-+M: Claudiu Beznea <claudiu.beznea@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
-+F: drivers/regulator/mcp16502.c
-+
-+MICROCHIP MCP3911 ADC DRIVER
-+M: Marcus Folkesson <marcus.folkesson@gmail.com>
-+M: Kent Gustavsson <kent@minoris.se>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
-+F: drivers/iio/adc/mcp3911.c
-+
-+MICROCHIP MMC/SD/SDIO MCI DRIVER
-+M: Ludovic Desroches <ludovic.desroches@microchip.com>
-+S: Maintained
-+F: drivers/mmc/host/atmel-mci.c
-+
-+MICROCHIP NAND DRIVER
-+M: Tudor Ambarus <tudor.ambarus@microchip.com>
-+L: linux-mtd@lists.infradead.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
-+F: drivers/mtd/nand/raw/atmel/*
-+
-+MICROCHIP PWM DRIVER
-+M: Claudiu Beznea <claudiu.beznea@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-pwm@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pwm/atmel-pwm.txt
-+F: drivers/pwm/pwm-atmel.c
-+
-+MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER
-+M: Eugen Hristev <eugen.hristev@microchip.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
-+F: drivers/iio/adc/at91-sama5d2_adc.c
-+F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h
-+
-+MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER
-+M: Claudiu Beznea <claudiu.beznea@microchip.com>
-+S: Supported
-+F: drivers/power/reset/at91-sama5d2_shdwc.c
-+
-+MICROCHIP SPI DRIVER
-+M: Tudor Ambarus <tudor.ambarus@microchip.com>
-+S: Supported
-+F: drivers/spi/spi-atmel.*
-+
-+MICROCHIP SSC DRIVER
-+M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/misc/atmel-ssc.c
-+F: include/linux/atmel-ssc.h
-+
-+MICROCHIP USB251XB DRIVER
-+M: Richard Leitner <richard.leitner@skidata.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/usb/usb251xb.txt
-+F: drivers/usb/misc/usb251xb.c
-+
-+MICROCHIP USBA UDC DRIVER
-+M: Cristian Birsan <cristian.birsan@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/usb/gadget/udc/atmel_usba_udc.*
-+
-+MICROCHIP WILC1000 WIFI DRIVER
-+M: Ajay Singh <ajay.kathat@microchip.com>
-+M: Claudiu Beznea <claudiu.beznea@microchip.com>
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+F: drivers/net/wireless/microchip/wilc1000/
-+
-+MICROSEMI MIPS SOCS
-+M: Alexandre Belloni <alexandre.belloni@bootlin.com>
-+M: UNGLinuxDriver@microchip.com
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mips/mscc.txt
-+F: Documentation/devicetree/bindings/power/reset/ocelot-reset.txt
-+F: arch/mips/boot/dts/mscc/
-+F: arch/mips/configs/generic/board-ocelot.config
-+F: arch/mips/generic/board-ocelot.c
-+
-+MICROSEMI SMART ARRAY SMARTPQI DRIVER (smartpqi)
-+M: Don Brace <don.brace@microchip.com>
-+L: storagedev@microchip.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: Documentation/scsi/smartpqi.rst
-+F: drivers/scsi/smartpqi/Kconfig
-+F: drivers/scsi/smartpqi/Makefile
-+F: drivers/scsi/smartpqi/smartpqi*.[ch]
-+F: include/linux/cciss*.h
-+F: include/uapi/linux/cciss*.h
-+
-+MICROSOFT SURFACE BATTERY AND AC DRIVERS
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: linux-pm@vger.kernel.org
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/power/supply/surface_battery.c
-+F: drivers/power/supply/surface_charger.c
-+
-+MICROSOFT SURFACE DTX DRIVER
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/driver-api/surface_aggregator/clients/dtx.rst
-+F: drivers/platform/surface/surface_dtx.c
-+F: include/uapi/linux/surface_aggregator/dtx.h
-+
-+MICROSOFT SURFACE GPE LID SUPPORT DRIVER
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/surface/surface_gpe.c
-+
-+MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
-+M: Hans de Goede <hdegoede@redhat.com>
-+M: Mark Gross <mgross@linux.intel.com>
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
-+F: drivers/platform/surface/
-+
-+MICROSOFT SURFACE HID TRANSPORT DRIVER
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: linux-input@vger.kernel.org
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/surface-hid/
-+
-+MICROSOFT SURFACE HOT-PLUG DRIVER
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/surface/surface_hotplug.c
-+
-+MICROSOFT SURFACE PLATFORM PROFILE DRIVER
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/surface/surface_platform_profile.c
-+
-+MICROSOFT SURFACE PRO 3 BUTTON DRIVER
-+M: Chen Yu <yu.c.chen@intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Supported
-+F: drivers/platform/surface/surfacepro3_button.c
-+
-+MICROSOFT SURFACE SYSTEM AGGREGATOR SUBSYSTEM
-+M: Maximilian Luz <luzmaximilian@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: https://github.com/linux-surface/surface-aggregator-module
-+C: irc://irc.libera.chat/linux-surface
-+F: Documentation/driver-api/surface_aggregator/
-+F: drivers/platform/surface/aggregator/
-+F: drivers/platform/surface/surface_acpi_notify.c
-+F: drivers/platform/surface/surface_aggregator_cdev.c
-+F: drivers/platform/surface/surface_aggregator_registry.c
-+F: include/linux/surface_acpi_notify.h
-+F: include/linux/surface_aggregator/
-+F: include/uapi/linux/surface_aggregator/
-+
-+MICROTEK X6 SCANNER
-+M: Oliver Neukum <oliver@neukum.org>
-+S: Maintained
-+F: drivers/usb/image/microtek.*
-+
-+MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT
-+M: Luka Kovacic <luka.kovacic@sartura.hr>
-+M: Luka Perkov <luka.perkov@sartura.hr>
-+S: Maintained
-+F: arch/arm/boot/dts/armada-xp-crs305-1g-4s-bit.dts
-+F: arch/arm/boot/dts/armada-xp-crs305-1g-4s.dts
-+F: arch/arm/boot/dts/armada-xp-crs326-24g-2s-bit.dts
-+F: arch/arm/boot/dts/armada-xp-crs326-24g-2s.dts
-+F: arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s-bit.dts
-+F: arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dts
-+
-+MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
-+F: Documentation/driver-api/media/drivers/ccs/
-+F: Documentation/userspace-api/media/drivers/ccs.rst
-+F: drivers/media/i2c/ccs-pll.c
-+F: drivers/media/i2c/ccs-pll.h
-+F: drivers/media/i2c/ccs/
-+F: include/uapi/linux/ccs.h
-+F: include/uapi/linux/smiapp.h
-+
-+MIPS
-+M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-mips.org/
-+Q: https://patchwork.kernel.org/project/linux-mips/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
-+F: Documentation/devicetree/bindings/mips/
-+F: Documentation/mips/
-+F: arch/mips/
-+F: drivers/platform/mips/
-+
-+MIPS BOSTON DEVELOPMENT BOARD
-+M: Paul Burton <paulburton@kernel.org>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/clock/img,boston-clock.txt
-+F: arch/mips/boot/dts/img/boston.dts
-+F: arch/mips/configs/generic/board-boston.config
-+F: drivers/clk/imgtec/clk-boston.c
-+F: include/dt-bindings/clock/boston-clock.h
-+
-+MIPS CORE DRIVERS
-+M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-+M: Serge Semin <fancer.lancer@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: drivers/bus/mips_cdmm.c
-+F: drivers/clocksource/mips-gic-timer.c
-+F: drivers/cpuidle/cpuidle-cps.c
-+F: drivers/irqchip/irq-mips-cpu.c
-+F: drivers/irqchip/irq-mips-gic.c
-+
-+MIPS GENERIC PLATFORM
-+M: Paul Burton <paulburton@kernel.org>
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/power/mti,mips-cpc.yaml
-+F: arch/mips/generic/
-+F: arch/mips/tools/generic-board-config.sh
-+
-+MIPS RINT INSTRUCTION EMULATION
-+M: Aleksandar Markovic <aleksandar.markovic@mips.com>
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: arch/mips/math-emu/dp_rint.c
-+F: arch/mips/math-emu/sp_rint.c
-+
-+MIPS/LOONGSON1 ARCHITECTURE
-+M: Keguang Zhang <keguang.zhang@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/include/asm/mach-loongson32/
-+F: arch/mips/loongson32/
-+F: drivers/*/*/*loongson1*
-+F: drivers/*/*loongson1*
-+
-+MIPS/LOONGSON2EF ARCHITECTURE
-+M: Jiaxun Yang <jiaxun.yang@flygoat.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/include/asm/mach-loongson2ef/
-+F: arch/mips/loongson2ef/
-+F: drivers/cpufreq/loongson2_cpufreq.c
-+
-+MIPS/LOONGSON64 ARCHITECTURE
-+M: Huacai Chen <chenhuacai@kernel.org>
-+M: Jiaxun Yang <jiaxun.yang@flygoat.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/include/asm/mach-loongson64/
-+F: arch/mips/loongson64/
-+F: drivers/irqchip/irq-loongson*
-+F: drivers/platform/mips/cpu_hwmon.c
-+
-+MIROSOUND PCM20 FM RADIO RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-miropcm20*
-+
-+MMP SUPPORT
-+R: Lubomir Rintel <lkundrak@v3.sk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Odd Fixes
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git
-+F: arch/arm/boot/dts/mmp*
-+F: arch/arm/mach-mmp/
-+F: include/linux/soc/mmp/
-+
-+MMP USB PHY DRIVERS
-+R: Lubomir Rintel <lkundrak@v3.sk>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/phy/marvell/phy-mmp3-usb.c
-+F: drivers/phy/marvell/phy-pxa-usb.c
-+
-+MMU GATHER AND TLB INVALIDATION
-+M: Will Deacon <will@kernel.org>
-+M: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
-+M: Andrew Morton <akpm@linux-foundation.org>
-+M: Nick Piggin <npiggin@gmail.com>
-+M: Peter Zijlstra <peterz@infradead.org>
-+L: linux-arch@vger.kernel.org
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: arch/*/include/asm/tlb.h
-+F: include/asm-generic/tlb.h
-+F: mm/mmu_gather.c
-+
-+MN88472 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/mn88472*
-+
-+MN88473 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/mn88473*
-+
-+MODULE SUPPORT
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+M: Jessica Yu <jeyu@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux.git modules-next
-+F: include/linux/module.h
-+F: kernel/module.c
-+
-+MONOLITHIC POWER SYSTEM PMIC DRIVER
-+M: Saravanan Sekar <sravanhome@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/mps,mp2629.yaml
-+F: Documentation/devicetree/bindings/regulator/mps,mp*.yaml
-+F: drivers/iio/adc/mp2629_adc.c
-+F: drivers/mfd/mp2629.c
-+F: drivers/power/supply/mp2629_charger.c
-+F: drivers/regulator/mp5416.c
-+F: drivers/regulator/mpq7920.c
-+F: drivers/regulator/mpq7920.h
-+F: include/linux/mfd/mp2629.h
-+
-+MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
-+S: Orphan
-+W: http://popies.net/meye/
-+F: Documentation/userspace-api/media/drivers/meye*
-+F: drivers/media/pci/meye/
-+F: include/uapi/linux/meye.h
-+
-+MOTORCOMM PHY DRIVER
-+M: Peter Geis <pgwipeout@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/phy/motorcomm.c
-+
-+MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
-+M: Jiri Slaby <jirislaby@kernel.org>
-+S: Maintained
-+F: Documentation/driver-api/serial/moxa-smartio.rst
-+F: drivers/tty/mxser.*
-+
-+MR800 AVERMEDIA USB FM RADIO DRIVER
-+M: Alexey Klimov <klimov.linux@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-mr800.c
-+
-+MRF24J40 IEEE 802.15.4 RADIO DRIVER
-+M: Alan Ott <alan@signal11.us>
-+L: linux-wpan@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt
-+F: drivers/net/ieee802154/mrf24j40.c
-+
-+MSI LAPTOP SUPPORT
-+M: "Lee, Chun-Yi" <jlee@suse.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/msi-laptop.c
-+
-+MSI WMI SUPPORT
-+L: platform-driver-x86@vger.kernel.org
-+S: Orphan
-+F: drivers/platform/x86/msi-wmi.c
-+
-+MSI001 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/msi001*
-+
-+MSI2500 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/usb/msi2500/
-+
-+MSTAR INTERRUPT CONTROLLER DRIVER
-+M: Mark-PK Tsai <mark-pk.tsai@mediatek.com>
-+M: Daniel Palmer <daniel@thingy.jp>
-+S: Maintained
-+F: Documentation/devicetree/bindings/interrupt-controller/mstar,mst-intc.yaml
-+F: drivers/irqchip/irq-mst-intc.c
-+
-+MSYSTEMS DISKONCHIP G3 MTD DRIVER
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: drivers/mtd/devices/docg3*
-+
-+MT9M032 APTINA SENSOR DRIVER
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/mt9m032.c
-+F: include/media/i2c/mt9m032.h
-+
-+MT9P031 APTINA CAMERA SENSOR
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/mt9p031.c
-+F: include/media/i2c/mt9p031.h
-+
-+MT9T001 APTINA CAMERA SENSOR
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/mt9t001.c
-+F: include/media/i2c/mt9t001.h
-+
-+MT9T112 APTINA CAMERA SENSOR
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/mt9t112.c
-+F: include/media/i2c/mt9t112.h
-+
-+MT9V032 APTINA CAMERA SENSOR
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/mt9v032.txt
-+F: drivers/media/i2c/mt9v032.c
-+F: include/media/i2c/mt9v032.h
-+
-+MT9V111 APTINA CAMERA SENSOR
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml
-+F: drivers/media/i2c/mt9v111.c
-+
-+MULTIFUNCTION DEVICES (MFD)
-+M: Lee Jones <lee.jones@linaro.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
-+F: Documentation/devicetree/bindings/mfd/
-+F: drivers/mfd/
-+F: include/dt-bindings/mfd/
-+F: include/linux/mfd/
-+
-+MULTIMEDIA CARD (MMC) ETC. OVER SPI
-+S: Orphan
-+F: drivers/mmc/host/mmc_spi.c
-+F: include/linux/spi/mmc_spi.h
-+
-+MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
-+M: Ulf Hansson <ulf.hansson@linaro.org>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
-+F: Documentation/devicetree/bindings/mmc/
-+F: drivers/mmc/
-+F: include/linux/mmc/
-+F: include/uapi/linux/mmc/
-+
-+MULTIPLEXER SUBSYSTEM
-+M: Peter Rosin <peda@axentia.se>
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-mux*
-+F: Documentation/devicetree/bindings/mux/
-+F: drivers/mux/
-+F: include/dt-bindings/mux/
-+F: include/linux/mux/
-+
-+MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
-+M: Bin Liu <b-liu@ti.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/musb/
-+
-+MXL301RF MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/tuners/mxl301rf*
-+
-+MXL5007T MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/tuners/mxl5007t.*
-+
-+MXSFB DRM DRIVER
-+M: Marek Vasut <marex@denx.de>
-+M: Stefan Agner <stefan@agner.ch>
-+L: dri-devel@lists.freedesktop.org
-+S: Supported
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/devicetree/bindings/display/fsl,lcdif.yaml
-+F: drivers/gpu/drm/mxsfb/
-+
-+MYLEX DAC960 PCI RAID Controller
-+M: Hannes Reinecke <hare@kernel.org>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/myrb.*
-+F: drivers/scsi/myrs.*
-+
-+MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
-+M: Chris Lee <christopher.lee@cspi.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: https://www.cspi.com/ethernet-products/support/downloads/
-+F: drivers/net/ethernet/myricom/myri10ge/
-+
-+NAND FLASH SUBSYSTEM
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+R: Richard Weinberger <richard@nod.at>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+W: http://www.linux-mtd.infradead.org/
-+Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
-+C: irc://irc.oftc.net/mtd
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
-+F: drivers/mtd/nand/
-+F: include/linux/mtd/*nand*.h
-+
-+NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
-+M: Daniel Mack <zonque@gmail.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.native-instruments.com
-+F: sound/usb/caiaq/
-+
-+NATSEMI ETHERNET DRIVER (DP8381x)
-+S: Orphan
-+F: drivers/net/ethernet/natsemi/natsemi.c
-+
-+NCR 5380 SCSI DRIVERS
-+M: Finn Thain <fthain@linux-m68k.org>
-+M: Michael Schmitz <schmitzmic@gmail.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: Documentation/scsi/g_NCR5380.rst
-+F: drivers/scsi/NCR5380.*
-+F: drivers/scsi/arm/cumana_1.c
-+F: drivers/scsi/arm/oak.c
-+F: drivers/scsi/atari_scsi.*
-+F: drivers/scsi/dmx3191d.c
-+F: drivers/scsi/g_NCR5380.*
-+F: drivers/scsi/mac_scsi.*
-+F: drivers/scsi/sun3_scsi.*
-+F: drivers/scsi/sun3_scsi_vme.c
-+
-+NCSI LIBRARY
-+M: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-+S: Maintained
-+F: net/ncsi/
-+
-+NCT6775 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/nct6775.rst
-+F: drivers/hwmon/nct6775.c
-+
-+NETDEVSIM
-+M: Jakub Kicinski <kuba@kernel.org>
-+S: Maintained
-+F: drivers/net/netdevsim/*
-+
-+NETEM NETWORK EMULATOR
-+M: Stephen Hemminger <stephen@networkplumber.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: net/sched/sch_netem.c
-+
-+NETERION 10GbE DRIVERS (s2io/vxge)
-+M: Jon Mason <jdmason@kudzu.us>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/ethernet/neterion/s2io.rst
-+F: Documentation/networking/device_drivers/ethernet/neterion/vxge.rst
-+F: drivers/net/ethernet/neterion/
-+
-+NETFILTER
-+M: Pablo Neira Ayuso <pablo@netfilter.org>
-+M: Jozsef Kadlecsik <kadlec@netfilter.org>
-+M: Florian Westphal <fw@strlen.de>
-+L: netfilter-devel@vger.kernel.org
-+L: coreteam@netfilter.org
-+S: Maintained
-+W: http://www.netfilter.org/
-+W: http://www.iptables.org/
-+W: http://www.nftables.org/
-+Q: http://patchwork.ozlabs.org/project/netfilter-devel/list/
-+C: irc://irc.libera.chat/netfilter
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
-+F: include/linux/netfilter*
-+F: include/linux/netfilter/
-+F: include/net/netfilter/
-+F: include/uapi/linux/netfilter*
-+F: include/uapi/linux/netfilter/
-+F: net/*/netfilter.c
-+F: net/*/netfilter/
-+F: net/bridge/br_netfilter*.c
-+F: net/netfilter/
-+
-+NETROM NETWORK LAYER
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-ax25.org/
-+F: include/net/netrom.h
-+F: include/uapi/linux/netrom.h
-+F: net/netrom/
-+
-+NETRONIX EMBEDDED CONTROLLER
-+M: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mfd/netronix,ntxec.yaml
-+F: drivers/mfd/ntxec.c
-+F: drivers/pwm/pwm-ntxec.c
-+F: drivers/rtc/rtc-ntxec.c
-+F: include/linux/mfd/ntxec.h
-+
-+NETRONOME ETHERNET DRIVERS
-+M: Simon Horman <simon.horman@corigine.com>
-+R: Jakub Kicinski <kuba@kernel.org>
-+L: oss-drivers@corigine.com
-+S: Maintained
-+F: drivers/net/ethernet/netronome/
-+
-+NETWORK BLOCK DEVICE (NBD)
-+M: Josef Bacik <josef@toxicpanda.com>
-+L: linux-block@vger.kernel.org
-+L: nbd@other.debian.org
-+S: Maintained
-+F: Documentation/admin-guide/blockdev/nbd.rst
-+F: drivers/block/nbd.c
-+F: include/trace/events/nbd.h
-+F: include/uapi/linux/nbd.h
-+
-+NETWORK DROP MONITOR
-+M: Neil Horman <nhorman@tuxdriver.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: https://fedorahosted.org/dropwatch/
-+F: include/uapi/linux/net_dropmon.h
-+F: net/core/drop_monitor.c
-+
-+NETWORKING DRIVERS
-+M: "David S. Miller" <davem@davemloft.net>
-+M: Jakub Kicinski <kuba@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
-+F: Documentation/devicetree/bindings/net/
-+F: drivers/connector/
-+F: drivers/net/
-+F: include/linux/etherdevice.h
-+F: include/linux/fcdevice.h
-+F: include/linux/fddidevice.h
-+F: include/linux/hippidevice.h
-+F: include/linux/if_*
-+F: include/linux/inetdevice.h
-+F: include/linux/netdevice.h
-+F: include/uapi/linux/if_*
-+F: include/uapi/linux/netdevice.h
-+
-+NETWORKING DRIVERS (WIRELESS)
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-wireless/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git
-+F: Documentation/devicetree/bindings/net/wireless/
-+F: drivers/net/wireless/
-+
-+NETWORKING [DSA]
-+M: Andrew Lunn <andrew@lunn.ch>
-+M: Vivien Didelot <vivien.didelot@gmail.com>
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+M: Vladimir Oltean <olteanv@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/
-+F: drivers/net/dsa/
-+F: include/linux/dsa/
-+F: include/linux/platform_data/dsa.h
-+F: include/net/dsa.h
-+F: net/dsa/
-+
-+NETWORKING [GENERAL]
-+M: "David S. Miller" <davem@davemloft.net>
-+M: Jakub Kicinski <kuba@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/netdevbpf/list/
-+B: mailto:netdev@vger.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
-+F: Documentation/networking/
-+F: include/linux/in.h
-+F: include/linux/net.h
-+F: include/linux/netdevice.h
-+F: include/net/
-+F: include/uapi/linux/in.h
-+F: include/uapi/linux/net.h
-+F: include/uapi/linux/net_namespace.h
-+F: include/uapi/linux/netdevice.h
-+F: lib/net_utils.c
-+F: lib/random32.c
-+F: net/
-+F: tools/testing/selftests/net/
-+
-+NETWORKING [IPSEC]
-+M: Steffen Klassert <steffen.klassert@secunet.com>
-+M: Herbert Xu <herbert@gondor.apana.org.au>
-+M: "David S. Miller" <davem@davemloft.net>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
-+F: include/net/xfrm.h
-+F: include/uapi/linux/xfrm.h
-+F: net/ipv4/ah4.c
-+F: net/ipv4/esp4*
-+F: net/ipv4/ip_vti.c
-+F: net/ipv4/ipcomp.c
-+F: net/ipv4/xfrm*
-+F: net/ipv6/ah6.c
-+F: net/ipv6/esp6*
-+F: net/ipv6/ip6_vti.c
-+F: net/ipv6/ipcomp6.c
-+F: net/ipv6/xfrm*
-+F: net/key/
-+F: net/xfrm/
-+F: tools/testing/selftests/net/ipsec.c
-+
-+NETWORKING [IPv4/IPv6]
-+M: "David S. Miller" <davem@davemloft.net>
-+M: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
-+M: David Ahern <dsahern@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
-+F: arch/x86/net/*
-+F: include/net/ip*
-+F: net/ipv4/
-+F: net/ipv6/
-+
-+NETWORKING [LABELED] (NetLabel, Labeled IPsec, SECMARK)
-+M: Paul Moore <paul@paul-moore.com>
-+L: netdev@vger.kernel.org
-+L: linux-security-module@vger.kernel.org
-+S: Maintained
-+W: https://github.com/netlabel
-+F: Documentation/netlabel/
-+F: include/net/calipso.h
-+F: include/net/cipso_ipv4.h
-+F: include/net/netlabel.h
-+F: include/uapi/linux/netfilter/xt_CONNSECMARK.h
-+F: include/uapi/linux/netfilter/xt_SECMARK.h
-+F: net/ipv4/cipso_ipv4.c
-+F: net/ipv6/calipso.c
-+F: net/netfilter/xt_CONNSECMARK.c
-+F: net/netfilter/xt_SECMARK.c
-+F: net/netlabel/
-+
-+NETWORKING [MPTCP]
-+M: Mat Martineau <mathew.j.martineau@linux.intel.com>
-+M: Matthieu Baerts <matthieu.baerts@tessares.net>
-+L: netdev@vger.kernel.org
-+L: mptcp@lists.linux.dev
-+S: Maintained
-+W: https://github.com/multipath-tcp/mptcp_net-next/wiki
-+B: https://github.com/multipath-tcp/mptcp_net-next/issues
-+F: Documentation/networking/mptcp-sysctl.rst
-+F: include/net/mptcp.h
-+F: include/trace/events/mptcp.h
-+F: include/uapi/linux/mptcp.h
-+F: net/mptcp/
-+F: tools/testing/selftests/net/mptcp/
-+
-+NETWORKING [TCP]
-+M: Eric Dumazet <edumazet@google.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/linux/tcp.h
-+F: include/net/tcp.h
-+F: include/trace/events/tcp.h
-+F: include/uapi/linux/tcp.h
-+F: net/ipv4/syncookies.c
-+F: net/ipv4/tcp*.c
-+F: net/ipv6/syncookies.c
-+F: net/ipv6/tcp*.c
-+
-+NETWORKING [TLS]
-+M: Boris Pismenny <borisp@nvidia.com>
-+M: John Fastabend <john.fastabend@gmail.com>
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+M: Jakub Kicinski <kuba@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/net/tls.h
-+F: include/uapi/linux/tls.h
-+F: net/tls/*
-+
-+NETWORKING [WIRELESS]
-+L: linux-wireless@vger.kernel.org
-+Q: http://patchwork.kernel.org/project/linux-wireless/list/
-+
-+NETXEN (1/10) GbE SUPPORT
-+M: Manish Chopra <manishc@marvell.com>
-+M: Rahul Verma <rahulv@marvell.com>
-+M: GR-Linux-NIC-Dev@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/qlogic/netxen/
-+
-+NET_FAILOVER MODULE
-+M: Sridhar Samudrala <sridhar.samudrala@intel.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/net_failover.rst
-+F: drivers/net/net_failover.c
-+F: include/net/net_failover.h
-+
-+NEXTHOP
-+M: David Ahern <dsahern@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/net/netns/nexthop.h
-+F: include/net/nexthop.h
-+F: include/uapi/linux/nexthop.h
-+F: net/ipv4/nexthop.c
-+
-+NFC SUBSYSTEM
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-nfc@lists.01.org (subscribers-only)
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/nfc/
-+F: drivers/nfc/
-+F: include/linux/platform_data/nfcmrvl.h
-+F: include/net/nfc/
-+F: include/uapi/linux/nfc.h
-+F: net/nfc/
-+
-+NFC VIRTUAL NCI DEVICE DRIVER
-+M: Bongsu Jeon <bongsu.jeon@samsung.com>
-+L: netdev@vger.kernel.org
-+L: linux-nfc@lists.01.org (subscribers-only)
-+S: Supported
-+F: drivers/nfc/virtual_ncidev.c
-+F: tools/testing/selftests/nci/
-+
-+NFS, SUNRPC, AND LOCKD CLIENTS
-+M: Trond Myklebust <trond.myklebust@hammerspace.com>
-+M: Anna Schumaker <anna.schumaker@netapp.com>
-+L: linux-nfs@vger.kernel.org
-+S: Maintained
-+W: http://client.linux-nfs.org
-+T: git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
-+F: fs/lockd/
-+F: fs/nfs/
-+F: fs/nfs_common/
-+F: include/linux/lockd/
-+F: include/linux/nfs*
-+F: include/linux/sunrpc/
-+F: include/uapi/linux/nfs*
-+F: include/uapi/linux/sunrpc/
-+F: net/sunrpc/
-+F: Documentation/filesystems/nfs/
-+
-+NILFS2 FILESYSTEM
-+M: Ryusuke Konishi <konishi.ryusuke@gmail.com>
-+L: linux-nilfs@vger.kernel.org
-+S: Supported
-+W: https://nilfs.sourceforge.io/
-+W: https://nilfs.osdn.jp/
-+T: git git://github.com/konis/nilfs2.git
-+F: Documentation/filesystems/nilfs2.rst
-+F: fs/nilfs2/
-+F: include/trace/events/nilfs2.h
-+F: include/uapi/linux/nilfs2_api.h
-+F: include/uapi/linux/nilfs2_ondisk.h
-+
-+NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
-+M: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
-+S: Maintained
-+W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
-+F: Documentation/scsi/NinjaSCSI.rst
-+F: drivers/scsi/pcmcia/nsp_*
-+
-+NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER
-+M: GOTO Masanori <gotom@debian.or.jp>
-+M: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
-+S: Maintained
-+W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
-+F: Documentation/scsi/NinjaSCSI.rst
-+F: drivers/scsi/nsp32*
-+
-+NIOS2 ARCHITECTURE
-+M: Dinh Nguyen <dinguyen@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
-+F: arch/nios2/
-+
-+NITRO ENCLAVES (NE)
-+M: Andra Paraschiv <andraprs@amazon.com>
-+M: Alexandru Vasile <lexnv@amazon.com>
-+M: Alexandru Ciobotaru <alcioa@amazon.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+W: https://aws.amazon.com/ec2/nitro/nitro-enclaves/
-+F: Documentation/virt/ne_overview.rst
-+F: drivers/virt/nitro_enclaves/
-+F: include/linux/nitro_enclaves.h
-+F: include/uapi/linux/nitro_enclaves.h
-+F: samples/nitro_enclaves/
-+
-+NOHZ, DYNTICKS SUPPORT
-+M: Frederic Weisbecker <fweisbec@gmail.com>
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Ingo Molnar <mingo@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/nohz
-+F: include/linux/sched/nohz.h
-+F: include/linux/tick.h
-+F: kernel/time/tick*.*
-+
-+NOKIA N900 CAMERA SUPPORT (ET8EK8 SENSOR, AD5820 FOCUS)
-+M: Pavel Machek <pavel@ucw.cz>
-+M: Sakari Ailus <sakari.ailus@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/ad5820.c
-+F: drivers/media/i2c/et8ek8
-+
-+NOKIA N900 POWER SUPPLY DRIVERS
-+R: Pali Rohár <pali@kernel.org>
-+F: drivers/power/supply/bq2415x_charger.c
-+F: drivers/power/supply/bq27xxx_battery.c
-+F: drivers/power/supply/bq27xxx_battery_i2c.c
-+F: drivers/power/supply/isp1704_charger.c
-+F: drivers/power/supply/rx51_battery.c
-+F: include/linux/power/bq2415x_charger.h
-+F: include/linux/power/bq27xxx_battery.h
-+
-+NOLIBC HEADER FILE
-+M: Willy Tarreau <w@1wt.eu>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
-+F: tools/include/nolibc/
-+
-+NSDEPS
-+M: Matthias Maennich <maennich@google.com>
-+S: Maintained
-+F: Documentation/core-api/symbol-namespaces.rst
-+F: scripts/nsdeps
-+
-+NTB AMD DRIVER
-+M: Sanjay R Mehta <sanju.mehta@amd.com>
-+M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-+L: linux-ntb@googlegroups.com
-+S: Supported
-+F: drivers/ntb/hw/amd/
-+
-+NTB DRIVER CORE
-+M: Jon Mason <jdmason@kudzu.us>
-+M: Dave Jiang <dave.jiang@intel.com>
-+M: Allen Hubbe <allenbh@gmail.com>
-+L: linux-ntb@googlegroups.com
-+S: Supported
-+W: https://github.com/jonmason/ntb/wiki
-+T: git git://github.com/jonmason/ntb.git
-+F: drivers/net/ntb_netdev.c
-+F: drivers/ntb/
-+F: include/linux/ntb.h
-+F: include/linux/ntb_transport.h
-+F: tools/testing/selftests/ntb/
-+
-+NTB IDT DRIVER
-+M: Serge Semin <fancer.lancer@gmail.com>
-+L: linux-ntb@googlegroups.com
-+S: Supported
-+F: drivers/ntb/hw/idt/
-+
-+NTB INTEL DRIVER
-+M: Dave Jiang <dave.jiang@intel.com>
-+L: linux-ntb@googlegroups.com
-+S: Supported
-+W: https://github.com/davejiang/linux/wiki
-+T: git https://github.com/davejiang/linux.git
-+F: drivers/ntb/hw/intel/
-+
-+NTFS FILESYSTEM
-+M: Anton Altaparmakov <anton@tuxera.com>
-+L: linux-ntfs-dev@lists.sourceforge.net
-+S: Supported
-+W: http://www.tuxera.com/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs.git
-+F: Documentation/filesystems/ntfs.rst
-+F: fs/ntfs/
-+
-+NTFS3 FILESYSTEM
-+M: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
-+L: ntfs3@lists.linux.dev
-+S: Supported
-+W: http://www.paragon-software.com/
-+T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git
-+F: Documentation/filesystems/ntfs3.rst
-+F: fs/ntfs3/
-+
-+NUBUS SUBSYSTEM
-+M: Finn Thain <fthain@linux-m68k.org>
-+L: linux-m68k@lists.linux-m68k.org
-+S: Maintained
-+F: arch/*/include/asm/nubus.h
-+F: drivers/nubus/
-+F: include/linux/nubus.h
-+F: include/uapi/linux/nubus.h
-+
-+NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
-+M: Antonino Daplas <adaplas@gmail.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/nvidia/
-+F: drivers/video/fbdev/riva/
-+
-+NVM EXPRESS DRIVER
-+M: Keith Busch <kbusch@kernel.org>
-+M: Jens Axboe <axboe@fb.com>
-+M: Christoph Hellwig <hch@lst.de>
-+M: Sagi Grimberg <sagi@grimberg.me>
-+L: linux-nvme@lists.infradead.org
-+S: Supported
-+W: http://git.infradead.org/nvme.git
-+T: git://git.infradead.org/nvme.git
-+F: drivers/nvme/host/
-+F: include/linux/nvme.h
-+F: include/uapi/linux/nvme_ioctl.h
-+
-+NVM EXPRESS FC TRANSPORT DRIVERS
-+M: James Smart <james.smart@broadcom.com>
-+L: linux-nvme@lists.infradead.org
-+S: Supported
-+F: drivers/nvme/host/fc.c
-+F: drivers/nvme/target/fc.c
-+F: drivers/nvme/target/fcloop.c
-+F: include/linux/nvme-fc-driver.h
-+F: include/linux/nvme-fc.h
-+
-+NVM EXPRESS TARGET DRIVER
-+M: Christoph Hellwig <hch@lst.de>
-+M: Sagi Grimberg <sagi@grimberg.me>
-+M: Chaitanya Kulkarni <kch@nvidia.com>
-+L: linux-nvme@lists.infradead.org
-+S: Supported
-+W: http://git.infradead.org/nvme.git
-+T: git://git.infradead.org/nvme.git
-+F: drivers/nvme/target/
-+
-+NVMEM FRAMEWORK
-+M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/srini/nvmem.git
-+F: Documentation/ABI/stable/sysfs-bus-nvmem
-+F: Documentation/devicetree/bindings/nvmem/
-+F: drivers/nvmem/
-+F: include/linux/nvmem-consumer.h
-+F: include/linux/nvmem-provider.h
-+
-+NXP C45 TJA11XX PHY DRIVER
-+M: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/phy/nxp-c45-tja11xx.c
-+
-+NXP FSPI DRIVER
-+M: Ashish Kumar <ashish.kumar@nxp.com>
-+R: Yogesh Gaur <yogeshgaur.83@gmail.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt
-+F: drivers/spi/spi-nxp-fspi.c
-+
-+NXP FXAS21002C DRIVER
-+M: Rui Miguel Silva <rmfrfs@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/gyroscope/nxp,fxas21002c.yaml
-+F: drivers/iio/gyro/fxas21002c.h
-+F: drivers/iio/gyro/fxas21002c_core.c
-+F: drivers/iio/gyro/fxas21002c_i2c.c
-+F: drivers/iio/gyro/fxas21002c_spi.c
-+
-+NXP i.MX CLOCK DRIVERS
-+M: Abel Vesa <abel.vesa@nxp.com>
-+L: linux-clk@vger.kernel.org
-+L: linux-imx@nxp.com
-+S: Maintained
-+F: drivers/clk/imx/
-+
-+NXP i.MX 8MQ DCSS DRIVER
-+M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
-+R: Lucas Stach <l.stach@pengutronix.de>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml
-+F: drivers/gpu/drm/imx/dcss/
-+
-+NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
-+M: Jagan Teki <jagan@amarulasolutions.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml
-+F: drivers/regulator/pf8x00-regulator.c
-+
-+NXP PTN5150A CC LOGIC AND EXTCON DRIVER
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
-+F: drivers/extcon/extcon-ptn5150.c
-+
-+NXP SGTL5000 DRIVER
-+M: Fabio Estevam <festevam@gmail.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/sgtl5000.yaml
-+F: sound/soc/codecs/sgtl5000*
-+
-+NXP SJA1105 ETHERNET SWITCH DRIVER
-+M: Vladimir Oltean <olteanv@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/net/dsa/sja1105
-+F: drivers/net/pcs/pcs-xpcs-nxp.c
-+
-+NXP TDA998X DRM DRIVER
-+M: Russell King <linux@armlinux.org.uk>
-+S: Maintained
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-devel
-+T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-fixes
-+F: drivers/gpu/drm/i2c/tda998x_drv.c
-+F: include/drm/i2c/tda998x.h
-+F: include/dt-bindings/display/tda998x.h
-+K: "nxp,tda998x"
-+
-+NXP TFA9879 DRIVER
-+M: Peter Rosin <peda@axentia.se>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/tfa9879.txt
-+F: sound/soc/codecs/tfa9879*
-+
-+NXP/Goodix TFA989X (TFA1) DRIVER
-+M: Stephan Gerhold <stephan@gerhold.net>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
-+F: sound/soc/codecs/tfa989x.c
-+
-+NXP-NCI NFC DRIVER
-+R: Charles Gorand <charles.gorand@effinnov.com>
-+L: linux-nfc@lists.01.org (subscribers-only)
-+S: Supported
-+F: drivers/nfc/nxp-nci
-+
-+NXP i.MX 8QXP/8QM JPEG V4L2 DRIVER
-+M: Mirela Rabulea <mirela.rabulea@nxp.com>
-+R: NXP Linux Team <linux-imx@nxp.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/imx8-jpeg.yaml
-+F: drivers/media/platform/imx-jpeg
-+
-+NZXT-KRAKEN2 HARDWARE MONITORING DRIVER
-+M: Jonas Malaco <jonas@protocubo.io>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/nzxt-kraken2.rst
-+F: drivers/hwmon/nzxt-kraken2.c
-+
-+OBJAGG
-+M: Jiri Pirko <jiri@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: include/linux/objagg.h
-+F: lib/objagg.c
-+F: lib/test_objagg.c
-+
-+OBJTOOL
-+M: Josh Poimboeuf <jpoimboe@redhat.com>
-+M: Peter Zijlstra <peterz@infradead.org>
-+S: Supported
-+F: tools/objtool/
-+F: include/linux/objtool.h
-+
-+OCELOT ETHERNET SWITCH DRIVER
-+M: Vladimir Oltean <vladimir.oltean@nxp.com>
-+M: Claudiu Manoil <claudiu.manoil@nxp.com>
-+M: Alexandre Belloni <alexandre.belloni@bootlin.com>
-+M: UNGLinuxDriver@microchip.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/dsa/ocelot/*
-+F: drivers/net/ethernet/mscc/
-+F: include/soc/mscc/ocelot*
-+F: net/dsa/tag_ocelot.c
-+F: net/dsa/tag_ocelot_8021q.c
-+F: tools/testing/selftests/drivers/net/ocelot/*
-+
-+OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
-+M: Frederic Barrat <fbarrat@linux.ibm.com>
-+M: Andrew Donnellan <ajd@linux.ibm.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: Documentation/userspace-api/accelerators/ocxl.rst
-+F: arch/powerpc/include/asm/pnv-ocxl.h
-+F: arch/powerpc/platforms/powernv/ocxl.c
-+F: drivers/misc/ocxl/
-+F: include/misc/ocxl*
-+F: include/uapi/misc/ocxl.h
-+
-+OMAP AUDIO SUPPORT
-+M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
-+M: Jarkko Nikula <jarkko.nikula@bitmer.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: sound/soc/ti/n810.c
-+F: sound/soc/ti/omap*
-+F: sound/soc/ti/rx51.c
-+F: sound/soc/ti/sdma-pcm.*
-+
-+OMAP CLOCK FRAMEWORK SUPPORT
-+M: Paul Walmsley <paul@pwsan.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/*omap*/*clock*
-+
-+OMAP DEVICE TREE SUPPORT
-+M: Benoît Cousson <bcousson@baylibre.com>
-+M: Tony Lindgren <tony@atomide.com>
-+L: linux-omap@vger.kernel.org
-+L: devicetree@vger.kernel.org
-+S: Maintained
-+F: arch/arm/boot/dts/*am3*
-+F: arch/arm/boot/dts/*am4*
-+F: arch/arm/boot/dts/*am5*
-+F: arch/arm/boot/dts/*dra7*
-+F: arch/arm/boot/dts/*omap*
-+F: arch/arm/boot/dts/logicpd-som-lv*
-+F: arch/arm/boot/dts/logicpd-torpedo*
-+
-+OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
-+L: linux-omap@vger.kernel.org
-+L: linux-fbdev@vger.kernel.org
-+S: Orphan
-+F: Documentation/arm/omap/dss.rst
-+F: drivers/video/fbdev/omap2/
-+
-+OMAP FRAMEBUFFER SUPPORT
-+L: linux-fbdev@vger.kernel.org
-+L: linux-omap@vger.kernel.org
-+S: Orphan
-+F: drivers/video/fbdev/omap/
-+
-+OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
-+M: Roger Quadros <rogerq@kernel.org>
-+M: Tony Lindgren <tony@atomide.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/mach-omap2/*gpmc*
-+F: drivers/memory/omap-gpmc.c
-+
-+OMAP GPIO DRIVER
-+M: Grygorii Strashko <grygorii.strashko@ti.com>
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+M: Kevin Hilman <khilman@kernel.org>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml
-+F: drivers/gpio/gpio-omap.c
-+
-+OMAP HARDWARE SPINLOCK SUPPORT
-+M: Ohad Ben-Cohen <ohad@wizery.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: drivers/hwspinlock/omap_hwspinlock.c
-+
-+OMAP HS MMC SUPPORT
-+L: linux-mmc@vger.kernel.org
-+L: linux-omap@vger.kernel.org
-+S: Orphan
-+F: drivers/mmc/host/omap_hsmmc.c
-+
-+OMAP HWMOD DATA
-+M: Paul Walmsley <paul@pwsan.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/mach-omap2/omap_hwmod*data*
-+
-+OMAP HWMOD SUPPORT
-+M: Benoît Cousson <bcousson@baylibre.com>
-+M: Paul Walmsley <paul@pwsan.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/mach-omap2/omap_hwmod.*
-+
-+OMAP I2C DRIVER
-+M: Vignesh R <vigneshr@ti.com>
-+L: linux-omap@vger.kernel.org
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
-+F: drivers/i2c/busses/i2c-omap.c
-+
-+OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/ti,omap3isp.txt
-+F: drivers/media/platform/omap3isp/
-+F: drivers/staging/media/omap4iss/
-+
-+OMAP MMC SUPPORT
-+M: Aaro Koskinen <aaro.koskinen@iki.fi>
-+L: linux-omap@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/mmc/host/omap.c
-+
-+OMAP POWER MANAGEMENT SUPPORT
-+M: Kevin Hilman <khilman@kernel.org>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/*omap*/*pm*
-+F: drivers/cpufreq/omap-cpufreq.c
-+
-+OMAP POWERDOMAIN SOC ADAPTATION LAYER SUPPORT
-+M: Rajendra Nayak <rnayak@codeaurora.org>
-+M: Paul Walmsley <paul@pwsan.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/mach-omap2/prm*
-+
-+OMAP RANDOM NUMBER GENERATOR SUPPORT
-+M: Deepak Saxena <dsaxena@plexity.net>
-+S: Maintained
-+F: drivers/char/hw_random/omap-rng.c
-+
-+OMAP USB SUPPORT
-+L: linux-usb@vger.kernel.org
-+L: linux-omap@vger.kernel.org
-+S: Orphan
-+F: arch/arm/*omap*/usb*
-+F: drivers/usb/*/*omap*
-+
-+OMAP/NEWFLOW NANOBONE MACHINE SUPPORT
-+M: Mark Jackson <mpfj@newflow.co.uk>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: arch/arm/boot/dts/am335x-nano.dts
-+
-+OMAP1 SUPPORT
-+M: Aaro Koskinen <aaro.koskinen@iki.fi>
-+M: Tony Lindgren <tony@atomide.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-omap/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
-+F: arch/arm/configs/omap1_defconfig
-+F: arch/arm/mach-omap1/
-+F: arch/arm/plat-omap/
-+F: drivers/i2c/busses/i2c-omap.c
-+F: include/linux/platform_data/ams-delta-fiq.h
-+F: include/linux/platform_data/i2c-omap.h
-+
-+OMAP2+ SUPPORT
-+M: Tony Lindgren <tony@atomide.com>
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+W: http://www.muru.com/linux/omap/
-+W: http://linux.omap.com/
-+Q: http://patchwork.kernel.org/project/linux-omap/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
-+F: arch/arm/configs/omap2plus_defconfig
-+F: arch/arm/mach-omap2/
-+F: arch/arm/plat-omap/
-+F: drivers/bus/ti-sysc.c
-+F: drivers/i2c/busses/i2c-omap.c
-+F: drivers/irqchip/irq-omap-intc.c
-+F: drivers/mfd/*omap*.c
-+F: drivers/mfd/menelaus.c
-+F: drivers/mfd/palmas.c
-+F: drivers/mfd/tps65217.c
-+F: drivers/mfd/tps65218.c
-+F: drivers/mfd/tps65910.c
-+F: drivers/mfd/twl-core.[ch]
-+F: drivers/mfd/twl4030*.c
-+F: drivers/mfd/twl6030*.c
-+F: drivers/mfd/twl6040*.c
-+F: drivers/regulator/palmas-regulator*.c
-+F: drivers/regulator/pbias-regulator.c
-+F: drivers/regulator/tps65217-regulator.c
-+F: drivers/regulator/tps65218-regulator.c
-+F: drivers/regulator/tps65910-regulator.c
-+F: drivers/regulator/twl-regulator.c
-+F: drivers/regulator/twl6030-regulator.c
-+F: include/linux/platform_data/i2c-omap.h
-+F: include/linux/platform_data/ti-sysc.h
-+
-+OMFS FILESYSTEM
-+M: Bob Copeland <me@bobcopeland.com>
-+L: linux-karma-devel@lists.sourceforge.net
-+S: Maintained
-+F: Documentation/filesystems/omfs.rst
-+F: fs/omfs/
-+
-+OMNIKEY CARDMAN 4000 DRIVER
-+M: Harald Welte <laforge@gnumonks.org>
-+S: Maintained
-+F: drivers/char/pcmcia/cm4000_cs.c
-+F: include/linux/cm4000_cs.h
-+F: include/uapi/linux/cm4000_cs.h
-+
-+OMNIKEY CARDMAN 4040 DRIVER
-+M: Harald Welte <laforge@gnumonks.org>
-+S: Maintained
-+F: drivers/char/pcmcia/cm4040_cs.*
-+
-+OMNIVISION OV02A10 SENSOR DRIVER
-+M: Dongchun Zhu <dongchun.zhu@mediatek.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
-+F: drivers/media/i2c/ov02a10.c
-+
-+OMNIVISION OV13858 SENSOR DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov13858.c
-+
-+OMNIVISION OV2680 SENSOR DRIVER
-+M: Rui Miguel Silva <rmfrfs@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml
-+F: drivers/media/i2c/ov2680.c
-+
-+OMNIVISION OV2685 SENSOR DRIVER
-+M: Shunqian Zheng <zhengsq@rock-chips.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov2685.c
-+
-+OMNIVISION OV2740 SENSOR DRIVER
-+M: Tianshu Qiu <tian.shu.qiu@intel.com>
-+R: Shawn Tu <shawnx.tu@intel.com>
-+R: Bingbu Cao <bingbu.cao@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov2740.c
-+
-+OMNIVISION OV5640 SENSOR DRIVER
-+M: Steve Longerbeam <slongerbeam@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov5640.c
-+
-+OMNIVISION OV5647 SENSOR DRIVER
-+M: Dave Stevenson <dave.stevenson@raspberrypi.com>
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ovti,ov5647.yaml
-+F: drivers/media/i2c/ov5647.c
-+
-+OMNIVISION OV5670 SENSOR DRIVER
-+M: Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
-+M: Hyungwoo Yang <hyungwoo.yang@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov5670.c
-+
-+OMNIVISION OV5675 SENSOR DRIVER
-+M: Shawn Tu <shawnx.tu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov5675.c
-+
-+OMNIVISION OV5695 SENSOR DRIVER
-+M: Shunqian Zheng <zhengsq@rock-chips.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov5695.c
-+
-+OMNIVISION OV7670 SENSOR DRIVER
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
-+F: drivers/media/i2c/ov7670.c
-+
-+OMNIVISION OV772x SENSOR DRIVER
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml
-+F: drivers/media/i2c/ov772x.c
-+F: include/media/i2c/ov772x.h
-+
-+OMNIVISION OV7740 SENSOR DRIVER
-+M: Wenyou Yang <wenyou.yang@microchip.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
-+F: drivers/media/i2c/ov7740.c
-+
-+OMNIVISION OV8856 SENSOR DRIVER
-+M: Dongchun Zhu <dongchun.zhu@mediatek.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ov8856.yaml
-+F: drivers/media/i2c/ov8856.c
-+
-+OMNIVISION OV9282 SENSOR DRIVER
-+M: Paul J. Murphy <paul.j.murphy@intel.com>
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
-+F: drivers/media/i2c/ov9282.c
-+
-+OMNIVISION OV9640 SENSOR DRIVER
-+M: Petr Cvek <petrcvekcz@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/ov9640.*
-+
-+OMNIVISION OV9650 SENSOR DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+R: Akinobu Mita <akinobu.mita@gmail.com>
-+R: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/ov9650.txt
-+F: drivers/media/i2c/ov9650.c
-+
-+OMNIVISION OV9734 SENSOR DRIVER
-+M: Tianshu Qiu <tian.shu.qiu@intel.com>
-+R: Bingbu Cao <bingbu.cao@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/ov9734.c
-+
-+ONENAND FLASH DRIVER
-+M: Kyungmin Park <kyungmin.park@samsung.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: drivers/mtd/nand/onenand/
-+F: include/linux/mtd/onenand*.h
-+
-+ONION OMEGA2+ BOARD
-+M: Harvey Hunt <harveyhuntnexus@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/boot/dts/ralink/omega2p.dts
-+
-+OP-TEE DRIVER
-+M: Jens Wiklander <jens.wiklander@linaro.org>
-+L: op-tee@lists.trustedfirmware.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-optee-devices
-+F: drivers/tee/optee/
-+
-+OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
-+M: Sumit Garg <sumit.garg@linaro.org>
-+L: op-tee@lists.trustedfirmware.org
-+S: Maintained
-+F: drivers/char/hw_random/optee-rng.c
-+
-+OPA-VNIC DRIVER
-+M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
-+M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/ulp/opa_vnic
-+
-+OPEN FIRMWARE AND DEVICE TREE OVERLAYS
-+M: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
-+M: Frank Rowand <frowand.list@gmail.com>
-+L: devicetree@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/dynamic-resolution-notes.rst
-+F: Documentation/devicetree/overlay-notes.rst
-+F: drivers/of/overlay.c
-+F: drivers/of/resolver.c
-+K: of_overlay_notifier_
-+
-+OPEN FIRMWARE AND FLATTENED DEVICE TREE
-+M: Rob Herring <robh+dt@kernel.org>
-+M: Frank Rowand <frowand.list@gmail.com>
-+L: devicetree@vger.kernel.org
-+S: Maintained
-+W: http://www.devicetree.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
-+F: Documentation/ABI/testing/sysfs-firmware-ofw
-+F: drivers/of/
-+F: include/linux/of*.h
-+F: scripts/dtc/
-+
-+OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-+M: Rob Herring <robh+dt@kernel.org>
-+L: devicetree@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.ozlabs.org/project/devicetree-bindings/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
-+F: Documentation/devicetree/
-+F: arch/*/boot/dts/
-+F: include/dt-bindings/
-+
-+OPENCOMPUTE PTP CLOCK DRIVER
-+M: Jonathan Lemon <jonathan.lemon@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/ptp/ptp_ocp.c
-+
-+OPENCORES I2C BUS DRIVER
-+M: Peter Korsgaard <peter@korsgaard.com>
-+M: Andrew Lunn <andrew@lunn.ch>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-ocores.txt
-+F: Documentation/i2c/busses/i2c-ocores.rst
-+F: drivers/i2c/busses/i2c-ocores.c
-+F: include/linux/platform_data/i2c-ocores.h
-+
-+OPENRISC ARCHITECTURE
-+M: Jonas Bonn <jonas@southpole.se>
-+M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
-+M: Stafford Horne <shorne@gmail.com>
-+L: openrisc@lists.librecores.org
-+S: Maintained
-+W: http://openrisc.io
-+T: git git://github.com/openrisc/linux.git
-+F: Documentation/devicetree/bindings/openrisc/
-+F: Documentation/openrisc/
-+F: arch/openrisc/
-+F: drivers/irqchip/irq-ompic.c
-+F: drivers/irqchip/irq-or1k-*
-+
-+OPENVSWITCH
-+M: Pravin B Shelar <pshelar@ovn.org>
-+L: netdev@vger.kernel.org
-+L: dev@openvswitch.org
-+S: Maintained
-+W: http://openvswitch.org
-+F: include/uapi/linux/openvswitch.h
-+F: net/openvswitch/
-+
-+OPERATING PERFORMANCE POINTS (OPP)
-+M: Viresh Kumar <vireshk@kernel.org>
-+M: Nishanth Menon <nm@ti.com>
-+M: Stephen Boyd <sboyd@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git
-+F: Documentation/devicetree/bindings/opp/
-+F: Documentation/power/opp.rst
-+F: drivers/opp/
-+F: include/linux/pm_opp.h
-+
-+OPL4 DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: sound/drivers/opl4/
-+
-+ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
-+M: Mark Fasheh <mark@fasheh.com>
-+M: Joel Becker <jlbec@evilplan.org>
-+M: Joseph Qi <joseph.qi@linux.alibaba.com>
-+L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
-+S: Supported
-+W: http://ocfs2.wiki.kernel.org
-+F: Documentation/filesystems/dlmfs.rst
-+F: Documentation/filesystems/ocfs2.rst
-+F: fs/ocfs2/
-+
-+ORANGEFS FILESYSTEM
-+M: Mike Marshall <hubcap@omnibond.com>
-+R: Martin Brandenburg <martin@omnibond.com>
-+L: devel@lists.orangefs.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux.git
-+F: Documentation/filesystems/orangefs.rst
-+F: fs/orangefs/
-+
-+ORINOCO DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/orinoco
-+W: http://www.nongnu.org/orinoco/
-+F: drivers/net/wireless/intersil/orinoco/
-+
-+OV2659 OMNIVISION SENSOR DRIVER
-+M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
-+F: drivers/media/i2c/ov2659.c
-+F: include/media/i2c/ov2659.h
-+
-+OVERLAY FILESYSTEM
-+M: Miklos Szeredi <miklos@szeredi.hu>
-+L: linux-unionfs@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
-+F: Documentation/filesystems/overlayfs.rst
-+F: fs/overlayfs/
-+
-+P54 WIRELESS DRIVER
-+M: Christian Lamparter <chunkeey@googlemail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/p54
-+F: drivers/net/wireless/intersil/p54/
-+
-+PACKING
-+M: Vladimir Oltean <olteanv@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/core-api/packing.rst
-+F: include/linux/packing.h
-+F: lib/packing.c
-+
-+PADATA PARALLEL EXECUTION MECHANISM
-+M: Steffen Klassert <steffen.klassert@secunet.com>
-+M: Daniel Jordan <daniel.m.jordan@oracle.com>
-+L: linux-crypto@vger.kernel.org
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/core-api/padata.rst
-+F: include/linux/padata.h
-+F: kernel/padata.c
-+
-+PAGE POOL
-+M: Jesper Dangaard Brouer <hawk@kernel.org>
-+M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/page_pool.rst
-+F: include/net/page_pool.h
-+F: include/trace/events/page_pool.h
-+F: net/core/page_pool.c
-+
-+PANASONIC LAPTOP ACPI EXTRAS DRIVER
-+M: Kenneth Chan <kenneth.t.chan@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/panasonic-laptop.c
-+
-+PARALLAX PING IIO SENSOR DRIVER
-+M: Andreas Klinger <ak@it-klinger.de>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml
-+F: drivers/iio/proximity/ping.c
-+
-+PARALLEL LCD/KEYPAD PANEL DRIVER
-+M: Willy Tarreau <willy@haproxy.com>
-+M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
-+S: Odd Fixes
-+F: Documentation/admin-guide/lcd-panel-cgram.rst
-+F: drivers/auxdisplay/panel.c
-+
-+PARALLEL PORT SUBSYSTEM
-+M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-+M: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
-+L: linux-parport@lists.infradead.org (subscribers-only)
-+S: Maintained
-+F: Documentation/driver-api/parport*.rst
-+F: drivers/char/ppdev.c
-+F: drivers/parport/
-+F: include/linux/parport*.h
-+F: include/uapi/linux/ppdev.h
-+
-+PARAVIRT_OPS INTERFACE
-+M: Juergen Gross <jgross@suse.com>
-+M: Deep Shah <sdeep@vmware.com>
-+M: "VMware, Inc." <pv-drivers@vmware.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Supported
-+F: Documentation/virt/paravirt_ops.rst
-+F: arch/*/include/asm/paravirt*.h
-+F: arch/*/kernel/paravirt*
-+F: include/linux/hypervisor.h
-+
-+PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
-+M: Tim Waugh <tim@cyberelk.net>
-+L: linux-parport@lists.infradead.org (subscribers-only)
-+S: Maintained
-+F: Documentation/admin-guide/blockdev/paride.rst
-+F: drivers/block/paride/
-+
-+PARISC ARCHITECTURE
-+M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
-+M: Helge Deller <deller@gmx.de>
-+L: linux-parisc@vger.kernel.org
-+S: Maintained
-+W: https://parisc.wiki.kernel.org
-+Q: http://patchwork.kernel.org/project/linux-parisc/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
-+F: Documentation/parisc/
-+F: arch/parisc/
-+F: drivers/char/agp/parisc-agp.c
-+F: drivers/input/misc/hp_sdc_rtc.c
-+F: drivers/input/serio/gscps2.c
-+F: drivers/input/serio/hp_sdc*
-+F: drivers/parisc/
-+F: drivers/parport/parport_gsc.*
-+F: drivers/tty/serial/8250/8250_gsc.c
-+F: drivers/video/console/sti*
-+F: drivers/video/fbdev/sti*
-+F: drivers/video/logo/logo_parisc*
-+F: include/linux/hp_sdc.h
-+
-+PARMAN
-+M: Jiri Pirko <jiri@nvidia.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: include/linux/parman.h
-+F: lib/parman.c
-+F: lib/test_parman.c
-+
-+PC ENGINES APU BOARD DRIVER
-+M: Enrico Weigelt, metux IT consult <info@metux.net>
-+S: Maintained
-+F: drivers/platform/x86/pcengines-apuv2.c
-+
-+PC87360 HARDWARE MONITORING DRIVER
-+M: Jim Cromie <jim.cromie@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/pc87360.rst
-+F: drivers/hwmon/pc87360.c
-+
-+PC8736x GPIO DRIVER
-+M: Jim Cromie <jim.cromie@gmail.com>
-+S: Maintained
-+F: drivers/char/pc8736x_gpio.c
-+
-+PC87427 HARDWARE MONITORING DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/pc87427.rst
-+F: drivers/hwmon/pc87427.c
-+
-+PCA9532 LED DRIVER
-+M: Riku Voipio <riku.voipio@iki.fi>
-+S: Maintained
-+F: drivers/leds/leds-pca9532.c
-+F: include/linux/leds-pca9532.h
-+
-+PCA9541 I2C BUS MASTER SELECTOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/muxes/i2c-mux-pca9541.c
-+
-+PCDP - PRIMARY CONSOLE AND DEBUG PORT
-+M: Khalid Aziz <khalid@gonehiking.org>
-+S: Maintained
-+F: drivers/firmware/pcdp.*
-+
-+PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
-+M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
-+M: Pali Rohár <pali@kernel.org>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/aardvark-pci.txt
-+F: drivers/pci/controller/pci-aardvark.c
-+
-+PCI DRIVER FOR ALTERA PCIE IP
-+M: Joyce Ooi <joyce.ooi@intel.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/altera-pcie.txt
-+F: drivers/pci/controller/pcie-altera.c
-+
-+PCI DRIVER FOR APPLIEDMICRO XGENE
-+M: Toan Le <toan@os.amperecomputing.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/xgene-pci.txt
-+F: drivers/pci/controller/pci-xgene.c
-+
-+PCI DRIVER FOR ARM VERSATILE PLATFORM
-+M: Rob Herring <robh@kernel.org>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/versatile.yaml
-+F: drivers/pci/controller/pci-versatile.c
-+
-+PCI DRIVER FOR ARMADA 8K
-+M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
-+F: drivers/pci/controller/dwc/pcie-armada8k.c
-+
-+PCI DRIVER FOR CADENCE PCIE IP
-+M: Tom Joseph <tjoseph@cadence.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/cdns,*
-+F: drivers/pci/controller/cadence/
-+
-+PCI DRIVER FOR FREESCALE LAYERSCAPE
-+M: Minghuan Lian <minghuan.Lian@nxp.com>
-+M: Mingkai Hu <mingkai.hu@nxp.com>
-+M: Roy Zang <roy.zang@nxp.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/pci/controller/dwc/*layerscape*
-+
-+PCI DRIVER FOR GENERIC OF HOSTS
-+M: Will Deacon <will@kernel.org>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/host-generic-pci.yaml
-+F: drivers/pci/controller/pci-host-common.c
-+F: drivers/pci/controller/pci-host-generic.c
-+
-+PCI DRIVER FOR IMX6
-+M: Richard Zhu <hongxing.zhu@nxp.com>
-+M: Lucas Stach <l.stach@pengutronix.de>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
-+F: drivers/pci/controller/dwc/*imx6*
-+
-+PCI DRIVER FOR FU740
-+M: Paul Walmsley <paul.walmsley@sifive.com>
-+M: Greentime Hu <greentime.hu@sifive.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
-+F: drivers/pci/controller/dwc/pcie-fu740.c
-+
-+PCI DRIVER FOR INTEL IXP4XX
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
-+F: drivers/pci/controller/pci-ixp4xx.c
-+
-+PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
-+M: Nirmal Patel <nirmal.patel@linux.intel.com>
-+R: Jonathan Derrick <jonathan.derrick@linux.dev>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: drivers/pci/controller/vmd.c
-+
-+PCI DRIVER FOR MICROSEMI SWITCHTEC
-+M: Kurt Schwemmer <kurt.schwemmer@microsemi.com>
-+M: Logan Gunthorpe <logang@deltatee.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-switchtec
-+F: Documentation/driver-api/switchtec.rst
-+F: drivers/ntb/hw/mscc/
-+F: drivers/pci/switch/switchtec*
-+F: include/linux/switchtec.h
-+F: include/uapi/linux/switchtec_ioctl.h
-+
-+PCI DRIVER FOR MOBIVEIL PCIE IP
-+M: Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in>
-+M: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
-+F: drivers/pci/controller/mobiveil/pcie-mobiveil*
-+
-+PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
-+M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/pci/controller/*mvebu*
-+
-+PCI DRIVER FOR NVIDIA TEGRA
-+M: Thierry Reding <thierry.reding@gmail.com>
-+L: linux-tegra@vger.kernel.org
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
-+F: drivers/pci/controller/pci-tegra.c
-+
-+PCI DRIVER FOR NXP LAYERSCAPE GEN4 CONTROLLER
-+M: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
-+F: drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
-+
-+PCI DRIVER FOR RENESAS R-CAR
-+M: Marek Vasut <marek.vasut+renesas@gmail.com>
-+M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/*rcar*
-+F: drivers/pci/controller/*rcar*
-+
-+PCI DRIVER FOR SAMSUNG EXYNOS
-+M: Jingoo Han <jingoohan1@gmail.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/controller/dwc/pci-exynos.c
-+
-+PCI DRIVER FOR SYNOPSYS DESIGNWARE
-+M: Jingoo Han <jingoohan1@gmail.com>
-+M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
-+F: Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
-+F: drivers/pci/controller/dwc/*designware*
-+
-+PCI DRIVER FOR TI DRA7XX/J721E
-+M: Kishon Vijay Abraham I <kishon@ti.com>
-+L: linux-omap@vger.kernel.org
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/ti-pci.txt
-+F: drivers/pci/controller/cadence/pci-j721e.c
-+F: drivers/pci/controller/dwc/pci-dra7xx.c
-+
-+PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt
-+F: drivers/pci/controller/pci-v3-semi.c
-+
-+PCI ENDPOINT SUBSYSTEM
-+M: Kishon Vijay Abraham I <kishon@ti.com>
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+R: Krzysztof Wilczyński <kw@linux.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/PCI/endpoint/*
-+F: Documentation/misc-devices/pci-endpoint-test.rst
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/pci-endpoint.git
-+F: drivers/misc/pci_endpoint_test.c
-+F: drivers/pci/endpoint/
-+F: tools/pci/
-+
-+PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC
-+M: Russell Currey <ruscur@russell.cc>
-+M: Oliver O'Halloran <oohall@gmail.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+F: Documentation/PCI/pci-error-recovery.rst
-+F: Documentation/powerpc/eeh-pci-error-recovery.rst
-+F: arch/powerpc/include/*/eeh*.h
-+F: arch/powerpc/kernel/eeh*.c
-+F: arch/powerpc/platforms/*/eeh*.c
-+F: drivers/pci/pcie/aer.c
-+F: drivers/pci/pcie/dpc.c
-+F: drivers/pci/pcie/err.c
-+
-+PCI ERROR RECOVERY
-+M: Linas Vepstas <linasvepstas@gmail.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/PCI/pci-error-recovery.rst
-+
-+PCI MSI DRIVER FOR ALTERA MSI IP
-+M: Joyce Ooi <joyce.ooi@intel.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/altera-pcie-msi.txt
-+F: drivers/pci/controller/pcie-altera-msi.c
-+
-+PCI MSI DRIVER FOR APPLIEDMICRO XGENE
-+M: Toan Le <toan@os.amperecomputing.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
-+F: drivers/pci/controller/pci-xgene-msi.c
-+
-+PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+R: Rob Herring <robh@kernel.org>
-+R: Krzysztof Wilczyński <kw@linux.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.ozlabs.org/project/linux-pci/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
-+F: drivers/pci/controller/
-+
-+PCI SUBSYSTEM
-+M: Bjorn Helgaas <bhelgaas@google.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.ozlabs.org/project/linux-pci/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
-+F: Documentation/PCI/
-+F: Documentation/devicetree/bindings/pci/
-+F: arch/x86/kernel/early-quirks.c
-+F: arch/x86/kernel/quirks.c
-+F: arch/x86/pci/
-+F: drivers/acpi/pci*
-+F: drivers/pci/
-+F: include/asm-generic/pci*
-+F: include/linux/of_pci.h
-+F: include/linux/pci*
-+F: include/uapi/linux/pci*
-+F: lib/pci*
-+
-+PCIE DRIVER FOR AMAZON ANNAPURNA LABS
-+M: Jonathan Chocron <jonnyc@amazon.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/pcie-al.txt
-+F: drivers/pci/controller/dwc/pcie-al.c
-+
-+PCIE DRIVER FOR AMLOGIC MESON
-+M: Yue Wang <yue.wang@Amlogic.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Maintained
-+F: drivers/pci/controller/dwc/pci-meson.c
-+
-+PCIE DRIVER FOR AXIS ARTPEC
-+M: Jesper Nilsson <jesper.nilsson@axis.com>
-+L: linux-arm-kernel@axis.com
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/axis,artpec*
-+F: drivers/pci/controller/dwc/*artpec*
-+
-+PCIE DRIVER FOR CAVIUM THUNDERX
-+M: Robert Richter <rric@kernel.org>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Odd Fixes
-+F: drivers/pci/controller/pci-thunder-*
-+
-+PCIE DRIVER FOR HISILICON
-+M: Zhou Wang <wangzhou1@hisilicon.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/controller/dwc/pcie-hisi.c
-+
-+PCIE DRIVER FOR HISILICON KIRIN
-+M: Xiaowei Song <songxiaowei@hisilicon.com>
-+M: Binghui Wang <wangbinghui@hisilicon.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml
-+F: drivers/pci/controller/dwc/pcie-kirin.c
-+
-+PCIE DRIVER FOR HISILICON STB
-+M: Shawn Guo <shawn.guo@linaro.org>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
-+F: drivers/pci/controller/dwc/pcie-histb.c
-+
-+PCIE DRIVER FOR INTEL KEEM BAY
-+M: Srikanth Thokala <srikanth.thokala@intel.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/intel,keembay-pcie*
-+F: drivers/pci/controller/dwc/pcie-keembay.c
-+
-+PCIE DRIVER FOR INTEL LGM GW SOC
-+M: Rahul Tanwar <rtanwar@maxlinear.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
-+F: drivers/pci/controller/dwc/pcie-intel-gw.c
-+
-+PCIE DRIVER FOR MEDIATEK
-+M: Ryder Lee <ryder.lee@mediatek.com>
-+M: Jianjun Wang <jianjun.wang@mediatek.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-mediatek@lists.infradead.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/mediatek*
-+F: drivers/pci/controller/*mediatek*
-+
-+PCIE DRIVER FOR MICROCHIP
-+M: Daire McNamara <daire.mcnamara@microchip.com>
-+L: linux-pci@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/pci/microchip*
-+F: drivers/pci/controller/*microchip*
-+
-+PCIE DRIVER FOR QUALCOMM MSM
-+M: Stanimir Varbanov <svarbanov@mm-sol.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/controller/dwc/*qcom*
-+
-+PCIE DRIVER FOR ROCKCHIP
-+M: Shawn Lin <shawn.lin@rock-chips.com>
-+L: linux-pci@vger.kernel.org
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/rockchip-pcie*
-+F: drivers/pci/controller/pcie-rockchip*
-+
-+PCIE DRIVER FOR SOCIONEXT UNIPHIER
-+M: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pci/uniphier-pcie*
-+F: drivers/pci/controller/dwc/pcie-uniphier*
-+
-+PCIE DRIVER FOR ST SPEAR13XX
-+M: Pratyush Anand <pratyush.anand@gmail.com>
-+L: linux-pci@vger.kernel.org
-+S: Maintained
-+F: drivers/pci/controller/dwc/*spear*
-+
-+PCMCIA SUBSYSTEM
-+M: Dominik Brodowski <linux@dominikbrodowski.net>
-+S: Odd Fixes
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git
-+F: Documentation/pcmcia/
-+F: drivers/pcmcia/
-+F: include/pcmcia/
-+F: tools/pcmcia/
-+
-+PCNET32 NETWORK DRIVER
-+M: Don Fry <pcnet32@frontier.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/amd/pcnet32.c
-+
-+PCRYPT PARALLEL CRYPTO ENGINE
-+M: Steffen Klassert <steffen.klassert@secunet.com>
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: crypto/pcrypt.c
-+F: include/crypto/pcrypt.h
-+
-+PEAQ WMI HOTKEYS DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/peaq-wmi.c
-+
-+PENSANDO ETHERNET DRIVERS
-+M: Shannon Nelson <snelson@pensando.io>
-+M: drivers@pensando.io
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/ethernet/pensando/ionic.rst
-+F: drivers/net/ethernet/pensando/
-+
-+PER-CPU MEMORY ALLOCATOR
-+M: Dennis Zhou <dennis@kernel.org>
-+M: Tejun Heo <tj@kernel.org>
-+M: Christoph Lameter <cl@linux.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu.git
-+F: arch/*/include/asm/percpu.h
-+F: include/linux/percpu*.h
-+F: lib/percpu*.c
-+F: mm/percpu*.c
-+
-+PER-TASK DELAY ACCOUNTING
-+M: Balbir Singh <bsingharora@gmail.com>
-+S: Maintained
-+F: include/linux/delayacct.h
-+F: kernel/delayacct.c
-+
-+PERFORMANCE EVENTS SUBSYSTEM
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Ingo Molnar <mingo@redhat.com>
-+M: Arnaldo Carvalho de Melo <acme@kernel.org>
-+R: Mark Rutland <mark.rutland@arm.com>
-+R: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-+R: Jiri Olsa <jolsa@redhat.com>
-+R: Namhyung Kim <namhyung@kernel.org>
-+L: linux-perf-users@vger.kernel.org
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+W: https://perf.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
-+F: arch/*/events/*
-+F: arch/*/events/*/*
-+F: arch/*/include/asm/perf_event.h
-+F: arch/*/kernel/*/*/perf_event*.c
-+F: arch/*/kernel/*/perf_event*.c
-+F: arch/*/kernel/perf_callchain.c
-+F: arch/*/kernel/perf_event*.c
-+F: include/linux/perf_event.h
-+F: include/uapi/linux/perf_event.h
-+F: kernel/events/*
-+F: tools/lib/perf/
-+F: tools/perf/
-+
-+PERFORMANCE EVENTS TOOLING ARM64
-+R: John Garry <john.garry@huawei.com>
-+R: Will Deacon <will@kernel.org>
-+R: Mathieu Poirier <mathieu.poirier@linaro.org>
-+R: Leo Yan <leo.yan@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: tools/build/feature/test-libopencsd.c
-+F: tools/perf/arch/arm*/
-+F: tools/perf/pmu-events/arch/arm64/
-+F: tools/perf/util/arm-spe*
-+F: tools/perf/util/cs-etm*
-+
-+PERSONALITY HANDLING
-+M: Christoph Hellwig <hch@infradead.org>
-+L: linux-abi-devel@lists.sourceforge.net
-+S: Maintained
-+F: include/linux/personality.h
-+F: include/uapi/linux/personality.h
-+
-+PHOENIX RC FLIGHT CONTROLLER ADAPTER
-+M: Marcus Folkesson <marcus.folkesson@gmail.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/input/devices/pxrc.rst
-+F: drivers/input/joystick/pxrc.c
-+
-+PHONET PROTOCOL
-+M: Remi Denis-Courmont <courmisch@gmail.com>
-+S: Supported
-+F: Documentation/networking/phonet.rst
-+F: include/linux/phonet.h
-+F: include/net/phonet/
-+F: include/uapi/linux/phonet.h
-+F: net/phonet/
-+
-+PHRAM MTD DRIVER
-+M: Joern Engel <joern@lazybastard.org>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+F: drivers/mtd/devices/phram.c
-+
-+PICOLCD HID DRIVER
-+M: Bruno Prémont <bonbons@linux-vserver.org>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-picolcd*
-+
-+PIDFD API
-+M: Christian Brauner <christian@brauner.io>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
-+F: samples/pidfd/
-+F: tools/testing/selftests/clone3/
-+F: tools/testing/selftests/pid_namespace/
-+F: tools/testing/selftests/pidfd/
-+K: (?i)pidfd
-+K: (?i)clone3
-+K: \b(clone_args|kernel_clone_args)\b
-+
-+PIN CONTROL SUBSYSTEM
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git
-+F: Documentation/devicetree/bindings/pinctrl/
-+F: Documentation/driver-api/pin-control.rst
-+F: drivers/pinctrl/
-+F: include/linux/pinctrl/
-+
-+PIN CONTROLLER - AMD
-+M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-+M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-+S: Maintained
-+F: drivers/pinctrl/pinctrl-amd.c
-+
-+PIN CONTROLLER - FREESCALE
-+M: Dong Aisheng <aisheng.dong@nxp.com>
-+M: Fabio Estevam <festevam@gmail.com>
-+M: Shawn Guo <shawnguo@kernel.org>
-+M: Stefan Agner <stefan@agner.ch>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pinctrl/fsl,*
-+F: drivers/pinctrl/freescale/
-+
-+PIN CONTROLLER - INTEL
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+M: Andy Shevchenko <andy@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git
-+F: drivers/pinctrl/intel/
-+
-+PIN CONTROLLER - KEEMBAY
-+M: Lakshmi Sowjanya D <lakshmi.sowjanya.d@intel.com>
-+S: Supported
-+F: drivers/pinctrl/pinctrl-keembay*
-+
-+PIN CONTROLLER - MEDIATEK
-+M: Sean Wang <sean.wang@kernel.org>
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
-+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
-+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
-+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
-+F: drivers/pinctrl/mediatek/
-+
-+PIN CONTROLLER - MICROCHIP AT91
-+M: Ludovic Desroches <ludovic.desroches@microchip.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-gpio@vger.kernel.org
-+S: Supported
-+F: drivers/gpio/gpio-sama5d2-piobu.c
-+F: drivers/pinctrl/pinctrl-at91*
-+
-+PIN CONTROLLER - QUALCOMM
-+M: Bjorn Andersson <bjorn.andersson@linaro.org>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/pinctrl/qcom,*.txt
-+F: drivers/pinctrl/qcom/
-+
-+PIN CONTROLLER - RENESAS
-+M: Geert Uytterhoeven <geert+renesas@glider.be>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git renesas-pinctrl
-+F: Documentation/devicetree/bindings/pinctrl/renesas,*
-+F: drivers/pinctrl/renesas/
-+
-+PIN CONTROLLER - SAMSUNG
-+M: Tomasz Figa <tomasz.figa@gmail.com>
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git
-+F: Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
-+F: drivers/pinctrl/samsung/
-+F: include/dt-bindings/pinctrl/samsung.h
-+
-+PIN CONTROLLER - SINGLE
-+M: Tony Lindgren <tony@atomide.com>
-+M: Haojian Zhuang <haojian.zhuang@linaro.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: drivers/pinctrl/pinctrl-single.c
-+
-+PIN CONTROLLER - ST SPEAR
-+M: Viresh Kumar <vireshk@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.st.com/spear
-+F: drivers/pinctrl/spear/
-+
-+PKTCDVD DRIVER
-+M: linux-block@vger.kernel.org
-+S: Orphan
-+F: drivers/block/pktcdvd.c
-+F: include/linux/pktcdvd.h
-+F: include/uapi/linux/pktcdvd.h
-+
-+PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER
-+M: Tomasz Duszynski <tduszyns@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml
-+F: drivers/iio/chemical/pms7003.c
-+
-+PLDMFW LIBRARY
-+M: Jacob Keller <jacob.e.keller@intel.com>
-+S: Maintained
-+F: Documentation/driver-api/pldmfw/
-+F: include/linux/pldmfw.h
-+F: lib/pldmfw/
-+
-+PLX DMA DRIVER
-+M: Logan Gunthorpe <logang@deltatee.com>
-+S: Maintained
-+F: drivers/dma/plx_dma.c
-+
-+PM6764TR DRIVER
-+M: Charles Hsu <hsu.yungteng@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/pm6764tr.rst
-+F: drivers/hwmon/pmbus/pm6764tr.c
-+
-+PM-GRAPH UTILITY
-+M: "Todd E Brandt" <todd.e.brandt@linux.intel.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+W: https://01.org/pm-graph
-+B: https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools
-+T: git git://github.com/intel/pm-graph
-+F: tools/power/pm-graph
-+
-+PMBUS HARDWARE MONITORING DRIVERS
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+W: http://hwmon.wiki.kernel.org/
-+W: http://www.roeck-us.net/linux/drivers/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
-+F: Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
-+F: Documentation/devicetree/bindings/hwmon/ltc2978.txt
-+F: Documentation/devicetree/bindings/hwmon/max31785.txt
-+F: Documentation/hwmon/adm1275.rst
-+F: Documentation/hwmon/ibm-cffps.rst
-+F: Documentation/hwmon/ir35221.rst
-+F: Documentation/hwmon/lm25066.rst
-+F: Documentation/hwmon/ltc2978.rst
-+F: Documentation/hwmon/ltc3815.rst
-+F: Documentation/hwmon/max16064.rst
-+F: Documentation/hwmon/max20751.rst
-+F: Documentation/hwmon/max31785.rst
-+F: Documentation/hwmon/max34440.rst
-+F: Documentation/hwmon/max8688.rst
-+F: Documentation/hwmon/pmbus-core.rst
-+F: Documentation/hwmon/pmbus.rst
-+F: Documentation/hwmon/tps40422.rst
-+F: Documentation/hwmon/ucd9000.rst
-+F: Documentation/hwmon/ucd9200.rst
-+F: Documentation/hwmon/zl6100.rst
-+F: drivers/hwmon/pmbus/
-+F: include/linux/pmbus.h
-+
-+PMC SIERRA MaxRAID DRIVER
-+L: linux-scsi@vger.kernel.org
-+S: Orphan
-+W: http://www.pmc-sierra.com/
-+F: drivers/scsi/pmcraid.*
-+
-+PMC SIERRA PM8001 DRIVER
-+M: Jack Wang <jinpu.wang@cloud.ionos.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/pm8001/
-+
-+PNI RM3100 IIO DRIVER
-+M: Song Qiang <songqiang1304521@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/magnetometer/pni,rm3100.yaml
-+F: drivers/iio/magnetometer/rm3100*
-+
-+PNP SUPPORT
-+M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Maintained
-+F: drivers/pnp/
-+F: include/linux/pnp.h
-+
-+POSIX CLOCKS and TIMERS
-+M: Thomas Gleixner <tglx@linutronix.de>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
-+F: fs/timerfd.c
-+F: include/linux/time_namespace.h
-+F: include/linux/timer*
-+F: kernel/time/*timer*
-+F: kernel/time/namespace.c
-+
-+POWER MANAGEMENT CORE
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-+F: drivers/base/power/
-+F: drivers/powercap/
-+F: include/linux/intel_rapl.h
-+F: include/linux/pm.h
-+F: include/linux/pm_*
-+F: include/linux/powercap.h
-+F: kernel/configs/nopm.config
-+
-+DYNAMIC THERMAL POWER MANAGEMENT (DTPM)
-+M: Daniel Lezcano <daniel.lezcano@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-+F: drivers/powercap/dtpm*
-+F: include/linux/dtpm.h
-+
-+POWER STATE COORDINATION INTERFACE (PSCI)
-+M: Mark Rutland <mark.rutland@arm.com>
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/firmware/psci/
-+F: include/linux/psci.h
-+F: include/uapi/linux/psci.h
-+
-+POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
-+M: Sebastian Reichel <sre@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git
-+F: Documentation/ABI/testing/sysfs-class-power
-+F: Documentation/devicetree/bindings/power/supply/
-+F: drivers/power/supply/
-+F: include/linux/power/
-+F: include/linux/power_supply.h
-+
-+POWERNV OPERATOR PANEL LCD DISPLAY DRIVER
-+M: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/char/powernv-op-panel.c
-+
-+PPP OVER ATM (RFC 2364)
-+M: Mitchell Blank Jr <mitch@sfgoth.com>
-+S: Maintained
-+F: include/uapi/linux/atmppp.h
-+F: net/atm/pppoatm.c
-+
-+PPP OVER ETHERNET
-+M: Michal Ostrowski <mostrows@earthlink.net>
-+S: Maintained
-+F: drivers/net/ppp/pppoe.c
-+F: drivers/net/ppp/pppox.c
-+
-+PPP OVER L2TP
-+M: James Chapman <jchapman@katalix.com>
-+S: Maintained
-+F: include/linux/if_pppol2tp.h
-+F: include/uapi/linux/if_pppol2tp.h
-+F: net/l2tp/l2tp_ppp.c
-+
-+PPP PROTOCOL DRIVERS AND COMPRESSORS
-+M: Paul Mackerras <paulus@samba.org>
-+L: linux-ppp@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ppp/ppp_*
-+
-+PPS SUPPORT
-+M: Rodolfo Giometti <giometti@enneenne.com>
-+L: linuxpps@ml.enneenne.com (subscribers-only)
-+S: Maintained
-+W: http://wiki.enneenne.com/index.php/LinuxPPS_support
-+F: Documentation/ABI/testing/sysfs-pps
-+F: Documentation/devicetree/bindings/pps/pps-gpio.txt
-+F: Documentation/driver-api/pps.rst
-+F: drivers/pps/
-+F: include/linux/pps*.h
-+F: include/uapi/linux/pps.h
-+
-+PPTP DRIVER
-+M: Dmitry Kozlov <xeb@mail.ru>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://sourceforge.net/projects/accel-pptp
-+F: drivers/net/ppp/pptp.c
-+
-+PRESSURE STALL INFORMATION (PSI)
-+M: Johannes Weiner <hannes@cmpxchg.org>
-+S: Maintained
-+F: include/linux/psi*
-+F: kernel/sched/psi.c
-+
-+PRINTK
-+M: Petr Mladek <pmladek@suse.com>
-+M: Sergey Senozhatsky <senozhatsky@chromium.org>
-+R: Steven Rostedt <rostedt@goodmis.org>
-+R: John Ogness <john.ogness@linutronix.de>
-+S: Maintained
-+F: include/linux/printk.h
-+F: kernel/printk/
-+
-+PRINTK INDEXING
-+R: Chris Down <chris@chrisdown.name>
-+S: Maintained
-+F: kernel/printk/index.c
-+
-+PROC FILESYSTEM
-+L: linux-kernel@vger.kernel.org
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: Documentation/filesystems/proc.rst
-+F: fs/proc/
-+F: include/linux/proc_fs.h
-+F: tools/testing/selftests/proc/
-+
-+PROC SYSCTL
-+M: Luis Chamberlain <mcgrof@kernel.org>
-+M: Kees Cook <keescook@chromium.org>
-+M: Iurii Zaikin <yzaikin@google.com>
-+L: linux-kernel@vger.kernel.org
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/proc/proc_sysctl.c
-+F: include/linux/sysctl.h
-+F: kernel/sysctl-test.c
-+F: kernel/sysctl.c
-+F: tools/testing/selftests/sysctl/
-+
-+PS3 NETWORK SUPPORT
-+M: Geoff Levand <geoff@infradead.org>
-+L: netdev@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/net/ethernet/toshiba/ps3_gelic_net.*
-+
-+PS3 PLATFORM SUPPORT
-+M: Geoff Levand <geoff@infradead.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: arch/powerpc/boot/ps3*
-+F: arch/powerpc/include/asm/lv1call.h
-+F: arch/powerpc/include/asm/ps3*.h
-+F: arch/powerpc/platforms/ps3/
-+F: drivers/*/ps3*
-+F: drivers/ps3/
-+F: drivers/rtc/rtc-ps3.c
-+F: drivers/usb/host/*ps3.c
-+F: sound/ppc/snd_ps3*
-+
-+PS3VRAM DRIVER
-+M: Jim Paris <jim@jtan.com>
-+M: Geoff Levand <geoff@infradead.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: drivers/block/ps3vram.c
-+
-+PSAMPLE PACKET SAMPLING SUPPORT
-+M: Yotam Gigi <yotam.gi@gmail.com>
-+S: Maintained
-+F: include/net/psample.h
-+F: include/uapi/linux/psample.h
-+F: net/psample
-+
-+PSTORE FILESYSTEM
-+M: Kees Cook <keescook@chromium.org>
-+M: Anton Vorontsov <anton@enomsg.org>
-+M: Colin Cross <ccross@android.com>
-+M: Tony Luck <tony.luck@intel.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
-+F: Documentation/admin-guide/ramoops.rst
-+F: Documentation/admin-guide/pstore-blk.rst
-+F: Documentation/devicetree/bindings/reserved-memory/ramoops.txt
-+F: drivers/acpi/apei/erst.c
-+F: drivers/firmware/efi/efi-pstore.c
-+F: fs/pstore/
-+F: include/linux/pstore*
-+K: \b(pstore|ramoops)
-+
-+PTP HARDWARE CLOCK SUPPORT
-+M: Richard Cochran <richardcochran@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://linuxptp.sourceforge.net/
-+F: Documentation/ABI/testing/sysfs-ptp
-+F: Documentation/driver-api/ptp.rst
-+F: drivers/net/phy/dp83640*
-+F: drivers/ptp/*
-+F: include/linux/ptp_cl*
-+
-+PTP VIRTUAL CLOCK SUPPORT
-+M: Yangbo Lu <yangbo.lu@nxp.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/ptp/ptp_vclock.c
-+F: net/ethtool/phc_vclocks.c
-+
-+PTRACE SUPPORT
-+M: Oleg Nesterov <oleg@redhat.com>
-+S: Maintained
-+F: arch/*/*/ptrace*.c
-+F: arch/*/include/asm/ptrace*.h
-+F: arch/*/ptrace*.c
-+F: include/asm-generic/syscall.h
-+F: include/linux/ptrace.h
-+F: include/linux/regset.h
-+F: include/linux/tracehook.h
-+F: include/uapi/linux/ptrace.h
-+F: include/uapi/linux/ptrace.h
-+F: kernel/ptrace.c
-+
-+PULSE8-CEC DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/pulse8-cec.rst
-+F: drivers/media/cec/usb/pulse8/
-+
-+PVRUSB2 VIDEO4LINUX DRIVER
-+M: Mike Isely <isely@pobox.com>
-+L: pvrusb2@isely.net (subscribers-only)
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://www.isely.net/pvrusb2/
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/driver-api/media/drivers/pvrusb2*
-+F: drivers/media/usb/pvrusb2/
-+
-+PWC WEBCAM DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/pwc/*
-+F: include/trace/events/pwc.h
-+
-+PWM FAN DRIVER
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
-+F: Documentation/hwmon/pwm-fan.rst
-+F: drivers/hwmon/pwm-fan.c
-+
-+PWM IR Transmitter
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/pwm-ir-tx.c
-+
-+PWM SUBSYSTEM
-+M: Thierry Reding <thierry.reding@gmail.com>
-+R: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-+M: Lee Jones <lee.jones@linaro.org>
-+L: linux-pwm@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.ozlabs.org/project/linux-pwm/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git
-+F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
-+F: Documentation/devicetree/bindings/pwm/
-+F: Documentation/driver-api/pwm.rst
-+F: drivers/gpio/gpio-mvebu.c
-+F: drivers/pwm/
-+F: drivers/video/backlight/pwm_bl.c
-+F: include/linux/pwm.h
-+F: include/linux/pwm_backlight.h
-+K: pwm_(config|apply_state|ops)
-+
-+PXA GPIO DRIVER
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-pxa.c
-+
-+PXA MMCI DRIVER
-+S: Orphan
-+
-+PXA RTC DRIVER
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-rtc@vger.kernel.org
-+S: Maintained
-+
-+PXA2xx/PXA3xx SUPPORT
-+M: Daniel Mack <daniel@zonque.org>
-+M: Haojian Zhuang <haojian.zhuang@gmail.com>
-+M: Robert Jarzmik <robert.jarzmik@free.fr>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://github.com/hzhuang1/linux.git
-+T: git git://github.com/rjarzmik/linux.git
-+F: arch/arm/boot/dts/pxa*
-+F: arch/arm/mach-pxa/
-+F: drivers/dma/pxa*
-+F: drivers/pcmcia/pxa2xx*
-+F: drivers/pinctrl/pxa/
-+F: drivers/spi/spi-pxa2xx*
-+F: drivers/usb/gadget/udc/pxa2*
-+F: include/sound/pxa2xx-lib.h
-+F: sound/arm/pxa*
-+F: sound/soc/pxa/
-+
-+QAT DRIVER
-+M: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
-+L: qat-linux@intel.com
-+S: Supported
-+F: drivers/crypto/qat/
-+
-+QCOM AUDIO (ASoC) DRIVERS
-+M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-+M: Banajit Goswami <bgoswami@codeaurora.org>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+F: sound/soc/codecs/lpass-va-macro.c
-+F: sound/soc/codecs/lpass-wsa-macro.*
-+F: sound/soc/codecs/msm8916-wcd-analog.c
-+F: sound/soc/codecs/msm8916-wcd-digital.c
-+F: sound/soc/codecs/wcd9335.*
-+F: sound/soc/codecs/wcd934x.c
-+F: sound/soc/codecs/wcd-clsh-v2.*
-+F: sound/soc/codecs/wsa881x.c
-+F: sound/soc/qcom/
-+
-+QCOM IPA DRIVER
-+M: Alex Elder <elder@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ipa/
-+
-+QEMU MACHINE EMULATOR AND VIRTUALIZER SUPPORT
-+M: Gabriel Somlo <somlo@cmu.edu>
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+L: qemu-devel@nongnu.org
-+S: Maintained
-+F: drivers/firmware/qemu_fw_cfg.c
-+F: include/uapi/linux/qemu_fw_cfg.h
-+
-+QIB DRIVER
-+M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
-+M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/hw/qib/
-+
-+QLOGIC QL41xxx FCOE DRIVER
-+M: Saurav Kashyap <skashyap@marvell.com>
-+M: Javed Hasan <jhasan@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/qedf/
-+
-+QLOGIC QL41xxx ISCSI DRIVER
-+M: Nilesh Javali <njavali@marvell.com>
-+M: Manish Rangankar <mrangankar@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/qedi/
-+
-+QLOGIC QL4xxx ETHERNET DRIVER
-+M: Ariel Elior <aelior@marvell.com>
-+M: GR-everest-linux-l2@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/qlogic/qed/
-+F: drivers/net/ethernet/qlogic/qede/
-+F: include/linux/qed/
-+
-+QLOGIC QL4xxx RDMA DRIVER
-+M: Michal Kalderon <mkalderon@marvell.com>
-+M: Ariel Elior <aelior@marvell.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/hw/qedr/
-+F: include/uapi/rdma/qedr-abi.h
-+
-+QLOGIC QLA1280 SCSI DRIVER
-+M: Michael Reed <mdr@sgi.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/qla1280.[ch]
-+
-+QLOGIC QLA2XXX FC-SCSI DRIVER
-+M: Nilesh Javali <njavali@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/qla2xxx/
-+
-+QLOGIC QLA3XXX NETWORK DRIVER
-+M: GR-Linux-NIC-Dev@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/qlogic/qla3xxx.*
-+
-+QLOGIC QLA4XXX iSCSI DRIVER
-+M: Nilesh Javali <njavali@marvell.com>
-+M: Manish Rangankar <mrangankar@marvell.com>
-+M: GR-QLogic-Storage-Upstream@marvell.com
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/qla4xxx/
-+
-+QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-+M: Shahed Shaikh <shshaikh@marvell.com>
-+M: Manish Chopra <manishc@marvell.com>
-+M: GR-Linux-NIC-Dev@marvell.com
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/qlogic/qlcnic/
-+
-+QLOGIC QLGE 10Gb ETHERNET DRIVER
-+M: Manish Chopra <manishc@marvell.com>
-+M: GR-Linux-NIC-Dev@marvell.com
-+M: Coiby Xu <coiby.xu@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: Documentation/networking/device_drivers/qlogic/qlge.rst
-+F: drivers/staging/qlge/
-+
-+QM1D1B0004 MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/tuners/qm1d1b0004*
-+
-+QM1D1C0042 MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/tuners/qm1d1c0042*
-+
-+QNX4 FILESYSTEM
-+M: Anders Larsen <al@alarsen.net>
-+S: Maintained
-+W: http://www.alarsen.net/linux/qnx4fs/
-+F: fs/qnx4/
-+F: include/uapi/linux/qnx4_fs.h
-+F: include/uapi/linux/qnxtypes.h
-+
-+QORIQ DPAA2 FSL-MC BUS DRIVER
-+M: Stuart Yoder <stuyoder@gmail.com>
-+M: Laurentiu Tudor <laurentiu.tudor@nxp.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/stable/sysfs-bus-fsl-mc
-+F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
-+F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
-+F: drivers/bus/fsl-mc/
-+F: include/uapi/linux/fsl_mc.h
-+
-+QT1010 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/qt1010*
-+
-+QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: ath10k@lists.infradead.org
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
-+F: drivers/net/wireless/ath/ath10k/
-+
-+QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: ath11k@lists.infradead.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
-+F: drivers/net/wireless/ath/ath11k/
-+
-+QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
-+M: ath9k-devel@qca.qualcomm.com
-+L: linux-wireless@vger.kernel.org
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
-+F: drivers/net/wireless/ath/ath9k/
-+
-+QUALCOMM CAMERA SUBSYSTEM DRIVER
-+M: Robert Foss <robert.foss@linaro.org>
-+M: Todor Tomov <todor.too@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/media/qcom_camss.rst
-+F: Documentation/devicetree/bindings/media/*camss*
-+F: drivers/media/platform/qcom/camss/
-+
-+QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
-+M: Niklas Cassel <nks@flawful.org>
-+L: linux-pm@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
-+F: drivers/soc/qcom/cpr.c
-+
-+QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
-+M: Ilia Lin <ilia.lin@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
-+F: drivers/cpufreq/qcom-cpufreq-nvmem.c
-+
-+QUALCOMM CRYPTO DRIVERS
-+M: Thara Gopinath <thara.gopinath@linaro.org>
-+L: linux-crypto@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/qce/
-+
-+QUALCOMM EMAC GIGABIT ETHERNET DRIVER
-+M: Timur Tabi <timur@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/qualcomm/emac/
-+
-+QUALCOMM ETHQOS ETHERNET DRIVER
-+M: Vinod Koul <vkoul@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/qcom,ethqos.txt
-+F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
-+
-+QUALCOMM GENERIC INTERFACE I2C DRIVER
-+M: Akash Asthana <akashast@codeaurora.org>
-+M: Mukesh Savaliya <msavaliy@codeaurora.org>
-+L: linux-i2c@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Supported
-+F: drivers/i2c/busses/i2c-qcom-geni.c
-+
-+QUALCOMM HEXAGON ARCHITECTURE
-+M: Brian Cain <bcain@codeaurora.org>
-+L: linux-hexagon@vger.kernel.org
-+S: Supported
-+F: arch/hexagon/
-+
-+QUALCOMM HIDMA DRIVER
-+M: Sinan Kaya <okaya@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+L: linux-arm-msm@vger.kernel.org
-+L: dmaengine@vger.kernel.org
-+S: Supported
-+F: drivers/dma/qcom/hidma*
-+
-+QUALCOMM I2C CCI DRIVER
-+M: Loic Poulain <loic.poulain@linaro.org>
-+M: Robert Foss <robert.foss@linaro.org>
-+L: linux-i2c@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
-+F: drivers/i2c/busses/i2c-qcom-cci.c
-+
-+QUALCOMM IOMMU
-+M: Rob Clark <robdclark@gmail.com>
-+L: iommu@lists.linux-foundation.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: drivers/iommu/arm/arm-smmu/qcom_iommu.c
-+
-+QUALCOMM IPC ROUTER (QRTR) DRIVER
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: include/trace/events/qrtr.h
-+F: include/uapi/linux/qrtr.h
-+F: net/qrtr/
-+
-+QUALCOMM IPCC MAILBOX DRIVER
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-arm-msm@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
-+F: drivers/mailbox/qcom-ipcc.c
-+F: include/dt-bindings/mailbox/qcom-ipcc.h
-+
-+QUALCOMM IPQ4019 USB PHY DRIVER
-+M: Robert Marko <robert.marko@sartura.hr>
-+M: Luka Perkov <luka.perkov@sartura.hr>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/qcom-usb-ipq4019-phy.yaml
-+F: drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
-+
-+QUALCOMM IPQ4019 VQMMC REGULATOR DRIVER
-+M: Robert Marko <robert.marko@sartura.hr>
-+M: Luka Perkov <luka.perkov@sartura.hr>
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
-+F: drivers/regulator/vqmmc-ipq4019-regulator.c
-+
-+QUALCOMM RMNET DRIVER
-+M: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
-+M: Sean Tranchetti <stranche@codeaurora.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst
-+F: drivers/net/ethernet/qualcomm/rmnet/
-+F: include/linux/if_rmnet.h
-+
-+QUALCOMM TSENS THERMAL DRIVER
-+M: Amit Kucheria <amitk@kernel.org>
-+M: Thara Gopinath <thara.gopinath@linaro.org>
-+L: linux-pm@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
-+F: drivers/thermal/qcom/
-+
-+QUALCOMM VENUS VIDEO ACCELERATOR DRIVER
-+M: Stanimir Varbanov <stanimir.varbanov@linaro.org>
-+L: linux-media@vger.kernel.org
-+L: linux-arm-msm@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/*venus*
-+F: drivers/media/platform/qcom/venus/
-+
-+QUALCOMM WCN36XX WIRELESS DRIVER
-+M: Kalle Valo <kvalo@codeaurora.org>
-+L: wcn36xx@lists.infradead.org
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx
-+T: git git://github.com/KrasnikovEugene/wcn36xx.git
-+F: drivers/net/wireless/ath/wcn36xx/
-+
-+QUANTENNA QTNFMAC WIRELESS DRIVER
-+M: Igor Mitsyanko <imitsyanko@quantenna.com>
-+R: Sergey Matyukevich <geomatsi@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/quantenna
-+
-+RADEON and AMDGPU DRM DRIVERS
-+M: Alex Deucher <alexander.deucher@amd.com>
-+M: Christian König <christian.koenig@amd.com>
-+M: Pan, Xinhui <Xinhui.Pan@amd.com>
-+L: amd-gfx@lists.freedesktop.org
-+S: Supported
-+T: git https://gitlab.freedesktop.org/agd5f/linux.git
-+B: https://gitlab.freedesktop.org/drm/amd/-/issues
-+C: irc://irc.oftc.net/radeon
-+F: drivers/gpu/drm/amd/
-+F: drivers/gpu/drm/radeon/
-+F: include/uapi/drm/amdgpu_drm.h
-+F: include/uapi/drm/radeon_drm.h
-+
-+RADEON FRAMEBUFFER DISPLAY DRIVER
-+M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/aty/radeon*
-+F: include/uapi/linux/radeonfb.h
-+
-+RADIOSHARK RADIO DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-shark.c
-+
-+RADIOSHARK2 RADIO DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-shark2.c
-+F: drivers/media/radio/radio-tea5777.c
-+
-+RADOS BLOCK DEVICE (RBD)
-+M: Ilya Dryomov <idryomov@gmail.com>
-+R: Dongsheng Yang <dongsheng.yang@easystack.cn>
-+L: ceph-devel@vger.kernel.org
-+S: Supported
-+W: http://ceph.com/
-+T: git git://github.com/ceph/ceph-client.git
-+F: Documentation/ABI/testing/sysfs-bus-rbd
-+F: drivers/block/rbd.c
-+F: drivers/block/rbd_types.h
-+
-+RAGE128 FRAMEBUFFER DISPLAY DRIVER
-+M: Paul Mackerras <paulus@samba.org>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/aty/aty128fb.c
-+
-+RAINSHADOW-CEC DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/cec/usb/rainshadow/
-+
-+RALINK MIPS ARCHITECTURE
-+M: John Crispin <john@phrozen.org>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/ralink
-+
-+RALINK RT2X00 WIRELESS LAN DRIVER
-+M: Stanislaw Gruszka <stf_xl@wp.pl>
-+M: Helmut Schaa <helmut.schaa@googlemail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/ralink/rt2x00/
-+
-+RAMDISK RAM BLOCK DEVICE DRIVER
-+M: Jens Axboe <axboe@kernel.dk>
-+S: Maintained
-+F: Documentation/admin-guide/blockdev/ramdisk.rst
-+F: drivers/block/brd.c
-+
-+RANCHU VIRTUAL BOARD FOR MIPS
-+M: Miodrag Dinic <miodrag.dinic@mips.com>
-+L: linux-mips@vger.kernel.org
-+S: Supported
-+F: arch/mips/configs/generic/board-ranchu.config
-+F: arch/mips/generic/board-ranchu.c
-+
-+RANDOM NUMBER DRIVER
-+M: "Theodore Ts'o" <tytso@mit.edu>
-+S: Maintained
-+F: drivers/char/random.c
-+
-+RAPIDIO SUBSYSTEM
-+M: Matt Porter <mporter@kernel.crashing.org>
-+M: Alexandre Bounine <alex.bou9@gmail.com>
-+S: Maintained
-+F: drivers/rapidio/
-+
-+RAS INFRASTRUCTURE
-+M: Tony Luck <tony.luck@intel.com>
-+M: Borislav Petkov <bp@alien8.de>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/ras.rst
-+F: drivers/ras/
-+F: include/linux/ras.h
-+F: include/ras/ras_event.h
-+
-+RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+F: drivers/net/wireless/ray*
-+
-+RC-CORE / LIRC FRAMEWORK
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/driver-api/media/rc-core.rst
-+F: Documentation/userspace-api/media/rc/
-+F: drivers/media/rc/
-+F: include/media/rc-map.h
-+F: include/media/rc-core.h
-+F: include/uapi/linux/lirc.h
-+
-+RCMM REMOTE CONTROLS DECODER
-+M: Patrick Lerda <patrick9876@free.fr>
-+S: Maintained
-+F: drivers/media/rc/ir-rcmm-decoder.c
-+
-+RCUTORTURE TEST FRAMEWORK
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+M: Josh Triplett <josh@joshtriplett.org>
-+R: Steven Rostedt <rostedt@goodmis.org>
-+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+R: Lai Jiangshan <jiangshanlai@gmail.com>
-+L: rcu@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
-+F: tools/testing/selftests/rcutorture
-+
-+RDACM20 Camera Sensor
-+M: Jacopo Mondi <jacopo+renesas@jmondi.org>
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-+M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
-+F: drivers/media/i2c/max9271.c
-+F: drivers/media/i2c/max9271.h
-+F: drivers/media/i2c/rdacm20.c
-+
-+RDACM21 Camera Sensor
-+M: Jacopo Mondi <jacopo+renesas@jmondi.org>
-+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
-+M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-+M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
-+F: drivers/media/i2c/max9271.c
-+F: drivers/media/i2c/max9271.h
-+F: drivers/media/i2c/rdacm21.c
-+
-+RDC R-321X SoC
-+M: Florian Fainelli <florian@openwrt.org>
-+S: Maintained
-+
-+RDC R6040 FAST ETHERNET DRIVER
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/rdc/r6040.c
-+
-+RDMAVT - RDMA verbs software
-+M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
-+M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/sw/rdmavt
-+
-+RDS - RELIABLE DATAGRAM SOCKETS
-+M: Santosh Shilimkar <santosh.shilimkar@oracle.com>
-+L: netdev@vger.kernel.org
-+L: linux-rdma@vger.kernel.org
-+L: rds-devel@oss.oracle.com (moderated for non-subscribers)
-+S: Supported
-+W: https://oss.oracle.com/projects/rds/
-+F: Documentation/networking/rds.rst
-+F: net/rds/
-+
-+RDT - RESOURCE ALLOCATION
-+M: Fenghua Yu <fenghua.yu@intel.com>
-+M: Reinette Chatre <reinette.chatre@intel.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/x86/resctrl*
-+F: arch/x86/include/asm/resctrl.h
-+F: arch/x86/kernel/cpu/resctrl/
-+F: tools/testing/selftests/resctrl/
-+
-+READ-COPY UPDATE (RCU)
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+M: Josh Triplett <josh@joshtriplett.org>
-+R: Steven Rostedt <rostedt@goodmis.org>
-+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+R: Lai Jiangshan <jiangshanlai@gmail.com>
-+R: Joel Fernandes <joel@joelfernandes.org>
-+L: rcu@vger.kernel.org
-+S: Supported
-+W: http://www.rdrop.com/users/paulmck/RCU/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
-+F: Documentation/RCU/
-+F: include/linux/rcu*
-+F: kernel/rcu/
-+X: Documentation/RCU/torture.rst
-+X: include/linux/srcu*.h
-+X: kernel/rcu/srcu*.c
-+
-+REAL TIME CLOCK (RTC) SUBSYSTEM
-+M: Alessandro Zummo <a.zummo@towertech.it>
-+M: Alexandre Belloni <alexandre.belloni@bootlin.com>
-+L: linux-rtc@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
-+F: Documentation/admin-guide/rtc.rst
-+F: Documentation/devicetree/bindings/rtc/
-+F: drivers/rtc/
-+F: include/linux/platform_data/rtc-*
-+F: include/linux/rtc.h
-+F: include/linux/rtc/
-+F: include/uapi/linux/rtc.h
-+F: tools/testing/selftests/rtc/
-+
-+REALTEK AUDIO CODECS
-+M: Oder Chiou <oder_chiou@realtek.com>
-+S: Maintained
-+F: include/sound/rt*.h
-+F: sound/soc/codecs/rt*
-+
-+REALTEK RTL83xx SMI DSA ROUTER CHIPS
-+M: Linus Walleij <linus.walleij@linaro.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
-+F: drivers/net/dsa/realtek-smi*
-+F: drivers/net/dsa/rtl83*
-+
-+REALTEK WIRELESS DRIVER (rtlwifi family)
-+M: Ping-Ke Shih <pkshih@realtek.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-+F: drivers/net/wireless/realtek/rtlwifi/
-+
-+REALTEK WIRELESS DRIVER (rtw88)
-+M: Yan-Hsuan Chuang <tony0620emma@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/realtek/rtw88/
-+
-+REDPINE WIRELESS DRIVER
-+M: Amitkumar Karwar <amitkarwar@gmail.com>
-+M: Siva Rebbagondla <siva8118@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/rsi/
-+
-+REGISTER MAP ABSTRACTION
-+M: Mark Brown <broonie@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
-+F: Documentation/devicetree/bindings/regmap/
-+F: drivers/base/regmap/
-+F: include/linux/regmap.h
-+
-+REISERFS FILE SYSTEM
-+L: reiserfs-devel@vger.kernel.org
-+S: Supported
-+F: fs/reiserfs/
-+
-+REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
-+M: Ohad Ben-Cohen <ohad@wizery.com>
-+M: Bjorn Andersson <bjorn.andersson@linaro.org>
-+M: Mathieu Poirier <mathieu.poirier@linaro.org>
-+L: linux-remoteproc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rproc-next
-+F: Documentation/ABI/testing/sysfs-class-remoteproc
-+F: Documentation/devicetree/bindings/remoteproc/
-+F: Documentation/staging/remoteproc.rst
-+F: drivers/remoteproc/
-+F: include/linux/remoteproc.h
-+F: include/linux/remoteproc/
-+
-+REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM
-+M: Ohad Ben-Cohen <ohad@wizery.com>
-+M: Bjorn Andersson <bjorn.andersson@linaro.org>
-+M: Mathieu Poirier <mathieu.poirier@linaro.org>
-+L: linux-remoteproc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rpmsg-next
-+F: Documentation/ABI/testing/sysfs-bus-rpmsg
-+F: Documentation/staging/rpmsg.rst
-+F: drivers/rpmsg/
-+F: include/linux/rpmsg.h
-+F: include/linux/rpmsg/
-+F: include/uapi/linux/rpmsg.h
-+F: samples/rpmsg/
-+
-+REMOTE PROCESSOR MESSAGING (RPMSG) WWAN CONTROL DRIVER
-+M: Stephan Gerhold <stephan@gerhold.net>
-+L: netdev@vger.kernel.org
-+L: linux-remoteproc@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wwan/rpmsg_wwan_ctrl.c
-+
-+RENESAS CLOCK DRIVERS
-+M: Geert Uytterhoeven <geert+renesas@glider.be>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git renesas-clk
-+F: Documentation/devicetree/bindings/clock/renesas,*
-+F: drivers/clk/renesas/
-+
-+RENESAS EMEV2 I2C DRIVER
-+M: Wolfram Sang <wsa+renesas@sang-engineering.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml
-+F: drivers/i2c/busses/i2c-emev2.c
-+
-+RENESAS ETHERNET DRIVERS
-+R: Sergey Shtylyov <s.shtylyov@omp.ru>
-+L: netdev@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+F: Documentation/devicetree/bindings/net/renesas,*.yaml
-+F: drivers/net/ethernet/renesas/
-+F: include/linux/sh_eth.h
-+
-+RENESAS R-CAR GYROADC DRIVER
-+M: Marek Vasut <marek.vasut@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml
-+F: drivers/iio/adc/rcar-gyroadc.c
-+
-+RENESAS R-CAR I2C DRIVERS
-+M: Wolfram Sang <wsa+renesas@sang-engineering.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml
-+F: Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml
-+F: drivers/i2c/busses/i2c-rcar.c
-+F: drivers/i2c/busses/i2c-sh_mobile.c
-+
-+RENESAS R-CAR THERMAL DRIVERS
-+M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
-+F: Documentation/devicetree/bindings/thermal/rcar-thermal.yaml
-+F: drivers/thermal/rcar_gen3_thermal.c
-+F: drivers/thermal/rcar_thermal.c
-+
-+RENESAS RIIC DRIVER
-+M: Chris Brandt <chris.brandt@renesas.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/i2c/renesas,riic.yaml
-+F: drivers/i2c/busses/i2c-riic.c
-+
-+RENESAS USB PHY DRIVER
-+M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-+L: linux-renesas-soc@vger.kernel.org
-+S: Maintained
-+F: drivers/phy/renesas/phy-rcar-gen3-usb*.c
-+
-+RENESAS RZ/G2L A/D DRIVER
-+M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
-+L: linux-iio@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
-+F: drivers/iio/adc/rzg2l_adc.c
-+
-+RESET CONTROLLER FRAMEWORK
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+S: Maintained
-+T: git git://git.pengutronix.de/git/pza/linux
-+F: Documentation/devicetree/bindings/reset/
-+F: Documentation/driver-api/reset.rst
-+F: drivers/reset/
-+F: include/dt-bindings/reset/
-+F: include/linux/reset-controller.h
-+F: include/linux/reset.h
-+F: include/linux/reset/
-+K: \b(?:devm_|of_)?reset_control(?:ler_[a-z]+|_[a-z_]+)?\b
-+
-+RESTARTABLE SEQUENCES SUPPORT
-+M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+M: Boqun Feng <boqun.feng@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: include/trace/events/rseq.h
-+F: include/uapi/linux/rseq.h
-+F: kernel/rseq.c
-+F: tools/testing/selftests/rseq/
-+
-+RFKILL
-+M: Johannes Berg <johannes@sipsolutions.net>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
-+F: Documentation/ABI/stable/sysfs-class-rfkill
-+F: Documentation/driver-api/rfkill.rst
-+F: include/linux/rfkill.h
-+F: include/uapi/linux/rfkill.h
-+F: net/rfkill/
-+
-+RHASHTABLE
-+M: Thomas Graf <tgraf@suug.ch>
-+M: Herbert Xu <herbert@gondor.apana.org.au>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/linux/rhashtable-types.h
-+F: include/linux/rhashtable.h
-+F: lib/rhashtable.c
-+F: lib/test_rhashtable.c
-+
-+RICOH R5C592 MEMORYSTICK DRIVER
-+M: Maxim Levitsky <maximlevitsky@gmail.com>
-+S: Maintained
-+F: drivers/memstick/host/r592.*
-+
-+RICOH SMARTMEDIA/XD DRIVER
-+M: Maxim Levitsky <maximlevitsky@gmail.com>
-+S: Maintained
-+F: drivers/mtd/nand/raw/r852.c
-+F: drivers/mtd/nand/raw/r852.h
-+
-+RISC-V ARCHITECTURE
-+M: Paul Walmsley <paul.walmsley@sifive.com>
-+M: Palmer Dabbelt <palmer@dabbelt.com>
-+M: Albert Ou <aou@eecs.berkeley.edu>
-+L: linux-riscv@lists.infradead.org
-+S: Supported
-+P: Documentation/riscv/patch-acceptance.rst
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
-+F: arch/riscv/
-+N: riscv
-+K: riscv
-+
-+RISC-V/MICROCHIP POLARFIRE SOC SUPPORT
-+M: Lewis Hanly <lewis.hanly@microchip.com>
-+L: linux-riscv@lists.infradead.org
-+S: Supported
-+F: drivers/mailbox/mailbox-mpfs.c
-+F: drivers/soc/microchip/
-+F: include/soc/microchip/mpfs.h
-+
-+RNBD BLOCK DRIVERS
-+M: Md. Haris Iqbal <haris.iqbal@ionos.com>
-+M: Jack Wang <jinpu.wang@ionos.com>
-+L: linux-block@vger.kernel.org
-+S: Maintained
-+F: drivers/block/rnbd/
-+
-+ROCCAT DRIVERS
-+M: Stefan Achatz <erazor_de@users.sourceforge.net>
-+S: Maintained
-+W: http://sourceforge.net/projects/roccat/
-+F: Documentation/ABI/*/sysfs-driver-hid-roccat*
-+F: drivers/hid/hid-roccat*
-+F: include/linux/hid-roccat*
-+
-+ROCKCHIP ISP V1 DRIVER
-+M: Helen Koike <helen.koike@collabora.com>
-+M: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
-+L: linux-media@vger.kernel.org
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+F: Documentation/admin-guide/media/rkisp1.rst
-+F: Documentation/devicetree/bindings/media/rockchip-isp1.yaml
-+F: Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst
-+F: drivers/media/platform/rockchip/rkisp1
-+F: include/uapi/linux/rkisp1-config.h
-+
-+ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER
-+M: Jacob Chen <jacob-chen@iotwrt.com>
-+M: Ezequiel Garcia <ezequiel@collabora.com>
-+L: linux-media@vger.kernel.org
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/rockchip-rga.yaml
-+F: drivers/media/platform/rockchip/rga/
-+
-+ROCKCHIP VIDEO DECODER DRIVER
-+M: Ezequiel Garcia <ezequiel@collabora.com>
-+L: linux-media@vger.kernel.org
-+L: linux-rockchip@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/rockchip,vdec.yaml
-+F: drivers/staging/media/rkvdec/
-+
-+ROCKER DRIVER
-+M: Jiri Pirko <jiri@resnulli.us>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/rocker/
-+
-+ROCKETPORT EXPRESS/INFINITY DRIVER
-+M: Kevin Cernekee <cernekee@gmail.com>
-+L: linux-serial@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/tty/serial/rp2.*
-+
-+ROHM BD99954 CHARGER IC
-+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
-+L: linux-power@fi.rohmeurope.com
-+S: Supported
-+F: drivers/power/supply/bd99954-charger.c
-+F: drivers/power/supply/bd99954-charger.h
-+
-+ROHM BH1750 AMBIENT LIGHT SENSOR DRIVER
-+M: Tomasz Duszynski <tduszyns@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
-+F: drivers/iio/light/bh1750.c
-+
-+ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
-+M: Marek Vasut <marek.vasut+renesas@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+L: linux-renesas-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/mfd/bd9571mwv.txt
-+F: drivers/gpio/gpio-bd9571mwv.c
-+F: drivers/mfd/bd9571mwv.c
-+F: drivers/regulator/bd9571mwv-regulator.c
-+F: include/linux/mfd/bd9571mwv.h
-+
-+ROHM POWER MANAGEMENT IC DEVICE DRIVERS
-+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
-+L: linux-power@fi.rohmeurope.com
-+S: Supported
-+F: Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
-+F: Documentation/devicetree/bindings/regulator/rohm,bd70528-regulator.txt
-+F: drivers/clk/clk-bd718x7.c
-+F: drivers/gpio/gpio-bd70528.c
-+F: drivers/gpio/gpio-bd71815.c
-+F: drivers/gpio/gpio-bd71828.c
-+F: drivers/mfd/rohm-bd70528.c
-+F: drivers/mfd/rohm-bd71828.c
-+F: drivers/mfd/rohm-bd718x7.c
-+F: drivers/mfd/rohm-bd9576.c
-+F: drivers/power/supply/bd70528-charger.c
-+F: drivers/regulator/bd70528-regulator.c
-+F: drivers/regulator/bd71815-regulator.c
-+F: drivers/regulator/bd71828-regulator.c
-+F: drivers/regulator/bd718x7-regulator.c
-+F: drivers/regulator/bd9576-regulator.c
-+F: drivers/regulator/rohm-regulator.c
-+F: drivers/rtc/rtc-bd70528.c
-+F: drivers/watchdog/bd70528_wdt.c
-+F: drivers/watchdog/bd9576_wdt.c
-+F: include/linux/mfd/rohm-bd70528.h
-+F: include/linux/mfd/rohm-bd71815.h
-+F: include/linux/mfd/rohm-bd71828.h
-+F: include/linux/mfd/rohm-bd718x7.h
-+F: include/linux/mfd/rohm-bd957x.h
-+F: include/linux/mfd/rohm-generic.h
-+F: include/linux/mfd/rohm-shared.h
-+
-+ROSE NETWORK LAYER
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-ax25.org/
-+F: include/net/rose.h
-+F: include/uapi/linux/rose.h
-+F: net/rose/
-+
-+ROTATION DRIVER FOR ALLWINNER A83T
-+M: Jernej Skrabec <jernej.skrabec@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
-+F: drivers/media/platform/sunxi/sun8i-rotate/
-+
-+RTL2830 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/rtl2830*
-+
-+RTL2832 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/rtl2832*
-+
-+RTL2832_SDR MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/rtl2832_sdr*
-+
-+RTL8180 WIRELESS DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-+F: drivers/net/wireless/realtek/rtl818x/rtl8180/
-+
-+RTL8187 WIRELESS DRIVER
-+M: Herton Ronaldo Krzesinski <herton@canonical.com>
-+M: Hin-Tak Leung <htl10@users.sourceforge.net>
-+M: Larry Finger <Larry.Finger@lwfinger.net>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+W: https://wireless.wiki.kernel.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-+F: drivers/net/wireless/realtek/rtl818x/rtl8187/
-+
-+RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
-+M: Jes Sorensen <Jes.Sorensen@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel
-+F: drivers/net/wireless/realtek/rtl8xxxu/
-+
-+RTRS TRANSPORT DRIVERS
-+M: Md. Haris Iqbal <haris.iqbal@ionos.com>
-+M: Jack Wang <jinpu.wang@ionos.com>
-+L: linux-rdma@vger.kernel.org
-+S: Maintained
-+F: drivers/infiniband/ulp/rtrs/
-+
-+RXRPC SOCKETS (AF_RXRPC)
-+M: David Howells <dhowells@redhat.com>
-+M: Marc Dionne <marc.dionne@auristor.com>
-+L: linux-afs@lists.infradead.org
-+S: Supported
-+W: https://www.infradead.org/~dhowells/kafs/
-+F: Documentation/networking/rxrpc.rst
-+F: include/keys/rxrpc-type.h
-+F: include/net/af_rxrpc.h
-+F: include/trace/events/rxrpc.h
-+F: include/uapi/linux/rxrpc.h
-+F: net/rxrpc/
-+
-+S3 SAVAGE FRAMEBUFFER DRIVER
-+M: Antonino Daplas <adaplas@gmail.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/savage/
-+
-+S390
-+M: Heiko Carstens <hca@linux.ibm.com>
-+M: Vasily Gorbik <gor@linux.ibm.com>
-+M: Christian Borntraeger <borntraeger@de.ibm.com>
-+R: Alexander Gordeev <agordeev@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
-+F: Documentation/driver-api/s390-drivers.rst
-+F: Documentation/s390/
-+F: arch/s390/
-+F: drivers/s390/
-+
-+S390 COMMON I/O LAYER
-+M: Vineeth Vijayan <vneethv@linux.ibm.com>
-+M: Peter Oberparleiter <oberpar@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/s390/cio/
-+
-+S390 DASD DRIVER
-+M: Stefan Haberland <sth@linux.ibm.com>
-+M: Jan Hoeppner <hoeppner@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: block/partitions/ibm.c
-+F: drivers/s390/block/dasd*
-+F: include/linux/dasd_mod.h
-+
-+S390 IOMMU (PCI)
-+M: Matthew Rosato <mjrosato@linux.ibm.com>
-+M: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/iommu/s390-iommu.c
-+
-+S390 IUCV NETWORK LAYER
-+M: Julian Wiedmann <jwi@linux.ibm.com>
-+M: Karsten Graul <kgraul@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/s390/net/*iucv*
-+F: include/net/iucv/
-+F: net/iucv/
-+
-+S390 NETWORK DRIVERS
-+M: Julian Wiedmann <jwi@linux.ibm.com>
-+M: Karsten Graul <kgraul@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/s390/net/
-+
-+S390 PCI SUBSYSTEM
-+M: Niklas Schnelle <schnelle@linux.ibm.com>
-+M: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: arch/s390/pci/
-+F: drivers/pci/hotplug/s390_pci_hpc.c
-+F: Documentation/s390/pci.rst
-+
-+S390 VFIO AP DRIVER
-+M: Tony Krowiak <akrowiak@linux.ibm.com>
-+M: Halil Pasic <pasic@linux.ibm.com>
-+M: Jason Herne <jjherne@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: Documentation/s390/vfio-ap.rst
-+F: drivers/s390/crypto/vfio_ap_drv.c
-+F: drivers/s390/crypto/vfio_ap_ops.c
-+F: drivers/s390/crypto/vfio_ap_private.h
-+
-+S390 VFIO-CCW DRIVER
-+M: Eric Farman <farman@linux.ibm.com>
-+M: Matthew Rosato <mjrosato@linux.ibm.com>
-+R: Halil Pasic <pasic@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+L: kvm@vger.kernel.org
-+S: Supported
-+F: Documentation/s390/vfio-ccw.rst
-+F: drivers/s390/cio/vfio_ccw*
-+F: include/uapi/linux/vfio_ccw.h
-+
-+S390 VFIO-PCI DRIVER
-+M: Matthew Rosato <mjrosato@linux.ibm.com>
-+M: Eric Farman <farman@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+L: kvm@vger.kernel.org
-+S: Supported
-+F: drivers/vfio/pci/vfio_pci_zdev.c
-+F: include/uapi/linux/vfio_zdev.h
-+
-+S390 ZCRYPT DRIVER
-+M: Harald Freudenberger <freude@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/s390/crypto/
-+
-+S390 ZFCP DRIVER
-+M: Steffen Maier <maier@linux.ibm.com>
-+M: Benjamin Block <bblock@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: drivers/s390/scsi/zfcp_*
-+
-+S3C ADC BATTERY DRIVER
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-samsung-soc@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/power/supply/s3c_adc_battery.c
-+F: include/linux/s3c_adc_battery.h
-+
-+S3C24XX SD/MMC Driver
-+M: Ben Dooks <ben-linux@fluff.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/mmc/host/s3cmci.*
-+
-+SAA6588 RDS RECEIVER DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/saa6588*
-+
-+SAA7134 VIDEO4LINUX DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/driver-api/media/drivers/saa7134*
-+F: drivers/media/pci/saa7134/
-+
-+SAA7146 VIDEO4LINUX-2 DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/common/saa7146/
-+F: drivers/media/pci/saa7146/
-+F: include/media/drv-intf/saa7146*
-+
-+SAFESETID SECURITY MODULE
-+M: Micah Morton <mortonm@chromium.org>
-+S: Supported
-+F: Documentation/admin-guide/LSM/SafeSetID.rst
-+F: security/safesetid/
-+
-+SAMSUNG AUDIO (ASoC) DRIVERS
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+F: Documentation/devicetree/bindings/sound/samsung*
-+F: sound/soc/samsung/
-+
-+SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+L: linux-crypto@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/rng/samsung,exynos4-rng.yaml
-+F: drivers/crypto/exynos-rng.c
-+
-+SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
-+M: Łukasz Stelmach <l.stelmach@samsung.com>
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml
-+F: drivers/char/hw_random/exynos-trng.c
-+
-+SAMSUNG FRAMEBUFFER DRIVER
-+M: Jingoo Han <jingoohan1@gmail.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/s3c-fb.c
-+
-+SAMSUNG INTERCONNECT DRIVERS
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+M: Artur Świgoń <a.swigon@samsung.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Supported
-+F: drivers/interconnect/samsung/
-+
-+SAMSUNG LAPTOP DRIVER
-+M: Corentin Chary <corentin.chary@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/samsung-laptop.c
-+
-+SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+L: linux-kernel@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/clock/samsung,s2mps11.txt
-+F: Documentation/devicetree/bindings/mfd/samsung,sec-core.txt
-+F: Documentation/devicetree/bindings/regulator/samsung,s2m*.txt
-+F: Documentation/devicetree/bindings/regulator/samsung,s5m*.txt
-+F: drivers/clk/clk-s2mps11.c
-+F: drivers/mfd/sec*.c
-+F: drivers/regulator/s2m*.c
-+F: drivers/regulator/s5m*.c
-+F: drivers/rtc/rtc-s5m.c
-+F: include/linux/mfd/samsung/
-+
-+SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
-+M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
-+L: linux-media@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/s3c-camif/
-+F: include/media/drv-intf/s3c_camif.h
-+
-+SAMSUNG S3FWRN5 NFC DRIVER
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Krzysztof Opasiak <k.opasiak@samsung.com>
-+L: linux-nfc@lists.01.org (subscribers-only)
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
-+F: drivers/nfc/s3fwrn5
-+
-+SAMSUNG S5C73M3 CAMERA DRIVER
-+M: Andrzej Hajda <a.hajda@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/i2c/s5c73m3/*
-+
-+SAMSUNG S5K5BAF CAMERA DRIVER
-+M: Andrzej Hajda <a.hajda@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/i2c/s5k5baf.c
-+
-+SAMSUNG S5P Security SubSystem (SSS) DRIVER
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Vladimir Zapolskiy <vz@mleia.com>
-+L: linux-crypto@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/crypto/samsung-slimsss.yaml
-+F: Documentation/devicetree/bindings/crypto/samsung-sss.yaml
-+F: drivers/crypto/s5p-sss.c
-+
-+SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/platform/exynos4-is/
-+
-+SAMSUNG SOC CLOCK DRIVERS
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+M: Tomasz Figa <tomasz.figa@gmail.com>
-+M: Chanwoo Choi <cw00.choi@samsung.com>
-+L: linux-samsung-soc@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
-+F: Documentation/devicetree/bindings/clock/exynos*.txt
-+F: Documentation/devicetree/bindings/clock/samsung,*.yaml
-+F: Documentation/devicetree/bindings/clock/samsung,s3c*
-+F: Documentation/devicetree/bindings/clock/samsung,s5p*
-+F: drivers/clk/samsung/
-+F: include/dt-bindings/clock/exynos*.h
-+F: include/dt-bindings/clock/s3c*.h
-+F: include/dt-bindings/clock/s5p*.h
-+F: include/dt-bindings/clock/samsung,*.h
-+F: include/linux/clk/samsung.h
-+F: include/linux/platform_data/clk-s3c2410.h
-+
-+SAMSUNG SPI DRIVERS
-+M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
-+M: Andi Shyti <andi@etezian.org>
-+L: linux-spi@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/spi-samsung.txt
-+F: drivers/spi/spi-s3c*
-+F: include/linux/platform_data/spi-s3c64xx.h
-+F: include/linux/spi/s3c24xx-fiq.h
-+
-+SAMSUNG SXGBE DRIVERS
-+M: Byungho An <bh74.an@samsung.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/samsung/sxgbe/
-+
-+SAMSUNG THERMAL DRIVER
-+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-samsung-soc@vger.kernel.org
-+S: Supported
-+T: git https://github.com/lmajewski/linux-samsung-thermal.git
-+F: drivers/thermal/samsung/
-+
-+SAMSUNG USB2 PHY DRIVER
-+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/phy/samsung-phy.txt
-+F: Documentation/driver-api/phy/samsung-usb2.rst
-+F: drivers/phy/samsung/phy-exynos4210-usb2.c
-+F: drivers/phy/samsung/phy-exynos4x12-usb2.c
-+F: drivers/phy/samsung/phy-exynos5250-usb2.c
-+F: drivers/phy/samsung/phy-s5pv210-usb2.c
-+F: drivers/phy/samsung/phy-samsung-usb2.c
-+F: drivers/phy/samsung/phy-samsung-usb2.h
-+
-+SANCLOUD BEAGLEBONE ENHANCED DEVICE TREE
-+M: Paul Barker <paul.barker@sancloud.com>
-+R: Marc Murphy <marc.murphy@sancloud.com>
-+S: Supported
-+F: arch/arm/boot/dts/am335x-sancloud*
-+
-+SC1200 WDT DRIVER
-+M: Zwane Mwaikambo <zwanem@gmail.com>
-+S: Maintained
-+F: drivers/watchdog/sc1200wdt.c
-+
-+SCHEDULER
-+M: Ingo Molnar <mingo@redhat.com>
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Juri Lelli <juri.lelli@redhat.com> (SCHED_DEADLINE)
-+M: Vincent Guittot <vincent.guittot@linaro.org> (SCHED_NORMAL)
-+R: Dietmar Eggemann <dietmar.eggemann@arm.com> (SCHED_NORMAL)
-+R: Steven Rostedt <rostedt@goodmis.org> (SCHED_FIFO/SCHED_RR)
-+R: Ben Segall <bsegall@google.com> (CONFIG_CFS_BANDWIDTH)
-+R: Mel Gorman <mgorman@suse.de> (CONFIG_NUMA_BALANCING)
-+R: Daniel Bristot de Oliveira <bristot@redhat.com> (SCHED_DEADLINE)
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
-+F: include/linux/preempt.h
-+F: include/linux/sched.h
-+F: include/linux/wait.h
-+F: include/uapi/linux/sched.h
-+F: kernel/sched/
-+
-+SCR24X CHIP CARD INTERFACE DRIVER
-+M: Lubomir Rintel <lkundrak@v3.sk>
-+S: Supported
-+F: drivers/char/pcmcia/scr24x_cs.c
-+
-+SCSI RDMA PROTOCOL (SRP) INITIATOR
-+M: Bart Van Assche <bvanassche@acm.org>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/ulp/srp/
-+F: include/scsi/srp.h
-+
-+SCSI RDMA PROTOCOL (SRP) TARGET
-+M: Bart Van Assche <bvanassche@acm.org>
-+L: linux-rdma@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.kernel.org/project/linux-rdma/list/
-+F: drivers/infiniband/ulp/srpt/
-+
-+SCSI SG DRIVER
-+M: Doug Gilbert <dgilbert@interlog.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+W: http://sg.danny.cz/sg
-+F: Documentation/scsi/scsi-generic.rst
-+F: drivers/scsi/sg.c
-+F: include/scsi/sg.h
-+
-+SCSI SUBSYSTEM
-+M: "James E.J. Bottomley" <jejb@linux.ibm.com>
-+M: "Martin K. Petersen" <martin.petersen@oracle.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+Q: https://patchwork.kernel.org/project/linux-scsi/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
-+F: Documentation/devicetree/bindings/scsi/
-+F: drivers/scsi/
-+F: include/scsi/
-+
-+SCSI TAPE DRIVER
-+M: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: Documentation/scsi/st.rst
-+F: drivers/scsi/st.*
-+F: drivers/scsi/st_*.h
-+
-+SCSI TARGET CORE USER DRIVER
-+M: Bodo Stroesser <bostroesser@gmail.com>
-+L: linux-scsi@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+F: Documentation/target/tcmu-design.rst
-+F: drivers/target/target_core_user.c
-+F: include/uapi/linux/target_core_user.h
-+
-+SCSI TARGET SUBSYSTEM
-+M: "Martin K. Petersen" <martin.petersen@oracle.com>
-+L: linux-scsi@vger.kernel.org
-+L: target-devel@vger.kernel.org
-+S: Supported
-+W: http://www.linux-iscsi.org
-+Q: https://patchwork.kernel.org/project/target-devel/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
-+F: Documentation/target/
-+F: drivers/target/
-+F: include/target/
-+
-+SCTP PROTOCOL
-+M: Vlad Yasevich <vyasevich@gmail.com>
-+M: Neil Horman <nhorman@tuxdriver.com>
-+M: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
-+L: linux-sctp@vger.kernel.org
-+S: Maintained
-+W: http://lksctp.sourceforge.net
-+F: Documentation/networking/sctp.rst
-+F: include/linux/sctp.h
-+F: include/net/sctp/
-+F: include/uapi/linux/sctp.h
-+F: net/sctp/
-+
-+SCx200 CPU SUPPORT
-+M: Jim Cromie <jim.cromie@gmail.com>
-+S: Odd Fixes
-+F: Documentation/i2c/busses/scx200_acb.rst
-+F: arch/x86/platform/scx200/
-+F: drivers/i2c/busses/scx200*
-+F: drivers/mtd/maps/scx200_docflash.c
-+F: drivers/watchdog/scx200_wdt.c
-+F: include/linux/scx200.h
-+
-+SCx200 GPIO DRIVER
-+M: Jim Cromie <jim.cromie@gmail.com>
-+S: Maintained
-+F: drivers/char/scx200_gpio.c
-+F: include/linux/scx200_gpio.h
-+
-+SCx200 HRT CLOCKSOURCE DRIVER
-+M: Jim Cromie <jim.cromie@gmail.com>
-+S: Maintained
-+F: drivers/clocksource/scx200_hrt.c
-+
-+SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
-+M: Sascha Sommer <saschasommer@freenet.de>
-+L: sdricohcs-devel@lists.sourceforge.net (subscribers-only)
-+S: Maintained
-+F: drivers/mmc/host/sdricoh_cs.c
-+
-+SECO BOARDS CEC DRIVER
-+M: Ettore Chimenti <ek5.chimenti@gmail.com>
-+S: Maintained
-+F: drivers/media/cec/platform/seco/seco-cec.c
-+F: drivers/media/cec/platform/seco/seco-cec.h
-+
-+SECURE COMPUTING
-+M: Kees Cook <keescook@chromium.org>
-+R: Andy Lutomirski <luto@amacapital.net>
-+R: Will Drewry <wad@chromium.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp
-+F: Documentation/userspace-api/seccomp_filter.rst
-+F: include/linux/seccomp.h
-+F: include/uapi/linux/seccomp.h
-+F: kernel/seccomp.c
-+F: tools/testing/selftests/kselftest_harness.h
-+F: tools/testing/selftests/seccomp/*
-+K: \bsecure_computing
-+K: \bTIF_SECCOMP\b
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) Broadcom BRCMSTB DRIVER
-+M: Al Cooper <alcooperx@gmail.com>
-+L: linux-mmc@vger.kernel.org
-+L: bcm-kernel-feedback-list@broadcom.com
-+S: Maintained
-+F: drivers/mmc/host/sdhci-brcmstb*
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-+M: Adrian Hunter <adrian.hunter@intel.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci*
-+F: include/linux/mmc/sdhci*
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER
-+M: Eugen Hristev <eugen.hristev@microchip.com>
-+L: linux-mmc@vger.kernel.org
-+S: Supported
-+F: drivers/mmc/host/sdhci-of-at91.c
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
-+M: Ben Dooks <ben-linux@fluff.org>
-+M: Jaehoon Chung <jh80.chung@samsung.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci-s3c*
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
-+M: Viresh Kumar <vireshk@kernel.org>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci-spear.c
-+
-+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) TI OMAP DRIVER
-+M: Kishon Vijay Abraham I <kishon@ti.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci-omap.c
-+
-+SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
-+M: Jonathan Derrick <jonathan.derrick@intel.com>
-+M: Revanth Rajashekar <revanth.rajashekar@intel.com>
-+L: linux-block@vger.kernel.org
-+S: Supported
-+F: block/opal_proto.h
-+F: block/sed*
-+F: include/linux/sed*
-+F: include/uapi/linux/sed*
-+
-+SECURITY CONTACT
-+M: Security Officers <security@kernel.org>
-+S: Supported
-+F: Documentation/admin-guide/security-bugs.rst
-+
-+SECURITY SUBSYSTEM
-+M: James Morris <jmorris@namei.org>
-+M: "Serge E. Hallyn" <serge@hallyn.com>
-+L: linux-security-module@vger.kernel.org (suggested Cc:)
-+S: Supported
-+W: http://kernsec.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
-+F: security/
-+X: security/selinux/
-+
-+SELINUX SECURITY MODULE
-+M: Paul Moore <paul@paul-moore.com>
-+M: Stephen Smalley <stephen.smalley.work@gmail.com>
-+M: Eric Paris <eparis@parisplace.org>
-+L: selinux@vger.kernel.org
-+S: Supported
-+W: https://selinuxproject.org
-+W: https://github.com/SELinuxProject
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
-+F: Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
-+F: Documentation/ABI/obsolete/sysfs-selinux-disable
-+F: Documentation/admin-guide/LSM/SELinux.rst
-+F: include/trace/events/avc.h
-+F: include/uapi/linux/selinux_netlink.h
-+F: scripts/selinux/
-+F: security/selinux/
-+
-+SENSABLE PHANTOM
-+M: Jiri Slaby <jirislaby@kernel.org>
-+S: Maintained
-+F: drivers/misc/phantom.c
-+F: include/uapi/linux/phantom.h
-+
-+SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER
-+M: Tomasz Duszynski <tomasz.duszynski@octakon.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml
-+F: drivers/iio/chemical/scd30.h
-+F: drivers/iio/chemical/scd30_core.c
-+F: drivers/iio/chemical/scd30_i2c.c
-+F: drivers/iio/chemical/scd30_serial.c
-+
-+SENSIRION SGP40 GAS SENSOR DRIVER
-+M: Andreas Klinger <ak@it-klinger.de>
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp40
-+F: drivers/iio/chemical/sgp40.c
-+
-+SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER
-+M: Tomasz Duszynski <tduszyns@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.yaml
-+F: drivers/iio/chemical/sps30.c
-+F: drivers/iio/chemical/sps30_i2c.c
-+F: drivers/iio/chemical/sps30_serial.c
-+
-+SERIAL DEVICE BUS
-+M: Rob Herring <robh@kernel.org>
-+L: linux-serial@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/serial/serial.yaml
-+F: drivers/tty/serdev/
-+F: include/linux/serdev.h
-+
-+SERIAL DRIVERS
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-serial@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/serial/
-+F: drivers/tty/serial/
-+
-+SERIAL IR RECEIVER
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/serial_ir.c
-+
-+SERIAL LOW-POWER INTER-CHIP MEDIA BUS (SLIMbus)
-+M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/slimbus/
-+F: drivers/slimbus/
-+F: include/linux/slimbus.h
-+
-+SFC NETWORK DRIVER
-+M: Edward Cree <ecree.xilinx@gmail.com>
-+M: Martin Habets <habetsm.xilinx@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/sfc/
-+
-+SFF/SFP/SFP+ MODULE SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/phy/phylink.c
-+F: drivers/net/phy/sfp*
-+F: include/linux/mdio/mdio-i2c.h
-+F: include/linux/phylink.h
-+F: include/linux/sfp.h
-+K: phylink\.h|struct\s+phylink|\.phylink|>phylink_|phylink_(autoneg|clear|connect|create|destroy|disconnect|ethtool|helper|mac|mii|of|set|start|stop|test|validate)
-+
-+SGI GRU DRIVER
-+M: Dimitri Sivanich <dimitri.sivanich@hpe.com>
-+S: Maintained
-+F: drivers/misc/sgi-gru/
-+
-+SGI XP/XPC/XPNET DRIVER
-+M: Robin Holt <robinmholt@gmail.com>
-+M: Steve Wahl <steve.wahl@hpe.com>
-+R: Mike Travis <mike.travis@hpe.com>
-+S: Maintained
-+F: drivers/misc/sgi-xp/
-+
-+SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
-+M: Karsten Graul <kgraul@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/linux/linux390/
-+F: net/smc/
-+
-+SHARP GP2AP002A00F/GP2AP002S00F SENSOR DRIVER
-+M: Linus Walleij <linus.walleij@linaro.org>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
-+F: Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml
-+F: drivers/iio/light/gp2ap002.c
-+
-+SHARP RJ54N1CB0C SENSOR DRIVER
-+M: Jacopo Mondi <jacopo@jmondi.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/rj54n1cb0c.c
-+F: include/media/i2c/rj54n1cb0c.h
-+
-+SH_VOU V4L2 OUTPUT DRIVER
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+F: drivers/media/platform/sh_vou.c
-+F: include/media/drv-intf/sh_vou.h
-+
-+SI2157 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/si2157*
-+
-+SI2165 MEDIA DRIVER
-+M: Matthias Schwarzott <zzam@gentoo.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/si2165*
-+
-+SI2168 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/si2168*
-+
-+SI470X FM RADIO RECEIVER I2C DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/si470x/radio-si470x-i2c.c
-+
-+SI470X FM RADIO RECEIVER USB DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/si470x/radio-si470x-common.c
-+F: drivers/media/radio/si470x/radio-si470x-usb.c
-+F: drivers/media/radio/si470x/radio-si470x.h
-+
-+SI4713 FM RADIO TRANSMITTER I2C DRIVER
-+M: Eduardo Valentin <edubezval@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/si4713/si4713.?
-+
-+SI4713 FM RADIO TRANSMITTER PLATFORM DRIVER
-+M: Eduardo Valentin <edubezval@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/si4713/radio-platform-si4713.c
-+
-+SI4713 FM RADIO TRANSMITTER USB DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/si4713/radio-usb-si4713.c
-+
-+SIANO DVB DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/common/siano/
-+F: drivers/media/mmc/siano/
-+F: drivers/media/usb/siano/
-+F: drivers/media/usb/siano/
-+
-+SIFIVE DRIVERS
-+M: Palmer Dabbelt <palmer@dabbelt.com>
-+M: Paul Walmsley <paul.walmsley@sifive.com>
-+L: linux-riscv@lists.infradead.org
-+S: Supported
-+T: git git://github.com/sifive/riscv-linux.git
-+N: sifive
-+K: [^@]sifive
-+
-+SIFIVE FU540 SYSTEM-ON-CHIP
-+M: Paul Walmsley <paul.walmsley@sifive.com>
-+M: Palmer Dabbelt <palmer@dabbelt.com>
-+L: linux-riscv@lists.infradead.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git
-+N: fu540
-+K: fu540
-+
-+SIFIVE PDMA DRIVER
-+M: Green Wan <green.wan@sifive.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml
-+F: drivers/dma/sf-pdma/
-+
-+SILEAD TOUCHSCREEN DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/input/touchscreen/silead.c
-+F: drivers/platform/x86/touchscreen_dmi.c
-+
-+SILICON LABS WIRELESS DRIVERS (for WFxxx series)
-+M: Jérôme Pouiller <jerome.pouiller@silabs.com>
-+S: Supported
-+F: drivers/staging/wfx/
-+
-+SILICON MOTION SM712 FRAME BUFFER DRIVER
-+M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-+M: Teddy Wang <teddy.wang@siliconmotion.com>
-+M: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/fb/sm712fb.rst
-+F: drivers/video/fbdev/sm712*
-+
-+SILVACO I3C DUAL-ROLE MASTER
-+M: Miquel Raynal <miquel.raynal@bootlin.com>
-+M: Conor Culhane <conor.culhane@silvaco.com>
-+L: linux-i3c@lists.infradead.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
-+F: drivers/i3c/master/svc-i3c-master.c
-+
-+SIMPLEFB FB DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/simple-framebuffer.yaml
-+F: drivers/video/fbdev/simplefb.c
-+F: include/linux/platform_data/simplefb.h
-+
-+SIMTEC EB110ATX (Chalice CATS)
-+M: Simtec Linux Team <linux@simtec.co.uk>
-+S: Supported
-+W: http://www.simtec.co.uk/products/EB110ATX/
-+
-+SIMTEC EB2410ITX (BAST)
-+M: Simtec Linux Team <linux@simtec.co.uk>
-+S: Supported
-+W: http://www.simtec.co.uk/products/EB2410ITX/
-+F: arch/arm/mach-s3c/bast-ide.c
-+F: arch/arm/mach-s3c/bast-irq.c
-+F: arch/arm/mach-s3c/mach-bast.c
-+
-+SIOX
-+M: Thorsten Scherer <t.scherer@eckelmann.de>
-+M: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-+R: Pengutronix Kernel Team <kernel@pengutronix.de>
-+S: Supported
-+F: drivers/gpio/gpio-siox.c
-+F: drivers/siox/*
-+F: include/trace/events/siox.h
-+
-+SIPHASH PRF ROUTINES
-+M: Jason A. Donenfeld <Jason@zx2c4.com>
-+S: Maintained
-+F: include/linux/siphash.h
-+F: lib/siphash.c
-+F: lib/test_siphash.c
-+
-+SIS 190 ETHERNET DRIVER
-+M: Francois Romieu <romieu@fr.zoreil.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/sis/sis190.c
-+
-+SIS 900/7016 FAST ETHERNET DRIVER
-+M: Daniele Venzano <venza@brownhat.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.brownhat.org/sis900.html
-+F: drivers/net/ethernet/sis/sis900.*
-+
-+SIS FRAMEBUFFER DRIVER
-+M: Thomas Winischhofer <thomas@winischhofer.net>
-+S: Maintained
-+W: http://www.winischhofer.net/linuxsisvga.shtml
-+F: Documentation/fb/sisfb.rst
-+F: drivers/video/fbdev/sis/
-+F: include/video/sisfb.h
-+
-+SIS I2C TOUCHSCREEN DRIVER
-+M: Mika Penttilä <mika.penttila@nextfour.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt
-+F: drivers/input/touchscreen/sis_i2c.c
-+
-+SIS USB2VGA DRIVER
-+M: Thomas Winischhofer <thomas@winischhofer.net>
-+S: Maintained
-+W: http://www.winischhofer.at/linuxsisusbvga.shtml
-+F: drivers/usb/misc/sisusbvga/
-+
-+SLAB ALLOCATOR
-+M: Christoph Lameter <cl@linux.com>
-+M: Pekka Enberg <penberg@kernel.org>
-+M: David Rientjes <rientjes@google.com>
-+M: Joonsoo Kim <iamjoonsoo.kim@lge.com>
-+M: Andrew Morton <akpm@linux-foundation.org>
-+M: Vlastimil Babka <vbabka@suse.cz>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: include/linux/sl?b*.h
-+F: mm/sl?b*
-+
-+SLEEPABLE READ-COPY UPDATE (SRCU)
-+M: Lai Jiangshan <jiangshanlai@gmail.com>
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+M: Josh Triplett <josh@joshtriplett.org>
-+R: Steven Rostedt <rostedt@goodmis.org>
-+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+L: rcu@vger.kernel.org
-+S: Supported
-+W: http://www.rdrop.com/users/paulmck/RCU/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
-+F: include/linux/srcu*.h
-+F: kernel/rcu/srcu*.c
-+
-+SMACK SECURITY MODULE
-+M: Casey Schaufler <casey@schaufler-ca.com>
-+L: linux-security-module@vger.kernel.org
-+S: Maintained
-+W: http://schaufler-ca.com
-+T: git git://github.com/cschaufler/smack-next
-+F: Documentation/admin-guide/LSM/Smack.rst
-+F: security/smack/
-+
-+SMC91x ETHERNET DRIVER
-+M: Nicolas Pitre <nico@fluxnic.net>
-+S: Odd Fixes
-+F: drivers/net/ethernet/smsc/smc91x.*
-+
-+SECURE MONITOR CALL(SMC) CALLING CONVENTION (SMCCC)
-+M: Mark Rutland <mark.rutland@arm.com>
-+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/firmware/smccc/
-+F: include/linux/arm-smccc.h
-+
-+SMM665 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/smm665.rst
-+F: drivers/hwmon/smm665.c
-+
-+SMSC EMC2103 HARDWARE MONITOR DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/emc2103.rst
-+F: drivers/hwmon/emc2103.c
-+
-+SMSC SCH5627 HARDWARE MONITOR DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Supported
-+F: Documentation/hwmon/sch5627.rst
-+F: drivers/hwmon/sch5627.c
-+
-+SMSC UFX6000 and UFX7000 USB to VGA DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/smscufx.c
-+
-+SMSC47B397 HARDWARE MONITOR DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/smsc47b397.rst
-+F: drivers/hwmon/smsc47b397.c
-+
-+SMSC911x ETHERNET DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/smsc/smsc911x.*
-+F: include/linux/smsc911x.h
-+
-+SMSC9420 PCI ETHERNET DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/smsc/smsc9420.*
-+
-+SOCIONEXT (SNI) AVE NETWORK DRIVER
-+M: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/socionext,uniphier-ave4.yaml
-+F: drivers/net/ethernet/socionext/sni_ave.c
-+
-+SOCIONEXT (SNI) NETSEC NETWORK DRIVER
-+M: Jassi Brar <jaswinder.singh@linaro.org>
-+M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/socionext-netsec.txt
-+F: drivers/net/ethernet/socionext/netsec.c
-+
-+SOCIONEXT (SNI) Synquacer SPI DRIVER
-+M: Masahisa Kojima <masahisa.kojima@linaro.org>
-+M: Jassi Brar <jaswinder.singh@linaro.org>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/spi/spi-synquacer.txt
-+F: drivers/spi/spi-synquacer.c
-+
-+SOCIONEXT SYNQUACER I2C DRIVER
-+M: Ard Biesheuvel <ardb@kernel.org>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
-+F: drivers/i2c/busses/i2c-synquacer.c
-+
-+SOCIONEXT UNIPHIER SOUND DRIVER
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Orphan
-+F: sound/soc/uniphier/
-+
-+SOEKRIS NET48XX LED SUPPORT
-+M: Chris Boot <bootc@bootc.net>
-+S: Maintained
-+F: drivers/leds/leds-net48xx.c
-+
-+SOFT-IWARP DRIVER (siw)
-+M: Bernard Metzler <bmt@zurich.ibm.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/sw/siw/
-+F: include/uapi/rdma/siw-abi.h
-+
-+SOFT-ROCE DRIVER (rxe)
-+M: Zhu Yanjun <zyjzyj2000@gmail.com>
-+L: linux-rdma@vger.kernel.org
-+S: Supported
-+F: drivers/infiniband/sw/rxe/
-+F: include/uapi/rdma/rdma_user_rxe.h
-+
-+SOFTLOGIC 6x10 MPEG CODEC
-+M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
-+M: Anton Sviridenko <anton@corp.bluecherry.net>
-+M: Andrey Utkin <andrey_utkin@fastmail.com>
-+M: Ismael Luceno <ismael@iodev.co.uk>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/pci/solo6x10/
-+
-+SOFTWARE DELEGATED EXCEPTION INTERFACE (SDEI)
-+M: James Morse <james.morse@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/firmware/sdei.txt
-+F: drivers/firmware/arm_sdei.c
-+F: include/linux/arm_sdei.h
-+F: include/uapi/linux/arm_sdei.h
-+
-+SOFTWARE NODES
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+R: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-+L: linux-acpi@vger.kernel.org
-+S: Maintained
-+F: drivers/base/swnode.c
-+
-+SOFTWARE RAID (Multiple Disks) SUPPORT
-+M: Song Liu <song@kernel.org>
-+L: linux-raid@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/song/md.git
-+F: drivers/md/Kconfig
-+F: drivers/md/Makefile
-+F: drivers/md/md*
-+F: drivers/md/raid*
-+F: include/linux/raid/
-+F: include/uapi/linux/raid/
-+
-+SOLIDRUN CLEARFOG SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+S: Maintained
-+F: arch/arm/boot/dts/armada-388-clearfog*
-+F: arch/arm/boot/dts/armada-38x-solidrun-*
-+
-+SOLIDRUN CUBOX-I/HUMMINGBOARD SUPPORT
-+M: Russell King <linux@armlinux.org.uk>
-+S: Maintained
-+F: arch/arm/boot/dts/imx6*-cubox-i*
-+F: arch/arm/boot/dts/imx6*-hummingboard*
-+F: arch/arm/boot/dts/imx6*-sr-*
-+
-+SONIC NETWORK DRIVER
-+M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/natsemi/sonic.*
-+
-+SONICS SILICON BACKPLANE DRIVER (SSB)
-+M: Michael Buesch <m@bues.ch>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/ssb/
-+F: include/linux/ssb/
-+
-+SONY IMX208 SENSOR DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/imx208.c
-+
-+SONY IMX214 SENSOR DRIVER
-+M: Ricardo Ribalda <ribalda@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml
-+F: drivers/media/i2c/imx214.c
-+
-+SONY IMX219 SENSOR DRIVER
-+M: Dave Stevenson <dave.stevenson@raspberrypi.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/imx219.yaml
-+F: drivers/media/i2c/imx219.c
-+
-+SONY IMX258 SENSOR DRIVER
-+M: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/imx258.yaml
-+F: drivers/media/i2c/imx258.c
-+
-+SONY IMX274 SENSOR DRIVER
-+M: Leon Luo <leonl@leopardimaging.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
-+F: drivers/media/i2c/imx274.c
-+
-+SONY IMX290 SENSOR DRIVER
-+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/imx290.txt
-+F: drivers/media/i2c/imx290.c
-+
-+SONY IMX319 SENSOR DRIVER
-+M: Bingbu Cao <bingbu.cao@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/imx319.c
-+
-+SONY IMX334 SENSOR DRIVER
-+M: Paul J. Murphy <paul.j.murphy@intel.com>
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
-+F: drivers/media/i2c/imx334.c
-+
-+SONY IMX335 SENSOR DRIVER
-+M: Paul J. Murphy <paul.j.murphy@intel.com>
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
-+F: drivers/media/i2c/imx335.c
-+
-+SONY IMX355 SENSOR DRIVER
-+M: Tianshu Qiu <tian.shu.qiu@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/imx355.c
-+
-+SONY IMX412 SENSOR DRIVER
-+M: Paul J. Murphy <paul.j.murphy@intel.com>
-+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
-+F: drivers/media/i2c/imx412.c
-+
-+SONY MEMORYSTICK SUBSYSTEM
-+M: Maxim Levitsky <maximlevitsky@gmail.com>
-+M: Alex Dubov <oakad@yahoo.com>
-+M: Ulf Hansson <ulf.hansson@linaro.org>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
-+F: drivers/memstick/
-+F: include/linux/memstick.h
-+
-+SONY VAIO CONTROL DEVICE DRIVER
-+M: Mattia Dongili <malattia@linux.it>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
-+F: Documentation/admin-guide/laptops/sony-laptop.rst
-+F: drivers/char/sonypi.c
-+F: drivers/platform/x86/sony-laptop.c
-+F: include/linux/sony-laptop.h
-+
-+SOUND
-+M: Jaroslav Kysela <perex@perex.cz>
-+M: Takashi Iwai <tiwai@suse.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.alsa-project.org/
-+Q: http://patchwork.kernel.org/project/alsa-devel/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: Documentation/sound/
-+F: include/sound/
-+F: include/uapi/sound/
-+F: sound/
-+
-+SOUND - COMPRESSED AUDIO
-+M: Vinod Koul <vkoul@kernel.org>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: Documentation/sound/designs/compress-offload.rst
-+F: include/sound/compress_driver.h
-+F: include/uapi/sound/compress_*
-+F: sound/core/compress_offload.c
-+F: sound/soc/soc-compress.c
-+
-+SOUND - DMAENGINE HELPERS
-+M: Lars-Peter Clausen <lars@metafoo.de>
-+S: Supported
-+F: include/sound/dmaengine_pcm.h
-+F: sound/core/pcm_dmaengine.c
-+F: sound/soc/soc-generic-dmaengine-pcm.c
-+
-+SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
-+M: Liam Girdwood <lgirdwood@gmail.com>
-+M: Mark Brown <broonie@kernel.org>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+W: http://alsa-project.org/main/index.php/ASoC
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
-+F: Documentation/devicetree/bindings/sound/
-+F: Documentation/sound/soc/
-+F: include/dt-bindings/sound/
-+F: include/sound/soc*
-+F: sound/soc/
-+
-+SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
-+M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
-+M: Liam Girdwood <lgirdwood@gmail.com>
-+M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
-+M: Kai Vehmanen <kai.vehmanen@linux.intel.com>
-+M: Daniel Baluta <daniel.baluta@nxp.com>
-+L: sound-open-firmware@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+W: https://github.com/thesofproject/linux/
-+F: sound/soc/sof/
-+
-+SOUNDWIRE SUBSYSTEM
-+M: Vinod Koul <vkoul@kernel.org>
-+M: Bard Liao <yung-chuan.liao@linux.intel.com>
-+R: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
-+R: Sanyog Kale <sanyog.r.kale@intel.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git
-+F: Documentation/driver-api/soundwire/
-+F: drivers/soundwire/
-+F: include/linux/soundwire/
-+
-+SP2 MEDIA DRIVER
-+M: Olli Salonen <olli.salonen@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/sp2*
-+
-+SPARC + UltraSPARC (sparc/sparc64)
-+M: "David S. Miller" <davem@davemloft.net>
-+L: sparclinux@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.ozlabs.org/project/sparclinux/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git
-+F: arch/sparc/
-+F: drivers/sbus/
-+
-+SPARC SERIAL DRIVERS
-+M: "David S. Miller" <davem@davemloft.net>
-+L: sparclinux@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git
-+F: drivers/tty/serial/suncore.c
-+F: drivers/tty/serial/sunhv.c
-+F: drivers/tty/serial/sunsab.c
-+F: drivers/tty/serial/sunsab.h
-+F: drivers/tty/serial/sunsu.c
-+F: drivers/tty/serial/sunzilog.c
-+F: drivers/tty/serial/sunzilog.h
-+F: drivers/tty/vcc.c
-+F: include/linux/sunserialcore.h
-+
-+SPARSE CHECKER
-+M: "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
-+L: linux-sparse@vger.kernel.org
-+S: Maintained
-+W: https://sparse.docs.kernel.org/
-+T: git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
-+Q: https://patchwork.kernel.org/project/linux-sparse/list/
-+B: https://bugzilla.kernel.org/enter_bug.cgi?component=Sparse&product=Tools
-+F: include/linux/compiler.h
-+
-+SPEAKUP CONSOLE SPEECH DRIVER
-+M: William Hubbs <w.d.hubbs@gmail.com>
-+M: Chris Brannon <chris@the-brannons.com>
-+M: Kirk Reiser <kirk@reisers.ca>
-+M: Samuel Thibault <samuel.thibault@ens-lyon.org>
-+L: speakup@linux-speakup.org
-+S: Odd Fixes
-+W: http://www.linux-speakup.org/
-+W: https://github.com/linux-speakup/speakup
-+B: https://github.com/linux-speakup/speakup/issues
-+F: drivers/accessibility/speakup/
-+
-+SPEAR CLOCK FRAMEWORK SUPPORT
-+M: Viresh Kumar <vireshk@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.st.com/spear
-+F: drivers/clk/spear/
-+
-+SPEAR PLATFORM SUPPORT
-+M: Viresh Kumar <vireshk@kernel.org>
-+M: Shiraz Hashim <shiraz.linux.kernel@gmail.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+W: http://www.st.com/spear
-+F: arch/arm/boot/dts/spear*
-+F: arch/arm/mach-spear/
-+
-+SPI NOR SUBSYSTEM
-+M: Tudor Ambarus <tudor.ambarus@microchip.com>
-+R: Michael Walle <michael@walle.cc>
-+R: Pratyush Yadav <p.yadav@ti.com>
-+L: linux-mtd@lists.infradead.org
-+S: Maintained
-+W: http://www.linux-mtd.infradead.org/
-+Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
-+C: irc://irc.oftc.net/mtd
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git spi-nor/next
-+F: drivers/mtd/spi-nor/
-+F: include/linux/mtd/spi-nor.h
-+
-+SPI SUBSYSTEM
-+M: Mark Brown <broonie@kernel.org>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/spi-devel-general/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
-+F: Documentation/devicetree/bindings/spi/
-+F: Documentation/spi/
-+F: drivers/spi/
-+F: include/linux/spi/
-+F: include/uapi/linux/spi/
-+F: tools/spi/
-+
-+SPIDERNET NETWORK DRIVER for CELL
-+M: Ishizaki Kou <kou.ishizaki@toshiba.co.jp>
-+M: Geoff Levand <geoff@infradead.org>
-+L: netdev@vger.kernel.org
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Maintained
-+F: Documentation/networking/device_drivers/ethernet/toshiba/spider_net.rst
-+F: drivers/net/ethernet/toshiba/spider_net*
-+
-+SPMI SUBSYSTEM
-+M: Stephen Boyd <sboyd@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sboyd/spmi.git
-+F: Documentation/devicetree/bindings/spmi/
-+F: drivers/spmi/
-+F: include/dt-bindings/spmi/spmi.h
-+F: include/linux/spmi.h
-+F: include/trace/events/spmi.h
-+
-+SPU FILE SYSTEM
-+M: Jeremy Kerr <jk@ozlabs.org>
-+L: linuxppc-dev@lists.ozlabs.org
-+S: Supported
-+W: http://www.ibm.com/developerworks/power/cell/
-+F: Documentation/filesystems/spufs/spufs.rst
-+F: arch/powerpc/platforms/cell/spufs/
-+
-+SQUASHFS FILE SYSTEM
-+M: Phillip Lougher <phillip@squashfs.org.uk>
-+L: squashfs-devel@lists.sourceforge.net (subscribers-only)
-+S: Maintained
-+W: http://squashfs.org.uk
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git
-+F: Documentation/filesystems/squashfs.rst
-+F: fs/squashfs/
-+
-+SRM (Alpha) environment access
-+M: Jan-Benedict Glaw <jbglaw@lug-owl.de>
-+S: Maintained
-+F: arch/alpha/kernel/srm_env.c
-+
-+ST LSM6DSx IMU IIO DRIVER
-+M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+W: http://www.st.com/
-+F: Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
-+F: drivers/iio/imu/st_lsm6dsx/
-+
-+ST MIPID02 CSI-2 TO PARALLEL BRIDGE DRIVER
-+M: Mickael Guene <mickael.guene@st.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt
-+F: drivers/media/i2c/st-mipid02.c
-+
-+ST STM32 I2C/SMBUS DRIVER
-+M: Pierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>
-+M: Alain Volmat <alain.volmat@foss.st.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-stm32*
-+
-+ST STM32 SPI DRIVER
-+M: Alain Volmat <alain.volmat@foss.st.com>
-+L: linux-spi@vger.kernel.org
-+S: Maintained
-+F: drivers/spi/spi-stm32.c
-+
-+ST STPDDC60 DRIVER
-+M: Daniel Nilsson <daniel.nilsson@flex.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/stpddc60.rst
-+F: drivers/hwmon/pmbus/stpddc60.c
-+
-+ST VL53L0X ToF RANGER(I2C) IIO DRIVER
-+M: Song Qiang <songqiang1304521@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
-+F: drivers/iio/proximity/vl53l0x-i2c.c
-+
-+STABLE BRANCH
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+M: Sasha Levin <sashal@kernel.org>
-+L: stable@vger.kernel.org
-+S: Supported
-+F: Documentation/process/stable-kernel-rules.rst
-+
-+STAGING - ATOMISP DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+R: Sakari Ailus <sakari.ailus@linux.intel.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/staging/media/atomisp/
-+
-+STAGING - FIELDBUS SUBSYSTEM
-+M: Sven Van Asbroeck <TheSven73@gmail.com>
-+S: Maintained
-+F: drivers/staging/fieldbus/*
-+F: drivers/staging/fieldbus/Documentation/
-+
-+STAGING - HMS ANYBUS-S BUS
-+M: Sven Van Asbroeck <TheSven73@gmail.com>
-+S: Maintained
-+F: drivers/staging/fieldbus/anybuss/
-+
-+STAGING - INDUSTRIAL IO
-+M: Jonathan Cameron <jic23@kernel.org>
-+L: linux-iio@vger.kernel.org
-+S: Odd Fixes
-+F: Documentation/devicetree/bindings/staging/iio/
-+F: drivers/staging/iio/
-+
-+STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
-+M: Marc Dietrich <marvin24@gmx.de>
-+L: ac100@lists.launchpad.net (moderated for non-subscribers)
-+L: linux-tegra@vger.kernel.org
-+S: Maintained
-+F: drivers/staging/nvec/
-+
-+STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
-+M: Jens Frederich <jfrederich@gmail.com>
-+M: Jon Nettleton <jon.nettleton@gmail.com>
-+S: Maintained
-+W: http://wiki.laptop.org/go/DCON
-+F: drivers/staging/olpc_dcon/
-+
-+STAGING - REALTEK RTL8188EU DRIVERS
-+M: Larry Finger <Larry.Finger@lwfinger.net>
-+M: Phillip Potter <phil@philpotter.co.uk>
-+S: Supported
-+F: drivers/staging/r8188eu/
-+
-+STAGING - REALTEK RTL8712U DRIVERS
-+M: Larry Finger <Larry.Finger@lwfinger.net>
-+M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
-+S: Odd Fixes
-+F: drivers/staging/rtl8712/
-+
-+STAGING - SEPS525 LCD CONTROLLER DRIVERS
-+M: Michael Hennerich <michael.hennerich@analog.com>
-+L: linux-fbdev@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
-+F: drivers/staging/fbtft/fb_seps525.c
-+
-+STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
-+M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-+M: Teddy Wang <teddy.wang@siliconmotion.com>
-+M: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/staging/sm750fb/
-+
-+STAGING - VIA VT665X DRIVERS
-+M: Forest Bond <forest@alittletooquiet.net>
-+S: Odd Fixes
-+F: drivers/staging/vt665?/
-+
-+STAGING SUBSYSTEM
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-staging@lists.linux.dev
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
-+F: drivers/staging/
-+
-+STARFIRE/DURALAN NETWORK DRIVER
-+M: Ion Badulescu <ionut@badula.org>
-+S: Odd Fixes
-+F: drivers/net/ethernet/adaptec/starfire*
-+
-+STATIC BRANCH/CALL
-+M: Peter Zijlstra <peterz@infradead.org>
-+M: Josh Poimboeuf <jpoimboe@redhat.com>
-+M: Jason Baron <jbaron@akamai.com>
-+R: Steven Rostedt <rostedt@goodmis.org>
-+R: Ard Biesheuvel <ardb@kernel.org>
-+S: Supported
-+F: arch/*/include/asm/jump_label*.h
-+F: arch/*/include/asm/static_call*.h
-+F: arch/*/kernel/jump_label.c
-+F: arch/*/kernel/static_call.c
-+F: include/linux/jump_label*.h
-+F: include/linux/static_call*.h
-+F: kernel/jump_label.c
-+F: kernel/static_call.c
-+
-+STI AUDIO (ASoC) DRIVERS
-+M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
-+F: sound/soc/sti/
-+
-+STI CEC DRIVER
-+M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-+S: Maintained
-+F: Documentation/devicetree/bindings/media/stih-cec.txt
-+F: drivers/media/cec/platform/sti/
-+
-+STK1160 USB VIDEO CAPTURE DRIVER
-+M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/stk1160/
-+
-+STM32 AUDIO (ASoC) DRIVERS
-+M: Olivier Moysan <olivier.moysan@foss.st.com>
-+M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
-+F: Documentation/devicetree/bindings/sound/st,stm32-*.yaml
-+F: sound/soc/stm/
-+
-+STM32 TIMER/LPTIMER DRIVERS
-+M: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
-+S: Maintained
-+F: Documentation/ABI/testing/*timer-stm32
-+F: Documentation/devicetree/bindings/*/*stm32-*timer*
-+F: drivers/*/stm32-*timer*
-+F: drivers/pwm/pwm-stm32*
-+F: include/linux/*/stm32-*tim*
-+
-+STMMAC ETHERNET DRIVER
-+M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-+M: Alexandre Torgue <alexandre.torgue@foss.st.com>
-+M: Jose Abreu <joabreu@synopsys.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+W: http://www.stlinux.com
-+F: Documentation/networking/device_drivers/ethernet/stmicro/
-+F: drivers/net/ethernet/stmicro/stmmac/
-+
-+SUN3/3X
-+M: Sam Creasey <sammy@sammy.net>
-+S: Maintained
-+W: http://sammy.net/sun3/
-+F: arch/m68k/include/asm/sun3*
-+F: arch/m68k/kernel/*sun3*
-+F: arch/m68k/sun3*/
-+F: drivers/net/ethernet/i825xx/sun3*
-+
-+SUN4I LOW RES ADC ATTACHED TABLET KEYS DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
-+F: drivers/input/keyboard/sun4i-lradc-keys.c
-+
-+SUNDANCE NETWORK DRIVER
-+M: Denis Kirjanov <kda@linux-powerpc.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/dlink/sundance.c
-+
-+SUPERH
-+M: Yoshinori Sato <ysato@users.sourceforge.jp>
-+M: Rich Felker <dalias@libc.org>
-+L: linux-sh@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.kernel.org/project/linux-sh/list/
-+F: Documentation/sh/
-+F: arch/sh/
-+F: drivers/sh/
-+
-+SUSPEND TO RAM
-+M: "Rafael J. Wysocki" <rafael@kernel.org>
-+M: Len Brown <len.brown@intel.com>
-+M: Pavel Machek <pavel@ucw.cz>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+B: https://bugzilla.kernel.org
-+F: Documentation/power/
-+F: arch/x86/kernel/acpi/
-+F: drivers/base/power/
-+F: include/linux/freezer.h
-+F: include/linux/pm.h
-+F: include/linux/suspend.h
-+F: kernel/power/
-+
-+SVGA HANDLING
-+M: Martin Mares <mj@ucw.cz>
-+L: linux-video@atrey.karlin.mff.cuni.cz
-+S: Maintained
-+F: Documentation/admin-guide/svga.rst
-+F: arch/x86/boot/video*
-+
-+SWIOTLB SUBSYSTEM
-+M: Christoph Hellwig <hch@infradead.org>
-+L: iommu@lists.linux-foundation.org
-+S: Supported
-+W: http://git.infradead.org/users/hch/dma-mapping.git
-+T: git git://git.infradead.org/users/hch/dma-mapping.git
-+F: arch/*/kernel/pci-swiotlb.c
-+F: include/linux/swiotlb.h
-+F: kernel/dma/swiotlb.c
-+
-+SWITCHDEV
-+M: Jiri Pirko <jiri@resnulli.us>
-+M: Ivan Vecera <ivecera@redhat.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: include/net/switchdev.h
-+F: net/switchdev/
-+
-+SY8106A REGULATOR DRIVER
-+M: Icenowy Zheng <icenowy@aosc.io>
-+S: Maintained
-+F: Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml
-+F: drivers/regulator/sy8106a-regulator.c
-+
-+SYNC FILE FRAMEWORK
-+M: Sumit Semwal <sumit.semwal@linaro.org>
-+R: Gustavo Padovan <gustavo@padovan.org>
-+L: linux-media@vger.kernel.org
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/driver-api/sync_file.rst
-+F: drivers/dma-buf/dma-fence*
-+F: drivers/dma-buf/sw_sync.c
-+F: drivers/dma-buf/sync_*
-+F: include/linux/sync_file.h
-+F: include/uapi/linux/sync_file.h
-+
-+SYNOPSYS ARC ARCHITECTURE
-+M: Vineet Gupta <vgupta@kernel.org>
-+L: linux-snps-arc@lists.infradead.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
-+F: Documentation/devicetree/bindings/arc/*
-+F: Documentation/devicetree/bindings/interrupt-controller/snps,arc*
-+F: arch/arc/
-+F: drivers/clocksource/arc_timer.c
-+F: drivers/tty/serial/arc_uart.c
-+
-+SYNOPSYS ARC HSDK SDP pll clock driver
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt
-+F: drivers/clk/clk-hsdk-pll.c
-+
-+SYNOPSYS ARC SDP clock driver
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/clock/snps,pll-clock.txt
-+F: drivers/clk/axs10x/*
-+
-+SYNOPSYS ARC SDP platform support
-+M: Alexey Brodkin <abrodkin@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/arc/axs10*
-+F: arch/arc/boot/dts/ax*
-+F: arch/arc/plat-axs10x
-+
-+SYNOPSYS AXS10x RESET CONTROLLER DRIVER
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/reset/snps,axs10x-reset.txt
-+F: drivers/reset/reset-axs10x.c
-+
-+SYNOPSYS CREG GPIO DRIVER
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/snps,creg-gpio.txt
-+F: drivers/gpio/gpio-creg-snps.c
-+
-+SYNOPSYS DESIGNWARE 8250 UART DRIVER
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+S: Maintained
-+F: drivers/tty/serial/8250/8250_dw.c
-+F: drivers/tty/serial/8250/8250_dwlib.*
-+F: drivers/tty/serial/8250/8250_lpss.c
-+
-+SYNOPSYS DESIGNWARE APB GPIO DRIVER
-+M: Hoan Tran <hoan@os.amperecomputing.com>
-+M: Serge Semin <fancer.lancer@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/snps,dw-apb-gpio.yaml
-+F: drivers/gpio/gpio-dwapb.c
-+
-+SYNOPSYS DESIGNWARE APB SSI DRIVER
-+M: Serge Semin <fancer.lancer@gmail.com>
-+L: linux-spi@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
-+F: drivers/spi/spi-dw*
-+
-+SYNOPSYS DESIGNWARE AXI DMAC DRIVER
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
-+F: drivers/dma/dw-axi-dmac/
-+
-+SYNOPSYS DESIGNWARE DMAC DRIVER
-+M: Viresh Kumar <vireshk@kernel.org>
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml
-+F: drivers/dma/dw/
-+F: include/dt-bindings/dma/dw-dmac.h
-+F: include/linux/dma/dw.h
-+F: include/linux/platform_data/dma-dw.h
-+
-+SYNOPSYS DESIGNWARE ENTERPRISE ETHERNET DRIVER
-+M: Jose Abreu <Jose.Abreu@synopsys.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/synopsys/
-+
-+SYNOPSYS DESIGNWARE ETHERNET XPCS DRIVER
-+M: Jose Abreu <Jose.Abreu@synopsys.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/pcs/pcs-xpcs.c
-+F: drivers/net/pcs/pcs-xpcs.h
-+F: include/linux/pcs/pcs-xpcs.h
-+
-+SYNOPSYS DESIGNWARE I2C DRIVER
-+M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+R: Mika Westerberg <mika.westerberg@linux.intel.com>
-+L: linux-i2c@vger.kernel.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-designware-*
-+
-+SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
-+M: Jaehoon Chung <jh80.chung@samsung.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/dw_mmc*
-+
-+SYNOPSYS HSDK RESET CONTROLLER DRIVER
-+M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
-+S: Supported
-+F: Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt
-+F: drivers/reset/reset-hsdk.c
-+F: include/dt-bindings/reset/snps,hsdk-reset.h
-+
-+SYNOPSYS SDHCI COMPLIANT DWC MSHC DRIVER
-+M: Prabu Thangamuthu <prabu.t@synopsys.com>
-+M: Manjunath M B <manjumb@synopsys.com>
-+L: linux-mmc@vger.kernel.org
-+S: Maintained
-+F: drivers/mmc/host/sdhci-pci-dwc-mshc.c
-+
-+SYSTEM CONFIGURATION (SYSCON)
-+M: Lee Jones <lee.jones@linaro.org>
-+M: Arnd Bergmann <arnd@arndb.de>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
-+F: drivers/mfd/syscon.c
-+
-+SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
-+M: Sudeep Holla <sudeep.holla@arm.com>
-+R: Cristian Marussi <cristian.marussi@arm.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/firmware/arm,sc[mp]i.yaml
-+F: drivers/clk/clk-sc[mp]i.c
-+F: drivers/cpufreq/sc[mp]i-cpufreq.c
-+F: drivers/firmware/arm_scmi/
-+F: drivers/firmware/arm_scpi.c
-+F: drivers/regulator/scmi-regulator.c
-+F: drivers/reset/reset-scmi.c
-+F: include/linux/sc[mp]i_protocol.h
-+F: include/trace/events/scmi.h
-+F: include/uapi/linux/virtio_scmi.h
-+
-+SYSTEM RESET/SHUTDOWN DRIVERS
-+M: Sebastian Reichel <sre@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git
-+F: Documentation/devicetree/bindings/power/reset/
-+F: drivers/power/reset/
-+
-+SYSTEM TRACE MODULE CLASS
-+M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm.git
-+F: Documentation/trace/stm.rst
-+F: drivers/hwtracing/stm/
-+F: include/linux/stm.h
-+F: include/uapi/linux/stm.h
-+
-+SYSTEM76 ACPI DRIVER
-+M: Jeremy Soller <jeremy@system76.com>
-+M: System76 Product Development <productdev@system76.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/system76_acpi.c
-+
-+SYSV FILESYSTEM
-+M: Christoph Hellwig <hch@infradead.org>
-+S: Maintained
-+F: Documentation/filesystems/sysv-fs.rst
-+F: fs/sysv/
-+F: include/linux/sysv_fs.h
-+
-+TASKSTATS STATISTICS INTERFACE
-+M: Balbir Singh <bsingharora@gmail.com>
-+S: Maintained
-+F: Documentation/accounting/taskstats*
-+F: include/linux/taskstats*
-+F: kernel/taskstats.c
-+
-+TC subsystem
-+M: Jamal Hadi Salim <jhs@mojatatu.com>
-+M: Cong Wang <xiyou.wangcong@gmail.com>
-+M: Jiri Pirko <jiri@resnulli.us>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: include/net/pkt_cls.h
-+F: include/net/pkt_sched.h
-+F: include/net/tc_act/
-+F: include/uapi/linux/pkt_cls.h
-+F: include/uapi/linux/pkt_sched.h
-+F: include/uapi/linux/tc_act/
-+F: include/uapi/linux/tc_ematch/
-+F: net/sched/
-+
-+TC90522 MEDIA DRIVER
-+M: Akihiro Tsukada <tskd08@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/media/dvb-frontends/tc90522*
-+
-+TCP LOW PRIORITY MODULE
-+M: "Wong Hoi Sing, Edison" <hswong3i@gmail.com>
-+M: "Hung Hing Lun, Mike" <hlhung3i@gmail.com>
-+S: Maintained
-+W: http://tcp-lp-mod.sourceforge.net/
-+F: net/ipv4/tcp_lp.c
-+
-+TDA10071 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/dvb-frontends/tda10071*
-+
-+TDA18212 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/tda18212*
-+
-+TDA18218 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/tda18218*
-+
-+TDA18250 MEDIA DRIVER
-+M: Olli Salonen <olli.salonen@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/tuners/tda18250*
-+
-+TDA18271 MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/tuners/tda18271*
-+
-+TDA1997x MEDIA DRIVER
-+M: Tim Harvey <tharvey@gateworks.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/i2c/tda1997x.*
-+
-+TDA827x MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/tuners/tda8290.*
-+
-+TDA8290 MEDIA DRIVER
-+M: Michael Krufky <mkrufky@linuxtv.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://github.com/mkrufky
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mkrufky/tuners.git
-+F: drivers/media/tuners/tda8290.*
-+
-+TDA9840 MEDIA DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/tda9840*
-+
-+TEA5761 TUNER DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/tuners/tea5761.*
-+
-+TEA5767 TUNER DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/tuners/tea5767.*
-+
-+TEA6415C MEDIA DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/tea6415c*
-+
-+TEA6420 MEDIA DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/i2c/tea6420*
-+
-+TEAM DRIVER
-+M: Jiri Pirko <jiri@resnulli.us>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/team/
-+F: include/linux/if_team.h
-+F: include/uapi/linux/if_team.h
-+
-+TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
-+M: "Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
-+S: Maintained
-+F: arch/x86/platform/ts5500/
-+
-+TECHNOTREND USB IR RECEIVER
-+M: Sean Young <sean@mess.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/rc/ttusbir.c
-+
-+TECHWELL TW9910 VIDEO DECODER
-+L: linux-media@vger.kernel.org
-+S: Orphan
-+F: drivers/media/i2c/tw9910.c
-+F: include/media/i2c/tw9910.h
-+
-+TEE SUBSYSTEM
-+M: Jens Wiklander <jens.wiklander@linaro.org>
-+R: Sumit Garg <sumit.garg@linaro.org>
-+L: op-tee@lists.trustedfirmware.org
-+S: Maintained
-+F: Documentation/staging/tee.rst
-+F: drivers/tee/
-+F: include/linux/tee_drv.h
-+F: include/uapi/linux/tee.h
-+
-+TEGRA ARCHITECTURE SUPPORT
-+M: Thierry Reding <thierry.reding@gmail.com>
-+M: Jonathan Hunter <jonathanh@nvidia.com>
-+L: linux-tegra@vger.kernel.org
-+S: Supported
-+Q: http://patchwork.ozlabs.org/project/linux-tegra/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git
-+N: [^a-z]tegra
-+
-+TEGRA CLOCK DRIVER
-+M: Peter De Schrijver <pdeschrijver@nvidia.com>
-+M: Prashant Gaikwad <pgaikwad@nvidia.com>
-+S: Supported
-+F: drivers/clk/tegra/
-+
-+TEGRA DMA DRIVERS
-+M: Laxman Dewangan <ldewangan@nvidia.com>
-+M: Jon Hunter <jonathanh@nvidia.com>
-+S: Supported
-+F: drivers/dma/tegra*
-+
-+TEGRA I2C DRIVER
-+M: Laxman Dewangan <ldewangan@nvidia.com>
-+R: Dmitry Osipenko <digetx@gmail.com>
-+S: Supported
-+F: drivers/i2c/busses/i2c-tegra.c
-+
-+TEGRA IOMMU DRIVERS
-+M: Thierry Reding <thierry.reding@gmail.com>
-+R: Krishna Reddy <vdumpa@nvidia.com>
-+L: linux-tegra@vger.kernel.org
-+S: Supported
-+F: drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
-+F: drivers/iommu/tegra*
-+
-+TEGRA KBC DRIVER
-+M: Laxman Dewangan <ldewangan@nvidia.com>
-+S: Supported
-+F: drivers/input/keyboard/tegra-kbc.c
-+
-+TEGRA NAND DRIVER
-+M: Stefan Agner <stefan@agner.ch>
-+M: Lucas Stach <dev@lynxeye.de>
-+S: Maintained
-+F: Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt
-+F: drivers/mtd/nand/raw/tegra_nand.c
-+
-+TEGRA PWM DRIVER
-+M: Thierry Reding <thierry.reding@gmail.com>
-+S: Supported
-+F: drivers/pwm/pwm-tegra.c
-+
-+TEGRA SERIAL DRIVER
-+M: Laxman Dewangan <ldewangan@nvidia.com>
-+S: Supported
-+F: drivers/tty/serial/serial-tegra.c
-+
-+TEGRA SPI DRIVER
-+M: Laxman Dewangan <ldewangan@nvidia.com>
-+S: Supported
-+F: drivers/spi/spi-tegra*
-+
-+TEGRA QUAD SPI DRIVER
-+M: Thierry Reding <thierry.reding@gmail.com>
-+M: Jonathan Hunter <jonathanh@nvidia.com>
-+M: Sowjanya Komatineni <skomatineni@nvidia.com>
-+L: linux-tegra@vger.kernel.org
-+S: Maintained
-+F: drivers/spi/spi-tegra210-quad.c
-+
-+TEGRA VIDEO DRIVER
-+M: Thierry Reding <thierry.reding@gmail.com>
-+M: Jonathan Hunter <jonathanh@nvidia.com>
-+M: Sowjanya Komatineni <skomatineni@nvidia.com>
-+L: linux-media@vger.kernel.org
-+L: linux-tegra@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
-+F: drivers/staging/media/tegra-video/
-+
-+TEGRA XUSB PADCTL DRIVER
-+M: JC Kuo <jckuo@nvidia.com>
-+S: Supported
-+F: drivers/phy/tegra/xusb*
-+
-+TEHUTI ETHERNET DRIVER
-+M: Andy Gospodarek <andy@greyhouse.net>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/ethernet/tehuti/*
-+
-+TELECOM CLOCK DRIVER FOR MCPL0010
-+M: Mark Gross <mark.gross@intel.com>
-+S: Supported
-+F: drivers/char/tlclk.c
-+
-+TEMPO SEMICONDUCTOR DRIVERS
-+M: Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/tscs*.txt
-+F: sound/soc/codecs/tscs*.c
-+F: sound/soc/codecs/tscs*.h
-+
-+TENSILICA XTENSA PORT (xtensa)
-+M: Chris Zankel <chris@zankel.net>
-+M: Max Filippov <jcmvbkbc@gmail.com>
-+L: linux-xtensa@linux-xtensa.org
-+S: Maintained
-+T: git git://github.com/czankel/xtensa-linux.git
-+F: arch/xtensa/
-+F: drivers/irqchip/irq-xtensa-*
-+
-+TEXAS INSTRUMENTS ASoC DRIVERS
-+M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: sound/soc/ti/
-+
-+TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
-+M: Ricardo Ribalda <ribalda@kernel.org>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
-+F: drivers/iio/dac/ti-dac7612.c
-+
-+TEXAS INSTRUMENTS DMA DRIVERS
-+M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
-+L: dmaengine@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt
-+F: Documentation/devicetree/bindings/dma/ti-edma.txt
-+F: Documentation/devicetree/bindings/dma/ti/
-+F: drivers/dma/ti/
-+X: drivers/dma/ti/cppi41.c
-+F: include/linux/dma/k3-udma-glue.h
-+F: include/linux/dma/ti-cppi5.h
-+F: include/linux/dma/k3-psil.h
-+
-+TEXAS INSTRUMENTS' SYSTEM CONTROL INTERFACE (TISCI) PROTOCOL DRIVER
-+M: Nishanth Menon <nm@ti.com>
-+M: Tero Kristo <kristo@kernel.org>
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/arm/keystone/ti,k3-sci-common.yaml
-+F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
-+F: Documentation/devicetree/bindings/clock/ti,sci-clk.yaml
-+F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml
-+F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.yaml
-+F: Documentation/devicetree/bindings/reset/ti,sci-reset.yaml
-+F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml
-+F: drivers/clk/keystone/sci-clk.c
-+F: drivers/firmware/ti_sci*
-+F: drivers/irqchip/irq-ti-sci-inta.c
-+F: drivers/irqchip/irq-ti-sci-intr.c
-+F: drivers/reset/reset-ti-sci.c
-+F: drivers/soc/ti/ti_sci_inta_msi.c
-+F: drivers/soc/ti/ti_sci_pm_domains.c
-+F: include/dt-bindings/soc/ti,sci_pm_domain.h
-+F: include/linux/soc/ti/ti_sci_inta_msi.h
-+F: include/linux/soc/ti/ti_sci_protocol.h
-+
-+TEXAS INSTRUMENTS TPS23861 PoE PSE DRIVER
-+M: Robert Marko <robert.marko@sartura.hr>
-+M: Luka Perkov <luka.perkov@sartura.hr>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/hwmon/ti,tps23861.yaml
-+F: Documentation/hwmon/tps23861.rst
-+F: drivers/hwmon/tps23861.c
-+
-+TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER
-+M: Puranjay Mohan <puranjay12@gmail.com>
-+L: linux-iio@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml
-+F: drivers/iio/temperature/tmp117.c
-+
-+THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/radio/radio-raremono.c
-+
-+THERMAL
-+M: Rafael J. Wysocki <rafael@kernel.org>
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+R: Amit Kucheria <amitk@kernel.org>
-+R: Zhang Rui <rui.zhang@intel.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-pm/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git thermal
-+F: Documentation/devicetree/bindings/thermal/
-+F: drivers/thermal/
-+F: include/linux/cpu_cooling.h
-+F: include/linux/thermal.h
-+F: include/uapi/linux/thermal.h
-+F: tools/thermal/
-+
-+THERMAL DRIVER FOR AMLOGIC SOCS
-+M: Guillaume La Roque <glaroque@baylibre.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-amlogic@lists.infradead.org
-+S: Supported
-+W: http://linux-meson.com/
-+F: Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
-+F: drivers/thermal/amlogic_thermal.c
-+
-+THERMAL/CPU_COOLING
-+M: Amit Daniel Kachhap <amit.kachhap@gmail.com>
-+M: Daniel Lezcano <daniel.lezcano@linaro.org>
-+M: Viresh Kumar <viresh.kumar@linaro.org>
-+R: Lukasz Luba <lukasz.luba@arm.com>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+F: Documentation/driver-api/thermal/cpu-cooling-api.rst
-+F: Documentation/driver-api/thermal/cpu-idle-cooling.rst
-+F: drivers/thermal/cpufreq_cooling.c
-+F: drivers/thermal/cpuidle_cooling.c
-+F: include/linux/cpu_cooling.h
-+
-+THERMAL/POWER_ALLOCATOR
-+M: Lukasz Luba <lukasz.luba@arm.com>
-+L: linux-pm@vger.kernel.org
-+S: Maintained
-+F: Documentation/driver-api/thermal/power_allocator.rst
-+F: drivers/thermal/gov_power_allocator.c
-+F: include/trace/events/thermal_power_allocator.h
-+
-+THINKPAD ACPI EXTRAS DRIVER
-+M: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
-+L: ibm-acpi-devel@lists.sourceforge.net
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+W: http://ibm-acpi.sourceforge.net
-+W: http://thinkwiki.org/wiki/Ibm-acpi
-+T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
-+F: drivers/platform/x86/thinkpad_acpi.c
-+
-+THINKPAD LMI DRIVER
-+M: Mark Pearson <markpearson@lenovo.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-firmware-attributes
-+F: drivers/platform/x86/think-lmi.?
-+
-+THUNDERBOLT DMA TRAFFIC TEST DRIVER
-+M: Isaac Hazan <isaac.hazan@intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/thunderbolt/dma_test.c
-+
-+THUNDERBOLT DRIVER
-+M: Andreas Noever <andreas.noever@gmail.com>
-+M: Michael Jamet <michael.jamet@intel.com>
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+M: Yehezkel Bernat <YehezkelShB@gmail.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
-+F: Documentation/admin-guide/thunderbolt.rst
-+F: drivers/thunderbolt/
-+F: include/linux/thunderbolt.h
-+
-+THUNDERBOLT NETWORK DRIVER
-+M: Michael Jamet <michael.jamet@intel.com>
-+M: Mika Westerberg <mika.westerberg@linux.intel.com>
-+M: Yehezkel Bernat <YehezkelShB@gmail.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/thunderbolt.c
-+
-+THUNDERX GPIO DRIVER
-+M: Robert Richter <rric@kernel.org>
-+S: Odd Fixes
-+F: drivers/gpio/gpio-thunderx.c
-+
-+TI ADS131E0X ADC SERIES DRIVER
-+M: Tomislav Denis <tomislav.denis@avl.com>
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/adc/ti,ads131e08.yaml
-+F: drivers/iio/adc/ti-ads131e08.c
-+
-+TI AM437X VPFE DRIVER
-+M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
-+F: drivers/media/platform/am437x/
-+
-+TI BANDGAP AND THERMAL DRIVER
-+M: Eduardo Valentin <edubezval@gmail.com>
-+M: Keerthy <j-keerthy@ti.com>
-+L: linux-pm@vger.kernel.org
-+L: linux-omap@vger.kernel.org
-+S: Maintained
-+F: drivers/thermal/ti-soc-thermal/
-+
-+TI BQ27XXX POWER SUPPLY DRIVER
-+F: drivers/power/supply/bq27xxx_battery.c
-+F: drivers/power/supply/bq27xxx_battery_i2c.c
-+F: include/linux/power/bq27xxx_battery.h
-+
-+TI CDCE706 CLOCK DRIVER
-+M: Max Filippov <jcmvbkbc@gmail.com>
-+S: Maintained
-+F: drivers/clk/clk-cdce706.c
-+
-+TI CLOCK DRIVER
-+M: Tero Kristo <kristo@kernel.org>
-+L: linux-omap@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/clk/ti/
-+F: include/linux/clk/ti.h
-+
-+TI DAVINCI MACHINE SUPPORT
-+M: Sekhar Nori <nsekhar@ti.com>
-+R: Bartosz Golaszewski <brgl@bgdev.pl>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
-+F: Documentation/devicetree/bindings/i2c/i2c-davinci.txt
-+F: arch/arm/boot/dts/da850*
-+F: arch/arm/mach-davinci/
-+F: drivers/i2c/busses/i2c-davinci.c
-+
-+TI DAVINCI SERIES CLOCK DRIVER
-+M: David Lechner <david@lechnology.com>
-+R: Sekhar Nori <nsekhar@ti.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/clock/ti/davinci/
-+F: drivers/clk/davinci/
-+
-+TI DAVINCI SERIES GPIO DRIVER
-+M: Keerthy <j-keerthy@ti.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/gpio-davinci.yaml
-+F: drivers/gpio/gpio-davinci.c
-+
-+TI DAVINCI SERIES MEDIA DRIVER
-+M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
-+F: drivers/media/platform/davinci/
-+F: include/media/davinci/
-+
-+TI ENHANCED QUADRATURE ENCODER PULSE (eQEP) DRIVER
-+R: David Lechner <david@lechnology.com>
-+L: linux-iio@vger.kernel.org
-+F: Documentation/devicetree/bindings/counter/ti-eqep.yaml
-+F: drivers/counter/ti-eqep.c
-+
-+TI ETHERNET SWITCH DRIVER (CPSW)
-+R: Grygorii Strashko <grygorii.strashko@ti.com>
-+L: linux-omap@vger.kernel.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/ti/cpsw*
-+F: drivers/net/ethernet/ti/davinci*
-+
-+TI FLASH MEDIA MEMORYSTICK/MMC DRIVERS
-+M: Alex Dubov <oakad@yahoo.com>
-+S: Maintained
-+W: http://tifmxx.berlios.de/
-+F: drivers/memstick/host/tifm_ms.c
-+F: drivers/misc/tifm*
-+F: drivers/mmc/host/tifm_sd.c
-+F: include/linux/tifm.h
-+
-+TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
-+M: Santosh Shilimkar <ssantosh@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
-+F: drivers/soc/ti/*
-+
-+TI LM49xxx FAMILY ASoC CODEC DRIVERS
-+M: M R Swami Reddy <mr.swami.reddy@ti.com>
-+M: Vishwas A Deshpande <vishwas.a.deshpande@ti.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: sound/soc/codecs/isabelle*
-+F: sound/soc/codecs/lm49453*
-+
-+TI PCM3060 ASoC CODEC DRIVER
-+M: Kirill Marinushkin <kmarinushkin@birdec.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: Documentation/devicetree/bindings/sound/pcm3060.txt
-+F: sound/soc/codecs/pcm3060*
-+
-+TI TAS571X FAMILY ASoC CODEC DRIVER
-+M: Kevin Cernekee <cernekee@chromium.org>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Odd Fixes
-+F: sound/soc/codecs/tas571x*
-+
-+TI TRF7970A NFC DRIVER
-+M: Mark Greer <mgreer@animalcreek.com>
-+L: linux-wireless@vger.kernel.org
-+L: linux-nfc@lists.01.org (subscribers-only)
-+S: Supported
-+F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
-+F: drivers/nfc/trf7970a.c
-+
-+TI TSC2046 ADC DRIVER
-+M: Oleksij Rempel <o.rempel@pengutronix.de>
-+R: kernel@pengutronix.de
-+L: linux-iio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
-+F: drivers/iio/adc/ti-tsc2046.c
-+
-+TI TWL4030 SERIES SOC CODEC DRIVER
-+M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: sound/soc/codecs/twl4030*
-+
-+TI VPE/CAL DRIVERS
-+M: Benoit Parrot <bparrot@ti.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://linuxtv.org/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+F: Documentation/devicetree/bindings/media/ti,cal.yaml
-+F: Documentation/devicetree/bindings/media/ti,vpe.yaml
-+F: drivers/media/platform/ti-vpe/
-+
-+TI WILINK WIRELESS DRIVERS
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
-+F: drivers/net/wireless/ti/
-+F: include/linux/wl12xx.h
-+
-+TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
-+M: John Stultz <john.stultz@linaro.org>
-+M: Thomas Gleixner <tglx@linutronix.de>
-+R: Stephen Boyd <sboyd@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
-+F: include/linux/clocksource.h
-+F: include/linux/time.h
-+F: include/linux/timex.h
-+F: include/uapi/linux/time.h
-+F: include/uapi/linux/timex.h
-+F: kernel/time/alarmtimer.c
-+F: kernel/time/clocksource.c
-+F: kernel/time/ntp.c
-+F: kernel/time/time*.c
-+F: tools/testing/selftests/timers/
-+
-+TIPC NETWORK LAYER
-+M: Jon Maloy <jmaloy@redhat.com>
-+M: Ying Xue <ying.xue@windriver.com>
-+L: netdev@vger.kernel.org (core kernel code)
-+L: tipc-discussion@lists.sourceforge.net (user apps, general discussion)
-+S: Maintained
-+W: http://tipc.sourceforge.net/
-+F: include/uapi/linux/tipc*.h
-+F: net/tipc/
-+
-+TLAN NETWORK DRIVER
-+M: Samuel Chessman <chessman@tux.org>
-+L: tlan-devel@lists.sourceforge.net (subscribers-only)
-+S: Maintained
-+W: http://sourceforge.net/projects/tlan/
-+F: Documentation/networking/device_drivers/ethernet/ti/tlan.rst
-+F: drivers/net/ethernet/ti/tlan.*
-+
-+TM6000 VIDEO4LINUX DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Odd fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/tm6000*
-+F: drivers/media/usb/tm6000/
-+
-+TMIO/SDHI MMC DRIVER
-+M: Wolfram Sang <wsa+renesas@sang-engineering.com>
-+L: linux-mmc@vger.kernel.org
-+S: Supported
-+F: drivers/mmc/host/renesas_sdhi*
-+F: drivers/mmc/host/tmio_mmc*
-+F: include/linux/mfd/tmio.h
-+
-+TMP401 HARDWARE MONITOR DRIVER
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/tmp401.rst
-+F: drivers/hwmon/tmp401.c
-+
-+TMP513 HARDWARE MONITOR DRIVER
-+M: Eric Tremblay <etremblay@distech-controls.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/tmp513.rst
-+F: drivers/hwmon/tmp513.c
-+
-+TMPFS (SHMEM FILESYSTEM)
-+M: Hugh Dickins <hughd@google.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: include/linux/shmem_fs.h
-+F: mm/shmem.c
-+
-+TOMOYO SECURITY MODULE
-+M: Kentaro Takeda <takedakn@nttdata.co.jp>
-+M: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
-+L: tomoyo-dev-en@lists.osdn.me (subscribers-only, for developers in English)
-+L: tomoyo-users-en@lists.osdn.me (subscribers-only, for users in English)
-+L: tomoyo-dev@lists.osdn.me (subscribers-only, for developers in Japanese)
-+L: tomoyo-users@lists.osdn.me (subscribers-only, for users in Japanese)
-+S: Maintained
-+W: https://tomoyo.osdn.jp/
-+F: security/tomoyo/
-+
-+TOPSTAR LAPTOP EXTRAS DRIVER
-+M: Herton Ronaldo Krzesinski <herton@canonical.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/topstar-laptop.c
-+
-+TORTURE-TEST MODULES
-+M: Davidlohr Bueso <dave@stgolabs.net>
-+M: "Paul E. McKenney" <paulmck@kernel.org>
-+M: Josh Triplett <josh@joshtriplett.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
-+F: Documentation/RCU/torture.rst
-+F: kernel/locking/locktorture.c
-+F: kernel/rcu/rcuscale.c
-+F: kernel/rcu/rcutorture.c
-+F: kernel/rcu/refscale.c
-+F: kernel/torture.c
-+
-+TOSHIBA ACPI EXTRAS DRIVER
-+M: Azael Avalos <coproscefalo@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/toshiba_acpi.c
-+
-+TOSHIBA BLUETOOTH DRIVER
-+M: Azael Avalos <coproscefalo@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/toshiba_bluetooth.c
-+
-+TOSHIBA HDD ACTIVE PROTECTION SENSOR DRIVER
-+M: Azael Avalos <coproscefalo@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/toshiba_haps.c
-+
-+TOSHIBA SMM DRIVER
-+M: Jonathan Buzzard <jonathan@buzzard.org.uk>
-+S: Maintained
-+W: http://www.buzzard.org.uk/toshiba/
-+F: drivers/char/toshiba.c
-+F: include/linux/toshiba.h
-+F: include/uapi/linux/toshiba.h
-+
-+TOSHIBA TC358743 DRIVER
-+M: Mats Randgaard <matrandg@cisco.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/tc358743*
-+F: include/media/i2c/tc358743.h
-+
-+TOSHIBA WMI HOTKEYS DRIVER
-+M: Azael Avalos <coproscefalo@gmail.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/toshiba-wmi.c
-+
-+TPM DEVICE DRIVER
-+M: Peter Huewe <peterhuewe@gmx.de>
-+M: Jarkko Sakkinen <jarkko@kernel.org>
-+R: Jason Gunthorpe <jgg@ziepe.ca>
-+L: linux-integrity@vger.kernel.org
-+S: Maintained
-+W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity
-+Q: https://patchwork.kernel.org/project/linux-integrity/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git
-+F: drivers/char/tpm/
-+
-+TRACING
-+M: Steven Rostedt <rostedt@goodmis.org>
-+M: Ingo Molnar <mingo@redhat.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
-+F: Documentation/trace/ftrace.rst
-+F: arch/*/*/*/ftrace.h
-+F: arch/*/kernel/ftrace.c
-+F: fs/tracefs/
-+F: include/*/ftrace.h
-+F: include/linux/trace*.h
-+F: include/trace/
-+F: kernel/trace/
-+F: tools/testing/selftests/ftrace/
-+
-+TRACING MMIO ACCESSES (MMIOTRACE)
-+M: Steven Rostedt <rostedt@goodmis.org>
-+M: Ingo Molnar <mingo@kernel.org>
-+R: Karol Herbst <karolherbst@gmail.com>
-+R: Pekka Paalanen <ppaalanen@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+L: nouveau@lists.freedesktop.org
-+S: Maintained
-+F: arch/x86/mm/kmmio.c
-+F: arch/x86/mm/mmio-mod.c
-+F: arch/x86/mm/testmmiotrace.c
-+F: include/linux/mmiotrace.h
-+F: kernel/trace/trace_mmiotrace.c
-+
-+TRACING OS NOISE / LATENCY TRACERS
-+M: Steven Rostedt <rostedt@goodmis.org>
-+M: Daniel Bristot de Oliveira <bristot@kernel.org>
-+S: Maintained
-+F: kernel/trace/trace_osnoise.c
-+F: include/trace/events/osnoise.h
-+F: kernel/trace/trace_hwlat.c
-+F: kernel/trace/trace_irqsoff.c
-+F: kernel/trace/trace_sched_wakeup.c
-+F: Documentation/trace/osnoise-tracer.rst
-+F: Documentation/trace/timerlat-tracer.rst
-+F: Documentation/trace/hwlat_detector.rst
-+F: arch/*/kernel/trace.c
-+
-+TRADITIONAL CHINESE DOCUMENTATION
-+M: Hu Haowen <src.res@email.cn>
-+L: linux-doc-tw-discuss@lists.sourceforge.net
-+S: Maintained
-+W: https://github.com/srcres258/linux-doc
-+T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
-+F: Documentation/translations/zh_TW/
-+
-+TRIVIAL PATCHES
-+M: Jiri Kosina <trivial@kernel.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
-+K: ^Subject:.*(?i)trivial
-+
-+TTY LAYER
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+M: Jiri Slaby <jirislaby@kernel.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
-+F: Documentation/driver-api/serial/
-+F: drivers/tty/
-+F: drivers/tty/serial/serial_core.c
-+F: include/linux/selection.h
-+F: include/linux/serial.h
-+F: include/linux/serial_core.h
-+F: include/linux/sysrq.h
-+F: include/linux/tty*.h
-+F: include/linux/vt.h
-+F: include/linux/vt_*.h
-+F: include/uapi/linux/serial.h
-+F: include/uapi/linux/serial_core.h
-+F: include/uapi/linux/tty.h
-+
-+TUA9001 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+W: http://palosaari.fi/linux/
-+Q: http://patchwork.linuxtv.org/project/linux-media/list/
-+T: git git://linuxtv.org/anttip/media_tree.git
-+F: drivers/media/tuners/tua9001*
-+
-+TULIP NETWORK DRIVERS
-+L: netdev@vger.kernel.org
-+L: linux-parisc@vger.kernel.org
-+S: Orphan
-+F: drivers/net/ethernet/dec/tulip/
-+
-+TUN/TAP driver
-+M: Maxim Krasnyansky <maxk@qti.qualcomm.com>
-+S: Maintained
-+W: http://vtun.sourceforge.net/tun
-+F: Documentation/networking/tuntap.rst
-+F: arch/um/os-Linux/drivers/
-+
-+TURBOCHANNEL SUBSYSTEM
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+M: Ralf Baechle <ralf@linux-mips.org>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+Q: http://patchwork.linux-mips.org/project/linux-mips/list/
-+F: drivers/tc/
-+F: include/linux/tc.h
-+
-+TURBOSTAT UTILITY
-+M: "Len Brown" <lenb@kernel.org>
-+L: linux-pm@vger.kernel.org
-+S: Supported
-+Q: https://patchwork.kernel.org/project/linux-pm/list/
-+B: https://bugzilla.kernel.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git turbostat
-+F: tools/power/x86/turbostat/
-+
-+TW5864 VIDEO4LINUX DRIVER
-+M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
-+M: Anton Sviridenko <anton@corp.bluecherry.net>
-+M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
-+M: Andrey Utkin <andrey_utkin@fastmail.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/pci/tw5864/
-+
-+TW68 VIDEO4LINUX DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Odd Fixes
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/tw68/
-+
-+TW686X VIDEO4LINUX DRIVER
-+M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/pci/tw686x/
-+
-+UACCE ACCELERATOR FRAMEWORK
-+M: Zhangfei Gao <zhangfei.gao@linaro.org>
-+M: Zhou Wang <wangzhou1@hisilicon.com>
-+L: linux-accelerators@lists.ozlabs.org
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-driver-uacce
-+F: Documentation/misc-devices/uacce.rst
-+F: drivers/misc/uacce/
-+F: include/linux/uacce.h
-+F: include/uapi/misc/uacce/
-+
-+UBI FILE SYSTEM (UBIFS)
-+M: Richard Weinberger <richard@nod.at>
-+L: linux-mtd@lists.infradead.org
-+S: Supported
-+W: http://www.linux-mtd.infradead.org/doc/ubifs.html
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
-+F: Documentation/filesystems/ubifs-authentication.rst
-+F: Documentation/filesystems/ubifs.rst
-+F: fs/ubifs/
-+
-+UCLINUX (M68KNOMMU AND COLDFIRE)
-+M: Greg Ungerer <gerg@linux-m68k.org>
-+L: linux-m68k@lists.linux-m68k.org
-+L: uclinux-dev@uclinux.org (subscribers-only)
-+S: Maintained
-+W: http://www.linux-m68k.org/
-+W: http://www.uclinux.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git
-+F: arch/m68k/*/*_no.*
-+F: arch/m68k/68*/
-+F: arch/m68k/coldfire/
-+F: arch/m68k/include/asm/*_no.*
-+
-+UDF FILESYSTEM
-+M: Jan Kara <jack@suse.com>
-+S: Maintained
-+F: Documentation/filesystems/udf.rst
-+F: fs/udf/
-+
-+UDRAW TABLET
-+M: Bastien Nocera <hadess@hadess.net>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-udraw-ps3.c
-+
-+UFS FILESYSTEM
-+M: Evgeniy Dushistov <dushistov@mail.ru>
-+S: Maintained
-+F: Documentation/admin-guide/ufs.rst
-+F: fs/ufs/
-+
-+UHID USERSPACE HID IO DRIVER
-+M: David Rheinsberg <david.rheinsberg@gmail.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/uhid.c
-+F: include/uapi/linux/uhid.h
-+
-+ULPI BUS
-+M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/common/ulpi.c
-+F: include/linux/ulpi/
-+
-+UNICODE SUBSYSTEM
-+M: Gabriel Krisman Bertazi <krisman@collabora.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Supported
-+F: fs/unicode/
-+
-+UNIFDEF
-+M: Tony Finch <dot@dotat.at>
-+S: Maintained
-+W: http://dotat.at/prog/unifdef
-+F: scripts/unifdef.c
-+
-+UNIFORM CDROM DRIVER
-+M: Phillip Potter <phil@philpotter.co.uk>
-+S: Maintained
-+F: Documentation/cdrom/
-+F: drivers/cdrom/cdrom.c
-+F: include/linux/cdrom.h
-+F: include/uapi/linux/cdrom.h
-+
-+UNISYS S-PAR DRIVERS
-+M: David Kershner <david.kershner@unisys.com>
-+L: sparmaintainer@unisys.com (Unisys internal)
-+S: Supported
-+F: drivers/staging/unisys/
-+F: drivers/visorbus/
-+F: include/linux/visorbus.h
-+
-+UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
-+R: Alim Akhtar <alim.akhtar@samsung.com>
-+R: Avri Altman <avri.altman@wdc.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: Documentation/scsi/ufs.rst
-+F: drivers/scsi/ufs/
-+
-+UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS
-+M: Pedro Sousa <pedrom.sousa@synopsys.com>
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/ufs/*dwc*
-+
-+UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER MEDIATEK HOOKS
-+M: Stanley Chu <stanley.chu@mediatek.com>
-+L: linux-scsi@vger.kernel.org
-+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/scsi/ufs/ufs-mediatek*
-+
-+UNSORTED BLOCK IMAGES (UBI)
-+M: Richard Weinberger <richard@nod.at>
-+L: linux-mtd@lists.infradead.org
-+S: Supported
-+W: http://www.linux-mtd.infradead.org/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
-+F: drivers/mtd/ubi/
-+F: include/linux/mtd/ubi.h
-+F: include/uapi/mtd/ubi-user.h
-+
-+USB "USBNET" DRIVER FRAMEWORK
-+M: Oliver Neukum <oneukum@suse.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-usb.org/usbnet
-+F: drivers/net/usb/usbnet.c
-+F: include/linux/usb/usbnet.h
-+
-+USB ACM DRIVER
-+M: Oliver Neukum <oneukum@suse.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/usb/acm.rst
-+F: drivers/usb/class/cdc-acm.*
-+
-+USB APPLE MFI FASTCHARGE DRIVER
-+M: Bastien Nocera <hadess@hadess.net>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/misc/apple-mfi-fastcharge.c
-+
-+USB AR5523 WIRELESS DRIVER
-+M: Pontus Fuchs <pontus.fuchs@gmail.com>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/ath/ar5523/
-+
-+USB ATTACHED SCSI
-+M: Oliver Neukum <oneukum@suse.com>
-+L: linux-usb@vger.kernel.org
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/storage/uas.c
-+
-+USB CDC ETHERNET DRIVER
-+M: Oliver Neukum <oliver@neukum.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/net/usb/cdc_*.c
-+F: include/uapi/linux/usb/cdc.h
-+
-+USB CHAOSKEY DRIVER
-+M: Keith Packard <keithp@keithp.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/misc/chaoskey.c
-+
-+USB CYPRESS C67X00 DRIVER
-+L: linux-usb@vger.kernel.org
-+S: Orphan
-+F: drivers/usb/c67x00/
-+
-+USB DAVICOM DM9601 DRIVER
-+M: Peter Korsgaard <peter@korsgaard.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-usb.org/usbnet
-+F: drivers/net/usb/dm9601.c
-+
-+USB EHCI DRIVER
-+M: Alan Stern <stern@rowland.harvard.edu>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/usb/ehci.rst
-+F: drivers/usb/host/ehci*
-+
-+USB GADGET/PERIPHERAL SUBSYSTEM
-+M: Felipe Balbi <balbi@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-usb.org/gadget
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-+F: drivers/usb/gadget/
-+F: include/linux/usb/gadget*
-+
-+USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
-+M: Jiri Kosina <jikos@kernel.org>
-+M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
-+F: Documentation/hid/hiddev.rst
-+F: drivers/hid/usbhid/
-+
-+USB INTEL XHCI ROLE MUX DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/roles/intel-xhci-usb-role-switch.c
-+
-+USB IP DRIVER FOR HISILICON KIRIN 960
-+M: Yu Chen <chenyu56@huawei.com>
-+M: Binghui Wang <wangbinghui@hisilicon.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
-+F: drivers/phy/hisilicon/phy-hi3660-usb3.c
-+
-+USB IP DRIVER FOR HISILICON KIRIN 970
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
-+F: drivers/phy/hisilicon/phy-hi3670-usb3.c
-+
-+USB ISP116X DRIVER
-+M: Olav Kongas <ok@artecdesign.ee>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/host/isp116x*
-+F: include/linux/usb/isp116x.h
-+
-+USB ISP1760 DRIVER
-+M: Rui Miguel Silva <rui.silva@linaro.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/isp1760/*
-+F: Documentation/devicetree/bindings/usb/nxp,isp1760.yaml
-+
-+USB LAN78XX ETHERNET DRIVER
-+M: Woojung Huh <woojung.huh@microchip.com>
-+M: UNGLinuxDriver@microchip.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/microchip,lan78xx.txt
-+F: drivers/net/usb/lan78xx.*
-+F: include/dt-bindings/net/microchip-lan78xx.h
-+
-+USB MASS STORAGE DRIVER
-+M: Alan Stern <stern@rowland.harvard.edu>
-+L: linux-usb@vger.kernel.org
-+L: usb-storage@lists.one-eyed-alien.net
-+S: Maintained
-+F: drivers/usb/storage/
-+
-+USB MIDI DRIVER
-+M: Clemens Ladisch <clemens@ladisch.de>
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-+F: sound/usb/midi.*
-+
-+USB NETWORKING DRIVERS
-+L: linux-usb@vger.kernel.org
-+S: Odd Fixes
-+F: drivers/net/usb/
-+
-+USB OHCI DRIVER
-+M: Alan Stern <stern@rowland.harvard.edu>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/usb/ohci.rst
-+F: drivers/usb/host/ohci*
-+
-+USB OTG FSM (Finite State Machine)
-+M: Peter Chen <peter.chen@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
-+F: drivers/usb/common/usb-otg-fsm.c
-+
-+USB OVER IP DRIVER
-+M: Valentina Manea <valentina.manea.m@gmail.com>
-+M: Shuah Khan <shuah@kernel.org>
-+M: Shuah Khan <skhan@linuxfoundation.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/usb/usbip_protocol.rst
-+F: drivers/usb/usbip/
-+F: tools/testing/selftests/drivers/usb/usbip/
-+F: tools/usb/usbip/
-+
-+USB PEGASUS DRIVER
-+M: Petko Manolov <petkan@nucleusys.com>
-+L: linux-usb@vger.kernel.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: https://github.com/petkan/pegasus
-+T: git git://github.com/petkan/pegasus.git
-+F: drivers/net/usb/pegasus.*
-+
-+USB PHY LAYER
-+M: Felipe Balbi <balbi@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-+F: drivers/usb/phy/
-+
-+USB PRINTER DRIVER (usblp)
-+M: Pete Zaitcev <zaitcev@redhat.com>
-+L: linux-usb@vger.kernel.org
-+S: Supported
-+F: drivers/usb/class/usblp.c
-+
-+USB RAW GADGET DRIVER
-+R: Andrey Konovalov <andreyknvl@gmail.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/usb/raw-gadget.rst
-+F: drivers/usb/gadget/legacy/raw_gadget.c
-+F: include/uapi/linux/usb/raw_gadget.h
-+
-+USB QMI WWAN NETWORK DRIVER
-+M: Bjørn Mork <bjorn@mork.no>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-net-qmi
-+F: drivers/net/usb/qmi_wwan.c
-+
-+USB RTL8150 DRIVER
-+M: Petko Manolov <petkan@nucleusys.com>
-+L: linux-usb@vger.kernel.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+W: https://github.com/petkan/rtl8150
-+T: git git://github.com/petkan/rtl8150.git
-+F: drivers/net/usb/rtl8150.c
-+
-+USB SERIAL SUBSYSTEM
-+M: Johan Hovold <johan@kernel.org>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial.git
-+F: Documentation/usb/usb-serial.rst
-+F: drivers/usb/serial/
-+F: include/linux/usb/serial.h
-+
-+USB SMSC75XX ETHERNET DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/usb/smsc75xx.*
-+
-+USB SMSC95XX ETHERNET DRIVER
-+M: Steve Glendinning <steve.glendinning@shawell.net>
-+M: UNGLinuxDriver@microchip.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/usb/smsc95xx.*
-+
-+USB SUBSYSTEM
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-usb@vger.kernel.org
-+S: Supported
-+W: http://www.linux-usb.org
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
-+F: Documentation/devicetree/bindings/usb/
-+F: Documentation/usb/
-+F: drivers/usb/
-+F: include/linux/usb.h
-+F: include/linux/usb/
-+
-+USB TYPEC BUS FOR ALTERNATE MODES
-+M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-bus-typec
-+F: Documentation/driver-api/usb/typec_bus.rst
-+F: drivers/usb/typec/altmodes/
-+F: include/linux/usb/typec_altmode.h
-+
-+USB TYPEC CLASS
-+M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/ABI/testing/sysfs-class-typec
-+F: Documentation/driver-api/usb/typec.rst
-+F: drivers/usb/typec/
-+F: include/linux/usb/typec.h
-+
-+USB TYPEC INTEL PMC MUX DRIVER
-+M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: Documentation/firmware-guide/acpi/intel-pmc-mux.rst
-+F: drivers/usb/typec/mux/intel_pmc_mux.c
-+
-+USB TYPEC PI3USB30532 MUX DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/typec/mux/pi3usb30532.c
-+
-+USB TYPEC PORT CONTROLLER DRIVERS
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/typec/tcpm/
-+
-+USB UHCI DRIVER
-+M: Alan Stern <stern@rowland.harvard.edu>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/host/uhci*
-+
-+USB VIDEO CLASS
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-uvc-devel@lists.sourceforge.net (subscribers-only)
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://www.ideasonboard.org/uvc/
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/usb/uvc/
-+F: include/uapi/linux/uvcvideo.h
-+
-+USB WEBCAM GADGET
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-usb@vger.kernel.org
-+S: Maintained
-+F: drivers/usb/gadget/function/*uvc*
-+F: drivers/usb/gadget/legacy/webcam.c
-+F: include/uapi/linux/usb/g_uvc.h
-+
-+USB WIRELESS RNDIS DRIVER (rndis_wlan)
-+M: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-+L: linux-wireless@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireless/rndis_wlan.c
-+
-+USB XHCI DRIVER
-+M: Mathias Nyman <mathias.nyman@intel.com>
-+L: linux-usb@vger.kernel.org
-+S: Supported
-+F: drivers/usb/host/pci-quirks*
-+F: drivers/usb/host/xhci*
-+
-+USB ZD1201 DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Orphan
-+W: http://linux-lc100020.sourceforge.net
-+F: drivers/net/wireless/zydas/zd1201.*
-+
-+USB ZR364XX DRIVER
-+M: Antoine Jacquet <royale@zerezo.com>
-+L: linux-usb@vger.kernel.org
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://royale.zerezo.com/zr364xx/
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/admin-guide/media/zr364xx*
-+F: drivers/media/usb/zr364xx/
-+
-+USER-MODE LINUX (UML)
-+M: Jeff Dike <jdike@addtoit.com>
-+M: Richard Weinberger <richard@nod.at>
-+M: Anton Ivanov <anton.ivanov@cambridgegreys.com>
-+L: linux-um@lists.infradead.org
-+S: Maintained
-+W: http://user-mode-linux.sourceforge.net
-+Q: https://patchwork.ozlabs.org/project/linux-um/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
-+F: Documentation/virt/uml/
-+F: arch/um/
-+F: arch/x86/um/
-+F: fs/hostfs/
-+
-+USERSPACE COPYIN/COPYOUT (UIOVEC)
-+M: Alexander Viro <viro@zeniv.linux.org.uk>
-+S: Maintained
-+F: include/linux/uio.h
-+F: lib/iov_iter.c
-+
-+USERSPACE DMA BUFFER DRIVER
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+L: dri-devel@lists.freedesktop.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/dma-buf/udmabuf.c
-+F: include/uapi/linux/udmabuf.h
-+
-+USERSPACE I/O (UIO)
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-+F: Documentation/driver-api/uio-howto.rst
-+F: drivers/uio/
-+F: include/linux/uio_driver.h
-+
-+UTIL-LINUX PACKAGE
-+M: Karel Zak <kzak@redhat.com>
-+L: util-linux@vger.kernel.org
-+S: Maintained
-+W: http://en.wikipedia.org/wiki/Util-linux
-+T: git git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git
-+
-+UUID HELPERS
-+M: Christoph Hellwig <hch@lst.de>
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.infradead.org/users/hch/uuid.git
-+F: include/linux/uuid.h
-+F: include/uapi/linux/uuid.h
-+F: lib/test_uuid.c
-+F: lib/uuid.c
-+
-+UV SYSFS DRIVER
-+M: Justin Ernst <justin.ernst@hpe.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+F: drivers/platform/x86/uv_sysfs.c
-+
-+UVESAFB DRIVER
-+M: Michal Januszewski <spock@gentoo.org>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+W: https://github.com/mjanusz/v86d
-+F: Documentation/fb/uvesafb.rst
-+F: drivers/video/fbdev/uvesafb.*
-+
-+Ux500 CLOCK DRIVERS
-+M: Ulf Hansson <ulf.hansson@linaro.org>
-+L: linux-clk@vger.kernel.org
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/clk/ux500/
-+
-+VF610 NAND DRIVER
-+M: Stefan Agner <stefan@agner.ch>
-+L: linux-mtd@lists.infradead.org
-+S: Supported
-+F: drivers/mtd/nand/raw/vf610_nfc.c
-+
-+VFAT/FAT/MSDOS FILESYSTEM
-+M: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-+S: Maintained
-+F: Documentation/filesystems/vfat.rst
-+F: fs/fat/
-+
-+VFIO DRIVER
-+M: Alex Williamson <alex.williamson@redhat.com>
-+R: Cornelia Huck <cohuck@redhat.com>
-+L: kvm@vger.kernel.org
-+S: Maintained
-+T: git git://github.com/awilliam/linux-vfio.git
-+F: Documentation/driver-api/vfio.rst
-+F: drivers/vfio/
-+F: include/linux/vfio.h
-+F: include/linux/vfio_pci_core.h
-+F: include/uapi/linux/vfio.h
-+
-+VFIO FSL-MC DRIVER
-+M: Diana Craciun <diana.craciun@oss.nxp.com>
-+L: kvm@vger.kernel.org
-+S: Maintained
-+F: drivers/vfio/fsl-mc/
-+
-+VFIO MEDIATED DEVICE DRIVERS
-+M: Kirti Wankhede <kwankhede@nvidia.com>
-+L: kvm@vger.kernel.org
-+S: Maintained
-+F: Documentation/driver-api/vfio-mediated-device.rst
-+F: drivers/vfio/mdev/
-+F: include/linux/mdev.h
-+F: samples/vfio-mdev/
-+
-+VFIO PLATFORM DRIVER
-+M: Eric Auger <eric.auger@redhat.com>
-+L: kvm@vger.kernel.org
-+S: Maintained
-+F: drivers/vfio/platform/
-+
-+VGA_SWITCHEROO
-+R: Lukas Wunner <lukas@wunner.de>
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: Documentation/gpu/vga-switcheroo.rst
-+F: drivers/gpu/vga/vga_switcheroo.c
-+F: include/linux/vga_switcheroo.h
-+
-+VIA RHINE NETWORK DRIVER
-+S: Maintained
-+M: Kevin Brace <kevinbrace@bracecomputerlab.com>
-+F: drivers/net/ethernet/via/via-rhine.c
-+
-+VIA SD/MMC CARD CONTROLLER DRIVER
-+M: Bruce Chang <brucechang@via.com.tw>
-+M: Harald Welte <HaraldWelte@viatech.com>
-+S: Maintained
-+F: drivers/mmc/host/via-sdmmc.c
-+
-+VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
-+M: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-+L: linux-fbdev@vger.kernel.org
-+S: Maintained
-+F: drivers/video/fbdev/via/
-+F: include/linux/via-core.h
-+F: include/linux/via-gpio.h
-+F: include/linux/via_i2c.h
-+
-+VIA VELOCITY NETWORK DRIVER
-+M: Francois Romieu <romieu@fr.zoreil.com>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/ethernet/via/via-velocity.*
-+
-+VICODEC VIRTUAL CODEC DRIVER
-+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/test-drivers/vicodec/*
-+
-+VIDEO I2C POLLING DRIVER
-+M: Matt Ranostay <matt.ranostay@konsulko.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/i2c/video-i2c.c
-+
-+VIDEO MULTIPLEXER DRIVER
-+M: Philipp Zabel <p.zabel@pengutronix.de>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/platform/video-mux.c
-+
-+VIDEOBUF2 FRAMEWORK
-+M: Tomasz Figa <tfiga@chromium.org>
-+M: Marek Szyprowski <m.szyprowski@samsung.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+F: drivers/media/common/videobuf2/*
-+F: include/media/videobuf2-*
-+
-+VIMC VIRTUAL MEDIA CONTROLLER DRIVER
-+M: Helen Koike <helen.koike@collabora.com>
-+R: Shuah Khan <skhan@linuxfoundation.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/test-drivers/vimc/*
-+
-+VIRT LIB
-+M: Alex Williamson <alex.williamson@redhat.com>
-+M: Paolo Bonzini <pbonzini@redhat.com>
-+L: kvm@vger.kernel.org
-+S: Supported
-+F: virt/lib/
-+
-+VIRTIO AND VHOST VSOCK DRIVER
-+M: Stefan Hajnoczi <stefanha@redhat.com>
-+M: Stefano Garzarella <sgarzare@redhat.com>
-+L: kvm@vger.kernel.org
-+L: virtualization@lists.linux-foundation.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/vhost/vsock.c
-+F: include/linux/virtio_vsock.h
-+F: include/uapi/linux/virtio_vsock.h
-+F: net/vmw_vsock/virtio_transport.c
-+F: net/vmw_vsock/virtio_transport_common.c
-+
-+VIRTIO BLOCK AND SCSI DRIVERS
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+M: Jason Wang <jasowang@redhat.com>
-+R: Paolo Bonzini <pbonzini@redhat.com>
-+R: Stefan Hajnoczi <stefanha@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/block/virtio_blk.c
-+F: drivers/scsi/virtio_scsi.c
-+F: drivers/vhost/scsi.c
-+F: include/uapi/linux/virtio_blk.h
-+F: include/uapi/linux/virtio_scsi.h
-+
-+VIRTIO CONSOLE DRIVER
-+M: Amit Shah <amit@kernel.org>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/char/virtio_console.c
-+F: include/linux/virtio_console.h
-+F: include/uapi/linux/virtio_console.h
-+
-+VIRTIO CORE AND NET DRIVERS
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+M: Jason Wang <jasowang@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/virtio/
-+F: drivers/block/virtio_blk.c
-+F: drivers/crypto/virtio/
-+F: drivers/net/virtio_net.c
-+F: drivers/vdpa/
-+F: drivers/virtio/
-+F: include/linux/vdpa.h
-+F: include/linux/virtio*.h
-+F: include/uapi/linux/virtio_*.h
-+F: tools/virtio/
-+
-+VIRTIO BALLOON
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+M: David Hildenbrand <david@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/virtio/virtio_balloon.c
-+F: include/uapi/linux/virtio_balloon.h
-+F: include/linux/balloon_compaction.h
-+F: mm/balloon_compaction.c
-+
-+VIRTIO CRYPTO DRIVER
-+M: Gonglei <arei.gonglei@huawei.com>
-+L: virtualization@lists.linux-foundation.org
-+L: linux-crypto@vger.kernel.org
-+S: Maintained
-+F: drivers/crypto/virtio/
-+F: include/uapi/linux/virtio_crypto.h
-+
-+VIRTIO DRIVERS FOR S390
-+M: Cornelia Huck <cohuck@redhat.com>
-+M: Halil Pasic <pasic@linux.ibm.com>
-+L: linux-s390@vger.kernel.org
-+L: virtualization@lists.linux-foundation.org
-+L: kvm@vger.kernel.org
-+S: Supported
-+F: arch/s390/include/uapi/asm/virtio-ccw.h
-+F: drivers/s390/virtio/
-+
-+VIRTIO FILE SYSTEM
-+M: Vivek Goyal <vgoyal@redhat.com>
-+M: Stefan Hajnoczi <stefanha@redhat.com>
-+M: Miklos Szeredi <miklos@szeredi.hu>
-+L: virtualization@lists.linux-foundation.org
-+L: linux-fsdevel@vger.kernel.org
-+S: Supported
-+W: https://virtio-fs.gitlab.io/
-+F: Documentation/filesystems/virtiofs.rst
-+F: fs/fuse/virtio_fs.c
-+F: include/uapi/linux/virtio_fs.h
-+
-+VIRTIO GPIO DRIVER
-+M: Enrico Weigelt, metux IT consult <info@metux.net>
-+M: Viresh Kumar <vireshk@kernel.org>
-+L: linux-gpio@vger.kernel.org
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/gpio/gpio-virtio.c
-+F: include/uapi/linux/virtio_gpio.h
-+
-+VIRTIO GPU DRIVER
-+M: David Airlie <airlied@linux.ie>
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+L: dri-devel@lists.freedesktop.org
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+T: git git://anongit.freedesktop.org/drm/drm-misc
-+F: drivers/gpu/drm/virtio/
-+F: include/uapi/linux/virtio_gpu.h
-+
-+VIRTIO HOST (VHOST)
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+M: Jason Wang <jasowang@redhat.com>
-+L: kvm@vger.kernel.org
-+L: virtualization@lists.linux-foundation.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git
-+F: drivers/vhost/
-+F: include/linux/vhost_iotlb.h
-+F: include/uapi/linux/vhost.h
-+
-+VIRTIO INPUT DRIVER
-+M: Gerd Hoffmann <kraxel@redhat.com>
-+S: Maintained
-+F: drivers/virtio/virtio_input.c
-+F: include/uapi/linux/virtio_input.h
-+
-+VIRTIO IOMMU DRIVER
-+M: Jean-Philippe Brucker <jean-philippe@linaro.org>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/iommu/virtio-iommu.c
-+F: include/uapi/linux/virtio_iommu.h
-+
-+VIRTIO MEM DRIVER
-+M: David Hildenbrand <david@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+W: https://virtio-mem.gitlab.io/
-+F: drivers/virtio/virtio_mem.c
-+F: include/uapi/linux/virtio_mem.h
-+
-+VIRTIO SOUND DRIVER
-+M: Anton Yakovlev <anton.yakovlev@opensynergy.com>
-+M: "Michael S. Tsirkin" <mst@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Maintained
-+F: include/uapi/linux/virtio_snd.h
-+F: sound/virtio/*
-+
-+VIRTIO I2C DRIVER
-+M: Jie Deng <jie.deng@intel.com>
-+M: Viresh Kumar <viresh.kumar@linaro.org>
-+L: linux-i2c@vger.kernel.org
-+L: virtualization@lists.linux-foundation.org
-+S: Maintained
-+F: drivers/i2c/busses/i2c-virtio.c
-+F: include/uapi/linux/virtio_i2c.h
-+
-+VIRTUAL BOX GUEST DEVICE DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+M: Arnd Bergmann <arnd@arndb.de>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+S: Maintained
-+F: drivers/virt/vboxguest/
-+F: include/linux/vbox_utils.h
-+F: include/uapi/linux/vbox*.h
-+
-+VIRTUAL BOX SHARED FOLDER VFS DRIVER
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+F: fs/vboxsf/*
-+
-+VIRTUAL SERIO DEVICE DRIVER
-+M: Stephen Chandler Paul <thatslyude@gmail.com>
-+S: Maintained
-+F: drivers/input/serio/userio.c
-+F: include/uapi/linux/userio.h
-+
-+VIVID VIRTUAL VIDEO DRIVER
-+M: Hans Verkuil <hverkuil@xs4all.nl>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/test-drivers/vivid/*
-+
-+VIDTV VIRTUAL DIGITAL TV DRIVER
-+M: Daniel W. S. Almeida <dwlsalmeida@gmail.com>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/test-drivers/vidtv/*
-+
-+VLYNQ BUS
-+M: Florian Fainelli <f.fainelli@gmail.com>
-+L: openwrt-devel@lists.openwrt.org (subscribers-only)
-+S: Maintained
-+F: drivers/vlynq/vlynq.c
-+F: include/linux/vlynq.h
-+
-+VME SUBSYSTEM
-+M: Martyn Welch <martyn@welchs.me.uk>
-+M: Manohar Vanga <manohar.vanga@gmail.com>
-+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-+F: Documentation/driver-api/vme.rst
-+F: drivers/staging/vme/
-+F: drivers/vme/
-+F: include/linux/vme*
-+
-+VM SOCKETS (AF_VSOCK)
-+M: Stefano Garzarella <sgarzare@redhat.com>
-+L: virtualization@lists.linux-foundation.org
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/vsockmon.c
-+F: include/net/af_vsock.h
-+F: include/uapi/linux/vm_sockets.h
-+F: include/uapi/linux/vm_sockets_diag.h
-+F: include/uapi/linux/vsockmon.h
-+F: net/vmw_vsock/
-+F: tools/testing/vsock/
-+
-+VMWARE BALLOON DRIVER
-+M: Nadav Amit <namit@vmware.com>
-+M: "VMware, Inc." <pv-drivers@vmware.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: drivers/misc/vmw_balloon.c
-+
-+VMWARE HYPERVISOR INTERFACE
-+M: Deep Shah <sdeep@vmware.com>
-+M: "VMware, Inc." <pv-drivers@vmware.com>
-+L: virtualization@lists.linux-foundation.org
-+S: Supported
-+F: arch/x86/include/asm/vmware.h
-+F: arch/x86/kernel/cpu/vmware.c
-+
-+VMWARE PVRDMA DRIVER
-+M: Adit Ranadive <aditr@vmware.com>
-+M: VMware PV-Drivers <pv-drivers@vmware.com>
-+L: linux-rdma@vger.kernel.org
-+S: Maintained
-+F: drivers/infiniband/hw/vmw_pvrdma/
-+
-+VMware PVSCSI driver
-+M: Vishal Bhakta <vbhakta@vmware.com>
-+M: VMware PV-Drivers <pv-drivers@vmware.com>
-+L: linux-scsi@vger.kernel.org
-+S: Maintained
-+F: drivers/scsi/vmw_pvscsi.c
-+F: drivers/scsi/vmw_pvscsi.h
-+
-+VMWARE VIRTUAL PTP CLOCK DRIVER
-+M: Vivek Thampi <vithampi@vmware.com>
-+M: "VMware, Inc." <pv-drivers@vmware.com>
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/ptp/ptp_vmw.c
-+
-+VMWARE VMCI DRIVER
-+M: Jorgen Hansen <jhansen@vmware.com>
-+M: Vishnu Dasa <vdasa@vmware.com>
-+L: linux-kernel@vger.kernel.org
-+L: pv-drivers@vmware.com (private)
-+S: Maintained
-+F: drivers/misc/vmw_vmci/
-+
-+VMWARE VMMOUSE SUBDRIVER
-+M: "VMware Graphics" <linux-graphics-maintainer@vmware.com>
-+M: "VMware, Inc." <pv-drivers@vmware.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/mouse/vmmouse.c
-+F: drivers/input/mouse/vmmouse.h
-+
-+VMWARE VMXNET3 ETHERNET DRIVER
-+M: Ronak Doshi <doshir@vmware.com>
-+M: pv-drivers@vmware.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/vmxnet3/
-+
-+VOCORE VOCORE2 BOARD
-+M: Harvey Hunt <harveyhuntnexus@gmail.com>
-+L: linux-mips@vger.kernel.org
-+S: Maintained
-+F: arch/mips/boot/dts/ralink/vocore2.dts
-+
-+VOLTAGE AND CURRENT REGULATOR FRAMEWORK
-+M: Liam Girdwood <lgirdwood@gmail.com>
-+M: Mark Brown <broonie@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+W: http://www.slimlogic.co.uk/?p=48
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git
-+F: Documentation/devicetree/bindings/regulator/
-+F: Documentation/power/regulator/
-+F: drivers/regulator/
-+F: include/dt-bindings/regulator/
-+F: include/linux/regulator/
-+K: regulator_get_optional
-+
-+VOLTAGE AND CURRENT REGULATOR IRQ HELPERS
-+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
-+F: drivers/regulator/irq_helpers.c
-+
-+VRF
-+M: David Ahern <dsahern@kernel.org>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/vrf.rst
-+F: drivers/net/vrf.c
-+
-+VSPRINTF
-+M: Petr Mladek <pmladek@suse.com>
-+M: Steven Rostedt <rostedt@goodmis.org>
-+M: Sergey Senozhatsky <senozhatsky@chromium.org>
-+R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-+R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk.git
-+F: Documentation/core-api/printk-formats.rst
-+F: lib/test_printf.c
-+F: lib/test_scanf.c
-+F: lib/vsprintf.c
-+
-+VT1211 HARDWARE MONITOR DRIVER
-+M: Juerg Haefliger <juergh@gmail.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/vt1211.rst
-+F: drivers/hwmon/vt1211.c
-+
-+VT8231 HARDWARE MONITOR DRIVER
-+M: Roger Lucas <vt8231@hiddenengine.co.uk>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/vt8231.c
-+
-+VUB300 USB to SDIO/SD/MMC bridge chip
-+L: linux-mmc@vger.kernel.org
-+S: Orphan
-+F: drivers/mmc/host/vub300.c
-+
-+W1 DALLAS'S 1-WIRE BUS
-+M: Evgeniy Polyakov <zbr@ioremap.net>
-+S: Maintained
-+F: Documentation/devicetree/bindings/w1/
-+F: Documentation/w1/
-+F: drivers/w1/
-+F: include/linux/w1.h
-+
-+W83791D HARDWARE MONITORING DRIVER
-+M: Marc Hulsman <m.hulsman@tudelft.nl>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/w83791d.rst
-+F: drivers/hwmon/w83791d.c
-+
-+W83793 HARDWARE MONITORING DRIVER
-+M: Rudolf Marek <r.marek@assembler.cz>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: Documentation/hwmon/w83793.rst
-+F: drivers/hwmon/w83793.c
-+
-+W83795 HARDWARE MONITORING DRIVER
-+M: Jean Delvare <jdelvare@suse.com>
-+L: linux-hwmon@vger.kernel.org
-+S: Maintained
-+F: drivers/hwmon/w83795.c
-+
-+W83L51xD SD/MMC CARD INTERFACE DRIVER
-+M: Pierre Ossman <pierre@ossman.eu>
-+S: Maintained
-+F: drivers/mmc/host/wbsd.*
-+
-+WACOM PROTOCOL 4 SERIAL TABLETS
-+M: Julian Squires <julian@cipht.net>
-+M: Hans de Goede <hdegoede@redhat.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/input/tablet/wacom_serial4.c
-+
-+WATCHDOG DEVICE DRIVERS
-+M: Wim Van Sebroeck <wim@linux-watchdog.org>
-+M: Guenter Roeck <linux@roeck-us.net>
-+L: linux-watchdog@vger.kernel.org
-+S: Maintained
-+W: http://www.linux-watchdog.org/
-+T: git git://www.linux-watchdog.org/linux-watchdog.git
-+F: Documentation/devicetree/bindings/watchdog/
-+F: Documentation/watchdog/
-+F: drivers/watchdog/
-+F: include/linux/watchdog.h
-+F: include/uapi/linux/watchdog.h
-+
-+WHISKEYCOVE PMIC GPIO DRIVER
-+M: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-wcove.c
-+
-+WHWAVE RTC DRIVER
-+M: Dianlong Li <long17.cool@163.com>
-+L: linux-rtc@vger.kernel.org
-+S: Maintained
-+F: drivers/rtc/rtc-sd3078.c
-+
-+WIIMOTE HID DRIVER
-+M: David Rheinsberg <david.rheinsberg@gmail.com>
-+L: linux-input@vger.kernel.org
-+S: Maintained
-+F: drivers/hid/hid-wiimote*
-+
-+WILOCITY WIL6210 WIRELESS DRIVER
-+M: Maya Erez <merez@codeaurora.org>
-+L: linux-wireless@vger.kernel.org
-+L: wil6210@qti.qualcomm.com
-+S: Supported
-+W: https://wireless.wiki.kernel.org/en/users/Drivers/wil6210
-+F: drivers/net/wireless/ath/wil6210/
-+
-+WINBOND CIR DRIVER
-+M: David Härdeman <david@hardeman.nu>
-+S: Maintained
-+F: drivers/media/rc/winbond-cir.c
-+
-+WINSYSTEMS EBC-C384 WATCHDOG DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-watchdog@vger.kernel.org
-+S: Maintained
-+F: drivers/watchdog/ebc-c384_wdt.c
-+
-+WINSYSTEMS WS16C48 GPIO DRIVER
-+M: William Breathitt Gray <vilhelm.gray@gmail.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: drivers/gpio/gpio-ws16c48.c
-+
-+WIREGUARD SECURE NETWORK TUNNEL
-+M: Jason A. Donenfeld <Jason@zx2c4.com>
-+L: wireguard@lists.zx2c4.com
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wireguard/
-+F: tools/testing/selftests/wireguard/
-+
-+WISTRON LAPTOP BUTTON DRIVER
-+M: Miloslav Trmac <mitr@volny.cz>
-+S: Maintained
-+F: drivers/input/misc/wistron_btns.c
-+
-+WL3501 WIRELESS PCMCIA CARD DRIVER
-+L: linux-wireless@vger.kernel.org
-+S: Odd fixes
-+F: drivers/net/wireless/wl3501*
-+
-+WOLFSON MICROELECTRONICS DRIVERS
-+L: patches@opensource.cirrus.com
-+S: Supported
-+W: https://github.com/CirrusLogic/linux-drivers/wiki
-+T: git https://github.com/CirrusLogic/linux-drivers.git
-+F: Documentation/devicetree/bindings/extcon/wlf,arizona.yaml
-+F: Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
-+F: Documentation/devicetree/bindings/mfd/wm831x.txt
-+F: Documentation/devicetree/bindings/regulator/wlf,arizona.yaml
-+F: Documentation/devicetree/bindings/sound/wlf,*.yaml
-+F: Documentation/devicetree/bindings/sound/wm*
-+F: Documentation/hwmon/wm83??.rst
-+F: arch/arm/mach-s3c/mach-crag6410*
-+F: drivers/clk/clk-wm83*.c
-+F: drivers/gpio/gpio-*wm*.c
-+F: drivers/gpio/gpio-arizona.c
-+F: drivers/hwmon/wm83??-hwmon.c
-+F: drivers/input/misc/wm831x-on.c
-+F: drivers/input/touchscreen/wm831x-ts.c
-+F: drivers/input/touchscreen/wm97*.c
-+F: drivers/leds/leds-wm83*.c
-+F: drivers/mfd/arizona*
-+F: drivers/mfd/cs47l24*
-+F: drivers/mfd/wm*.c
-+F: drivers/power/supply/wm83*.c
-+F: drivers/regulator/arizona*
-+F: drivers/regulator/wm8*.c
-+F: drivers/rtc/rtc-wm83*.c
-+F: drivers/video/backlight/wm83*_bl.c
-+F: drivers/watchdog/wm83*_wdt.c
-+F: include/linux/mfd/arizona/
-+F: include/linux/mfd/wm831x/
-+F: include/linux/mfd/wm8350/
-+F: include/linux/mfd/wm8400*
-+F: include/linux/regulator/arizona*
-+F: include/linux/wm97xx.h
-+F: include/sound/wm????.h
-+F: sound/soc/codecs/arizona*
-+F: sound/soc/codecs/cs47l24*
-+F: sound/soc/codecs/wm*
-+
-+WORKQUEUE
-+M: Tejun Heo <tj@kernel.org>
-+R: Lai Jiangshan <jiangshanlai@gmail.com>
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
-+F: Documentation/core-api/workqueue.rst
-+F: include/linux/workqueue.h
-+F: kernel/workqueue.c
-+
-+WWAN DRIVERS
-+M: Loic Poulain <loic.poulain@linaro.org>
-+M: Sergey Ryazanov <ryazanov.s.a@gmail.com>
-+R: Johannes Berg <johannes@sipsolutions.net>
-+L: netdev@vger.kernel.org
-+S: Maintained
-+F: drivers/net/wwan/
-+F: include/linux/wwan.h
-+F: include/uapi/linux/wwan.h
-+
-+X-POWERS AXP288 PMIC DRIVERS
-+M: Hans de Goede <hdegoede@redhat.com>
-+S: Maintained
-+F: drivers/acpi/pmic/intel_pmic_xpower.c
-+N: axp288
-+
-+X-POWERS MULTIFUNCTION PMIC DEVICE DRIVERS
-+M: Chen-Yu Tsai <wens@csie.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+N: axp[128]
-+
-+X.25 STACK
-+M: Martin Schiller <ms@dev.tdt.de>
-+L: linux-x25@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/lapb-module.rst
-+F: Documentation/networking/x25*
-+F: drivers/net/wan/hdlc_x25.c
-+F: drivers/net/wan/lapbether.c
-+F: include/*/lapb.h
-+F: include/net/x25*
-+F: include/uapi/linux/x25.h
-+F: net/lapb/
-+F: net/x25/
-+
-+X86 ARCHITECTURE (32-BIT AND 64-BIT)
-+M: Thomas Gleixner <tglx@linutronix.de>
-+M: Ingo Molnar <mingo@redhat.com>
-+M: Borislav Petkov <bp@alien8.de>
-+M: Dave Hansen <dave.hansen@linux.intel.com>
-+M: x86@kernel.org
-+R: "H. Peter Anvin" <hpa@zytor.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
-+F: Documentation/devicetree/bindings/x86/
-+F: Documentation/x86/
-+F: arch/x86/
-+
-+X86 ENTRY CODE
-+M: Andy Lutomirski <luto@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/asm
-+F: arch/x86/entry/
-+
-+X86 MCE INFRASTRUCTURE
-+M: Tony Luck <tony.luck@intel.com>
-+M: Borislav Petkov <bp@alien8.de>
-+L: linux-edac@vger.kernel.org
-+S: Maintained
-+F: arch/x86/kernel/cpu/mce/*
-+
-+X86 MICROCODE UPDATE SUPPORT
-+M: Borislav Petkov <bp@alien8.de>
-+S: Maintained
-+F: arch/x86/kernel/cpu/microcode/*
-+
-+X86 MM
-+M: Dave Hansen <dave.hansen@linux.intel.com>
-+M: Andy Lutomirski <luto@kernel.org>
-+M: Peter Zijlstra <peterz@infradead.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/mm
-+F: arch/x86/mm/
-+
-+X86 PLATFORM DRIVERS
-+M: Hans de Goede <hdegoede@redhat.com>
-+M: Mark Gross <mgross@linux.intel.com>
-+L: platform-driver-x86@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
-+F: drivers/platform/olpc/
-+F: drivers/platform/x86/
-+
-+X86 PLATFORM DRIVERS - ARCH
-+R: Darren Hart <dvhart@infradead.org>
-+R: Andy Shevchenko <andy@infradead.org>
-+L: platform-driver-x86@vger.kernel.org
-+L: x86@kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
-+F: arch/x86/platform
-+
-+X86 PLATFORM UV HPE SUPERDOME FLEX
-+M: Steve Wahl <steve.wahl@hpe.com>
-+R: Mike Travis <mike.travis@hpe.com>
-+R: Dimitri Sivanich <dimitri.sivanich@hpe.com>
-+R: Russ Anderson <russ.anderson@hpe.com>
-+S: Supported
-+F: arch/x86/include/asm/uv/
-+F: arch/x86/kernel/apic/x2apic_uv_x.c
-+F: arch/x86/platform/uv/
-+
-+X86 VDSO
-+M: Andy Lutomirski <luto@kernel.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vdso
-+F: arch/x86/entry/vdso/
-+
-+XARRAY
-+M: Matthew Wilcox <willy@infradead.org>
-+L: linux-fsdevel@vger.kernel.org
-+S: Supported
-+F: Documentation/core-api/xarray.rst
-+F: include/linux/idr.h
-+F: include/linux/xarray.h
-+F: lib/idr.c
-+F: lib/xarray.c
-+F: tools/testing/radix-tree
-+
-+XBOX DVD IR REMOTE
-+M: Benjamin Valentin <benpicco@googlemail.com>
-+S: Maintained
-+F: drivers/media/rc/keymaps/rc-xbox-dvd.c
-+F: drivers/media/rc/xbox_remote.c
-+
-+XC2028/3028 TUNER DRIVER
-+M: Mauro Carvalho Chehab <mchehab@kernel.org>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org
-+T: git git://linuxtv.org/media_tree.git
-+F: drivers/media/tuners/tuner-xc2028.*
-+
-+XDP (eXpress Data Path)
-+M: Alexei Starovoitov <ast@kernel.org>
-+M: Daniel Borkmann <daniel@iogearbox.net>
-+M: David S. Miller <davem@davemloft.net>
-+M: Jakub Kicinski <kuba@kernel.org>
-+M: Jesper Dangaard Brouer <hawk@kernel.org>
-+M: John Fastabend <john.fastabend@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Supported
-+F: include/net/xdp.h
-+F: include/net/xdp_priv.h
-+F: include/trace/events/xdp.h
-+F: kernel/bpf/cpumap.c
-+F: kernel/bpf/devmap.c
-+F: net/core/xdp.c
-+F: samples/bpf/xdp*
-+F: tools/testing/selftests/bpf/*xdp*
-+F: tools/testing/selftests/bpf/*/*xdp*
-+F: drivers/net/ethernet/*/*/*/*/*xdp*
-+F: drivers/net/ethernet/*/*/*xdp*
-+K: (?:\b|_)xdp(?:\b|_)
-+
-+XDP SOCKETS (AF_XDP)
-+M: Björn Töpel <bjorn@kernel.org>
-+M: Magnus Karlsson <magnus.karlsson@intel.com>
-+R: Jonathan Lemon <jonathan.lemon@gmail.com>
-+L: netdev@vger.kernel.org
-+L: bpf@vger.kernel.org
-+S: Maintained
-+F: Documentation/networking/af_xdp.rst
-+F: include/net/xdp_sock*
-+F: include/net/xsk_buff_pool.h
-+F: include/uapi/linux/if_xdp.h
-+F: include/uapi/linux/xdp_diag.h
-+F: include/net/netns/xdp.h
-+F: net/xdp/
-+F: samples/bpf/xdpsock*
-+F: tools/lib/bpf/xsk*
-+
-+XEN BLOCK SUBSYSTEM
-+M: Roger Pau Monné <roger.pau@citrix.com>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/block/xen*
-+F: drivers/block/xen-blkback/*
-+
-+XEN HYPERVISOR ARM
-+M: Stefano Stabellini <sstabellini@kernel.org>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm/include/asm/xen/
-+F: arch/arm/xen/
-+
-+XEN HYPERVISOR ARM64
-+M: Stefano Stabellini <sstabellini@kernel.org>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Maintained
-+F: arch/arm64/include/asm/xen/
-+F: arch/arm64/xen/
-+
-+XEN HYPERVISOR INTERFACE
-+M: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-+M: Juergen Gross <jgross@suse.com>
-+R: Stefano Stabellini <sstabellini@kernel.org>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git
-+F: Documentation/ABI/stable/sysfs-hypervisor-xen
-+F: Documentation/ABI/testing/sysfs-hypervisor-xen
-+F: arch/x86/include/asm/pvclock-abi.h
-+F: arch/x86/include/asm/xen/
-+F: arch/x86/platform/pvh/
-+F: arch/x86/xen/
-+F: drivers/*/xen-*front.c
-+F: drivers/xen/
-+F: include/uapi/xen/
-+F: include/xen/
-+
-+XEN NETWORK BACKEND DRIVER
-+M: Wei Liu <wei.liu@kernel.org>
-+M: Paul Durrant <paul@xen.org>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+L: netdev@vger.kernel.org
-+S: Supported
-+F: drivers/net/xen-netback/*
-+
-+XEN PCI SUBSYSTEM
-+M: Juergen Gross <jgross@suse.com>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+S: Supported
-+F: arch/x86/pci/*xen*
-+F: drivers/pci/*xen*
-+
-+XEN PVSCSI DRIVERS
-+M: Juergen Gross <jgross@suse.com>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+L: linux-scsi@vger.kernel.org
-+S: Supported
-+F: drivers/scsi/xen-scsifront.c
-+F: drivers/xen/xen-scsiback.c
-+F: include/xen/interface/io/vscsiif.h
-+
-+XEN SOUND FRONTEND DRIVER
-+M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-+S: Supported
-+F: sound/xen/*
-+
-+XEN SWIOTLB SUBSYSTEM
-+M: Juergen Gross <jgross@suse.com>
-+M: Stefano Stabellini <sstabellini@kernel.org>
-+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
-+L: iommu@lists.linux-foundation.org
-+S: Supported
-+F: arch/x86/xen/*swiotlb*
-+F: drivers/xen/*swiotlb*
-+
-+XFS FILESYSTEM
-+C: irc://irc.oftc.net/xfs
-+M: Darrick J. Wong <djwong@kernel.org>
-+M: linux-xfs@vger.kernel.org
-+L: linux-xfs@vger.kernel.org
-+S: Supported
-+W: http://xfs.org/
-+T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
-+F: Documentation/ABI/testing/sysfs-fs-xfs
-+F: Documentation/admin-guide/xfs.rst
-+F: Documentation/filesystems/xfs-delayed-logging-design.rst
-+F: Documentation/filesystems/xfs-self-describing-metadata.rst
-+F: fs/xfs/
-+F: include/uapi/linux/dqblk_xfs.h
-+F: include/uapi/linux/fsmap.h
-+
-+XILINX AXI ETHERNET DRIVER
-+M: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
-+S: Maintained
-+F: drivers/net/ethernet/xilinx/xilinx_axienet*
-+
-+XILINX CAN DRIVER
-+M: Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
-+R: Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
-+L: linux-can@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/net/can/xilinx_can.txt
-+F: drivers/net/can/xilinx_can.c
-+
-+XILINX GPIO DRIVER
-+M: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
-+R: Srinivas Neeli <srinivas.neeli@xilinx.com>
-+R: Michal Simek <michal.simek@xilinx.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
-+F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
-+F: drivers/gpio/gpio-xilinx.c
-+F: drivers/gpio/gpio-zynq.c
-+
-+XILINX SD-FEC IP CORES
-+M: Derek Kiernan <derek.kiernan@xilinx.com>
-+M: Dragan Cvetic <dragan.cvetic@xilinx.com>
-+S: Maintained
-+F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt
-+F: Documentation/misc-devices/xilinx_sdfec.rst
-+F: drivers/misc/Kconfig
-+F: drivers/misc/Makefile
-+F: drivers/misc/xilinx_sdfec.c
-+F: include/uapi/misc/xilinx_sdfec.h
-+
-+XILINX UARTLITE SERIAL DRIVER
-+M: Peter Korsgaard <jacmet@sunsite.dk>
-+L: linux-serial@vger.kernel.org
-+S: Maintained
-+F: drivers/tty/serial/uartlite.c
-+
-+XILINX VIDEO IP CORES
-+M: Hyun Kwon <hyun.kwon@xilinx.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+T: git git://linuxtv.org/media_tree.git
-+F: Documentation/devicetree/bindings/media/xilinx/
-+F: drivers/media/platform/xilinx/
-+F: include/uapi/linux/xilinx-v4l2-controls.h
-+
-+XILINX ZYNQMP DPDMA DRIVER
-+M: Hyun Kwon <hyun.kwon@xilinx.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: dmaengine@vger.kernel.org
-+S: Supported
-+F: Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml
-+F: drivers/dma/xilinx/xilinx_dpdma.c
-+F: include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
-+
-+XILINX ZYNQMP PSGTR PHY DRIVER
-+M: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
-+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+T: git https://github.com/Xilinx/linux-xlnx.git
-+F: Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml
-+F: drivers/phy/xilinx/phy-zynqmp.c
-+
-+XILLYBUS DRIVER
-+M: Eli Billauer <eli.billauer@gmail.com>
-+L: linux-kernel@vger.kernel.org
-+S: Supported
-+F: drivers/char/xillybus/
-+
-+XLP9XX I2C DRIVER
-+M: George Cherian <gcherian@marvell.com>
-+L: linux-i2c@vger.kernel.org
-+S: Supported
-+W: http://www.marvell.com
-+F: Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt
-+F: drivers/i2c/busses/i2c-xlp9xx.c
-+
-+XRA1403 GPIO EXPANDER
-+M: Nandor Han <nandor.han@ge.com>
-+M: Semi Malinen <semi.malinen@ge.com>
-+L: linux-gpio@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
-+F: drivers/gpio/gpio-xra1403.c
-+
-+XTENSA XTFPGA PLATFORM SUPPORT
-+M: Max Filippov <jcmvbkbc@gmail.com>
-+L: linux-xtensa@linux-xtensa.org
-+S: Maintained
-+F: drivers/spi/spi-xtensa-xtfpga.c
-+F: sound/soc/xtensa/xtfpga-i2s.c
-+
-+YAM DRIVER FOR AX.25
-+M: Jean-Paul Roubelat <jpr@f6fbb.org>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+F: drivers/net/hamradio/yam*
-+F: include/linux/yam.h
-+
-+YAMA SECURITY MODULE
-+M: Kees Cook <keescook@chromium.org>
-+S: Supported
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git yama/tip
-+F: Documentation/admin-guide/LSM/Yama.rst
-+F: security/yama/
-+
-+YEALINK PHONE DRIVER
-+M: Henk Vergonet <Henk.Vergonet@gmail.com>
-+L: usbb2k-api-dev@nongnu.org
-+S: Maintained
-+F: Documentation/input/devices/yealink.rst
-+F: drivers/input/misc/yealink.*
-+
-+Z8530 DRIVER FOR AX.25
-+M: Joerg Reuter <jreuter@yaina.de>
-+L: linux-hams@vger.kernel.org
-+S: Maintained
-+W: http://yaina.de/jreuter/
-+W: http://www.qsl.net/dl1bke/
-+F: Documentation/networking/device_drivers/hamradio/z8530drv.rst
-+F: drivers/net/hamradio/*scc.c
-+F: drivers/net/hamradio/z8530.h
-+
-+ZBUD COMPRESSED PAGE ALLOCATOR
-+M: Seth Jennings <sjenning@redhat.com>
-+M: Dan Streetman <ddstreet@ieee.org>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: mm/zbud.c
-+
-+ZD1211RW WIRELESS DRIVER
-+M: Ulrich Kunitz <kune@deine-taler.de>
-+L: linux-wireless@vger.kernel.org
-+L: zd1211-devs@lists.sourceforge.net (subscribers-only)
-+S: Maintained
-+W: http://zd1211.ath.cx/wiki/DriverRewrite
-+F: drivers/net/wireless/zydas/zd1211rw/
-+
-+ZD1301 MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org/
-+W: http://palosaari.fi/linux/
-+Q: https://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/usb/dvb-usb-v2/zd1301*
-+
-+ZD1301_DEMOD MEDIA DRIVER
-+M: Antti Palosaari <crope@iki.fi>
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: https://linuxtv.org/
-+W: http://palosaari.fi/linux/
-+Q: https://patchwork.linuxtv.org/project/linux-media/list/
-+F: drivers/media/dvb-frontends/zd1301_demod*
-+
-+ZHAOXIN PROCESSOR SUPPORT
-+M: Tony W Wang-oc <TonyWWang-oc@zhaoxin.com>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: arch/x86/kernel/cpu/zhaoxin.c
-+
-+ZONEFS FILESYSTEM
-+M: Damien Le Moal <damien.lemoal@wdc.com>
-+M: Naohiro Aota <naohiro.aota@wdc.com>
-+R: Johannes Thumshirn <jth@kernel.org>
-+L: linux-fsdevel@vger.kernel.org
-+S: Maintained
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs.git
-+F: Documentation/filesystems/zonefs.rst
-+F: fs/zonefs/
-+
-+ZPOOL COMPRESSED PAGE STORAGE API
-+M: Dan Streetman <ddstreet@ieee.org>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: include/linux/zpool.h
-+F: mm/zpool.c
-+
-+ZR36067 VIDEO FOR LINUX DRIVER
-+M: Corentin Labbe <clabbe@baylibre.com>
-+L: mjpeg-users@lists.sourceforge.net
-+L: linux-media@vger.kernel.org
-+S: Maintained
-+W: http://mjpeg.sourceforge.net/driver-zoran/
-+Q: https://patchwork.linuxtv.org/project/linux-media/list/
-+F: Documentation/driver-api/media/drivers/zoran.rst
-+F: drivers/staging/media/zoran/
-+
-+ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
-+M: Minchan Kim <minchan@kernel.org>
-+M: Nitin Gupta <ngupta@vflare.org>
-+R: Sergey Senozhatsky <senozhatsky@chromium.org>
-+L: linux-kernel@vger.kernel.org
-+S: Maintained
-+F: Documentation/admin-guide/blockdev/zram.rst
-+F: drivers/block/zram/
-+
-+ZS DECSTATION Z85C30 SERIAL DRIVER
-+M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-+S: Maintained
-+F: drivers/tty/serial/zs.*
-+
-+ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
-+M: Minchan Kim <minchan@kernel.org>
-+M: Nitin Gupta <ngupta@vflare.org>
-+R: Sergey Senozhatsky <senozhatsky@chromium.org>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: Documentation/vm/zsmalloc.rst
-+F: include/linux/zsmalloc.h
-+F: mm/zsmalloc.c
-+
-+ZSWAP COMPRESSED SWAP CACHING
-+M: Seth Jennings <sjenning@redhat.com>
-+M: Dan Streetman <ddstreet@ieee.org>
-+M: Vitaly Wool <vitaly.wool@konsulko.com>
-+L: linux-mm@kvack.org
-+S: Maintained
-+F: mm/zswap.c
-+
-+THE REST
-+M: Linus Torvalds <torvalds@linux-foundation.org>
-+L: linux-kernel@vger.kernel.org
-+S: Buried alive in reporters
-+Q: http://patchwork.kernel.org/project/LKML/list/
-+T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-+F: *
-+F: */
-diff -urN linux-5.15/crypto/drbg.c linux-5.15-lrng/crypto/drbg.c
---- linux-5.15/crypto/drbg.c 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/crypto/drbg.c 2021-11-29 12:37:31.183279025 +1100
-@@ -114,7 +114,7 @@
- * the SHA256 / AES 256 over other ciphers. Thus, the favored
- * DRBGs are the latest entries in this array.
- */
--static const struct drbg_core drbg_cores[] = {
-+const struct drbg_core drbg_cores[] = {
- #ifdef CONFIG_CRYPTO_DRBG_CTR
- {
- .flags = DRBG_CTR | DRBG_STRENGTH128,
-@@ -191,6 +191,7 @@
- },
- #endif /* CONFIG_CRYPTO_DRBG_HMAC */
- };
-+EXPORT_SYMBOL(drbg_cores);
-
- static int drbg_uninstantiate(struct drbg_state *drbg);
-
-@@ -206,7 +207,7 @@
- * Return: normalized strength in *bytes* value or 32 as default
- * to counter programming errors
- */
--static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
-+unsigned short drbg_sec_strength(drbg_flag_t flags)
- {
- switch (flags & DRBG_STRENGTH_MASK) {
- case DRBG_STRENGTH128:
-@@ -219,6 +220,7 @@
- return 32;
- }
- }
-+EXPORT_SYMBOL(drbg_sec_strength);
-
- /*
- * FIPS 140-2 continuous self test for the noise source
-@@ -1215,7 +1217,7 @@
- }
-
- /* Free all substructures in a DRBG state without the DRBG state structure */
--static inline void drbg_dealloc_state(struct drbg_state *drbg)
-+void drbg_dealloc_state(struct drbg_state *drbg)
- {
- if (!drbg)
- return;
-@@ -1236,12 +1238,13 @@
- drbg->fips_primed = false;
- }
- }
-+EXPORT_SYMBOL(drbg_dealloc_state);
-
- /*
- * Allocate all sub-structures for a DRBG state.
- * The DRBG state structure must already be allocated.
- */
--static inline int drbg_alloc_state(struct drbg_state *drbg)
-+int drbg_alloc_state(struct drbg_state *drbg)
- {
- int ret = -ENOMEM;
- unsigned int sb_size = 0;
-@@ -1322,6 +1325,7 @@
- drbg_dealloc_state(drbg);
- return ret;
- }
-+EXPORT_SYMBOL(drbg_alloc_state);
-
- /*************************************************************************
- * DRBG interface functions
-@@ -1891,8 +1895,7 @@
- *
- * return: flags
- */
--static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-- int *coreref, bool *pr)
-+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
- {
- int i = 0;
- size_t start = 0;
-@@ -1919,6 +1922,7 @@
- }
- }
- }
-+EXPORT_SYMBOL(drbg_convert_tfm_core);
-
- static int drbg_kcapi_init(struct crypto_tfm *tfm)
- {
-diff -urN linux-5.15/crypto/jitterentropy-kcapi.c linux-5.15-lrng/crypto/jitterentropy-kcapi.c
---- linux-5.15/crypto/jitterentropy-kcapi.c 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/crypto/jitterentropy-kcapi.c 2021-11-29 12:37:52.903278942 +1100
-@@ -43,8 +43,7 @@
- #include <linux/fips.h>
- #include <linux/time.h>
- #include <crypto/internal/rng.h>
--
--#include "jitterentropy.h"
-+#include <crypto/internal/jitterentropy.h>
-
- /***************************************************************************
- * Helper function
-diff -urN linux-5.15/crypto/jitterentropy.c linux-5.15-lrng/crypto/jitterentropy.c
---- linux-5.15/crypto/jitterentropy.c 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/crypto/jitterentropy.c 2021-11-29 12:37:52.903278942 +1100
-@@ -117,7 +117,7 @@
- #define JENT_EHEALTH 9 /* Health test failed during initialization */
- #define JENT_ERCT 10 /* RCT failed during initialization */
-
--#include "jitterentropy.h"
-+#include <crypto/internal/jitterentropy.h>
-
- /***************************************************************************
- * Adaptive Proportion Test
-diff -urN linux-5.15/crypto/jitterentropy.h linux-5.15-lrng/crypto/jitterentropy.h
---- linux-5.15/crypto/jitterentropy.h 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/crypto/jitterentropy.h 1970-01-01 10:00:00.000000000 +1000
-@@ -1,17 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--
--extern void *jent_zalloc(unsigned int len);
--extern void jent_zfree(void *ptr);
--extern int jent_fips_enabled(void);
--extern void jent_panic(char *s);
--extern void jent_memcpy(void *dest, const void *src, unsigned int n);
--extern void jent_get_nstime(__u64 *out);
--
--struct rand_data;
--extern int jent_entropy_init(void);
--extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
-- unsigned int len);
--
--extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
-- unsigned int flags);
--extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
-diff -urN linux-5.15/drivers/char/Kconfig linux-5.15-lrng/drivers/char/Kconfig
---- linux-5.15/drivers/char/Kconfig 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/drivers/char/Kconfig 2021-11-29 12:36:52.113279174 +1100
-@@ -451,4 +451,6 @@
- pool. Otherwise, say N here so it will be regarded as device input that
- only mixes the entropy pool.
-
-+source "drivers/char/lrng/Kconfig"
-+
- endmenu
-diff -urN linux-5.15/drivers/char/Makefile linux-5.15-lrng/drivers/char/Makefile
---- linux-5.15/drivers/char/Makefile 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/drivers/char/Makefile 2021-11-29 12:36:52.113279174 +1100
-@@ -3,7 +3,14 @@
- # Makefile for the kernel character device drivers.
- #
-
--obj-y += mem.o random.o
-+obj-y += mem.o
-+
-+ifeq ($(CONFIG_LRNG),y)
-+ obj-y += lrng/
-+else
-+ obj-y += random.o
-+endif
-+
- obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
- obj-y += misc.o
- obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
-diff -urN linux-5.15/drivers/char/lrng/Kconfig linux-5.15-lrng/drivers/char/lrng/Kconfig
---- linux-5.15/drivers/char/lrng/Kconfig 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/Kconfig 2021-11-29 12:38:26.593278813 +1100
-@@ -0,0 +1,589 @@
-+# SPDX-License-Identifier: GPL-2.0
-+#
-+# Linux Random Number Generator configuration
-+#
-+
-+menuconfig LRNG
-+ bool "Linux Random Number Generator"
-+ select CRYPTO_LIB_SHA256 if CRYPTO
-+ help
-+ The Linux Random Number Generator (LRNG) is the replacement
-+ of the existing /dev/random provided with drivers/char/random.c.
-+ It generates entropy from different noise sources and
-+ delivers significant entropy during boot.
-+
-+if LRNG
-+
-+menu "Specific DRNG seeding strategies"
-+
-+config LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+ bool "Oversample entropy sources"
-+ default n
-+ help
-+ When enabling this option, the entropy sources are
-+ over-sampled with the following approach: First, the
-+ the entropy sources are requested to provide 64 bits more
-+ entropy than the size of the entropy buffer. For example,
-+ if the entropy buffer is 256 bits, 320 bits of entropy
-+ is requested to fill that buffer.
-+
-+ Second, the seed operation of the deterministic RNG
-+ requests 128 bits more data from each entropy source than
-+ the security strength of the DRNG during initialization.
-+ A prerequisite for this operation is that the digest size
-+ of the used hash must be at least equally large to generate
-+ that buffer. If the prerequisite is not met, this
-+ oversampling is not applied.
-+
-+ This strategy is intended to offset the asymptotic entropy
-+ increase to reach full entropy in a buffer.
-+
-+ The strategy is consistent with the requirements in
-+ NIST SP800-90C and is only enforced with fips=1.
-+
-+ If unsure, say N.
-+
-+config LRNG_OVERSAMPLE_ES_BITS
-+ int
-+ default 0 if !LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+ default 64 if LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+
-+config LRNG_SEED_BUFFER_INIT_ADD_BITS
-+ int
-+ default 0 if !LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+ default 128 if LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+
-+endmenu # "Specific DRNG seeding strategies"
-+
-+menu "Entropy Source Configuration"
-+
-+comment "Interrupt Entropy Source"
-+
-+config LRNG_IRQ
-+ bool "Enable Interrupt Entropy Source as LRNG Seed Source"
-+ default y
-+ help
-+ The LRNG models an entropy source based on the timing of the
-+ occurrence of interrupts. Enable this option to enable this
-+ IRQ entropy source.
-+
-+ The IRQ entropy source is triggered every time an interrupt
-+ arrives and thus causes the interrupt handler to execute
-+ slightly longer. Disabling the IRQ entropy source implies
-+ that the performance penalty on the interrupt handler added
-+ by the LRNG is eliminated. Yet, this entropy source is
-+ considered to be the internal entropy source of the LRNG.
-+ Thus, only disable it if you ensured that other entropy
-+ sources are available that supply the LRNG with entropy.
-+
-+ If you disable the IRQ entropy source, you MUST ensure
-+ one or more entropy sources collectively have the
-+ capability to deliver sufficient entropy with one invocation
-+ at a rate compliant to the security strength of the DRNG
-+ (usually 256 bits of entropy). In addition, if those
-+ entropy sources do not deliver sufficient entropy during
-+ first request, the reseed must be triggered from user
-+ space or kernel space when sufficient entropy is considered
-+ to be present.
-+
-+ If unsure, say Y.
-+
-+choice
-+ prompt "Continuous entropy compression boot time setting"
-+ default LRNG_CONTINUOUS_COMPRESSION_ENABLED
-+ depends on LRNG_IRQ
-+ help
-+ Select the default behavior of the interrupt entropy source
-+ continuous compression operation.
-+
-+ The Linux RNG collects entropy data during each interrupt.
-+ For performance reasons, a amount of entropy data defined by
-+ the LRNG entropy collection pool size is concatenated into
-+ an array. When that array is filled up, a hash is calculated
-+ to compress the entropy. That hash is calculated in
-+ interrupt context.
-+
-+ In case such hash calculation in interrupt context is deemed
-+ too time-consuming, the continuous compression operation
-+ can be disabled. If disabled, the collection of entropy will
-+ not trigger a hash compression operation in interrupt context.
-+ The compression happens only when the DRNG is reseeded which is
-+ in process context. This implies that old entropy data
-+ collected after the last DRNG-reseed is overwritten with newer
-+ entropy data once the collection pool is full instead of
-+ retaining its entropy with the compression operation.
-+
-+ config LRNG_CONTINUOUS_COMPRESSION_ENABLED
-+ bool "Enable continuous compression (default)"
-+
-+ config LRNG_CONTINUOUS_COMPRESSION_DISABLED
-+ bool "Disable continuous compression"
-+endchoice
-+
-+config LRNG_ENABLE_CONTINUOUS_COMPRESSION
-+ bool
-+ default y if LRNG_CONTINUOUS_COMPRESSION_ENABLED
-+ default n if LRNG_CONTINUOUS_COMPRESSION_DISABLED
-+
-+config LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION
-+ bool "Runtime-switchable continuous entropy compression"
-+ depends on LRNG_IRQ
-+ help
-+ Per default, the interrupt entropy source continuous
-+ compression operation behavior is hard-wired into the kernel.
-+ Enable this option to allow it to be configurable at boot time.
-+
-+ To modify the default behavior of the continuous
-+ compression operation, use the kernel command line option
-+ of lrng_sw_noise.lrng_pcpu_continuous_compression.
-+
-+ If unsure, say N.
-+
-+choice
-+ prompt "LRNG Entropy Collection Pool Size"
-+ default LRNG_COLLECTION_SIZE_1024
-+ depends on LRNG_IRQ
-+ help
-+ Select the size of the LRNG entropy collection pool
-+ storing data for the interrupt entropy source without
-+ performing a compression operation. The larger the
-+ collection size is, the faster the average interrupt
-+ handling will be. The collection size represents the
-+ number of bytes of the per-CPU memory used to batch
-+ up entropy event data.
-+
-+ The default value is good for regular operations. Choose
-+ larger sizes for servers that have no memory limitations.
-+ If runtime memory is precious, choose a smaller size.
-+
-+ The collection size is unrelated to the entropy rate
-+ or the amount of entropy the LRNG can process.
-+
-+ config LRNG_COLLECTION_SIZE_32
-+ depends on LRNG_CONTINUOUS_COMPRESSION_ENABLED
-+ depends on !LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION
-+ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+ bool "32 interrupt events"
-+
-+ config LRNG_COLLECTION_SIZE_256
-+ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES
-+ bool "256 interrupt events"
-+
-+ config LRNG_COLLECTION_SIZE_512
-+ bool "512 interrupt events"
-+
-+ config LRNG_COLLECTION_SIZE_1024
-+ bool "1024 interrupt events (default)"
-+
-+ config LRNG_COLLECTION_SIZE_2048
-+ bool "2048 interrupt events"
-+
-+ config LRNG_COLLECTION_SIZE_4096
-+ bool "4096 interrupt events"
-+
-+ config LRNG_COLLECTION_SIZE_8192
-+ bool "8192 interrupt events"
-+
-+endchoice
-+
-+config LRNG_COLLECTION_SIZE
-+ int
-+ default 32 if LRNG_COLLECTION_SIZE_32
-+ default 256 if LRNG_COLLECTION_SIZE_256
-+ default 512 if LRNG_COLLECTION_SIZE_512
-+ default 1024 if LRNG_COLLECTION_SIZE_1024
-+ default 2048 if LRNG_COLLECTION_SIZE_2048
-+ default 4096 if LRNG_COLLECTION_SIZE_4096
-+ default 8192 if LRNG_COLLECTION_SIZE_8192
-+
-+config LRNG_HEALTH_TESTS
-+ bool "Enable interrupt entropy source online health tests"
-+ depends on LRNG_IRQ
-+ help
-+ The online health tests applied to the interrupt entropy
-+ source validate the noise source at runtime for fatal
-+ errors. These tests include SP800-90B compliant tests
-+ which are invoked if the system is booted with fips=1.
-+ In case of fatal errors during active SP800-90B tests,
-+ the issue is logged and the noise data is discarded.
-+ These tests are required for full compliance of the
-+ interrupt entropy source with SP800-90B.
-+
-+ If unsure, say Y.
-+
-+config LRNG_RCT_BROKEN
-+ bool "SP800-90B RCT with dangerous low cutoff value"
-+ depends on LRNG_HEALTH_TESTS
-+ depends on BROKEN
-+ default n
-+ help
-+ This option enables a dangerously low SP800-90B repetitive
-+ count test (RCT) cutoff value which makes it very likely
-+ that the RCT is triggered to raise a self test failure.
-+
-+ This option is ONLY intended for developers wanting to
-+ test the effectiveness of the SP800-90B RCT health test.
-+
-+ If unsure, say N.
-+
-+config LRNG_APT_BROKEN
-+ bool "SP800-90B APT with dangerous low cutoff value"
-+ depends on LRNG_HEALTH_TESTS
-+ depends on BROKEN
-+ default n
-+ help
-+ This option enables a dangerously low SP800-90B adaptive
-+ proportion test (APT) cutoff value which makes it very
-+ likely that the APT is triggered to raise a self test
-+ failure.
-+
-+ This option is ONLY intended for developers wanting to
-+ test the effectiveness of the SP800-90B APT health test.
-+
-+ If unsure, say N.
-+
-+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
-+config LRNG_RCT_CUTOFF
-+ int
-+ default 31 if !LRNG_RCT_BROKEN
-+ default 1 if LRNG_RCT_BROKEN
-+
-+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
-+config LRNG_APT_CUTOFF
-+ int
-+ default 325 if !LRNG_APT_BROKEN
-+ default 32 if LRNG_APT_BROKEN
-+
-+config LRNG_IRQ_ENTROPY_RATE
-+ int "Interrupt Entropy Source Entropy Rate"
-+ depends on LRNG_IRQ
-+ range 256 4294967295
-+ default 256
-+ help
-+ The LRNG will collect the configured number of interrupts to
-+ obtain 256 bits of entropy. This value can be set to any between
-+ 256 and 4294967295. The LRNG guarantees that this value is not
-+ lower than 256. This lower limit implies that one interrupt event
-+ is credited with one bit of entropy. This value is subject to the
-+ increase by the oversampling factor, if no high-resolution timer
-+ is found.
-+
-+ In order to effectively disable the interrupt entropy source,
-+ the option has to be set to 4294967295. In this case, the
-+ interrupt entropy source will still deliver data but without
-+ being credited with entropy.
-+
-+comment "Jitter RNG Entropy Source"
-+
-+config LRNG_JENT
-+ bool "Enable Jitter RNG as LRNG Seed Source"
-+ depends on CRYPTO
-+ select CRYPTO_JITTERENTROPY
-+ help
-+ The Linux RNG may use the Jitter RNG as noise source. Enabling
-+ this option enables the use of the Jitter RNG. Its default
-+ entropy level is 16 bits of entropy per 256 data bits delivered
-+ by the Jitter RNG. This entropy level can be changed at boot
-+ time or at runtime with the lrng_base.jitterrng configuration
-+ variable.
-+
-+config LRNG_JENT_ENTROPY_RATE
-+ int "Jitter RNG Entropy Source Entropy Rate"
-+ depends on LRNG_JENT
-+ range 0 256
-+ default 16
-+ help
-+ The option defines the amount of entropy the LRNG applies to 256
-+ bits of data obtained from the Jitter RNG entropy source. The
-+ LRNG enforces the limit that this value must be in the range
-+ between 0 and 256.
-+
-+ When configuring this value to 0, the Jitter RNG entropy source
-+ will provide 256 bits of data without being credited to contain
-+ entropy.
-+
-+comment "CPU Entropy Source"
-+
-+config LRNG_CPU
-+ bool "Enable CPU Entropy Source as LRNG Seed Source"
-+ default y
-+ help
-+ Current CPUs commonly contain entropy sources which can be
-+ used to seed the LRNG. For example, the Intel RDSEED
-+ instruction, or the POWER DARN instruction will be sourced
-+ to seed the LRNG if this option is enabled.
-+
-+ Note, if this option is enabled and the underlying CPU
-+ does not offer such entropy source, the LRNG will automatically
-+ detect this and ignore the hardware.
-+
-+config LRNG_CPU_FULL_ENT_MULTIPLIER
-+ int
-+ default 1 if !LRNG_TEST_CPU_ES_COMPRESSION
-+ default 123 if LRNG_TEST_CPU_ES_COMPRESSION
-+
-+config LRNG_CPU_ENTROPY_RATE
-+ int "CPU Entropy Source Entropy Rate"
-+ depends on LRNG_CPU
-+ range 0 256
-+ default 8
-+ help
-+ The option defines the amount of entropy the LRNG applies to 256
-+ bits of data obtained from the CPU entropy source. The LRNG
-+ enforces the limit that this value must be in the range between
-+ 0 and 256.
-+
-+ When configuring this value to 0, the CPU entropy source will
-+ provide 256 bits of data without being credited to contain
-+ entropy.
-+
-+ Note, this option is overwritten when the option
-+ CONFIG_RANDOM_TRUST_CPU is set.
-+
-+endmenu # "Entropy Source Configuration"
-+
-+menuconfig LRNG_DRNG_SWITCH
-+ bool "Support DRNG runtime switching"
-+ help
-+ The Linux RNG per default uses a ChaCha20 DRNG that is
-+ accessible via the external interfaces. With this configuration
-+ option other DRNGs can be selected and loaded at runtime.
-+
-+if LRNG_DRNG_SWITCH
-+
-+config LRNG_KCAPI_HASH
-+ bool
-+ select CRYPTO_HASH
-+
-+config LRNG_DRBG
-+ tristate "SP800-90A support for the LRNG"
-+ depends on CRYPTO
-+ select CRYPTO_DRBG_MENU
-+ select CRYPTO_SHA512
-+ select LRNG_KCAPI_HASH
-+ help
-+ Enable the SP800-90A DRBG support for the LRNG. Once the
-+ module is loaded, output from /dev/random, /dev/urandom,
-+ getrandom(2), or get_random_bytes_full is provided by a DRBG.
-+
-+config LRNG_KCAPI
-+ tristate "Kernel Crypto API support for the LRNG"
-+ depends on CRYPTO
-+ depends on !LRNG_DRBG
-+ select CRYPTO_RNG
-+ select LRNG_KCAPI_HASH
-+ help
-+ Enable the support for generic pseudo-random number
-+ generators offered by the kernel crypto API with the
-+ LRNG. Once the module is loaded, output from /dev/random,
-+ /dev/urandom, getrandom(2), or get_random_bytes is
-+ provided by the selected kernel crypto API RNG.
-+endif # LRNG_DRNG_SWITCH
-+
-+menuconfig LRNG_TESTING_MENU
-+ bool "LRNG testing interfaces"
-+ depends on DEBUG_FS
-+ help
-+ Enable one or more of the following test interfaces.
-+
-+ If unsure, say N.
-+
-+if LRNG_TESTING_MENU
-+
-+config LRNG_RAW_HIRES_ENTROPY
-+ bool "Enable entropy test interface to hires timer noise source"
-+ default y
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned high resolution time stamp noise that
-+ is collected by the LRNG for statistical analysis. Extracted
-+ noise data is not used to seed the LRNG.
-+
-+ The raw noise data can be obtained using the lrng_raw_hires
-+ debugfs file. Using the option lrng_testing.boot_raw_hires_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_JIFFIES_ENTROPY
-+ bool "Enable entropy test interface to Jiffies noise source"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned Jiffies that is collected by
-+ the LRNG for statistical analysis. This data is used for
-+ seeding the LRNG if a high-resolution time stamp is not
-+ available. If a high-resolution time stamp is detected,
-+ the Jiffies value is not collected by the LRNG and no
-+ data is provided via the test interface. Extracted noise
-+ data is not used to seed the random number generator.
-+
-+ The raw noise data can be obtained using the lrng_raw_jiffies
-+ debugfs file. Using the option lrng_testing.boot_raw_jiffies_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_IRQ_ENTROPY
-+ bool "Enable entropy test interface to IRQ number noise source"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned interrupt number that is collected by
-+ the LRNG for statistical analysis. This data is used for
-+ seeding the random32 PRNG external to the LRNG if a
-+ high-resolution time stamp is available or it will be used to
-+ seed the LRNG otherwise. Extracted noise data is not used to
-+ seed the random number generator.
-+
-+ The raw noise data can be obtained using the lrng_raw_irq
-+ debugfs file. Using the option lrng_testing.boot_raw_irq_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_IRQFLAGS_ENTROPY
-+ bool "Enable entropy test interface to IRQ flags noise source"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned interrupt flags that is collected by
-+ the LRNG for statistical analysis. This data is used for
-+ seeding the random32 PRNG external to the LRNG if a
-+ high-resolution time stamp is available or it will be used to
-+ seed the LRNG otherwise. Extracted noise data is not used to
-+ seed the random number generator.
-+
-+ The raw noise data can be obtained using the lrng_raw_irqflags
-+ debugfs file. Using the option lrng_testing.boot_raw_irqflags_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_RETIP_ENTROPY
-+ bool "Enable entropy test interface to RETIP value noise source"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned return instruction pointer value
-+ that is collected by the LRNG for statistical analysis.
-+ This data is used for seeding the random32 PRNG external
-+ to the LRNG if a high-resolution time stamp is available or
-+ it will be used to seed the LRNG otherwise. Extracted noise
-+ data is not used to seed the random number generator.
-+
-+ The raw noise data can be obtained using the lrng_raw_retip
-+ debugfs file. Using the option lrng_testing.boot_raw_retip_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_REGS_ENTROPY
-+ bool "Enable entropy test interface to IRQ register value noise source"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw unconditioned interrupt register value that is
-+ collected by the LRNG for statistical analysis. Extracted noise
-+ data is not used to seed the random number generator.
-+
-+ The raw noise data can be obtained using the lrng_raw_regs
-+ debugfs file. Using the option lrng_testing.boot_raw_regs_test=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_RAW_ARRAY
-+ bool "Enable test interface to LRNG raw entropy storage array"
-+ help
-+ The test interface allows a privileged process to capture
-+ the raw noise data that is collected by the LRNG
-+ in the per-CPU array for statistical analysis. The purpose
-+ of this interface is to verify that the array handling code
-+ truly only concatenates data and provides the same entropy
-+ rate as the raw unconditioned noise source when assessing
-+ the collected data byte-wise.
-+
-+ The data can be obtained using the lrng_raw_array debugfs
-+ file. Using the option lrng_testing.boot_raw_array=1
-+ the raw noise of the first 1000 entropy events since boot
-+ can be sampled.
-+
-+config LRNG_IRQ_PERF
-+ bool "Enable LRNG interrupt performance monitor"
-+ help
-+ With this option, the performance monitor of the LRNG
-+ interrupt handling code is enabled. The file provides
-+ the execution time of the interrupt handler in
-+ cycles.
-+
-+ The interrupt performance data can be obtained using
-+ the lrng_irq_perf debugfs file. Using the option
-+ lrng_testing.boot_irq_perf=1 the performance data of
-+ the first 1000 entropy events since boot can be sampled.
-+
-+config LRNG_ACVT_HASH
-+ bool "Enable LRNG ACVT Hash interface"
-+ help
-+ With this option, the LRNG built-in hash function used for
-+ auxiliary pool management and prior to switching the
-+ cryptographic backends is made available for ACVT. The
-+ interface allows writing of the data to be hashed
-+ into the interface. The read operation triggers the hash
-+ operation to generate message digest.
-+
-+ The ACVT interface is available with the lrng_acvt_hash
-+ debugfs file.
-+
-+config LRNG_RUNTIME_ES_CONFIG
-+ bool "Enable runtime configuration of entropy sources"
-+ help
-+ When enabling this option, the LRNG provides the mechanism
-+ allowing to alter the entropy rate of each entropy source
-+ during boot time and runtime.
-+
-+ The following interfaces are available:
-+ lrng_archrandom.archrandom for the CPU entropy source,
-+ lrng_jent.jitterrng for the Jitter RNG entropy source, and
-+ lrng_sw_noise.irq_entropy for the interrupt entropy source.
-+
-+config LRNG_RUNTIME_MAX_WO_RESEED_CONFIG
-+ bool "Enable runtime configuration of max reseed threshold"
-+ help
-+ When enabling this option, the LRNG provides an interface
-+ allowing the setting of the maximum number of DRNG generate
-+ operations without a reseed that has full entropy. The
-+ interface is lrng_drng.max_wo_reseed.
-+
-+config LRNG_TEST_CPU_ES_COMPRESSION
-+ bool "Force CPU ES compression operation"
-+ help
-+ When enabling this option, the CPU ES compression operation
-+ is forced by setting an arbitrary value > 1 for the data
-+ multiplier even when the CPU ES would deliver full entropy.
-+ This allows testing of the compression operation. It
-+ therefore forces to pull more data from the CPU ES
-+ than what may be required.
-+
-+config LRNG_TESTING
-+ bool
-+ default y if (LRNG_RAW_HIRES_ENTROPY || LRNG_RAW_JIFFIES_ENTROPY ||LRNG_RAW_IRQ_ENTROPY || LRNG_RAW_IRQFLAGS_ENTROPY || LRNG_RAW_RETIP_ENTROPY || LRNG_RAW_REGS_ENTROPY || LRNG_RAW_ARRAY || LRNG_IRQ_PERF || LRNG_ACVT_HASH)
-+
-+endif #LRNG_TESTING_MENU
-+
-+config LRNG_SELFTEST
-+ bool "Enable power-on and on-demand self-tests"
-+ help
-+ The power-on self-tests are executed during boot time
-+ covering the ChaCha20 DRNG, the hash operation used for
-+ processing the entropy pools and the auxiliary pool, and
-+ the time stamp management of the LRNG.
-+
-+ The on-demand self-tests are triggered by writing any
-+ value into the SysFS file selftest_status. At the same
-+ time, when reading this file, the test status is
-+ returned. A zero indicates that all tests were executed
-+ successfully.
-+
-+ If unsure, say Y.
-+
-+if LRNG_SELFTEST
-+
-+config LRNG_SELFTEST_PANIC
-+ bool "Panic the kernel upon self-test failure"
-+ help
-+ If the option is enabled, the kernel is terminated if an
-+ LRNG power-on self-test failure is detected.
-+
-+endif # LRNG_SELFTEST
-+
-+endif # LRNG
-diff -urN linux-5.15/drivers/char/lrng/Makefile linux-5.15-lrng/drivers/char/lrng/Makefile
---- linux-5.15/drivers/char/lrng/Makefile 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/Makefile 2021-11-29 12:38:26.593278813 +1100
-@@ -0,0 +1,21 @@
-+# SPDX-License-Identifier: GPL-2.0
-+#
-+# Makefile for the Linux Random Number Generator.
-+#
-+
-+obj-y += lrng_es_mgr.o lrng_aux.o \
-+ lrng_drng.o lrng_chacha20.o \
-+ lrng_interfaces.o lrng_es_aux.o
-+
-+obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o
-+obj-$(CONFIG_SYSCTL) += lrng_proc.o
-+obj-$(CONFIG_NUMA) += lrng_numa.o
-+obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o
-+obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o
-+obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o
-+obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o
-+obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o
-+obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o
-+obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o
-+obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o
-+obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o
-diff -urN linux-5.15/drivers/char/lrng/lrng_aux.c linux-5.15-lrng/drivers/char/lrng/lrng_aux.c
---- linux-5.15/drivers/char/lrng/lrng_aux.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_aux.c 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,136 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG auxiliary interfaces
-+ *
-+ * Copyright (C) 2019 - 2021 Stephan Mueller <smueller@chronox.de>
-+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
-+ * Rights Reserved.
-+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
-+ */
-+
-+#include <linux/mm.h>
-+#include <linux/random.h>
-+
-+#include "lrng_internal.h"
-+
-+struct batched_entropy {
-+ union {
-+ u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
-+ u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
-+ };
-+ unsigned int position;
-+ spinlock_t batch_lock;
-+};
-+
-+/*
-+ * Get a random word for internal kernel use only. The quality of the random
-+ * number is as good as /dev/urandom, but there is no backtrack protection,
-+ * with the goal of being quite fast and not depleting entropy.
-+ */
-+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
-+ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
-+};
-+
-+u64 get_random_u64(void)
-+{
-+ u64 ret;
-+ unsigned long flags;
-+ struct batched_entropy *batch;
-+
-+ lrng_debug_report_seedlevel("get_random_u64");
-+
-+ batch = raw_cpu_ptr(&batched_entropy_u64);
-+ spin_lock_irqsave(&batch->batch_lock, flags);
-+ if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
-+ lrng_drng_get_atomic((u8 *)batch->entropy_u64,
-+ LRNG_DRNG_BLOCKSIZE);
-+ batch->position = 0;
-+ }
-+ ret = batch->entropy_u64[batch->position++];
-+ spin_unlock_irqrestore(&batch->batch_lock, flags);
-+ return ret;
-+}
-+EXPORT_SYMBOL(get_random_u64);
-+
-+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
-+ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
-+};
-+
-+u32 get_random_u32(void)
-+{
-+ u32 ret;
-+ unsigned long flags;
-+ struct batched_entropy *batch;
-+
-+ lrng_debug_report_seedlevel("get_random_u32");
-+
-+ batch = raw_cpu_ptr(&batched_entropy_u32);
-+ spin_lock_irqsave(&batch->batch_lock, flags);
-+ if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
-+ lrng_drng_get_atomic((u8 *)batch->entropy_u32,
-+ LRNG_DRNG_BLOCKSIZE);
-+ batch->position = 0;
-+ }
-+ ret = batch->entropy_u32[batch->position++];
-+ spin_unlock_irqrestore(&batch->batch_lock, flags);
-+ return ret;
-+}
-+EXPORT_SYMBOL(get_random_u32);
-+
-+/*
-+ * It's important to invalidate all potential batched entropy that might
-+ * be stored before the crng is initialized, which we can do lazily by
-+ * simply resetting the counter to zero so that it's re-extracted on the
-+ * next usage.
-+ */
-+void invalidate_batched_entropy(void)
-+{
-+ int cpu;
-+ unsigned long flags;
-+
-+ for_each_possible_cpu(cpu) {
-+ struct batched_entropy *batched_entropy;
-+
-+ batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
-+ spin_lock_irqsave(&batched_entropy->batch_lock, flags);
-+ batched_entropy->position = 0;
-+ spin_unlock(&batched_entropy->batch_lock);
-+
-+ batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
-+ spin_lock(&batched_entropy->batch_lock);
-+ batched_entropy->position = 0;
-+ spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
-+ }
-+}
-+
-+/*
-+ * randomize_page - Generate a random, page aligned address
-+ * @start: The smallest acceptable address the caller will take.
-+ * @range: The size of the area, starting at @start, within which the
-+ * random address must fall.
-+ *
-+ * If @start + @range would overflow, @range is capped.
-+ *
-+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
-+ * @start was already page aligned. We now align it regardless.
-+ *
-+ * Return: A page aligned address within [start, start + range). On error,
-+ * @start is returned.
-+ */
-+unsigned long randomize_page(unsigned long start, unsigned long range)
-+{
-+ if (!PAGE_ALIGNED(start)) {
-+ range -= PAGE_ALIGN(start) - start;
-+ start = PAGE_ALIGN(start);
-+ }
-+
-+ if (start > ULONG_MAX - range)
-+ range = ULONG_MAX - start;
-+
-+ range >>= PAGE_SHIFT;
-+
-+ if (range == 0)
-+ return start;
-+
-+ return start + (get_random_long() % range << PAGE_SHIFT);
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_chacha20.c linux-5.15-lrng/drivers/char/lrng/lrng_chacha20.c
---- linux-5.15/drivers/char/lrng/lrng_chacha20.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_chacha20.c 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,321 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Backend for the LRNG providing the cryptographic primitives using
-+ * ChaCha20 cipher implementations.
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <crypto/chacha.h>
-+#include <linux/lrng.h>
-+#include <linux/random.h>
-+#include <linux/slab.h>
-+
-+#include "lrng_chacha20.h"
-+#include "lrng_internal.h"
-+
-+/******************************* ChaCha20 DRNG *******************************/
-+
-+#define CHACHA_BLOCK_WORDS (CHACHA_BLOCK_SIZE / sizeof(u32))
-+
-+struct chacha20_state {
-+ struct chacha20_block block;
-+};
-+
-+/*
-+ * Have a static memory blocks for the ChaCha20 DRNG instance to avoid calling
-+ * kmalloc too early in the boot cycle. For subsequent allocation requests,
-+ * such as per-NUMA-node DRNG instances, kmalloc will be used.
-+ */
-+struct chacha20_state chacha20 __latent_entropy;
-+
-+/*
-+ * Update of the ChaCha20 state by either using an unused buffer part or by
-+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
-+ * The block is XORed into the key part of the state. This shall ensure
-+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
-+ * the key is injected.
-+ */
-+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
-+ __le32 *buf, u32 used_words)
-+{
-+ struct chacha20_block *chacha20 = &chacha20_state->block;
-+ u32 i;
-+ __le32 tmp[CHACHA_BLOCK_WORDS];
-+
-+ BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
-+ BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
-+
-+ if (used_words > CHACHA_KEY_SIZE_WORDS) {
-+ chacha20_block(&chacha20->constants[0], (u8 *)tmp);
-+ for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
-+ chacha20->key.u[i] ^= le32_to_cpu(tmp[i]);
-+ memzero_explicit(tmp, sizeof(tmp));
-+ } else {
-+ for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
-+ chacha20->key.u[i] ^= le32_to_cpu(buf[i + used_words]);
-+ }
-+
-+ /* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
-+ chacha20->nonce[0]++;
-+ if (chacha20->nonce[0] == 0) {
-+ chacha20->nonce[1]++;
-+ if (chacha20->nonce[1] == 0)
-+ chacha20->nonce[2]++;
-+ }
-+
-+ /* Leave counter untouched as it is start value is undefined in RFC */
-+}
-+
-+/*
-+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
-+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
-+ * perform a ChaCha20 operation after processing of key size input data.
-+ * This operation shall spread out the entropy into the ChaCha20 state before
-+ * new entropy is injected into the key part.
-+ */
-+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
-+{
-+ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
-+ struct chacha20_block *chacha20 = &chacha20_state->block;
-+
-+ while (inbuflen) {
-+ u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
-+
-+ for (i = 0; i < todo; i++)
-+ chacha20->key.b[i] ^= inbuf[i];
-+
-+ /* Break potential dependencies between the inbuf key blocks */
-+ lrng_chacha20_update(chacha20_state, NULL,
-+ CHACHA_BLOCK_WORDS);
-+ inbuf += todo;
-+ inbuflen -= todo;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
-+ * is the random number. After the completion of the generation of the
-+ * stream, the entire ChaCha20 state is updated.
-+ *
-+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
-+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
-+ * before a reseed or an update happens. This is ensured by the variable
-+ * outbuflen which is a 32 bit integer defining the number of bytes to be
-+ * generated by the ChaCha20 DRNG. At the end of this function, an update
-+ * operation is invoked which implies that the 32 bit counter will never be
-+ * overflown in this implementation.
-+ */
-+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
-+{
-+ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
-+ struct chacha20_block *chacha20 = &chacha20_state->block;
-+ __le32 aligned_buf[CHACHA_BLOCK_WORDS];
-+ u32 ret = outbuflen, used = CHACHA_BLOCK_WORDS;
-+ int zeroize_buf = 0;
-+
-+ while (outbuflen >= CHACHA_BLOCK_SIZE) {
-+ chacha20_block(&chacha20->constants[0], outbuf);
-+ outbuf += CHACHA_BLOCK_SIZE;
-+ outbuflen -= CHACHA_BLOCK_SIZE;
-+ }
-+
-+ if (outbuflen) {
-+ chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
-+ memcpy(outbuf, aligned_buf, outbuflen);
-+ used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
-+ sizeof(aligned_buf[0]));
-+ zeroize_buf = 1;
-+ }
-+
-+ lrng_chacha20_update(chacha20_state, aligned_buf, used);
-+
-+ if (zeroize_buf)
-+ memzero_explicit(aligned_buf, sizeof(aligned_buf));
-+
-+ return ret;
-+}
-+
-+void lrng_cc20_init_state(struct chacha20_state *state)
-+{
-+ lrng_cc20_init_rfc7539(&state->block);
-+}
-+
-+/*
-+ * Allocation of the DRNG state
-+ */
-+static void *lrng_cc20_drng_alloc(u32 sec_strength)
-+{
-+ struct chacha20_state *state = NULL;
-+
-+ if (sec_strength > CHACHA_KEY_SIZE) {
-+ pr_err("Security strength of ChaCha20 DRNG (%u bits) lower than requested by LRNG (%u bits)\n",
-+ CHACHA_KEY_SIZE * 8, sec_strength * 8);
-+ return ERR_PTR(-EINVAL);
-+ }
-+ if (sec_strength < CHACHA_KEY_SIZE)
-+ pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher than requested by LRNG (%u bits)\n",
-+ CHACHA_KEY_SIZE * 8, sec_strength * 8);
-+
-+ state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
-+ if (!state)
-+ return ERR_PTR(-ENOMEM);
-+ pr_debug("memory for ChaCha20 core allocated\n");
-+
-+ lrng_cc20_init_state(state);
-+
-+ return state;
-+}
-+
-+static void lrng_cc20_drng_dealloc(void *drng)
-+{
-+ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
-+
-+ if (drng == &chacha20) {
-+ memzero_explicit(chacha20_state, sizeof(*chacha20_state));
-+ pr_debug("static ChaCha20 core zeroized\n");
-+ return;
-+ }
-+
-+ pr_debug("ChaCha20 core zeroized and freed\n");
-+ kfree_sensitive(chacha20_state);
-+}
-+
-+/******************************* Hash Operation *******************************/
-+
-+#ifdef CONFIG_CRYPTO_LIB_SHA256
-+
-+#include <crypto/sha2.h>
-+
-+static u32 lrng_cc20_hash_digestsize(void *hash)
-+{
-+ return SHA256_DIGEST_SIZE;
-+}
-+
-+static int lrng_cc20_hash_init(struct shash_desc *shash, void *hash)
-+{
-+ /*
-+ * We do not need a TFM - we only need sufficient space for
-+ * struct sha256_state on the stack.
-+ */
-+ sha256_init(shash_desc_ctx(shash));
-+ return 0;
-+}
-+
-+static int lrng_cc20_hash_update(struct shash_desc *shash,
-+ const u8 *inbuf, u32 inbuflen)
-+{
-+ sha256_update(shash_desc_ctx(shash), inbuf, inbuflen);
-+ return 0;
-+}
-+
-+static int lrng_cc20_hash_final(struct shash_desc *shash, u8 *digest)
-+{
-+ sha256_final(shash_desc_ctx(shash), digest);
-+ return 0;
-+}
-+
-+static const char *lrng_cc20_hash_name(void)
-+{
-+ return "SHA-256";
-+}
-+
-+static void lrng_cc20_hash_desc_zero(struct shash_desc *shash)
-+{
-+ memzero_explicit(shash_desc_ctx(shash), sizeof(struct sha256_state));
-+}
-+
-+#else /* CONFIG_CRYPTO_LIB_SHA256 */
-+
-+#include <crypto/sha1.h>
-+#include <crypto/sha1_base.h>
-+
-+/*
-+ * If the SHA-256 support is not compiled, we fall back to SHA-1 that is always
-+ * compiled and present in the kernel.
-+ */
-+static u32 lrng_cc20_hash_digestsize(void *hash)
-+{
-+ return SHA1_DIGEST_SIZE;
-+}
-+
-+static void lrng_sha1_block_fn(struct sha1_state *sctx, const u8 *src,
-+ int blocks)
-+{
-+ u32 temp[SHA1_WORKSPACE_WORDS];
-+
-+ while (blocks--) {
-+ sha1_transform(sctx->state, src, temp);
-+ src += SHA1_BLOCK_SIZE;
-+ }
-+ memzero_explicit(temp, sizeof(temp));
-+}
-+
-+static int lrng_cc20_hash_init(struct shash_desc *shash, void *hash)
-+{
-+ /*
-+ * We do not need a TFM - we only need sufficient space for
-+ * struct sha1_state on the stack.
-+ */
-+ sha1_base_init(shash);
-+ return 0;
-+}
-+
-+static int lrng_cc20_hash_update(struct shash_desc *shash,
-+ const u8 *inbuf, u32 inbuflen)
-+{
-+ return sha1_base_do_update(shash, inbuf, inbuflen, lrng_sha1_block_fn);
-+}
-+
-+static int lrng_cc20_hash_final(struct shash_desc *shash, u8 *digest)
-+{
-+ return sha1_base_do_finalize(shash, lrng_sha1_block_fn) ?:
-+ sha1_base_finish(shash, digest);
-+}
-+
-+static const char *lrng_cc20_hash_name(void)
-+{
-+ return "SHA-1";
-+}
-+
-+static void lrng_cc20_hash_desc_zero(struct shash_desc *shash)
-+{
-+ memzero_explicit(shash_desc_ctx(shash), sizeof(struct sha1_state));
-+}
-+
-+#endif /* CONFIG_CRYPTO_LIB_SHA256 */
-+
-+static void *lrng_cc20_hash_alloc(void)
-+{
-+ pr_info("Hash %s allocated\n", lrng_cc20_hash_name());
-+ return NULL;
-+}
-+
-+static void lrng_cc20_hash_dealloc(void *hash)
-+{
-+}
-+
-+static const char *lrng_cc20_drng_name(void)
-+{
-+ return "ChaCha20 DRNG";
-+}
-+
-+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
-+ .lrng_drng_name = lrng_cc20_drng_name,
-+ .lrng_hash_name = lrng_cc20_hash_name,
-+ .lrng_drng_alloc = lrng_cc20_drng_alloc,
-+ .lrng_drng_dealloc = lrng_cc20_drng_dealloc,
-+ .lrng_drng_seed_helper = lrng_cc20_drng_seed_helper,
-+ .lrng_drng_generate_helper = lrng_cc20_drng_generate_helper,
-+ .lrng_hash_alloc = lrng_cc20_hash_alloc,
-+ .lrng_hash_dealloc = lrng_cc20_hash_dealloc,
-+ .lrng_hash_digestsize = lrng_cc20_hash_digestsize,
-+ .lrng_hash_init = lrng_cc20_hash_init,
-+ .lrng_hash_update = lrng_cc20_hash_update,
-+ .lrng_hash_final = lrng_cc20_hash_final,
-+ .lrng_hash_desc_zero = lrng_cc20_hash_desc_zero,
-+};
-diff -urN linux-5.15/drivers/char/lrng/lrng_chacha20.h linux-5.15-lrng/drivers/char/lrng/lrng_chacha20.h
---- linux-5.15/drivers/char/lrng/lrng_chacha20.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_chacha20.h 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
-+/*
-+ * LRNG ChaCha20 definitions
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#include <crypto/chacha.h>
-+
-+/* State according to RFC 7539 section 2.3 */
-+struct chacha20_block {
-+ u32 constants[4];
-+ union {
-+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
-+ u32 u[CHACHA_KEY_SIZE_WORDS];
-+ u8 b[CHACHA_KEY_SIZE];
-+ } key;
-+ u32 counter;
-+ u32 nonce[3];
-+};
-+
-+static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20)
-+{
-+ chacha_init_consts(chacha20->constants);
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_drbg.c linux-5.15-lrng/drivers/char/lrng/lrng_drbg.c
---- linux-5.15/drivers/char/lrng/lrng_drbg.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_drbg.c 2021-11-29 12:37:37.193279002 +1100
-@@ -0,0 +1,198 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Backend for the LRNG providing the cryptographic primitives using the
-+ * kernel crypto API and its DRBG.
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <crypto/drbg.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/lrng.h>
-+
-+#include "lrng_kcapi_hash.h"
-+
-+/*
-+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
-+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
-+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
-+ * is not wise). The idea is that the used cipher primitive can be selected to
-+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
-+ * primitive using the same cipher implementation with the options offered in
-+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
-+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
-+ *
-+ * The security strengths of the DRBGs are all 256 bits according to
-+ * SP800-57 section 5.6.1.
-+ *
-+ * This definition is allowed to be changed.
-+ */
-+#ifdef CONFIG_CRYPTO_DRBG_CTR
-+static unsigned int lrng_drbg_type = 0;
-+#elif defined CONFIG_CRYPTO_DRBG_HMAC
-+static unsigned int lrng_drbg_type = 1;
-+#elif defined CONFIG_CRYPTO_DRBG_HASH
-+static unsigned int lrng_drbg_type = 2;
-+#else
-+#error "Unknown DRBG in use"
-+#endif
-+
-+/* The parameter must be r/o in sysfs as otherwise races appear. */
-+module_param(lrng_drbg_type, uint, 0444);
-+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, 1->HMAC_DRBG, 2->Hash_DRBG)");
-+
-+struct lrng_drbg {
-+ const char *hash_name;
-+ const char *drbg_core;
-+};
-+
-+static const struct lrng_drbg lrng_drbg_types[] = {
-+ { /* CTR_DRBG with AES-256 using derivation function */
-+ .hash_name = "sha512",
-+ .drbg_core = "drbg_nopr_ctr_aes256",
-+ }, { /* HMAC_DRBG with SHA-512 */
-+ .hash_name = "sha512",
-+ .drbg_core = "drbg_nopr_hmac_sha512",
-+ }, { /* Hash_DRBG with SHA-512 using derivation function */
-+ .hash_name = "sha512",
-+ .drbg_core = "drbg_nopr_sha512"
-+ }
-+};
-+
-+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
-+{
-+ struct drbg_state *drbg = (struct drbg_state *)drng;
-+ LIST_HEAD(seedlist);
-+ struct drbg_string data;
-+ int ret;
-+
-+ drbg_string_fill(&data, inbuf, inbuflen);
-+ list_add_tail(&data.list, &seedlist);
-+ ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
-+
-+ if (ret >= 0)
-+ drbg->seeded = true;
-+
-+ return ret;
-+}
-+
-+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
-+{
-+ struct drbg_state *drbg = (struct drbg_state *)drng;
-+
-+ return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
-+}
-+
-+static void *lrng_drbg_drng_alloc(u32 sec_strength)
-+{
-+ struct drbg_state *drbg;
-+ int coreref = -1;
-+ bool pr = false;
-+ int ret;
-+
-+ drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
-+ &coreref, &pr);
-+ if (coreref < 0)
-+ return ERR_PTR(-EFAULT);
-+
-+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
-+ if (!drbg)
-+ return ERR_PTR(-ENOMEM);
-+
-+ drbg->core = &drbg_cores[coreref];
-+ drbg->seeded = false;
-+ ret = drbg_alloc_state(drbg);
-+ if (ret)
-+ goto err;
-+
-+ if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
-+ pr_err("Security strength of DRBG (%u bits) lower than requested by LRNG (%u bits)\n",
-+ drbg_sec_strength(drbg->core->flags) * 8,
-+ sec_strength * 8);
-+ goto dealloc;
-+ }
-+
-+ if (sec_strength < drbg_sec_strength(drbg->core->flags))
-+ pr_warn("Security strength of DRBG (%u bits) higher than requested by LRNG (%u bits)\n",
-+ drbg_sec_strength(drbg->core->flags) * 8,
-+ sec_strength * 8);
-+
-+ pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
-+
-+ return drbg;
-+
-+dealloc:
-+ if (drbg->d_ops)
-+ drbg->d_ops->crypto_fini(drbg);
-+ drbg_dealloc_state(drbg);
-+err:
-+ kfree(drbg);
-+ return ERR_PTR(-EINVAL);
-+}
-+
-+static void lrng_drbg_drng_dealloc(void *drng)
-+{
-+ struct drbg_state *drbg = (struct drbg_state *)drng;
-+
-+ if (drbg && drbg->d_ops)
-+ drbg->d_ops->crypto_fini(drbg);
-+ drbg_dealloc_state(drbg);
-+ kfree_sensitive(drbg);
-+ pr_info("DRBG deallocated\n");
-+}
-+
-+static void *lrng_drbg_hash_alloc(void)
-+{
-+ return lrng_kcapi_hash_alloc(lrng_drbg_types[lrng_drbg_type].hash_name);
-+}
-+
-+static const char *lrng_drbg_name(void)
-+{
-+ return lrng_drbg_types[lrng_drbg_type].drbg_core;
-+}
-+
-+static const char *lrng_hash_name(void)
-+{
-+ return lrng_drbg_types[lrng_drbg_type].hash_name;
-+}
-+
-+static const struct lrng_crypto_cb lrng_drbg_crypto_cb = {
-+ .lrng_drng_name = lrng_drbg_name,
-+ .lrng_hash_name = lrng_hash_name,
-+ .lrng_drng_alloc = lrng_drbg_drng_alloc,
-+ .lrng_drng_dealloc = lrng_drbg_drng_dealloc,
-+ .lrng_drng_seed_helper = lrng_drbg_drng_seed_helper,
-+ .lrng_drng_generate_helper = lrng_drbg_drng_generate_helper,
-+ .lrng_hash_alloc = lrng_drbg_hash_alloc,
-+ .lrng_hash_dealloc = lrng_kcapi_hash_dealloc,
-+ .lrng_hash_digestsize = lrng_kcapi_hash_digestsize,
-+ .lrng_hash_init = lrng_kcapi_hash_init,
-+ .lrng_hash_update = lrng_kcapi_hash_update,
-+ .lrng_hash_final = lrng_kcapi_hash_final,
-+ .lrng_hash_desc_zero = lrng_kcapi_hash_zero,
-+};
-+
-+static int __init lrng_drbg_init(void)
-+{
-+ if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
-+ pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
-+ lrng_drbg_type,
-+ (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
-+ return -EAGAIN;
-+ }
-+ return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
-+}
-+
-+static void __exit lrng_drbg_exit(void)
-+{
-+ lrng_set_drng_cb(NULL);
-+}
-+
-+late_initcall(lrng_drbg_init);
-+module_exit(lrng_drbg_exit);
-+MODULE_LICENSE("Dual BSD/GPL");
-+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
-+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-diff -urN linux-5.15/drivers/char/lrng/lrng_drng.c linux-5.15-lrng/drivers/char/lrng/lrng_drng.c
---- linux-5.15/drivers/char/lrng/lrng_drng.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_drng.c 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,451 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG DRNG processing
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/fips.h>
-+#include <linux/lrng.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note,
-+ * this is enforced with the next request of random numbers from the
-+ * DRNG. Setting this value to zero implies a reseeding attempt before every
-+ * generated random number.
-+ */
-+int lrng_drng_reseed_max_time = 600;
-+
-+static atomic_t lrng_avail = ATOMIC_INIT(0);
-+
-+DEFINE_MUTEX(lrng_crypto_cb_update);
-+
-+/* DRNG for /dev/urandom, getrandom(2), get_random_bytes */
-+static struct lrng_drng lrng_drng_init = {
-+ .drng = &chacha20,
-+ .crypto_cb = &lrng_cc20_crypto_cb,
-+ .lock = __MUTEX_INITIALIZER(lrng_drng_init.lock),
-+ .spin_lock = __SPIN_LOCK_UNLOCKED(lrng_drng_init.spin_lock),
-+ .hash_lock = __RW_LOCK_UNLOCKED(lrng_drng_init.hash_lock)
-+};
-+
-+/*
-+ * DRNG for get_random_bytes when called in atomic context. This
-+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
-+ * DRNG switch like the "regular" DRNG. If there was no DRNG switch, the atomic
-+ * DRNG is identical to the "regular" DRNG.
-+ *
-+ * The reason for having this is due to the fact that DRNGs other than
-+ * the ChaCha20 DRNG may sleep.
-+ */
-+static struct lrng_drng lrng_drng_atomic = {
-+ .drng = &chacha20,
-+ .crypto_cb = &lrng_cc20_crypto_cb,
-+ .spin_lock = __SPIN_LOCK_UNLOCKED(lrng_drng_atomic.spin_lock),
-+ .hash_lock = __RW_LOCK_UNLOCKED(lrng_drng_atomic.hash_lock)
-+};
-+
-+static u32 max_wo_reseed = LRNG_DRNG_MAX_WITHOUT_RESEED;
-+#ifdef CONFIG_LRNG_RUNTIME_MAX_WO_RESEED_CONFIG
-+module_param(max_wo_reseed, uint, 0444);
-+MODULE_PARM_DESC(max_wo_reseed,
-+ "Maximum number of DRNG generate operation without full reseed\n");
-+#endif
-+
-+/********************************** Helper ************************************/
-+
-+bool lrng_get_available(void)
-+{
-+ return likely(atomic_read(&lrng_avail));
-+}
-+
-+void lrng_set_available(void)
-+{
-+ atomic_set(&lrng_avail, 1);
-+}
-+
-+struct lrng_drng *lrng_drng_init_instance(void)
-+{
-+ return &lrng_drng_init;
-+}
-+
-+struct lrng_drng *lrng_drng_atomic_instance(void)
-+{
-+ return &lrng_drng_atomic;
-+}
-+
-+void lrng_drng_reset(struct lrng_drng *drng)
-+{
-+ atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
-+ atomic_set(&drng->requests_since_fully_seeded, 0);
-+ drng->last_seeded = jiffies;
-+ drng->fully_seeded = false;
-+ drng->force_reseed = true;
-+ pr_debug("reset DRNG\n");
-+}
-+
-+/* Initialize the default DRNG during boot */
-+static void lrng_drng_seed(struct lrng_drng *drng);
-+void lrng_drngs_init_cc20(bool force_seed)
-+{
-+ unsigned long flags = 0;
-+
-+ if (lrng_get_available())
-+ return;
-+
-+ lrng_drng_lock(&lrng_drng_init, &flags);
-+ if (lrng_get_available()) {
-+ lrng_drng_unlock(&lrng_drng_init, &flags);
-+ if (force_seed)
-+ goto seed;
-+ return;
-+ }
-+
-+ lrng_drng_reset(&lrng_drng_init);
-+ lrng_cc20_init_state(&chacha20);
-+ lrng_drng_unlock(&lrng_drng_init, &flags);
-+
-+ lrng_drng_lock(&lrng_drng_atomic, &flags);
-+ lrng_drng_reset(&lrng_drng_atomic);
-+ /*
-+ * We do not initialize the state of the atomic DRNG as it is identical
-+ * to the DRNG at this point.
-+ */
-+ lrng_drng_unlock(&lrng_drng_atomic, &flags);
-+
-+ lrng_set_available();
-+
-+seed:
-+ /* Seed the DRNG with any entropy available */
-+ if (!lrng_pool_trylock()) {
-+ lrng_drng_seed(&lrng_drng_init);
-+ pr_info("ChaCha20 core initialized with first seeding\n");
-+ lrng_pool_unlock();
-+ } else {
-+ pr_info("ChaCha20 core initialized without seeding\n");
-+ }
-+}
-+
-+bool lrng_sp80090c_compliant(void)
-+{
-+ if (!IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES))
-+ return false;
-+
-+ /* Entropy source hash must be capable of transporting enough entropy */
-+ if (lrng_get_digestsize() <
-+ (lrng_security_strength() + CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS))
-+ return false;
-+
-+ /* SP800-90C only requested in FIPS mode */
-+ return fips_enabled;
-+}
-+
-+/************************* Random Number Generation ***************************/
-+
-+/* Inject a data buffer into the DRNG */
-+static void lrng_drng_inject(struct lrng_drng *drng,
-+ const u8 *inbuf, u32 inbuflen, bool fully_seeded)
-+{
-+ const char *drng_type = unlikely(drng == &lrng_drng_atomic) ?
-+ "atomic" : "regular";
-+ unsigned long flags = 0;
-+
-+ BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
-+ pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
-+ lrng_drng_lock(drng, &flags);
-+ if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng,
-+ inbuf, inbuflen) < 0) {
-+ pr_warn("seeding of %s DRNG failed\n", drng_type);
-+ drng->force_reseed = true;
-+ } else {
-+ int gc = LRNG_DRNG_RESEED_THRESH - atomic_read(&drng->requests);
-+
-+ pr_debug("%s DRNG stats since last seeding: %lu secs; generate calls: %d\n",
-+ drng_type,
-+ (time_after(jiffies, drng->last_seeded) ?
-+ (jiffies - drng->last_seeded) : 0) / HZ, gc);
-+
-+ /* Count the numbers of generate ops since last fully seeded */
-+ if (fully_seeded)
-+ atomic_set(&drng->requests_since_fully_seeded, 0);
-+ else
-+ atomic_add(gc, &drng->requests_since_fully_seeded);
-+
-+ drng->last_seeded = jiffies;
-+ atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
-+ drng->force_reseed = false;
-+
-+ if (!drng->fully_seeded) {
-+ drng->fully_seeded = fully_seeded;
-+ if (drng->fully_seeded)
-+ pr_debug("DRNG fully seeded\n");
-+ }
-+
-+ if (drng->drng == lrng_drng_atomic.drng) {
-+ lrng_drng_atomic.last_seeded = jiffies;
-+ atomic_set(&lrng_drng_atomic.requests,
-+ LRNG_DRNG_RESEED_THRESH);
-+ lrng_drng_atomic.force_reseed = false;
-+ }
-+ }
-+ lrng_drng_unlock(drng, &flags);
-+}
-+
-+/*
-+ * Perform the seeding of the DRNG with data from noise source
-+ */
-+static inline void _lrng_drng_seed(struct lrng_drng *drng)
-+{
-+ struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
-+
-+ lrng_fill_seed_buffer(&seedbuf,
-+ lrng_get_seed_entropy_osr(drng->fully_seeded));
-+ lrng_init_ops(&seedbuf);
-+ lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf),
-+ lrng_fully_seeded(drng->fully_seeded, &seedbuf));
-+ memzero_explicit(&seedbuf, sizeof(seedbuf));
-+}
-+
-+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen);
-+static void lrng_drng_seed(struct lrng_drng *drng)
-+{
-+ _lrng_drng_seed(drng);
-+
-+ BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
-+ LRNG_DRNG_SECURITY_STRENGTH_BITS);
-+
-+ /*
-+ * Reseed atomic DRNG from current DRNG,
-+ *
-+ * We can obtain random numbers from DRNG as the lock type
-+ * chosen by lrng_drng_get is usable with the current caller.
-+ */
-+ if ((drng->drng != lrng_drng_atomic.drng) &&
-+ (lrng_drng_atomic.force_reseed ||
-+ atomic_read(&lrng_drng_atomic.requests) <= 0 ||
-+ time_after(jiffies, lrng_drng_atomic.last_seeded +
-+ lrng_drng_reseed_max_time * HZ))) {
-+ u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
-+ __aligned(LRNG_KCAPI_ALIGN);
-+ int ret = lrng_drng_get(drng, seedbuf, sizeof(seedbuf));
-+
-+ if (ret < 0) {
-+ pr_warn("Error generating random numbers for atomic DRNG: %d\n",
-+ ret);
-+ } else {
-+ lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret, true);
-+ }
-+ memzero_explicit(&seedbuf, sizeof(seedbuf));
-+ }
-+}
-+
-+static inline void _lrng_drng_seed_work(struct lrng_drng *drng, u32 node)
-+{
-+ pr_debug("reseed triggered by interrupt noise source for DRNG on NUMA node %d\n",
-+ node);
-+ lrng_drng_seed(drng);
-+ if (drng->fully_seeded) {
-+ /* Prevent reseed storm */
-+ drng->last_seeded += node * 100 * HZ;
-+ /* Prevent draining of pool on idle systems */
-+ lrng_drng_reseed_max_time += 100;
-+ }
-+}
-+
-+/*
-+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
-+ */
-+void lrng_drng_seed_work(struct work_struct *dummy)
-+{
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ u32 node;
-+
-+ if (lrng_drng) {
-+ for_each_online_node(node) {
-+ struct lrng_drng *drng = lrng_drng[node];
-+
-+ if (drng && !drng->fully_seeded) {
-+ _lrng_drng_seed_work(drng, node);
-+ goto out;
-+ }
-+ }
-+ } else {
-+ if (!lrng_drng_init.fully_seeded) {
-+ _lrng_drng_seed_work(&lrng_drng_init, 0);
-+ goto out;
-+ }
-+ }
-+
-+ lrng_pool_all_numa_nodes_seeded(true);
-+
-+out:
-+ /* Allow the seeding operation to be called again */
-+ lrng_pool_unlock();
-+}
-+
-+/* Force all DRNGs to reseed before next generation */
-+void lrng_drng_force_reseed(void)
-+{
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ u32 node;
-+
-+ /*
-+ * If the initial DRNG is over the reseed threshold, allow a forced
-+ * reseed only for the initial DRNG as this is the fallback for all. It
-+ * must be kept seeded before all others to keep the LRNG operational.
-+ */
-+ if (!lrng_drng ||
-+ (atomic_read_u32(&lrng_drng_init.requests_since_fully_seeded) >
-+ LRNG_DRNG_RESEED_THRESH)) {
-+ lrng_drng_init.force_reseed = lrng_drng_init.fully_seeded;
-+ pr_debug("force reseed of initial DRNG\n");
-+ return;
-+ }
-+ for_each_online_node(node) {
-+ struct lrng_drng *drng = lrng_drng[node];
-+
-+ if (!drng)
-+ continue;
-+
-+ drng->force_reseed = drng->fully_seeded;
-+ pr_debug("force reseed of DRNG on node %u\n", node);
-+ }
-+ lrng_drng_atomic.force_reseed = lrng_drng_atomic.fully_seeded;
-+}
-+
-+/*
-+ * lrng_drng_get() - Get random data out of the DRNG which is reseeded
-+ * frequently.
-+ *
-+ * @outbuf: buffer for storing random data
-+ * @outbuflen: length of outbuf
-+ *
-+ * Return:
-+ * * < 0 in error case (DRNG generation or update failed)
-+ * * >=0 returning the returned number of bytes
-+ */
-+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen)
-+{
-+ unsigned long flags = 0;
-+ u32 processed = 0;
-+
-+ if (!outbuf || !outbuflen)
-+ return 0;
-+
-+ outbuflen = min_t(size_t, outbuflen, INT_MAX);
-+
-+ lrng_drngs_init_cc20(false);
-+
-+ /* If DRNG operated without proper reseed for too long, block LRNG */
-+ BUILD_BUG_ON(LRNG_DRNG_MAX_WITHOUT_RESEED < LRNG_DRNG_RESEED_THRESH);
-+ if (atomic_read_u32(&drng->requests_since_fully_seeded) > max_wo_reseed)
-+ lrng_unset_fully_seeded(drng);
-+
-+ while (outbuflen) {
-+ u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
-+ int ret;
-+
-+ /* All but the atomic DRNG are seeded during generation */
-+ if (atomic_dec_and_test(&drng->requests) ||
-+ drng->force_reseed ||
-+ time_after(jiffies, drng->last_seeded +
-+ lrng_drng_reseed_max_time * HZ)) {
-+ if (likely(drng != &lrng_drng_atomic)) {
-+ if (lrng_pool_trylock()) {
-+ drng->force_reseed = true;
-+ } else {
-+ lrng_drng_seed(drng);
-+ lrng_pool_unlock();
-+ }
-+ }
-+ }
-+
-+ lrng_drng_lock(drng, &flags);
-+ ret = drng->crypto_cb->lrng_drng_generate_helper(
-+ drng->drng, outbuf + processed, todo);
-+ lrng_drng_unlock(drng, &flags);
-+ if (ret <= 0) {
-+ pr_warn("getting random data from DRNG failed (%d)\n",
-+ ret);
-+ return -EFAULT;
-+ }
-+ processed += ret;
-+ outbuflen -= ret;
-+ }
-+
-+ return processed;
-+}
-+
-+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_drng_get(&lrng_drng_atomic, outbuf, outbuflen);
-+}
-+
-+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen)
-+{
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ struct lrng_drng *drng = &lrng_drng_init;
-+ int node = numa_node_id();
-+
-+ might_sleep();
-+
-+ if (lrng_drng && lrng_drng[node] && lrng_drng[node]->fully_seeded)
-+ drng = lrng_drng[node];
-+
-+ return lrng_drng_get(drng, outbuf, outbuflen);
-+}
-+
-+/* Reset LRNG such that all existing entropy is gone */
-+static void _lrng_reset(struct work_struct *work)
-+{
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ unsigned long flags = 0;
-+
-+ if (!lrng_drng) {
-+ lrng_drng_lock(&lrng_drng_init, &flags);
-+ lrng_drng_reset(&lrng_drng_init);
-+ lrng_drng_unlock(&lrng_drng_init, &flags);
-+ } else {
-+ u32 node;
-+
-+ for_each_online_node(node) {
-+ struct lrng_drng *drng = lrng_drng[node];
-+
-+ if (!drng)
-+ continue;
-+ lrng_drng_lock(drng, &flags);
-+ lrng_drng_reset(drng);
-+ lrng_drng_unlock(drng, &flags);
-+ }
-+ }
-+ lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS);
-+
-+ lrng_reset_state();
-+}
-+
-+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
-+
-+void lrng_reset(void)
-+{
-+ schedule_work(&lrng_reset_work);
-+}
-+
-+/***************************** Initialize LRNG *******************************/
-+
-+static int __init lrng_init(void)
-+{
-+ lrng_drngs_init_cc20(false);
-+
-+ lrng_drngs_numa_alloc();
-+ return 0;
-+}
-+
-+late_initcall(lrng_init);
-+
-+MODULE_LICENSE("Dual BSD/GPL");
-+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
-+MODULE_DESCRIPTION("Linux Random Number Generator");
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_archrandom.c linux-5.15-lrng/drivers/char/lrng/lrng_es_archrandom.c
---- linux-5.15/drivers/char/lrng/lrng_es_archrandom.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_archrandom.c 2021-11-29 12:37:14.483279088 +1100
-@@ -0,0 +1,226 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG Fast Entropy Source: CPU-based entropy source
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <crypto/hash.h>
-+#include <linux/lrng.h>
-+#include <linux/random.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
-+ * As we have no ability to review the implementation of those noise sources,
-+ * it is prudent to have a conservative estimate here.
-+ */
-+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE
-+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
-+#ifdef CONFIG_RANDOM_TRUST_CPU
-+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
-+#else
-+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
-+#endif
-+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG
-+module_param(archrandom, uint, 0644);
-+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDSEED)");
-+#endif
-+
-+static int __init lrng_parse_trust_cpu(char *arg)
-+{
-+ int ret;
-+ bool trust_cpu = false;
-+
-+ ret = kstrtobool(arg, &trust_cpu);
-+ if (ret)
-+ return ret;
-+
-+ if (trust_cpu) {
-+ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
-+ lrng_pool_add_entropy();
-+ } else {
-+ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
-+ }
-+
-+ return 0;
-+}
-+early_param("random.trust_cpu", lrng_parse_trust_cpu);
-+
-+u32 lrng_archrandom_entropylevel(u32 requested_bits)
-+{
-+ return lrng_fast_noise_entropylevel(archrandom, requested_bits);
-+}
-+
-+static u32 lrng_get_arch_data(u8 *outbuf, u32 requested_bits)
-+{
-+ u32 i;
-+
-+ /* operate on full blocks */
-+ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
-+ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS %
-+ sizeof(unsigned long));
-+ /* ensure we have aligned buffers */
-+ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
-+
-+ for (i = 0; i < (requested_bits >> 3);
-+ i += sizeof(unsigned long)) {
-+ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
-+ !arch_get_random_long((unsigned long *)(outbuf + i))) {
-+ archrandom = 0;
-+ return 0;
-+ }
-+ }
-+
-+ return requested_bits;
-+}
-+
-+static u32 inline lrng_get_arch_data_compress(u8 *outbuf, u32 requested_bits,
-+ u32 data_multiplier)
-+{
-+ SHASH_DESC_ON_STACK(shash, NULL);
-+ const struct lrng_crypto_cb *crypto_cb;
-+ struct lrng_drng *drng = lrng_drng_init_instance();
-+ unsigned long flags;
-+ u32 ent_bits = 0, i, partial_bits = 0,
-+ full_bits = requested_bits * data_multiplier;
-+ void *hash;
-+
-+ /* Calculate oversampling for SP800-90C */
-+ if (lrng_sp80090c_compliant()) {
-+ /* Complete amount of bits to be pulled */
-+ full_bits += CONFIG_LRNG_OVERSAMPLE_ES_BITS * data_multiplier;
-+ /* Full blocks that will be pulled */
-+ data_multiplier = full_bits / requested_bits;
-+ /* Partial block in bits to be pulled */
-+ partial_bits = full_bits - (data_multiplier * requested_bits);
-+ }
-+
-+ lrng_hash_lock(drng, &flags);
-+ crypto_cb = drng->crypto_cb;
-+ hash = drng->hash;
-+
-+ if (crypto_cb->lrng_hash_init(shash, hash))
-+ goto out;
-+
-+ /* Hash all data from the CPU entropy source */
-+ for (i = 0; i < data_multiplier; i++) {
-+ ent_bits = lrng_get_arch_data(outbuf, requested_bits);
-+ if (!ent_bits)
-+ goto out;
-+
-+ if (crypto_cb->lrng_hash_update(shash, outbuf, ent_bits >> 3))
-+ goto err;
-+ }
-+
-+ /* Hash partial block, if applicable */
-+ ent_bits = lrng_get_arch_data(outbuf, partial_bits);
-+ if (ent_bits &&
-+ crypto_cb->lrng_hash_update(shash, outbuf, ent_bits >> 3))
-+ goto err;
-+
-+ pr_debug("pulled %u bits from CPU RNG entropy source\n", full_bits);
-+
-+ /* Generate the compressed data to be returned to the caller */
-+ ent_bits = crypto_cb->lrng_hash_digestsize(hash) << 3;
-+ if (requested_bits < ent_bits) {
-+ u8 digest[LRNG_MAX_DIGESTSIZE];
-+
-+ if (crypto_cb->lrng_hash_final(shash, digest))
-+ goto err;
-+
-+ /* Truncate output data to requested size */
-+ memcpy(outbuf, digest, requested_bits >> 3);
-+ memzero_explicit(digest, crypto_cb->lrng_hash_digestsize(hash));
-+ ent_bits = requested_bits;
-+ } else {
-+ if (crypto_cb->lrng_hash_final(shash, outbuf))
-+ goto err;
-+ }
-+
-+out:
-+ crypto_cb->lrng_hash_desc_zero(shash);
-+ lrng_hash_unlock(drng, flags);
-+ return ent_bits;
-+
-+err:
-+ ent_bits = 0;
-+ goto out;
-+}
-+
-+/*
-+ * If CPU entropy source requires does not return full entropy, return the
-+ * multiplier of how much data shall be sampled from it.
-+ */
-+static u32 lrng_arch_multiplier(void)
-+{
-+ static u32 data_multiplier = 0;
-+
-+ if (data_multiplier > 0) {
-+ return data_multiplier;
-+ } else {
-+ unsigned long v;
-+
-+ if (IS_ENABLED(CONFIG_X86) && !arch_get_random_seed_long(&v)) {
-+ /*
-+ * Intel SPEC: pulling 512 blocks from RDRAND ensures
-+ * one reseed making it logically equivalent to RDSEED.
-+ */
-+ data_multiplier = 512;
-+ } else if (IS_ENABLED(CONFIG_PPC)) {
-+ /*
-+ * PowerISA defines DARN to deliver at least 0.5 bits of
-+ * entropy per data bit.
-+ */
-+ data_multiplier = 2;
-+ } else {
-+ /* CPU provides full entropy */
-+ data_multiplier = CONFIG_LRNG_CPU_FULL_ENT_MULTIPLIER;
-+ }
-+ }
-+ return data_multiplier;
-+}
-+
-+/*
-+ * lrng_get_arch() - Get CPU entropy source entropy
-+ *
-+ * @outbuf: buffer to store entropy of size requested_bits
-+ *
-+ * Return:
-+ * * > 0 on success where value provides the added entropy in bits
-+ * * 0 if no fast source was available
-+ */
-+u32 lrng_get_arch(u8 *outbuf, u32 requested_bits)
-+{
-+ u32 ent_bits, data_multiplier = lrng_arch_multiplier();
-+
-+ if (data_multiplier <= 1) {
-+ ent_bits = lrng_get_arch_data(outbuf, requested_bits);
-+ } else {
-+ ent_bits = lrng_get_arch_data_compress(outbuf, requested_bits,
-+ data_multiplier);
-+ }
-+
-+ ent_bits = lrng_archrandom_entropylevel(ent_bits);
-+ pr_debug("obtained %u bits of entropy from CPU RNG entropy source\n",
-+ ent_bits);
-+ return ent_bits;
-+}
-+
-+void lrng_arch_es_state(unsigned char *buf, size_t buflen)
-+{
-+ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+ u32 data_multiplier = lrng_arch_multiplier();
-+
-+ /* Assume the lrng_drng_init lock is taken by caller */
-+ snprintf(buf, buflen,
-+ "CPU ES properties:\n"
-+ " Hash for compressing data: %s\n"
-+ " Data multiplier: %u\n",
-+ (data_multiplier <= 1) ?
-+ "N/A" : lrng_drng_init->crypto_cb->lrng_hash_name(),
-+ data_multiplier);
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_aux.c linux-5.15-lrng/drivers/char/lrng/lrng_es_aux.c
---- linux-5.15/drivers/char/lrng/lrng_es_aux.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_aux.c 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,294 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG Slow Entropy Source: Auxiliary entropy pool
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/lrng.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * This is the auxiliary pool
-+ *
-+ * The aux pool array is aligned to 8 bytes to comfort the kernel crypto API
-+ * cipher implementations of the hash functions used to read the pool: for some
-+ * accelerated implementations, we need an alignment to avoid a realignment
-+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
-+ * implementations.
-+ */
-+struct lrng_pool {
-+ u8 aux_pool[LRNG_POOL_SIZE]; /* Aux pool: digest state */
-+ atomic_t aux_entropy_bits;
-+ atomic_t digestsize; /* Digest size of used hash */
-+ bool initialized; /* Aux pool initialized? */
-+
-+ /* Serialize read of entropy pool and update of aux pool */
-+ spinlock_t lock;
-+};
-+
-+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
-+ .aux_entropy_bits = ATOMIC_INIT(0),
-+ .digestsize = ATOMIC_INIT(LRNG_ATOMIC_DIGEST_SIZE),
-+ .initialized = false,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
-+};
-+
-+/********************************** Helper ***********************************/
-+
-+/* Entropy in bits present in aux pool */
-+u32 lrng_avail_aux_entropy(void)
-+{
-+ /* Cap available entropy with max entropy */
-+ u32 avail_bits = min_t(u32, lrng_get_digestsize(),
-+ atomic_read_u32(&lrng_pool.aux_entropy_bits));
-+
-+ /* Consider oversampling rate due to aux pool conditioning */
-+ return lrng_reduce_by_osr(avail_bits);
-+}
-+
-+/* Set the digest size of the used hash in bytes */
-+static inline void lrng_set_digestsize(u32 digestsize)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ u32 ent_bits = atomic_xchg_relaxed(&pool->aux_entropy_bits, 0),
-+ old_digestsize = lrng_get_digestsize();
-+
-+ atomic_set(&lrng_pool.digestsize, digestsize);
-+
-+ /*
-+ * Update the /proc/.../write_wakeup_threshold which must not be larger
-+ * than the digest size of the curent conditioning hash.
-+ */
-+ digestsize <<= 3;
-+ lrng_proc_update_max_write_thresh(digestsize);
-+ if (lrng_write_wakeup_bits > digestsize)
-+ lrng_write_wakeup_bits = digestsize;
-+
-+ /*
-+ * In case the new digest is larger than the old one, cap the available
-+ * entropy to the old message digest used to process the existing data.
-+ */
-+ ent_bits = min_t(u32, ent_bits, old_digestsize);
-+ atomic_add(ent_bits, &pool->aux_entropy_bits);
-+}
-+
-+/* Obtain the digest size provided by the used hash in bits */
-+u32 lrng_get_digestsize(void)
-+{
-+ return atomic_read_u32(&lrng_pool.digestsize) << 3;
-+}
-+
-+/* Set entropy content in user-space controllable aux pool */
-+void lrng_pool_set_entropy(u32 entropy_bits)
-+{
-+ atomic_set(&lrng_pool.aux_entropy_bits, entropy_bits);
-+}
-+
-+/*
-+ * Replace old with new hash for auxiliary pool handling
-+ *
-+ * Assumption: the caller must guarantee that the new_cb is available during the
-+ * entire operation (e.g. it must hold the write lock against pointer updating).
-+ */
-+int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash,
-+ const struct lrng_crypto_cb *old_cb)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
-+ u8 digest[LRNG_MAX_DIGESTSIZE];
-+ int ret;
-+
-+ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH))
-+ return -EOPNOTSUPP;
-+
-+ if (unlikely(!pool->initialized))
-+ return 0;
-+
-+ /* Get the aux pool hash with old digest ... */
-+ ret = old_cb->lrng_hash_final(shash, digest) ?:
-+ /* ... re-initialize the hash with the new digest ... */
-+ new_cb->lrng_hash_init(shash, new_hash) ?:
-+ /*
-+ * ... feed the old hash into the new state. We may feed
-+ * uninitialized memory into the new state, but this is
-+ * considered no issue and even good as we have some more
-+ * uncertainty here.
-+ */
-+ new_cb->lrng_hash_update(shash, digest, sizeof(digest));
-+ if (!ret) {
-+ lrng_set_digestsize(new_cb->lrng_hash_digestsize(new_hash));
-+ pr_debug("Re-initialize aux entropy pool with hash %s\n",
-+ new_cb->lrng_hash_name());
-+ }
-+
-+ memzero_explicit(digest, sizeof(digest));
-+ return ret;
-+}
-+
-+/* Insert data into auxiliary pool by using the hash update function. */
-+static int
-+lrng_pool_insert_aux_locked(const u8 *inbuf, u32 inbuflen, u32 entropy_bits)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
-+ struct lrng_drng *drng = lrng_drng_init_instance();
-+ const struct lrng_crypto_cb *crypto_cb;
-+ unsigned long flags;
-+ void *hash;
-+ int ret;
-+
-+ entropy_bits = min_t(u32, entropy_bits, inbuflen << 3);
-+
-+ lrng_hash_lock(drng, &flags);
-+
-+ crypto_cb = drng->crypto_cb;
-+ hash = drng->hash;
-+
-+ if (unlikely(!pool->initialized)) {
-+ ret = crypto_cb->lrng_hash_init(shash, hash);
-+ if (ret)
-+ goto out;
-+ pool->initialized = true;
-+ }
-+
-+ ret = crypto_cb->lrng_hash_update(shash, inbuf, inbuflen);
-+ if (ret)
-+ goto out;
-+
-+ /*
-+ * Cap the available entropy to the hash output size compliant to
-+ * SP800-90B section 3.1.5.1 table 1.
-+ */
-+ entropy_bits += atomic_read_u32(&pool->aux_entropy_bits);
-+ atomic_set(&pool->aux_entropy_bits,
-+ min_t(u32, entropy_bits,
-+ crypto_cb->lrng_hash_digestsize(hash) << 3));
-+
-+out:
-+ lrng_hash_unlock(drng, flags);
-+ return ret;
-+}
-+
-+int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ unsigned long flags;
-+ int ret;
-+
-+ spin_lock_irqsave(&pool->lock, flags);
-+ ret = lrng_pool_insert_aux_locked(inbuf, inbuflen, entropy_bits);
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+
-+ lrng_pool_add_entropy();
-+
-+ return ret;
-+}
-+
-+/************************* Get data from entropy pool *************************/
-+
-+/*
-+ * Get auxiliary entropy pool and its entropy content for seed buffer.
-+ * Caller must hold lrng_pool.pool->lock.
-+ * @outbuf: buffer to store data in with size requested_bits
-+ * @requested_bits: Requested amount of entropy
-+ * @return: amount of entropy in outbuf in bits.
-+ */
-+static inline u32 lrng_get_aux_pool(u8 *outbuf, u32 requested_bits)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
-+ struct lrng_drng *drng = lrng_drng_init_instance();
-+ const struct lrng_crypto_cb *crypto_cb;
-+ unsigned long flags;
-+ void *hash;
-+ u32 collected_ent_bits, returned_ent_bits, unused_bits = 0,
-+ digestsize;
-+ u8 aux_output[LRNG_MAX_DIGESTSIZE];
-+
-+ if (unlikely(!pool->initialized))
-+ return 0;
-+
-+ lrng_hash_lock(drng, &flags);
-+
-+ crypto_cb = drng->crypto_cb;
-+ hash = drng->hash;
-+ digestsize = crypto_cb->lrng_hash_digestsize(hash);
-+
-+ /* Ensure that no more than the size of aux_pool can be requested */
-+ requested_bits = min_t(u32, requested_bits, (LRNG_MAX_DIGESTSIZE << 3));
-+
-+ /* Cap entropy with entropy counter from aux pool and the used digest */
-+ collected_ent_bits = min_t(u32, digestsize << 3,
-+ atomic_xchg_relaxed(&pool->aux_entropy_bits, 0));
-+
-+ /* We collected too much entropy and put the overflow back */
-+ if (collected_ent_bits > (requested_bits + lrng_compress_osr())) {
-+ /* Amount of bits we collected too much */
-+ unused_bits = collected_ent_bits - requested_bits;
-+ /* Put entropy back */
-+ atomic_add(unused_bits, &pool->aux_entropy_bits);
-+ /* Fix collected entropy */
-+ collected_ent_bits = requested_bits;
-+ }
-+
-+ /* Apply oversampling: discount requested oversampling rate */
-+ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits);
-+
-+ pr_debug("obtained %u bits by collecting %u bits of entropy from aux pool, %u bits of entropy remaining\n",
-+ returned_ent_bits, collected_ent_bits, unused_bits);
-+
-+ /* Get the digest for the aux pool to be returned to the caller ... */
-+ if (crypto_cb->lrng_hash_final(shash, aux_output) ||
-+ /*
-+ * ... and re-initialize the aux state. Do not add the aux pool
-+ * digest for backward secrecy as it will be added with the
-+ * insertion of the complete seed buffer after it has been filled.
-+ */
-+ crypto_cb->lrng_hash_init(shash, hash)) {
-+ returned_ent_bits = 0;
-+ } else {
-+ /*
-+ * Do not truncate the output size exactly to collected_ent_bits
-+ * as the aux pool may contain data that is not credited with
-+ * entropy, but we want to use them to stir the DRNG state.
-+ */
-+ memcpy(outbuf, aux_output, requested_bits >> 3);
-+ }
-+
-+ lrng_hash_unlock(drng, flags);
-+ memzero_explicit(aux_output, digestsize);
-+ return returned_ent_bits;
-+}
-+
-+void lrng_get_backtrack_aux(struct entropy_buf *entropy_buf, u32 requested_bits)
-+{
-+ struct lrng_pool *pool = &lrng_pool;
-+ unsigned long flags;
-+
-+ /* Ensure aux pool extraction and backtracking op are atomic */
-+ spin_lock_irqsave(&pool->lock, flags);
-+
-+ entropy_buf->a_bits = lrng_get_aux_pool(entropy_buf->a, requested_bits);
-+
-+ /* Mix the extracted data back into pool for backtracking resistance */
-+ if (lrng_pool_insert_aux_locked((u8 *)entropy_buf,
-+ sizeof(struct entropy_buf), 0))
-+ pr_warn("Backtracking resistance operation failed\n");
-+
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
-+void lrng_aux_es_state(unsigned char *buf, size_t buflen)
-+{
-+ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+
-+ /* Assume the lrng_drng_init lock is taken by caller */
-+ snprintf(buf, buflen,
-+ "Auxiliary ES properties:\n"
-+ " Hash for operating entropy pool: %s\n",
-+ lrng_drng_init->crypto_cb->lrng_hash_name());
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_irq.c linux-5.15-lrng/drivers/char/lrng/lrng_es_irq.c
---- linux-5.15/drivers/char/lrng/lrng_es_irq.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_irq.c 2021-11-29 12:36:57.763279152 +1100
-@@ -0,0 +1,823 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG Slow Entropy Source: Interrupt data collection
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <asm/irq_regs.h>
-+#include <asm/ptrace.h>
-+#include <crypto/hash.h>
-+#include <linux/gcd.h>
-+#include <linux/lrng.h>
-+#include <linux/random.h>
-+
-+#include "lrng_internal.h"
-+#include "lrng_es_irq.h"
-+
-+/*
-+ * Number of interrupts to be recorded to assume that DRNG security strength
-+ * bits of entropy are received.
-+ * Note: a value below the DRNG security strength should not be defined as this
-+ * may imply the DRNG can never be fully seeded in case other noise
-+ * sources are unavailable.
-+ */
-+#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE
-+
-+
-+/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */
-+static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS;
-+/* Is high-resolution timer present? */
-+static bool lrng_irq_highres_timer = false;
-+
-+static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS;
-+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG
-+module_param(irq_entropy, uint, 0444);
-+MODULE_PARM_DESC(irq_entropy,
-+ "How many interrupts must be collected for obtaining 256 bits of entropy\n");
-+#endif
-+
-+/* Per-CPU array holding concatenated entropy events */
-+static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array)
-+ __aligned(LRNG_KCAPI_ALIGN);
-+static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0;
-+static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0);
-+
-+/*
-+ * The entropy collection is performed by executing the following steps:
-+ * 1. fill up the per-CPU array holding the time stamps
-+ * 2. once the per-CPU array is full, a compression of the data into
-+ * the entropy pool is performed - this happens in interrupt context
-+ *
-+ * If step 2 is not desired in interrupt context, the following boolean
-+ * needs to be set to false. This implies that old entropy data in the
-+ * per-CPU array collected since the last DRNG reseed is overwritten with
-+ * new entropy data instead of retaining the entropy with the compression
-+ * operation.
-+ *
-+ * Impact on entropy:
-+ *
-+ * If continuous compression is enabled, the maximum entropy that is collected
-+ * per CPU between DRNG reseeds is equal to the digest size of the used hash.
-+ *
-+ * If continuous compression is disabled, the maximum number of entropy events
-+ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount
-+ * of events is converted into an entropy statement which then represents the
-+ * maximum amount of entropy collectible per CPU between DRNG reseeds.
-+ */
-+static bool lrng_pcpu_continuous_compression __read_mostly =
-+ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION);
-+
-+#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION
-+module_param(lrng_pcpu_continuous_compression, bool, 0444);
-+MODULE_PARM_DESC(lrng_pcpu_continuous_compression,
-+ "Perform entropy compression if per-CPU entropy data array is full\n");
-+#endif
-+
-+/*
-+ * Per-CPU entropy pool with compressed entropy event
-+ *
-+ * The per-CPU entropy pool is defined as the hash state. New data is simply
-+ * inserted into the entropy pool by performing a hash update operation.
-+ * To read the entropy pool, a hash final must be invoked. However, before
-+ * the entropy pool is released again after a hash final, the hash init must
-+ * be performed.
-+ */
-+static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool)
-+ __aligned(LRNG_KCAPI_ALIGN);
-+/*
-+ * Lock to allow other CPUs to read the pool - as this is only done during
-+ * reseed which is infrequent, this lock is hardly contended.
-+ */
-+static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock);
-+static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false;
-+
-+/* Number of time stamps analyzed to calculate a GCD */
-+#define LRNG_GCD_WINDOW_SIZE 100
-+static u32 lrng_gcd_history[LRNG_GCD_WINDOW_SIZE];
-+static atomic_t lrng_gcd_history_ptr = ATOMIC_INIT(-1);
-+
-+/* The common divisor for all timestamps */
-+static u32 lrng_gcd_timer = 0;
-+
-+static inline bool lrng_gcd_tested(void)
-+{
-+ return (lrng_gcd_timer != 0);
-+}
-+
-+/* Set the GCD for use in IRQ ES - if 0, the GCD calculation is restarted. */
-+static inline void _lrng_gcd_set(u32 running_gcd)
-+{
-+ lrng_gcd_timer = running_gcd;
-+ mb();
-+}
-+
-+static void lrng_gcd_set(u32 running_gcd)
-+{
-+ if (!lrng_gcd_tested()) {
-+ _lrng_gcd_set(running_gcd);
-+ pr_debug("Setting GCD to %u\n", running_gcd);
-+ }
-+}
-+
-+u32 lrng_gcd_analyze(u32 *history, size_t nelem)
-+{
-+ u32 running_gcd = 0;
-+ size_t i;
-+
-+ /* Now perform the analysis on the accumulated time data. */
-+ for (i = 0; i < nelem; i++) {
-+ /*
-+ * NOTE: this would be the place to add more analysis on the
-+ * appropriateness of the timer like checking the presence
-+ * of sufficient variations in the timer.
-+ */
-+
-+ /*
-+ * This calculates the gcd of all the time values. that is
-+ * gcd(time_1, time_2, ..., time_nelem)
-+ *
-+ * Some timers increment by a fixed (non-1) amount each step.
-+ * This code checks for such increments, and allows the library
-+ * to output the number of such changes have occurred.
-+ */
-+ running_gcd = (u32)gcd(history[i], running_gcd);
-+
-+ /* Zeroize data */
-+ history[i] = 0;
-+ }
-+
-+ return running_gcd;
-+}
-+
-+static void lrng_gcd_add_value(u32 time)
-+{
-+ u32 ptr = (u32)atomic_inc_return_relaxed(&lrng_gcd_history_ptr);
-+
-+ if (ptr < LRNG_GCD_WINDOW_SIZE) {
-+ lrng_gcd_history[ptr] = time;
-+ } else if (ptr == LRNG_GCD_WINDOW_SIZE) {
-+ u32 gcd = lrng_gcd_analyze(lrng_gcd_history,
-+ LRNG_GCD_WINDOW_SIZE);
-+
-+ if (!gcd)
-+ gcd = 1;
-+
-+ /*
-+ * Ensure that we have variations in the time stamp below the
-+ * given value. This is just a safety measure to prevent the GCD
-+ * becoming too large.
-+ */
-+ if (gcd >= 1000) {
-+ pr_warn("calculated GCD is larger than expected: %u\n",
-+ gcd);
-+ gcd = 1000;
-+ }
-+
-+ /* Adjust all deltas by the observed (small) common factor. */
-+ lrng_gcd_set(gcd);
-+ atomic_set(&lrng_gcd_history_ptr, 0);
-+ }
-+}
-+
-+/* Return boolean whether LRNG identified presence of high-resolution timer */
-+static bool lrng_pool_highres_timer(void)
-+{
-+ return lrng_irq_highres_timer;
-+}
-+
-+/* Convert entropy in bits into number of IRQs with the same entropy content. */
-+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
-+{
-+ return ((entropy_bits * lrng_irq_entropy_bits) /
-+ LRNG_DRNG_SECURITY_STRENGTH_BITS);
-+}
-+
-+/* Convert number of IRQs into entropy value. */
-+static inline u32 lrng_data_to_entropy(u32 irqnum)
-+{
-+ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
-+ lrng_irq_entropy_bits);
-+}
-+
-+static inline bool lrng_pcpu_pool_online(int cpu)
-+{
-+ return per_cpu(lrng_pcpu_lock_init, cpu);
-+}
-+
-+static void lrng_pcpu_check_compression_state(void)
-+{
-+ /* One pool must hold sufficient entropy for disabled compression */
-+ if (!lrng_pcpu_continuous_compression) {
-+ u32 max_ent = min_t(u32, lrng_get_digestsize(),
-+ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES));
-+ if (max_ent < lrng_security_strength()) {
-+ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n");
-+ lrng_pcpu_continuous_compression = true;
-+ }
-+ }
-+}
-+
-+static int __init lrng_init_time_source(void)
-+{
-+ /* Set a minimum number of interrupts that must be collected */
-+ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy);
-+
-+ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) ||
-+ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) {
-+ /*
-+ * As the highres timer is identified here, previous interrupts
-+ * obtained during boot time are treated like a lowres-timer
-+ * would have been present.
-+ */
-+ lrng_irq_highres_timer = true;
-+ lrng_irq_entropy_bits = irq_entropy;
-+ } else {
-+ u32 new_entropy = irq_entropy * LRNG_IRQ_OVERSAMPLING_FACTOR;
-+
-+ lrng_health_disable();
-+ lrng_irq_highres_timer = false;
-+ lrng_irq_entropy_bits = (irq_entropy < new_entropy) ?
-+ new_entropy : irq_entropy;
-+ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n",
-+ LRNG_IRQ_OVERSAMPLING_FACTOR);
-+ lrng_pcpu_check_compression_state();
-+ }
-+ mb();
-+
-+ return 0;
-+}
-+core_initcall(lrng_init_time_source);
-+
-+/*
-+ * Reset all per-CPU pools - reset entropy estimator but leave the pool data
-+ * that may or may not have entropy unchanged.
-+ */
-+void lrng_pcpu_reset(void)
-+{
-+ int cpu;
-+
-+ /* Trigger GCD calculation anew. */
-+ _lrng_gcd_set(0);
-+
-+ for_each_online_cpu(cpu)
-+ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0);
-+}
-+
-+u32 lrng_pcpu_avail_pool_size(void)
-+{
-+ u32 max_size = 0, max_pool = lrng_get_digestsize();
-+ int cpu;
-+
-+ if (!lrng_pcpu_continuous_compression)
-+ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES);
-+
-+ for_each_online_cpu(cpu) {
-+ if (lrng_pcpu_pool_online(cpu))
-+ max_size += max_pool;
-+ }
-+
-+ return max_size;
-+}
-+
-+/* Return entropy of unused IRQs present in all per-CPU pools. */
-+u32 lrng_pcpu_avail_entropy(void)
-+{
-+ u32 digestsize_irqs, irq = 0;
-+ int cpu;
-+
-+ /* Obtain the cap of maximum numbers of IRQs we count */
-+ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize());
-+ if (!lrng_pcpu_continuous_compression) {
-+ /* Cap to max. number of IRQs the array can hold */
-+ digestsize_irqs = min_t(u32, digestsize_irqs,
-+ LRNG_DATA_NUM_VALUES);
-+ }
-+
-+ for_each_online_cpu(cpu) {
-+ if (!lrng_pcpu_pool_online(cpu))
-+ continue;
-+ irq += min_t(u32, digestsize_irqs,
-+ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs,
-+ cpu)));
-+ }
-+
-+ /* Consider oversampling rate */
-+ return lrng_reduce_by_osr(lrng_data_to_entropy(irq));
-+}
-+
-+/*
-+ * Trigger a switch of the hash implementation for the per-CPU pool.
-+ *
-+ * For each per-CPU pool, obtain the message digest with the old hash
-+ * implementation, initialize the per-CPU pool again with the new hash
-+ * implementation and inject the message digest into the new state.
-+ *
-+ * Assumption: the caller must guarantee that the new_cb is available during the
-+ * entire operation (e.g. it must hold the lock against pointer updating).
-+ */
-+int lrng_pcpu_switch_hash(int node,
-+ const struct lrng_crypto_cb *new_cb, void *new_hash,
-+ const struct lrng_crypto_cb *old_cb)
-+{
-+ u8 digest[LRNG_MAX_DIGESTSIZE];
-+ u32 digestsize_irqs, found_irqs;
-+ int ret = 0, cpu;
-+
-+ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH))
-+ return -EOPNOTSUPP;
-+
-+ for_each_online_cpu(cpu) {
-+ struct shash_desc *pcpu_shash;
-+
-+ /*
-+ * Only switch the per-CPU pools for the current node because
-+ * the crypto_cb only applies NUMA-node-wide.
-+ */
-+ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu))
-+ continue;
-+
-+ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool,
-+ cpu);
-+
-+ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash);
-+ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3);
-+
-+ if (pcpu_shash->tfm == new_hash)
-+ continue;
-+
-+ /* Get the per-CPU pool hash with old digest ... */
-+ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?:
-+ /* ... re-initialize the hash with the new digest ... */
-+ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?:
-+ /*
-+ * ... feed the old hash into the new state. We may feed
-+ * uninitialized memory into the new state, but this is
-+ * considered no issue and even good as we have some more
-+ * uncertainty here.
-+ */
-+ new_cb->lrng_hash_update(pcpu_shash, digest,
-+ sizeof(digest));
-+ if (ret)
-+ goto out;
-+
-+ /*
-+ * In case the new digest is larger than the old one, cap
-+ * the available entropy to the old message digest used to
-+ * process the existing data.
-+ */
-+ found_irqs = atomic_xchg_relaxed(
-+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0);
-+ found_irqs = min_t(u32, found_irqs, digestsize_irqs);
-+ atomic_add_return_relaxed(found_irqs,
-+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu));
-+
-+ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n",
-+ cpu, node, new_cb->lrng_hash_name());
-+ }
-+
-+out:
-+ memzero_explicit(digest, sizeof(digest));
-+ return ret;
-+}
-+
-+/*
-+ * When reading the per-CPU message digest, make sure we use the crypto
-+ * callbacks defined for the NUMA node the per-CPU pool is defined for because
-+ * the LRNG crypto switch support is only atomic per NUMA node.
-+ */
-+static inline u32
-+lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb,
-+ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize)
-+{
-+ struct shash_desc *pcpu_shash =
-+ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu);
-+ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu);
-+ unsigned long flags;
-+ u32 digestsize_irqs, found_irqs;
-+
-+ /* Lock guarding against reading / writing to per-CPU pool */
-+ spin_lock_irqsave(lock, flags);
-+
-+ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash);
-+ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3);
-+
-+ /* Obtain entropy statement like for the entropy pool */
-+ found_irqs = atomic_xchg_relaxed(
-+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0);
-+ /* Cap to maximum amount of data we can hold in hash */
-+ found_irqs = min_t(u32, found_irqs, digestsize_irqs);
-+
-+ /* Cap to maximum amount of data we can hold in array */
-+ if (!lrng_pcpu_continuous_compression)
-+ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES);
-+
-+ /* Store all not-yet compressed data in data array into hash, ... */
-+ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash,
-+ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu),
-+ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?:
-+ /* ... get the per-CPU pool digest, ... */
-+ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?:
-+ /* ... re-initialize the hash, ... */
-+ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?:
-+ /* ... feed the old hash into the new state. */
-+ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize))
-+ found_irqs = 0;
-+
-+ spin_unlock_irqrestore(lock, flags);
-+ return found_irqs;
-+}
-+
-+/*
-+ * Hash all per-CPU pools and return the digest to be used as seed data for
-+ * seeding a DRNG. The caller must guarantee backtracking resistance.
-+ * The function will only copy as much data as entropy is available into the
-+ * caller-provided output buffer.
-+ *
-+ * This function handles the translation from the number of received interrupts
-+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
-+ * which defines how many interrupts must be received to obtain 256 bits of
-+ * entropy. With this value, the function lrng_data_to_entropy converts a given
-+ * data size (received interrupts, requested amount of data, etc.) into an
-+ * entropy statement. lrng_entropy_to_data does the reverse.
-+ *
-+ * @outbuf: buffer to store data in with size requested_bits
-+ * @requested_bits: Requested amount of entropy
-+ * @fully_seeded: indicator whether LRNG is fully seeded
-+ * @return: amount of entropy in outbuf in bits.
-+ */
-+u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded)
-+{
-+ SHASH_DESC_ON_STACK(shash, NULL);
-+ const struct lrng_crypto_cb *crypto_cb;
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ struct lrng_drng *drng = lrng_drng_init_instance();
-+ u8 digest[LRNG_MAX_DIGESTSIZE];
-+ unsigned long flags, flags2;
-+ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs,
-+ returned_ent_bits;
-+ int ret, cpu;
-+ void *hash;
-+
-+ /* Lock guarding replacement of per-NUMA hash */
-+ lrng_hash_lock(drng, &flags);
-+
-+ crypto_cb = drng->crypto_cb;
-+ hash = drng->hash;
-+
-+ /* The hash state of filled with all per-CPU pool hashes. */
-+ ret = crypto_cb->lrng_hash_init(shash, hash);
-+ if (ret)
-+ goto err;
-+
-+ requested_irqs = lrng_entropy_to_data(requested_bits +
-+ lrng_compress_osr());
-+
-+ /*
-+ * Harvest entropy from each per-CPU hash state - even though we may
-+ * have collected sufficient entropy, we will hash all per-CPU pools.
-+ */
-+ for_each_online_cpu(cpu) {
-+ struct lrng_drng *pcpu_drng = drng;
-+ u32 digestsize, pcpu_unused_irqs = 0;
-+ int node = cpu_to_node(cpu);
-+
-+ /* If pool is not online, then no entropy is present. */
-+ if (!lrng_pcpu_pool_online(cpu))
-+ continue;
-+
-+ if (lrng_drng && lrng_drng[node])
-+ pcpu_drng = lrng_drng[node];
-+
-+ if (pcpu_drng == drng) {
-+ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash,
-+ cpu, digest,
-+ &digestsize);
-+ } else {
-+ lrng_hash_lock(pcpu_drng, &flags2);
-+ found_irqs =
-+ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb,
-+ pcpu_drng->hash, cpu,
-+ digest, &digestsize);
-+ lrng_hash_unlock(pcpu_drng, flags2);
-+ }
-+
-+ /* Inject the digest into the state of all per-CPU pools */
-+ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize);
-+ if (ret)
-+ goto err;
-+
-+ collected_irqs += found_irqs;
-+ if (collected_irqs > requested_irqs) {
-+ pcpu_unused_irqs = collected_irqs - requested_irqs;
-+ atomic_add_return_relaxed(pcpu_unused_irqs,
-+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu));
-+ collected_irqs = requested_irqs;
-+ }
-+ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n",
-+ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs);
-+ }
-+
-+ ret = crypto_cb->lrng_hash_final(shash, digest);
-+ if (ret)
-+ goto err;
-+
-+ collected_ent_bits = lrng_data_to_entropy(collected_irqs);
-+ /* Cap to maximum entropy that can ever be generated with given hash */
-+ collected_ent_bits = min_t(u32, collected_ent_bits,
-+ crypto_cb->lrng_hash_digestsize(hash) << 3);
-+ /* Apply oversampling: discount requested oversampling rate */
-+ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits);
-+
-+ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n",
-+ returned_ent_bits, collected_ent_bits);
-+
-+ /*
-+ * Truncate to available entropy as implicitly allowed by SP800-90B
-+ * section 3.1.5.1.1 table 1 which awards truncated hashes full
-+ * entropy.
-+ *
-+ * During boot time, we read requested_bits data with
-+ * returned_ent_bits entropy. In case our conservative entropy
-+ * estimate underestimates the available entropy we can transport as
-+ * much available entropy as possible.
-+ */
-+ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 :
-+ requested_bits >> 3);
-+
-+out:
-+ crypto_cb->lrng_hash_desc_zero(shash);
-+ lrng_hash_unlock(drng, flags);
-+ memzero_explicit(digest, sizeof(digest));
-+ return returned_ent_bits;
-+
-+err:
-+ returned_ent_bits = 0;
-+ goto out;
-+}
-+
-+/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */
-+static inline void lrng_pcpu_array_compress(void)
-+{
-+ struct shash_desc *shash =
-+ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool);
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ struct lrng_drng *drng = lrng_drng_init_instance();
-+ const struct lrng_crypto_cb *crypto_cb;
-+ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock);
-+ unsigned long flags, flags2;
-+ int node = numa_node_id();
-+ void *hash;
-+ bool init = false;
-+
-+ /* Get NUMA-node local hash instance */
-+ if (lrng_drng && lrng_drng[node])
-+ drng = lrng_drng[node];
-+
-+ lrng_hash_lock(drng, &flags);
-+ crypto_cb = drng->crypto_cb;
-+ hash = drng->hash;
-+
-+ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) {
-+ init = true;
-+ spin_lock_init(lock);
-+ this_cpu_write(lrng_pcpu_lock_init, true);
-+ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n",
-+ raw_smp_processor_id(), node,
-+ crypto_cb->lrng_hash_name());
-+ }
-+
-+ spin_lock_irqsave(lock, flags2);
-+
-+ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) {
-+ this_cpu_write(lrng_pcpu_lock_init, false);
-+ pr_warn("Initialization of hash failed\n");
-+ } else if (lrng_pcpu_continuous_compression) {
-+ /* Add entire per-CPU data array content into entropy pool. */
-+ if (crypto_cb->lrng_hash_update(shash,
-+ (u8 *)this_cpu_ptr(lrng_pcpu_array),
-+ LRNG_DATA_ARRAY_SIZE * sizeof(u32)))
-+ pr_warn_ratelimited("Hashing of entropy data failed\n");
-+ }
-+
-+ spin_unlock_irqrestore(lock, flags2);
-+ lrng_hash_unlock(drng, flags);
-+}
-+
-+/* Compress data array into hash */
-+static inline void lrng_pcpu_array_to_hash(u32 ptr)
-+{
-+ u32 *array = this_cpu_ptr(lrng_pcpu_array);
-+
-+ /*
-+ * During boot time the hash operation is triggered more often than
-+ * during regular operation.
-+ */
-+ if (unlikely(!lrng_state_fully_seeded())) {
-+ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK))
-+ return;
-+ } else if (ptr < LRNG_DATA_WORD_MASK) {
-+ return;
-+ }
-+
-+ if (lrng_raw_array_entropy_store(*array)) {
-+ u32 i;
-+
-+ /*
-+ * If we fed even a part of the array to external analysis, we
-+ * mark that the entire array and the per-CPU pool to have no
-+ * entropy. This is due to the non-IID property of the data as
-+ * we do not fully know whether the existing dependencies
-+ * diminish the entropy beyond to what we expect it has.
-+ */
-+ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0);
-+
-+ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++)
-+ lrng_raw_array_entropy_store(*(array + i));
-+ } else {
-+ lrng_pcpu_array_compress();
-+ /* Ping pool handler about received entropy */
-+ lrng_pool_add_entropy();
-+ }
-+}
-+
-+/*
-+ * Concatenate full 32 bit word at the end of time array even when current
-+ * ptr is not aligned to sizeof(data).
-+ */
-+static inline void _lrng_pcpu_array_add_u32(u32 data)
-+{
-+ /* Increment pointer by number of slots taken for input value */
-+ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr,
-+ LRNG_DATA_SLOTS_PER_UINT);
-+ unsigned int pre_array;
-+
-+ /*
-+ * This function injects a unit into the array - guarantee that
-+ * array unit size is equal to data type of input data.
-+ */
-+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3));
-+
-+ /*
-+ * The following logic requires at least two units holding
-+ * the data as otherwise the pointer would immediately wrap when
-+ * injection an u32 word.
-+ */
-+ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT);
-+
-+ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask);
-+
-+ /* MSB of data go into previous unit */
-+ pre_array = lrng_data_idx2array(pre_ptr);
-+ /* zeroization of slot to ensure the following OR adds the data */
-+ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff & ~mask));
-+ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask);
-+
-+ /* Invoke compression as we just filled data array completely */
-+ if (unlikely(pre_ptr > ptr))
-+ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK);
-+
-+ /* LSB of data go into current unit */
-+ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)],
-+ data & mask);
-+
-+ if (likely(pre_ptr <= ptr))
-+ lrng_pcpu_array_to_hash(ptr);
-+}
-+
-+/* Concatenate a 32-bit word at the end of the per-CPU array */
-+void lrng_pcpu_array_add_u32(u32 data)
-+{
-+ /*
-+ * Disregard entropy-less data without continuous compression to
-+ * avoid it overwriting data with entropy when array ptr wraps.
-+ */
-+ if (lrng_pcpu_continuous_compression)
-+ _lrng_pcpu_array_add_u32(data);
-+}
-+
-+/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */
-+static inline void lrng_pcpu_array_add_slot(u32 data)
-+{
-+ /* Get slot */
-+ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) &
-+ LRNG_DATA_WORD_MASK;
-+ unsigned int array = lrng_data_idx2array(ptr);
-+ unsigned int slot = lrng_data_idx2slot(ptr);
-+
-+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS);
-+ /* Ensure consistency of values */
-+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS !=
-+ sizeof(lrng_pcpu_array[0]) << 3);
-+
-+ /* zeroization of slot to ensure the following OR adds the data */
-+ this_cpu_and(lrng_pcpu_array[array],
-+ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK,
-+ slot)));
-+ /* Store data into slot */
-+ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot));
-+
-+ lrng_pcpu_array_to_hash(ptr);
-+}
-+
-+static inline void
-+lrng_time_process_common(u32 time, void(*add_time)(u32 data))
-+{
-+ enum lrng_health_res health_test;
-+
-+ if (lrng_raw_hires_entropy_store(time))
-+ return;
-+
-+ health_test = lrng_health_test(time);
-+ if (health_test > lrng_health_fail_use)
-+ return;
-+
-+ if (health_test == lrng_health_pass)
-+ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs));
-+
-+ add_time(time);
-+}
-+
-+/*
-+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
-+ */
-+static inline void lrng_time_process(void)
-+{
-+ u32 now_time = random_get_entropy();
-+
-+ if (unlikely(!lrng_gcd_tested())) {
-+ /* When GCD is unknown, we process the full time stamp */
-+ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32);
-+ lrng_gcd_add_value(now_time);
-+ } else {
-+ /* GCD is known and applied */
-+ lrng_time_process_common((now_time / lrng_gcd_timer) &
-+ LRNG_DATA_SLOTSIZE_MASK,
-+ lrng_pcpu_array_add_slot);
-+ }
-+
-+ lrng_perf_time(now_time);
-+}
-+
-+/* Hot code path - Callback for interrupt handler */
-+void add_interrupt_randomness(int irq, int irq_flg)
-+{
-+ if (lrng_pool_highres_timer()) {
-+ lrng_time_process();
-+ } else {
-+ struct pt_regs *regs = get_irq_regs();
-+ static atomic_t reg_idx = ATOMIC_INIT(0);
-+ u64 ip;
-+ u32 tmp;
-+
-+ if (regs) {
-+ u32 *ptr = (u32 *)regs;
-+ int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
-+ size_t n = (sizeof(struct pt_regs) / sizeof(u32));
-+
-+ ip = instruction_pointer(regs);
-+ tmp = *(ptr + (reg_ptr % n));
-+ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp;
-+ _lrng_pcpu_array_add_u32(tmp);
-+ } else {
-+ ip = _RET_IP_;
-+ }
-+
-+ lrng_time_process();
-+
-+ /*
-+ * The XOR operation combining the different values is not
-+ * considered to destroy entropy since the entirety of all
-+ * processed values delivers the entropy (and not each
-+ * value separately of the other values).
-+ */
-+ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies;
-+ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq;
-+ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg;
-+ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip;
-+ tmp ^= ip >> 32;
-+ _lrng_pcpu_array_add_u32(tmp);
-+ }
-+}
-+EXPORT_SYMBOL(add_interrupt_randomness);
-+
-+void lrng_irq_es_state(unsigned char *buf, size_t buflen)
-+{
-+ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+
-+ /* Assume the lrng_drng_init lock is taken by caller */
-+ snprintf(buf, buflen,
-+ "IRQ ES properties:\n"
-+ " Hash for operating entropy pool: %s\n"
-+ " per-CPU interrupt collection size: %u\n"
-+ " Standards compliance: %s\n"
-+ " High-resolution timer: %s\n"
-+ " Continuous compression: %s\n",
-+ lrng_drng_init->crypto_cb->lrng_hash_name(),
-+ LRNG_DATA_NUM_VALUES,
-+ lrng_sp80090b_compliant() ? "SP800-90B " : "",
-+ lrng_pool_highres_timer() ? "true" : "false",
-+ lrng_pcpu_continuous_compression ? "true" : "false");
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_irq.h linux-5.15-lrng/drivers/char/lrng/lrng_es_irq.h
---- linux-5.15/drivers/char/lrng/lrng_es_irq.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_irq.h 2021-11-29 12:36:57.773279152 +1100
-@@ -0,0 +1,71 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
-+/*
-+ * LRNG Slow Noise Source: Time stamp array handling
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+/*
-+ * To limit the impact on the interrupt handling, the LRNG concatenates
-+ * entropic LSB parts of the time stamps in a per-CPU array and only
-+ * injects them into the entropy pool when the array is full.
-+ */
-+
-+/* Store multiple integers in one u32 */
-+#define LRNG_DATA_SLOTSIZE_BITS (8)
-+#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1)
-+#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */
-+#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \
-+ LRNG_DATA_SLOTSIZE_BITS)
-+
-+/*
-+ * Number of time values to store in the array - in small environments
-+ * only one atomic_t variable per CPU is used.
-+ */
-+#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE)
-+/* Mask of LSB of time stamp to store */
-+#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1)
-+
-+#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1)
-+#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \
-+ LRNG_DATA_SLOTS_PER_UINT)
-+
-+/* Starting bit index of slot */
-+static inline unsigned int lrng_data_slot2bitindex(unsigned int slot)
-+{
-+ return (LRNG_DATA_SLOTSIZE_BITS * slot);
-+}
-+
-+/* Convert index into the array index */
-+static inline unsigned int lrng_data_idx2array(unsigned int idx)
-+{
-+ return idx / LRNG_DATA_SLOTS_PER_UINT;
-+}
-+
-+/* Convert index into the slot of a given array index */
-+static inline unsigned int lrng_data_idx2slot(unsigned int idx)
-+{
-+ return idx & LRNG_DATA_SLOTS_MASK;
-+}
-+
-+/* Convert value into slot value */
-+static inline unsigned int lrng_data_slot_val(unsigned int val,
-+ unsigned int slot)
-+{
-+ return val << lrng_data_slot2bitindex(slot);
-+}
-+
-+/*
-+ * Return the pointers for the previous and current units to inject a u32 into.
-+ * Also return the mask which the u32 word is to be processed.
-+ */
-+static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask)
-+{
-+ /* ptr to previous unit */
-+ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK;
-+ *ptr &= LRNG_DATA_WORD_MASK;
-+
-+ /* mask to split data into the two parts for the two units */
-+ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) *
-+ LRNG_DATA_SLOTSIZE_BITS)) - 1;
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_jent.c linux-5.15-lrng/drivers/char/lrng/lrng_es_jent.c
---- linux-5.15/drivers/char/lrng/lrng_es_jent.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_jent.c 2021-11-29 12:38:04.443278898 +1100
-@@ -0,0 +1,97 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG Fast Entropy Source: Jitter RNG
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/types.h>
-+#include <crypto/internal/jitterentropy.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
-+ * Albeit a full entropy assessment is provided for the noise source indicating
-+ * that it provides high entropy rates and considering that it deactivates
-+ * when it detects insufficient hardware, the chosen under estimation of
-+ * entropy is considered to be acceptable to all reviewers.
-+ */
-+static u32 jitterrng = CONFIG_LRNG_JENT_ENTROPY_RATE;
-+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG
-+module_param(jitterrng, uint, 0644);
-+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter RNG noise source");
-+#endif
-+
-+static bool lrng_jent_initialized = false;
-+static struct rand_data *lrng_jent_state;
-+
-+static int __init lrng_jent_initialize(void)
-+{
-+ /* Initialize the Jitter RNG after the clocksources are initialized. */
-+ if (jent_entropy_init() ||
-+ (lrng_jent_state = jent_entropy_collector_alloc(1, 0)) == NULL) {
-+ jitterrng = 0;
-+ pr_info("Jitter RNG unusable on current system\n");
-+ return 0;
-+ }
-+ lrng_jent_initialized = true;
-+ lrng_pool_add_entropy();
-+ pr_debug("Jitter RNG working on current system\n");
-+
-+ return 0;
-+}
-+device_initcall(lrng_jent_initialize);
-+
-+/*
-+ * lrng_get_jent() - Get Jitter RNG entropy
-+ *
-+ * @outbuf: buffer to store entropy
-+ * @outbuflen: length of buffer
-+ *
-+ * Return:
-+ * * > 0 on success where value provides the added entropy in bits
-+ * * 0 if no fast source was available
-+ */
-+u32 lrng_get_jent(u8 *outbuf, u32 requested_bits)
-+{
-+ int ret;
-+ u32 ent_bits = lrng_jent_entropylevel(requested_bits);
-+ unsigned long flags;
-+ static DEFINE_SPINLOCK(lrng_jent_lock);
-+
-+ spin_lock_irqsave(&lrng_jent_lock, flags);
-+
-+ if (!lrng_jent_initialized) {
-+ spin_unlock_irqrestore(&lrng_jent_lock, flags);
-+ return 0;
-+ }
-+
-+ ret = jent_read_entropy(lrng_jent_state, outbuf, requested_bits >> 3);
-+ spin_unlock_irqrestore(&lrng_jent_lock, flags);
-+
-+ if (ret) {
-+ pr_debug("Jitter RNG failed with %d\n", ret);
-+ return 0;
-+ }
-+
-+ pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
-+ ent_bits);
-+
-+ return ent_bits;
-+}
-+
-+u32 lrng_jent_entropylevel(u32 requested_bits)
-+{
-+ return lrng_fast_noise_entropylevel((lrng_jent_initialized) ?
-+ jitterrng : 0, requested_bits);
-+}
-+
-+void lrng_jent_es_state(unsigned char *buf, size_t buflen)
-+{
-+ snprintf(buf, buflen,
-+ "JitterRNG ES properties:\n"
-+ " Enabled: %s\n", lrng_jent_initialized ? "true" : "false");
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_es_mgr.c linux-5.15-lrng/drivers/char/lrng/lrng_es_mgr.c
---- linux-5.15/drivers/char/lrng/lrng_es_mgr.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_es_mgr.c 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,373 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG Entropy sources management
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <asm/irq_regs.h>
-+#include <linux/percpu.h>
-+#include <linux/random.h>
-+#include <linux/utsname.h>
-+#include <linux/workqueue.h>
-+
-+#include "lrng_internal.h"
-+
-+struct lrng_state {
-+ bool can_invalidate; /* Can invalidate batched entropy? */
-+ bool perform_seedwork; /* Can seed work be performed? */
-+ bool lrng_operational; /* Is DRNG operational? */
-+ bool lrng_fully_seeded; /* Is DRNG fully seeded? */
-+ bool lrng_min_seeded; /* Is DRNG minimally seeded? */
-+ bool all_online_numa_node_seeded;/* All NUMA DRNGs seeded? */
-+
-+ /*
-+ * To ensure that external entropy providers cannot dominate the
-+ * internal noise sources but yet cannot be dominated by internal
-+ * noise sources, the following booleans are intended to allow
-+ * external to provide seed once when a DRNG reseed occurs. This
-+ * triggering of external noise source is performed even when the
-+ * entropy pool has sufficient entropy.
-+ */
-+ bool lrng_seed_hw; /* Allow HW to provide seed */
-+ bool lrng_seed_user; /* Allow user space to provide seed */
-+
-+ atomic_t boot_entropy_thresh; /* Reseed threshold */
-+ atomic_t reseed_in_progress; /* Flag for on executing reseed */
-+ struct work_struct lrng_seed_work; /* (re)seed work queue */
-+};
-+
-+static struct lrng_state lrng_state = {
-+ false, false, false, false, false, false, true, true,
-+ .boot_entropy_thresh = ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS),
-+ .reseed_in_progress = ATOMIC_INIT(0),
-+};
-+
-+/********************************** Helper ***********************************/
-+
-+/* External entropy provider is allowed to provide seed data */
-+bool lrng_state_exseed_allow(enum lrng_external_noise_source source)
-+{
-+ if (source == lrng_noise_source_hw)
-+ return lrng_state.lrng_seed_hw;
-+ return lrng_state.lrng_seed_user;
-+}
-+
-+/* Enable / disable external entropy provider to furnish seed */
-+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type)
-+{
-+ if (source == lrng_noise_source_hw)
-+ lrng_state.lrng_seed_hw = type;
-+ else
-+ lrng_state.lrng_seed_user = type;
-+}
-+
-+static inline void lrng_state_exseed_allow_all(void)
-+{
-+ lrng_state_exseed_set(lrng_noise_source_hw, true);
-+ lrng_state_exseed_set(lrng_noise_source_user, true);
-+}
-+
-+/*
-+ * Reading of the LRNG pool is only allowed by one caller. The reading is
-+ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken,
-+ * the reseeding operation is in progress. The caller is not intended to wait
-+ * but continue with its other operation.
-+ */
-+int lrng_pool_trylock(void)
-+{
-+ return atomic_cmpxchg(&lrng_state.reseed_in_progress, 0, 1);
-+}
-+
-+void lrng_pool_unlock(void)
-+{
-+ atomic_set(&lrng_state.reseed_in_progress, 0);
-+}
-+
-+/* Set new entropy threshold for reseeding during boot */
-+void lrng_set_entropy_thresh(u32 new_entropy_bits)
-+{
-+ atomic_set(&lrng_state.boot_entropy_thresh, new_entropy_bits);
-+}
-+
-+/*
-+ * Reset LRNG state - the entropy counters are reset, but the data that may
-+ * or may not have entropy remains in the pools as this data will not hurt.
-+ */
-+void lrng_reset_state(void)
-+{
-+ lrng_pool_set_entropy(0);
-+ lrng_pcpu_reset();
-+ lrng_state.lrng_operational = false;
-+ lrng_state.lrng_fully_seeded = false;
-+ lrng_state.lrng_min_seeded = false;
-+ lrng_state.all_online_numa_node_seeded = false;
-+ pr_debug("reset LRNG\n");
-+}
-+
-+/* Set flag that all DRNGs are fully seeded */
-+void lrng_pool_all_numa_nodes_seeded(bool set)
-+{
-+ lrng_state.all_online_numa_node_seeded = set;
-+}
-+
-+/* Return boolean whether LRNG reached minimally seed level */
-+bool lrng_state_min_seeded(void)
-+{
-+ return lrng_state.lrng_min_seeded;
-+}
-+
-+/* Return boolean whether LRNG reached fully seed level */
-+bool lrng_state_fully_seeded(void)
-+{
-+ return lrng_state.lrng_fully_seeded;
-+}
-+
-+/* Return boolean whether LRNG is considered fully operational */
-+bool lrng_state_operational(void)
-+{
-+ return lrng_state.lrng_operational;
-+}
-+
-+/* Policy to check whether entropy buffer contains full seeded entropy */
-+bool lrng_fully_seeded(bool fully_seeded, struct entropy_buf *eb)
-+{
-+ return ((eb->a_bits + eb->b_bits + eb->c_bits + eb->d_bits) >=
-+ lrng_get_seed_entropy_osr(fully_seeded));
-+}
-+
-+/* Mark one DRNG as not fully seeded */
-+void lrng_unset_fully_seeded(struct lrng_drng *drng)
-+{
-+ drng->fully_seeded = false;
-+ lrng_pool_all_numa_nodes_seeded(false);
-+
-+ /*
-+ * The init DRNG instance must always be fully seeded as this instance
-+ * is the fall-back if any of the per-NUMA node DRNG instances is
-+ * insufficiently seeded. Thus, we mark the entire LRNG as
-+ * non-operational if the initial DRNG becomes not fully seeded.
-+ */
-+ if (drng == lrng_drng_init_instance() && lrng_state_operational()) {
-+ pr_debug("LRNG set to non-operational\n");
-+ lrng_state.lrng_operational = false;
-+ lrng_state.lrng_fully_seeded = false;
-+
-+ /* If sufficient entropy is available, reseed now. */
-+ lrng_pool_add_entropy();
-+ }
-+}
-+
-+/* Policy to enable LRNG operational mode */
-+static inline void lrng_set_operational(u32 external_es)
-+{
-+ /* LRNG is operational if the initial DRNG is fully seeded ... */
-+ if (lrng_state.lrng_fully_seeded &&
-+ /* ... and either internal ES SP800-90B startup is complete ... */
-+ (lrng_sp80090b_startup_complete() ||
-+ /* ... or the external ES provided sufficient entropy. */
-+ (lrng_get_seed_entropy_osr(lrng_state_fully_seeded()) <=
-+ external_es))) {
-+ lrng_state.lrng_operational = true;
-+ lrng_process_ready_list();
-+ lrng_init_wakeup();
-+ pr_info("LRNG fully operational\n");
-+ }
-+}
-+
-+/* Available entropy in the entire LRNG considering all entropy sources */
-+u32 lrng_avail_entropy(void)
-+{
-+ u32 ent_thresh = lrng_security_strength();
-+
-+ /*
-+ * Apply oversampling during initialization according to SP800-90C as
-+ * we request a larger buffer from the ES.
-+ */
-+ if (lrng_sp80090c_compliant() &&
-+ !lrng_state.all_online_numa_node_seeded)
-+ ent_thresh += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS;
-+
-+ return lrng_pcpu_avail_entropy() + lrng_avail_aux_entropy() +
-+ lrng_archrandom_entropylevel(ent_thresh) +
-+ lrng_jent_entropylevel(ent_thresh);
-+}
-+
-+/*
-+ * lrng_init_ops() - Set seed stages of LRNG
-+ *
-+ * Set the slow noise source reseed trigger threshold. The initial threshold
-+ * is set to the minimum data size that can be read from the pool: a word. Upon
-+ * reaching this value, the next seed threshold of 128 bits is set followed
-+ * by 256 bits.
-+ *
-+ * @eb: buffer containing the size of entropy currently injected into DRNG
-+ */
-+void lrng_init_ops(struct entropy_buf *eb)
-+{
-+ struct lrng_state *state = &lrng_state;
-+ u32 requested_bits, seed_bits, external_es;
-+
-+ if (state->lrng_operational)
-+ return;
-+
-+ requested_bits = lrng_get_seed_entropy_osr(
-+ state->all_online_numa_node_seeded);
-+
-+ /*
-+ * Entropy provided by external entropy sources - if they provide
-+ * the requested amount of entropy, unblock the interface.
-+ */
-+ external_es = eb->a_bits + eb->c_bits + eb->d_bits;
-+ seed_bits = external_es + eb->b_bits;
-+
-+ /* DRNG is seeded with full security strength */
-+ if (state->lrng_fully_seeded) {
-+ lrng_set_operational(external_es);
-+ lrng_set_entropy_thresh(requested_bits);
-+ } else if (lrng_fully_seeded(state->all_online_numa_node_seeded, eb)) {
-+ if (state->can_invalidate)
-+ invalidate_batched_entropy();
-+
-+ state->lrng_fully_seeded = true;
-+ lrng_set_operational(external_es);
-+ state->lrng_min_seeded = true;
-+ pr_info("LRNG fully seeded with %u bits of entropy\n",
-+ seed_bits);
-+ lrng_set_entropy_thresh(requested_bits);
-+ } else if (!state->lrng_min_seeded) {
-+
-+ /* DRNG is seeded with at least 128 bits of entropy */
-+ if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
-+ if (state->can_invalidate)
-+ invalidate_batched_entropy();
-+
-+ state->lrng_min_seeded = true;
-+ pr_info("LRNG minimally seeded with %u bits of entropy\n",
-+ seed_bits);
-+ lrng_set_entropy_thresh(requested_bits);
-+ lrng_init_wakeup();
-+
-+ /* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
-+ } else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
-+ pr_info("LRNG initial entropy level %u bits of entropy\n",
-+ seed_bits);
-+ lrng_set_entropy_thresh(LRNG_MIN_SEED_ENTROPY_BITS);
-+ }
-+ }
-+}
-+
-+int __init rand_initialize(void)
-+{
-+ struct seed {
-+ ktime_t time;
-+ unsigned long data[(LRNG_MAX_DIGESTSIZE /
-+ sizeof(unsigned long))];
-+ struct new_utsname utsname;
-+ } seed __aligned(LRNG_KCAPI_ALIGN);
-+ unsigned int i;
-+
-+ BUILD_BUG_ON(LRNG_MAX_DIGESTSIZE % sizeof(unsigned long));
-+
-+ seed.time = ktime_get_real();
-+
-+ for (i = 0; i < ARRAY_SIZE(seed.data); i++) {
-+ if (!arch_get_random_seed_long_early(&(seed.data[i])) &&
-+ !arch_get_random_long_early(&seed.data[i]))
-+ seed.data[i] = random_get_entropy();
-+ }
-+ memcpy(&seed.utsname, utsname(), sizeof(*(utsname())));
-+
-+ lrng_pool_insert_aux((u8 *)&seed, sizeof(seed), 0);
-+ memzero_explicit(&seed, sizeof(seed));
-+
-+ /* Initialize the seed work queue */
-+ INIT_WORK(&lrng_state.lrng_seed_work, lrng_drng_seed_work);
-+ lrng_state.perform_seedwork = true;
-+
-+ lrng_drngs_init_cc20(true);
-+ invalidate_batched_entropy();
-+
-+ lrng_state.can_invalidate = true;
-+
-+ return 0;
-+}
-+
-+/* Interface requesting a reseed of the DRNG */
-+void lrng_pool_add_entropy(void)
-+{
-+ /*
-+ * Once all DRNGs are fully seeded, the interrupt noise
-+ * sources will not trigger any reseeding any more.
-+ */
-+ if (likely(lrng_state.all_online_numa_node_seeded))
-+ return;
-+
-+ /* Only try to reseed if the DRNG is alive. */
-+ if (!lrng_get_available())
-+ return;
-+
-+ /* Only trigger the DRNG reseed if we have collected entropy. */
-+ if (lrng_avail_entropy() <
-+ atomic_read_u32(&lrng_state.boot_entropy_thresh))
-+ return;
-+
-+ /* Ensure that the seeding only occurs once at any given time. */
-+ if (lrng_pool_trylock())
-+ return;
-+
-+ /* Seed the DRNG with any available noise. */
-+ if (lrng_state.perform_seedwork)
-+ schedule_work(&lrng_state.lrng_seed_work);
-+ else
-+ lrng_drng_seed_work(NULL);
-+}
-+
-+/* Fill the seed buffer with data from the noise sources */
-+void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits)
-+{
-+ struct lrng_state *state = &lrng_state;
-+ u32 req_ent = lrng_sp80090c_compliant() ?
-+ lrng_security_strength() : LRNG_MIN_SEED_ENTROPY_BITS;
-+
-+ /* Guarantee that requested bits is a multiple of bytes */
-+ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BITS % 8);
-+
-+ /* always reseed the DRNG with the current time stamp */
-+ entropy_buf->now = random_get_entropy();
-+
-+ /*
-+ * Require at least 128 bits of entropy for any reseed. If the LRNG is
-+ * operated SP800-90C compliant we want to comply with SP800-90A section
-+ * 9.2 mandating that DRNG is reseeded with the security strength.
-+ */
-+ if (state->lrng_fully_seeded && (lrng_avail_entropy() < req_ent)) {
-+ entropy_buf->a_bits = entropy_buf->b_bits = 0;
-+ entropy_buf->c_bits = entropy_buf->d_bits = 0;
-+ goto wakeup;
-+ }
-+
-+ /* Concatenate the output of the entropy sources. */
-+ entropy_buf->b_bits = lrng_pcpu_pool_hash(entropy_buf->b,
-+ requested_bits,
-+ state->lrng_fully_seeded);
-+ entropy_buf->c_bits = lrng_get_arch(entropy_buf->c, requested_bits);
-+ entropy_buf->d_bits = lrng_get_jent(entropy_buf->d, requested_bits);
-+ lrng_get_backtrack_aux(entropy_buf, requested_bits);
-+
-+ /* allow external entropy provider to provide seed */
-+ lrng_state_exseed_allow_all();
-+
-+wakeup:
-+ /*
-+ * Shall we wake up user space writers? This location covers
-+ * ensures that the user space provider does not dominate the internal
-+ * noise sources since in case the first call of this function finds
-+ * sufficient entropy in the entropy pool, it will not trigger the
-+ * wakeup. This implies that when the next /dev/urandom read happens,
-+ * the entropy pool is drained.
-+ */
-+ lrng_writer_wakeup();
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_health.c linux-5.15-lrng/drivers/char/lrng/lrng_health.c
---- linux-5.15/drivers/char/lrng/lrng_health.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_health.c 2021-11-29 12:38:11.793278870 +1100
-@@ -0,0 +1,410 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Linux Random Number Generator (LRNG) Health Testing
-+ *
-+ * Copyright (C) 2019 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/fips.h>
-+#include <linux/module.h>
-+
-+#include "lrng_internal.h"
-+
-+/* Stuck Test */
-+struct lrng_stuck_test {
-+ u32 last_time; /* Stuck test: time of previous IRQ */
-+ u32 last_delta; /* Stuck test: delta of previous IRQ */
-+ u32 last_delta2; /* Stuck test: 2. time derivation of prev IRQ */
-+};
-+
-+/* Repetition Count Test */
-+struct lrng_rct {
-+ atomic_t rct_count; /* Number of stuck values */
-+};
-+
-+/* Adaptive Proportion Test */
-+struct lrng_apt {
-+ /* Data window size */
-+#define LRNG_APT_WINDOW_SIZE 512
-+ /* LSB of time stamp to process */
-+#define LRNG_APT_LSB 16
-+#define LRNG_APT_WORD_MASK (LRNG_APT_LSB - 1)
-+ atomic_t apt_count; /* APT counter */
-+ atomic_t apt_base; /* APT base reference */
-+
-+ atomic_t apt_trigger;
-+ bool apt_base_set; /* Is APT base set? */
-+};
-+
-+/* The health test code must operate lock-less */
-+struct lrng_health {
-+ struct lrng_rct rct;
-+ struct lrng_apt apt;
-+
-+ bool health_test_enabled;
-+
-+ /* SP800-90B startup health tests */
-+#define LRNG_SP80090B_STARTUP_SAMPLES 1024
-+#define LRNG_SP80090B_STARTUP_BLOCKS ((LRNG_SP80090B_STARTUP_SAMPLES + \
-+ LRNG_APT_WINDOW_SIZE - 1) / \
-+ LRNG_APT_WINDOW_SIZE)
-+ bool sp80090b_startup_done;
-+ atomic_t sp80090b_startup_blocks;
-+};
-+
-+static struct lrng_health lrng_health = {
-+ .rct.rct_count = ATOMIC_INIT(0),
-+
-+ .apt.apt_count = ATOMIC_INIT(0),
-+ .apt.apt_base = ATOMIC_INIT(-1),
-+ .apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
-+ .apt.apt_base_set = false,
-+
-+ .health_test_enabled = true,
-+
-+ .sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
-+ .sp80090b_startup_done = false,
-+};
-+
-+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
-+
-+static inline bool lrng_sp80090b_health_requested(void)
-+{
-+ /* Health tests are only requested in FIPS mode */
-+ return fips_enabled;
-+}
-+
-+static inline bool lrng_sp80090b_health_enabled(void)
-+{
-+ struct lrng_health *health = &lrng_health;
-+
-+ return lrng_sp80090b_health_requested() && health->health_test_enabled;
-+}
-+
-+/***************************************************************************
-+ * SP800-90B Compliance
-+ *
-+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
-+ * provide an SP800-90B compliant noise source:
-+ *
-+ * * /dev/random
-+ * * getrandom(2)
-+ * * get_random_bytes when using it in conjunction with
-+ * add_random_ready_callback
-+ *
-+ * All other interfaces, including /dev/urandom or get_random_bytes without
-+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
-+ * noise source.
-+ ***************************************************************************/
-+
-+/*
-+ * Perform SP800-90B startup testing
-+ */
-+static inline void lrng_sp80090b_startup(struct lrng_health *health)
-+{
-+ if (!health->sp80090b_startup_done &&
-+ atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
-+ struct entropy_buf eb;
-+
-+ health->sp80090b_startup_done = true;
-+ pr_info("SP800-90B startup health tests completed\n");
-+ memset(&eb, 0, sizeof(eb));
-+ lrng_init_ops(&eb);
-+
-+ /*
-+ * Force a reseed of DRNGs to ensure they are seeded with
-+ * entropy that passed the SP800-90B health tests.
-+ * As the DRNG always will reseed before generating
-+ * random numbers, it does not need a reseed trigger.
-+ */
-+ lrng_drng_force_reseed();
-+ }
-+}
-+
-+/*
-+ * Handle failure of SP800-90B startup testing
-+ */
-+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
-+{
-+ /* Reset of LRNG and its entropy - NOTE: we are in atomic context */
-+ lrng_reset();
-+
-+ /*
-+ * Reset the SP800-90B startup test.
-+ *
-+ * NOTE SP800-90B section 4.3 bullet 4 does not specify what
-+ * exactly is to be done in case of failure! Thus, we do what
-+ * makes sense, i.e. restarting the health test and thus gating
-+ * the output function of /dev/random and getrandom(2).
-+ */
-+ atomic_set(&health->sp80090b_startup_blocks,
-+ LRNG_SP80090B_STARTUP_BLOCKS);
-+}
-+
-+/*
-+ * Handle failure of SP800-90B runtime testing
-+ */
-+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
-+{
-+ lrng_sp80090b_startup_failure(health);
-+ health->sp80090b_startup_done = false;
-+}
-+
-+static inline void lrng_sp80090b_failure(struct lrng_health *health)
-+{
-+ if (health->sp80090b_startup_done) {
-+ pr_err("SP800-90B runtime health test failure - invalidating all existing entropy and initiate SP800-90B startup\n");
-+ lrng_sp80090b_runtime_failure(health);
-+ } else {
-+ pr_err("SP800-90B startup test failure - resetting\n");
-+ lrng_sp80090b_startup_failure(health);
-+ }
-+}
-+
-+/*
-+ * Is the SP800-90B startup testing complete?
-+ *
-+ * This function is called by the LRNG to determine whether to unblock
-+ * a certain user interface. Therefore, only the potentially blocking
-+ * user interfaces are considered SP800-90B compliant.
-+ */
-+bool lrng_sp80090b_startup_complete(void)
-+{
-+ struct lrng_health *health = &lrng_health;
-+
-+ return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
-+ true;
-+}
-+
-+bool lrng_sp80090b_compliant(void)
-+{
-+ struct lrng_health *health = &lrng_health;
-+
-+ return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
-+}
-+
-+/***************************************************************************
-+ * Adaptive Proportion Test
-+ *
-+ * This test complies with SP800-90B section 4.4.2.
-+ ***************************************************************************/
-+
-+/*
-+ * Reset the APT counter
-+ *
-+ * @health [in] Reference to health state
-+ */
-+static inline void lrng_apt_reset(struct lrng_health *health,
-+ unsigned int time_masked)
-+{
-+ struct lrng_apt *apt = &health->apt;
-+
-+ pr_debug("APT value %d for base %d\n",
-+ atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
-+
-+ /* Reset APT */
-+ atomic_set(&apt->apt_count, 0);
-+ atomic_set(&apt->apt_base, time_masked);
-+}
-+
-+static inline void lrng_apt_restart(struct lrng_health *health)
-+{
-+ struct lrng_apt *apt = &health->apt;
-+
-+ atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
-+}
-+
-+/*
-+ * Insert a new entropy event into APT
-+ *
-+ * This function does is void as it does not decide about the fate of a time
-+ * stamp. An APT failure can only happen at the same time of a stuck test
-+ * failure. Thus, the stuck failure will already decide how the time stamp
-+ * is handled.
-+ *
-+ * @health [in] Reference to health state
-+ * @now_time [in] Time stamp to process
-+ */
-+static inline void lrng_apt_insert(struct lrng_health *health,
-+ unsigned int now_time)
-+{
-+ struct lrng_apt *apt = &health->apt;
-+
-+ if (!lrng_sp80090b_health_requested())
-+ return;
-+
-+ now_time &= LRNG_APT_WORD_MASK;
-+
-+ /* Initialization of APT */
-+ if (!apt->apt_base_set) {
-+ atomic_set(&apt->apt_base, now_time);
-+ apt->apt_base_set = true;
-+ return;
-+ }
-+
-+ if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
-+ u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
-+
-+ if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
-+ lrng_sp80090b_failure(health);
-+ }
-+
-+ if (atomic_dec_and_test(&apt->apt_trigger)) {
-+ lrng_apt_restart(health);
-+ lrng_apt_reset(health, now_time);
-+ lrng_sp80090b_startup(health);
-+ }
-+}
-+
-+/***************************************************************************
-+ * Repetition Count Test
-+ *
-+ * The LRNG uses an enhanced version of the Repetition Count Test
-+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
-+ * back-to-back values, the input to the RCT is the counting of the stuck
-+ * values while filling the entropy pool.
-+ *
-+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
-+ *
-+ * During the counting operation, the LRNG always calculates the RCT
-+ * cut-off value of C. If that value exceeds the allowed cut-off value,
-+ * the LRNG will invalidate all entropy for the entropy pool which implies
-+ * that no data can be extracted from the entropy pool unless new entropy
-+ * is received.
-+ ***************************************************************************/
-+
-+/*
-+ * Hot code path - Insert data for Repetition Count Test
-+ *
-+ * @health: Reference to health information
-+ * @stuck: Decision of stuck test
-+ */
-+static inline void lrng_rct(struct lrng_health *health, int stuck)
-+{
-+ struct lrng_rct *rct = &health->rct;
-+
-+ if (!lrng_sp80090b_health_requested())
-+ return;
-+
-+ if (stuck) {
-+ u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
-+
-+ pr_debug("RCT count: %u\n", rct_count);
-+
-+ /*
-+ * The cutoff value is based on the following consideration:
-+ * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
-+ * In addition, we imply an entropy value H of 1 bit as this
-+ * is the minimum entropy required to provide full entropy.
-+ *
-+ * Note, rct_count (which equals to value B in the
-+ * pseudo code of SP800-90B section 4.4.1) starts with zero.
-+ * Hence we need to subtract one from the cutoff value as
-+ * calculated following SP800-90B.
-+ */
-+ if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
-+ atomic_set(&rct->rct_count, 0);
-+
-+ /*
-+ * APT must start anew as we consider all previously
-+ * recorded data to contain no entropy.
-+ */
-+ lrng_apt_restart(health);
-+
-+ lrng_sp80090b_failure(health);
-+ }
-+ } else {
-+ atomic_set(&rct->rct_count, 0);
-+ }
-+}
-+
-+/***************************************************************************
-+ * Stuck Test
-+ *
-+ * Checking the:
-+ * 1st derivative of the event occurrence (time delta)
-+ * 2nd derivative of the event occurrence (delta of time deltas)
-+ * 3rd derivative of the event occurrence (delta of delta of time deltas)
-+ *
-+ * All values must always be non-zero. The stuck test is only valid disabled if
-+ * high-resolution time stamps are identified after initialization.
-+ ***************************************************************************/
-+
-+static inline u32 lrng_delta(u32 prev, u32 next)
-+{
-+ /*
-+ * Note that this (unsigned) subtraction does yield the correct value
-+ * in the wraparound-case, i.e. when next < prev.
-+ */
-+ return (next - prev);
-+}
-+
-+/*
-+ * Hot code path
-+ *
-+ * @health: Reference to health information
-+ * @now: Event time
-+ * @return: 0 event occurrence not stuck (good time stamp)
-+ * != 0 event occurrence stuck (reject time stamp)
-+ */
-+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
-+{
-+ u32 delta = lrng_delta(stuck->last_time, now_time);
-+ u32 delta2 = lrng_delta(stuck->last_delta, delta);
-+ u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
-+
-+ stuck->last_time = now_time;
-+ stuck->last_delta = delta;
-+ stuck->last_delta2 = delta2;
-+
-+ if (!delta || !delta2 || !delta3)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/***************************************************************************
-+ * Health test interfaces
-+ ***************************************************************************/
-+
-+/*
-+ * Disable all health tests
-+ */
-+void lrng_health_disable(void)
-+{
-+ struct lrng_health *health = &lrng_health;
-+
-+ health->health_test_enabled = false;
-+
-+ if (lrng_sp80090b_health_requested())
-+ pr_warn("SP800-90B compliance requested but the Linux RNG is NOT SP800-90B compliant\n");
-+}
-+
-+/*
-+ * Hot code path - Perform health test on time stamp received from an event
-+ *
-+ * @now_time Time stamp
-+ */
-+enum lrng_health_res lrng_health_test(u32 now_time)
-+{
-+ struct lrng_health *health = &lrng_health;
-+ struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
-+ int stuck;
-+
-+ if (!health->health_test_enabled)
-+ return lrng_health_pass;
-+
-+ lrng_apt_insert(health, now_time);
-+
-+ stuck = lrng_irq_stuck(stuck_test, now_time);
-+ lrng_rct(health, stuck);
-+ if (stuck) {
-+ /* SP800-90B disallows using a failing health test time stamp */
-+ return lrng_sp80090b_health_requested() ?
-+ lrng_health_fail_drop : lrng_health_fail_use;
-+ }
-+
-+ return lrng_health_pass;
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_interfaces.c linux-5.15-lrng/drivers/char/lrng/lrng_interfaces.c
---- linux-5.15/drivers/char/lrng/lrng_interfaces.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_interfaces.c 2021-11-29 12:37:03.083279132 +1100
-@@ -0,0 +1,654 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG User and kernel space interfaces
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/freezer.h>
-+#include <linux/fs.h>
-+#include <linux/genhd.h>
-+#include <linux/hw_random.h>
-+#include <linux/kthread.h>
-+#include <linux/poll.h>
-+#include <linux/preempt.h>
-+#include <linux/random.h>
-+#include <linux/slab.h>
-+#include <linux/syscalls.h>
-+#include <linux/timex.h>
-+
-+#define CREATE_TRACE_POINTS
-+#include <trace/events/random.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * If the entropy count falls under this number of bits, then we
-+ * should wake up processes which are selecting or polling on write
-+ * access to /dev/random.
-+ */
-+u32 lrng_write_wakeup_bits = (LRNG_WRITE_WAKEUP_ENTROPY << 3);
-+
-+static LIST_HEAD(lrng_ready_list);
-+static DEFINE_SPINLOCK(lrng_ready_list_lock);
-+
-+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
-+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
-+static struct fasync_struct *fasync;
-+
-+/********************************** Helper ***********************************/
-+
-+/* Is the DRNG seed level too low? */
-+static inline bool lrng_need_entropy(void)
-+{
-+ return (lrng_avail_aux_entropy() < lrng_write_wakeup_bits);
-+}
-+
-+void lrng_writer_wakeup(void)
-+{
-+ if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
-+ wake_up_interruptible(&lrng_write_wait);
-+ kill_fasync(&fasync, SIGIO, POLL_OUT);
-+ }
-+}
-+
-+void lrng_init_wakeup(void)
-+{
-+ wake_up_all(&lrng_init_wait);
-+ kill_fasync(&fasync, SIGIO, POLL_IN);
-+}
-+
-+/**
-+ * lrng_process_ready_list() - Ping all kernel internal callers waiting until
-+ * the DRNG is completely initialized to inform that the DRNG reached that
-+ * seed level.
-+ *
-+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
-+ * startup health tests are completed. This implies that kernel internal
-+ * callers always have an SP800-90B compliant noise source when being
-+ * pinged.
-+ */
-+void lrng_process_ready_list(void)
-+{
-+ unsigned long flags;
-+ struct random_ready_callback *rdy, *tmp;
-+
-+ if (!lrng_state_operational())
-+ return;
-+
-+ spin_lock_irqsave(&lrng_ready_list_lock, flags);
-+ list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
-+ struct module *owner = rdy->owner;
-+
-+ list_del_init(&rdy->list);
-+ rdy->func(rdy);
-+ module_put(owner);
-+ }
-+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
-+}
-+
-+void lrng_debug_report_seedlevel(const char *name)
-+{
-+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-+ static void *previous = NULL;
-+ void *caller = (void *) _RET_IP_;
-+
-+ if (READ_ONCE(previous) == caller)
-+ return;
-+
-+ if (!lrng_state_min_seeded())
-+ pr_notice("%pS %s called without reaching minimally seeded level (available entropy %u)\n",
-+ caller, name, lrng_avail_entropy());
-+
-+ WRITE_ONCE(previous, caller);
-+#endif
-+}
-+
-+/************************ LRNG kernel input interfaces ************************/
-+
-+/*
-+ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true
-+ * hardware RNGs.
-+ *
-+ * Those devices may produce endless random bits and will be throttled
-+ * when our pool is full.
-+ *
-+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
-+ * insert into entropy pool.
-+ * @count: length of buffer
-+ * @entropy_bits: amount of entropy in buffer (value is in bits)
-+ */
-+void add_hwgenerator_randomness(const char *buffer, size_t count,
-+ size_t entropy_bits)
-+{
-+ /*
-+ * Suspend writing if we are fully loaded with entropy.
-+ * We'll be woken up again once below lrng_write_wakeup_thresh,
-+ * or when the calling thread is about to terminate.
-+ */
-+ wait_event_interruptible(lrng_write_wait,
-+ lrng_need_entropy() ||
-+ lrng_state_exseed_allow(lrng_noise_source_hw) ||
-+ kthread_should_stop());
-+ lrng_state_exseed_set(lrng_noise_source_hw, false);
-+ lrng_pool_insert_aux(buffer, count, entropy_bits);
-+}
-+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
-+
-+/*
-+ * add_bootloader_randomness() - Handle random seed passed by bootloader.
-+ *
-+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
-+ * it would be regarded as device data.
-+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
-+ *
-+ * @buf: buffer holding the entropic data from HW noise sources to be used to
-+ * insert into entropy pool.
-+ * @size: length of buffer
-+ */
-+void add_bootloader_randomness(const void *buf, unsigned int size)
-+{
-+ lrng_pool_insert_aux(buf, size,
-+ IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER) ?
-+ size * 8 : 0);
-+}
-+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
-+
-+/*
-+ * Callback for HID layer -- use the HID event values to stir the entropy pool
-+ */
-+void add_input_randomness(unsigned int type, unsigned int code,
-+ unsigned int value)
-+{
-+ static unsigned char last_value;
-+
-+ /* ignore autorepeat and the like */
-+ if (value == last_value)
-+ return;
-+
-+ last_value = value;
-+
-+ lrng_pcpu_array_add_u32((type << 4) ^ code ^ (code >> 4) ^ value);
-+}
-+EXPORT_SYMBOL_GPL(add_input_randomness);
-+
-+/*
-+ * add_device_randomness() - Add device- or boot-specific data to the entropy
-+ * pool to help initialize it.
-+ *
-+ * None of this adds any entropy; it is meant to avoid the problem of
-+ * the entropy pool having similar initial state across largely
-+ * identical devices.
-+ *
-+ * @buf: buffer holding the entropic data from HW noise sources to be used to
-+ * insert into entropy pool.
-+ * @size: length of buffer
-+ */
-+void add_device_randomness(const void *buf, unsigned int size)
-+{
-+ lrng_pool_insert_aux((u8 *)buf, size, 0);
-+}
-+EXPORT_SYMBOL(add_device_randomness);
-+
-+#ifdef CONFIG_BLOCK
-+void rand_initialize_disk(struct gendisk *disk) { }
-+void add_disk_randomness(struct gendisk *disk) { }
-+EXPORT_SYMBOL(add_disk_randomness);
-+#endif
-+
-+#ifndef CONFIG_LRNG_IRQ
-+void add_interrupt_randomness(int irq, int irq_flg) { }
-+EXPORT_SYMBOL(add_interrupt_randomness);
-+#endif
-+
-+/*
-+ * del_random_ready_callback() - Delete a previously registered readiness
-+ * callback function.
-+ *
-+ * @rdy: callback definition that was registered initially
-+ */
-+void del_random_ready_callback(struct random_ready_callback *rdy)
-+{
-+ unsigned long flags;
-+ struct module *owner = NULL;
-+
-+ spin_lock_irqsave(&lrng_ready_list_lock, flags);
-+ if (!list_empty(&rdy->list)) {
-+ list_del_init(&rdy->list);
-+ owner = rdy->owner;
-+ }
-+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
-+
-+ module_put(owner);
-+}
-+EXPORT_SYMBOL(del_random_ready_callback);
-+
-+/*
-+ * add_random_ready_callback() - Add a callback function that will be invoked
-+ * when the DRNG is fully initialized and seeded.
-+ *
-+ * @rdy: callback definition to be invoked when the LRNG is seeded
-+ *
-+ * Return:
-+ * * 0 if callback is successfully added
-+ * * -EALREADY if pool is already initialised (callback not called)
-+ * * -ENOENT if module for callback is not alive
-+ */
-+int add_random_ready_callback(struct random_ready_callback *rdy)
-+{
-+ struct module *owner;
-+ unsigned long flags;
-+ int err = -EALREADY;
-+
-+ if (likely(lrng_state_operational()))
-+ return err;
-+
-+ owner = rdy->owner;
-+ if (!try_module_get(owner))
-+ return -ENOENT;
-+
-+ spin_lock_irqsave(&lrng_ready_list_lock, flags);
-+ if (lrng_state_operational())
-+ goto out;
-+
-+ owner = NULL;
-+
-+ list_add(&rdy->list, &lrng_ready_list);
-+ err = 0;
-+
-+out:
-+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
-+
-+ module_put(owner);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL(add_random_ready_callback);
-+
-+/*********************** LRNG kernel output interfaces ************************/
-+
-+/*
-+ * get_random_bytes() - Provider of cryptographic strong random numbers for
-+ * kernel-internal usage.
-+ *
-+ * This function is appropriate for all in-kernel use cases. However,
-+ * it will always use the ChaCha20 DRNG.
-+ *
-+ * @buf: buffer to store the random bytes
-+ * @nbytes: size of the buffer
-+ */
-+void get_random_bytes(void *buf, int nbytes)
-+{
-+ lrng_drng_get_atomic((u8 *)buf, (u32)nbytes);
-+ lrng_debug_report_seedlevel("get_random_bytes");
-+}
-+EXPORT_SYMBOL(get_random_bytes);
-+
-+/*
-+ * get_random_bytes_full() - Provider of cryptographic strong random numbers
-+ * for kernel-internal usage.
-+ *
-+ * This function is appropriate only for non-atomic use cases as this
-+ * function may sleep. Though, it provides access to the full functionality
-+ * of LRNG including the switchable DRNG support, that may support other
-+ * DRNGs such as the SP800-90A DRBG.
-+ *
-+ * @buf: buffer to store the random bytes
-+ * @nbytes: size of the buffer
-+ */
-+void get_random_bytes_full(void *buf, int nbytes)
-+{
-+ lrng_drng_get_sleep((u8 *)buf, (u32)nbytes);
-+ lrng_debug_report_seedlevel("get_random_bytes_full");
-+}
-+EXPORT_SYMBOL(get_random_bytes_full);
-+
-+/*
-+ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus
-+ * guaranteed to supply cryptographically secure random numbers.
-+ *
-+ * This applies to: the /dev/urandom device, the get_random_bytes function,
-+ * and the get_random_{u32,u64,int,long} family of functions. Using any of
-+ * these functions without first calling this function forfeits the guarantee
-+ * of security.
-+ *
-+ * Return:
-+ * * 0 if the LRNG has been seeded.
-+ * * -ERESTARTSYS if the function was interrupted by a signal.
-+ */
-+int wait_for_random_bytes(void)
-+{
-+ if (likely(lrng_state_min_seeded()))
-+ return 0;
-+ return wait_event_interruptible(lrng_init_wait,
-+ lrng_state_min_seeded());
-+}
-+EXPORT_SYMBOL(wait_for_random_bytes);
-+
-+/*
-+ * get_random_bytes_arch() - This function will use the architecture-specific
-+ * hardware random number generator if it is available.
-+ *
-+ * The arch-specific hw RNG will almost certainly be faster than what we can
-+ * do in software, but it is impossible to verify that it is implemented
-+ * securely (as opposed, to, say, the AES encryption of a sequence number using
-+ * a key known by the NSA). So it's useful if we need the speed, but only if
-+ * we're willing to trust the hardware manufacturer not to have put in a back
-+ * door.
-+ *
-+ * @buf: buffer allocated by caller to store the random data in
-+ * @nbytes: length of outbuf
-+ *
-+ * Return: number of bytes filled in.
-+ */
-+int __must_check get_random_bytes_arch(void *buf, int nbytes)
-+{
-+ u8 *p = buf;
-+
-+ while (nbytes) {
-+ unsigned long v;
-+ int chunk = min_t(int, nbytes, sizeof(unsigned long));
-+
-+ if (!arch_get_random_long(&v))
-+ break;
-+
-+ memcpy(p, &v, chunk);
-+ p += chunk;
-+ nbytes -= chunk;
-+ }
-+
-+ if (nbytes)
-+ lrng_drng_get_atomic((u8 *)p, (u32)nbytes);
-+
-+ return nbytes;
-+}
-+EXPORT_SYMBOL(get_random_bytes_arch);
-+
-+/*
-+ * Returns whether or not the LRNG has been seeded.
-+ *
-+ * Returns: true if the urandom pool has been seeded.
-+ * false if the urandom pool has not been seeded.
-+ */
-+bool rng_is_initialized(void)
-+{
-+ return lrng_state_operational();
-+}
-+EXPORT_SYMBOL(rng_is_initialized);
-+
-+/************************ LRNG user output interfaces *************************/
-+
-+static ssize_t lrng_read_common(char __user *buf, size_t nbytes)
-+{
-+ ssize_t ret = 0;
-+ u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
-+ u8 *tmp_large = NULL, *tmp = tmpbuf;
-+ u32 tmplen = sizeof(tmpbuf);
-+
-+ if (nbytes == 0)
-+ return 0;
-+
-+ /*
-+ * Satisfy large read requests -- as the common case are smaller
-+ * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
-+ * those by using the stack variable of tmpbuf.
-+ */
-+ if (!CONFIG_BASE_SMALL && (nbytes > sizeof(tmpbuf))) {
-+ tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
-+ tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
-+ if (!tmp_large)
-+ tmplen = sizeof(tmpbuf);
-+ else
-+ tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
-+ }
-+
-+ while (nbytes) {
-+ u32 todo = min_t(u32, nbytes, tmplen);
-+ int rc = 0;
-+
-+ /* Reschedule if we received a large request. */
-+ if ((tmp_large) && need_resched()) {
-+ if (signal_pending(current)) {
-+ if (ret == 0)
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+
-+ rc = lrng_drng_get_sleep(tmp, todo);
-+ if (rc <= 0) {
-+ if (rc < 0)
-+ ret = rc;
-+ break;
-+ }
-+ if (copy_to_user(buf, tmp, rc)) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ nbytes -= rc;
-+ buf += rc;
-+ ret += rc;
-+ }
-+
-+ /* Wipe data just returned from memory */
-+ if (tmp_large)
-+ kfree_sensitive(tmp_large);
-+ else
-+ memzero_explicit(tmpbuf, sizeof(tmpbuf));
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes)
-+{
-+ if (nbytes == 0)
-+ return 0;
-+
-+ if (unlikely(!lrng_state_operational())) {
-+ int ret;
-+
-+ if (nonblock)
-+ return -EAGAIN;
-+
-+ ret = wait_event_interruptible(lrng_init_wait,
-+ lrng_state_operational());
-+ if (unlikely(ret))
-+ return ret;
-+ }
-+
-+ return lrng_read_common(buf, nbytes);
-+}
-+
-+static ssize_t lrng_drng_read_block(struct file *file, char __user *buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes);
-+}
-+
-+static __poll_t lrng_random_poll(struct file *file, poll_table *wait)
-+{
-+ __poll_t mask;
-+
-+ poll_wait(file, &lrng_init_wait, wait);
-+ poll_wait(file, &lrng_write_wait, wait);
-+ mask = 0;
-+ if (lrng_state_operational())
-+ mask |= EPOLLIN | EPOLLRDNORM;
-+ if (lrng_need_entropy() ||
-+ lrng_state_exseed_allow(lrng_noise_source_user)) {
-+ lrng_state_exseed_set(lrng_noise_source_user, false);
-+ mask |= EPOLLOUT | EPOLLWRNORM;
-+ }
-+ return mask;
-+}
-+
-+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
-+ u32 entropy_bits)
-+{
-+ ssize_t ret = 0;
-+ u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
-+ const char __user *p = buffer;
-+ u32 orig_entropy_bits = entropy_bits;
-+
-+ if (!lrng_get_available())
-+ return -EAGAIN;
-+
-+ count = min_t(size_t, count, INT_MAX);
-+ while (count > 0) {
-+ size_t bytes = min_t(size_t, count, sizeof(buf));
-+ u32 ent = min_t(u32, bytes<<3, entropy_bits);
-+
-+ if (copy_from_user(&buf, p, bytes))
-+ return -EFAULT;
-+ /* Inject data into entropy pool */
-+ lrng_pool_insert_aux(buf, bytes, ent);
-+
-+ count -= bytes;
-+ p += bytes;
-+ ret += bytes;
-+ entropy_bits -= ent;
-+
-+ cond_resched();
-+ }
-+
-+ /* Force reseed of DRNG during next data request. */
-+ if (!orig_entropy_bits)
-+ lrng_drng_force_reseed();
-+
-+ return ret;
-+}
-+
-+static ssize_t lrng_drng_read(struct file *file, char __user *buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ if (!lrng_state_min_seeded())
-+ pr_notice_ratelimited("%s - use of insufficiently seeded DRNG (%zu bytes read)\n",
-+ current->comm, nbytes);
-+ else if (!lrng_state_operational())
-+ pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu bytes read)\n",
-+ current->comm, nbytes);
-+
-+ return lrng_read_common(buf, nbytes);
-+}
-+
-+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_drng_write_common(buffer, count, 0);
-+}
-+
-+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-+{
-+ u32 digestsize_bits;
-+ int size, ent_count_bits;
-+ int __user *p = (int __user *)arg;
-+
-+ switch (cmd) {
-+ case RNDGETENTCNT:
-+ ent_count_bits = lrng_avail_entropy();
-+ if (put_user(ent_count_bits, p))
-+ return -EFAULT;
-+ return 0;
-+ case RNDADDTOENTCNT:
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ if (get_user(ent_count_bits, p))
-+ return -EFAULT;
-+ ent_count_bits = (int)lrng_avail_aux_entropy() + ent_count_bits;
-+ if (ent_count_bits < 0)
-+ ent_count_bits = 0;
-+ digestsize_bits = lrng_get_digestsize();
-+ if (ent_count_bits > digestsize_bits)
-+ ent_count_bits = digestsize_bits;
-+ lrng_pool_set_entropy(ent_count_bits);
-+ return 0;
-+ case RNDADDENTROPY:
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ if (get_user(ent_count_bits, p++))
-+ return -EFAULT;
-+ if (ent_count_bits < 0)
-+ return -EINVAL;
-+ if (get_user(size, p++))
-+ return -EFAULT;
-+ if (size < 0)
-+ return -EINVAL;
-+ /* there cannot be more entropy than data */
-+ ent_count_bits = min(ent_count_bits, size<<3);
-+ return lrng_drng_write_common((const char __user *)p, size,
-+ ent_count_bits);
-+ case RNDZAPENTCNT:
-+ case RNDCLEARPOOL:
-+ /* Clear the entropy pool counter. */
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ lrng_pool_set_entropy(0);
-+ return 0;
-+ case RNDRESEEDCRNG:
-+ /*
-+ * We leave the capability check here since it is present
-+ * in the upstream's RNG implementation. Yet, user space
-+ * can trigger a reseed as easy as writing into /dev/random
-+ * or /dev/urandom where no privilege is needed.
-+ */
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ /* Force a reseed of all DRNGs */
-+ lrng_drng_force_reseed();
-+ return 0;
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+static int lrng_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &fasync);
-+}
-+
-+const struct file_operations random_fops = {
-+ .read = lrng_drng_read_block,
-+ .write = lrng_drng_write,
-+ .poll = lrng_random_poll,
-+ .unlocked_ioctl = lrng_ioctl,
-+ .compat_ioctl = compat_ptr_ioctl,
-+ .fasync = lrng_fasync,
-+ .llseek = noop_llseek,
-+};
-+
-+const struct file_operations urandom_fops = {
-+ .read = lrng_drng_read,
-+ .write = lrng_drng_write,
-+ .unlocked_ioctl = lrng_ioctl,
-+ .compat_ioctl = compat_ptr_ioctl,
-+ .fasync = lrng_fasync,
-+ .llseek = noop_llseek,
-+};
-+
-+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
-+ unsigned int, flags)
-+{
-+ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE))
-+ return -EINVAL;
-+
-+ /*
-+ * Requesting insecure and blocking randomness at the same time makes
-+ * no sense.
-+ */
-+ if ((flags &
-+ (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
-+ return -EINVAL;
-+
-+ if (count > INT_MAX)
-+ count = INT_MAX;
-+
-+ if (flags & GRND_INSECURE)
-+ return lrng_drng_read(NULL, buf, count, NULL);
-+
-+ return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count);
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_internal.h linux-5.15-lrng/drivers/char/lrng/lrng_internal.h
---- linux-5.15/drivers/char/lrng/lrng_internal.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_internal.h 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,485 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
-+/*
-+ * Copyright (C) 2018 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#ifndef _LRNG_INTERNAL_H
-+#define _LRNG_INTERNAL_H
-+
-+#include <crypto/sha1.h>
-+#include <crypto/sha2.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/rwlock.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+
-+/*************************** General LRNG parameter ***************************/
-+
-+/* Security strength of LRNG -- this must match DRNG security strength */
-+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
-+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
-+#define LRNG_DRNG_BLOCKSIZE 64 /* Maximum of DRNG block sizes */
-+#define LRNG_DRNG_INIT_SEED_SIZE_BITS (LRNG_DRNG_SECURITY_STRENGTH_BITS + \
-+ CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS)
-+#define LRNG_DRNG_INIT_SEED_SIZE_BYTES (LRNG_DRNG_INIT_SEED_SIZE_BITS >> 3)
-+
-+/*
-+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
-+ * considered a safer margin.
-+ *
-+ * This value is allowed to be changed.
-+ */
-+#define LRNG_DRNG_MAX_REQSIZE (1<<12)
-+
-+/*
-+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
-+ * The given value is considered a much safer margin, balancing requests for
-+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
-+ * larger than INT_MAX because it is used in an atomic_t.
-+ *
-+ * This value is allowed to be changed.
-+ */
-+#define LRNG_DRNG_RESEED_THRESH (1<<20)
-+
-+/*
-+ * Maximum DRNG generation operations without reseed having full entropy
-+ * This value defines the absolute maximum value of DRNG generation operations
-+ * without a reseed holding full entropy. LRNG_DRNG_RESEED_THRESH is the
-+ * threshold when a new reseed is attempted. But it is possible that this fails
-+ * to deliver full entropy. In this case the DRNG will continue to provide data
-+ * even though it was not reseeded with full entropy. To avoid in the extreme
-+ * case that no reseed is performed for too long, this threshold is enforced.
-+ * If that absolute low value is reached, the LRNG is marked as not operational.
-+ *
-+ * This value is allowed to be changed.
-+ */
-+#define LRNG_DRNG_MAX_WITHOUT_RESEED (1<<30)
-+
-+/*
-+ * Min required seed entropy is 128 bits covering the minimum entropy
-+ * requirement of SP800-131A and the German BSI's TR02102.
-+ *
-+ * This value is allowed to be changed.
-+ */
-+#define LRNG_FULL_SEED_ENTROPY_BITS LRNG_DRNG_SECURITY_STRENGTH_BITS
-+#define LRNG_MIN_SEED_ENTROPY_BITS 128
-+#define LRNG_INIT_ENTROPY_BITS 32
-+
-+/*
-+ * Wakeup value
-+ *
-+ * This value is allowed to be changed but must not be larger than the
-+ * digest size of the hash operation used update the aux_pool.
-+ */
-+#ifdef CONFIG_CRYPTO_LIB_SHA256
-+# define LRNG_ATOMIC_DIGEST_SIZE SHA256_DIGEST_SIZE
-+#else
-+# define LRNG_ATOMIC_DIGEST_SIZE SHA1_DIGEST_SIZE
-+#endif
-+#define LRNG_WRITE_WAKEUP_ENTROPY LRNG_ATOMIC_DIGEST_SIZE
-+
-+/*
-+ * If the switching support is configured, we must provide support up to
-+ * the largest digest size. Without switching support, we know it is only
-+ * the built-in digest size.
-+ */
-+#ifdef CONFIG_LRNG_DRNG_SWITCH
-+# define LRNG_MAX_DIGESTSIZE 64
-+#else
-+# define LRNG_MAX_DIGESTSIZE LRNG_ATOMIC_DIGEST_SIZE
-+#endif
-+
-+/*
-+ * Oversampling factor of IRQ events to obtain
-+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
-+ * high-resolution time stamp is not available. In this case, jiffies and
-+ * register contents are used to fill the entropy pool. These noise sources
-+ * are much less entropic than the high-resolution timer. The entropy content
-+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
-+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
-+ *
-+ * This value is allowed to be changed.
-+ */
-+#define LRNG_IRQ_OVERSAMPLING_FACTOR 10
-+
-+/* Alignmask that is intended to be identical to CRYPTO_MINALIGN */
-+#define LRNG_KCAPI_ALIGN ARCH_KMALLOC_MINALIGN
-+
-+/*
-+ * This definition must provide a buffer that is equal to SHASH_DESC_ON_STACK
-+ * as it will be casted into a struct shash_desc.
-+ */
-+#define LRNG_POOL_SIZE (sizeof(struct shash_desc) + HASH_MAX_DESCSIZE)
-+
-+/************************ Default DRNG implementation *************************/
-+
-+extern struct chacha20_state chacha20;
-+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
-+void lrng_cc20_init_state(struct chacha20_state *state);
-+
-+/********************************** /proc *************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+void lrng_pool_inc_numa_node(void);
-+void lrng_proc_update_max_write_thresh(u32 new_digestsize);
-+#else
-+static inline void lrng_pool_inc_numa_node(void) { }
-+static inline void lrng_proc_update_max_write_thresh(u32 new_digestsize) { }
-+#endif
-+
-+/****************************** LRNG interfaces *******************************/
-+
-+extern u32 lrng_write_wakeup_bits;
-+extern int lrng_drng_reseed_max_time;
-+
-+void lrng_writer_wakeup(void);
-+void lrng_init_wakeup(void);
-+void lrng_debug_report_seedlevel(const char *name);
-+void lrng_process_ready_list(void);
-+
-+/* External interface to use of the switchable DRBG inside the kernel */
-+void get_random_bytes_full(void *buf, int nbytes);
-+
-+/************************* Jitter RNG Entropy Source **************************/
-+
-+#ifdef CONFIG_LRNG_JENT
-+u32 lrng_get_jent(u8 *outbuf, u32 requested_bits);
-+u32 lrng_jent_entropylevel(u32 requested_bits);
-+void lrng_jent_es_state(unsigned char *buf, size_t buflen);
-+#else /* CONFIG_LRNG_JENT */
-+static inline u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) { return 0; }
-+static inline u32 lrng_jent_entropylevel(u32 requested_bits) { return 0; }
-+static inline void lrng_jent_es_state(unsigned char *buf, size_t buflen) { }
-+#endif /* CONFIG_LRNG_JENT */
-+
-+/************************** CPU-based Entropy Source **************************/
-+
-+static inline u32 lrng_fast_noise_entropylevel(u32 ent_bits, u32 requested_bits)
-+{
-+ /* Obtain entropy statement */
-+ ent_bits = ent_bits * requested_bits / LRNG_DRNG_SECURITY_STRENGTH_BITS;
-+ /* Cap entropy to buffer size in bits */
-+ ent_bits = min_t(u32, ent_bits, requested_bits);
-+ return ent_bits;
-+}
-+
-+#ifdef CONFIG_LRNG_CPU
-+u32 lrng_get_arch(u8 *outbuf, u32 requested_bits);
-+u32 lrng_archrandom_entropylevel(u32 requested_bits);
-+void lrng_arch_es_state(unsigned char *buf, size_t buflen);
-+#else /* CONFIG_LRNG_CPU */
-+static inline u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) { return 0; }
-+static inline u32 lrng_archrandom_entropylevel(u32 requested_bits) { return 0; }
-+static inline void lrng_arch_es_state(unsigned char *buf, size_t buflen) { }
-+#endif /* CONFIG_LRNG_CPU */
-+
-+/************************** Interrupt Entropy Source **************************/
-+
-+#ifdef CONFIG_LRNG_IRQ
-+void lrng_pcpu_reset(void);
-+u32 lrng_pcpu_avail_pool_size(void);
-+u32 lrng_pcpu_avail_entropy(void);
-+int lrng_pcpu_switch_hash(int node,
-+ const struct lrng_crypto_cb *new_cb, void *new_hash,
-+ const struct lrng_crypto_cb *old_cb);
-+u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded);
-+void lrng_pcpu_array_add_u32(u32 data);
-+u32 lrng_gcd_analyze(u32 *history, size_t nelem);
-+void lrng_irq_es_state(unsigned char *buf, size_t buflen);
-+#else /* CONFIG_LRNG_IRQ */
-+static inline void lrng_pcpu_reset(void) { }
-+static inline u32 lrng_pcpu_avail_pool_size(void) { return 0; }
-+static inline u32 lrng_pcpu_avail_entropy(void) { return 0; }
-+static inline int lrng_pcpu_switch_hash(int node,
-+ const struct lrng_crypto_cb *new_cb, void *new_hash,
-+ const struct lrng_crypto_cb *old_cb)
-+{
-+ return 0;
-+}
-+static inline u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits,
-+ bool fully_seeded)
-+{
-+ return 0;
-+}
-+static inline void lrng_pcpu_array_add_u32(u32 data) { }
-+static inline void lrng_irq_es_state(unsigned char *buf, size_t buflen) { }
-+#endif /* CONFIG_LRNG_IRQ */
-+
-+/****************************** DRNG processing *******************************/
-+
-+/* DRNG state handle */
-+struct lrng_drng {
-+ void *drng; /* DRNG handle */
-+ void *hash; /* Hash handle */
-+ const struct lrng_crypto_cb *crypto_cb; /* Crypto callbacks */
-+ atomic_t requests; /* Number of DRNG requests */
-+ atomic_t requests_since_fully_seeded; /* Number DRNG requests since
-+ last fully seeded */
-+ unsigned long last_seeded; /* Last time it was seeded */
-+ bool fully_seeded; /* Is DRNG fully seeded? */
-+ bool force_reseed; /* Force a reseed */
-+
-+ /* Lock write operations on DRNG state, DRNG replacement of crypto_cb */
-+ struct mutex lock;
-+ spinlock_t spin_lock;
-+ /* Lock *hash replacement - always take before DRNG lock */
-+ rwlock_t hash_lock;
-+};
-+
-+extern struct mutex lrng_crypto_cb_update;
-+
-+struct lrng_drng *lrng_drng_init_instance(void);
-+struct lrng_drng *lrng_drng_atomic_instance(void);
-+
-+static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng)
-+{
-+ return (drng->drng == lrng_drng_atomic_instance()->drng);
-+}
-+
-+/* Lock the DRNG */
-+static __always_inline void lrng_drng_lock(struct lrng_drng *drng,
-+ unsigned long *flags)
-+ __acquires(&drng->spin_lock)
-+{
-+ /* Use spin lock in case the atomic DRNG context is used */
-+ if (lrng_drng_is_atomic(drng)) {
-+ spin_lock_irqsave(&drng->spin_lock, *flags);
-+
-+ /*
-+ * In case a lock transition happened while we were spinning,
-+ * catch this case and use the new lock type.
-+ */
-+ if (!lrng_drng_is_atomic(drng)) {
-+ spin_unlock_irqrestore(&drng->spin_lock, *flags);
-+ __acquire(&drng->spin_lock);
-+ mutex_lock(&drng->lock);
-+ }
-+ } else {
-+ __acquire(&drng->spin_lock);
-+ mutex_lock(&drng->lock);
-+ }
-+}
-+
-+/* Unlock the DRNG */
-+static __always_inline void lrng_drng_unlock(struct lrng_drng *drng,
-+ unsigned long *flags)
-+ __releases(&drng->spin_lock)
-+{
-+ if (lrng_drng_is_atomic(drng)) {
-+ spin_unlock_irqrestore(&drng->spin_lock, *flags);
-+ } else {
-+ mutex_unlock(&drng->lock);
-+ __release(&drng->spin_lock);
-+ }
-+}
-+
-+void lrng_reset(void);
-+void lrng_drngs_init_cc20(bool force_seed);
-+bool lrng_sp80090c_compliant(void);
-+
-+static inline u32 lrng_compress_osr(void)
-+{
-+ return lrng_sp80090c_compliant() ? CONFIG_LRNG_OVERSAMPLE_ES_BITS : 0;
-+}
-+
-+static inline u32 lrng_reduce_by_osr(u32 entropy_bits)
-+{
-+ u32 osr_bits = lrng_compress_osr();
-+ return (entropy_bits >= osr_bits) ? (entropy_bits - osr_bits) : 0;
-+}
-+
-+bool lrng_get_available(void);
-+void lrng_set_available(void);
-+void lrng_drng_reset(struct lrng_drng *drng);
-+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen);
-+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
-+void lrng_drng_force_reseed(void);
-+void lrng_drng_seed_work(struct work_struct *dummy);
-+
-+#ifdef CONFIG_NUMA
-+struct lrng_drng **lrng_drng_instances(void);
-+void lrng_drngs_numa_alloc(void);
-+#else /* CONFIG_NUMA */
-+static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
-+static inline void lrng_drngs_numa_alloc(void) { return; }
-+#endif /* CONFIG_NUMA */
-+
-+/************************* Entropy sources management *************************/
-+
-+enum lrng_external_noise_source {
-+ lrng_noise_source_hw,
-+ lrng_noise_source_user
-+};
-+
-+void lrng_set_entropy_thresh(u32 new);
-+u32 lrng_avail_entropy(void);
-+void lrng_reset_state(void);
-+
-+bool lrng_state_exseed_allow(enum lrng_external_noise_source source);
-+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type);
-+bool lrng_state_min_seeded(void);
-+bool lrng_state_fully_seeded(void);
-+bool lrng_state_operational(void);
-+
-+int lrng_pool_trylock(void);
-+void lrng_pool_unlock(void);
-+void lrng_pool_all_numa_nodes_seeded(bool set);
-+void lrng_pool_add_entropy(void);
-+
-+struct entropy_buf {
-+ u8 a[LRNG_DRNG_INIT_SEED_SIZE_BYTES];
-+ u8 b[LRNG_DRNG_INIT_SEED_SIZE_BYTES];
-+ u8 c[LRNG_DRNG_INIT_SEED_SIZE_BYTES];
-+ u8 d[LRNG_DRNG_INIT_SEED_SIZE_BYTES];
-+ u32 now, a_bits, b_bits, c_bits, d_bits;
-+};
-+
-+bool lrng_fully_seeded(bool fully_seeded, struct entropy_buf *eb);
-+void lrng_unset_fully_seeded(struct lrng_drng *drng);
-+void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits);
-+void lrng_init_ops(struct entropy_buf *eb);
-+
-+/*********************** Auxiliary Pool Entropy Source ************************/
-+
-+u32 lrng_avail_aux_entropy(void);
-+void lrng_aux_es_state(unsigned char *buf, size_t buflen);
-+u32 lrng_get_digestsize(void);
-+void lrng_pool_set_entropy(u32 entropy_bits);
-+int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash,
-+ const struct lrng_crypto_cb *old_cb);
-+int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits);
-+void lrng_get_backtrack_aux(struct entropy_buf *entropy_buf,
-+ u32 requested_bits);
-+
-+/* Obtain the security strength of the LRNG in bits */
-+static inline u32 lrng_security_strength(void)
-+{
-+ /*
-+ * We use a hash to read the entropy in the entropy pool. According to
-+ * SP800-90B table 1, the entropy can be at most the digest size.
-+ * Considering this together with the last sentence in section 3.1.5.1.2
-+ * the security strength of a (approved) hash is equal to its output
-+ * size. On the other hand the entropy cannot be larger than the
-+ * security strength of the used DRBG.
-+ */
-+ return min_t(u32, LRNG_FULL_SEED_ENTROPY_BITS, lrng_get_digestsize());
-+}
-+
-+static inline u32 lrng_get_seed_entropy_osr(bool fully_seeded)
-+{
-+ u32 requested_bits = lrng_security_strength();
-+
-+ /* Apply oversampling during initialization according to SP800-90C */
-+ if (lrng_sp80090c_compliant() && !fully_seeded)
-+ requested_bits += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS;
-+ return requested_bits;
-+}
-+
-+/************************** Health Test linking code **************************/
-+
-+enum lrng_health_res {
-+ lrng_health_pass, /* Health test passes on time stamp */
-+ lrng_health_fail_use, /* Time stamp unhealthy, but mix in */
-+ lrng_health_fail_drop /* Time stamp unhealthy, drop it */
-+};
-+
-+#ifdef CONFIG_LRNG_HEALTH_TESTS
-+bool lrng_sp80090b_startup_complete(void);
-+bool lrng_sp80090b_compliant(void);
-+
-+enum lrng_health_res lrng_health_test(u32 now_time);
-+void lrng_health_disable(void);
-+
-+#else /* CONFIG_LRNG_HEALTH_TESTS */
-+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
-+static inline bool lrng_sp80090b_compliant(void) { return false; }
-+
-+static inline enum lrng_health_res
-+lrng_health_test(u32 now_time) { return lrng_health_pass; }
-+static inline void lrng_health_disable(void) { }
-+#endif /* CONFIG_LRNG_HEALTH_TESTS */
-+
-+/****************************** Helper code ***********************************/
-+
-+static inline u32 atomic_read_u32(atomic_t *v)
-+{
-+ return (u32)atomic_read(v);
-+}
-+
-+/******************** Crypto Primitive Switching Support **********************/
-+
-+#ifdef CONFIG_LRNG_DRNG_SWITCH
-+static inline void lrng_hash_lock(struct lrng_drng *drng, unsigned long *flags)
-+{
-+ read_lock_irqsave(&drng->hash_lock, *flags);
-+}
-+
-+static inline void lrng_hash_unlock(struct lrng_drng *drng, unsigned long flags)
-+{
-+ read_unlock_irqrestore(&drng->hash_lock, flags);
-+}
-+#else /* CONFIG_LRNG_DRNG_SWITCH */
-+static inline void lrng_hash_lock(struct lrng_drng *drng, unsigned long *flags)
-+{ }
-+
-+static inline void lrng_hash_unlock(struct lrng_drng *drng, unsigned long flags)
-+{ }
-+#endif /* CONFIG_LRNG_DRNG_SWITCH */
-+
-+/*************************** Auxiliary functions ******************************/
-+
-+void invalidate_batched_entropy(void);
-+
-+/***************************** Testing code ***********************************/
-+
-+#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY
-+bool lrng_raw_hires_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_HIRES_ENTROPY */
-+static inline bool lrng_raw_hires_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY
-+bool lrng_raw_jiffies_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */
-+static inline bool lrng_raw_jiffies_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY
-+bool lrng_raw_irq_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_IRQ_ENTROPY */
-+static inline bool lrng_raw_irq_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY
-+bool lrng_raw_irqflags_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */
-+static inline bool lrng_raw_irqflags_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY
-+bool lrng_raw_retip_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_RETIP_ENTROPY */
-+static inline bool lrng_raw_retip_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY
-+bool lrng_raw_regs_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_REGS_ENTROPY */
-+static inline bool lrng_raw_regs_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */
-+
-+#ifdef CONFIG_LRNG_RAW_ARRAY
-+bool lrng_raw_array_entropy_store(u32 value);
-+#else /* CONFIG_LRNG_RAW_ARRAY */
-+static inline bool lrng_raw_array_entropy_store(u32 value) { return false; }
-+#endif /* CONFIG_LRNG_RAW_ARRAY */
-+
-+#ifdef CONFIG_LRNG_IRQ_PERF
-+bool lrng_perf_time(u32 start);
-+#else /* CONFIG_LRNG_IRQ_PERF */
-+static inline bool lrng_perf_time(u32 start) { return false; }
-+#endif /*CONFIG_LRNG_IRQ_PERF */
-+
-+#endif /* _LRNG_INTERNAL_H */
-diff -urN linux-5.15/drivers/char/lrng/lrng_kcapi.c linux-5.15-lrng/drivers/char/lrng/lrng_kcapi.c
---- linux-5.15/drivers/char/lrng/lrng_kcapi.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_kcapi.c 2021-11-29 12:37:45.153278971 +1100
-@@ -0,0 +1,227 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Backend for the LRNG providing the cryptographic primitives using the
-+ * kernel crypto API.
-+ *
-+ * Copyright (C) 2018 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <crypto/hash.h>
-+#include <crypto/rng.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/lrng.h>
-+
-+#include "lrng_kcapi_hash.h"
-+
-+static char *drng_name = NULL;
-+module_param(drng_name, charp, 0444);
-+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
-+
-+static char *pool_hash = "sha512";
-+module_param(pool_hash, charp, 0444);
-+MODULE_PARM_DESC(pool_hash,
-+ "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
-+
-+static char *seed_hash = NULL;
-+module_param(seed_hash, charp, 0444);
-+MODULE_PARM_DESC(seed_hash,
-+ "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
-+
-+struct lrng_drng_info {
-+ struct crypto_rng *kcapi_rng;
-+ void *lrng_hash;
-+};
-+
-+static void *lrng_kcapi_drng_hash_alloc(void)
-+{
-+ return lrng_kcapi_hash_alloc(pool_hash);
-+}
-+
-+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
-+ u32 inbuflen)
-+{
-+ SHASH_DESC_ON_STACK(shash, NULL);
-+ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
-+ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
-+ void *hash = lrng_drng_info->lrng_hash;
-+ u32 digestsize = lrng_kcapi_hash_digestsize(hash);
-+ u8 digest[64] __aligned(8);
-+ int ret;
-+
-+ if (!hash)
-+ return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
-+
-+ BUG_ON(digestsize > sizeof(digest));
-+
-+ ret = lrng_kcapi_hash_init(shash, hash) ?:
-+ lrng_kcapi_hash_update(shash, inbuf, inbuflen) ?:
-+ lrng_kcapi_hash_final(shash, digest);
-+ lrng_kcapi_hash_zero(shash);
-+ if (ret)
-+ return ret;
-+
-+ ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
-+ if (ret)
-+ return ret;
-+
-+ memzero_explicit(digest, digestsize);
-+ return 0;
-+}
-+
-+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
-+ u32 outbuflen)
-+{
-+ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
-+ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
-+ int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
-+
-+ if (ret < 0)
-+ return ret;
-+
-+ return outbuflen;
-+}
-+
-+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
-+{
-+ struct lrng_drng_info *lrng_drng_info;
-+ struct crypto_rng *kcapi_rng;
-+ int seedsize;
-+ void *ret = ERR_PTR(-ENOMEM);
-+
-+ if (!drng_name) {
-+ pr_err("DRNG name missing\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ if (!memcmp(drng_name, "drbg", 4) ||
-+ !memcmp(drng_name, "stdrng", 6) ||
-+ !memcmp(drng_name, "jitterentropy_rng", 17)) {
-+ pr_err("Refusing to load the requested random number generator\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
-+ if (!lrng_drng_info)
-+ return ERR_PTR(-ENOMEM);
-+
-+ kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
-+ if (IS_ERR(kcapi_rng)) {
-+ pr_err("DRNG %s cannot be allocated\n", drng_name);
-+ ret = ERR_CAST(kcapi_rng);
-+ goto free;
-+ }
-+ lrng_drng_info->kcapi_rng = kcapi_rng;
-+
-+ seedsize = crypto_rng_seedsize(kcapi_rng);
-+
-+ if (sec_strength > seedsize)
-+ pr_info("Seedsize DRNG (%u bits) lower than security strength of LRNG noise source (%u bits)\n",
-+ crypto_rng_seedsize(kcapi_rng) * 8, sec_strength * 8);
-+
-+ if (seedsize) {
-+ void *lrng_hash;
-+
-+ if (!seed_hash) {
-+ switch (seedsize) {
-+ case 32:
-+ seed_hash = "sha256";
-+ break;
-+ case 48:
-+ seed_hash = "sha384";
-+ break;
-+ case 64:
-+ seed_hash = "sha512";
-+ break;
-+ default:
-+ pr_err("Seed size %d cannot be processed\n",
-+ seedsize);
-+ goto dealloc;
-+ }
-+ }
-+
-+ lrng_hash = lrng_kcapi_hash_alloc(seed_hash);
-+ if (IS_ERR(lrng_hash)) {
-+ ret = ERR_CAST(lrng_hash);
-+ goto dealloc;
-+ }
-+
-+ if (seedsize != lrng_kcapi_hash_digestsize(lrng_hash)) {
-+ pr_err("Seed hash output size not equal to DRNG seed size\n");
-+ lrng_kcapi_hash_dealloc(lrng_hash);
-+ ret = ERR_PTR(-EINVAL);
-+ goto dealloc;
-+ }
-+
-+ lrng_drng_info->lrng_hash = lrng_hash;
-+
-+ pr_info("Seed hash %s allocated\n", seed_hash);
-+ } else {
-+ lrng_drng_info->lrng_hash = NULL;
-+ }
-+
-+ pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
-+
-+ return lrng_drng_info;
-+
-+dealloc:
-+ crypto_free_rng(kcapi_rng);
-+free:
-+ kfree(lrng_drng_info);
-+ return ret;
-+}
-+
-+static void lrng_kcapi_drng_dealloc(void *drng)
-+{
-+ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
-+ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
-+
-+ crypto_free_rng(kcapi_rng);
-+ if (lrng_drng_info->lrng_hash)
-+ lrng_kcapi_hash_dealloc(lrng_drng_info->lrng_hash);
-+ kfree(lrng_drng_info);
-+ pr_info("DRNG %s deallocated\n", drng_name);
-+}
-+
-+static const char *lrng_kcapi_drng_name(void)
-+{
-+ return drng_name;
-+}
-+
-+static const char *lrng_kcapi_pool_hash(void)
-+{
-+ return pool_hash;
-+}
-+
-+static const struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
-+ .lrng_drng_name = lrng_kcapi_drng_name,
-+ .lrng_hash_name = lrng_kcapi_pool_hash,
-+ .lrng_drng_alloc = lrng_kcapi_drng_alloc,
-+ .lrng_drng_dealloc = lrng_kcapi_drng_dealloc,
-+ .lrng_drng_seed_helper = lrng_kcapi_drng_seed_helper,
-+ .lrng_drng_generate_helper = lrng_kcapi_drng_generate_helper,
-+ .lrng_hash_alloc = lrng_kcapi_drng_hash_alloc,
-+ .lrng_hash_dealloc = lrng_kcapi_hash_dealloc,
-+ .lrng_hash_digestsize = lrng_kcapi_hash_digestsize,
-+ .lrng_hash_init = lrng_kcapi_hash_init,
-+ .lrng_hash_update = lrng_kcapi_hash_update,
-+ .lrng_hash_final = lrng_kcapi_hash_final,
-+ .lrng_hash_desc_zero = lrng_kcapi_hash_zero,
-+};
-+
-+static int __init lrng_kcapi_init(void)
-+{
-+ return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
-+}
-+static void __exit lrng_kcapi_exit(void)
-+{
-+ lrng_set_drng_cb(NULL);
-+}
-+
-+late_initcall(lrng_kcapi_init);
-+module_exit(lrng_kcapi_exit);
-+MODULE_LICENSE("Dual BSD/GPL");
-+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
-+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-diff -urN linux-5.15/drivers/char/lrng/lrng_kcapi_hash.c linux-5.15-lrng/drivers/char/lrng/lrng_kcapi_hash.c
---- linux-5.15/drivers/char/lrng/lrng_kcapi_hash.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_kcapi_hash.c 2021-11-29 12:37:24.863279049 +1100
-@@ -0,0 +1,103 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Backend for providing the hash primitive using the kernel crypto API.
-+ *
-+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <crypto/hash.h>
-+
-+#include "lrng_kcapi_hash.h"
-+
-+struct lrng_hash_info {
-+ struct crypto_shash *tfm;
-+};
-+
-+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
-+{
-+ struct crypto_shash *tfm = lrng_hash->tfm;
-+
-+ crypto_free_shash(tfm);
-+ kfree(lrng_hash);
-+}
-+
-+void *lrng_kcapi_hash_alloc(const char *name)
-+{
-+ struct lrng_hash_info *lrng_hash;
-+ struct crypto_shash *tfm;
-+ int ret;
-+
-+ if (!name) {
-+ pr_err("Hash name missing\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ tfm = crypto_alloc_shash(name, 0, 0);
-+ if (IS_ERR(tfm)) {
-+ pr_err("could not allocate hash %s\n", name);
-+ return ERR_CAST(tfm);
-+ }
-+
-+ ret = sizeof(struct lrng_hash_info);
-+ lrng_hash = kmalloc(ret, GFP_KERNEL);
-+ if (!lrng_hash) {
-+ crypto_free_shash(tfm);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ lrng_hash->tfm = tfm;
-+
-+ pr_info("Hash %s allocated\n", name);
-+
-+ return lrng_hash;
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_alloc);
-+
-+u32 lrng_kcapi_hash_digestsize(void *hash)
-+{
-+ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
-+ struct crypto_shash *tfm = lrng_hash->tfm;
-+
-+ return crypto_shash_digestsize(tfm);
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_digestsize);
-+
-+void lrng_kcapi_hash_dealloc(void *hash)
-+{
-+ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
-+
-+ _lrng_kcapi_hash_free(lrng_hash);
-+ pr_info("Hash deallocated\n");
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_dealloc);
-+
-+int lrng_kcapi_hash_init(struct shash_desc *shash, void *hash)
-+{
-+ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
-+ struct crypto_shash *tfm = lrng_hash->tfm;
-+
-+ shash->tfm = tfm;
-+ return crypto_shash_init(shash);
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_init);
-+
-+int lrng_kcapi_hash_update(struct shash_desc *shash, const u8 *inbuf,
-+ u32 inbuflen)
-+{
-+ return crypto_shash_update(shash, inbuf, inbuflen);
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_update);
-+
-+int lrng_kcapi_hash_final(struct shash_desc *shash, u8 *digest)
-+{
-+ return crypto_shash_final(shash, digest);
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_final);
-+
-+void lrng_kcapi_hash_zero(struct shash_desc *shash)
-+{
-+ shash_desc_zero(shash);
-+}
-+EXPORT_SYMBOL(lrng_kcapi_hash_zero);
-diff -urN linux-5.15/drivers/char/lrng/lrng_kcapi_hash.h linux-5.15-lrng/drivers/char/lrng/lrng_kcapi_hash.h
---- linux-5.15/drivers/char/lrng/lrng_kcapi_hash.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_kcapi_hash.h 2021-11-29 12:37:24.863279049 +1100
-@@ -0,0 +1,20 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
-+/*
-+ * Copyright (C) 2020 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#ifndef _LRNG_KCAPI_HASH_H
-+#define _LRNG_KCAPI_HASH_H
-+
-+#include <linux/module.h>
-+
-+void *lrng_kcapi_hash_alloc(const char *name);
-+u32 lrng_kcapi_hash_digestsize(void *hash);
-+void lrng_kcapi_hash_dealloc(void *hash);
-+int lrng_kcapi_hash_init(struct shash_desc *shash, void *hash);
-+int lrng_kcapi_hash_update(struct shash_desc *shash, const u8 *inbuf,
-+ u32 inbuflen);
-+int lrng_kcapi_hash_final(struct shash_desc *shash, u8 *digest);
-+void lrng_kcapi_hash_zero(struct shash_desc *shash);
-+
-+#endif /* _LRNG_KCAPI_HASH_H */
-diff -urN linux-5.15/drivers/char/lrng/lrng_numa.c linux-5.15-lrng/drivers/char/lrng/lrng_numa.c
---- linux-5.15/drivers/char/lrng/lrng_numa.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_numa.c 2021-11-29 12:37:08.753279110 +1100
-@@ -0,0 +1,122 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG NUMA support
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/lrng.h>
-+#include <linux/slab.h>
-+
-+#include "lrng_internal.h"
-+
-+static struct lrng_drng **lrng_drng __read_mostly = NULL;
-+
-+struct lrng_drng **lrng_drng_instances(void)
-+{
-+ return smp_load_acquire(&lrng_drng);
-+}
-+
-+/* Allocate the data structures for the per-NUMA node DRNGs */
-+static void _lrng_drngs_numa_alloc(struct work_struct *work)
-+{
-+ struct lrng_drng **drngs;
-+ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+ u32 node;
-+ bool init_drng_used = false;
-+
-+ mutex_lock(&lrng_crypto_cb_update);
-+
-+ /* per-NUMA-node DRNGs are already present */
-+ if (lrng_drng)
-+ goto unlock;
-+
-+ drngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
-+ for_each_online_node(node) {
-+ struct lrng_drng *drng;
-+
-+ if (!init_drng_used) {
-+ drngs[node] = lrng_drng_init;
-+ init_drng_used = true;
-+ continue;
-+ }
-+
-+ drng = kmalloc_node(sizeof(struct lrng_drng),
-+ GFP_KERNEL|__GFP_NOFAIL, node);
-+ memset(drng, 0, sizeof(lrng_drng));
-+
-+ drng->crypto_cb = lrng_drng_init->crypto_cb;
-+ drng->drng = drng->crypto_cb->lrng_drng_alloc(
-+ LRNG_DRNG_SECURITY_STRENGTH_BYTES);
-+ if (IS_ERR(drng->drng)) {
-+ kfree(drng);
-+ goto err;
-+ }
-+
-+ drng->hash = drng->crypto_cb->lrng_hash_alloc();
-+ if (IS_ERR(drng->hash)) {
-+ drng->crypto_cb->lrng_drng_dealloc(drng->drng);
-+ kfree(drng);
-+ goto err;
-+ }
-+
-+ mutex_init(&drng->lock);
-+ spin_lock_init(&drng->spin_lock);
-+ rwlock_init(&drng->hash_lock);
-+
-+ /*
-+ * Switch the hash used by the per-CPU pool.
-+ * We do not need to lock the new hash as it is not usable yet
-+ * due to **drngs not yet being initialized.
-+ */
-+ if (lrng_pcpu_switch_hash(node, drng->crypto_cb, drng->hash,
-+ &lrng_cc20_crypto_cb))
-+ goto err;
-+
-+ /*
-+ * No reseeding of NUMA DRNGs from previous DRNGs as this
-+ * would complicate the code. Let it simply reseed.
-+ */
-+ lrng_drng_reset(drng);
-+ drngs[node] = drng;
-+
-+ lrng_pool_inc_numa_node();
-+ pr_info("DRNG and entropy pool read hash for NUMA node %d allocated\n",
-+ node);
-+ }
-+
-+ /* counterpart to smp_load_acquire in lrng_drng_instances */
-+ if (!cmpxchg_release(&lrng_drng, NULL, drngs)) {
-+ lrng_pool_all_numa_nodes_seeded(false);
-+ goto unlock;
-+ }
-+
-+err:
-+ for_each_online_node(node) {
-+ struct lrng_drng *drng = drngs[node];
-+
-+ if (drng == lrng_drng_init)
-+ continue;
-+
-+ if (drng) {
-+ lrng_pcpu_switch_hash(node, &lrng_cc20_crypto_cb, NULL,
-+ drng->crypto_cb);
-+ drng->crypto_cb->lrng_hash_dealloc(drng->hash);
-+ drng->crypto_cb->lrng_drng_dealloc(drng->drng);
-+ kfree(drng);
-+ }
-+ }
-+ kfree(drngs);
-+
-+unlock:
-+ mutex_unlock(&lrng_crypto_cb_update);
-+}
-+
-+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
-+
-+void lrng_drngs_numa_alloc(void)
-+{
-+ schedule_work(&lrng_drngs_numa_alloc_work);
-+}
-diff -urN linux-5.15/drivers/char/lrng/lrng_proc.c linux-5.15-lrng/drivers/char/lrng/lrng_proc.c
---- linux-5.15/drivers/char/lrng/lrng_proc.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_proc.c 2021-11-29 12:37:03.083279132 +1100
-@@ -0,0 +1,199 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG proc and sysctl interfaces
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#include <linux/lrng.h>
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <linux/sysctl.h>
-+#include <linux/uuid.h>
-+
-+#include "lrng_internal.h"
-+
-+/*
-+ * This function is used to return both the bootid UUID, and random
-+ * UUID. The difference is in whether table->data is NULL; if it is,
-+ * then a new UUID is generated and returned to the user.
-+ *
-+ * If the user accesses this via the proc interface, the UUID will be
-+ * returned as an ASCII string in the standard UUID format; if via the
-+ * sysctl system call, as 16 bytes of binary data.
-+ */
-+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ struct ctl_table fake_table;
-+ unsigned char buf[64], tmp_uuid[16], *uuid;
-+
-+ uuid = table->data;
-+ if (!uuid) {
-+ uuid = tmp_uuid;
-+ generate_random_uuid(uuid);
-+ } else {
-+ static DEFINE_SPINLOCK(bootid_spinlock);
-+
-+ spin_lock(&bootid_spinlock);
-+ if (!uuid[8])
-+ generate_random_uuid(uuid);
-+ spin_unlock(&bootid_spinlock);
-+ }
-+
-+ sprintf(buf, "%pU", uuid);
-+
-+ fake_table.data = buf;
-+ fake_table.maxlen = sizeof(buf);
-+
-+ return proc_dostring(&fake_table, write, buffer, lenp, ppos);
-+}
-+
-+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ struct ctl_table fake_table;
-+ int entropy_count;
-+
-+ entropy_count = lrng_avail_entropy();
-+
-+ fake_table.data = &entropy_count;
-+ fake_table.maxlen = sizeof(entropy_count);
-+
-+ return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
-+}
-+
-+static int lrng_proc_do_poolsize(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ struct ctl_table fake_table;
-+ int entropy_count;
-+
-+ /* LRNG can at most retain entropy in per-CPU pools and aux pool */
-+ entropy_count = lrng_get_digestsize() + lrng_pcpu_avail_pool_size();
-+
-+ fake_table.data = &entropy_count;
-+ fake_table.maxlen = sizeof(entropy_count);
-+
-+ return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
-+}
-+
-+static int lrng_min_write_thresh;
-+static int lrng_max_write_thresh = (LRNG_WRITE_WAKEUP_ENTROPY << 3);
-+static char lrng_sysctl_bootid[16];
-+static int lrng_drng_reseed_max_min;
-+
-+void lrng_proc_update_max_write_thresh(u32 new_digestsize)
-+{
-+ lrng_max_write_thresh = (int)new_digestsize;
-+ mb();
-+}
-+
-+struct ctl_table random_table[] = {
-+ {
-+ .procname = "poolsize",
-+ .maxlen = sizeof(int),
-+ .mode = 0444,
-+ .proc_handler = lrng_proc_do_poolsize,
-+ },
-+ {
-+ .procname = "entropy_avail",
-+ .maxlen = sizeof(int),
-+ .mode = 0444,
-+ .proc_handler = lrng_proc_do_entropy,
-+ },
-+ {
-+ .procname = "write_wakeup_threshold",
-+ .data = &lrng_write_wakeup_bits,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax,
-+ .extra1 = &lrng_min_write_thresh,
-+ .extra2 = &lrng_max_write_thresh,
-+ },
-+ {
-+ .procname = "boot_id",
-+ .data = &lrng_sysctl_bootid,
-+ .maxlen = 16,
-+ .mode = 0444,
-+ .proc_handler = lrng_proc_do_uuid,
-+ },
-+ {
-+ .procname = "uuid",
-+ .maxlen = 16,
-+ .mode = 0444,
-+ .proc_handler = lrng_proc_do_uuid,
-+ },
-+ {
-+ .procname = "urandom_min_reseed_secs",
-+ .data = &lrng_drng_reseed_max_time,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec,
-+ .extra1 = &lrng_drng_reseed_max_min,
-+ },
-+ { }
-+};
-+
-+/* Number of online DRNGs */
-+static u32 numa_drngs = 1;
-+
-+void lrng_pool_inc_numa_node(void)
-+{
-+ numa_drngs++;
-+}
-+
-+static int lrng_proc_type_show(struct seq_file *m, void *v)
-+{
-+ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+ unsigned long flags = 0;
-+ unsigned char buf[250], irq[200], aux[100], cpu[90], jent[45];
-+
-+ lrng_drng_lock(lrng_drng_init, &flags);
-+ snprintf(buf, sizeof(buf),
-+ "DRNG name: %s\n"
-+ "LRNG security strength in bits: %d\n"
-+ "number of DRNG instances: %u\n"
-+ "Standards compliance: %s\n"
-+ "Entropy Sources: %s%s%sAuxiliary\n"
-+ "LRNG minimally seeded: %s\n"
-+ "LRNG fully seeded: %s\n",
-+ lrng_drng_init->crypto_cb->lrng_drng_name(),
-+ lrng_security_strength(),
-+ numa_drngs,
-+ lrng_sp80090c_compliant() ? "SP800-90C " : "",
-+ IS_ENABLED(CONFIG_LRNG_IRQ) ? "IRQ " : "",
-+ IS_ENABLED(CONFIG_LRNG_JENT) ? "JitterRNG " : "",
-+ IS_ENABLED(CONFIG_LRNG_CPU) ? "CPU " : "",
-+ lrng_state_min_seeded() ? "true" : "false",
-+ lrng_state_fully_seeded() ? "true" : "false");
-+
-+ lrng_aux_es_state(aux, sizeof(aux));
-+
-+ irq[0] = '\0';
-+ lrng_irq_es_state(irq, sizeof(irq));
-+
-+ jent[0] = '\0';
-+ lrng_jent_es_state(jent, sizeof(jent));
-+
-+ cpu[0] = '\0';
-+ lrng_arch_es_state(cpu, sizeof(cpu));
-+
-+ lrng_drng_unlock(lrng_drng_init, &flags);
-+
-+ seq_write(m, buf, strlen(buf));
-+ seq_write(m, aux, strlen(aux));
-+ seq_write(m, irq, strlen(irq));
-+ seq_write(m, jent, strlen(jent));
-+ seq_write(m, cpu, strlen(cpu));
-+
-+ return 0;
-+}
-+
-+static int __init lrng_proc_type_init(void)
-+{
-+ proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
-+ return 0;
-+}
-+
-+module_init(lrng_proc_type_init);
-diff -urN linux-5.15/drivers/char/lrng/lrng_selftest.c linux-5.15-lrng/drivers/char/lrng/lrng_selftest.c
---- linux-5.15/drivers/char/lrng/lrng_selftest.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_selftest.c 2021-11-29 12:38:26.603278813 +1100
-@@ -0,0 +1,386 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG power-on and on-demand self-test
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+/*
-+ * In addition to the self-tests below, the following LRNG components
-+ * are covered with self-tests during regular operation:
-+ *
-+ * * power-on self-test: SP800-90A DRBG provided by the Linux kernel crypto API
-+ * * power-on self-test: PRNG provided by the Linux kernel crypto API
-+ * * runtime test: Raw noise source data testing including SP800-90B compliant
-+ * tests when enabling CONFIG_LRNG_HEALTH_TESTS
-+ *
-+ * Additional developer tests present with LRNG code:
-+ * * SP800-90B APT and RCT test enforcement validation when enabling
-+ * CONFIG_LRNG_APT_BROKEN or CONFIG_LRNG_RCT_BROKEN.
-+ * * Collection of raw entropy from the interrupt noise source when enabling
-+ * CONFIG_LRNG_TESTING and pulling the data from the kernel with the provided
-+ * interface.
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/lrng.h>
-+#include <linux/slab.h>
-+
-+#include "lrng_chacha20.h"
-+#include "lrng_internal.h"
-+
-+#define LRNG_SELFTEST_PASSED 0
-+#define LRNG_SEFLTEST_ERROR_TIME (1 << 0)
-+#define LRNG_SEFLTEST_ERROR_CHACHA20 (1 << 1)
-+#define LRNG_SEFLTEST_ERROR_HASH (1 << 2)
-+#define LRNG_SEFLTEST_ERROR_GCD (1 << 3)
-+#define LRNG_SELFTEST_NOT_EXECUTED 0xffffffff
-+
-+#ifdef CONFIG_LRNG_IRQ
-+
-+#include "lrng_es_irq.h"
-+
-+static u32 lrng_data_selftest_ptr = 0;
-+static u32 lrng_data_selftest[LRNG_DATA_ARRAY_SIZE];
-+
-+static inline void lrng_data_process_selftest_insert(u32 time)
-+{
-+ u32 ptr = lrng_data_selftest_ptr++ & LRNG_DATA_WORD_MASK;
-+ unsigned int array = lrng_data_idx2array(ptr);
-+ unsigned int slot = lrng_data_idx2slot(ptr);
-+
-+ /* zeroization of slot to ensure the following OR adds the data */
-+ lrng_data_selftest[array] &=
-+ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK,
-+ slot));
-+ lrng_data_selftest[array] |=
-+ lrng_data_slot_val(time & LRNG_DATA_SLOTSIZE_MASK, slot);
-+}
-+
-+static inline void lrng_data_process_selftest_u32(u32 data)
-+{
-+ u32 pre_ptr, ptr, mask;
-+ unsigned int pre_array;
-+
-+ /* Increment pointer by number of slots taken for input value */
-+ lrng_data_selftest_ptr += LRNG_DATA_SLOTS_PER_UINT;
-+
-+ /* ptr to current unit */
-+ ptr = lrng_data_selftest_ptr;
-+
-+ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask);
-+
-+ /* MSB of data go into previous unit */
-+ pre_array = lrng_data_idx2array(pre_ptr);
-+ /* zeroization of slot to ensure the following OR adds the data */
-+ lrng_data_selftest[pre_array] &= ~(0xffffffff & ~mask);
-+ lrng_data_selftest[pre_array] |= data & ~mask;
-+
-+ /* LSB of data go into current unit */
-+ lrng_data_selftest[lrng_data_idx2array(ptr)] = data & mask;
-+}
-+
-+static unsigned int lrng_data_process_selftest(void)
-+{
-+ u32 time;
-+ u32 idx_zero_compare = (0 << 0) | (1 << 8) | (2 << 16) | (3 << 24);
-+ u32 idx_one_compare = (4 << 0) | (5 << 8) | (6 << 16) | (7 << 24);
-+ u32 idx_last_compare =
-+ (((LRNG_DATA_NUM_VALUES - 4) & LRNG_DATA_SLOTSIZE_MASK) << 0) |
-+ (((LRNG_DATA_NUM_VALUES - 3) & LRNG_DATA_SLOTSIZE_MASK) << 8) |
-+ (((LRNG_DATA_NUM_VALUES - 2) & LRNG_DATA_SLOTSIZE_MASK) << 16) |
-+ (((LRNG_DATA_NUM_VALUES - 1) & LRNG_DATA_SLOTSIZE_MASK) << 24);
-+
-+ (void)idx_one_compare;
-+
-+ /* "poison" the array to verify the operation of the zeroization */
-+ lrng_data_selftest[0] = 0xffffffff;
-+ lrng_data_selftest[1] = 0xffffffff;
-+
-+ lrng_data_process_selftest_insert(0);
-+ /*
-+ * Note, when using lrng_data_process_u32() on unaligned ptr,
-+ * the first slots will go into next word, and the last slots go
-+ * into the previous word.
-+ */
-+ lrng_data_process_selftest_u32((4 << 0) | (1 << 8) | (2 << 16) |
-+ (3 << 24));
-+ lrng_data_process_selftest_insert(5);
-+ lrng_data_process_selftest_insert(6);
-+ lrng_data_process_selftest_insert(7);
-+
-+ if ((lrng_data_selftest[0] != idx_zero_compare) ||
-+ (lrng_data_selftest[1] != idx_one_compare))
-+ goto err;
-+
-+ /* Reset for next test */
-+ lrng_data_selftest[0] = 0;
-+ lrng_data_selftest[1] = 0;
-+ lrng_data_selftest_ptr = 0;
-+
-+ for (time = 0; time < LRNG_DATA_NUM_VALUES; time++)
-+ lrng_data_process_selftest_insert(time);
-+
-+ if ((lrng_data_selftest[0] != idx_zero_compare) ||
-+ (lrng_data_selftest[1] != idx_one_compare) ||
-+ (lrng_data_selftest[LRNG_DATA_ARRAY_SIZE - 1] != idx_last_compare))
-+ goto err;
-+
-+ return LRNG_SELFTEST_PASSED;
-+
-+err:
-+ pr_err("LRNG data array self-test FAILED\n");
-+ return LRNG_SEFLTEST_ERROR_TIME;
-+}
-+
-+static unsigned int lrng_gcd_selftest(void)
-+{
-+ u32 history[10];
-+ unsigned int i;
-+
-+#define LRNG_GCD_SELFTEST 3
-+ for (i = 0; i < ARRAY_SIZE(history); i++)
-+ history[i] = i * LRNG_GCD_SELFTEST;
-+
-+ if (lrng_gcd_analyze(history, ARRAY_SIZE(history)) == LRNG_GCD_SELFTEST)
-+ return LRNG_SELFTEST_PASSED;
-+
-+ pr_err("LRNG GCD self-test FAILED\n");
-+ return LRNG_SEFLTEST_ERROR_GCD;
-+}
-+
-+#else /* CONFIG_LRNG_IRQ */
-+
-+static unsigned int lrng_data_process_selftest(void)
-+{
-+ return LRNG_SELFTEST_PASSED;
-+}
-+
-+static unsigned int lrng_gcd_selftest(void)
-+{
-+ return LRNG_SELFTEST_PASSED;
-+}
-+
-+#endif /* CONFIG_LRNG_IRQ */
-+
-+static inline void lrng_selftest_bswap32(u32 *ptr, u32 words)
-+{
-+ u32 i;
-+
-+ /* Byte-swap data which is an LE representation */
-+ for (i = 0; i < words; i++) {
-+ __le32 *p = (__le32 *)ptr;
-+
-+ *p = cpu_to_le32(*ptr);
-+ ptr++;
-+ }
-+}
-+
-+/* The test vectors are taken from crypto/testmgr.h */
-+static unsigned int lrng_hash_selftest(void)
-+{
-+ SHASH_DESC_ON_STACK(shash, NULL);
-+ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
-+ static const u8 lrng_hash_selftest_result[] =
-+#ifdef CONFIG_CRYPTO_LIB_SHA256
-+ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
-+ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
-+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
-+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad };
-+#else /* CONFIG_CRYPTO_LIB_SHA256 */
-+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
-+ 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d };
-+#endif /* CONFIG_CRYPTO_LIB_SHA256 */
-+ static const u8 hash_input[] = { 0x61, 0x62, 0x63 }; /* "abc" */
-+ u8 digest[sizeof(lrng_hash_selftest_result)] __aligned(sizeof(u32));
-+
-+ BUG_ON(sizeof(digest) != crypto_cb->lrng_hash_digestsize(NULL));
-+
-+ if (!crypto_cb->lrng_hash_init(shash, NULL) &&
-+ !crypto_cb->lrng_hash_update(shash, hash_input,
-+ sizeof(hash_input)) &&
-+ !crypto_cb->lrng_hash_final(shash, digest) &&
-+ !memcmp(digest, lrng_hash_selftest_result, sizeof(digest)))
-+ return 0;
-+
-+ pr_err("LRNG %s Hash self-test FAILED\n", crypto_cb->lrng_hash_name());
-+ return LRNG_SEFLTEST_ERROR_HASH;
-+}
-+
-+/*
-+ * The test vectors were generated using the ChaCha20 DRNG from
-+ * https://www.chronox.de/chacha20.html
-+ */
-+static unsigned int lrng_chacha20_drng_selftest(void)
-+{
-+ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
-+ u8 seed[CHACHA_KEY_SIZE * 2] = {
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-+ };
-+ struct chacha20_block chacha20;
-+ int ret;
-+ u8 outbuf[CHACHA_KEY_SIZE * 2] __aligned(sizeof(u32));
-+
-+ /*
-+ * Expected result when ChaCha20 DRNG state is zero:
-+ * * constants are set to "expand 32-byte k"
-+ * * remaining state is 0
-+ * and pulling one half ChaCha20 DRNG block.
-+ */
-+ static const u8 expected_halfblock[CHACHA_KEY_SIZE] = {
-+ 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
-+ 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
-+ 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
-+ 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7 };
-+
-+ /*
-+ * Expected result when ChaCha20 DRNG state is zero:
-+ * * constants are set to "expand 32-byte k"
-+ * * remaining state is 0
-+ * followed by a reseed with two keyblocks
-+ * 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ * 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+ * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+ * 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+ * 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+ * 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-+ * 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+ * 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
-+ * and pulling one ChaCha20 DRNG block.
-+ */
-+ static const u8 expected_oneblock[CHACHA_KEY_SIZE * 2] = {
-+ 0xe3, 0xb0, 0x8a, 0xcc, 0x34, 0xc3, 0x17, 0x0e,
-+ 0xc3, 0xd8, 0xc3, 0x40, 0xe7, 0x73, 0xe9, 0x0d,
-+ 0xd1, 0x62, 0xa3, 0x5d, 0x7d, 0xf2, 0xf1, 0x4a,
-+ 0x24, 0x42, 0xb7, 0x1e, 0xb0, 0x05, 0x17, 0x07,
-+ 0xb9, 0x35, 0x10, 0x69, 0x8b, 0x46, 0xfb, 0x51,
-+ 0xe9, 0x91, 0x3f, 0x46, 0xf2, 0x4d, 0xea, 0xd0,
-+ 0x81, 0xc1, 0x1b, 0xa9, 0x5d, 0x52, 0x91, 0x5f,
-+ 0xcd, 0xdc, 0xc6, 0xd6, 0xc3, 0x7c, 0x50, 0x23 };
-+
-+ /*
-+ * Expected result when ChaCha20 DRNG state is zero:
-+ * * constants are set to "expand 32-byte k"
-+ * * remaining state is 0
-+ * followed by a reseed with one key block plus one byte
-+ * 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ * 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+ * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+ * 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+ * 0x20
-+ * and pulling less than one ChaCha20 DRNG block.
-+ */
-+ static const u8 expected_block_nonalinged[CHACHA_KEY_SIZE + 4] = {
-+ 0x9c, 0xfc, 0x5e, 0x31, 0x21, 0x62, 0x11, 0x85,
-+ 0xd3, 0x77, 0xd3, 0x69, 0x0f, 0xa8, 0x16, 0x55,
-+ 0xb4, 0x4c, 0xf6, 0x52, 0xf3, 0xa8, 0x37, 0x99,
-+ 0x38, 0x76, 0xa0, 0x66, 0xec, 0xbb, 0xce, 0xa9,
-+ 0x9c, 0x95, 0xa1, 0xfd };
-+
-+ BUILD_BUG_ON(sizeof(seed) % sizeof(u32));
-+
-+ memset(&chacha20, 0, sizeof(chacha20));
-+ lrng_cc20_init_rfc7539(&chacha20);
-+ lrng_selftest_bswap32((u32 *)seed, sizeof(seed) / sizeof(u32));
-+
-+ /* Generate with zero state */
-+ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
-+ sizeof(expected_halfblock));
-+ if (ret != sizeof(expected_halfblock))
-+ goto err;
-+ if (memcmp(outbuf, expected_halfblock, sizeof(expected_halfblock)))
-+ goto err;
-+
-+ /* Clear state of DRNG */
-+ memset(&chacha20.key.u[0], 0, 48);
-+
-+ /* Reseed with 2 key blocks */
-+ ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
-+ sizeof(expected_oneblock));
-+ if (ret < 0)
-+ goto err;
-+ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
-+ sizeof(expected_oneblock));
-+ if (ret != sizeof(expected_oneblock))
-+ goto err;
-+ if (memcmp(outbuf, expected_oneblock, sizeof(expected_oneblock)))
-+ goto err;
-+
-+ /* Clear state of DRNG */
-+ memset(&chacha20.key.u[0], 0, 48);
-+
-+ /* Reseed with 1 key block and one byte */
-+ ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
-+ sizeof(expected_block_nonalinged));
-+ if (ret < 0)
-+ goto err;
-+ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
-+ sizeof(expected_block_nonalinged));
-+ if (ret != sizeof(expected_block_nonalinged))
-+ goto err;
-+ if (memcmp(outbuf, expected_block_nonalinged,
-+ sizeof(expected_block_nonalinged)))
-+ goto err;
-+
-+ return LRNG_SELFTEST_PASSED;
-+
-+err:
-+ pr_err("LRNG ChaCha20 DRNG self-test FAILED\n");
-+ return LRNG_SEFLTEST_ERROR_CHACHA20;
-+}
-+
-+static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED;
-+
-+static int lrng_selftest(void)
-+{
-+ unsigned int ret = lrng_data_process_selftest();
-+
-+ ret |= lrng_chacha20_drng_selftest();
-+ ret |= lrng_hash_selftest();
-+ ret |= lrng_gcd_selftest();
-+
-+ if (ret) {
-+ if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC))
-+ panic("LRNG self-tests failed: %u\n", ret);
-+ } else {
-+ pr_info("LRNG self-tests passed\n");
-+ }
-+
-+ lrng_selftest_status = ret;
-+
-+ if (lrng_selftest_status)
-+ return -EFAULT;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SYSFS
-+/* Re-perform self-test when any value is written to the sysfs file. */
-+static int lrng_selftest_sysfs_set(const char *val,
-+ const struct kernel_param *kp)
-+{
-+ return lrng_selftest();
-+}
-+
-+static const struct kernel_param_ops lrng_selftest_sysfs = {
-+ .set = lrng_selftest_sysfs_set,
-+ .get = param_get_uint,
-+};
-+module_param_cb(selftest_status, &lrng_selftest_sysfs, &lrng_selftest_status,
-+ 0644);
-+#endif /* CONFIG_SYSFS */
-+
-+static int __init lrng_selftest_init(void)
-+{
-+ return lrng_selftest();
-+}
-+
-+module_init(lrng_selftest_init);
-diff -urN linux-5.15/drivers/char/lrng/lrng_switch.c linux-5.15-lrng/drivers/char/lrng/lrng_switch.c
---- linux-5.15/drivers/char/lrng/lrng_switch.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_switch.c 2021-11-29 12:37:19.323279070 +1100
-@@ -0,0 +1,226 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * LRNG DRNG switching support
-+ *
-+ * Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/lrng.h>
-+
-+#include "lrng_internal.h"
-+
-+static int lrng_drng_switch(struct lrng_drng *drng_store,
-+ const struct lrng_crypto_cb *cb, int node)
-+{
-+ const struct lrng_crypto_cb *old_cb;
-+ unsigned long flags = 0, flags2 = 0;
-+ int ret;
-+ u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
-+ void *new_drng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
-+ void *old_drng, *new_hash, *old_hash;
-+ u32 current_security_strength;
-+ bool sl = false, reset_drng = !lrng_get_available();
-+
-+ if (IS_ERR(new_drng)) {
-+ pr_warn("could not allocate new DRNG for NUMA node %d (%ld)\n",
-+ node, PTR_ERR(new_drng));
-+ return PTR_ERR(new_drng);
-+ }
-+
-+ new_hash = cb->lrng_hash_alloc();
-+ if (IS_ERR(new_hash)) {
-+ pr_warn("could not allocate new LRNG pool hash (%ld)\n",
-+ PTR_ERR(new_hash));
-+ cb->lrng_drng_dealloc(new_drng);
-+ return PTR_ERR(new_hash);
-+ }
-+
-+ if (cb->lrng_hash_digestsize(new_hash) > LRNG_MAX_DIGESTSIZE) {
-+ pr_warn("digest size of newly requested hash too large\n");
-+ cb->lrng_hash_dealloc(new_hash);
-+ cb->lrng_drng_dealloc(new_drng);
-+ return -EINVAL;
-+ }
-+
-+ current_security_strength = lrng_security_strength();
-+ lrng_drng_lock(drng_store, &flags);
-+
-+ /*
-+ * Pull from existing DRNG to seed new DRNG regardless of seed status
-+ * of old DRNG -- the entropy state for the DRNG is left unchanged which
-+ * implies that als the new DRNG is reseeded when deemed necessary. This
-+ * seeding of the new DRNG shall only ensure that the new DRNG has the
-+ * same entropy as the old DRNG.
-+ */
-+ ret = drng_store->crypto_cb->lrng_drng_generate_helper(
-+ drng_store->drng, seed, sizeof(seed));
-+ lrng_drng_unlock(drng_store, &flags);
-+
-+ if (ret < 0) {
-+ reset_drng = true;
-+ pr_warn("getting random data from DRNG failed for NUMA node %d (%d)\n",
-+ node, ret);
-+ } else {
-+ /* seed new DRNG with data */
-+ ret = cb->lrng_drng_seed_helper(new_drng, seed, ret);
-+ memzero_explicit(seed, sizeof(seed));
-+ if (ret < 0) {
-+ reset_drng = true;
-+ pr_warn("seeding of new DRNG failed for NUMA node %d (%d)\n",
-+ node, ret);
-+ } else {
-+ pr_debug("seeded new DRNG of NUMA node %d instance from old DRNG instance\n",
-+ node);
-+ }
-+ }
-+
-+ mutex_lock(&drng_store->lock);
-+ write_lock_irqsave(&drng_store->hash_lock, flags2);
-+ /*
-+ * If we switch the DRNG from the initial ChaCha20 DRNG to something
-+ * else, there is a lock transition from spin lock to mutex (see
-+ * lrng_drng_is_atomic and how the lock is taken in lrng_drng_lock).
-+ * Thus, we need to take both locks during the transition phase.
-+ */
-+ if (lrng_drng_is_atomic(drng_store)) {
-+ spin_lock_irqsave(&drng_store->spin_lock, flags);
-+ sl = true;
-+ } else {
-+ __acquire(&drng_store->spin_lock);
-+ }
-+
-+ /* Trigger the switch of the aux entropy pool for current node. */
-+ if (drng_store == lrng_drng_init_instance()) {
-+ ret = lrng_aux_switch_hash(cb, new_hash, drng_store->crypto_cb);
-+ if (ret)
-+ goto err;
-+ }
-+
-+ /* Trigger the switch of the per-CPU entropy pools for current node. */
-+ ret = lrng_pcpu_switch_hash(node, cb, new_hash, drng_store->crypto_cb);
-+ if (ret) {
-+ /* Switch the crypto operation back to be consistent */
-+ WARN_ON(lrng_aux_switch_hash(drng_store->crypto_cb,
-+ drng_store->hash, cb));
-+ } else {
-+ if (reset_drng)
-+ lrng_drng_reset(drng_store);
-+
-+ old_drng = drng_store->drng;
-+ old_cb = drng_store->crypto_cb;
-+ drng_store->drng = new_drng;
-+ drng_store->crypto_cb = cb;
-+
-+ old_hash = drng_store->hash;
-+ drng_store->hash = new_hash;
-+ pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n",
-+ node);
-+
-+ /* Reseed if previous LRNG security strength was insufficient */
-+ if (current_security_strength < lrng_security_strength())
-+ drng_store->force_reseed = true;
-+
-+ /* Force oversampling seeding as we initialize DRNG */
-+ if (IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES))
-+ lrng_unset_fully_seeded(drng_store);
-+
-+ if (lrng_state_min_seeded())
-+ lrng_set_entropy_thresh(lrng_get_seed_entropy_osr(
-+ drng_store->fully_seeded));
-+
-+ /* ChaCha20 serves as atomic instance left untouched. */
-+ if (old_drng != &chacha20) {
-+ old_cb->lrng_drng_dealloc(old_drng);
-+ old_cb->lrng_hash_dealloc(old_hash);
-+ }
-+
-+ pr_info("DRNG of NUMA node %d switched\n", node);
-+ }
-+
-+err:
-+ if (sl)
-+ spin_unlock_irqrestore(&drng_store->spin_lock, flags);
-+ else
-+ __release(&drng_store->spin_lock);
-+ write_unlock_irqrestore(&drng_store->hash_lock, flags2);
-+ mutex_unlock(&drng_store->lock);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Switch the existing DRNG instances with new using the new crypto callbacks.
-+ * The caller must hold the lrng_crypto_cb_update lock.
-+ */
-+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
-+{
-+ struct lrng_drng **lrng_drng = lrng_drng_instances();
-+ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+ int ret = 0;
-+
-+ /* Update DRNG */
-+ if (lrng_drng) {
-+ u32 node;
-+
-+ for_each_online_node(node) {
-+ if (lrng_drng[node])
-+ ret = lrng_drng_switch(lrng_drng[node], cb,
-+ node);
-+ }
-+ } else {
-+ ret = lrng_drng_switch(lrng_drng_init, cb, 0);
-+ }
-+
-+ if (!ret)
-+ lrng_set_available();
-+
-+ return 0;
-+}
-+
-+/*
-+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
-+ * The registering implies that all old DRNG states are replaced with new
-+ * DRNG states.
-+ *
-+ * @cb: Callback functions to be registered -- if NULL, use the default
-+ * callbacks pointing to the ChaCha20 DRNG.
-+ *
-+ * Return:
-+ * * 0 on success
-+ * * < 0 on error
-+ */
-+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
-+{
-+ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
-+ int ret;
-+
-+ if (!cb)
-+ cb = &lrng_cc20_crypto_cb;
-+
-+ mutex_lock(&lrng_crypto_cb_update);
-+
-+ /*
-+ * If a callback other than the default is set, allow it only to be
-+ * set back to the default callback. This ensures that multiple
-+ * different callbacks can be registered at the same time. If a
-+ * callback different from the current callback and the default
-+ * callback shall be set, the current callback must be deregistered
-+ * (e.g. the kernel module providing it must be unloaded) and the new
-+ * implementation can be registered.
-+ */
-+ if ((cb != &lrng_cc20_crypto_cb) &&
-+ (lrng_drng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
-+ pr_warn("disallow setting new cipher callbacks, unload the old callbacks first!\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ ret = lrng_drngs_switch(cb);
-+
-+out:
-+ mutex_unlock(&lrng_crypto_cb_update);
-+ return ret;
-+}
-+EXPORT_SYMBOL(lrng_set_drng_cb);
-diff -urN linux-5.15/drivers/char/lrng/lrng_testing.c linux-5.15-lrng/drivers/char/lrng/lrng_testing.c
---- linux-5.15/drivers/char/lrng/lrng_testing.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/drivers/char/lrng/lrng_testing.c 2021-11-29 12:38:19.263278841 +1100
-@@ -0,0 +1,689 @@
-+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
-+/*
-+ * Linux Random Number Generator (LRNG) testing interfaces
-+ *
-+ * Copyright (C) 2019 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/atomic.h>
-+#include <linux/bug.h>
-+#include <linux/debugfs.h>
-+#include <linux/lrng.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/sched/signal.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/uaccess.h>
-+#include <linux/workqueue.h>
-+#include <asm/errno.h>
-+
-+#include "lrng_internal.h"
-+
-+#define LRNG_TESTING_RINGBUFFER_SIZE 1024
-+#define LRNG_TESTING_RINGBUFFER_MASK (LRNG_TESTING_RINGBUFFER_SIZE - 1)
-+
-+struct lrng_testing {
-+ u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
-+ u32 rb_reader;
-+ u32 rb_writer;
-+ atomic_t lrng_testing_enabled;
-+ spinlock_t lock;
-+ wait_queue_head_t read_wait;
-+};
-+
-+/*************************** Generic Data Handling ****************************/
-+
-+/*
-+ * boot variable:
-+ * 0 ==> No boot test, gathering of runtime data allowed
-+ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
-+ * data is disabled
-+ * 2 ==> Boot test completed and disabled, gathering of runtime data is
-+ * disabled
-+ */
-+
-+static inline void lrng_testing_reset(struct lrng_testing *data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&data->lock, flags);
-+ data->rb_reader = 0;
-+ data->rb_writer = 0;
-+ spin_unlock_irqrestore(&data->lock, flags);
-+}
-+
-+static inline void lrng_testing_init(struct lrng_testing *data, u32 boot)
-+{
-+ /*
-+ * The boot time testing implies we have a running test. If the
-+ * caller wants to clear it, he has to unset the boot_test flag
-+ * at runtime via sysfs to enable regular runtime testing
-+ */
-+ if (boot)
-+ return;
-+
-+ lrng_testing_reset(data);
-+ atomic_set(&data->lrng_testing_enabled, 1);
-+ pr_warn("Enabling data collection\n");
-+}
-+
-+static inline void lrng_testing_fini(struct lrng_testing *data, u32 boot)
-+{
-+ /* If we have boot data, we do not reset yet to allow data to be read */
-+ if (boot)
-+ return;
-+
-+ atomic_set(&data->lrng_testing_enabled, 0);
-+ lrng_testing_reset(data);
-+ pr_warn("Disabling data collection\n");
-+}
-+
-+static inline bool lrng_testing_store(struct lrng_testing *data, u32 value,
-+ u32 *boot)
-+{
-+ unsigned long flags;
-+
-+ if (!atomic_read(&data->lrng_testing_enabled) && (*boot != 1))
-+ return false;
-+
-+ spin_lock_irqsave(&data->lock, flags);
-+
-+ /*
-+ * Disable entropy testing for boot time testing after ring buffer
-+ * is filled.
-+ */
-+ if (*boot) {
-+ if (data->rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) {
-+ *boot = 2;
-+ pr_warn_once("One time data collection test disabled\n");
-+ spin_unlock_irqrestore(&data->lock, flags);
-+ return false;
-+ }
-+
-+ if (data->rb_writer == 1)
-+ pr_warn("One time data collection test enabled\n");
-+ }
-+
-+ data->lrng_testing_rb[data->rb_writer & LRNG_TESTING_RINGBUFFER_MASK] =
-+ value;
-+ data->rb_writer++;
-+
-+ spin_unlock_irqrestore(&data->lock, flags);
-+
-+ if (wq_has_sleeper(&data->read_wait))
-+ wake_up_interruptible(&data->read_wait);
-+
-+ return true;
-+}
-+
-+static inline bool lrng_testing_have_data(struct lrng_testing *data)
-+{
-+ return ((data->rb_writer & LRNG_TESTING_RINGBUFFER_MASK) !=
-+ (data->rb_reader & LRNG_TESTING_RINGBUFFER_MASK));
-+}
-+
-+static inline int lrng_testing_reader(struct lrng_testing *data, u32 *boot,
-+ u8 *outbuf, u32 outbuflen)
-+{
-+ unsigned long flags;
-+ int collected_data = 0;
-+
-+ lrng_testing_init(data, *boot);
-+
-+ while (outbuflen) {
-+ spin_lock_irqsave(&data->lock, flags);
-+
-+ /* We have no data or reached the writer. */
-+ if (!data->rb_writer ||
-+ (data->rb_writer == data->rb_reader)) {
-+
-+ spin_unlock_irqrestore(&data->lock, flags);
-+
-+ /*
-+ * Now we gathered all boot data, enable regular data
-+ * collection.
-+ */
-+ if (*boot) {
-+ *boot = 0;
-+ goto out;
-+ }
-+
-+ wait_event_interruptible(data->read_wait,
-+ lrng_testing_have_data(data));
-+ if (signal_pending(current)) {
-+ collected_data = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ continue;
-+ }
-+
-+ /* We copy out word-wise */
-+ if (outbuflen < sizeof(u32)) {
-+ spin_unlock_irqrestore(&data->lock, flags);
-+ goto out;
-+ }
-+
-+ memcpy(outbuf, &data->lrng_testing_rb[data->rb_reader],
-+ sizeof(u32));
-+ data->rb_reader++;
-+
-+ spin_unlock_irqrestore(&data->lock, flags);
-+
-+ outbuf += sizeof(u32);
-+ outbuflen -= sizeof(u32);
-+ collected_data += sizeof(u32);
-+ }
-+
-+out:
-+ lrng_testing_fini(data, *boot);
-+ return collected_data;
-+}
-+
-+static int lrng_testing_extract_user(struct file *file, char __user *buf,
-+ size_t nbytes, loff_t *ppos,
-+ int (*reader)(u8 *outbuf, u32 outbuflen))
-+{
-+ u8 *tmp, *tmp_aligned;
-+ int ret = 0, large_request = (nbytes > 256);
-+
-+ if (!nbytes)
-+ return 0;
-+
-+ /*
-+ * The intention of this interface is for collecting at least
-+ * 1000 samples due to the SP800-90B requirements. So, we make no
-+ * effort in avoiding allocating more memory that actually needed
-+ * by the user. Hence, we allocate sufficient memory to always hold
-+ * that amount of data.
-+ */
-+ tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
-+ if (!tmp)
-+ return -ENOMEM;
-+
-+ tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
-+
-+ while (nbytes) {
-+ int i;
-+
-+ if (large_request && need_resched()) {
-+ if (signal_pending(current)) {
-+ if (ret == 0)
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+
-+ i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
-+ i = reader(tmp_aligned, i);
-+ if (i <= 0) {
-+ if (i < 0)
-+ ret = i;
-+ break;
-+ }
-+ if (copy_to_user(buf, tmp_aligned, i)) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ nbytes -= i;
-+ buf += i;
-+ ret += i;
-+ }
-+
-+ kfree_sensitive(tmp);
-+
-+ if (ret > 0)
-+ *ppos += ret;
-+
-+ return ret;
-+}
-+
-+/************** Raw High-Resolution Timer Entropy Data Handling ***************/
-+
-+#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY
-+
-+static u32 boot_raw_hires_test = 0;
-+module_param(boot_raw_hires_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_hires_test, "Enable gathering boot time high resolution timer entropy of the first entropy events");
-+
-+static struct lrng_testing lrng_raw_hires = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_hires.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_hires.read_wait)
-+};
-+
-+bool lrng_raw_hires_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_hires, value, &boot_raw_hires_test);
-+}
-+
-+static int lrng_raw_hires_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_hires, &boot_raw_hires_test,
-+ outbuf, outbuflen);
-+}
-+
-+static ssize_t lrng_raw_hires_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_hires_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_hires_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_hires_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */
-+
-+/********************* Raw Jiffies Entropy Data Handling **********************/
-+
-+#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY
-+
-+static u32 boot_raw_jiffies_test = 0;
-+module_param(boot_raw_jiffies_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_jiffies_test, "Enable gathering boot time high resolution timer entropy of the first entropy events");
-+
-+static struct lrng_testing lrng_raw_jiffies = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_jiffies.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_jiffies.read_wait)
-+};
-+
-+bool lrng_raw_jiffies_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_jiffies, value,
-+ &boot_raw_jiffies_test);
-+}
-+
-+static int lrng_raw_jiffies_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_jiffies, &boot_raw_jiffies_test,
-+ outbuf, outbuflen);
-+}
-+
-+static ssize_t lrng_raw_jiffies_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_jiffies_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_jiffies_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_jiffies_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */
-+
-+/************************** Raw IRQ Data Handling ****************************/
-+
-+#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY
-+
-+static u32 boot_raw_irq_test = 0;
-+module_param(boot_raw_irq_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_irq_test, "Enable gathering boot time entropy of the first IRQ entropy events");
-+
-+static struct lrng_testing lrng_raw_irq = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_irq.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_irq.read_wait)
-+};
-+
-+bool lrng_raw_irq_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_irq, value, &boot_raw_irq_test);
-+}
-+
-+static int lrng_raw_irq_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_irq, &boot_raw_irq_test, outbuf,
-+ outbuflen);
-+}
-+
-+static ssize_t lrng_raw_irq_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_irq_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_irq_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_irq_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */
-+
-+/************************ Raw IRQFLAGS Data Handling **************************/
-+
-+#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY
-+
-+static u32 boot_raw_irqflags_test = 0;
-+module_param(boot_raw_irqflags_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_irqflags_test, "Enable gathering boot time entropy of the first IRQ flags entropy events");
-+
-+static struct lrng_testing lrng_raw_irqflags = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_irqflags.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_irqflags.read_wait)
-+};
-+
-+bool lrng_raw_irqflags_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_irqflags, value,
-+ &boot_raw_irqflags_test);
-+}
-+
-+static int lrng_raw_irqflags_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_irqflags, &boot_raw_irqflags_test,
-+ outbuf, outbuflen);
-+}
-+
-+static ssize_t lrng_raw_irqflags_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_irqflags_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_irqflags_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_irqflags_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */
-+
-+/************************ Raw _RET_IP_ Data Handling **************************/
-+
-+#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY
-+
-+static u32 boot_raw_retip_test = 0;
-+module_param(boot_raw_retip_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_retip_test, "Enable gathering boot time entropy of the first return instruction pointer entropy events");
-+
-+static struct lrng_testing lrng_raw_retip = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_retip.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_retip.read_wait)
-+};
-+
-+bool lrng_raw_retip_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_retip, value, &boot_raw_retip_test);
-+}
-+
-+static int lrng_raw_retip_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_retip, &boot_raw_retip_test,
-+ outbuf, outbuflen);
-+}
-+
-+static ssize_t lrng_raw_retip_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_retip_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_retip_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_retip_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */
-+
-+/********************** Raw IRQ register Data Handling ************************/
-+
-+#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY
-+
-+static u32 boot_raw_regs_test = 0;
-+module_param(boot_raw_regs_test, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_regs_test, "Enable gathering boot time entropy of the first interrupt register entropy events");
-+
-+static struct lrng_testing lrng_raw_regs = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_regs.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_regs.read_wait)
-+};
-+
-+bool lrng_raw_regs_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_regs, value, &boot_raw_regs_test);
-+}
-+
-+static int lrng_raw_regs_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_regs, &boot_raw_regs_test,
-+ outbuf, outbuflen);
-+}
-+
-+static ssize_t lrng_raw_regs_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_regs_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_regs_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_regs_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */
-+
-+/********************** Raw Entropy Array Data Handling ***********************/
-+
-+#ifdef CONFIG_LRNG_RAW_ARRAY
-+
-+static u32 boot_raw_array = 0;
-+module_param(boot_raw_array, uint, 0644);
-+MODULE_PARM_DESC(boot_raw_array, "Enable gathering boot time raw noise array data of the first entropy events");
-+
-+static struct lrng_testing lrng_raw_array = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_array.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_array.read_wait)
-+};
-+
-+bool lrng_raw_array_entropy_store(u32 value)
-+{
-+ return lrng_testing_store(&lrng_raw_array, value, &boot_raw_array);
-+}
-+
-+static int lrng_raw_array_entropy_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_raw_array, &boot_raw_array, outbuf,
-+ outbuflen);
-+}
-+
-+static ssize_t lrng_raw_array_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_raw_array_entropy_reader);
-+}
-+
-+static const struct file_operations lrng_raw_array_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_raw_array_read,
-+};
-+
-+#endif /* CONFIG_LRNG_RAW_ARRAY */
-+
-+/******************** Interrupt Performance Data Handling *********************/
-+
-+#ifdef CONFIG_LRNG_IRQ_PERF
-+
-+static u32 boot_irq_perf = 0;
-+module_param(boot_irq_perf, uint, 0644);
-+MODULE_PARM_DESC(boot_irq_perf, "Enable gathering boot time interrupt performance data of the first entropy events");
-+
-+static struct lrng_testing lrng_irq_perf = {
-+ .rb_reader = 0,
-+ .rb_writer = 0,
-+ .lock = __SPIN_LOCK_UNLOCKED(lrng_irq_perf.lock),
-+ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_irq_perf.read_wait)
-+};
-+
-+bool lrng_perf_time(u32 start)
-+{
-+ return lrng_testing_store(&lrng_irq_perf, random_get_entropy() - start,
-+ &boot_irq_perf);
-+}
-+
-+static int lrng_irq_perf_reader(u8 *outbuf, u32 outbuflen)
-+{
-+ return lrng_testing_reader(&lrng_irq_perf, &boot_irq_perf, outbuf,
-+ outbuflen);
-+}
-+
-+static ssize_t lrng_irq_perf_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ return lrng_testing_extract_user(file, to, count, ppos,
-+ lrng_irq_perf_reader);
-+}
-+
-+static const struct file_operations lrng_irq_perf_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lrng_irq_perf_read,
-+};
-+
-+#endif /* CONFIG_LRNG_IRQ_PERF */
-+
-+/*********************************** ACVT ************************************/
-+
-+#ifdef CONFIG_LRNG_ACVT_HASH
-+
-+/* maximum amount of data to be hashed as defined by ACVP */
-+#define LRNG_ACVT_MAX_SHA_MSG (65536 >> 3)
-+
-+/*
-+ * As we use static variables to store the data, it is clear that the
-+ * test interface is only able to handle single threaded testing. This is
-+ * considered to be sufficient for testing. If multi-threaded use of the
-+ * ACVT test interface would be performed, the caller would get garbage
-+ * but the kernel operation is unaffected by this.
-+ */
-+static u8 lrng_acvt_hash_data[LRNG_ACVT_MAX_SHA_MSG]
-+ __aligned(LRNG_KCAPI_ALIGN);
-+static atomic_t lrng_acvt_hash_data_size = ATOMIC_INIT(0);
-+static u8 lrng_acvt_hash_digest[LRNG_ATOMIC_DIGEST_SIZE];
-+
-+static ssize_t lrng_acvt_hash_write(struct file *file, const char __user *buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ if (nbytes > LRNG_ACVT_MAX_SHA_MSG)
-+ return -EINVAL;
-+
-+ atomic_set(&lrng_acvt_hash_data_size, (int)nbytes);
-+
-+ return simple_write_to_buffer(lrng_acvt_hash_data,
-+ LRNG_ACVT_MAX_SHA_MSG, ppos, buf, nbytes);
-+}
-+
-+static ssize_t lrng_acvt_hash_read(struct file *file, char __user *to,
-+ size_t count, loff_t *ppos)
-+{
-+ SHASH_DESC_ON_STACK(shash, NULL);
-+ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
-+ ssize_t ret;
-+
-+ if (count > LRNG_ATOMIC_DIGEST_SIZE)
-+ return -EINVAL;
-+
-+ ret = crypto_cb->lrng_hash_init(shash, NULL) ?:
-+ crypto_cb->lrng_hash_update(shash, lrng_acvt_hash_data,
-+ atomic_read_u32(&lrng_acvt_hash_data_size)) ?:
-+ crypto_cb->lrng_hash_final(shash, lrng_acvt_hash_digest);
-+ if (ret)
-+ return ret;
-+
-+ return simple_read_from_buffer(to, count, ppos, lrng_acvt_hash_digest,
-+ sizeof(lrng_acvt_hash_digest));
-+}
-+
-+static const struct file_operations lrng_acvt_hash_fops = {
-+ .owner = THIS_MODULE,
-+ .open = simple_open,
-+ .llseek = default_llseek,
-+ .read = lrng_acvt_hash_read,
-+ .write = lrng_acvt_hash_write,
-+};
-+
-+#endif /* CONFIG_LRNG_ACVT_DRNG */
-+
-+/**************************************************************************
-+ * Debugfs interface
-+ **************************************************************************/
-+
-+static int __init lrng_raw_init(void)
-+{
-+ struct dentry *lrng_raw_debugfs_root;
-+
-+ lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-+
-+#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_hires", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_hires_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_jiffies", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_jiffies_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_irq", 0400, lrng_raw_debugfs_root,
-+ NULL, &lrng_raw_irq_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_irqflags", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_irqflags_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_retip", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_retip_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY
-+ debugfs_create_file_unsafe("lrng_raw_regs", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_regs_fops);
-+#endif
-+#ifdef CONFIG_LRNG_RAW_ARRAY
-+ debugfs_create_file_unsafe("lrng_raw_array", 0400,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_raw_array_fops);
-+#endif
-+#ifdef CONFIG_LRNG_IRQ_PERF
-+ debugfs_create_file_unsafe("lrng_irq_perf", 0400, lrng_raw_debugfs_root,
-+ NULL, &lrng_irq_perf_fops);
-+#endif
-+#ifdef CONFIG_LRNG_ACVT_HASH
-+ debugfs_create_file_unsafe("lrng_acvt_hash", 0600,
-+ lrng_raw_debugfs_root, NULL,
-+ &lrng_acvt_hash_fops);
-+#endif
-+
-+ return 0;
-+}
-+
-+module_init(lrng_raw_init);
-diff -urN linux-5.15/include/crypto/drbg.h linux-5.15-lrng/include/crypto/drbg.h
---- linux-5.15/include/crypto/drbg.h 2021-11-01 07:53:10.000000000 +1100
-+++ linux-5.15-lrng/include/crypto/drbg.h 2021-11-29 12:37:31.183279025 +1100
-@@ -278,4 +278,11 @@
- DRBG_PREFIX3
- };
-
-+extern int drbg_alloc_state(struct drbg_state *drbg);
-+extern void drbg_dealloc_state(struct drbg_state *drbg);
-+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
-+ bool *pr);
-+extern const struct drbg_core drbg_cores[];
-+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
-+
- #endif /* _DRBG_H */
-diff -urN linux-5.15/include/crypto/internal/jitterentropy.h linux-5.15-lrng/include/crypto/internal/jitterentropy.h
---- linux-5.15/include/crypto/internal/jitterentropy.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/include/crypto/internal/jitterentropy.h 2021-11-29 12:37:52.903278942 +1100
-@@ -0,0 +1,17 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+
-+extern void *jent_zalloc(unsigned int len);
-+extern void jent_zfree(void *ptr);
-+extern int jent_fips_enabled(void);
-+extern void jent_panic(char *s);
-+extern void jent_memcpy(void *dest, const void *src, unsigned int n);
-+extern void jent_get_nstime(__u64 *out);
-+
-+struct rand_data;
-+extern int jent_entropy_init(void);
-+extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
-+ unsigned int len);
-+
-+extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
-+ unsigned int flags);
-+extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
-diff -urN linux-5.15/include/linux/lrng.h linux-5.15-lrng/include/linux/lrng.h
---- linux-5.15/include/linux/lrng.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-5.15-lrng/include/linux/lrng.h 2021-11-29 12:36:52.113279174 +1100
-@@ -0,0 +1,81 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
-+/*
-+ * Copyright (C) 2018 - 2021, Stephan Mueller <smueller@chronox.de>
-+ */
-+
-+#ifndef _LRNG_H
-+#define _LRNG_H
-+
-+#include <crypto/hash.h>
-+#include <linux/errno.h>
-+#include <linux/types.h>
-+
-+/*
-+ * struct lrng_crypto_cb - cryptographic callback functions
-+ * @lrng_drng_name Name of DRNG
-+ * @lrng_hash_name Name of Hash used for reading entropy pool
-+ * @lrng_drng_alloc: Allocate DRNG -- the provided integer should be
-+ * used for sanity checks.
-+ * return: allocated data structure or PTR_ERR on
-+ * error
-+ * @lrng_drng_dealloc: Deallocate DRNG
-+ * @lrng_drng_seed_helper: Seed the DRNG with data of arbitrary length
-+ * drng: is pointer to data structure allocated
-+ * with lrng_drng_alloc
-+ * return: >= 0 on success, < 0 on error
-+ * @lrng_drng_generate_helper: Generate random numbers from the DRNG with
-+ * arbitrary length
-+ * @lrng_hash_alloc: Allocate the hash for reading the entropy pool
-+ * return: allocated data structure (NULL is
-+ * success too) or ERR_PTR on error
-+ * @lrng_hash_dealloc: Deallocate Hash
-+ * @lrng_hash_digestsize: Return the digestsize for the used hash to read
-+ * out entropy pool
-+ * hash: is pointer to data structure allocated
-+ * with lrng_hash_alloc
-+ * return: size of digest of hash in bytes
-+ * @lrng_hash_init: Initialize hash
-+ * hash: is pointer to data structure allocated
-+ * with lrng_hash_alloc
-+ * return: 0 on success, < 0 on error
-+ * @lrng_hash_update: Update hash operation
-+ * hash: is pointer to data structure allocated
-+ * with lrng_hash_alloc
-+ * return: 0 on success, < 0 on error
-+ * @lrng_hash_final Final hash operation
-+ * hash: is pointer to data structure allocated
-+ * with lrng_hash_alloc
-+ * return: 0 on success, < 0 on error
-+ * @lrng_hash_desc_zero Zeroization of hash state buffer
-+ *
-+ * Assumptions:
-+ *
-+ * 1. Hash operation will not sleep
-+ * 2. The hash' volatile state information is provided with *shash by caller.
-+ */
-+struct lrng_crypto_cb {
-+ const char *(*lrng_drng_name)(void);
-+ const char *(*lrng_hash_name)(void);
-+ void *(*lrng_drng_alloc)(u32 sec_strength);
-+ void (*lrng_drng_dealloc)(void *drng);
-+ int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
-+ int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
-+ void *(*lrng_hash_alloc)(void);
-+ void (*lrng_hash_dealloc)(void *hash);
-+ u32 (*lrng_hash_digestsize)(void *hash);
-+ int (*lrng_hash_init)(struct shash_desc *shash, void *hash);
-+ int (*lrng_hash_update)(struct shash_desc *shash, const u8 *inbuf,
-+ u32 inbuflen);
-+ int (*lrng_hash_final)(struct shash_desc *shash, u8 *digest);
-+ void (*lrng_hash_desc_zero)(struct shash_desc *shash);
-+};
-+
-+/* Register cryptographic backend */
-+#ifdef CONFIG_LRNG_DRNG_SWITCH
-+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
-+#else /* CONFIG_LRNG_DRNG_SWITCH */
-+static inline int
-+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
-+#endif /* CONFIG_LRNG_DRNG_SWITCH */
-+
-+#endif /* _LRNG_H */
diff --git a/system/easy-kernel/0250-projectc-5.15-r1.patch b/system/easy-kernel/0250-projectc-5.15-r1.patch
deleted file mode 100644
index c67c2c9fc..000000000
--- a/system/easy-kernel/0250-projectc-5.15-r1.patch
+++ /dev/null
@@ -1,9746 +0,0 @@
-diff -urN linux-5.15.3/Documentation/admin-guide/kernel-parameters.txt linux-prjc-v5.15-prjc-r1/Documentation/admin-guide/kernel-parameters.txt
---- linux-5.15.3/Documentation/admin-guide/kernel-parameters.txt 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/Documentation/admin-guide/kernel-parameters.txt 2021-11-20 02:15:12.000000000 +1100
-@@ -4985,6 +4985,12 @@
- sa1100ir [NET]
- See drivers/net/irda/sa1100_ir.c.
-
-+ sched_timeslice=
-+ [KNL] Time slice in ms for Project C BMQ/PDS scheduler.
-+ Format: integer 2, 4
-+ Default: 4
-+ See Documentation/scheduler/sched-BMQ.txt
-+
- sched_verbose [KNL] Enables verbose scheduler debug messages.
-
- schedstats= [KNL,X86] Enable or disable scheduled statistics.
-diff -urN linux-5.15.3/Documentation/admin-guide/sysctl/kernel.rst linux-prjc-v5.15-prjc-r1/Documentation/admin-guide/sysctl/kernel.rst
---- linux-5.15.3/Documentation/admin-guide/sysctl/kernel.rst 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/Documentation/admin-guide/sysctl/kernel.rst 2021-11-20 02:15:12.000000000 +1100
-@@ -1542,3 +1542,13 @@
-
- The softlockup threshold is (``2 * watchdog_thresh``). Setting this
- tunable to zero will disable lockup detection altogether.
-+
-+yield_type:
-+===========
-+
-+BMQ/PDS CPU scheduler only. This determines what type of yield calls
-+to sched_yield will perform.
-+
-+ 0 - No yield.
-+ 1 - Deboost and requeue task. (default)
-+ 2 - Set run queue skip task.
-diff -urN linux-5.15.3/Documentation/scheduler/sched-BMQ.txt linux-prjc-v5.15-prjc-r1/Documentation/scheduler/sched-BMQ.txt
---- linux-5.15.3/Documentation/scheduler/sched-BMQ.txt 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/Documentation/scheduler/sched-BMQ.txt 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,110 @@
-+ BitMap queue CPU Scheduler
-+ --------------------------
-+
-+CONTENT
-+========
-+
-+ Background
-+ Design
-+ Overview
-+ Task policy
-+ Priority management
-+ BitMap Queue
-+ CPU Assignment and Migration
-+
-+
-+Background
-+==========
-+
-+BitMap Queue CPU scheduler, referred to as BMQ from here on, is an evolution
-+of previous Priority and Deadline based Skiplist multiple queue scheduler(PDS),
-+and inspired by Zircon scheduler. The goal of it is to keep the scheduler code
-+simple, while efficiency and scalable for interactive tasks, such as desktop,
-+movie playback and gaming etc.
-+
-+Design
-+======
-+
-+Overview
-+--------
-+
-+BMQ use per CPU run queue design, each CPU(logical) has it's own run queue,
-+each CPU is responsible for scheduling the tasks that are putting into it's
-+run queue.
-+
-+The run queue is a set of priority queues. Note that these queues are fifo
-+queue for non-rt tasks or priority queue for rt tasks in data structure. See
-+BitMap Queue below for details. BMQ is optimized for non-rt tasks in the fact
-+that most applications are non-rt tasks. No matter the queue is fifo or
-+priority, In each queue is an ordered list of runnable tasks awaiting execution
-+and the data structures are the same. When it is time for a new task to run,
-+the scheduler simply looks the lowest numbered queueue that contains a task,
-+and runs the first task from the head of that queue. And per CPU idle task is
-+also in the run queue, so the scheduler can always find a task to run on from
-+its run queue.
-+
-+Each task will assigned the same timeslice(default 4ms) when it is picked to
-+start running. Task will be reinserted at the end of the appropriate priority
-+queue when it uses its whole timeslice. When the scheduler selects a new task
-+from the priority queue it sets the CPU's preemption timer for the remainder of
-+the previous timeslice. When that timer fires the scheduler will stop execution
-+on that task, select another task and start over again.
-+
-+If a task blocks waiting for a shared resource then it's taken out of its
-+priority queue and is placed in a wait queue for the shared resource. When it
-+is unblocked it will be reinserted in the appropriate priority queue of an
-+eligible CPU.
-+
-+Task policy
-+-----------
-+
-+BMQ supports DEADLINE, FIFO, RR, NORMAL, BATCH and IDLE task policy like the
-+mainline CFS scheduler. But BMQ is heavy optimized for non-rt task, that's
-+NORMAL/BATCH/IDLE policy tasks. Below is the implementation detail of each
-+policy.
-+
-+DEADLINE
-+ It is squashed as priority 0 FIFO task.
-+
-+FIFO/RR
-+ All RT tasks share one single priority queue in BMQ run queue designed. The
-+complexity of insert operation is O(n). BMQ is not designed for system runs
-+with major rt policy tasks.
-+
-+NORMAL/BATCH/IDLE
-+ BATCH and IDLE tasks are treated as the same policy. They compete CPU with
-+NORMAL policy tasks, but they just don't boost. To control the priority of
-+NORMAL/BATCH/IDLE tasks, simply use nice level.
-+
-+ISO
-+ ISO policy is not supported in BMQ. Please use nice level -20 NORMAL policy
-+task instead.
-+
-+Priority management
-+-------------------
-+
-+RT tasks have priority from 0-99. For non-rt tasks, there are three different
-+factors used to determine the effective priority of a task. The effective
-+priority being what is used to determine which queue it will be in.
-+
-+The first factor is simply the task’s static priority. Which is assigned from
-+task's nice level, within [-20, 19] in userland's point of view and [0, 39]
-+internally.
-+
-+The second factor is the priority boost. This is a value bounded between
-+[-MAX_PRIORITY_ADJ, MAX_PRIORITY_ADJ] used to offset the base priority, it is
-+modified by the following cases:
-+
-+*When a thread has used up its entire timeslice, always deboost its boost by
-+increasing by one.
-+*When a thread gives up cpu control(voluntary or non-voluntary) to reschedule,
-+and its switch-in time(time after last switch and run) below the thredhold
-+based on its priority boost, will boost its boost by decreasing by one buti is
-+capped at 0 (won’t go negative).
-+
-+The intent in this system is to ensure that interactive threads are serviced
-+quickly. These are usually the threads that interact directly with the user
-+and cause user-perceivable latency. These threads usually do little work and
-+spend most of their time blocked awaiting another user event. So they get the
-+priority boost from unblocking while background threads that do most of the
-+processing receive the priority penalty for using their entire timeslice.
-diff -urN linux-5.15.3/fs/proc/base.c linux-prjc-v5.15-prjc-r1/fs/proc/base.c
---- linux-5.15.3/fs/proc/base.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/fs/proc/base.c 2021-11-20 02:15:12.000000000 +1100
-@@ -480,7 +480,7 @@
- seq_puts(m, "0 0 0\n");
- else
- seq_printf(m, "%llu %llu %lu\n",
-- (unsigned long long)task->se.sum_exec_runtime,
-+ (unsigned long long)tsk_seruntime(task),
- (unsigned long long)task->sched_info.run_delay,
- task->sched_info.pcount);
-
-diff -urN linux-5.15.3/include/asm-generic/resource.h linux-prjc-v5.15-prjc-r1/include/asm-generic/resource.h
---- linux-5.15.3/include/asm-generic/resource.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/asm-generic/resource.h 2021-11-20 02:15:12.000000000 +1100
-@@ -23,7 +23,7 @@
- [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_SIGPENDING] = { 0, 0 }, \
- [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
-- [RLIMIT_NICE] = { 0, 0 }, \
-+ [RLIMIT_NICE] = { 30, 30 }, \
- [RLIMIT_RTPRIO] = { 0, 0 }, \
- [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
- }
-diff -urN linux-5.15.3/include/linux/sched/deadline.h linux-prjc-v5.15-prjc-r1/include/linux/sched/deadline.h
---- linux-5.15.3/include/linux/sched/deadline.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/linux/sched/deadline.h 2021-11-20 02:15:12.000000000 +1100
-@@ -1,5 +1,24 @@
- /* SPDX-License-Identifier: GPL-2.0 */
-
-+#ifdef CONFIG_SCHED_ALT
-+
-+static inline int dl_task(struct task_struct *p)
-+{
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SCHED_BMQ
-+#define __tsk_deadline(p) (0UL)
-+#endif
-+
-+#ifdef CONFIG_SCHED_PDS
-+#define __tsk_deadline(p) ((((u64) ((p)->prio))<<56) | (p)->deadline)
-+#endif
-+
-+#else
-+
-+#define __tsk_deadline(p) ((p)->dl.deadline)
-+
- /*
- * SCHED_DEADLINE tasks has negative priorities, reflecting
- * the fact that any of them has higher prio than RT and
-@@ -19,6 +38,7 @@
- {
- return dl_prio(p->prio);
- }
-+#endif /* CONFIG_SCHED_ALT */
-
- static inline bool dl_time_before(u64 a, u64 b)
- {
-diff -urN linux-5.15.3/include/linux/sched/prio.h linux-prjc-v5.15-prjc-r1/include/linux/sched/prio.h
---- linux-5.15.3/include/linux/sched/prio.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/linux/sched/prio.h 2021-11-20 02:15:12.000000000 +1100
-@@ -18,6 +18,32 @@
- #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
- #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
-
-+#ifdef CONFIG_SCHED_ALT
-+
-+/* Undefine MAX_PRIO and DEFAULT_PRIO */
-+#undef MAX_PRIO
-+#undef DEFAULT_PRIO
-+
-+/* +/- priority levels from the base priority */
-+#ifdef CONFIG_SCHED_BMQ
-+#define MAX_PRIORITY_ADJ (7)
-+
-+#define MIN_NORMAL_PRIO (MAX_RT_PRIO)
-+#define MAX_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH)
-+#define DEFAULT_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH / 2)
-+#endif
-+
-+#ifdef CONFIG_SCHED_PDS
-+#define MAX_PRIORITY_ADJ (0)
-+
-+#define MIN_NORMAL_PRIO (128)
-+#define NORMAL_PRIO_NUM (64)
-+#define MAX_PRIO (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM)
-+#define DEFAULT_PRIO (MAX_PRIO - NICE_WIDTH / 2)
-+#endif
-+
-+#endif /* CONFIG_SCHED_ALT */
-+
- /*
- * Convert user-nice values [ -20 ... 0 ... 19 ]
- * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
-diff -urN linux-5.15.3/include/linux/sched/rt.h linux-prjc-v5.15-prjc-r1/include/linux/sched/rt.h
---- linux-5.15.3/include/linux/sched/rt.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/linux/sched/rt.h 2021-11-20 02:15:12.000000000 +1100
-@@ -24,8 +24,10 @@
-
- if (policy == SCHED_FIFO || policy == SCHED_RR)
- return true;
-+#ifndef CONFIG_SCHED_ALT
- if (policy == SCHED_DEADLINE)
- return true;
-+#endif
- return false;
- }
-
-diff -urN linux-5.15.3/include/linux/sched/topology.h linux-prjc-v5.15-prjc-r1/include/linux/sched/topology.h
---- linux-5.15.3/include/linux/sched/topology.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/linux/sched/topology.h 2021-11-20 02:15:12.000000000 +1100
-@@ -225,7 +225,8 @@
-
- #endif /* !CONFIG_SMP */
-
--#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
-+#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) && \
-+ !defined(CONFIG_SCHED_ALT)
- extern void rebuild_sched_domains_energy(void);
- #else
- static inline void rebuild_sched_domains_energy(void)
-diff -urN linux-5.15.3/include/linux/sched.h linux-prjc-v5.15-prjc-r1/include/linux/sched.h
---- linux-5.15.3/include/linux/sched.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/include/linux/sched.h 2021-11-20 02:15:12.000000000 +1100
-@@ -748,12 +748,18 @@
- unsigned int ptrace;
-
- #ifdef CONFIG_SMP
-- int on_cpu;
- struct __call_single_node wake_entry;
-+#endif
-+#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_ALT)
-+ int on_cpu;
-+#endif
-+
-+#ifdef CONFIG_SMP
- #ifdef CONFIG_THREAD_INFO_IN_TASK
- /* Current CPU: */
- unsigned int cpu;
- #endif
-+#ifndef CONFIG_SCHED_ALT
- unsigned int wakee_flips;
- unsigned long wakee_flip_decay_ts;
- struct task_struct *last_wakee;
-@@ -767,6 +773,7 @@
- */
- int recent_used_cpu;
- int wake_cpu;
-+#endif /* !CONFIG_SCHED_ALT */
- #endif
- int on_rq;
-
-@@ -775,6 +782,20 @@
- int normal_prio;
- unsigned int rt_priority;
-
-+#ifdef CONFIG_SCHED_ALT
-+ u64 last_ran;
-+ s64 time_slice;
-+ int sq_idx;
-+ struct list_head sq_node;
-+#ifdef CONFIG_SCHED_BMQ
-+ int boost_prio;
-+#endif /* CONFIG_SCHED_BMQ */
-+#ifdef CONFIG_SCHED_PDS
-+ u64 deadline;
-+#endif /* CONFIG_SCHED_PDS */
-+ /* sched_clock time spent running */
-+ u64 sched_time;
-+#else /* !CONFIG_SCHED_ALT */
- const struct sched_class *sched_class;
- struct sched_entity se;
- struct sched_rt_entity rt;
-@@ -785,6 +806,7 @@
- unsigned long core_cookie;
- unsigned int core_occupation;
- #endif
-+#endif /* !CONFIG_SCHED_ALT */
-
- #ifdef CONFIG_CGROUP_SCHED
- struct task_group *sched_task_group;
-@@ -1505,6 +1527,15 @@
- */
- };
-
-+#ifdef CONFIG_SCHED_ALT
-+#define tsk_seruntime(t) ((t)->sched_time)
-+/* replace the uncertian rt_timeout with 0UL */
-+#define tsk_rttimeout(t) (0UL)
-+#else /* CFS */
-+#define tsk_seruntime(t) ((t)->se.sum_exec_runtime)
-+#define tsk_rttimeout(t) ((t)->rt.timeout)
-+#endif /* !CONFIG_SCHED_ALT */
-+
- static inline struct pid *task_pid(struct task_struct *task)
- {
- return task->thread_pid;
-diff -urN linux-5.15.3/init/Kconfig linux-prjc-v5.15-prjc-r1/init/Kconfig
---- linux-5.15.3/init/Kconfig 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/init/Kconfig 2021-11-20 02:15:12.000000000 +1100
-@@ -814,9 +814,39 @@
-
- menu "Scheduler features"
-
-+menuconfig SCHED_ALT
-+ bool "Alternative CPU Schedulers"
-+ default y
-+ help
-+ This feature enable alternative CPU scheduler"
-+
-+if SCHED_ALT
-+
-+choice
-+ prompt "Alternative CPU Scheduler"
-+ default SCHED_BMQ
-+
-+config SCHED_BMQ
-+ bool "BMQ CPU scheduler"
-+ help
-+ The BitMap Queue CPU scheduler for excellent interactivity and
-+ responsiveness on the desktop and solid scalability on normal
-+ hardware and commodity servers.
-+
-+config SCHED_PDS
-+ bool "PDS CPU scheduler"
-+ help
-+ The Priority and Deadline based Skip list multiple queue CPU
-+ Scheduler.
-+
-+endchoice
-+
-+endif
-+
- config UCLAMP_TASK
- bool "Enable utilization clamping for RT/FAIR tasks"
- depends on CPU_FREQ_GOV_SCHEDUTIL
-+ depends on !SCHED_ALT
- help
- This feature enables the scheduler to track the clamped utilization
- of each CPU based on RUNNABLE tasks scheduled on that CPU.
-@@ -902,6 +932,7 @@
- depends on ARCH_SUPPORTS_NUMA_BALANCING
- depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY
- depends on SMP && NUMA && MIGRATION
-+ depends on !SCHED_ALT
- help
- This option adds support for automatic NUMA aware memory/task placement.
- The mechanism is quite primitive and is based on migrating memory when
-@@ -994,6 +1025,7 @@
- depends on CGROUP_SCHED
- default CGROUP_SCHED
-
-+if !SCHED_ALT
- config CFS_BANDWIDTH
- bool "CPU bandwidth provisioning for FAIR_GROUP_SCHED"
- depends on FAIR_GROUP_SCHED
-@@ -1016,6 +1048,7 @@
- realtime bandwidth for them.
- See Documentation/scheduler/sched-rt-group.rst for more information.
-
-+endif #!SCHED_ALT
- endif #CGROUP_SCHED
-
- config UCLAMP_TASK_GROUP
-@@ -1259,6 +1292,7 @@
-
- config SCHED_AUTOGROUP
- bool "Automatic process group scheduling"
-+ depends on !SCHED_ALT
- select CGROUPS
- select CGROUP_SCHED
- select FAIR_GROUP_SCHED
-diff -urN linux-5.15.3/init/init_task.c linux-prjc-v5.15-prjc-r1/init/init_task.c
---- linux-5.15.3/init/init_task.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/init/init_task.c 2021-11-20 02:15:12.000000000 +1100
-@@ -75,9 +75,15 @@
- .stack = init_stack,
- .usage = REFCOUNT_INIT(2),
- .flags = PF_KTHREAD,
-+#ifdef CONFIG_SCHED_ALT
-+ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
-+ .static_prio = DEFAULT_PRIO,
-+ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
-+#else
- .prio = MAX_PRIO - 20,
- .static_prio = MAX_PRIO - 20,
- .normal_prio = MAX_PRIO - 20,
-+#endif
- .policy = SCHED_NORMAL,
- .cpus_ptr = &init_task.cpus_mask,
- .user_cpus_ptr = NULL,
-@@ -88,6 +94,17 @@
- .restart_block = {
- .fn = do_no_restart_syscall,
- },
-+#ifdef CONFIG_SCHED_ALT
-+ .sq_node = LIST_HEAD_INIT(init_task.sq_node),
-+#ifdef CONFIG_SCHED_BMQ
-+ .boost_prio = 0,
-+ .sq_idx = 15,
-+#endif
-+#ifdef CONFIG_SCHED_PDS
-+ .deadline = 0,
-+#endif
-+ .time_slice = HZ,
-+#else
- .se = {
- .group_node = LIST_HEAD_INIT(init_task.se.group_node),
- },
-@@ -95,6 +112,7 @@
- .run_list = LIST_HEAD_INIT(init_task.rt.run_list),
- .time_slice = RR_TIMESLICE,
- },
-+#endif
- .tasks = LIST_HEAD_INIT(init_task.tasks),
- #ifdef CONFIG_SMP
- .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO),
-diff -urN linux-5.15.3/kernel/Kconfig.preempt linux-prjc-v5.15-prjc-r1/kernel/Kconfig.preempt
---- linux-5.15.3/kernel/Kconfig.preempt 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/Kconfig.preempt 2021-11-20 02:15:12.000000000 +1100
-@@ -102,7 +102,7 @@
-
- config SCHED_CORE
- bool "Core Scheduling for SMT"
-- depends on SCHED_SMT
-+ depends on SCHED_SMT && !SCHED_ALT
- help
- This option permits Core Scheduling, a means of coordinated task
- selection across SMT siblings. When enabled -- see
-diff -urN linux-5.15.3/kernel/cgroup/cpuset.c linux-prjc-v5.15-prjc-r1/kernel/cgroup/cpuset.c
---- linux-5.15.3/kernel/cgroup/cpuset.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/cgroup/cpuset.c 2021-11-20 02:15:12.000000000 +1100
-@@ -664,7 +664,7 @@
- return ret;
- }
-
--#ifdef CONFIG_SMP
-+#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_ALT)
- /*
- * Helper routine for generate_sched_domains().
- * Do cpusets a, b have overlapping effective cpus_allowed masks?
-@@ -1060,7 +1060,7 @@
- /* Have scheduler rebuild the domains */
- partition_and_rebuild_sched_domains(ndoms, doms, attr);
- }
--#else /* !CONFIG_SMP */
-+#else /* !CONFIG_SMP || CONFIG_SCHED_ALT */
- static void rebuild_sched_domains_locked(void)
- {
- }
-diff -urN linux-5.15.3/kernel/delayacct.c linux-prjc-v5.15-prjc-r1/kernel/delayacct.c
---- linux-5.15.3/kernel/delayacct.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/delayacct.c 2021-11-20 02:15:12.000000000 +1100
-@@ -139,7 +139,7 @@
- */
- t1 = tsk->sched_info.pcount;
- t2 = tsk->sched_info.run_delay;
-- t3 = tsk->se.sum_exec_runtime;
-+ t3 = tsk_seruntime(tsk);
-
- d->cpu_count += t1;
-
-diff -urN linux-5.15.3/kernel/exit.c linux-prjc-v5.15-prjc-r1/kernel/exit.c
---- linux-5.15.3/kernel/exit.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/exit.c 2021-11-20 02:15:12.000000000 +1100
-@@ -122,7 +122,7 @@
- sig->curr_target = next_thread(tsk);
- }
-
-- add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
-+ add_device_randomness((const void*) &tsk_seruntime(tsk),
- sizeof(unsigned long long));
-
- /*
-@@ -143,7 +143,7 @@
- sig->inblock += task_io_get_inblock(tsk);
- sig->oublock += task_io_get_oublock(tsk);
- task_io_accounting_add(&sig->ioac, &tsk->ioac);
-- sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
-+ sig->sum_sched_runtime += tsk_seruntime(tsk);
- sig->nr_threads--;
- __unhash_process(tsk, group_dead);
- write_sequnlock(&sig->stats_lock);
-diff -urN linux-5.15.3/kernel/livepatch/transition.c linux-prjc-v5.15-prjc-r1/kernel/livepatch/transition.c
---- linux-5.15.3/kernel/livepatch/transition.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/livepatch/transition.c 2021-11-20 02:15:12.000000000 +1100
-@@ -307,7 +307,11 @@
- */
- rq = task_rq_lock(task, &flags);
-
-+#ifdef CONFIG_SCHED_ALT
-+ if (task_running(task) && task != current) {
-+#else
- if (task_running(rq, task) && task != current) {
-+#endif
- snprintf(err_buf, STACK_ERR_BUF_SIZE,
- "%s: %s:%d is running\n", __func__, task->comm,
- task->pid);
-diff -urN linux-5.15.3/kernel/locking/rtmutex.c linux-prjc-v5.15-prjc-r1/kernel/locking/rtmutex.c
---- linux-5.15.3/kernel/locking/rtmutex.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/locking/rtmutex.c 2021-11-20 02:15:12.000000000 +1100
-@@ -298,21 +298,25 @@
- waiter_update_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
- {
- waiter->prio = __waiter_prio(task);
-- waiter->deadline = task->dl.deadline;
-+ waiter->deadline = __tsk_deadline(task);
- }
-
- /*
- * Only use with rt_mutex_waiter_{less,equal}()
- */
- #define task_to_waiter(p) \
-- &(struct rt_mutex_waiter){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
-+ &(struct rt_mutex_waiter){ .prio = __waiter_prio(p), .deadline = __tsk_deadline(p) }
-
- static __always_inline int rt_mutex_waiter_less(struct rt_mutex_waiter *left,
- struct rt_mutex_waiter *right)
- {
-+#ifdef CONFIG_SCHED_PDS
-+ return (left->deadline < right->deadline);
-+#else
- if (left->prio < right->prio)
- return 1;
-
-+#ifndef CONFIG_SCHED_BMQ
- /*
- * If both waiters have dl_prio(), we check the deadlines of the
- * associated tasks.
-@@ -321,16 +325,22 @@
- */
- if (dl_prio(left->prio))
- return dl_time_before(left->deadline, right->deadline);
-+#endif
-
- return 0;
-+#endif
- }
-
- static __always_inline int rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
- struct rt_mutex_waiter *right)
- {
-+#ifdef CONFIG_SCHED_PDS
-+ return (left->deadline == right->deadline);
-+#else
- if (left->prio != right->prio)
- return 0;
-
-+#ifndef CONFIG_SCHED_BMQ
- /*
- * If both waiters have dl_prio(), we check the deadlines of the
- * associated tasks.
-@@ -339,8 +349,10 @@
- */
- if (dl_prio(left->prio))
- return left->deadline == right->deadline;
-+#endif
-
- return 1;
-+#endif
- }
-
- static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
-diff -urN linux-5.15.3/kernel/sched/Makefile linux-prjc-v5.15-prjc-r1/kernel/sched/Makefile
---- linux-5.15.3/kernel/sched/Makefile 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/Makefile 2021-11-20 02:15:12.000000000 +1100
-@@ -22,14 +22,21 @@
- CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
- endif
-
--obj-y += core.o loadavg.o clock.o cputime.o
--obj-y += idle.o fair.o rt.o deadline.o
--obj-y += wait.o wait_bit.o swait.o completion.o
--
--obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o topology.o stop_task.o pelt.o
-+ifdef CONFIG_SCHED_ALT
-+obj-y += alt_core.o
-+obj-$(CONFIG_SCHED_DEBUG) += alt_debug.o
-+else
-+obj-y += core.o
-+obj-y += fair.o rt.o deadline.o
-+obj-$(CONFIG_SMP) += cpudeadline.o stop_task.o
- obj-$(CONFIG_SCHED_AUTOGROUP) += autogroup.o
--obj-$(CONFIG_SCHEDSTATS) += stats.o
-+endif
- obj-$(CONFIG_SCHED_DEBUG) += debug.o
-+obj-y += loadavg.o clock.o cputime.o
-+obj-y += idle.o
-+obj-y += wait.o wait_bit.o swait.o completion.o
-+obj-$(CONFIG_SMP) += cpupri.o pelt.o topology.o
-+obj-$(CONFIG_SCHEDSTATS) += stats.o
- obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o
- obj-$(CONFIG_CPU_FREQ) += cpufreq.o
- obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o
-diff -urN linux-5.15.3/kernel/sched/alt_core.c linux-prjc-v5.15-prjc-r1/kernel/sched/alt_core.c
---- linux-5.15.3/kernel/sched/alt_core.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/alt_core.c 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,7627 @@
-+/*
-+ * kernel/sched/alt_core.c
-+ *
-+ * Core alternative kernel scheduler code and related syscalls
-+ *
-+ * Copyright (C) 1991-2002 Linus Torvalds
-+ *
-+ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes
-+ * a whole lot of those previous things.
-+ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel
-+ * scheduler by Alfred Chen.
-+ * 2019-02-20 BMQ(BitMap Queue) kernel scheduler by Alfred Chen.
-+ */
-+#define CREATE_TRACE_POINTS
-+#include <trace/events/sched.h>
-+#undef CREATE_TRACE_POINTS
-+
-+#include "sched.h"
-+
-+#include <linux/sched/rt.h>
-+
-+#include <linux/context_tracking.h>
-+#include <linux/compat.h>
-+#include <linux/blkdev.h>
-+#include <linux/delayacct.h>
-+#include <linux/freezer.h>
-+#include <linux/init_task.h>
-+#include <linux/kprobes.h>
-+#include <linux/mmu_context.h>
-+#include <linux/nmi.h>
-+#include <linux/profile.h>
-+#include <linux/rcupdate_wait.h>
-+#include <linux/security.h>
-+#include <linux/syscalls.h>
-+#include <linux/wait_bit.h>
-+
-+#include <linux/kcov.h>
-+#include <linux/scs.h>
-+
-+#include <asm/switch_to.h>
-+
-+#include "../workqueue_internal.h"
-+#include "../../fs/io-wq.h"
-+#include "../smpboot.h"
-+
-+#include "pelt.h"
-+#include "smp.h"
-+
-+/*
-+ * Export tracepoints that act as a bare tracehook (ie: have no trace event
-+ * associated with them) to allow external modules to probe them.
-+ */
-+EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_irq_tp);
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+#define sched_feat(x) (1)
-+/*
-+ * Print a warning if need_resched is set for the given duration (if
-+ * LATENCY_WARN is enabled).
-+ *
-+ * If sysctl_resched_latency_warn_once is set, only one warning will be shown
-+ * per boot.
-+ */
-+__read_mostly int sysctl_resched_latency_warn_ms = 100;
-+__read_mostly int sysctl_resched_latency_warn_once = 1;
-+#else
-+#define sched_feat(x) (0)
-+#endif /* CONFIG_SCHED_DEBUG */
-+
-+#define ALT_SCHED_VERSION "v5.15-r1"
-+
-+/* rt_prio(prio) defined in include/linux/sched/rt.h */
-+#define rt_task(p) rt_prio((p)->prio)
-+#define rt_policy(policy) ((policy) == SCHED_FIFO || (policy) == SCHED_RR)
-+#define task_has_rt_policy(p) (rt_policy((p)->policy))
-+
-+#define STOP_PRIO (MAX_RT_PRIO - 1)
-+
-+/* Default time slice is 4 in ms, can be set via kernel parameter "sched_timeslice" */
-+u64 sched_timeslice_ns __read_mostly = (4 << 20);
-+
-+static inline void requeue_task(struct task_struct *p, struct rq *rq);
-+
-+#ifdef CONFIG_SCHED_BMQ
-+#include "bmq.h"
-+#endif
-+#ifdef CONFIG_SCHED_PDS
-+#include "pds.h"
-+#endif
-+
-+static int __init sched_timeslice(char *str)
-+{
-+ int timeslice_ms;
-+
-+ get_option(&str, &timeslice_ms);
-+ if (2 != timeslice_ms)
-+ timeslice_ms = 4;
-+ sched_timeslice_ns = timeslice_ms << 20;
-+ sched_timeslice_imp(timeslice_ms);
-+
-+ return 0;
-+}
-+early_param("sched_timeslice", sched_timeslice);
-+
-+/* Reschedule if less than this many μs left */
-+#define RESCHED_NS (100 << 10)
-+
-+/**
-+ * sched_yield_type - Choose what sort of yield sched_yield will perform.
-+ * 0: No yield.
-+ * 1: Deboost and requeue task. (default)
-+ * 2: Set rq skip task.
-+ */
-+int sched_yield_type __read_mostly = 1;
-+
-+#ifdef CONFIG_SMP
-+static cpumask_t sched_rq_pending_mask ____cacheline_aligned_in_smp;
-+
-+DEFINE_PER_CPU(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
-+DEFINE_PER_CPU(cpumask_t *, sched_cpu_llc_mask);
-+DEFINE_PER_CPU(cpumask_t *, sched_cpu_topo_end_mask);
-+
-+#ifdef CONFIG_SCHED_SMT
-+DEFINE_STATIC_KEY_FALSE(sched_smt_present);
-+EXPORT_SYMBOL_GPL(sched_smt_present);
-+#endif
-+
-+/*
-+ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of
-+ * the domain), this allows us to quickly tell if two cpus are in the same cache
-+ * domain, see cpus_share_cache().
-+ */
-+DEFINE_PER_CPU(int, sd_llc_id);
-+#endif /* CONFIG_SMP */
-+
-+static DEFINE_MUTEX(sched_hotcpu_mutex);
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-+
-+#ifndef prepare_arch_switch
-+# define prepare_arch_switch(next) do { } while (0)
-+#endif
-+#ifndef finish_arch_post_lock_switch
-+# define finish_arch_post_lock_switch() do { } while (0)
-+#endif
-+
-+#ifdef CONFIG_SCHED_SMT
-+static cpumask_t sched_sg_idle_mask ____cacheline_aligned_in_smp;
-+#endif
-+static cpumask_t sched_rq_watermark[SCHED_BITS] ____cacheline_aligned_in_smp;
-+
-+/* sched_queue related functions */
-+static inline void sched_queue_init(struct sched_queue *q)
-+{
-+ int i;
-+
-+ bitmap_zero(q->bitmap, SCHED_BITS);
-+ for(i = 0; i < SCHED_BITS; i++)
-+ INIT_LIST_HEAD(&q->heads[i]);
-+}
-+
-+/*
-+ * Init idle task and put into queue structure of rq
-+ * IMPORTANT: may be called multiple times for a single cpu
-+ */
-+static inline void sched_queue_init_idle(struct sched_queue *q,
-+ struct task_struct *idle)
-+{
-+ idle->sq_idx = IDLE_TASK_SCHED_PRIO;
-+ INIT_LIST_HEAD(&q->heads[idle->sq_idx]);
-+ list_add(&idle->sq_node, &q->heads[idle->sq_idx]);
-+}
-+
-+/* water mark related functions */
-+static inline void update_sched_rq_watermark(struct rq *rq)
-+{
-+ unsigned long watermark = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
-+ unsigned long last_wm = rq->watermark;
-+ unsigned long i;
-+ int cpu;
-+
-+ if (watermark == last_wm)
-+ return;
-+
-+ rq->watermark = watermark;
-+ cpu = cpu_of(rq);
-+ if (watermark < last_wm) {
-+ for (i = last_wm; i > watermark; i--)
-+ cpumask_clear_cpu(cpu, sched_rq_watermark + SCHED_BITS - 1 - i);
-+#ifdef CONFIG_SCHED_SMT
-+ if (static_branch_likely(&sched_smt_present) &&
-+ IDLE_TASK_SCHED_PRIO == last_wm)
-+ cpumask_andnot(&sched_sg_idle_mask,
-+ &sched_sg_idle_mask, cpu_smt_mask(cpu));
-+#endif
-+ return;
-+ }
-+ /* last_wm < watermark */
-+ for (i = watermark; i > last_wm; i--)
-+ cpumask_set_cpu(cpu, sched_rq_watermark + SCHED_BITS - 1 - i);
-+#ifdef CONFIG_SCHED_SMT
-+ if (static_branch_likely(&sched_smt_present) &&
-+ IDLE_TASK_SCHED_PRIO == watermark) {
-+ cpumask_t tmp;
-+
-+ cpumask_and(&tmp, cpu_smt_mask(cpu), sched_rq_watermark);
-+ if (cpumask_equal(&tmp, cpu_smt_mask(cpu)))
-+ cpumask_or(&sched_sg_idle_mask,
-+ &sched_sg_idle_mask, cpu_smt_mask(cpu));
-+ }
-+#endif
-+}
-+
-+/*
-+ * This routine assume that the idle task always in queue
-+ */
-+static inline struct task_struct *sched_rq_first_task(struct rq *rq)
-+{
-+ unsigned long idx = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
-+ const struct list_head *head = &rq->queue.heads[sched_prio2idx(idx, rq)];
-+
-+ return list_first_entry(head, struct task_struct, sq_node);
-+}
-+
-+static inline struct task_struct *
-+sched_rq_next_task(struct task_struct *p, struct rq *rq)
-+{
-+ unsigned long idx = p->sq_idx;
-+ struct list_head *head = &rq->queue.heads[idx];
-+
-+ if (list_is_last(&p->sq_node, head)) {
-+ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS,
-+ sched_idx2prio(idx, rq) + 1);
-+ head = &rq->queue.heads[sched_prio2idx(idx, rq)];
-+
-+ return list_first_entry(head, struct task_struct, sq_node);
-+ }
-+
-+ return list_next_entry(p, sq_node);
-+}
-+
-+static inline struct task_struct *rq_runnable_task(struct rq *rq)
-+{
-+ struct task_struct *next = sched_rq_first_task(rq);
-+
-+ if (unlikely(next == rq->skip))
-+ next = sched_rq_next_task(next, rq);
-+
-+ return next;
-+}
-+
-+/*
-+ * Serialization rules:
-+ *
-+ * Lock order:
-+ *
-+ * p->pi_lock
-+ * rq->lock
-+ * hrtimer_cpu_base->lock (hrtimer_start() for bandwidth controls)
-+ *
-+ * rq1->lock
-+ * rq2->lock where: rq1 < rq2
-+ *
-+ * Regular state:
-+ *
-+ * Normal scheduling state is serialized by rq->lock. __schedule() takes the
-+ * local CPU's rq->lock, it optionally removes the task from the runqueue and
-+ * always looks at the local rq data structures to find the most eligible task
-+ * to run next.
-+ *
-+ * Task enqueue is also under rq->lock, possibly taken from another CPU.
-+ * Wakeups from another LLC domain might use an IPI to transfer the enqueue to
-+ * the local CPU to avoid bouncing the runqueue state around [ see
-+ * ttwu_queue_wakelist() ]
-+ *
-+ * Task wakeup, specifically wakeups that involve migration, are horribly
-+ * complicated to avoid having to take two rq->locks.
-+ *
-+ * Special state:
-+ *
-+ * System-calls and anything external will use task_rq_lock() which acquires
-+ * both p->pi_lock and rq->lock. As a consequence the state they change is
-+ * stable while holding either lock:
-+ *
-+ * - sched_setaffinity()/
-+ * set_cpus_allowed_ptr(): p->cpus_ptr, p->nr_cpus_allowed
-+ * - set_user_nice(): p->se.load, p->*prio
-+ * - __sched_setscheduler(): p->sched_class, p->policy, p->*prio,
-+ * p->se.load, p->rt_priority,
-+ * p->dl.dl_{runtime, deadline, period, flags, bw, density}
-+ * - sched_setnuma(): p->numa_preferred_nid
-+ * - sched_move_task()/
-+ * cpu_cgroup_fork(): p->sched_task_group
-+ * - uclamp_update_active() p->uclamp*
-+ *
-+ * p->state <- TASK_*:
-+ *
-+ * is changed locklessly using set_current_state(), __set_current_state() or
-+ * set_special_state(), see their respective comments, or by
-+ * try_to_wake_up(). This latter uses p->pi_lock to serialize against
-+ * concurrent self.
-+ *
-+ * p->on_rq <- { 0, 1 = TASK_ON_RQ_QUEUED, 2 = TASK_ON_RQ_MIGRATING }:
-+ *
-+ * is set by activate_task() and cleared by deactivate_task(), under
-+ * rq->lock. Non-zero indicates the task is runnable, the special
-+ * ON_RQ_MIGRATING state is used for migration without holding both
-+ * rq->locks. It indicates task_cpu() is not stable, see task_rq_lock().
-+ *
-+ * p->on_cpu <- { 0, 1 }:
-+ *
-+ * is set by prepare_task() and cleared by finish_task() such that it will be
-+ * set before p is scheduled-in and cleared after p is scheduled-out, both
-+ * under rq->lock. Non-zero indicates the task is running on its CPU.
-+ *
-+ * [ The astute reader will observe that it is possible for two tasks on one
-+ * CPU to have ->on_cpu = 1 at the same time. ]
-+ *
-+ * task_cpu(p): is changed by set_task_cpu(), the rules are:
-+ *
-+ * - Don't call set_task_cpu() on a blocked task:
-+ *
-+ * We don't care what CPU we're not running on, this simplifies hotplug,
-+ * the CPU assignment of blocked tasks isn't required to be valid.
-+ *
-+ * - for try_to_wake_up(), called under p->pi_lock:
-+ *
-+ * This allows try_to_wake_up() to only take one rq->lock, see its comment.
-+ *
-+ * - for migration called under rq->lock:
-+ * [ see task_on_rq_migrating() in task_rq_lock() ]
-+ *
-+ * o move_queued_task()
-+ * o detach_task()
-+ *
-+ * - for migration called under double_rq_lock():
-+ *
-+ * o __migrate_swap_task()
-+ * o push_rt_task() / pull_rt_task()
-+ * o push_dl_task() / pull_dl_task()
-+ * o dl_task_offline_migration()
-+ *
-+ */
-+
-+/*
-+ * Context: p->pi_lock
-+ */
-+static inline struct rq
-+*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
-+{
-+ struct rq *rq;
-+ for (;;) {
-+ rq = task_rq(p);
-+ if (p->on_cpu || task_on_rq_queued(p)) {
-+ raw_spin_lock(&rq->lock);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
-+ *plock = &rq->lock;
-+ return rq;
-+ }
-+ raw_spin_unlock(&rq->lock);
-+ } else if (task_on_rq_migrating(p)) {
-+ do {
-+ cpu_relax();
-+ } while (unlikely(task_on_rq_migrating(p)));
-+ } else {
-+ *plock = NULL;
-+ return rq;
-+ }
-+ }
-+}
-+
-+static inline void
-+__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
-+{
-+ if (NULL != lock)
-+ raw_spin_unlock(lock);
-+}
-+
-+static inline struct rq
-+*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock,
-+ unsigned long *flags)
-+{
-+ struct rq *rq;
-+ for (;;) {
-+ rq = task_rq(p);
-+ if (p->on_cpu || task_on_rq_queued(p)) {
-+ raw_spin_lock_irqsave(&rq->lock, *flags);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
-+ *plock = &rq->lock;
-+ return rq;
-+ }
-+ raw_spin_unlock_irqrestore(&rq->lock, *flags);
-+ } else if (task_on_rq_migrating(p)) {
-+ do {
-+ cpu_relax();
-+ } while (unlikely(task_on_rq_migrating(p)));
-+ } else {
-+ raw_spin_lock_irqsave(&p->pi_lock, *flags);
-+ if (likely(!p->on_cpu && !p->on_rq &&
-+ rq == task_rq(p))) {
-+ *plock = &p->pi_lock;
-+ return rq;
-+ }
-+ raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
-+ }
-+ }
-+}
-+
-+static inline void
-+task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock,
-+ unsigned long *flags)
-+{
-+ raw_spin_unlock_irqrestore(lock, *flags);
-+}
-+
-+/*
-+ * __task_rq_lock - lock the rq @p resides on.
-+ */
-+struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ lockdep_assert_held(&p->pi_lock);
-+
-+ for (;;) {
-+ rq = task_rq(p);
-+ raw_spin_lock(&rq->lock);
-+ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p)))
-+ return rq;
-+ raw_spin_unlock(&rq->lock);
-+
-+ while (unlikely(task_on_rq_migrating(p)))
-+ cpu_relax();
-+ }
-+}
-+
-+/*
-+ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on.
-+ */
-+struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(p->pi_lock)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ for (;;) {
-+ raw_spin_lock_irqsave(&p->pi_lock, rf->flags);
-+ rq = task_rq(p);
-+ raw_spin_lock(&rq->lock);
-+ /*
-+ * move_queued_task() task_rq_lock()
-+ *
-+ * ACQUIRE (rq->lock)
-+ * [S] ->on_rq = MIGRATING [L] rq = task_rq()
-+ * WMB (__set_task_cpu()) ACQUIRE (rq->lock);
-+ * [S] ->cpu = new_cpu [L] task_rq()
-+ * [L] ->on_rq
-+ * RELEASE (rq->lock)
-+ *
-+ * If we observe the old CPU in task_rq_lock(), the acquire of
-+ * the old rq->lock will fully serialize against the stores.
-+ *
-+ * If we observe the new CPU in task_rq_lock(), the address
-+ * dependency headed by '[L] rq = task_rq()' and the acquire
-+ * will pair with the WMB to ensure we then also see migrating.
-+ */
-+ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {
-+ return rq;
-+ }
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
-+
-+ while (unlikely(task_on_rq_migrating(p)))
-+ cpu_relax();
-+ }
-+}
-+
-+static inline void
-+rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ raw_spin_lock_irqsave(&rq->lock, rf->flags);
-+}
-+
-+static inline void
-+rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock_irqrestore(&rq->lock, rf->flags);
-+}
-+
-+void raw_spin_rq_lock_nested(struct rq *rq, int subclass)
-+{
-+ raw_spinlock_t *lock;
-+
-+ /* Matches synchronize_rcu() in __sched_core_enable() */
-+ preempt_disable();
-+
-+ for (;;) {
-+ lock = __rq_lockp(rq);
-+ raw_spin_lock_nested(lock, subclass);
-+ if (likely(lock == __rq_lockp(rq))) {
-+ /* preempt_count *MUST* be > 1 */
-+ preempt_enable_no_resched();
-+ return;
-+ }
-+ raw_spin_unlock(lock);
-+ }
-+}
-+
-+void raw_spin_rq_unlock(struct rq *rq)
-+{
-+ raw_spin_unlock(rq_lockp(rq));
-+}
-+
-+/*
-+ * RQ-clock updating methods:
-+ */
-+
-+static void update_rq_clock_task(struct rq *rq, s64 delta)
-+{
-+/*
-+ * In theory, the compile should just see 0 here, and optimize out the call
-+ * to sched_rt_avg_update. But I don't trust it...
-+ */
-+ s64 __maybe_unused steal = 0, irq_delta = 0;
-+
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
-+
-+ /*
-+ * Since irq_time is only updated on {soft,}irq_exit, we might run into
-+ * this case when a previous update_rq_clock() happened inside a
-+ * {soft,}irq region.
-+ *
-+ * When this happens, we stop ->clock_task and only update the
-+ * prev_irq_time stamp to account for the part that fit, so that a next
-+ * update will consume the rest. This ensures ->clock_task is
-+ * monotonic.
-+ *
-+ * It does however cause some slight miss-attribution of {soft,}irq
-+ * time, a more accurate solution would be to update the irq_time using
-+ * the current rq->clock timestamp, except that would require using
-+ * atomic ops.
-+ */
-+ if (irq_delta > delta)
-+ irq_delta = delta;
-+
-+ rq->prev_irq_time += irq_delta;
-+ delta -= irq_delta;
-+#endif
-+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
-+ if (static_key_false((&paravirt_steal_rq_enabled))) {
-+ steal = paravirt_steal_clock(cpu_of(rq));
-+ steal -= rq->prev_steal_time_rq;
-+
-+ if (unlikely(steal > delta))
-+ steal = delta;
-+
-+ rq->prev_steal_time_rq += steal;
-+ delta -= steal;
-+ }
-+#endif
-+
-+ rq->clock_task += delta;
-+
-+#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
-+ if ((irq_delta + steal))
-+ update_irq_load_avg(rq, irq_delta + steal);
-+#endif
-+}
-+
-+static inline void update_rq_clock(struct rq *rq)
-+{
-+ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
-+
-+ if (unlikely(delta <= 0))
-+ return;
-+ rq->clock += delta;
-+ update_rq_time_edge(rq);
-+ update_rq_clock_task(rq, delta);
-+}
-+
-+/*
-+ * RQ Load update routine
-+ */
-+#define RQ_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL)
-+#define RQ_UTIL_SHIFT (8)
-+#define RQ_LOAD_HISTORY_TO_UTIL(l) (((l) >> (RQ_LOAD_HISTORY_BITS - 1 - RQ_UTIL_SHIFT)) & 0xff)
-+
-+#define LOAD_BLOCK(t) ((t) >> 17)
-+#define LOAD_HALF_BLOCK(t) ((t) >> 16)
-+#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1))
-+#define LOAD_BLOCK_BIT(b) (1UL << (RQ_LOAD_HISTORY_BITS - 1 - (b)))
-+#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0)
-+
-+static inline void rq_load_update(struct rq *rq)
-+{
-+ u64 time = rq->clock;
-+ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp),
-+ RQ_LOAD_HISTORY_BITS - 1);
-+ u64 prev = !!(rq->load_history & CURRENT_LOAD_BIT);
-+ u64 curr = !!rq->nr_running;
-+
-+ if (delta) {
-+ rq->load_history = rq->load_history >> delta;
-+
-+ if (delta < RQ_UTIL_SHIFT) {
-+ rq->load_block += (~BLOCK_MASK(rq->load_stamp)) * prev;
-+ if (!!LOAD_HALF_BLOCK(rq->load_block) ^ curr)
-+ rq->load_history ^= LOAD_BLOCK_BIT(delta);
-+ }
-+
-+ rq->load_block = BLOCK_MASK(time) * prev;
-+ } else {
-+ rq->load_block += (time - rq->load_stamp) * prev;
-+ }
-+ if (prev ^ curr)
-+ rq->load_history ^= CURRENT_LOAD_BIT;
-+ rq->load_stamp = time;
-+}
-+
-+unsigned long rq_load_util(struct rq *rq, unsigned long max)
-+{
-+ return RQ_LOAD_HISTORY_TO_UTIL(rq->load_history) * (max >> RQ_UTIL_SHIFT);
-+}
-+
-+#ifdef CONFIG_SMP
-+unsigned long sched_cpu_util(int cpu, unsigned long max)
-+{
-+ return rq_load_util(cpu_rq(cpu), max);
-+}
-+#endif /* CONFIG_SMP */
-+
-+#ifdef CONFIG_CPU_FREQ
-+/**
-+ * cpufreq_update_util - Take a note about CPU utilization changes.
-+ * @rq: Runqueue to carry out the update for.
-+ * @flags: Update reason flags.
-+ *
-+ * This function is called by the scheduler on the CPU whose utilization is
-+ * being updated.
-+ *
-+ * It can only be called from RCU-sched read-side critical sections.
-+ *
-+ * The way cpufreq is currently arranged requires it to evaluate the CPU
-+ * performance state (frequency/voltage) on a regular basis to prevent it from
-+ * being stuck in a completely inadequate performance level for too long.
-+ * That is not guaranteed to happen if the updates are only triggered from CFS
-+ * and DL, though, because they may not be coming in if only RT tasks are
-+ * active all the time (or there are RT tasks only).
-+ *
-+ * As a workaround for that issue, this function is called periodically by the
-+ * RT sched class to trigger extra cpufreq updates to prevent it from stalling,
-+ * but that really is a band-aid. Going forward it should be replaced with
-+ * solutions targeted more specifically at RT tasks.
-+ */
-+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
-+{
-+ struct update_util_data *data;
-+
-+#ifdef CONFIG_SMP
-+ rq_load_update(rq);
-+#endif
-+ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
-+ cpu_of(rq)));
-+ if (data)
-+ data->func(data, rq_clock(rq), flags);
-+}
-+#else
-+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
-+{
-+#ifdef CONFIG_SMP
-+ rq_load_update(rq);
-+#endif
-+}
-+#endif /* CONFIG_CPU_FREQ */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+/*
-+ * Tick may be needed by tasks in the runqueue depending on their policy and
-+ * requirements. If tick is needed, lets send the target an IPI to kick it out
-+ * of nohz mode if necessary.
-+ */
-+static inline void sched_update_tick_dependency(struct rq *rq)
-+{
-+ int cpu = cpu_of(rq);
-+
-+ if (!tick_nohz_full_cpu(cpu))
-+ return;
-+
-+ if (rq->nr_running < 2)
-+ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
-+ else
-+ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
-+}
-+#else /* !CONFIG_NO_HZ_FULL */
-+static inline void sched_update_tick_dependency(struct rq *rq) { }
-+#endif
-+
-+bool sched_task_on_rq(struct task_struct *p)
-+{
-+ return task_on_rq_queued(p);
-+}
-+
-+/*
-+ * Add/Remove/Requeue task to/from the runqueue routines
-+ * Context: rq->lock
-+ */
-+#define __SCHED_DEQUEUE_TASK(p, rq, flags, func) \
-+ psi_dequeue(p, flags & DEQUEUE_SLEEP); \
-+ sched_info_dequeue(rq, p); \
-+ \
-+ list_del(&p->sq_node); \
-+ if (list_empty(&rq->queue.heads[p->sq_idx])) { \
-+ clear_bit(sched_idx2prio(p->sq_idx, rq), \
-+ rq->queue.bitmap); \
-+ func; \
-+ }
-+
-+#define __SCHED_ENQUEUE_TASK(p, rq, flags) \
-+ sched_info_enqueue(rq, p); \
-+ psi_enqueue(p, flags); \
-+ \
-+ p->sq_idx = task_sched_prio_idx(p, rq); \
-+ list_add_tail(&p->sq_node, &rq->queue.heads[p->sq_idx]); \
-+ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
-+
-+static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags)
-+{
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*printk(KERN_INFO "sched: dequeue(%d) %px %016llx\n", cpu_of(rq), p, p->priodl);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: dequeue task reside on cpu%d from cpu%d\n",
-+ task_cpu(p), cpu_of(rq));
-+
-+ __SCHED_DEQUEUE_TASK(p, rq, flags, update_sched_rq_watermark(rq));
-+ --rq->nr_running;
-+#ifdef CONFIG_SMP
-+ if (1 == rq->nr_running)
-+ cpumask_clear_cpu(cpu_of(rq), &sched_rq_pending_mask);
-+#endif
-+
-+ sched_update_tick_dependency(rq);
-+}
-+
-+static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags)
-+{
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*printk(KERN_INFO "sched: enqueue(%d) %px %016llx\n", cpu_of(rq), p, p->priodl);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: enqueue task reside on cpu%d to cpu%d\n",
-+ task_cpu(p), cpu_of(rq));
-+
-+ __SCHED_ENQUEUE_TASK(p, rq, flags);
-+ update_sched_rq_watermark(rq);
-+ ++rq->nr_running;
-+#ifdef CONFIG_SMP
-+ if (2 == rq->nr_running)
-+ cpumask_set_cpu(cpu_of(rq), &sched_rq_pending_mask);
-+#endif
-+
-+ sched_update_tick_dependency(rq);
-+}
-+
-+static inline void requeue_task(struct task_struct *p, struct rq *rq)
-+{
-+ int idx;
-+
-+ lockdep_assert_held(&rq->lock);
-+ /*printk(KERN_INFO "sched: requeue(%d) %px %016llx\n", cpu_of(rq), p, p->priodl);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: cpu[%d] requeue task reside on cpu%d\n",
-+ cpu_of(rq), task_cpu(p));
-+
-+ idx = task_sched_prio_idx(p, rq);
-+
-+ list_del(&p->sq_node);
-+ list_add_tail(&p->sq_node, &rq->queue.heads[idx]);
-+ if (idx != p->sq_idx) {
-+ if (list_empty(&rq->queue.heads[p->sq_idx]))
-+ clear_bit(sched_idx2prio(p->sq_idx, rq),
-+ rq->queue.bitmap);
-+ p->sq_idx = idx;
-+ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
-+ update_sched_rq_watermark(rq);
-+ }
-+}
-+
-+/*
-+ * cmpxchg based fetch_or, macro so it works for different integer types
-+ */
-+#define fetch_or(ptr, mask) \
-+ ({ \
-+ typeof(ptr) _ptr = (ptr); \
-+ typeof(mask) _mask = (mask); \
-+ typeof(*_ptr) _old, _val = *_ptr; \
-+ \
-+ for (;;) { \
-+ _old = cmpxchg(_ptr, _val, _val | _mask); \
-+ if (_old == _val) \
-+ break; \
-+ _val = _old; \
-+ } \
-+ _old; \
-+})
-+
-+#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
-+/*
-+ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
-+ * this avoids any races wrt polling state changes and thereby avoids
-+ * spurious IPIs.
-+ */
-+static bool set_nr_and_not_polling(struct task_struct *p)
-+{
-+ struct thread_info *ti = task_thread_info(p);
-+ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
-+}
-+
-+/*
-+ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set.
-+ *
-+ * If this returns true, then the idle task promises to call
-+ * sched_ttwu_pending() and reschedule soon.
-+ */
-+static bool set_nr_if_polling(struct task_struct *p)
-+{
-+ struct thread_info *ti = task_thread_info(p);
-+ typeof(ti->flags) old, val = READ_ONCE(ti->flags);
-+
-+ for (;;) {
-+ if (!(val & _TIF_POLLING_NRFLAG))
-+ return false;
-+ if (val & _TIF_NEED_RESCHED)
-+ return true;
-+ old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED);
-+ if (old == val)
-+ break;
-+ val = old;
-+ }
-+ return true;
-+}
-+
-+#else
-+static bool set_nr_and_not_polling(struct task_struct *p)
-+{
-+ set_tsk_need_resched(p);
-+ return true;
-+}
-+
-+#ifdef CONFIG_SMP
-+static bool set_nr_if_polling(struct task_struct *p)
-+{
-+ return false;
-+}
-+#endif
-+#endif
-+
-+static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
-+{
-+ struct wake_q_node *node = &task->wake_q;
-+
-+ /*
-+ * Atomically grab the task, if ->wake_q is !nil already it means
-+ * it's already queued (either by us or someone else) and will get the
-+ * wakeup due to that.
-+ *
-+ * In order to ensure that a pending wakeup will observe our pending
-+ * state, even in the failed case, an explicit smp_mb() must be used.
-+ */
-+ smp_mb__before_atomic();
-+ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))
-+ return false;
-+
-+ /*
-+ * The head is context local, there can be no concurrency.
-+ */
-+ *head->lastp = node;
-+ head->lastp = &node->next;
-+ return true;
-+}
-+
-+/**
-+ * wake_q_add() - queue a wakeup for 'later' waking.
-+ * @head: the wake_q_head to add @task to
-+ * @task: the task to queue for 'later' wakeup
-+ *
-+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
-+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
-+ * instantly.
-+ *
-+ * This function must be used as-if it were wake_up_process(); IOW the task
-+ * must be ready to be woken at this location.
-+ */
-+void wake_q_add(struct wake_q_head *head, struct task_struct *task)
-+{
-+ if (__wake_q_add(head, task))
-+ get_task_struct(task);
-+}
-+
-+/**
-+ * wake_q_add_safe() - safely queue a wakeup for 'later' waking.
-+ * @head: the wake_q_head to add @task to
-+ * @task: the task to queue for 'later' wakeup
-+ *
-+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
-+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
-+ * instantly.
-+ *
-+ * This function must be used as-if it were wake_up_process(); IOW the task
-+ * must be ready to be woken at this location.
-+ *
-+ * This function is essentially a task-safe equivalent to wake_q_add(). Callers
-+ * that already hold reference to @task can call the 'safe' version and trust
-+ * wake_q to do the right thing depending whether or not the @task is already
-+ * queued for wakeup.
-+ */
-+void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
-+{
-+ if (!__wake_q_add(head, task))
-+ put_task_struct(task);
-+}
-+
-+void wake_up_q(struct wake_q_head *head)
-+{
-+ struct wake_q_node *node = head->first;
-+
-+ while (node != WAKE_Q_TAIL) {
-+ struct task_struct *task;
-+
-+ task = container_of(node, struct task_struct, wake_q);
-+ /* task can safely be re-inserted now: */
-+ node = node->next;
-+ task->wake_q.next = NULL;
-+
-+ /*
-+ * wake_up_process() executes a full barrier, which pairs with
-+ * the queueing in wake_q_add() so as not to miss wakeups.
-+ */
-+ wake_up_process(task);
-+ put_task_struct(task);
-+ }
-+}
-+
-+/*
-+ * resched_curr - mark rq's current task 'to be rescheduled now'.
-+ *
-+ * On UP this means the setting of the need_resched flag, on SMP it
-+ * might also involve a cross-CPU call to trigger the scheduler on
-+ * the target CPU.
-+ */
-+void resched_curr(struct rq *rq)
-+{
-+ struct task_struct *curr = rq->curr;
-+ int cpu;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ if (test_tsk_need_resched(curr))
-+ return;
-+
-+ cpu = cpu_of(rq);
-+ if (cpu == smp_processor_id()) {
-+ set_tsk_need_resched(curr);
-+ set_preempt_need_resched();
-+ return;
-+ }
-+
-+ if (set_nr_and_not_polling(curr))
-+ smp_send_reschedule(cpu);
-+ else
-+ trace_sched_wake_idle_without_ipi(cpu);
-+}
-+
-+void resched_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ if (cpu_online(cpu) || cpu == smp_processor_id())
-+ resched_curr(cpu_rq(cpu));
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+}
-+
-+#ifdef CONFIG_SMP
-+#ifdef CONFIG_NO_HZ_COMMON
-+void nohz_balance_enter_idle(int cpu) {}
-+
-+void select_nohz_load_balancer(int stop_tick) {}
-+
-+void set_cpu_sd_state_idle(void) {}
-+
-+/*
-+ * In the semi idle case, use the nearest busy CPU for migrating timers
-+ * from an idle CPU. This is good for power-savings.
-+ *
-+ * We don't do similar optimization for completely idle system, as
-+ * selecting an idle CPU will add more delays to the timers than intended
-+ * (as that CPU's timer base may not be uptodate wrt jiffies etc).
-+ */
-+int get_nohz_timer_target(void)
-+{
-+ int i, cpu = smp_processor_id(), default_cpu = -1;
-+ struct cpumask *mask;
-+ const struct cpumask *hk_mask;
-+
-+ if (housekeeping_cpu(cpu, HK_FLAG_TIMER)) {
-+ if (!idle_cpu(cpu))
-+ return cpu;
-+ default_cpu = cpu;
-+ }
-+
-+ hk_mask = housekeeping_cpumask(HK_FLAG_TIMER);
-+
-+ for (mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+ mask < per_cpu(sched_cpu_topo_end_mask, cpu); mask++)
-+ for_each_cpu_and(i, mask, hk_mask)
-+ if (!idle_cpu(i))
-+ return i;
-+
-+ if (default_cpu == -1)
-+ default_cpu = housekeeping_any_cpu(HK_FLAG_TIMER);
-+ cpu = default_cpu;
-+
-+ return cpu;
-+}
-+
-+/*
-+ * When add_timer_on() enqueues a timer into the timer wheel of an
-+ * idle CPU then this timer might expire before the next timer event
-+ * which is scheduled to wake up that CPU. In case of a completely
-+ * idle system the next event might even be infinite time into the
-+ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
-+ * leaves the inner idle loop so the newly added timer is taken into
-+ * account when the CPU goes back to idle and evaluates the timer
-+ * wheel for the next timer event.
-+ */
-+static inline void wake_up_idle_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (cpu == smp_processor_id())
-+ return;
-+
-+ if (set_nr_and_not_polling(rq->idle))
-+ smp_send_reschedule(cpu);
-+ else
-+ trace_sched_wake_idle_without_ipi(cpu);
-+}
-+
-+static inline bool wake_up_full_nohz_cpu(int cpu)
-+{
-+ /*
-+ * We just need the target to call irq_exit() and re-evaluate
-+ * the next tick. The nohz full kick at least implies that.
-+ * If needed we can still optimize that later with an
-+ * empty IRQ.
-+ */
-+ if (cpu_is_offline(cpu))
-+ return true; /* Don't try to wake offline CPUs. */
-+ if (tick_nohz_full_cpu(cpu)) {
-+ if (cpu != smp_processor_id() ||
-+ tick_nohz_tick_stopped())
-+ tick_nohz_full_kick_cpu(cpu);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void wake_up_nohz_cpu(int cpu)
-+{
-+ if (!wake_up_full_nohz_cpu(cpu))
-+ wake_up_idle_cpu(cpu);
-+}
-+
-+static void nohz_csd_func(void *info)
-+{
-+ struct rq *rq = info;
-+ int cpu = cpu_of(rq);
-+ unsigned int flags;
-+
-+ /*
-+ * Release the rq::nohz_csd.
-+ */
-+ flags = atomic_fetch_andnot(NOHZ_KICK_MASK, nohz_flags(cpu));
-+ WARN_ON(!(flags & NOHZ_KICK_MASK));
-+
-+ rq->idle_balance = idle_cpu(cpu);
-+ if (rq->idle_balance && !need_resched()) {
-+ rq->nohz_idle_balance = flags;
-+ raise_softirq_irqoff(SCHED_SOFTIRQ);
-+ }
-+}
-+
-+#endif /* CONFIG_NO_HZ_COMMON */
-+#endif /* CONFIG_SMP */
-+
-+static inline void check_preempt_curr(struct rq *rq)
-+{
-+ if (sched_rq_first_task(rq) != rq->curr)
-+ resched_curr(rq);
-+}
-+
-+#ifdef CONFIG_SCHED_HRTICK
-+/*
-+ * Use HR-timers to deliver accurate preemption points.
-+ */
-+
-+static void hrtick_clear(struct rq *rq)
-+{
-+ if (hrtimer_active(&rq->hrtick_timer))
-+ hrtimer_cancel(&rq->hrtick_timer);
-+}
-+
-+/*
-+ * High-resolution timer tick.
-+ * Runs from hardirq context with interrupts disabled.
-+ */
-+static enum hrtimer_restart hrtick(struct hrtimer *timer)
-+{
-+ struct rq *rq = container_of(timer, struct rq, hrtick_timer);
-+
-+ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id());
-+
-+ raw_spin_lock(&rq->lock);
-+ resched_curr(rq);
-+ raw_spin_unlock(&rq->lock);
-+
-+ return HRTIMER_NORESTART;
-+}
-+
-+/*
-+ * Use hrtick when:
-+ * - enabled by features
-+ * - hrtimer is actually high res
-+ */
-+static inline int hrtick_enabled(struct rq *rq)
-+{
-+ /**
-+ * Alt schedule FW doesn't support sched_feat yet
-+ if (!sched_feat(HRTICK))
-+ return 0;
-+ */
-+ if (!cpu_active(cpu_of(rq)))
-+ return 0;
-+ return hrtimer_is_hres_active(&rq->hrtick_timer);
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+static void __hrtick_restart(struct rq *rq)
-+{
-+ struct hrtimer *timer = &rq->hrtick_timer;
-+ ktime_t time = rq->hrtick_time;
-+
-+ hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD);
-+}
-+
-+/*
-+ * called from hardirq (IPI) context
-+ */
-+static void __hrtick_start(void *arg)
-+{
-+ struct rq *rq = arg;
-+
-+ raw_spin_lock(&rq->lock);
-+ __hrtick_restart(rq);
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+/*
-+ * Called to set the hrtick timer state.
-+ *
-+ * called with rq->lock held and irqs disabled
-+ */
-+void hrtick_start(struct rq *rq, u64 delay)
-+{
-+ struct hrtimer *timer = &rq->hrtick_timer;
-+ s64 delta;
-+
-+ /*
-+ * Don't schedule slices shorter than 10000ns, that just
-+ * doesn't make sense and can cause timer DoS.
-+ */
-+ delta = max_t(s64, delay, 10000LL);
-+
-+ rq->hrtick_time = ktime_add_ns(timer->base->get_time(), delta);
-+
-+ if (rq == this_rq())
-+ __hrtick_restart(rq);
-+ else
-+ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd);
-+}
-+
-+#else
-+/*
-+ * Called to set the hrtick timer state.
-+ *
-+ * called with rq->lock held and irqs disabled
-+ */
-+void hrtick_start(struct rq *rq, u64 delay)
-+{
-+ /*
-+ * Don't schedule slices shorter than 10000ns, that just
-+ * doesn't make sense. Rely on vruntime for fairness.
-+ */
-+ delay = max_t(u64, delay, 10000LL);
-+ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay),
-+ HRTIMER_MODE_REL_PINNED_HARD);
-+}
-+#endif /* CONFIG_SMP */
-+
-+static void hrtick_rq_init(struct rq *rq)
-+{
-+#ifdef CONFIG_SMP
-+ INIT_CSD(&rq->hrtick_csd, __hrtick_start, rq);
-+#endif
-+
-+ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
-+ rq->hrtick_timer.function = hrtick;
-+}
-+#else /* CONFIG_SCHED_HRTICK */
-+static inline int hrtick_enabled(struct rq *rq)
-+{
-+ return 0;
-+}
-+
-+static inline void hrtick_clear(struct rq *rq)
-+{
-+}
-+
-+static inline void hrtick_rq_init(struct rq *rq)
-+{
-+}
-+#endif /* CONFIG_SCHED_HRTICK */
-+
-+static inline int __normal_prio(int policy, int rt_prio, int static_prio)
-+{
-+ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) :
-+ static_prio + MAX_PRIORITY_ADJ;
-+}
-+
-+/*
-+ * Calculate the expected normal priority: i.e. priority
-+ * without taking RT-inheritance into account. Might be
-+ * boosted by interactivity modifiers. Changes upon fork,
-+ * setprio syscalls, and whenever the interactivity
-+ * estimator recalculates.
-+ */
-+static inline int normal_prio(struct task_struct *p)
-+{
-+ return __normal_prio(p->policy, p->rt_priority, p->static_prio);
-+}
-+
-+/*
-+ * Calculate the current priority, i.e. the priority
-+ * taken into account by the scheduler. This value might
-+ * be boosted by RT tasks as it will be RT if the task got
-+ * RT-boosted. If not then it returns p->normal_prio.
-+ */
-+static int effective_prio(struct task_struct *p)
-+{
-+ p->normal_prio = normal_prio(p);
-+ /*
-+ * If we are RT tasks or we were boosted to RT priority,
-+ * keep the priority unchanged. Otherwise, update priority
-+ * to the normal priority:
-+ */
-+ if (!rt_prio(p->prio))
-+ return p->normal_prio;
-+ return p->prio;
-+}
-+
-+/*
-+ * activate_task - move a task to the runqueue.
-+ *
-+ * Context: rq->lock
-+ */
-+static void activate_task(struct task_struct *p, struct rq *rq)
-+{
-+ enqueue_task(p, rq, ENQUEUE_WAKEUP);
-+ p->on_rq = TASK_ON_RQ_QUEUED;
-+
-+ /*
-+ * If in_iowait is set, the code below may not trigger any cpufreq
-+ * utilization updates, so do it here explicitly with the IOWAIT flag
-+ * passed.
-+ */
-+ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait);
-+}
-+
-+/*
-+ * deactivate_task - remove a task from the runqueue.
-+ *
-+ * Context: rq->lock
-+ */
-+static inline void deactivate_task(struct task_struct *p, struct rq *rq)
-+{
-+ dequeue_task(p, rq, DEQUEUE_SLEEP);
-+ p->on_rq = 0;
-+ cpufreq_update_util(rq, 0);
-+}
-+
-+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
-+{
-+#ifdef CONFIG_SMP
-+ /*
-+ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be
-+ * successfully executed on another CPU. We must ensure that updates of
-+ * per-task data have been completed by this moment.
-+ */
-+ smp_wmb();
-+
-+#ifdef CONFIG_THREAD_INFO_IN_TASK
-+ WRITE_ONCE(p->cpu, cpu);
-+#else
-+ WRITE_ONCE(task_thread_info(p)->cpu, cpu);
-+#endif
-+#endif
-+}
-+
-+static inline bool is_migration_disabled(struct task_struct *p)
-+{
-+#ifdef CONFIG_SMP
-+ return p->migration_disabled;
-+#else
-+ return false;
-+#endif
-+}
-+
-+#define SCA_CHECK 0x01
-+#define SCA_USER 0x08
-+
-+#ifdef CONFIG_SMP
-+
-+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
-+{
-+#ifdef CONFIG_SCHED_DEBUG
-+ unsigned int state = READ_ONCE(p->__state);
-+
-+ /*
-+ * We should never call set_task_cpu() on a blocked task,
-+ * ttwu() will sort out the placement.
-+ */
-+ WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq);
-+
-+#ifdef CONFIG_LOCKDEP
-+ /*
-+ * The caller should hold either p->pi_lock or rq->lock, when changing
-+ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
-+ *
-+ * sched_move_task() holds both and thus holding either pins the cgroup,
-+ * see task_group().
-+ */
-+ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
-+ lockdep_is_held(&task_rq(p)->lock)));
-+#endif
-+ /*
-+ * Clearly, migrating tasks to offline CPUs is a fairly daft thing.
-+ */
-+ WARN_ON_ONCE(!cpu_online(new_cpu));
-+
-+ WARN_ON_ONCE(is_migration_disabled(p));
-+#endif
-+ if (task_cpu(p) == new_cpu)
-+ return;
-+ trace_sched_migrate_task(p, new_cpu);
-+ rseq_migrate(p);
-+ perf_event_task_migrate(p);
-+
-+ __set_task_cpu(p, new_cpu);
-+}
-+
-+#define MDF_FORCE_ENABLED 0x80
-+
-+static void
-+__do_set_cpus_ptr(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ /*
-+ * This here violates the locking rules for affinity, since we're only
-+ * supposed to change these variables while holding both rq->lock and
-+ * p->pi_lock.
-+ *
-+ * HOWEVER, it magically works, because ttwu() is the only code that
-+ * accesses these variables under p->pi_lock and only does so after
-+ * smp_cond_load_acquire(&p->on_cpu, !VAL), and we're in __schedule()
-+ * before finish_task().
-+ *
-+ * XXX do further audits, this smells like something putrid.
-+ */
-+ SCHED_WARN_ON(!p->on_cpu);
-+ p->cpus_ptr = new_mask;
-+}
-+
-+void migrate_disable(void)
-+{
-+ struct task_struct *p = current;
-+ int cpu;
-+
-+ if (p->migration_disabled) {
-+ p->migration_disabled++;
-+ return;
-+ }
-+
-+ preempt_disable();
-+ cpu = smp_processor_id();
-+ if (cpumask_test_cpu(cpu, &p->cpus_mask)) {
-+ cpu_rq(cpu)->nr_pinned++;
-+ p->migration_disabled = 1;
-+ p->migration_flags &= ~MDF_FORCE_ENABLED;
-+
-+ /*
-+ * Violates locking rules! see comment in __do_set_cpus_ptr().
-+ */
-+ if (p->cpus_ptr == &p->cpus_mask)
-+ __do_set_cpus_ptr(p, cpumask_of(cpu));
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(migrate_disable);
-+
-+void migrate_enable(void)
-+{
-+ struct task_struct *p = current;
-+
-+ if (0 == p->migration_disabled)
-+ return;
-+
-+ if (p->migration_disabled > 1) {
-+ p->migration_disabled--;
-+ return;
-+ }
-+
-+ /*
-+ * Ensure stop_task runs either before or after this, and that
-+ * __set_cpus_allowed_ptr(SCA_MIGRATE_ENABLE) doesn't schedule().
-+ */
-+ preempt_disable();
-+ /*
-+ * Assumption: current should be running on allowed cpu
-+ */
-+ WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &p->cpus_mask));
-+ if (p->cpus_ptr != &p->cpus_mask)
-+ __do_set_cpus_ptr(p, &p->cpus_mask);
-+ /*
-+ * Mustn't clear migration_disabled() until cpus_ptr points back at the
-+ * regular cpus_mask, otherwise things that race (eg.
-+ * select_fallback_rq) get confused.
-+ */
-+ barrier();
-+ p->migration_disabled = 0;
-+ this_rq()->nr_pinned--;
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(migrate_enable);
-+
-+static inline bool rq_has_pinned_tasks(struct rq *rq)
-+{
-+ return rq->nr_pinned;
-+}
-+
-+/*
-+ * Per-CPU kthreads are allowed to run on !active && online CPUs, see
-+ * __set_cpus_allowed_ptr() and select_fallback_rq().
-+ */
-+static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
-+{
-+ /* When not in the task's cpumask, no point in looking further. */
-+ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
-+ return false;
-+
-+ /* migrate_disabled() must be allowed to finish. */
-+ if (is_migration_disabled(p))
-+ return cpu_online(cpu);
-+
-+ /* Non kernel threads are not allowed during either online or offline. */
-+ if (!(p->flags & PF_KTHREAD))
-+ return cpu_active(cpu) && task_cpu_possible(cpu, p);
-+
-+ /* KTHREAD_IS_PER_CPU is always allowed. */
-+ if (kthread_is_per_cpu(p))
-+ return cpu_online(cpu);
-+
-+ /* Regular kernel threads don't get to stay during offline. */
-+ if (cpu_dying(cpu))
-+ return false;
-+
-+ /* But are allowed during online. */
-+ return cpu_online(cpu);
-+}
-+
-+/*
-+ * This is how migration works:
-+ *
-+ * 1) we invoke migration_cpu_stop() on the target CPU using
-+ * stop_one_cpu().
-+ * 2) stopper starts to run (implicitly forcing the migrated thread
-+ * off the CPU)
-+ * 3) it checks whether the migrated task is still in the wrong runqueue.
-+ * 4) if it's in the wrong runqueue then the migration thread removes
-+ * it and puts it into the right queue.
-+ * 5) stopper completes and stop_one_cpu() returns and the migration
-+ * is done.
-+ */
-+
-+/*
-+ * move_queued_task - move a queued task to new rq.
-+ *
-+ * Returns (locked) new rq. Old rq's lock is released.
-+ */
-+static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int
-+ new_cpu)
-+{
-+ lockdep_assert_held(&rq->lock);
-+
-+ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING);
-+ dequeue_task(p, rq, 0);
-+ set_task_cpu(p, new_cpu);
-+ raw_spin_unlock(&rq->lock);
-+
-+ rq = cpu_rq(new_cpu);
-+
-+ raw_spin_lock(&rq->lock);
-+ BUG_ON(task_cpu(p) != new_cpu);
-+ sched_task_sanity_check(p, rq);
-+ enqueue_task(p, rq, 0);
-+ p->on_rq = TASK_ON_RQ_QUEUED;
-+ check_preempt_curr(rq);
-+
-+ return rq;
-+}
-+
-+struct migration_arg {
-+ struct task_struct *task;
-+ int dest_cpu;
-+};
-+
-+/*
-+ * Move (not current) task off this CPU, onto the destination CPU. We're doing
-+ * this because either it can't run here any more (set_cpus_allowed()
-+ * away from this CPU, or CPU going down), or because we're
-+ * attempting to rebalance this task on exec (sched_exec).
-+ *
-+ * So we race with normal scheduler movements, but that's OK, as long
-+ * as the task is no longer on this CPU.
-+ */
-+static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int
-+ dest_cpu)
-+{
-+ /* Affinity changed (again). */
-+ if (!is_cpu_allowed(p, dest_cpu))
-+ return rq;
-+
-+ update_rq_clock(rq);
-+ return move_queued_task(rq, p, dest_cpu);
-+}
-+
-+/*
-+ * migration_cpu_stop - this will be executed by a highprio stopper thread
-+ * and performs thread migration by bumping thread off CPU then
-+ * 'pushing' onto another runqueue.
-+ */
-+static int migration_cpu_stop(void *data)
-+{
-+ struct migration_arg *arg = data;
-+ struct task_struct *p = arg->task;
-+ struct rq *rq = this_rq();
-+ unsigned long flags;
-+
-+ /*
-+ * The original target CPU might have gone down and we might
-+ * be on another CPU but it doesn't matter.
-+ */
-+ local_irq_save(flags);
-+ /*
-+ * We need to explicitly wake pending tasks before running
-+ * __migrate_task() such that we will not miss enforcing cpus_ptr
-+ * during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
-+ */
-+ flush_smp_call_function_from_idle();
-+
-+ raw_spin_lock(&p->pi_lock);
-+ raw_spin_lock(&rq->lock);
-+ /*
-+ * If task_rq(p) != rq, it cannot be migrated here, because we're
-+ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
-+ * we're holding p->pi_lock.
-+ */
-+ if (task_rq(p) == rq && task_on_rq_queued(p))
-+ rq = __migrate_task(rq, p, arg->dest_cpu);
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+
-+ return 0;
-+}
-+
-+static inline void
-+set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ cpumask_copy(&p->cpus_mask, new_mask);
-+ p->nr_cpus_allowed = cpumask_weight(new_mask);
-+}
-+
-+static void
-+__do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ lockdep_assert_held(&p->pi_lock);
-+ set_cpus_allowed_common(p, new_mask);
-+}
-+
-+void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ __do_set_cpus_allowed(p, new_mask);
-+}
-+
-+int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
-+ int node)
-+{
-+ if (!src->user_cpus_ptr)
-+ return 0;
-+
-+ dst->user_cpus_ptr = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
-+ if (!dst->user_cpus_ptr)
-+ return -ENOMEM;
-+
-+ cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
-+ return 0;
-+}
-+
-+static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
-+{
-+ struct cpumask *user_mask = NULL;
-+
-+ swap(p->user_cpus_ptr, user_mask);
-+
-+ return user_mask;
-+}
-+
-+void release_user_cpus_ptr(struct task_struct *p)
-+{
-+ kfree(clear_user_cpus_ptr(p));
-+}
-+
-+#endif
-+
-+/**
-+ * task_curr - is this task currently executing on a CPU?
-+ * @p: the task in question.
-+ *
-+ * Return: 1 if the task is currently executing. 0 otherwise.
-+ */
-+inline int task_curr(const struct task_struct *p)
-+{
-+ return cpu_curr(task_cpu(p)) == p;
-+}
-+
-+#ifdef CONFIG_SMP
-+/*
-+ * wait_task_inactive - wait for a thread to unschedule.
-+ *
-+ * If @match_state is nonzero, it's the @p->state value just checked and
-+ * not expected to change. If it changes, i.e. @p might have woken up,
-+ * then return zero. When we succeed in waiting for @p to be off its CPU,
-+ * we return a positive number (its total switch count). If a second call
-+ * a short while later returns the same number, the caller can be sure that
-+ * @p has remained unscheduled the whole time.
-+ *
-+ * The caller must ensure that the task *will* unschedule sometime soon,
-+ * else this function might spin for a *long* time. This function can't
-+ * be called with interrupts off, or it may introduce deadlock with
-+ * smp_call_function() if an IPI is sent by the same process we are
-+ * waiting to become inactive.
-+ */
-+unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state)
-+{
-+ unsigned long flags;
-+ bool running, on_rq;
-+ unsigned long ncsw;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ for (;;) {
-+ rq = task_rq(p);
-+
-+ /*
-+ * If the task is actively running on another CPU
-+ * still, just relax and busy-wait without holding
-+ * any locks.
-+ *
-+ * NOTE! Since we don't hold any locks, it's not
-+ * even sure that "rq" stays as the right runqueue!
-+ * But we don't care, since this will return false
-+ * if the runqueue has changed and p is actually now
-+ * running somewhere else!
-+ */
-+ while (task_running(p) && p == rq->curr) {
-+ if (match_state && unlikely(READ_ONCE(p->__state) != match_state))
-+ return 0;
-+ cpu_relax();
-+ }
-+
-+ /*
-+ * Ok, time to look more closely! We need the rq
-+ * lock now, to be *sure*. If we're wrong, we'll
-+ * just go back and repeat.
-+ */
-+ task_access_lock_irqsave(p, &lock, &flags);
-+ trace_sched_wait_task(p);
-+ running = task_running(p);
-+ on_rq = p->on_rq;
-+ ncsw = 0;
-+ if (!match_state || READ_ONCE(p->__state) == match_state)
-+ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
-+ task_access_unlock_irqrestore(p, lock, &flags);
-+
-+ /*
-+ * If it changed from the expected state, bail out now.
-+ */
-+ if (unlikely(!ncsw))
-+ break;
-+
-+ /*
-+ * Was it really running after all now that we
-+ * checked with the proper locks actually held?
-+ *
-+ * Oops. Go back and try again..
-+ */
-+ if (unlikely(running)) {
-+ cpu_relax();
-+ continue;
-+ }
-+
-+ /*
-+ * It's not enough that it's not actively running,
-+ * it must be off the runqueue _entirely_, and not
-+ * preempted!
-+ *
-+ * So if it was still runnable (but just not actively
-+ * running right now), it's preempted, and we should
-+ * yield - it could be a while.
-+ */
-+ if (unlikely(on_rq)) {
-+ ktime_t to = NSEC_PER_SEC / HZ;
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_hrtimeout(&to, HRTIMER_MODE_REL);
-+ continue;
-+ }
-+
-+ /*
-+ * Ahh, all good. It wasn't running, and it wasn't
-+ * runnable, which means that it will never become
-+ * running in the future either. We're all done!
-+ */
-+ break;
-+ }
-+
-+ return ncsw;
-+}
-+
-+/***
-+ * kick_process - kick a running thread to enter/exit the kernel
-+ * @p: the to-be-kicked thread
-+ *
-+ * Cause a process which is running on another CPU to enter
-+ * kernel-mode, without any delay. (to get signals handled.)
-+ *
-+ * NOTE: this function doesn't have to take the runqueue lock,
-+ * because all it wants to ensure is that the remote task enters
-+ * the kernel. If the IPI races and the task has been migrated
-+ * to another CPU then no harm is done and the purpose has been
-+ * achieved as well.
-+ */
-+void kick_process(struct task_struct *p)
-+{
-+ int cpu;
-+
-+ preempt_disable();
-+ cpu = task_cpu(p);
-+ if ((cpu != smp_processor_id()) && task_curr(p))
-+ smp_send_reschedule(cpu);
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(kick_process);
-+
-+/*
-+ * ->cpus_ptr is protected by both rq->lock and p->pi_lock
-+ *
-+ * A few notes on cpu_active vs cpu_online:
-+ *
-+ * - cpu_active must be a subset of cpu_online
-+ *
-+ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU,
-+ * see __set_cpus_allowed_ptr(). At this point the newly online
-+ * CPU isn't yet part of the sched domains, and balancing will not
-+ * see it.
-+ *
-+ * - on cpu-down we clear cpu_active() to mask the sched domains and
-+ * avoid the load balancer to place new tasks on the to be removed
-+ * CPU. Existing tasks will remain running there and will be taken
-+ * off.
-+ *
-+ * This means that fallback selection must not select !active CPUs.
-+ * And can assume that any active CPU must be online. Conversely
-+ * select_task_rq() below may allow selection of !active CPUs in order
-+ * to satisfy the above rules.
-+ */
-+static int select_fallback_rq(int cpu, struct task_struct *p)
-+{
-+ int nid = cpu_to_node(cpu);
-+ const struct cpumask *nodemask = NULL;
-+ enum { cpuset, possible, fail } state = cpuset;
-+ int dest_cpu;
-+
-+ /*
-+ * If the node that the CPU is on has been offlined, cpu_to_node()
-+ * will return -1. There is no CPU on the node, and we should
-+ * select the CPU on the other node.
-+ */
-+ if (nid != -1) {
-+ nodemask = cpumask_of_node(nid);
-+
-+ /* Look for allowed, online CPU in same node. */
-+ for_each_cpu(dest_cpu, nodemask) {
-+ if (is_cpu_allowed(p, dest_cpu))
-+ return dest_cpu;
-+ }
-+ }
-+
-+ for (;;) {
-+ /* Any allowed, online CPU? */
-+ for_each_cpu(dest_cpu, p->cpus_ptr) {
-+ if (!is_cpu_allowed(p, dest_cpu))
-+ continue;
-+ goto out;
-+ }
-+
-+ /* No more Mr. Nice Guy. */
-+ switch (state) {
-+ case cpuset:
-+ if (cpuset_cpus_allowed_fallback(p)) {
-+ state = possible;
-+ break;
-+ }
-+ fallthrough;
-+ case possible:
-+ /*
-+ * XXX When called from select_task_rq() we only
-+ * hold p->pi_lock and again violate locking order.
-+ *
-+ * More yuck to audit.
-+ */
-+ do_set_cpus_allowed(p, task_cpu_possible_mask(p));
-+ state = fail;
-+ break;
-+
-+ case fail:
-+ BUG();
-+ break;
-+ }
-+ }
-+
-+out:
-+ if (state != cpuset) {
-+ /*
-+ * Don't tell them about moving exiting tasks or
-+ * kernel threads (both mm NULL), since they never
-+ * leave kernel.
-+ */
-+ if (p->mm && printk_ratelimit()) {
-+ printk_deferred("process %d (%s) no longer affine to cpu%d\n",
-+ task_pid_nr(p), p->comm, cpu);
-+ }
-+ }
-+
-+ return dest_cpu;
-+}
-+
-+static inline int select_task_rq(struct task_struct *p)
-+{
-+ cpumask_t chk_mask, tmp;
-+
-+ if (unlikely(!cpumask_and(&chk_mask, p->cpus_ptr, cpu_active_mask)))
-+ return select_fallback_rq(task_cpu(p), p);
-+
-+ if (
-+#ifdef CONFIG_SCHED_SMT
-+ cpumask_and(&tmp, &chk_mask, &sched_sg_idle_mask) ||
-+#endif
-+ cpumask_and(&tmp, &chk_mask, sched_rq_watermark) ||
-+ cpumask_and(&tmp, &chk_mask,
-+ sched_rq_watermark + SCHED_BITS - task_sched_prio(p)))
-+ return best_mask_cpu(task_cpu(p), &tmp);
-+
-+ return best_mask_cpu(task_cpu(p), &chk_mask);
-+}
-+
-+void sched_set_stop_task(int cpu, struct task_struct *stop)
-+{
-+ static struct lock_class_key stop_pi_lock;
-+ struct sched_param stop_param = { .sched_priority = STOP_PRIO };
-+ struct sched_param start_param = { .sched_priority = 0 };
-+ struct task_struct *old_stop = cpu_rq(cpu)->stop;
-+
-+ if (stop) {
-+ /*
-+ * Make it appear like a SCHED_FIFO task, its something
-+ * userspace knows about and won't get confused about.
-+ *
-+ * Also, it will make PI more or less work without too
-+ * much confusion -- but then, stop work should not
-+ * rely on PI working anyway.
-+ */
-+ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param);
-+
-+ /*
-+ * The PI code calls rt_mutex_setprio() with ->pi_lock held to
-+ * adjust the effective priority of a task. As a result,
-+ * rt_mutex_setprio() can trigger (RT) balancing operations,
-+ * which can then trigger wakeups of the stop thread to push
-+ * around the current task.
-+ *
-+ * The stop task itself will never be part of the PI-chain, it
-+ * never blocks, therefore that ->pi_lock recursion is safe.
-+ * Tell lockdep about this by placing the stop->pi_lock in its
-+ * own class.
-+ */
-+ lockdep_set_class(&stop->pi_lock, &stop_pi_lock);
-+ }
-+
-+ cpu_rq(cpu)->stop = stop;
-+
-+ if (old_stop) {
-+ /*
-+ * Reset it back to a normal scheduling policy so that
-+ * it can die in pieces.
-+ */
-+ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param);
-+ }
-+}
-+
-+static int affine_move_task(struct rq *rq, struct task_struct *p, int dest_cpu,
-+ raw_spinlock_t *lock, unsigned long irq_flags)
-+{
-+ /* Can the task run on the task's current CPU? If so, we're done */
-+ if (!cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
-+ if (p->migration_disabled) {
-+ if (likely(p->cpus_ptr != &p->cpus_mask))
-+ __do_set_cpus_ptr(p, &p->cpus_mask);
-+ p->migration_disabled = 0;
-+ p->migration_flags |= MDF_FORCE_ENABLED;
-+ /* When p is migrate_disabled, rq->lock should be held */
-+ rq->nr_pinned--;
-+ }
-+
-+ if (task_running(p) || READ_ONCE(p->__state) == TASK_WAKING) {
-+ struct migration_arg arg = { p, dest_cpu };
-+
-+ /* Need help from migration thread: drop lock and wait. */
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
-+ return 0;
-+ }
-+ if (task_on_rq_queued(p)) {
-+ /*
-+ * OK, since we're going to drop the lock immediately
-+ * afterwards anyway.
-+ */
-+ update_rq_clock(rq);
-+ rq = move_queued_task(rq, p, dest_cpu);
-+ lock = &rq->lock;
-+ }
-+ }
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ return 0;
-+}
-+
-+static int __set_cpus_allowed_ptr_locked(struct task_struct *p,
-+ const struct cpumask *new_mask,
-+ u32 flags,
-+ struct rq *rq,
-+ raw_spinlock_t *lock,
-+ unsigned long irq_flags)
-+{
-+ const struct cpumask *cpu_allowed_mask = task_cpu_possible_mask(p);
-+ const struct cpumask *cpu_valid_mask = cpu_active_mask;
-+ bool kthread = p->flags & PF_KTHREAD;
-+ struct cpumask *user_mask = NULL;
-+ int dest_cpu;
-+ int ret = 0;
-+
-+ if (kthread || is_migration_disabled(p)) {
-+ /*
-+ * Kernel threads are allowed on online && !active CPUs,
-+ * however, during cpu-hot-unplug, even these might get pushed
-+ * away if not KTHREAD_IS_PER_CPU.
-+ *
-+ * Specifically, migration_disabled() tasks must not fail the
-+ * cpumask_any_and_distribute() pick below, esp. so on
-+ * SCA_MIGRATE_ENABLE, otherwise we'll not call
-+ * set_cpus_allowed_common() and actually reset p->cpus_ptr.
-+ */
-+ cpu_valid_mask = cpu_online_mask;
-+ }
-+
-+ if (!kthread && !cpumask_subset(new_mask, cpu_allowed_mask)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ /*
-+ * Must re-check here, to close a race against __kthread_bind(),
-+ * sched_setaffinity() is not guaranteed to observe the flag.
-+ */
-+ if ((flags & SCA_CHECK) && (p->flags & PF_NO_SETAFFINITY)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (cpumask_equal(&p->cpus_mask, new_mask))
-+ goto out;
-+
-+ dest_cpu = cpumask_any_and(cpu_valid_mask, new_mask);
-+ if (dest_cpu >= nr_cpu_ids) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ __do_set_cpus_allowed(p, new_mask);
-+
-+ if (flags & SCA_USER)
-+ user_mask = clear_user_cpus_ptr(p);
-+
-+ ret = affine_move_task(rq, p, dest_cpu, lock, irq_flags);
-+
-+ kfree(user_mask);
-+
-+ return ret;
-+
-+out:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Change a given task's CPU affinity. Migrate the thread to a
-+ * proper CPU and schedule it away if the CPU it's executing on
-+ * is removed from the allowed bitmask.
-+ *
-+ * NOTE: the caller must have a valid reference to the task, the
-+ * task must not exit() & deallocate itself prematurely. The
-+ * call is not atomic; no spinlocks may be held.
-+ */
-+static int __set_cpus_allowed_ptr(struct task_struct *p,
-+ const struct cpumask *new_mask, u32 flags)
-+{
-+ unsigned long irq_flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
-+ rq = __task_access_lock(p, &lock);
-+
-+ return __set_cpus_allowed_ptr_locked(p, new_mask, flags, rq, lock, irq_flags);
-+}
-+
-+int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ return __set_cpus_allowed_ptr(p, new_mask, 0);
-+}
-+EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
-+
-+/*
-+ * Change a given task's CPU affinity to the intersection of its current
-+ * affinity mask and @subset_mask, writing the resulting mask to @new_mask
-+ * and pointing @p->user_cpus_ptr to a copy of the old mask.
-+ * If the resulting mask is empty, leave the affinity unchanged and return
-+ * -EINVAL.
-+ */
-+static int restrict_cpus_allowed_ptr(struct task_struct *p,
-+ struct cpumask *new_mask,
-+ const struct cpumask *subset_mask)
-+{
-+ struct cpumask *user_mask = NULL;
-+ unsigned long irq_flags;
-+ raw_spinlock_t *lock;
-+ struct rq *rq;
-+ int err;
-+
-+ if (!p->user_cpus_ptr) {
-+ user_mask = kmalloc(cpumask_size(), GFP_KERNEL);
-+ if (!user_mask)
-+ return -ENOMEM;
-+ }
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
-+ rq = __task_access_lock(p, &lock);
-+
-+ if (!cpumask_and(new_mask, &p->cpus_mask, subset_mask)) {
-+ err = -EINVAL;
-+ goto err_unlock;
-+ }
-+
-+ /*
-+ * We're about to butcher the task affinity, so keep track of what
-+ * the user asked for in case we're able to restore it later on.
-+ */
-+ if (user_mask) {
-+ cpumask_copy(user_mask, p->cpus_ptr);
-+ p->user_cpus_ptr = user_mask;
-+ }
-+
-+ /*return __set_cpus_allowed_ptr_locked(p, new_mask, 0, rq, &rf);*/
-+ return __set_cpus_allowed_ptr_locked(p, new_mask, 0, rq, lock, irq_flags);
-+
-+err_unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ kfree(user_mask);
-+ return err;
-+}
-+
-+/*
-+ * Restrict the CPU affinity of task @p so that it is a subset of
-+ * task_cpu_possible_mask() and point @p->user_cpu_ptr to a copy of the
-+ * old affinity mask. If the resulting mask is empty, we warn and walk
-+ * up the cpuset hierarchy until we find a suitable mask.
-+ */
-+void force_compatible_cpus_allowed_ptr(struct task_struct *p)
-+{
-+ cpumask_var_t new_mask;
-+ const struct cpumask *override_mask = task_cpu_possible_mask(p);
-+
-+ alloc_cpumask_var(&new_mask, GFP_KERNEL);
-+
-+ /*
-+ * __migrate_task() can fail silently in the face of concurrent
-+ * offlining of the chosen destination CPU, so take the hotplug
-+ * lock to ensure that the migration succeeds.
-+ */
-+ cpus_read_lock();
-+ if (!cpumask_available(new_mask))
-+ goto out_set_mask;
-+
-+ if (!restrict_cpus_allowed_ptr(p, new_mask, override_mask))
-+ goto out_free_mask;
-+
-+ /*
-+ * We failed to find a valid subset of the affinity mask for the
-+ * task, so override it based on its cpuset hierarchy.
-+ */
-+ cpuset_cpus_allowed(p, new_mask);
-+ override_mask = new_mask;
-+
-+out_set_mask:
-+ if (printk_ratelimit()) {
-+ printk_deferred("Overriding affinity for process %d (%s) to CPUs %*pbl\n",
-+ task_pid_nr(p), p->comm,
-+ cpumask_pr_args(override_mask));
-+ }
-+
-+ WARN_ON(set_cpus_allowed_ptr(p, override_mask));
-+out_free_mask:
-+ cpus_read_unlock();
-+ free_cpumask_var(new_mask);
-+}
-+
-+static int
-+__sched_setaffinity(struct task_struct *p, const struct cpumask *mask);
-+
-+/*
-+ * Restore the affinity of a task @p which was previously restricted by a
-+ * call to force_compatible_cpus_allowed_ptr(). This will clear (and free)
-+ * @p->user_cpus_ptr.
-+ *
-+ * It is the caller's responsibility to serialise this with any calls to
-+ * force_compatible_cpus_allowed_ptr(@p).
-+ */
-+void relax_compatible_cpus_allowed_ptr(struct task_struct *p)
-+{
-+ struct cpumask *user_mask = p->user_cpus_ptr;
-+ unsigned long flags;
-+
-+ /*
-+ * Try to restore the old affinity mask. If this fails, then
-+ * we free the mask explicitly to avoid it being inherited across
-+ * a subsequent fork().
-+ */
-+ if (!user_mask || !__sched_setaffinity(p, user_mask))
-+ return;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ user_mask = clear_user_cpus_ptr(p);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+
-+ kfree(user_mask);
-+}
-+
-+#else /* CONFIG_SMP */
-+
-+static inline int select_task_rq(struct task_struct *p)
-+{
-+ return 0;
-+}
-+
-+static inline int
-+__set_cpus_allowed_ptr(struct task_struct *p,
-+ const struct cpumask *new_mask, u32 flags)
-+{
-+ return set_cpus_allowed_ptr(p, new_mask);
-+}
-+
-+static inline bool rq_has_pinned_tasks(struct rq *rq)
-+{
-+ return false;
-+}
-+
-+#endif /* !CONFIG_SMP */
-+
-+static void
-+ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq;
-+
-+ if (!schedstat_enabled())
-+ return;
-+
-+ rq = this_rq();
-+
-+#ifdef CONFIG_SMP
-+ if (cpu == rq->cpu)
-+ __schedstat_inc(rq->ttwu_local);
-+ else {
-+ /** Alt schedule FW ToDo:
-+ * How to do ttwu_wake_remote
-+ */
-+ }
-+#endif /* CONFIG_SMP */
-+
-+ __schedstat_inc(rq->ttwu_count);
-+}
-+
-+/*
-+ * Mark the task runnable and perform wakeup-preemption.
-+ */
-+static inline void
-+ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags)
-+{
-+ check_preempt_curr(rq);
-+ WRITE_ONCE(p->__state, TASK_RUNNING);
-+ trace_sched_wakeup(p);
-+}
-+
-+static inline void
-+ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags)
-+{
-+ if (p->sched_contributes_to_load)
-+ rq->nr_uninterruptible--;
-+
-+ if (
-+#ifdef CONFIG_SMP
-+ !(wake_flags & WF_MIGRATED) &&
-+#endif
-+ p->in_iowait) {
-+ delayacct_blkio_end(p);
-+ atomic_dec(&task_rq(p)->nr_iowait);
-+ }
-+
-+ activate_task(p, rq);
-+ ttwu_do_wakeup(rq, p, 0);
-+}
-+
-+/*
-+ * Consider @p being inside a wait loop:
-+ *
-+ * for (;;) {
-+ * set_current_state(TASK_UNINTERRUPTIBLE);
-+ *
-+ * if (CONDITION)
-+ * break;
-+ *
-+ * schedule();
-+ * }
-+ * __set_current_state(TASK_RUNNING);
-+ *
-+ * between set_current_state() and schedule(). In this case @p is still
-+ * runnable, so all that needs doing is change p->state back to TASK_RUNNING in
-+ * an atomic manner.
-+ *
-+ * By taking task_rq(p)->lock we serialize against schedule(), if @p->on_rq
-+ * then schedule() must still happen and p->state can be changed to
-+ * TASK_RUNNING. Otherwise we lost the race, schedule() has happened, and we
-+ * need to do a full wakeup with enqueue.
-+ *
-+ * Returns: %true when the wakeup is done,
-+ * %false otherwise.
-+ */
-+static int ttwu_runnable(struct task_struct *p, int wake_flags)
-+{
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+ int ret = 0;
-+
-+ rq = __task_access_lock(p, &lock);
-+ if (task_on_rq_queued(p)) {
-+ /* check_preempt_curr() may use rq clock */
-+ update_rq_clock(rq);
-+ ttwu_do_wakeup(rq, p, wake_flags);
-+ ret = 1;
-+ }
-+ __task_access_unlock(p, lock);
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_SMP
-+void sched_ttwu_pending(void *arg)
-+{
-+ struct llist_node *llist = arg;
-+ struct rq *rq = this_rq();
-+ struct task_struct *p, *t;
-+ struct rq_flags rf;
-+
-+ if (!llist)
-+ return;
-+
-+ /*
-+ * rq::ttwu_pending racy indication of out-standing wakeups.
-+ * Races such that false-negatives are possible, since they
-+ * are shorter lived that false-positives would be.
-+ */
-+ WRITE_ONCE(rq->ttwu_pending, 0);
-+
-+ rq_lock_irqsave(rq, &rf);
-+ update_rq_clock(rq);
-+
-+ llist_for_each_entry_safe(p, t, llist, wake_entry.llist) {
-+ if (WARN_ON_ONCE(p->on_cpu))
-+ smp_cond_load_acquire(&p->on_cpu, !VAL);
-+
-+ if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq)))
-+ set_task_cpu(p, cpu_of(rq));
-+
-+ ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0);
-+ }
-+
-+ rq_unlock_irqrestore(rq, &rf);
-+}
-+
-+void send_call_function_single_ipi(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (!set_nr_if_polling(rq->idle))
-+ arch_send_call_function_single_ipi(cpu);
-+ else
-+ trace_sched_wake_idle_without_ipi(cpu);
-+}
-+
-+/*
-+ * Queue a task on the target CPUs wake_list and wake the CPU via IPI if
-+ * necessary. The wakee CPU on receipt of the IPI will queue the task
-+ * via sched_ttwu_wakeup() for activation so the wakee incurs the cost
-+ * of the wakeup instead of the waker.
-+ */
-+static void __ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED);
-+
-+ WRITE_ONCE(rq->ttwu_pending, 1);
-+ __smp_call_single_queue(cpu, &p->wake_entry.llist);
-+}
-+
-+static inline bool ttwu_queue_cond(int cpu, int wake_flags)
-+{
-+ /*
-+ * Do not complicate things with the async wake_list while the CPU is
-+ * in hotplug state.
-+ */
-+ if (!cpu_active(cpu))
-+ return false;
-+
-+ /*
-+ * If the CPU does not share cache, then queue the task on the
-+ * remote rqs wakelist to avoid accessing remote data.
-+ */
-+ if (!cpus_share_cache(smp_processor_id(), cpu))
-+ return true;
-+
-+ /*
-+ * 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 ((wake_flags & WF_ON_CPU) && cpu_rq(cpu)->nr_running <= 1)
-+ return true;
-+
-+ return false;
-+}
-+
-+static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ if (__is_defined(ALT_SCHED_TTWU_QUEUE) && ttwu_queue_cond(cpu, wake_flags)) {
-+ if (WARN_ON_ONCE(cpu == smp_processor_id()))
-+ return false;
-+
-+ sched_clock_cpu(cpu); /* Sync clocks across CPUs */
-+ __ttwu_queue_wakelist(p, cpu, wake_flags);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void wake_up_if_idle(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ rcu_read_lock();
-+
-+ if (!is_idle_task(rcu_dereference(rq->curr)))
-+ goto out;
-+
-+ if (set_nr_if_polling(rq->idle)) {
-+ trace_sched_wake_idle_without_ipi(cpu);
-+ } else {
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ if (is_idle_task(rq->curr))
-+ smp_send_reschedule(cpu);
-+ /* Else CPU is not idle, do nothing here */
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+ }
-+
-+out:
-+ rcu_read_unlock();
-+}
-+
-+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);
-+}
-+#else /* !CONFIG_SMP */
-+
-+static inline bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ return false;
-+}
-+
-+#endif /* CONFIG_SMP */
-+
-+static inline void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (ttwu_queue_wakelist(p, cpu, wake_flags))
-+ return;
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+ ttwu_do_activate(rq, p, wake_flags);
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+/*
-+ * Invoked from try_to_wake_up() to check whether the task can be woken up.
-+ *
-+ * The caller holds p::pi_lock if p != current or has preemption
-+ * disabled when p == current.
-+ *
-+ * The rules of PREEMPT_RT saved_state:
-+ *
-+ * The related locking code always holds p::pi_lock when updating
-+ * p::saved_state, which means the code is fully serialized in both cases.
-+ *
-+ * The lock wait and lock wakeups happen via TASK_RTLOCK_WAIT. No other
-+ * bits set. This allows to distinguish all wakeup scenarios.
-+ */
-+static __always_inline
-+bool ttwu_state_match(struct task_struct *p, unsigned int state, int *success)
-+{
-+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
-+ WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) &&
-+ state != TASK_RTLOCK_WAIT);
-+ }
-+
-+ if (READ_ONCE(p->__state) & state) {
-+ *success = 1;
-+ return true;
-+ }
-+
-+#ifdef CONFIG_PREEMPT_RT
-+ /*
-+ * Saved state preserves the task state across blocking on
-+ * an RT lock. If the state matches, set p::saved_state to
-+ * TASK_RUNNING, but do not wake the task because it waits
-+ * for a lock wakeup. Also indicate success because from
-+ * the regular waker's point of view this has succeeded.
-+ *
-+ * After acquiring the lock the task will restore p::__state
-+ * from p::saved_state which ensures that the regular
-+ * wakeup is not lost. The restore will also set
-+ * p::saved_state to TASK_RUNNING so any further tests will
-+ * not result in false positives vs. @success
-+ */
-+ if (p->saved_state & state) {
-+ p->saved_state = TASK_RUNNING;
-+ *success = 1;
-+ }
-+#endif
-+ return false;
-+}
-+
-+/*
-+ * Notes on Program-Order guarantees on SMP systems.
-+ *
-+ * MIGRATION
-+ *
-+ * The basic program-order guarantee on SMP systems is that when a task [t]
-+ * migrates, all its activity on its old CPU [c0] happens-before any subsequent
-+ * execution on its new CPU [c1].
-+ *
-+ * For migration (of runnable tasks) this is provided by the following means:
-+ *
-+ * A) UNLOCK of the rq(c0)->lock scheduling out task t
-+ * B) migration for t is required to synchronize *both* rq(c0)->lock and
-+ * rq(c1)->lock (if not at the same time, then in that order).
-+ * C) LOCK of the rq(c1)->lock scheduling in task
-+ *
-+ * Transitivity guarantees that B happens after A and C after B.
-+ * Note: we only require RCpc transitivity.
-+ * Note: the CPU doing B need not be c0 or c1
-+ *
-+ * Example:
-+ *
-+ * CPU0 CPU1 CPU2
-+ *
-+ * LOCK rq(0)->lock
-+ * sched-out X
-+ * sched-in Y
-+ * UNLOCK rq(0)->lock
-+ *
-+ * LOCK rq(0)->lock // orders against CPU0
-+ * dequeue X
-+ * UNLOCK rq(0)->lock
-+ *
-+ * LOCK rq(1)->lock
-+ * enqueue X
-+ * UNLOCK rq(1)->lock
-+ *
-+ * LOCK rq(1)->lock // orders against CPU2
-+ * sched-out Z
-+ * sched-in X
-+ * UNLOCK rq(1)->lock
-+ *
-+ *
-+ * BLOCKING -- aka. SLEEP + WAKEUP
-+ *
-+ * For blocking we (obviously) need to provide the same guarantee as for
-+ * migration. However the means are completely different as there is no lock
-+ * chain to provide order. Instead we do:
-+ *
-+ * 1) smp_store_release(X->on_cpu, 0) -- finish_task()
-+ * 2) smp_cond_load_acquire(!X->on_cpu) -- try_to_wake_up()
-+ *
-+ * Example:
-+ *
-+ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule)
-+ *
-+ * LOCK rq(0)->lock LOCK X->pi_lock
-+ * dequeue X
-+ * sched-out X
-+ * smp_store_release(X->on_cpu, 0);
-+ *
-+ * smp_cond_load_acquire(&X->on_cpu, !VAL);
-+ * X->state = WAKING
-+ * set_task_cpu(X,2)
-+ *
-+ * LOCK rq(2)->lock
-+ * enqueue X
-+ * X->state = RUNNING
-+ * UNLOCK rq(2)->lock
-+ *
-+ * LOCK rq(2)->lock // orders against CPU1
-+ * sched-out Z
-+ * sched-in X
-+ * UNLOCK rq(2)->lock
-+ *
-+ * UNLOCK X->pi_lock
-+ * UNLOCK rq(0)->lock
-+ *
-+ *
-+ * However; for wakeups there is a second guarantee we must provide, namely we
-+ * must observe the state that lead to our wakeup. That is, not only must our
-+ * task observe its own prior state, it must also observe the stores prior to
-+ * its wakeup.
-+ *
-+ * This means that any means of doing remote wakeups must order the CPU doing
-+ * the wakeup against the CPU the task is going to end up running on. This,
-+ * however, is already required for the regular Program-Order guarantee above,
-+ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire).
-+ *
-+ */
-+
-+/**
-+ * try_to_wake_up - wake up a thread
-+ * @p: the thread to be awakened
-+ * @state: the mask of task states that can be woken
-+ * @wake_flags: wake modifier flags (WF_*)
-+ *
-+ * Conceptually does:
-+ *
-+ * If (@state & @p->state) @p->state = TASK_RUNNING.
-+ *
-+ * If the task was not queued/runnable, also place it back on a runqueue.
-+ *
-+ * This function is atomic against schedule() which would dequeue the task.
-+ *
-+ * It issues a full memory barrier before accessing @p->state, see the comment
-+ * with set_current_state().
-+ *
-+ * Uses p->pi_lock to serialize against concurrent wake-ups.
-+ *
-+ * Relies on p->pi_lock stabilizing:
-+ * - p->sched_class
-+ * - p->cpus_ptr
-+ * - p->sched_task_group
-+ * in order to do migration, see its use of select_task_rq()/set_task_cpu().
-+ *
-+ * Tries really hard to only take one task_rq(p)->lock for performance.
-+ * Takes rq->lock in:
-+ * - ttwu_runnable() -- old rq, unavoidable, see comment there;
-+ * - ttwu_queue() -- new rq, for enqueue of the task;
-+ * - psi_ttwu_dequeue() -- much sadness :-( accounting will kill us.
-+ *
-+ * As a consequence we race really badly with just about everything. See the
-+ * many memory barriers and their comments for details.
-+ *
-+ * Return: %true if @p->state changes (an actual wakeup was done),
-+ * %false otherwise.
-+ */
-+static int try_to_wake_up(struct task_struct *p, unsigned int state,
-+ int wake_flags)
-+{
-+ unsigned long flags;
-+ int cpu, success = 0;
-+
-+ preempt_disable();
-+ if (p == current) {
-+ /*
-+ * We're waking current, this means 'p->on_rq' and 'task_cpu(p)
-+ * == smp_processor_id()'. Together this means we can special
-+ * case the whole 'p->on_rq && ttwu_runnable()' case below
-+ * without taking any locks.
-+ *
-+ * In particular:
-+ * - we rely on Program-Order guarantees for all the ordering,
-+ * - we're serialized against set_special_state() by virtue of
-+ * it disabling IRQs (this allows not taking ->pi_lock).
-+ */
-+ if (!ttwu_state_match(p, state, &success))
-+ goto out;
-+
-+ trace_sched_waking(p);
-+ WRITE_ONCE(p->__state, TASK_RUNNING);
-+ trace_sched_wakeup(p);
-+ goto out;
-+ }
-+
-+ /*
-+ * If we are going to wake up a thread waiting for CONDITION we
-+ * need to ensure that CONDITION=1 done by the caller can not be
-+ * reordered with p->state check below. This pairs with smp_store_mb()
-+ * in set_current_state() that the waiting thread does.
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ smp_mb__after_spinlock();
-+ if (!ttwu_state_match(p, state, &success))
-+ goto unlock;
-+
-+ trace_sched_waking(p);
-+
-+ /*
-+ * Ensure we load p->on_rq _after_ p->state, otherwise it would
-+ * be possible to, falsely, observe p->on_rq == 0 and get stuck
-+ * in smp_cond_load_acquire() below.
-+ *
-+ * sched_ttwu_pending() try_to_wake_up()
-+ * STORE p->on_rq = 1 LOAD p->state
-+ * UNLOCK rq->lock
-+ *
-+ * __schedule() (switch to task 'p')
-+ * LOCK rq->lock smp_rmb();
-+ * smp_mb__after_spinlock();
-+ * UNLOCK rq->lock
-+ *
-+ * [task p]
-+ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq
-+ *
-+ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
-+ * __schedule(). See the comment for smp_mb__after_spinlock().
-+ *
-+ * A similar smb_rmb() lives in try_invoke_on_locked_down_task().
-+ */
-+ smp_rmb();
-+ if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags))
-+ goto unlock;
-+
-+#ifdef CONFIG_SMP
-+ /*
-+ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
-+ * possible to, falsely, observe p->on_cpu == 0.
-+ *
-+ * One must be running (->on_cpu == 1) in order to remove oneself
-+ * from the runqueue.
-+ *
-+ * __schedule() (switch to task 'p') try_to_wake_up()
-+ * STORE p->on_cpu = 1 LOAD p->on_rq
-+ * UNLOCK rq->lock
-+ *
-+ * __schedule() (put 'p' to sleep)
-+ * LOCK rq->lock smp_rmb();
-+ * smp_mb__after_spinlock();
-+ * STORE p->on_rq = 0 LOAD p->on_cpu
-+ *
-+ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
-+ * __schedule(). See the comment for smp_mb__after_spinlock().
-+ *
-+ * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
-+ * schedule()'s deactivate_task() has 'happened' and p will no longer
-+ * care about it's own p->state. See the comment in __schedule().
-+ */
-+ smp_acquire__after_ctrl_dep();
-+
-+ /*
-+ * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
-+ * == 0), which means we need to do an enqueue, change p->state to
-+ * TASK_WAKING such that we can unlock p->pi_lock before doing the
-+ * enqueue, such as ttwu_queue_wakelist().
-+ */
-+ WRITE_ONCE(p->__state, TASK_WAKING);
-+
-+ /*
-+ * If the owning (remote) CPU is still in the middle of schedule() with
-+ * this task as prev, considering queueing p on the remote CPUs wake_list
-+ * which potentially sends an IPI instead of spinning on p->on_cpu to
-+ * let the waker make forward progress. This is safe because IRQs are
-+ * disabled and the IPI will deliver after on_cpu is cleared.
-+ *
-+ * Ensure we load task_cpu(p) after p->on_cpu:
-+ *
-+ * set_task_cpu(p, cpu);
-+ * STORE p->cpu = @cpu
-+ * __schedule() (switch to task 'p')
-+ * LOCK rq->lock
-+ * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu)
-+ * STORE p->on_cpu = 1 LOAD p->cpu
-+ *
-+ * to ensure we observe the correct CPU on which the task is currently
-+ * scheduling.
-+ */
-+ if (smp_load_acquire(&p->on_cpu) &&
-+ ttwu_queue_wakelist(p, task_cpu(p), wake_flags | WF_ON_CPU))
-+ goto unlock;
-+
-+ /*
-+ * If the owning (remote) CPU is still in the middle of schedule() with
-+ * this task as prev, wait until it's done referencing the task.
-+ *
-+ * Pairs with the smp_store_release() in finish_task().
-+ *
-+ * This ensures that tasks getting woken will be fully ordered against
-+ * their previous state and preserve Program Order.
-+ */
-+ smp_cond_load_acquire(&p->on_cpu, !VAL);
-+
-+ sched_task_ttwu(p);
-+
-+ cpu = select_task_rq(p);
-+
-+ if (cpu != task_cpu(p)) {
-+ if (p->in_iowait) {
-+ delayacct_blkio_end(p);
-+ atomic_dec(&task_rq(p)->nr_iowait);
-+ }
-+
-+ wake_flags |= WF_MIGRATED;
-+ psi_ttwu_dequeue(p);
-+ set_task_cpu(p, cpu);
-+ }
-+#else
-+ cpu = task_cpu(p);
-+#endif /* CONFIG_SMP */
-+
-+ ttwu_queue(p, cpu, wake_flags);
-+unlock:
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+out:
-+ if (success)
-+ ttwu_stat(p, task_cpu(p), wake_flags);
-+ preempt_enable();
-+
-+ return success;
-+}
-+
-+/**
-+ * try_invoke_on_locked_down_task - Invoke a function on task in fixed state
-+ * @p: Process for which the function is to be invoked, can be @current.
-+ * @func: Function to invoke.
-+ * @arg: Argument to function.
-+ *
-+ * If the specified task can be quickly locked into a definite state
-+ * (either sleeping or on a given runqueue), arrange to keep it in that
-+ * state while invoking @func(@arg). This function can use ->on_rq and
-+ * task_curr() to work out what the state is, if required. Given that
-+ * @func can be invoked with a runqueue lock held, it had better be quite
-+ * lightweight.
-+ *
-+ * Returns:
-+ * @false if the task slipped out from under the locks.
-+ * @true if the task was locked onto a runqueue or is sleeping.
-+ * However, @func can override this by returning @false.
-+ */
-+bool try_invoke_on_locked_down_task(struct task_struct *p, bool (*func)(struct task_struct *t, void *arg), void *arg)
-+{
-+ struct rq_flags rf;
-+ bool ret = false;
-+ struct rq *rq;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
-+ if (p->on_rq) {
-+ rq = __task_rq_lock(p, &rf);
-+ if (task_rq(p) == rq)
-+ ret = func(p, arg);
-+ __task_rq_unlock(rq, &rf);
-+ } else {
-+ switch (READ_ONCE(p->__state)) {
-+ case TASK_RUNNING:
-+ case TASK_WAKING:
-+ break;
-+ default:
-+ smp_rmb(); // See smp_rmb() comment in try_to_wake_up().
-+ if (!p->on_rq)
-+ ret = func(p, arg);
-+ }
-+ }
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
-+ return ret;
-+}
-+
-+/**
-+ * wake_up_process - Wake up a specific process
-+ * @p: The process to be woken up.
-+ *
-+ * Attempt to wake up the nominated process and move it to the set of runnable
-+ * processes.
-+ *
-+ * Return: 1 if the process was woken up, 0 if it was already running.
-+ *
-+ * This function executes a full memory barrier before accessing the task state.
-+ */
-+int wake_up_process(struct task_struct *p)
-+{
-+ return try_to_wake_up(p, TASK_NORMAL, 0);
-+}
-+EXPORT_SYMBOL(wake_up_process);
-+
-+int wake_up_state(struct task_struct *p, unsigned int state)
-+{
-+ return try_to_wake_up(p, state, 0);
-+}
-+
-+/*
-+ * Perform scheduler related setup for a newly forked process p.
-+ * p is forked by current.
-+ *
-+ * __sched_fork() is basic setup used by init_idle() too:
-+ */
-+static inline void __sched_fork(unsigned long clone_flags, struct task_struct *p)
-+{
-+ p->on_rq = 0;
-+ p->on_cpu = 0;
-+ p->utime = 0;
-+ p->stime = 0;
-+ p->sched_time = 0;
-+
-+#ifdef CONFIG_PREEMPT_NOTIFIERS
-+ INIT_HLIST_HEAD(&p->preempt_notifiers);
-+#endif
-+
-+#ifdef CONFIG_COMPACTION
-+ p->capture_control = NULL;
-+#endif
-+#ifdef CONFIG_SMP
-+ p->wake_entry.u_flags = CSD_TYPE_TTWU;
-+#endif
-+}
-+
-+/*
-+ * fork()/clone()-time setup:
-+ */
-+int sched_fork(unsigned long clone_flags, struct task_struct *p)
-+{
-+ __sched_fork(clone_flags, p);
-+ /*
-+ * We mark the process as NEW here. This guarantees that
-+ * nobody will actually run it, and a signal or other external
-+ * event cannot wake it up and insert it on the runqueue either.
-+ */
-+ p->__state = TASK_NEW;
-+
-+ /*
-+ * Make sure we do not leak PI boosting priority to the child.
-+ */
-+ p->prio = current->normal_prio;
-+
-+ /*
-+ * Revert to default priority/policy on fork if requested.
-+ */
-+ if (unlikely(p->sched_reset_on_fork)) {
-+ if (task_has_rt_policy(p)) {
-+ p->policy = SCHED_NORMAL;
-+ p->static_prio = NICE_TO_PRIO(0);
-+ p->rt_priority = 0;
-+ } else if (PRIO_TO_NICE(p->static_prio) < 0)
-+ p->static_prio = NICE_TO_PRIO(0);
-+
-+ p->prio = p->normal_prio = p->static_prio;
-+
-+ /*
-+ * We don't need the reset flag anymore after the fork. It has
-+ * fulfilled its duty:
-+ */
-+ p->sched_reset_on_fork = 0;
-+ }
-+
-+#ifdef CONFIG_SCHED_INFO
-+ if (unlikely(sched_info_on()))
-+ memset(&p->sched_info, 0, sizeof(p->sched_info));
-+#endif
-+ init_task_preempt_count(p);
-+
-+ return 0;
-+}
-+
-+void sched_post_fork(struct task_struct *p, struct kernel_clone_args *kargs)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+
-+ /*
-+ * The child is not yet in the pid-hash so no cgroup attach races,
-+ * and the cgroup is pinned to this child due to cgroup_fork()
-+ * is ran before sched_fork().
-+ *
-+ * Silence PROVE_RCU.
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ /*
-+ * Share the timeslice between parent and child, thus the
-+ * total amount of pending timeslices in the system doesn't change,
-+ * resulting in more scheduling fairness.
-+ */
-+ rq = this_rq();
-+ raw_spin_lock(&rq->lock);
-+
-+ rq->curr->time_slice /= 2;
-+ p->time_slice = rq->curr->time_slice;
-+#ifdef CONFIG_SCHED_HRTICK
-+ hrtick_start(rq, rq->curr->time_slice);
-+#endif
-+
-+ if (p->time_slice < RESCHED_NS) {
-+ p->time_slice = sched_timeslice_ns;
-+ resched_curr(rq);
-+ }
-+ sched_task_fork(p, rq);
-+ raw_spin_unlock(&rq->lock);
-+
-+ rseq_migrate(p);
-+ /*
-+ * We're setting the CPU for the first time, we don't migrate,
-+ * so use __set_task_cpu().
-+ */
-+ __set_task_cpu(p, smp_processor_id());
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+
-+#ifdef CONFIG_SCHEDSTATS
-+
-+DEFINE_STATIC_KEY_FALSE(sched_schedstats);
-+
-+static void set_schedstats(bool enabled)
-+{
-+ if (enabled)
-+ static_branch_enable(&sched_schedstats);
-+ else
-+ static_branch_disable(&sched_schedstats);
-+}
-+
-+void force_schedstat_enabled(void)
-+{
-+ if (!schedstat_enabled()) {
-+ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n");
-+ static_branch_enable(&sched_schedstats);
-+ }
-+}
-+
-+static int __init setup_schedstats(char *str)
-+{
-+ int ret = 0;
-+ if (!str)
-+ goto out;
-+
-+ if (!strcmp(str, "enable")) {
-+ set_schedstats(true);
-+ ret = 1;
-+ } else if (!strcmp(str, "disable")) {
-+ set_schedstats(false);
-+ ret = 1;
-+ }
-+out:
-+ if (!ret)
-+ pr_warn("Unable to parse schedstats=\n");
-+
-+ return ret;
-+}
-+__setup("schedstats=", setup_schedstats);
-+
-+#ifdef CONFIG_PROC_SYSCTL
-+int sysctl_schedstats(struct ctl_table *table, int write,
-+ void __user *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ struct ctl_table t;
-+ int err;
-+ int state = static_branch_likely(&sched_schedstats);
-+
-+ if (write && !capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ t = *table;
-+ t.data = &state;
-+ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
-+ if (err < 0)
-+ return err;
-+ if (write)
-+ set_schedstats(state);
-+ return err;
-+}
-+#endif /* CONFIG_PROC_SYSCTL */
-+#endif /* CONFIG_SCHEDSTATS */
-+
-+/*
-+ * wake_up_new_task - wake up a newly created task for the first time.
-+ *
-+ * This function will do some initial scheduler statistics housekeeping
-+ * that must be done for every newly created context, then puts the task
-+ * on the runqueue and wakes it.
-+ */
-+void wake_up_new_task(struct task_struct *p)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ WRITE_ONCE(p->__state, TASK_RUNNING);
-+ rq = cpu_rq(select_task_rq(p));
-+#ifdef CONFIG_SMP
-+ rseq_migrate(p);
-+ /*
-+ * Fork balancing, do it here and not earlier because:
-+ * - cpus_ptr can change in the fork path
-+ * - any previously selected CPU might disappear through hotplug
-+ *
-+ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq,
-+ * as we're not fully set-up yet.
-+ */
-+ __set_task_cpu(p, cpu_of(rq));
-+#endif
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+
-+ activate_task(p, rq);
-+ trace_sched_wakeup_new(p);
-+ check_preempt_curr(rq);
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+
-+#ifdef CONFIG_PREEMPT_NOTIFIERS
-+
-+static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key);
-+
-+void preempt_notifier_inc(void)
-+{
-+ static_branch_inc(&preempt_notifier_key);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_inc);
-+
-+void preempt_notifier_dec(void)
-+{
-+ static_branch_dec(&preempt_notifier_key);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_dec);
-+
-+/**
-+ * preempt_notifier_register - tell me when current is being preempted & rescheduled
-+ * @notifier: notifier struct to register
-+ */
-+void preempt_notifier_register(struct preempt_notifier *notifier)
-+{
-+ if (!static_branch_unlikely(&preempt_notifier_key))
-+ WARN(1, "registering preempt_notifier while notifiers disabled\n");
-+
-+ hlist_add_head(&notifier->link, &current->preempt_notifiers);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_register);
-+
-+/**
-+ * preempt_notifier_unregister - no longer interested in preemption notifications
-+ * @notifier: notifier struct to unregister
-+ *
-+ * This is *not* safe to call from within a preemption notifier.
-+ */
-+void preempt_notifier_unregister(struct preempt_notifier *notifier)
-+{
-+ hlist_del(&notifier->link);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_unregister);
-+
-+static void __fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+ struct preempt_notifier *notifier;
-+
-+ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
-+ notifier->ops->sched_in(notifier, raw_smp_processor_id());
-+}
-+
-+static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+ if (static_branch_unlikely(&preempt_notifier_key))
-+ __fire_sched_in_preempt_notifiers(curr);
-+}
-+
-+static void
-+__fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+ struct preempt_notifier *notifier;
-+
-+ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
-+ notifier->ops->sched_out(notifier, next);
-+}
-+
-+static __always_inline void
-+fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+ if (static_branch_unlikely(&preempt_notifier_key))
-+ __fire_sched_out_preempt_notifiers(curr, next);
-+}
-+
-+#else /* !CONFIG_PREEMPT_NOTIFIERS */
-+
-+static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+}
-+
-+static inline void
-+fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+}
-+
-+#endif /* CONFIG_PREEMPT_NOTIFIERS */
-+
-+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.
-+ */
-+ WRITE_ONCE(next->on_cpu, 1);
-+}
-+
-+static inline void finish_task(struct task_struct *prev)
-+{
-+#ifdef CONFIG_SMP
-+ /*
-+ * This must be the very last reference to @prev from this CPU. After
-+ * p->on_cpu is cleared, the task can be moved to a different CPU. We
-+ * must ensure this doesn't happen until the switch is completely
-+ * finished.
-+ *
-+ * In particular, the load of prev->state in finish_task_switch() must
-+ * happen before this.
-+ *
-+ * Pairs with the smp_cond_load_acquire() in try_to_wake_up().
-+ */
-+ smp_store_release(&prev->on_cpu, 0);
-+#else
-+ prev->on_cpu = 0;
-+#endif
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+static void do_balance_callbacks(struct rq *rq, struct callback_head *head)
-+{
-+ void (*func)(struct rq *rq);
-+ struct callback_head *next;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ while (head) {
-+ func = (void (*)(struct rq *))head->func;
-+ next = head->next;
-+ head->next = NULL;
-+ head = next;
-+
-+ func(rq);
-+ }
-+}
-+
-+static void balance_push(struct rq *rq);
-+
-+struct callback_head balance_push_callback = {
-+ .next = NULL,
-+ .func = (void (*)(struct callback_head *))balance_push,
-+};
-+
-+static inline struct callback_head *splice_balance_callbacks(struct rq *rq)
-+{
-+ struct callback_head *head = rq->balance_callback;
-+
-+ if (head) {
-+ lockdep_assert_held(&rq->lock);
-+ rq->balance_callback = NULL;
-+ }
-+
-+ return head;
-+}
-+
-+static void __balance_callbacks(struct rq *rq)
-+{
-+ do_balance_callbacks(rq, splice_balance_callbacks(rq));
-+}
-+
-+static inline void balance_callbacks(struct rq *rq, struct callback_head *head)
-+{
-+ unsigned long flags;
-+
-+ if (unlikely(head)) {
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ do_balance_callbacks(rq, head);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+ }
-+}
-+
-+#else
-+
-+static inline void __balance_callbacks(struct rq *rq)
-+{
-+}
-+
-+static inline struct callback_head *splice_balance_callbacks(struct rq *rq)
-+{
-+ return NULL;
-+}
-+
-+static inline void balance_callbacks(struct rq *rq, struct callback_head *head)
-+{
-+}
-+
-+#endif
-+
-+static inline void
-+prepare_lock_switch(struct rq *rq, struct task_struct *next)
-+{
-+ /*
-+ * Since the runqueue lock will be released by the next
-+ * task (which is an invalid locking op but in the case
-+ * of the scheduler it's an obvious special-case), so we
-+ * do an early lockdep release here:
-+ */
-+ spin_release(&rq->lock.dep_map, _THIS_IP_);
-+#ifdef CONFIG_DEBUG_SPINLOCK
-+ /* this is a valid case when another task releases the spinlock */
-+ rq->lock.owner = next;
-+#endif
-+}
-+
-+static inline void finish_lock_switch(struct rq *rq)
-+{
-+ /*
-+ * If we are tracking spinlock dependencies then we have to
-+ * fix up the runqueue lock - which gets 'carried over' from
-+ * prev into current:
-+ */
-+ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_);
-+ __balance_callbacks(rq);
-+ raw_spin_unlock_irq(&rq->lock);
-+}
-+
-+/*
-+ * NOP if the arch has not defined these:
-+ */
-+
-+#ifndef prepare_arch_switch
-+# define prepare_arch_switch(next) do { } while (0)
-+#endif
-+
-+#ifndef finish_arch_post_lock_switch
-+# define finish_arch_post_lock_switch() do { } while (0)
-+#endif
-+
-+static inline void kmap_local_sched_out(void)
-+{
-+#ifdef CONFIG_KMAP_LOCAL
-+ if (unlikely(current->kmap_ctrl.idx))
-+ __kmap_local_sched_out();
-+#endif
-+}
-+
-+static inline void kmap_local_sched_in(void)
-+{
-+#ifdef CONFIG_KMAP_LOCAL
-+ if (unlikely(current->kmap_ctrl.idx))
-+ __kmap_local_sched_in();
-+#endif
-+}
-+
-+/**
-+ * prepare_task_switch - prepare to switch tasks
-+ * @rq: the runqueue preparing to switch
-+ * @next: the task we are going to switch to.
-+ *
-+ * This is called with the rq lock held and interrupts off. It must
-+ * be paired with a subsequent finish_task_switch after the context
-+ * switch.
-+ *
-+ * prepare_task_switch sets up locking and calls architecture specific
-+ * hooks.
-+ */
-+static inline void
-+prepare_task_switch(struct rq *rq, struct task_struct *prev,
-+ struct task_struct *next)
-+{
-+ kcov_prepare_switch(prev);
-+ sched_info_switch(rq, prev, next);
-+ perf_event_task_sched_out(prev, next);
-+ rseq_preempt(prev);
-+ fire_sched_out_preempt_notifiers(prev, next);
-+ kmap_local_sched_out();
-+ prepare_task(next);
-+ prepare_arch_switch(next);
-+}
-+
-+/**
-+ * finish_task_switch - clean up after a task-switch
-+ * @rq: runqueue associated with task-switch
-+ * @prev: the thread we just switched away from.
-+ *
-+ * finish_task_switch must be called after the context switch, paired
-+ * with a prepare_task_switch call before the context switch.
-+ * finish_task_switch will reconcile locking set up by prepare_task_switch,
-+ * and do any other architecture-specific cleanup actions.
-+ *
-+ * Note that we may have delayed dropping an mm in context_switch(). If
-+ * so, we finish that here outside of the runqueue lock. (Doing it
-+ * with the lock held can cause deadlocks; see schedule() for
-+ * details.)
-+ *
-+ * The context switch have flipped the stack from under us and restored the
-+ * local variables which were saved when this task called schedule() in the
-+ * past. prev == current is still correct but we need to recalculate this_rq
-+ * because prev may have moved to another CPU.
-+ */
-+static struct rq *finish_task_switch(struct task_struct *prev)
-+ __releases(rq->lock)
-+{
-+ struct rq *rq = this_rq();
-+ struct mm_struct *mm = rq->prev_mm;
-+ long prev_state;
-+
-+ /*
-+ * The previous task will have left us with a preempt_count of 2
-+ * because it left us after:
-+ *
-+ * schedule()
-+ * preempt_disable(); // 1
-+ * __schedule()
-+ * raw_spin_lock_irq(&rq->lock) // 2
-+ *
-+ * Also, see FORK_PREEMPT_COUNT.
-+ */
-+ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET,
-+ "corrupted preempt_count: %s/%d/0x%x\n",
-+ current->comm, current->pid, preempt_count()))
-+ preempt_count_set(FORK_PREEMPT_COUNT);
-+
-+ rq->prev_mm = NULL;
-+
-+ /*
-+ * A task struct has one reference for the use as "current".
-+ * If a task dies, then it sets TASK_DEAD in tsk->state and calls
-+ * schedule one last time. The schedule call will never return, and
-+ * the scheduled task must drop that reference.
-+ *
-+ * We must observe prev->state before clearing prev->on_cpu (in
-+ * finish_task), otherwise a concurrent wakeup can get prev
-+ * running on another CPU and we could rave with its RUNNING -> DEAD
-+ * transition, resulting in a double drop.
-+ */
-+ prev_state = READ_ONCE(prev->__state);
-+ vtime_task_switch(prev);
-+ perf_event_task_sched_in(prev, current);
-+ finish_task(prev);
-+ tick_nohz_task_switch();
-+ finish_lock_switch(rq);
-+ finish_arch_post_lock_switch();
-+ kcov_finish_switch(current);
-+ /*
-+ * kmap_local_sched_out() is invoked with rq::lock held and
-+ * interrupts disabled. There is no requirement for that, but the
-+ * sched out code does not have an interrupt enabled section.
-+ * Restoring the maps on sched in does not require interrupts being
-+ * disabled either.
-+ */
-+ kmap_local_sched_in();
-+
-+ fire_sched_in_preempt_notifiers(current);
-+ /*
-+ * When switching through a kernel thread, the loop in
-+ * membarrier_{private,global}_expedited() may have observed that
-+ * kernel thread and not issued an IPI. It is therefore possible to
-+ * schedule between user->kernel->user threads without passing though
-+ * switch_mm(). Membarrier requires a barrier after storing to
-+ * rq->curr, before returning to userspace, so provide them here:
-+ *
-+ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly
-+ * provided by mmdrop(),
-+ * - a sync_core for SYNC_CORE.
-+ */
-+ if (mm) {
-+ membarrier_mm_sync_core_before_usermode(mm);
-+ mmdrop(mm);
-+ }
-+ if (unlikely(prev_state == TASK_DEAD)) {
-+ /*
-+ * Remove function-return probe instances associated with this
-+ * task and put them back on the free list.
-+ */
-+ kprobe_flush_task(prev);
-+
-+ /* Task is done with its stack. */
-+ put_task_stack(prev);
-+
-+ put_task_struct_rcu_user(prev);
-+ }
-+
-+ return rq;
-+}
-+
-+/**
-+ * schedule_tail - first thing a freshly forked thread must call.
-+ * @prev: the thread we just switched away from.
-+ */
-+asmlinkage __visible void schedule_tail(struct task_struct *prev)
-+ __releases(rq->lock)
-+{
-+ /*
-+ * New tasks start with FORK_PREEMPT_COUNT, see there and
-+ * finish_task_switch() for details.
-+ *
-+ * finish_task_switch() will drop rq->lock() and lower preempt_count
-+ * and the preempt_enable() will end up enabling preemption (on
-+ * PREEMPT_COUNT kernels).
-+ */
-+
-+ finish_task_switch(prev);
-+ preempt_enable();
-+
-+ if (current->set_child_tid)
-+ put_user(task_pid_vnr(current), current->set_child_tid);
-+
-+ calculate_sigpending();
-+}
-+
-+/*
-+ * context_switch - switch to the new MM and the new thread's register state.
-+ */
-+static __always_inline struct rq *
-+context_switch(struct rq *rq, struct task_struct *prev,
-+ struct task_struct *next)
-+{
-+ prepare_task_switch(rq, prev, next);
-+
-+ /*
-+ * For paravirt, this is coupled with an exit in switch_to to
-+ * combine the page table reload and the switch backend into
-+ * one hypercall.
-+ */
-+ arch_start_context_switch(prev);
-+
-+ /*
-+ * kernel -> kernel lazy + transfer active
-+ * user -> kernel lazy + mmgrab() active
-+ *
-+ * kernel -> user switch + mmdrop() active
-+ * user -> user switch
-+ */
-+ if (!next->mm) { // to kernel
-+ enter_lazy_tlb(prev->active_mm, next);
-+
-+ next->active_mm = prev->active_mm;
-+ if (prev->mm) // from user
-+ mmgrab(prev->active_mm);
-+ else
-+ prev->active_mm = NULL;
-+ } else { // to user
-+ membarrier_switch_mm(rq, prev->active_mm, next->mm);
-+ /*
-+ * sys_membarrier() requires an smp_mb() between setting
-+ * rq->curr / membarrier_switch_mm() and returning to userspace.
-+ *
-+ * The below provides this either through switch_mm(), or in
-+ * case 'prev->active_mm == next->mm' through
-+ * finish_task_switch()'s mmdrop().
-+ */
-+ switch_mm_irqs_off(prev->active_mm, next->mm, next);
-+
-+ if (!prev->mm) { // from kernel
-+ /* will mmdrop() in finish_task_switch(). */
-+ rq->prev_mm = prev->active_mm;
-+ prev->active_mm = NULL;
-+ }
-+ }
-+
-+ prepare_lock_switch(rq, next);
-+
-+ /* Here we just switch the register state and the stack. */
-+ switch_to(prev, next, prev);
-+ barrier();
-+
-+ return finish_task_switch(prev);
-+}
-+
-+/*
-+ * nr_running, nr_uninterruptible and nr_context_switches:
-+ *
-+ * externally visible scheduler statistics: current number of runnable
-+ * threads, total number of context switches performed since bootup.
-+ */
-+unsigned int nr_running(void)
-+{
-+ unsigned int i, sum = 0;
-+
-+ for_each_online_cpu(i)
-+ sum += cpu_rq(i)->nr_running;
-+
-+ return sum;
-+}
-+
-+/*
-+ * Check if only the current task is running on the CPU.
-+ *
-+ * Caution: this function does not check that the caller has disabled
-+ * preemption, thus the result might have a time-of-check-to-time-of-use
-+ * race. The caller is responsible to use it correctly, for example:
-+ *
-+ * - from a non-preemptible section (of course)
-+ *
-+ * - from a thread that is bound to a single CPU
-+ *
-+ * - in a loop with very short iterations (e.g. a polling loop)
-+ */
-+bool single_task_running(void)
-+{
-+ return raw_rq()->nr_running == 1;
-+}
-+EXPORT_SYMBOL(single_task_running);
-+
-+unsigned long long nr_context_switches(void)
-+{
-+ int i;
-+ unsigned long long sum = 0;
-+
-+ for_each_possible_cpu(i)
-+ sum += cpu_rq(i)->nr_switches;
-+
-+ return sum;
-+}
-+
-+/*
-+ * Consumers of these two interfaces, like for example the cpuidle menu
-+ * governor, are using nonsensical data. Preferring shallow idle state selection
-+ * for a CPU that has IO-wait which might not even end up running the task when
-+ * it does become runnable.
-+ */
-+
-+unsigned int nr_iowait_cpu(int cpu)
-+{
-+ return atomic_read(&cpu_rq(cpu)->nr_iowait);
-+}
-+
-+/*
-+ * IO-wait accounting, and how it's mostly bollocks (on SMP).
-+ *
-+ * The idea behind IO-wait account is to account the idle time that we could
-+ * have spend running if it were not for IO. That is, if we were to improve the
-+ * storage performance, we'd have a proportional reduction in IO-wait time.
-+ *
-+ * This all works nicely on UP, where, when a task blocks on IO, we account
-+ * idle time as IO-wait, because if the storage were faster, it could've been
-+ * running and we'd not be idle.
-+ *
-+ * This has been extended to SMP, by doing the same for each CPU. This however
-+ * is broken.
-+ *
-+ * Imagine for instance the case where two tasks block on one CPU, only the one
-+ * CPU will have IO-wait accounted, while the other has regular idle. Even
-+ * though, if the storage were faster, both could've ran at the same time,
-+ * utilising both CPUs.
-+ *
-+ * This means, that when looking globally, the current IO-wait accounting on
-+ * SMP is a lower bound, by reason of under accounting.
-+ *
-+ * Worse, since the numbers are provided per CPU, they are sometimes
-+ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly
-+ * associated with any one particular CPU, it can wake to another CPU than it
-+ * blocked on. This means the per CPU IO-wait number is meaningless.
-+ *
-+ * Task CPU affinities can make all that even more 'interesting'.
-+ */
-+
-+unsigned int nr_iowait(void)
-+{
-+ unsigned int i, sum = 0;
-+
-+ for_each_possible_cpu(i)
-+ sum += nr_iowait_cpu(i);
-+
-+ return sum;
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+/*
-+ * sched_exec - execve() is a valuable balancing opportunity, because at
-+ * this point the task has the smallest effective memory and cache
-+ * footprint.
-+ */
-+void sched_exec(void)
-+{
-+ struct task_struct *p = current;
-+ unsigned long flags;
-+ int dest_cpu;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ dest_cpu = cpumask_any(p->cpus_ptr);
-+ if (dest_cpu == smp_processor_id())
-+ goto unlock;
-+
-+ if (likely(cpu_active(dest_cpu))) {
-+ struct migration_arg arg = { p, dest_cpu };
-+
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+ stop_one_cpu(task_cpu(p), migration_cpu_stop, &arg);
-+ return;
-+ }
-+unlock:
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+
-+#endif
-+
-+DEFINE_PER_CPU(struct kernel_stat, kstat);
-+DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
-+
-+EXPORT_PER_CPU_SYMBOL(kstat);
-+EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
-+
-+static inline void update_curr(struct rq *rq, struct task_struct *p)
-+{
-+ s64 ns = rq->clock_task - p->last_ran;
-+
-+ p->sched_time += ns;
-+ cgroup_account_cputime(p, ns);
-+ account_group_exec_runtime(p, ns);
-+
-+ p->time_slice -= ns;
-+ p->last_ran = rq->clock_task;
-+}
-+
-+/*
-+ * Return accounted runtime for the task.
-+ * Return separately the current's pending runtime that have not been
-+ * accounted yet.
-+ */
-+unsigned long long task_sched_runtime(struct task_struct *p)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+ u64 ns;
-+
-+#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
-+ /*
-+ * 64-bit doesn't need locks to atomically read a 64-bit value.
-+ * So we have a optimization chance when the task's delta_exec is 0.
-+ * Reading ->on_cpu is racy, but this is ok.
-+ *
-+ * If we race with it leaving CPU, we'll take a lock. So we're correct.
-+ * If we race with it entering CPU, unaccounted time is 0. This is
-+ * indistinguishable from the read occurring a few cycles earlier.
-+ * If we see ->on_cpu without ->on_rq, the task is leaving, and has
-+ * been accounted, so we're correct here as well.
-+ */
-+ if (!p->on_cpu || !task_on_rq_queued(p))
-+ return tsk_seruntime(p);
-+#endif
-+
-+ rq = task_access_lock_irqsave(p, &lock, &flags);
-+ /*
-+ * Must be ->curr _and_ ->on_rq. If dequeued, we would
-+ * project cycles that may never be accounted to this
-+ * thread, breaking clock_gettime().
-+ */
-+ if (p == rq->curr && task_on_rq_queued(p)) {
-+ update_rq_clock(rq);
-+ update_curr(rq, p);
-+ }
-+ ns = tsk_seruntime(p);
-+ task_access_unlock_irqrestore(p, lock, &flags);
-+
-+ return ns;
-+}
-+
-+/* This manages tasks that have run out of timeslice during a scheduler_tick */
-+static inline void scheduler_task_tick(struct rq *rq)
-+{
-+ struct task_struct *p = rq->curr;
-+
-+ if (is_idle_task(p))
-+ return;
-+
-+ update_curr(rq, p);
-+ cpufreq_update_util(rq, 0);
-+
-+ /*
-+ * Tasks have less than RESCHED_NS of time slice left they will be
-+ * rescheduled.
-+ */
-+ if (p->time_slice >= RESCHED_NS)
-+ return;
-+ set_tsk_need_resched(p);
-+ set_preempt_need_resched();
-+}
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+static u64 cpu_resched_latency(struct rq *rq)
-+{
-+ int latency_warn_ms = READ_ONCE(sysctl_resched_latency_warn_ms);
-+ u64 resched_latency, now = rq_clock(rq);
-+ static bool warned_once;
-+
-+ if (sysctl_resched_latency_warn_once && warned_once)
-+ return 0;
-+
-+ if (!need_resched() || !latency_warn_ms)
-+ return 0;
-+
-+ if (system_state == SYSTEM_BOOTING)
-+ return 0;
-+
-+ if (!rq->last_seen_need_resched_ns) {
-+ rq->last_seen_need_resched_ns = now;
-+ rq->ticks_without_resched = 0;
-+ return 0;
-+ }
-+
-+ rq->ticks_without_resched++;
-+ resched_latency = now - rq->last_seen_need_resched_ns;
-+ if (resched_latency <= latency_warn_ms * NSEC_PER_MSEC)
-+ return 0;
-+
-+ warned_once = true;
-+
-+ return resched_latency;
-+}
-+
-+static int __init setup_resched_latency_warn_ms(char *str)
-+{
-+ long val;
-+
-+ if ((kstrtol(str, 0, &val))) {
-+ pr_warn("Unable to set resched_latency_warn_ms\n");
-+ return 1;
-+ }
-+
-+ sysctl_resched_latency_warn_ms = val;
-+ return 1;
-+}
-+__setup("resched_latency_warn_ms=", setup_resched_latency_warn_ms);
-+#else
-+static inline u64 cpu_resched_latency(struct rq *rq) { return 0; }
-+#endif /* CONFIG_SCHED_DEBUG */
-+
-+/*
-+ * This function gets called by the timer code, with HZ frequency.
-+ * We call it with interrupts disabled.
-+ */
-+void scheduler_tick(void)
-+{
-+ int cpu __maybe_unused = smp_processor_id();
-+ struct rq *rq = cpu_rq(cpu);
-+ u64 resched_latency;
-+
-+ arch_scale_freq_tick();
-+ sched_clock_tick();
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+
-+ scheduler_task_tick(rq);
-+ if (sched_feat(LATENCY_WARN))
-+ resched_latency = cpu_resched_latency(rq);
-+ calc_global_load_tick(rq);
-+
-+ rq->last_tick = rq->clock;
-+ raw_spin_unlock(&rq->lock);
-+
-+ if (sched_feat(LATENCY_WARN) && resched_latency)
-+ resched_latency_warn(cpu, resched_latency);
-+
-+ perf_event_task_tick();
-+}
-+
-+#ifdef CONFIG_SCHED_SMT
-+static inline int active_load_balance_cpu_stop(void *data)
-+{
-+ struct rq *rq = this_rq();
-+ struct task_struct *p = data;
-+ cpumask_t tmp;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ raw_spin_lock(&p->pi_lock);
-+ raw_spin_lock(&rq->lock);
-+
-+ rq->active_balance = 0;
-+ /* _something_ may have changed the task, double check again */
-+ if (task_on_rq_queued(p) && task_rq(p) == rq &&
-+ cpumask_and(&tmp, p->cpus_ptr, &sched_sg_idle_mask) &&
-+ !is_migration_disabled(p)) {
-+ int cpu = cpu_of(rq);
-+ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu));
-+ rq = move_queued_task(rq, p, dcpu);
-+ }
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock(&p->pi_lock);
-+
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+/* sg_balance_trigger - trigger slibing group balance for @cpu */
-+static inline int sg_balance_trigger(const int cpu)
-+{
-+ struct rq *rq= cpu_rq(cpu);
-+ unsigned long flags;
-+ struct task_struct *curr;
-+ int res;
-+
-+ if (!raw_spin_trylock_irqsave(&rq->lock, flags))
-+ return 0;
-+ curr = rq->curr;
-+ res = (!is_idle_task(curr)) && (1 == rq->nr_running) &&\
-+ cpumask_intersects(curr->cpus_ptr, &sched_sg_idle_mask) &&\
-+ !is_migration_disabled(curr) && (!rq->active_balance);
-+
-+ if (res)
-+ rq->active_balance = 1;
-+
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ if (res)
-+ stop_one_cpu_nowait(cpu, active_load_balance_cpu_stop,
-+ curr, &rq->active_balance_work);
-+ return res;
-+}
-+
-+/*
-+ * sg_balance_check - slibing group balance check for run queue @rq
-+ */
-+static inline void sg_balance_check(struct rq *rq)
-+{
-+ cpumask_t chk;
-+ int cpu = cpu_of(rq);
-+
-+ /* exit when cpu is offline */
-+ if (unlikely(!rq->online))
-+ return;
-+
-+ /*
-+ * Only cpu in slibing idle group will do the checking and then
-+ * find potential cpus which can migrate the current running task
-+ */
-+ if (cpumask_test_cpu(cpu, &sched_sg_idle_mask) &&
-+ cpumask_andnot(&chk, cpu_online_mask, sched_rq_watermark) &&
-+ cpumask_andnot(&chk, &chk, &sched_rq_pending_mask)) {
-+ int i;
-+
-+ for_each_cpu_wrap(i, &chk, cpu) {
-+ if (cpumask_subset(cpu_smt_mask(i), &chk) &&
-+ sg_balance_trigger(i))
-+ return;
-+ }
-+ }
-+}
-+#endif /* CONFIG_SCHED_SMT */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+
-+struct tick_work {
-+ int cpu;
-+ atomic_t state;
-+ struct delayed_work work;
-+};
-+/* Values for ->state, see diagram below. */
-+#define TICK_SCHED_REMOTE_OFFLINE 0
-+#define TICK_SCHED_REMOTE_OFFLINING 1
-+#define TICK_SCHED_REMOTE_RUNNING 2
-+
-+/*
-+ * State diagram for ->state:
-+ *
-+ *
-+ * TICK_SCHED_REMOTE_OFFLINE
-+ * | ^
-+ * | |
-+ * | | sched_tick_remote()
-+ * | |
-+ * | |
-+ * +--TICK_SCHED_REMOTE_OFFLINING
-+ * | ^
-+ * | |
-+ * sched_tick_start() | | sched_tick_stop()
-+ * | |
-+ * V |
-+ * TICK_SCHED_REMOTE_RUNNING
-+ *
-+ *
-+ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote()
-+ * and sched_tick_start() are happy to leave the state in RUNNING.
-+ */
-+
-+static struct tick_work __percpu *tick_work_cpu;
-+
-+static void sched_tick_remote(struct work_struct *work)
-+{
-+ struct delayed_work *dwork = to_delayed_work(work);
-+ struct tick_work *twork = container_of(dwork, struct tick_work, work);
-+ int cpu = twork->cpu;
-+ struct rq *rq = cpu_rq(cpu);
-+ struct task_struct *curr;
-+ unsigned long flags;
-+ u64 delta;
-+ int os;
-+
-+ /*
-+ * Handle the tick only if it appears the remote CPU is running in full
-+ * dynticks mode. The check is racy by nature, but missing a tick or
-+ * having one too much is no big deal because the scheduler tick updates
-+ * statistics and checks timeslices in a time-independent way, regardless
-+ * of when exactly it is running.
-+ */
-+ if (!tick_nohz_tick_stopped_cpu(cpu))
-+ goto out_requeue;
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ curr = rq->curr;
-+ if (cpu_is_offline(cpu))
-+ goto out_unlock;
-+
-+ update_rq_clock(rq);
-+ if (!is_idle_task(curr)) {
-+ /*
-+ * Make sure the next tick runs within a reasonable
-+ * amount of time.
-+ */
-+ delta = rq_clock_task(rq) - curr->last_ran;
-+ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3);
-+ }
-+ scheduler_task_tick(rq);
-+
-+ calc_load_nohz_remote(rq);
-+out_unlock:
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+out_requeue:
-+ /*
-+ * Run the remote tick once per second (1Hz). This arbitrary
-+ * frequency is large enough to avoid overload but short enough
-+ * to keep scheduler internal stats reasonably up to date. But
-+ * first update state to reflect hotplug activity if required.
-+ */
-+ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING);
-+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE);
-+ if (os == TICK_SCHED_REMOTE_RUNNING)
-+ queue_delayed_work(system_unbound_wq, dwork, HZ);
-+}
-+
-+static void sched_tick_start(int cpu)
-+{
-+ int os;
-+ struct tick_work *twork;
-+
-+ if (housekeeping_cpu(cpu, HK_FLAG_TICK))
-+ return;
-+
-+ WARN_ON_ONCE(!tick_work_cpu);
-+
-+ twork = per_cpu_ptr(tick_work_cpu, cpu);
-+ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING);
-+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING);
-+ if (os == TICK_SCHED_REMOTE_OFFLINE) {
-+ twork->cpu = cpu;
-+ INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
-+ queue_delayed_work(system_unbound_wq, &twork->work, HZ);
-+ }
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+static void sched_tick_stop(int cpu)
-+{
-+ struct tick_work *twork;
-+
-+ if (housekeeping_cpu(cpu, HK_FLAG_TICK))
-+ return;
-+
-+ WARN_ON_ONCE(!tick_work_cpu);
-+
-+ twork = per_cpu_ptr(tick_work_cpu, cpu);
-+ cancel_delayed_work_sync(&twork->work);
-+}
-+#endif /* CONFIG_HOTPLUG_CPU */
-+
-+int __init sched_tick_offload_init(void)
-+{
-+ tick_work_cpu = alloc_percpu(struct tick_work);
-+ BUG_ON(!tick_work_cpu);
-+ return 0;
-+}
-+
-+#else /* !CONFIG_NO_HZ_FULL */
-+static inline void sched_tick_start(int cpu) { }
-+static inline void sched_tick_stop(int cpu) { }
-+#endif
-+
-+#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \
-+ defined(CONFIG_PREEMPT_TRACER))
-+/*
-+ * If the value passed in is equal to the current preempt count
-+ * then we just disabled preemption. Start timing the latency.
-+ */
-+static inline void preempt_latency_start(int val)
-+{
-+ if (preempt_count() == val) {
-+ unsigned long ip = get_lock_parent_ip();
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ current->preempt_disable_ip = ip;
-+#endif
-+ trace_preempt_off(CALLER_ADDR0, ip);
-+ }
-+}
-+
-+void preempt_count_add(int val)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Underflow?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
-+ return;
-+#endif
-+ __preempt_count_add(val);
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Spinlock count overflowing soon?
-+ */
-+ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
-+ PREEMPT_MASK - 10);
-+#endif
-+ preempt_latency_start(val);
-+}
-+EXPORT_SYMBOL(preempt_count_add);
-+NOKPROBE_SYMBOL(preempt_count_add);
-+
-+/*
-+ * If the value passed in equals to the current preempt count
-+ * then we just enabled preemption. Stop timing the latency.
-+ */
-+static inline void preempt_latency_stop(int val)
-+{
-+ if (preempt_count() == val)
-+ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
-+}
-+
-+void preempt_count_sub(int val)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Underflow?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
-+ return;
-+ /*
-+ * Is the spinlock portion underflowing?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) &&
-+ !(preempt_count() & PREEMPT_MASK)))
-+ return;
-+#endif
-+
-+ preempt_latency_stop(val);
-+ __preempt_count_sub(val);
-+}
-+EXPORT_SYMBOL(preempt_count_sub);
-+NOKPROBE_SYMBOL(preempt_count_sub);
-+
-+#else
-+static inline void preempt_latency_start(int val) { }
-+static inline void preempt_latency_stop(int val) { }
-+#endif
-+
-+static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ return p->preempt_disable_ip;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+/*
-+ * Print scheduling while atomic bug:
-+ */
-+static noinline void __schedule_bug(struct task_struct *prev)
-+{
-+ /* Save this before calling printk(), since that will clobber it */
-+ unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
-+
-+ if (oops_in_progress)
-+ return;
-+
-+ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
-+ prev->comm, prev->pid, preempt_count());
-+
-+ debug_show_held_locks(prev);
-+ print_modules();
-+ if (irqs_disabled())
-+ print_irqtrace_events(prev);
-+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)
-+ && in_atomic_preempt_off()) {
-+ pr_err("Preemption disabled at:");
-+ print_ip_sym(KERN_ERR, preempt_disable_ip);
-+ }
-+ if (panic_on_warn)
-+ panic("scheduling while atomic\n");
-+
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+
-+/*
-+ * Various schedule()-time debugging checks and statistics:
-+ */
-+static inline void schedule_debug(struct task_struct *prev, bool preempt)
-+{
-+#ifdef CONFIG_SCHED_STACK_END_CHECK
-+ if (task_stack_end_corrupted(prev))
-+ panic("corrupted stack end detected inside scheduler\n");
-+
-+ if (task_scs_end_corrupted(prev))
-+ panic("corrupted shadow stack detected inside scheduler\n");
-+#endif
-+
-+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
-+ if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
-+ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n",
-+ prev->comm, prev->pid, prev->non_block_count);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+ }
-+#endif
-+
-+ if (unlikely(in_atomic_preempt_off())) {
-+ __schedule_bug(prev);
-+ preempt_count_set(PREEMPT_DISABLED);
-+ }
-+ rcu_sleep_check();
-+ SCHED_WARN_ON(ct_state() == CONTEXT_USER);
-+
-+ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
-+
-+ schedstat_inc(this_rq()->sched_count);
-+}
-+
-+/*
-+ * Compile time debug macro
-+ * #define ALT_SCHED_DEBUG
-+ */
-+
-+#ifdef ALT_SCHED_DEBUG
-+void alt_sched_debug(void)
-+{
-+ printk(KERN_INFO "sched: pending: 0x%04lx, idle: 0x%04lx, sg_idle: 0x%04lx\n",
-+ sched_rq_pending_mask.bits[0],
-+ sched_rq_watermark[0].bits[0],
-+ sched_sg_idle_mask.bits[0]);
-+}
-+#else
-+inline void alt_sched_debug(void) {}
-+#endif
-+
-+#ifdef CONFIG_SMP
-+
-+#define SCHED_RQ_NR_MIGRATION (32U)
-+/*
-+ * Migrate pending tasks in @rq to @dest_cpu
-+ * Will try to migrate mininal of half of @rq nr_running tasks and
-+ * SCHED_RQ_NR_MIGRATION to @dest_cpu
-+ */
-+static inline int
-+migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, const int dest_cpu)
-+{
-+ struct task_struct *p, *skip = rq->curr;
-+ int nr_migrated = 0;
-+ int nr_tries = min(rq->nr_running / 2, SCHED_RQ_NR_MIGRATION);
-+
-+ while (skip != rq->idle && nr_tries &&
-+ (p = sched_rq_next_task(skip, rq)) != rq->idle) {
-+ skip = sched_rq_next_task(p, rq);
-+ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) {
-+ __SCHED_DEQUEUE_TASK(p, rq, 0, );
-+ set_task_cpu(p, dest_cpu);
-+ sched_task_sanity_check(p, dest_rq);
-+ __SCHED_ENQUEUE_TASK(p, dest_rq, 0);
-+ nr_migrated++;
-+ }
-+ nr_tries--;
-+ }
-+
-+ return nr_migrated;
-+}
-+
-+static inline int take_other_rq_tasks(struct rq *rq, int cpu)
-+{
-+ struct cpumask *topo_mask, *end_mask;
-+
-+ if (unlikely(!rq->online))
-+ return 0;
-+
-+ if (cpumask_empty(&sched_rq_pending_mask))
-+ return 0;
-+
-+ topo_mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+ end_mask = per_cpu(sched_cpu_topo_end_mask, cpu);
-+ do {
-+ int i;
-+ for_each_cpu_and(i, &sched_rq_pending_mask, topo_mask) {
-+ int nr_migrated;
-+ struct rq *src_rq;
-+
-+ src_rq = cpu_rq(i);
-+ if (!do_raw_spin_trylock(&src_rq->lock))
-+ continue;
-+ spin_acquire(&src_rq->lock.dep_map,
-+ SINGLE_DEPTH_NESTING, 1, _RET_IP_);
-+
-+ if ((nr_migrated = migrate_pending_tasks(src_rq, rq, cpu))) {
-+ src_rq->nr_running -= nr_migrated;
-+ if (src_rq->nr_running < 2)
-+ cpumask_clear_cpu(i, &sched_rq_pending_mask);
-+
-+ rq->nr_running += nr_migrated;
-+ if (rq->nr_running > 1)
-+ cpumask_set_cpu(cpu, &sched_rq_pending_mask);
-+
-+ update_sched_rq_watermark(rq);
-+ cpufreq_update_util(rq, 0);
-+
-+ spin_release(&src_rq->lock.dep_map, _RET_IP_);
-+ do_raw_spin_unlock(&src_rq->lock);
-+
-+ return 1;
-+ }
-+
-+ spin_release(&src_rq->lock.dep_map, _RET_IP_);
-+ do_raw_spin_unlock(&src_rq->lock);
-+ }
-+ } while (++topo_mask < end_mask);
-+
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Timeslices below RESCHED_NS are considered as good as expired as there's no
-+ * point rescheduling when there's so little time left.
-+ */
-+static inline void check_curr(struct task_struct *p, struct rq *rq)
-+{
-+ if (unlikely(rq->idle == p))
-+ return;
-+
-+ update_curr(rq, p);
-+
-+ if (p->time_slice < RESCHED_NS)
-+ time_slice_expired(p, rq);
-+}
-+
-+static inline struct task_struct *
-+choose_next_task(struct rq *rq, int cpu, struct task_struct *prev)
-+{
-+ struct task_struct *next;
-+
-+ if (unlikely(rq->skip)) {
-+ next = rq_runnable_task(rq);
-+ if (next == rq->idle) {
-+#ifdef CONFIG_SMP
-+ if (!take_other_rq_tasks(rq, cpu)) {
-+#endif
-+ rq->skip = NULL;
-+ schedstat_inc(rq->sched_goidle);
-+ return next;
-+#ifdef CONFIG_SMP
-+ }
-+ next = rq_runnable_task(rq);
-+#endif
-+ }
-+ rq->skip = NULL;
-+#ifdef CONFIG_HIGH_RES_TIMERS
-+ hrtick_start(rq, next->time_slice);
-+#endif
-+ return next;
-+ }
-+
-+ next = sched_rq_first_task(rq);
-+ if (next == rq->idle) {
-+#ifdef CONFIG_SMP
-+ if (!take_other_rq_tasks(rq, cpu)) {
-+#endif
-+ schedstat_inc(rq->sched_goidle);
-+ /*printk(KERN_INFO "sched: choose_next_task(%d) idle %px\n", cpu, next);*/
-+ return next;
-+#ifdef CONFIG_SMP
-+ }
-+ next = sched_rq_first_task(rq);
-+#endif
-+ }
-+#ifdef CONFIG_HIGH_RES_TIMERS
-+ hrtick_start(rq, next->time_slice);
-+#endif
-+ /*printk(KERN_INFO "sched: choose_next_task(%d) next %px\n", cpu,
-+ * next);*/
-+ return next;
-+}
-+
-+/*
-+ * Constants for the sched_mode argument of __schedule().
-+ *
-+ * The mode argument allows RT enabled kernels to differentiate a
-+ * preemption from blocking on an 'sleeping' spin/rwlock. Note that
-+ * SM_MASK_PREEMPT for !RT has all bits set, which allows the compiler to
-+ * optimize the AND operation out and just check for zero.
-+ */
-+#define SM_NONE 0x0
-+#define SM_PREEMPT 0x1
-+#define SM_RTLOCK_WAIT 0x2
-+
-+#ifndef CONFIG_PREEMPT_RT
-+# define SM_MASK_PREEMPT (~0U)
-+#else
-+# define SM_MASK_PREEMPT SM_PREEMPT
-+#endif
-+
-+/*
-+ * schedule() is the main scheduler function.
-+ *
-+ * The main means of driving the scheduler and thus entering this function are:
-+ *
-+ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc.
-+ *
-+ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return
-+ * paths. For example, see arch/x86/entry_64.S.
-+ *
-+ * To drive preemption between tasks, the scheduler sets the flag in timer
-+ * interrupt handler scheduler_tick().
-+ *
-+ * 3. Wakeups don't really cause entry into schedule(). They add a
-+ * task to the run-queue and that's it.
-+ *
-+ * Now, if the new task added to the run-queue preempts the current
-+ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets
-+ * called on the nearest possible occasion:
-+ *
-+ * - If the kernel is preemptible (CONFIG_PREEMPTION=y):
-+ *
-+ * - in syscall or exception context, at the next outmost
-+ * preempt_enable(). (this might be as soon as the wake_up()'s
-+ * spin_unlock()!)
-+ *
-+ * - in IRQ context, return from interrupt-handler to
-+ * preemptible context
-+ *
-+ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set)
-+ * then at the next:
-+ *
-+ * - cond_resched() call
-+ * - explicit schedule() call
-+ * - return from syscall or exception to user-space
-+ * - return from interrupt-handler to user-space
-+ *
-+ * WARNING: must be called with preemption disabled!
-+ */
-+static void __sched notrace __schedule(unsigned int sched_mode)
-+{
-+ struct task_struct *prev, *next;
-+ unsigned long *switch_count;
-+ unsigned long prev_state;
-+ struct rq *rq;
-+ int cpu;
-+
-+ cpu = smp_processor_id();
-+ rq = cpu_rq(cpu);
-+ prev = rq->curr;
-+
-+ schedule_debug(prev, !!sched_mode);
-+
-+ /* by passing sched_feat(HRTICK) checking which Alt schedule FW doesn't support */
-+ hrtick_clear(rq);
-+
-+ local_irq_disable();
-+ rcu_note_context_switch(!!sched_mode);
-+
-+ /*
-+ * Make sure that signal_pending_state()->signal_pending() below
-+ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
-+ * done by the caller to avoid the race with signal_wake_up():
-+ *
-+ * __set_current_state(@state) signal_wake_up()
-+ * schedule() set_tsk_thread_flag(p, TIF_SIGPENDING)
-+ * wake_up_state(p, state)
-+ * LOCK rq->lock LOCK p->pi_state
-+ * smp_mb__after_spinlock() smp_mb__after_spinlock()
-+ * if (signal_pending_state()) if (p->state & @state)
-+ *
-+ * Also, the membarrier system call requires a full memory barrier
-+ * after coming from user-space, before storing to rq->curr.
-+ */
-+ raw_spin_lock(&rq->lock);
-+ smp_mb__after_spinlock();
-+
-+ update_rq_clock(rq);
-+
-+ switch_count = &prev->nivcsw;
-+ /*
-+ * We must load prev->state once (task_struct::state is volatile), such
-+ * that:
-+ *
-+ * - we form a control dependency vs deactivate_task() below.
-+ * - ptrace_{,un}freeze_traced() can change ->state underneath us.
-+ */
-+ prev_state = READ_ONCE(prev->__state);
-+ if (!(sched_mode & SM_MASK_PREEMPT) && prev_state) {
-+ if (signal_pending_state(prev_state, prev)) {
-+ WRITE_ONCE(prev->__state, TASK_RUNNING);
-+ } else {
-+ prev->sched_contributes_to_load =
-+ (prev_state & TASK_UNINTERRUPTIBLE) &&
-+ !(prev_state & TASK_NOLOAD) &&
-+ !(prev->flags & PF_FROZEN);
-+
-+ if (prev->sched_contributes_to_load)
-+ rq->nr_uninterruptible++;
-+
-+ /*
-+ * __schedule() ttwu()
-+ * prev_state = prev->state; if (p->on_rq && ...)
-+ * if (prev_state) goto out;
-+ * p->on_rq = 0; smp_acquire__after_ctrl_dep();
-+ * p->state = TASK_WAKING
-+ *
-+ * Where __schedule() and ttwu() have matching control dependencies.
-+ *
-+ * After this, schedule() must not care about p->state any more.
-+ */
-+ sched_task_deactivate(prev, rq);
-+ deactivate_task(prev, rq);
-+
-+ if (prev->in_iowait) {
-+ atomic_inc(&rq->nr_iowait);
-+ delayacct_blkio_start();
-+ }
-+ }
-+ switch_count = &prev->nvcsw;
-+ }
-+
-+ check_curr(prev, rq);
-+
-+ next = choose_next_task(rq, cpu, prev);
-+ clear_tsk_need_resched(prev);
-+ clear_preempt_need_resched();
-+#ifdef CONFIG_SCHED_DEBUG
-+ rq->last_seen_need_resched_ns = 0;
-+#endif
-+
-+ if (likely(prev != next)) {
-+ next->last_ran = rq->clock_task;
-+ rq->last_ts_switch = rq->clock;
-+
-+ rq->nr_switches++;
-+ /*
-+ * RCU users of rcu_dereference(rq->curr) may not see
-+ * changes to task_struct made by pick_next_task().
-+ */
-+ RCU_INIT_POINTER(rq->curr, next);
-+ /*
-+ * The membarrier system call requires each architecture
-+ * to have a full memory barrier after updating
-+ * rq->curr, before returning to user-space.
-+ *
-+ * Here are the schemes providing that barrier on the
-+ * various architectures:
-+ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
-+ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
-+ * - finish_lock_switch() for weakly-ordered
-+ * architectures where spin_unlock is a full barrier,
-+ * - switch_to() for arm64 (weakly-ordered, spin_unlock
-+ * is a RELEASE barrier),
-+ */
-+ ++*switch_count;
-+
-+ psi_sched_switch(prev, next, !task_on_rq_queued(prev));
-+
-+ trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next);
-+
-+ /* Also unlocks the rq: */
-+ rq = context_switch(rq, prev, next);
-+ } else {
-+ __balance_callbacks(rq);
-+ raw_spin_unlock_irq(&rq->lock);
-+ }
-+
-+#ifdef CONFIG_SCHED_SMT
-+ sg_balance_check(rq);
-+#endif
-+}
-+
-+void __noreturn do_task_dead(void)
-+{
-+ /* Causes final put_task_struct in finish_task_switch(): */
-+ set_special_state(TASK_DEAD);
-+
-+ /* Tell freezer to ignore us: */
-+ current->flags |= PF_NOFREEZE;
-+
-+ __schedule(SM_NONE);
-+ BUG();
-+
-+ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */
-+ for (;;)
-+ cpu_relax();
-+}
-+
-+static inline void sched_submit_work(struct task_struct *tsk)
-+{
-+ unsigned int task_flags;
-+
-+ if (task_is_running(tsk))
-+ return;
-+
-+ task_flags = tsk->flags;
-+ /*
-+ * If a worker went to sleep, notify and ask workqueue whether
-+ * it wants to wake up a task to maintain concurrency.
-+ * As this function is called inside the schedule() context,
-+ * we disable preemption to avoid it calling schedule() again
-+ * in the possible wakeup of a kworker and because wq_worker_sleeping()
-+ * requires it.
-+ */
-+ if (task_flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
-+ preempt_disable();
-+ if (task_flags & PF_WQ_WORKER)
-+ wq_worker_sleeping(tsk);
-+ else
-+ io_wq_worker_sleeping(tsk);
-+ preempt_enable_no_resched();
-+ }
-+
-+ if (tsk_is_pi_blocked(tsk))
-+ return;
-+
-+ /*
-+ * If we are going to sleep and we have plugged IO queued,
-+ * make sure to submit it to avoid deadlocks.
-+ */
-+ if (blk_needs_flush_plug(tsk))
-+ blk_schedule_flush_plug(tsk);
-+}
-+
-+static void sched_update_worker(struct task_struct *tsk)
-+{
-+ if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
-+ if (tsk->flags & PF_WQ_WORKER)
-+ wq_worker_running(tsk);
-+ else
-+ io_wq_worker_running(tsk);
-+ }
-+}
-+
-+asmlinkage __visible void __sched schedule(void)
-+{
-+ struct task_struct *tsk = current;
-+
-+ sched_submit_work(tsk);
-+ do {
-+ preempt_disable();
-+ __schedule(SM_NONE);
-+ sched_preempt_enable_no_resched();
-+ } while (need_resched());
-+ sched_update_worker(tsk);
-+}
-+EXPORT_SYMBOL(schedule);
-+
-+/*
-+ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
-+ * state (have scheduled out non-voluntarily) by making sure that all
-+ * tasks have either left the run queue or have gone into user space.
-+ * As idle tasks do not do either, they must not ever be preempted
-+ * (schedule out non-voluntarily).
-+ *
-+ * schedule_idle() is similar to schedule_preempt_disable() except that it
-+ * never enables preemption because it does not call sched_submit_work().
-+ */
-+void __sched schedule_idle(void)
-+{
-+ /*
-+ * As this skips calling sched_submit_work(), which the idle task does
-+ * regardless because that function is a nop when the task is in a
-+ * TASK_RUNNING state, make sure this isn't used someplace that the
-+ * current task can be in any other state. Note, idle is always in the
-+ * TASK_RUNNING state.
-+ */
-+ WARN_ON_ONCE(current->__state);
-+ do {
-+ __schedule(SM_NONE);
-+ } while (need_resched());
-+}
-+
-+#if defined(CONFIG_CONTEXT_TRACKING) && !defined(CONFIG_HAVE_CONTEXT_TRACKING_OFFSTACK)
-+asmlinkage __visible void __sched schedule_user(void)
-+{
-+ /*
-+ * If we come here after a random call to set_need_resched(),
-+ * or we have been woken up remotely but the IPI has not yet arrived,
-+ * we haven't yet exited the RCU idle mode. Do it here manually until
-+ * we find a better solution.
-+ *
-+ * NB: There are buggy callers of this function. Ideally we
-+ * should warn if prev_state != CONTEXT_USER, but that will trigger
-+ * too frequently to make sense yet.
-+ */
-+ enum ctx_state prev_state = exception_enter();
-+ schedule();
-+ exception_exit(prev_state);
-+}
-+#endif
-+
-+/**
-+ * schedule_preempt_disabled - called with preemption disabled
-+ *
-+ * Returns with preemption disabled. Note: preempt_count must be 1
-+ */
-+void __sched schedule_preempt_disabled(void)
-+{
-+ sched_preempt_enable_no_resched();
-+ schedule();
-+ preempt_disable();
-+}
-+
-+#ifdef CONFIG_PREEMPT_RT
-+void __sched notrace schedule_rtlock(void)
-+{
-+ do {
-+ preempt_disable();
-+ __schedule(SM_RTLOCK_WAIT);
-+ sched_preempt_enable_no_resched();
-+ } while (need_resched());
-+}
-+NOKPROBE_SYMBOL(schedule_rtlock);
-+#endif
-+
-+static void __sched notrace preempt_schedule_common(void)
-+{
-+ do {
-+ /*
-+ * Because the function tracer can trace preempt_count_sub()
-+ * and it also uses preempt_enable/disable_notrace(), if
-+ * NEED_RESCHED is set, the preempt_enable_notrace() called
-+ * by the function tracer will call this function again and
-+ * cause infinite recursion.
-+ *
-+ * Preemption must be disabled here before the function
-+ * tracer can trace. Break up preempt_disable() into two
-+ * calls. One to disable preemption without fear of being
-+ * traced. The other to still record the preemption latency,
-+ * which can also be traced by the function tracer.
-+ */
-+ preempt_disable_notrace();
-+ preempt_latency_start(1);
-+ __schedule(SM_PREEMPT);
-+ preempt_latency_stop(1);
-+ preempt_enable_no_resched_notrace();
-+
-+ /*
-+ * Check again in case we missed a preemption opportunity
-+ * between schedule and now.
-+ */
-+ } while (need_resched());
-+}
-+
-+#ifdef CONFIG_PREEMPTION
-+/*
-+ * This is the entry point to schedule() from in-kernel preemption
-+ * off of preempt_enable.
-+ */
-+asmlinkage __visible void __sched notrace preempt_schedule(void)
-+{
-+ /*
-+ * If there is a non-zero preempt_count or interrupts are disabled,
-+ * we do not want to preempt the current task. Just return..
-+ */
-+ if (likely(!preemptible()))
-+ return;
-+
-+ preempt_schedule_common();
-+}
-+NOKPROBE_SYMBOL(preempt_schedule);
-+EXPORT_SYMBOL(preempt_schedule);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+DEFINE_STATIC_CALL(preempt_schedule, __preempt_schedule_func);
-+EXPORT_STATIC_CALL_TRAMP(preempt_schedule);
-+#endif
-+
-+
-+/**
-+ * preempt_schedule_notrace - preempt_schedule called by tracing
-+ *
-+ * The tracing infrastructure uses preempt_enable_notrace to prevent
-+ * recursion and tracing preempt enabling caused by the tracing
-+ * infrastructure itself. But as tracing can happen in areas coming
-+ * from userspace or just about to enter userspace, a preempt enable
-+ * can occur before user_exit() is called. This will cause the scheduler
-+ * to be called when the system is still in usermode.
-+ *
-+ * To prevent this, the preempt_enable_notrace will use this function
-+ * instead of preempt_schedule() to exit user context if needed before
-+ * calling the scheduler.
-+ */
-+asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
-+{
-+ enum ctx_state prev_ctx;
-+
-+ if (likely(!preemptible()))
-+ return;
-+
-+ do {
-+ /*
-+ * Because the function tracer can trace preempt_count_sub()
-+ * and it also uses preempt_enable/disable_notrace(), if
-+ * NEED_RESCHED is set, the preempt_enable_notrace() called
-+ * by the function tracer will call this function again and
-+ * cause infinite recursion.
-+ *
-+ * Preemption must be disabled here before the function
-+ * tracer can trace. Break up preempt_disable() into two
-+ * calls. One to disable preemption without fear of being
-+ * traced. The other to still record the preemption latency,
-+ * which can also be traced by the function tracer.
-+ */
-+ preempt_disable_notrace();
-+ preempt_latency_start(1);
-+ /*
-+ * Needs preempt disabled in case user_exit() is traced
-+ * and the tracer calls preempt_enable_notrace() causing
-+ * an infinite recursion.
-+ */
-+ prev_ctx = exception_enter();
-+ __schedule(SM_PREEMPT);
-+ exception_exit(prev_ctx);
-+
-+ preempt_latency_stop(1);
-+ preempt_enable_no_resched_notrace();
-+ } while (need_resched());
-+}
-+EXPORT_SYMBOL_GPL(preempt_schedule_notrace);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+DEFINE_STATIC_CALL(preempt_schedule_notrace, __preempt_schedule_notrace_func);
-+EXPORT_STATIC_CALL_TRAMP(preempt_schedule_notrace);
-+#endif
-+
-+#endif /* CONFIG_PREEMPTION */
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+
-+#include <linux/entry-common.h>
-+
-+/*
-+ * SC:cond_resched
-+ * SC:might_resched
-+ * SC:preempt_schedule
-+ * SC:preempt_schedule_notrace
-+ * SC:irqentry_exit_cond_resched
-+ *
-+ *
-+ * NONE:
-+ * cond_resched <- __cond_resched
-+ * might_resched <- RET0
-+ * preempt_schedule <- NOP
-+ * preempt_schedule_notrace <- NOP
-+ * irqentry_exit_cond_resched <- NOP
-+ *
-+ * VOLUNTARY:
-+ * cond_resched <- __cond_resched
-+ * might_resched <- __cond_resched
-+ * preempt_schedule <- NOP
-+ * preempt_schedule_notrace <- NOP
-+ * irqentry_exit_cond_resched <- NOP
-+ *
-+ * FULL:
-+ * cond_resched <- RET0
-+ * might_resched <- RET0
-+ * preempt_schedule <- preempt_schedule
-+ * preempt_schedule_notrace <- preempt_schedule_notrace
-+ * irqentry_exit_cond_resched <- irqentry_exit_cond_resched
-+ */
-+
-+enum {
-+ preempt_dynamic_none = 0,
-+ preempt_dynamic_voluntary,
-+ preempt_dynamic_full,
-+};
-+
-+int preempt_dynamic_mode = preempt_dynamic_full;
-+
-+int sched_dynamic_mode(const char *str)
-+{
-+ if (!strcmp(str, "none"))
-+ return preempt_dynamic_none;
-+
-+ if (!strcmp(str, "voluntary"))
-+ return preempt_dynamic_voluntary;
-+
-+ if (!strcmp(str, "full"))
-+ return preempt_dynamic_full;
-+
-+ return -EINVAL;
-+}
-+
-+void sched_dynamic_update(int mode)
-+{
-+ /*
-+ * Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
-+ * the ZERO state, which is invalid.
-+ */
-+ static_call_update(cond_resched, __cond_resched);
-+ static_call_update(might_resched, __cond_resched);
-+ static_call_update(preempt_schedule, __preempt_schedule_func);
-+ static_call_update(preempt_schedule_notrace, __preempt_schedule_notrace_func);
-+ static_call_update(irqentry_exit_cond_resched, irqentry_exit_cond_resched);
-+
-+ switch (mode) {
-+ case preempt_dynamic_none:
-+ static_call_update(cond_resched, __cond_resched);
-+ static_call_update(might_resched, (void *)&__static_call_return0);
-+ static_call_update(preempt_schedule, NULL);
-+ static_call_update(preempt_schedule_notrace, NULL);
-+ static_call_update(irqentry_exit_cond_resched, NULL);
-+ pr_info("Dynamic Preempt: none\n");
-+ break;
-+
-+ case preempt_dynamic_voluntary:
-+ static_call_update(cond_resched, __cond_resched);
-+ static_call_update(might_resched, __cond_resched);
-+ static_call_update(preempt_schedule, NULL);
-+ static_call_update(preempt_schedule_notrace, NULL);
-+ static_call_update(irqentry_exit_cond_resched, NULL);
-+ pr_info("Dynamic Preempt: voluntary\n");
-+ break;
-+
-+ case preempt_dynamic_full:
-+ static_call_update(cond_resched, (void *)&__static_call_return0);
-+ static_call_update(might_resched, (void *)&__static_call_return0);
-+ static_call_update(preempt_schedule, __preempt_schedule_func);
-+ static_call_update(preempt_schedule_notrace, __preempt_schedule_notrace_func);
-+ static_call_update(irqentry_exit_cond_resched, irqentry_exit_cond_resched);
-+ pr_info("Dynamic Preempt: full\n");
-+ break;
-+ }
-+
-+ preempt_dynamic_mode = mode;
-+}
-+
-+static int __init setup_preempt_mode(char *str)
-+{
-+ int mode = sched_dynamic_mode(str);
-+ if (mode < 0) {
-+ pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
-+ return 1;
-+ }
-+
-+ sched_dynamic_update(mode);
-+ return 0;
-+}
-+__setup("preempt=", setup_preempt_mode);
-+
-+#endif /* CONFIG_PREEMPT_DYNAMIC */
-+
-+/*
-+ * This is the entry point to schedule() from kernel preemption
-+ * off of irq context.
-+ * Note, that this is called and return with irqs disabled. This will
-+ * protect us against recursive calling from irq.
-+ */
-+asmlinkage __visible void __sched preempt_schedule_irq(void)
-+{
-+ enum ctx_state prev_state;
-+
-+ /* Catch callers which need to be fixed */
-+ BUG_ON(preempt_count() || !irqs_disabled());
-+
-+ prev_state = exception_enter();
-+
-+ do {
-+ preempt_disable();
-+ local_irq_enable();
-+ __schedule(SM_PREEMPT);
-+ local_irq_disable();
-+ sched_preempt_enable_no_resched();
-+ } while (need_resched());
-+
-+ exception_exit(prev_state);
-+}
-+
-+int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags,
-+ void *key)
-+{
-+ WARN_ON_ONCE(IS_ENABLED(CONFIG_SCHED_DEBUG) && wake_flags & ~WF_SYNC);
-+ return try_to_wake_up(curr->private, mode, wake_flags);
-+}
-+EXPORT_SYMBOL(default_wake_function);
-+
-+static inline void check_task_changed(struct task_struct *p, struct rq *rq)
-+{
-+ /* Trigger resched if task sched_prio has been modified. */
-+ if (task_on_rq_queued(p) && task_sched_prio_idx(p, rq) != p->sq_idx) {
-+ requeue_task(p, rq);
-+ check_preempt_curr(rq);
-+ }
-+}
-+
-+static void __setscheduler_prio(struct task_struct *p, int prio)
-+{
-+ p->prio = prio;
-+}
-+
-+#ifdef CONFIG_RT_MUTEXES
-+
-+static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
-+{
-+ if (pi_task)
-+ prio = min(prio, pi_task->prio);
-+
-+ return prio;
-+}
-+
-+static inline int rt_effective_prio(struct task_struct *p, int prio)
-+{
-+ struct task_struct *pi_task = rt_mutex_get_top_task(p);
-+
-+ return __rt_effective_prio(pi_task, prio);
-+}
-+
-+/*
-+ * rt_mutex_setprio - set the current priority of a task
-+ * @p: task to boost
-+ * @pi_task: donor task
-+ *
-+ * This function changes the 'effective' priority of a task. It does
-+ * not touch ->normal_prio like __setscheduler().
-+ *
-+ * Used by the rt_mutex code to implement priority inheritance
-+ * logic. Call site only calls if the priority of the task changed.
-+ */
-+void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
-+{
-+ int prio;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ /* XXX used to be waiter->prio, not waiter->task->prio */
-+ prio = __rt_effective_prio(pi_task, p->normal_prio);
-+
-+ /*
-+ * If nothing changed; bail early.
-+ */
-+ if (p->pi_top_task == pi_task && prio == p->prio)
-+ return;
-+
-+ rq = __task_access_lock(p, &lock);
-+ /*
-+ * Set under pi_lock && rq->lock, such that the value can be used under
-+ * either lock.
-+ *
-+ * Note that there is loads of tricky to make this pointer cache work
-+ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to
-+ * ensure a task is de-boosted (pi_task is set to NULL) before the
-+ * task is allowed to run again (and can exit). This ensures the pointer
-+ * points to a blocked task -- which guarantees the task is present.
-+ */
-+ p->pi_top_task = pi_task;
-+
-+ /*
-+ * For FIFO/RR we only need to set prio, if that matches we're done.
-+ */
-+ if (prio == p->prio)
-+ goto out_unlock;
-+
-+ /*
-+ * Idle task boosting is a nono in general. There is one
-+ * exception, when PREEMPT_RT and NOHZ is active:
-+ *
-+ * The idle task calls get_next_timer_interrupt() and holds
-+ * the timer wheel base->lock on the CPU and another CPU wants
-+ * to access the timer (probably to cancel it). We can safely
-+ * ignore the boosting request, as the idle CPU runs this code
-+ * with interrupts disabled and will complete the lock
-+ * protected section without being interrupted. So there is no
-+ * real need to boost.
-+ */
-+ if (unlikely(p == rq->idle)) {
-+ WARN_ON(p != rq->curr);
-+ WARN_ON(p->pi_blocked_on);
-+ goto out_unlock;
-+ }
-+
-+ trace_sched_pi_setprio(p, pi_task);
-+
-+ __setscheduler_prio(p, prio);
-+
-+ check_task_changed(p, rq);
-+out_unlock:
-+ /* Avoid rq from going away on us: */
-+ preempt_disable();
-+
-+ __balance_callbacks(rq);
-+ __task_access_unlock(p, lock);
-+
-+ preempt_enable();
-+}
-+#else
-+static inline int rt_effective_prio(struct task_struct *p, int prio)
-+{
-+ return prio;
-+}
-+#endif
-+
-+void set_user_nice(struct task_struct *p, long nice)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE)
-+ return;
-+ /*
-+ * We have to be careful, if called from sys_setpriority(),
-+ * the task might be in the middle of scheduling on another CPU.
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ rq = __task_access_lock(p, &lock);
-+
-+ p->static_prio = NICE_TO_PRIO(nice);
-+ /*
-+ * The RT priorities are set via sched_setscheduler(), but we still
-+ * allow the 'normal' nice value to be set - but as expected
-+ * it won't have any effect on scheduling until the task is
-+ * not SCHED_NORMAL/SCHED_BATCH:
-+ */
-+ if (task_has_rt_policy(p))
-+ goto out_unlock;
-+
-+ p->prio = effective_prio(p);
-+
-+ check_task_changed(p, rq);
-+out_unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+EXPORT_SYMBOL(set_user_nice);
-+
-+/*
-+ * can_nice - check if a task can reduce its nice value
-+ * @p: task
-+ * @nice: nice value
-+ */
-+int can_nice(const struct task_struct *p, const int nice)
-+{
-+ /* Convert nice value [19,-20] to rlimit style value [1,40] */
-+ int nice_rlim = nice_to_rlimit(nice);
-+
-+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
-+ capable(CAP_SYS_NICE));
-+}
-+
-+#ifdef __ARCH_WANT_SYS_NICE
-+
-+/*
-+ * sys_nice - change the priority of the current process.
-+ * @increment: priority increment
-+ *
-+ * sys_setpriority is a more generic, but much slower function that
-+ * does similar things.
-+ */
-+SYSCALL_DEFINE1(nice, int, increment)
-+{
-+ long nice, retval;
-+
-+ /*
-+ * Setpriority might change our priority at the same moment.
-+ * We don't have to worry. Conceptually one call occurs first
-+ * and we have a single winner.
-+ */
-+
-+ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH);
-+ nice = task_nice(current) + increment;
-+
-+ nice = clamp_val(nice, MIN_NICE, MAX_NICE);
-+ if (increment < 0 && !can_nice(current, nice))
-+ return -EPERM;
-+
-+ retval = security_task_setnice(current, nice);
-+ if (retval)
-+ return retval;
-+
-+ set_user_nice(current, nice);
-+ return 0;
-+}
-+
-+#endif
-+
-+/**
-+ * task_prio - return the priority value of a given task.
-+ * @p: the task in question.
-+ *
-+ * Return: The priority value as seen by users in /proc.
-+ *
-+ * sched policy return value kernel prio user prio/nice
-+ *
-+ * (BMQ)normal, batch, idle[0 ... 53] [100 ... 139] 0/[-20 ... 19]/[-7 ... 7]
-+ * (PDS)normal, batch, idle[0 ... 39] 100 0/[-20 ... 19]
-+ * fifo, rr [-1 ... -100] [99 ... 0] [0 ... 99]
-+ */
-+int task_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MAX_RT_PRIO) ? p->prio - MAX_RT_PRIO :
-+ task_sched_prio_normal(p, task_rq(p));
-+}
-+
-+/**
-+ * idle_cpu - is a given CPU idle currently?
-+ * @cpu: the processor in question.
-+ *
-+ * Return: 1 if the CPU is currently idle. 0 otherwise.
-+ */
-+int idle_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (rq->curr != rq->idle)
-+ return 0;
-+
-+ if (rq->nr_running)
-+ return 0;
-+
-+#ifdef CONFIG_SMP
-+ if (rq->ttwu_pending)
-+ return 0;
-+#endif
-+
-+ return 1;
-+}
-+
-+/**
-+ * idle_task - return the idle task for a given CPU.
-+ * @cpu: the processor in question.
-+ *
-+ * Return: The idle task for the cpu @cpu.
-+ */
-+struct task_struct *idle_task(int cpu)
-+{
-+ return cpu_rq(cpu)->idle;
-+}
-+
-+/**
-+ * find_process_by_pid - find a process with a matching PID value.
-+ * @pid: the pid in question.
-+ *
-+ * The task of @pid, if found. %NULL otherwise.
-+ */
-+static inline struct task_struct *find_process_by_pid(pid_t pid)
-+{
-+ return pid ? find_task_by_vpid(pid) : current;
-+}
-+
-+/*
-+ * sched_setparam() passes in -1 for its policy, to let the functions
-+ * it calls know not to change it.
-+ */
-+#define SETPARAM_POLICY -1
-+
-+static void __setscheduler_params(struct task_struct *p,
-+ const struct sched_attr *attr)
-+{
-+ int policy = attr->sched_policy;
-+
-+ if (policy == SETPARAM_POLICY)
-+ policy = p->policy;
-+
-+ p->policy = policy;
-+
-+ /*
-+ * allow normal nice value to be set, but will not have any
-+ * effect on scheduling until the task not SCHED_NORMAL/
-+ * SCHED_BATCH
-+ */
-+ p->static_prio = NICE_TO_PRIO(attr->sched_nice);
-+
-+ /*
-+ * __sched_setscheduler() ensures attr->sched_priority == 0 when
-+ * !rt_policy. Always setting this ensures that things like
-+ * getparam()/getattr() don't report silly values for !rt tasks.
-+ */
-+ p->rt_priority = attr->sched_priority;
-+ p->normal_prio = normal_prio(p);
-+}
-+
-+/*
-+ * check the target process has a UID that matches the current process's
-+ */
-+static bool check_same_owner(struct task_struct *p)
-+{
-+ const struct cred *cred = current_cred(), *pcred;
-+ bool match;
-+
-+ rcu_read_lock();
-+ pcred = __task_cred(p);
-+ match = (uid_eq(cred->euid, pcred->euid) ||
-+ uid_eq(cred->euid, pcred->uid));
-+ rcu_read_unlock();
-+ return match;
-+}
-+
-+static int __sched_setscheduler(struct task_struct *p,
-+ const struct sched_attr *attr,
-+ bool user, bool pi)
-+{
-+ const struct sched_attr dl_squash_attr = {
-+ .size = sizeof(struct sched_attr),
-+ .sched_policy = SCHED_FIFO,
-+ .sched_nice = 0,
-+ .sched_priority = 99,
-+ };
-+ int oldpolicy = -1, policy = attr->sched_policy;
-+ int retval, newprio;
-+ struct callback_head *head;
-+ unsigned long flags;
-+ struct rq *rq;
-+ int reset_on_fork;
-+ raw_spinlock_t *lock;
-+
-+ /* The pi code expects interrupts enabled */
-+ BUG_ON(pi && in_interrupt());
-+
-+ /*
-+ * Alt schedule FW supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO
-+ */
-+ if (unlikely(SCHED_DEADLINE == policy)) {
-+ attr = &dl_squash_attr;
-+ policy = attr->sched_policy;
-+ }
-+recheck:
-+ /* Double check policy once rq lock held */
-+ if (policy < 0) {
-+ reset_on_fork = p->sched_reset_on_fork;
-+ policy = oldpolicy = p->policy;
-+ } else {
-+ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK);
-+
-+ if (policy > SCHED_IDLE)
-+ return -EINVAL;
-+ }
-+
-+ if (attr->sched_flags & ~(SCHED_FLAG_ALL))
-+ return -EINVAL;
-+
-+ /*
-+ * Valid priorities for SCHED_FIFO and SCHED_RR are
-+ * 1..MAX_RT_PRIO-1, valid priority for SCHED_NORMAL and
-+ * SCHED_BATCH and SCHED_IDLE is 0.
-+ */
-+ if (attr->sched_priority < 0 ||
-+ (p->mm && attr->sched_priority > MAX_RT_PRIO - 1) ||
-+ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1))
-+ return -EINVAL;
-+ if ((SCHED_RR == policy || SCHED_FIFO == policy) !=
-+ (attr->sched_priority != 0))
-+ return -EINVAL;
-+
-+ /*
-+ * Allow unprivileged RT tasks to decrease priority:
-+ */
-+ if (user && !capable(CAP_SYS_NICE)) {
-+ if (SCHED_FIFO == policy || SCHED_RR == policy) {
-+ unsigned long rlim_rtprio =
-+ task_rlimit(p, RLIMIT_RTPRIO);
-+
-+ /* Can't set/change the rt policy */
-+ if (policy != p->policy && !rlim_rtprio)
-+ return -EPERM;
-+
-+ /* Can't increase priority */
-+ if (attr->sched_priority > p->rt_priority &&
-+ attr->sched_priority > rlim_rtprio)
-+ return -EPERM;
-+ }
-+
-+ /* Can't change other user's priorities */
-+ if (!check_same_owner(p))
-+ return -EPERM;
-+
-+ /* Normal users shall not reset the sched_reset_on_fork flag */
-+ if (p->sched_reset_on_fork && !reset_on_fork)
-+ return -EPERM;
-+ }
-+
-+ if (user) {
-+ retval = security_task_setscheduler(p);
-+ if (retval)
-+ return retval;
-+ }
-+
-+ if (pi)
-+ cpuset_read_lock();
-+
-+ /*
-+ * Make sure no PI-waiters arrive (or leave) while we are
-+ * changing the priority of the task:
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+
-+ /*
-+ * To be able to change p->policy safely, task_access_lock()
-+ * must be called.
-+ * IF use task_access_lock() here:
-+ * For the task p which is not running, reading rq->stop is
-+ * racy but acceptable as ->stop doesn't change much.
-+ * An enhancemnet can be made to read rq->stop saftly.
-+ */
-+ rq = __task_access_lock(p, &lock);
-+
-+ /*
-+ * Changing the policy of the stop threads its a very bad idea
-+ */
-+ if (p == rq->stop) {
-+ retval = -EINVAL;
-+ goto unlock;
-+ }
-+
-+ /*
-+ * If not changing anything there's no need to proceed further:
-+ */
-+ if (unlikely(policy == p->policy)) {
-+ if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
-+ goto change;
-+ if (!rt_policy(policy) &&
-+ NICE_TO_PRIO(attr->sched_nice) != p->static_prio)
-+ goto change;
-+
-+ p->sched_reset_on_fork = reset_on_fork;
-+ retval = 0;
-+ goto unlock;
-+ }
-+change:
-+
-+ /* Re-check policy now with rq lock held */
-+ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
-+ policy = oldpolicy = -1;
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+ if (pi)
-+ cpuset_read_unlock();
-+ goto recheck;
-+ }
-+
-+ p->sched_reset_on_fork = reset_on_fork;
-+
-+ newprio = __normal_prio(policy, attr->sched_priority, NICE_TO_PRIO(attr->sched_nice));
-+ if (pi) {
-+ /*
-+ * Take priority boosted tasks into account. If the new
-+ * effective priority is unchanged, we just store the new
-+ * normal parameters and do not touch the scheduler class and
-+ * the runqueue. This will be done when the task deboost
-+ * itself.
-+ */
-+ newprio = rt_effective_prio(p, newprio);
-+ }
-+
-+ if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
-+ __setscheduler_params(p, attr);
-+ __setscheduler_prio(p, newprio);
-+ }
-+
-+ check_task_changed(p, rq);
-+
-+ /* Avoid rq from going away on us: */
-+ preempt_disable();
-+ head = splice_balance_callbacks(rq);
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+
-+ if (pi) {
-+ cpuset_read_unlock();
-+ rt_mutex_adjust_pi(p);
-+ }
-+
-+ /* Run balance callbacks after we've adjusted the PI chain: */
-+ balance_callbacks(rq, head);
-+ preempt_enable();
-+
-+ return 0;
-+
-+unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+ if (pi)
-+ cpuset_read_unlock();
-+ return retval;
-+}
-+
-+static int _sched_setscheduler(struct task_struct *p, int policy,
-+ const struct sched_param *param, bool check)
-+{
-+ struct sched_attr attr = {
-+ .sched_policy = policy,
-+ .sched_priority = param->sched_priority,
-+ .sched_nice = PRIO_TO_NICE(p->static_prio),
-+ };
-+
-+ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */
-+ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) {
-+ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
-+ policy &= ~SCHED_RESET_ON_FORK;
-+ attr.sched_policy = policy;
-+ }
-+
-+ return __sched_setscheduler(p, &attr, check, true);
-+}
-+
-+/**
-+ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
-+ * @p: the task in question.
-+ * @policy: new policy.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Use sched_set_fifo(), read its comment.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ *
-+ * NOTE that the task may be already dead.
-+ */
-+int sched_setscheduler(struct task_struct *p, int policy,
-+ const struct sched_param *param)
-+{
-+ return _sched_setscheduler(p, policy, param, true);
-+}
-+
-+int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
-+{
-+ return __sched_setscheduler(p, attr, true, true);
-+}
-+
-+int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr)
-+{
-+ return __sched_setscheduler(p, attr, false, true);
-+}
-+EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
-+
-+/**
-+ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
-+ * @p: the task in question.
-+ * @policy: new policy.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Just like sched_setscheduler, only don't bother checking if the
-+ * current context has permission. For example, this is needed in
-+ * stop_machine(): we create temporary high priority worker threads,
-+ * but our caller might not have that capability.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+int sched_setscheduler_nocheck(struct task_struct *p, int policy,
-+ const struct sched_param *param)
-+{
-+ return _sched_setscheduler(p, policy, param, false);
-+}
-+
-+/*
-+ * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally
-+ * incapable of resource management, which is the one thing an OS really should
-+ * be doing.
-+ *
-+ * This is of course the reason it is limited to privileged users only.
-+ *
-+ * Worse still; it is fundamentally impossible to compose static priority
-+ * workloads. You cannot take two correctly working static prio workloads
-+ * and smash them together and still expect them to work.
-+ *
-+ * For this reason 'all' FIFO tasks the kernel creates are basically at:
-+ *
-+ * MAX_RT_PRIO / 2
-+ *
-+ * The administrator _MUST_ configure the system, the kernel simply doesn't
-+ * know enough information to make a sensible choice.
-+ */
-+void sched_set_fifo(struct task_struct *p)
-+{
-+ struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 };
-+ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_fifo);
-+
-+/*
-+ * For when you don't much care about FIFO, but want to be above SCHED_NORMAL.
-+ */
-+void sched_set_fifo_low(struct task_struct *p)
-+{
-+ struct sched_param sp = { .sched_priority = 1 };
-+ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_fifo_low);
-+
-+void sched_set_normal(struct task_struct *p, int nice)
-+{
-+ struct sched_attr attr = {
-+ .sched_policy = SCHED_NORMAL,
-+ .sched_nice = nice,
-+ };
-+ WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_normal);
-+
-+static int
-+do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
-+{
-+ struct sched_param lparam;
-+ struct task_struct *p;
-+ int retval;
-+
-+ if (!param || pid < 0)
-+ return -EINVAL;
-+ if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
-+ return -EFAULT;
-+
-+ rcu_read_lock();
-+ retval = -ESRCH;
-+ p = find_process_by_pid(pid);
-+ if (likely(p))
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ if (likely(p)) {
-+ retval = sched_setscheduler(p, policy, &lparam);
-+ put_task_struct(p);
-+ }
-+
-+ return retval;
-+}
-+
-+/*
-+ * Mimics kernel/events/core.c perf_copy_attr().
-+ */
-+static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr)
-+{
-+ u32 size;
-+ int ret;
-+
-+ /* Zero the full structure, so that a short copy will be nice: */
-+ memset(attr, 0, sizeof(*attr));
-+
-+ ret = get_user(size, &uattr->size);
-+ if (ret)
-+ return ret;
-+
-+ /* ABI compatibility quirk: */
-+ if (!size)
-+ size = SCHED_ATTR_SIZE_VER0;
-+
-+ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE)
-+ goto err_size;
-+
-+ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
-+ if (ret) {
-+ if (ret == -E2BIG)
-+ goto err_size;
-+ return ret;
-+ }
-+
-+ /*
-+ * XXX: Do we want to be lenient like existing syscalls; or do we want
-+ * to be strict and return an error on out-of-bounds values?
-+ */
-+ attr->sched_nice = clamp(attr->sched_nice, -20, 19);
-+
-+ /* sched/core.c uses zero here but we already know ret is zero */
-+ return 0;
-+
-+err_size:
-+ put_user(sizeof(*attr), &uattr->size);
-+ return -E2BIG;
-+}
-+
-+/**
-+ * sys_sched_setscheduler - set/change the scheduler policy and RT priority
-+ * @pid: the pid in question.
-+ * @policy: new policy.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ * @param: structure containing the new RT priority.
-+ */
-+SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
-+{
-+ if (policy < 0)
-+ return -EINVAL;
-+
-+ return do_sched_setscheduler(pid, policy, param);
-+}
-+
-+/**
-+ * sys_sched_setparam - set/change the RT priority of a thread
-+ * @pid: the pid in question.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
-+{
-+ return do_sched_setscheduler(pid, SETPARAM_POLICY, param);
-+}
-+
-+/**
-+ * sys_sched_setattr - same as above, but with extended sched_attr
-+ * @pid: the pid in question.
-+ * @uattr: structure containing the extended parameters.
-+ */
-+SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
-+ unsigned int, flags)
-+{
-+ struct sched_attr attr;
-+ struct task_struct *p;
-+ int retval;
-+
-+ if (!uattr || pid < 0 || flags)
-+ return -EINVAL;
-+
-+ retval = sched_copy_attr(uattr, &attr);
-+ if (retval)
-+ return retval;
-+
-+ if ((int)attr.sched_policy < 0)
-+ return -EINVAL;
-+
-+ rcu_read_lock();
-+ retval = -ESRCH;
-+ p = find_process_by_pid(pid);
-+ if (likely(p))
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ if (likely(p)) {
-+ retval = sched_setattr(p, &attr);
-+ put_task_struct(p);
-+ }
-+
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_getscheduler - get the policy (scheduling class) of a thread
-+ * @pid: the pid in question.
-+ *
-+ * Return: On success, the policy of the thread. Otherwise, a negative error
-+ * code.
-+ */
-+SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
-+{
-+ struct task_struct *p;
-+ int retval = -EINVAL;
-+
-+ if (pid < 0)
-+ goto out_nounlock;
-+
-+ retval = -ESRCH;
-+ rcu_read_lock();
-+ p = find_process_by_pid(pid);
-+ if (p) {
-+ retval = security_task_getscheduler(p);
-+ if (!retval)
-+ retval = p->policy;
-+ }
-+ rcu_read_unlock();
-+
-+out_nounlock:
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_getscheduler - get the RT priority of a thread
-+ * @pid: the pid in question.
-+ * @param: structure containing the RT priority.
-+ *
-+ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
-+ * code.
-+ */
-+SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
-+{
-+ struct sched_param lp = { .sched_priority = 0 };
-+ struct task_struct *p;
-+ int retval = -EINVAL;
-+
-+ if (!param || pid < 0)
-+ goto out_nounlock;
-+
-+ rcu_read_lock();
-+ p = find_process_by_pid(pid);
-+ retval = -ESRCH;
-+ if (!p)
-+ goto out_unlock;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ goto out_unlock;
-+
-+ if (task_has_rt_policy(p))
-+ lp.sched_priority = p->rt_priority;
-+ rcu_read_unlock();
-+
-+ /*
-+ * This one might sleep, we cannot do it with a spinlock held ...
-+ */
-+ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0;
-+
-+out_nounlock:
-+ return retval;
-+
-+out_unlock:
-+ rcu_read_unlock();
-+ return retval;
-+}
-+
-+/*
-+ * Copy the kernel size attribute structure (which might be larger
-+ * than what user-space knows about) to user-space.
-+ *
-+ * Note that all cases are valid: user-space buffer can be larger or
-+ * smaller than the kernel-space buffer. The usual case is that both
-+ * have the same size.
-+ */
-+static int
-+sched_attr_copy_to_user(struct sched_attr __user *uattr,
-+ struct sched_attr *kattr,
-+ unsigned int usize)
-+{
-+ unsigned int ksize = sizeof(*kattr);
-+
-+ if (!access_ok(uattr, usize))
-+ return -EFAULT;
-+
-+ /*
-+ * sched_getattr() ABI forwards and backwards compatibility:
-+ *
-+ * If usize == ksize then we just copy everything to user-space and all is good.
-+ *
-+ * If usize < ksize then we only copy as much as user-space has space for,
-+ * this keeps ABI compatibility as well. We skip the rest.
-+ *
-+ * If usize > ksize then user-space is using a newer version of the ABI,
-+ * which part the kernel doesn't know about. Just ignore it - tooling can
-+ * detect the kernel's knowledge of attributes from the attr->size value
-+ * which is set to ksize in this case.
-+ */
-+ kattr->size = min(usize, ksize);
-+
-+ if (copy_to_user(uattr, kattr, kattr->size))
-+ return -EFAULT;
-+
-+ return 0;
-+}
-+
-+/**
-+ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
-+ * @pid: the pid in question.
-+ * @uattr: structure containing the extended parameters.
-+ * @usize: sizeof(attr) for fwd/bwd comp.
-+ * @flags: for future extension.
-+ */
-+SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-+ unsigned int, usize, unsigned int, flags)
-+{
-+ struct sched_attr kattr = { };
-+ struct task_struct *p;
-+ int retval;
-+
-+ if (!uattr || pid < 0 || usize > PAGE_SIZE ||
-+ usize < SCHED_ATTR_SIZE_VER0 || flags)
-+ return -EINVAL;
-+
-+ rcu_read_lock();
-+ p = find_process_by_pid(pid);
-+ retval = -ESRCH;
-+ if (!p)
-+ goto out_unlock;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ goto out_unlock;
-+
-+ kattr.sched_policy = p->policy;
-+ if (p->sched_reset_on_fork)
-+ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
-+ if (task_has_rt_policy(p))
-+ kattr.sched_priority = p->rt_priority;
-+ else
-+ kattr.sched_nice = task_nice(p);
-+ kattr.sched_flags &= SCHED_FLAG_ALL;
-+
-+#ifdef CONFIG_UCLAMP_TASK
-+ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
-+ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
-+#endif
-+
-+ rcu_read_unlock();
-+
-+ return sched_attr_copy_to_user(uattr, &kattr, usize);
-+
-+out_unlock:
-+ rcu_read_unlock();
-+ return retval;
-+}
-+
-+static int
-+__sched_setaffinity(struct task_struct *p, const struct cpumask *mask)
-+{
-+ int retval;
-+ cpumask_var_t cpus_allowed, new_mask;
-+
-+ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
-+ retval = -ENOMEM;
-+ goto out_free_cpus_allowed;
-+ }
-+
-+ cpuset_cpus_allowed(p, cpus_allowed);
-+ cpumask_and(new_mask, mask, cpus_allowed);
-+again:
-+ retval = __set_cpus_allowed_ptr(p, new_mask, SCA_CHECK | SCA_USER);
-+ if (retval)
-+ goto out_free_new_mask;
-+
-+ cpuset_cpus_allowed(p, cpus_allowed);
-+ if (!cpumask_subset(new_mask, cpus_allowed)) {
-+ /*
-+ * We must have raced with a concurrent cpuset
-+ * update. Just reset the cpus_allowed to the
-+ * cpuset's cpus_allowed
-+ */
-+ cpumask_copy(new_mask, cpus_allowed);
-+ goto again;
-+ }
-+
-+out_free_new_mask:
-+ free_cpumask_var(new_mask);
-+out_free_cpus_allowed:
-+ free_cpumask_var(cpus_allowed);
-+ return retval;
-+}
-+
-+long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
-+{
-+ struct task_struct *p;
-+ int retval;
-+
-+ rcu_read_lock();
-+
-+ p = find_process_by_pid(pid);
-+ if (!p) {
-+ rcu_read_unlock();
-+ return -ESRCH;
-+ }
-+
-+ /* Prevent p going away */
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ if (p->flags & PF_NO_SETAFFINITY) {
-+ retval = -EINVAL;
-+ goto out_put_task;
-+ }
-+
-+ if (!check_same_owner(p)) {
-+ rcu_read_lock();
-+ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) {
-+ rcu_read_unlock();
-+ retval = -EPERM;
-+ goto out_put_task;
-+ }
-+ rcu_read_unlock();
-+ }
-+
-+ retval = security_task_setscheduler(p);
-+ if (retval)
-+ goto out_put_task;
-+
-+ retval = __sched_setaffinity(p, in_mask);
-+out_put_task:
-+ put_task_struct(p);
-+ return retval;
-+}
-+
-+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
-+ struct cpumask *new_mask)
-+{
-+ if (len < cpumask_size())
-+ cpumask_clear(new_mask);
-+ else if (len > cpumask_size())
-+ len = cpumask_size();
-+
-+ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
-+}
-+
-+/**
-+ * sys_sched_setaffinity - set the CPU affinity of a process
-+ * @pid: pid of the process
-+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
-+ * @user_mask_ptr: user-space pointer to the new CPU mask
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
-+ unsigned long __user *, user_mask_ptr)
-+{
-+ cpumask_var_t new_mask;
-+ int retval;
-+
-+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask);
-+ if (retval == 0)
-+ retval = sched_setaffinity(pid, new_mask);
-+ free_cpumask_var(new_mask);
-+ return retval;
-+}
-+
-+long sched_getaffinity(pid_t pid, cpumask_t *mask)
-+{
-+ struct task_struct *p;
-+ raw_spinlock_t *lock;
-+ unsigned long flags;
-+ int retval;
-+
-+ rcu_read_lock();
-+
-+ retval = -ESRCH;
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ goto out_unlock;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ goto out_unlock;
-+
-+ task_access_lock_irqsave(p, &lock, &flags);
-+ cpumask_and(mask, &p->cpus_mask, cpu_active_mask);
-+ task_access_unlock_irqrestore(p, lock, &flags);
-+
-+out_unlock:
-+ rcu_read_unlock();
-+
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_getaffinity - get the CPU affinity of a process
-+ * @pid: pid of the process
-+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
-+ * @user_mask_ptr: user-space pointer to hold the current CPU mask
-+ *
-+ * Return: size of CPU mask copied to user_mask_ptr on success. An
-+ * error code otherwise.
-+ */
-+SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
-+ unsigned long __user *, user_mask_ptr)
-+{
-+ int ret;
-+ cpumask_var_t mask;
-+
-+ if ((len * BITS_PER_BYTE) < nr_cpu_ids)
-+ return -EINVAL;
-+ if (len & (sizeof(unsigned long)-1))
-+ return -EINVAL;
-+
-+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ ret = sched_getaffinity(pid, mask);
-+ if (ret == 0) {
-+ unsigned int retlen = min_t(size_t, len, cpumask_size());
-+
-+ if (copy_to_user(user_mask_ptr, mask, retlen))
-+ ret = -EFAULT;
-+ else
-+ ret = retlen;
-+ }
-+ free_cpumask_var(mask);
-+
-+ return ret;
-+}
-+
-+static void do_sched_yield(void)
-+{
-+ struct rq *rq;
-+ struct rq_flags rf;
-+
-+ if (!sched_yield_type)
-+ return;
-+
-+ rq = this_rq_lock_irq(&rf);
-+
-+ schedstat_inc(rq->yld_count);
-+
-+ if (1 == sched_yield_type) {
-+ if (!rt_task(current))
-+ do_sched_yield_type_1(current, rq);
-+ } else if (2 == sched_yield_type) {
-+ if (rq->nr_running > 1)
-+ rq->skip = current;
-+ }
-+
-+ preempt_disable();
-+ raw_spin_unlock_irq(&rq->lock);
-+ sched_preempt_enable_no_resched();
-+
-+ schedule();
-+}
-+
-+/**
-+ * sys_sched_yield - yield the current processor to other threads.
-+ *
-+ * This function yields the current CPU to other tasks. If there are no
-+ * other threads running on this CPU then this function will return.
-+ *
-+ * Return: 0.
-+ */
-+SYSCALL_DEFINE0(sched_yield)
-+{
-+ do_sched_yield();
-+ return 0;
-+}
-+
-+#if !defined(CONFIG_PREEMPTION) || defined(CONFIG_PREEMPT_DYNAMIC)
-+int __sched __cond_resched(void)
-+{
-+ if (should_resched(0)) {
-+ preempt_schedule_common();
-+ return 1;
-+ }
-+ /*
-+ * In preemptible kernels, ->rcu_read_lock_nesting tells the tick
-+ * whether the current CPU is in an RCU read-side critical section,
-+ * so the tick can report quiescent states even for CPUs looping
-+ * in kernel context. In contrast, in non-preemptible kernels,
-+ * RCU readers leave no in-memory hints, which means that CPU-bound
-+ * processes executing in kernel context might never report an
-+ * RCU quiescent state. Therefore, the following code causes
-+ * cond_resched() to report a quiescent state, but only when RCU
-+ * is in urgent need of one.
-+ */
-+#ifndef CONFIG_PREEMPT_RCU
-+ rcu_all_qs();
-+#endif
-+ return 0;
-+}
-+EXPORT_SYMBOL(__cond_resched);
-+#endif
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+DEFINE_STATIC_CALL_RET0(cond_resched, __cond_resched);
-+EXPORT_STATIC_CALL_TRAMP(cond_resched);
-+
-+DEFINE_STATIC_CALL_RET0(might_resched, __cond_resched);
-+EXPORT_STATIC_CALL_TRAMP(might_resched);
-+#endif
-+
-+/*
-+ * __cond_resched_lock() - if a reschedule is pending, drop the given lock,
-+ * call schedule, and on return reacquire the lock.
-+ *
-+ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level
-+ * operations here to prevent schedule() from being called twice (once via
-+ * spin_unlock(), once by hand).
-+ */
-+int __cond_resched_lock(spinlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held(lock);
-+
-+ if (spin_needbreak(lock) || resched) {
-+ spin_unlock(lock);
-+ if (resched)
-+ preempt_schedule_common();
-+ else
-+ cpu_relax();
-+ ret = 1;
-+ spin_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_lock);
-+
-+int __cond_resched_rwlock_read(rwlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held_read(lock);
-+
-+ if (rwlock_needbreak(lock) || resched) {
-+ read_unlock(lock);
-+ if (resched)
-+ preempt_schedule_common();
-+ else
-+ cpu_relax();
-+ ret = 1;
-+ read_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_rwlock_read);
-+
-+int __cond_resched_rwlock_write(rwlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held_write(lock);
-+
-+ if (rwlock_needbreak(lock) || resched) {
-+ write_unlock(lock);
-+ if (resched)
-+ preempt_schedule_common();
-+ else
-+ cpu_relax();
-+ ret = 1;
-+ write_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_rwlock_write);
-+
-+/**
-+ * yield - yield the current processor to other threads.
-+ *
-+ * Do not ever use this function, there's a 99% chance you're doing it wrong.
-+ *
-+ * The scheduler is at all times free to pick the calling task as the most
-+ * eligible task to run, if removing the yield() call from your code breaks
-+ * it, it's already broken.
-+ *
-+ * Typical broken usage is:
-+ *
-+ * while (!event)
-+ * yield();
-+ *
-+ * where one assumes that yield() will let 'the other' process run that will
-+ * make event true. If the current task is a SCHED_FIFO task that will never
-+ * happen. Never use yield() as a progress guarantee!!
-+ *
-+ * If you want to use yield() to wait for something, use wait_event().
-+ * If you want to use yield() to be 'nice' for others, use cond_resched().
-+ * If you still want to use yield(), do not!
-+ */
-+void __sched yield(void)
-+{
-+ set_current_state(TASK_RUNNING);
-+ do_sched_yield();
-+}
-+EXPORT_SYMBOL(yield);
-+
-+/**
-+ * yield_to - yield the current processor to another thread in
-+ * your thread group, or accelerate that thread toward the
-+ * processor it's on.
-+ * @p: target task
-+ * @preempt: whether task preemption is allowed or not
-+ *
-+ * It's the caller's job to ensure that the target task struct
-+ * can't go away on us before we can do any checks.
-+ *
-+ * In Alt schedule FW, yield_to is not supported.
-+ *
-+ * Return:
-+ * true (>0) if we indeed boosted the target task.
-+ * false (0) if we failed to boost the target.
-+ * -ESRCH if there's no task to yield to.
-+ */
-+int __sched yield_to(struct task_struct *p, bool preempt)
-+{
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(yield_to);
-+
-+int io_schedule_prepare(void)
-+{
-+ int old_iowait = current->in_iowait;
-+
-+ current->in_iowait = 1;
-+ blk_schedule_flush_plug(current);
-+
-+ return old_iowait;
-+}
-+
-+void io_schedule_finish(int token)
-+{
-+ current->in_iowait = token;
-+}
-+
-+/*
-+ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
-+ * that process accounting knows that this is a task in IO wait state.
-+ *
-+ * But don't do that if it is a deliberate, throttling IO wait (this task
-+ * has set its backing_dev_info: the queue against which it should throttle)
-+ */
-+
-+long __sched io_schedule_timeout(long timeout)
-+{
-+ int token;
-+ long ret;
-+
-+ token = io_schedule_prepare();
-+ ret = schedule_timeout(timeout);
-+ io_schedule_finish(token);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(io_schedule_timeout);
-+
-+void __sched io_schedule(void)
-+{
-+ int token;
-+
-+ token = io_schedule_prepare();
-+ schedule();
-+ io_schedule_finish(token);
-+}
-+EXPORT_SYMBOL(io_schedule);
-+
-+/**
-+ * sys_sched_get_priority_max - return maximum RT priority.
-+ * @policy: scheduling class.
-+ *
-+ * Return: On success, this syscall returns the maximum
-+ * rt_priority that can be used by a given scheduling class.
-+ * On failure, a negative error code is returned.
-+ */
-+SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
-+{
-+ int ret = -EINVAL;
-+
-+ switch (policy) {
-+ case SCHED_FIFO:
-+ case SCHED_RR:
-+ ret = MAX_RT_PRIO - 1;
-+ break;
-+ case SCHED_NORMAL:
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ ret = 0;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * sys_sched_get_priority_min - return minimum RT priority.
-+ * @policy: scheduling class.
-+ *
-+ * Return: On success, this syscall returns the minimum
-+ * rt_priority that can be used by a given scheduling class.
-+ * On failure, a negative error code is returned.
-+ */
-+SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
-+{
-+ int ret = -EINVAL;
-+
-+ switch (policy) {
-+ case SCHED_FIFO:
-+ case SCHED_RR:
-+ ret = 1;
-+ break;
-+ case SCHED_NORMAL:
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ ret = 0;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int sched_rr_get_interval(pid_t pid, struct timespec64 *t)
-+{
-+ struct task_struct *p;
-+ int retval;
-+
-+ alt_sched_debug();
-+
-+ if (pid < 0)
-+ return -EINVAL;
-+
-+ retval = -ESRCH;
-+ rcu_read_lock();
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ goto out_unlock;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ goto out_unlock;
-+ rcu_read_unlock();
-+
-+ *t = ns_to_timespec64(sched_timeslice_ns);
-+ return 0;
-+
-+out_unlock:
-+ rcu_read_unlock();
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_rr_get_interval - return the default timeslice of a process.
-+ * @pid: pid of the process.
-+ * @interval: userspace pointer to the timeslice value.
-+ *
-+ *
-+ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
-+ * an error code.
-+ */
-+SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
-+ struct __kernel_timespec __user *, interval)
-+{
-+ struct timespec64 t;
-+ int retval = sched_rr_get_interval(pid, &t);
-+
-+ if (retval == 0)
-+ retval = put_timespec64(&t, interval);
-+
-+ return retval;
-+}
-+
-+#ifdef CONFIG_COMPAT_32BIT_TIME
-+SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid,
-+ struct old_timespec32 __user *, interval)
-+{
-+ struct timespec64 t;
-+ int retval = sched_rr_get_interval(pid, &t);
-+
-+ if (retval == 0)
-+ retval = put_old_timespec32(&t, interval);
-+ return retval;
-+}
-+#endif
-+
-+void sched_show_task(struct task_struct *p)
-+{
-+ unsigned long free = 0;
-+ int ppid;
-+
-+ if (!try_get_task_stack(p))
-+ return;
-+
-+ pr_info("task:%-15.15s state:%c", p->comm, task_state_to_char(p));
-+
-+ if (task_is_running(p))
-+ pr_cont(" running task ");
-+#ifdef CONFIG_DEBUG_STACK_USAGE
-+ free = stack_not_used(p);
-+#endif
-+ ppid = 0;
-+ rcu_read_lock();
-+ if (pid_alive(p))
-+ ppid = task_pid_nr(rcu_dereference(p->real_parent));
-+ rcu_read_unlock();
-+ pr_cont(" stack:%5lu pid:%5d ppid:%6d flags:0x%08lx\n",
-+ free, task_pid_nr(p), ppid,
-+ (unsigned long)task_thread_info(p)->flags);
-+
-+ print_worker_info(KERN_INFO, p);
-+ print_stop_info(KERN_INFO, p);
-+ show_stack(p, NULL, KERN_INFO);
-+ put_task_stack(p);
-+}
-+EXPORT_SYMBOL_GPL(sched_show_task);
-+
-+static inline bool
-+state_filter_match(unsigned long state_filter, struct task_struct *p)
-+{
-+ unsigned int state = READ_ONCE(p->__state);
-+
-+ /* no filter, everything matches */
-+ if (!state_filter)
-+ return true;
-+
-+ /* filter, but doesn't match */
-+ if (!(state & state_filter))
-+ return false;
-+
-+ /*
-+ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows
-+ * TASK_KILLABLE).
-+ */
-+ if (state_filter == TASK_UNINTERRUPTIBLE && state == TASK_IDLE)
-+ return false;
-+
-+ return true;
-+}
-+
-+
-+void show_state_filter(unsigned int state_filter)
-+{
-+ struct task_struct *g, *p;
-+
-+ rcu_read_lock();
-+ for_each_process_thread(g, p) {
-+ /*
-+ * reset the NMI-timeout, listing all files on a slow
-+ * console might take a lot of time:
-+ * Also, reset softlockup watchdogs on all CPUs, because
-+ * another CPU might be blocked waiting for us to process
-+ * an IPI.
-+ */
-+ touch_nmi_watchdog();
-+ touch_all_softlockup_watchdogs();
-+ if (state_filter_match(state_filter, p))
-+ sched_show_task(p);
-+ }
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+ /* TODO: Alt schedule FW should support this
-+ if (!state_filter)
-+ sysrq_sched_debug_show();
-+ */
-+#endif
-+ rcu_read_unlock();
-+ /*
-+ * Only show locks if all tasks are dumped:
-+ */
-+ if (!state_filter)
-+ debug_show_all_locks();
-+}
-+
-+void dump_cpu_task(int cpu)
-+{
-+ pr_info("Task dump for CPU %d:\n", cpu);
-+ sched_show_task(cpu_curr(cpu));
-+}
-+
-+/**
-+ * init_idle - set up an idle thread for a given CPU
-+ * @idle: task in question
-+ * @cpu: CPU the idle task belongs to
-+ *
-+ * NOTE: this function does not set the idle thread's NEED_RESCHED
-+ * flag, to make booting more robust.
-+ */
-+void __init init_idle(struct task_struct *idle, int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ __sched_fork(0, idle);
-+
-+ /*
-+ * The idle task doesn't need the kthread struct to function, but it
-+ * is dressed up as a per-CPU kthread and thus needs to play the part
-+ * if we want to avoid special-casing it in code that deals with per-CPU
-+ * kthreads.
-+ */
-+ set_kthread_struct(idle);
-+
-+ raw_spin_lock_irqsave(&idle->pi_lock, flags);
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+
-+ idle->last_ran = rq->clock_task;
-+ idle->__state = TASK_RUNNING;
-+ /*
-+ * PF_KTHREAD should already be set at this point; regardless, make it
-+ * look like a proper per-CPU kthread.
-+ */
-+ idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY;
-+ kthread_set_per_cpu(idle, cpu);
-+
-+ sched_queue_init_idle(&rq->queue, idle);
-+
-+ scs_task_reset(idle);
-+ kasan_unpoison_task_stack(idle);
-+
-+#ifdef CONFIG_SMP
-+ /*
-+ * It's possible that init_idle() gets called multiple times on a task,
-+ * in that case do_set_cpus_allowed() will not do the right thing.
-+ *
-+ * And since this is boot we can forgo the serialisation.
-+ */
-+ set_cpus_allowed_common(idle, cpumask_of(cpu));
-+#endif
-+
-+ /* Silence PROVE_RCU */
-+ rcu_read_lock();
-+ __set_task_cpu(idle, cpu);
-+ rcu_read_unlock();
-+
-+ rq->idle = idle;
-+ rcu_assign_pointer(rq->curr, idle);
-+ idle->on_cpu = 1;
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&idle->pi_lock, flags);
-+
-+ /* Set the preempt count _outside_ the spinlocks! */
-+ init_idle_preempt_count(idle, cpu);
-+
-+ ftrace_graph_init_idle_task(idle, cpu);
-+ vtime_init_idle(idle, cpu);
-+#ifdef CONFIG_SMP
-+ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
-+#endif
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur,
-+ const struct cpumask __maybe_unused *trial)
-+{
-+ return 1;
-+}
-+
-+int task_can_attach(struct task_struct *p,
-+ const struct cpumask *cs_cpus_allowed)
-+{
-+ int ret = 0;
-+
-+ /*
-+ * Kthreads which disallow setaffinity shouldn't be moved
-+ * to a new cpuset; we don't want to change their CPU
-+ * affinity and isolating such threads by their set of
-+ * allowed nodes is unnecessary. Thus, cpusets are not
-+ * applicable for such threads. This prevents checking for
-+ * success of set_cpus_allowed_ptr() on all attached tasks
-+ * before cpus_mask may be changed.
-+ */
-+ if (p->flags & PF_NO_SETAFFINITY)
-+ ret = -EINVAL;
-+
-+ return ret;
-+}
-+
-+bool sched_smp_initialized __read_mostly;
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+/*
-+ * Ensures that the idle task is using init_mm right before its CPU goes
-+ * offline.
-+ */
-+void idle_task_exit(void)
-+{
-+ struct mm_struct *mm = current->active_mm;
-+
-+ BUG_ON(current != this_rq()->idle);
-+
-+ if (mm != &init_mm) {
-+ switch_mm(mm, &init_mm, current);
-+ finish_arch_post_lock_switch();
-+ }
-+
-+ scs_task_reset(current);
-+ /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
-+}
-+
-+static int __balance_push_cpu_stop(void *arg)
-+{
-+ struct task_struct *p = arg;
-+ struct rq *rq = this_rq();
-+ struct rq_flags rf;
-+ int cpu;
-+
-+ raw_spin_lock_irq(&p->pi_lock);
-+ rq_lock(rq, &rf);
-+
-+ update_rq_clock(rq);
-+
-+ if (task_rq(p) == rq && task_on_rq_queued(p)) {
-+ cpu = select_fallback_rq(rq->cpu, p);
-+ rq = __migrate_task(rq, p, cpu);
-+ }
-+
-+ rq_unlock(rq, &rf);
-+ raw_spin_unlock_irq(&p->pi_lock);
-+
-+ put_task_struct(p);
-+
-+ return 0;
-+}
-+
-+static DEFINE_PER_CPU(struct cpu_stop_work, push_work);
-+
-+/*
-+ * This is enabled below SCHED_AP_ACTIVE; when !cpu_active(), but only
-+ * effective when the hotplug motion is down.
-+ */
-+static void balance_push(struct rq *rq)
-+{
-+ struct task_struct *push_task = rq->curr;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*
-+ * Ensure the thing is persistent until balance_push_set(.on = false);
-+ */
-+ rq->balance_callback = &balance_push_callback;
-+
-+ /*
-+ * Only active while going offline and when invoked on the outgoing
-+ * CPU.
-+ */
-+ if (!cpu_dying(rq->cpu) || rq != this_rq())
-+ return;
-+
-+ /*
-+ * Both the cpu-hotplug and stop task are in this case and are
-+ * required to complete the hotplug process.
-+ */
-+ if (kthread_is_per_cpu(push_task) ||
-+ is_migration_disabled(push_task)) {
-+
-+ /*
-+ * If this is the idle task on the outgoing CPU try to wake
-+ * up the hotplug control thread which might wait for the
-+ * last task to vanish. The rcuwait_active() check is
-+ * accurate here because the waiter is pinned on this CPU
-+ * and can't obviously be running in parallel.
-+ *
-+ * On RT kernels this also has to check whether there are
-+ * pinned and scheduled out tasks on the runqueue. They
-+ * need to leave the migrate disabled section first.
-+ */
-+ if (!rq->nr_running && !rq_has_pinned_tasks(rq) &&
-+ rcuwait_active(&rq->hotplug_wait)) {
-+ raw_spin_unlock(&rq->lock);
-+ rcuwait_wake_up(&rq->hotplug_wait);
-+ raw_spin_lock(&rq->lock);
-+ }
-+ return;
-+ }
-+
-+ get_task_struct(push_task);
-+ /*
-+ * Temporarily drop rq->lock such that we can wake-up the stop task.
-+ * Both preemption and IRQs are still disabled.
-+ */
-+ raw_spin_unlock(&rq->lock);
-+ stop_one_cpu_nowait(rq->cpu, __balance_push_cpu_stop, push_task,
-+ this_cpu_ptr(&push_work));
-+ /*
-+ * At this point need_resched() is true and we'll take the loop in
-+ * schedule(). The next pick is obviously going to be the stop task
-+ * which kthread_is_per_cpu() and will push this task away.
-+ */
-+ raw_spin_lock(&rq->lock);
-+}
-+
-+static void balance_push_set(int cpu, bool on)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ struct rq_flags rf;
-+
-+ rq_lock_irqsave(rq, &rf);
-+ if (on) {
-+ WARN_ON_ONCE(rq->balance_callback);
-+ rq->balance_callback = &balance_push_callback;
-+ } else if (rq->balance_callback == &balance_push_callback) {
-+ rq->balance_callback = NULL;
-+ }
-+ rq_unlock_irqrestore(rq, &rf);
-+}
-+
-+/*
-+ * Invoked from a CPUs hotplug control thread after the CPU has been marked
-+ * inactive. All tasks which are not per CPU kernel threads are either
-+ * pushed off this CPU now via balance_push() or placed on a different CPU
-+ * during wakeup. Wait until the CPU is quiescent.
-+ */
-+static void balance_hotplug_wait(void)
-+{
-+ struct rq *rq = this_rq();
-+
-+ rcuwait_wait_event(&rq->hotplug_wait,
-+ rq->nr_running == 1 && !rq_has_pinned_tasks(rq),
-+ TASK_UNINTERRUPTIBLE);
-+}
-+
-+#else
-+
-+static void balance_push(struct rq *rq)
-+{
-+}
-+
-+static void balance_push_set(int cpu, bool on)
-+{
-+}
-+
-+static inline void balance_hotplug_wait(void)
-+{
-+}
-+#endif /* CONFIG_HOTPLUG_CPU */
-+
-+static void set_rq_offline(struct rq *rq)
-+{
-+ if (rq->online)
-+ rq->online = false;
-+}
-+
-+static void set_rq_online(struct rq *rq)
-+{
-+ if (!rq->online)
-+ rq->online = true;
-+}
-+
-+/*
-+ * used to mark begin/end of suspend/resume:
-+ */
-+static int num_cpus_frozen;
-+
-+/*
-+ * Update cpusets according to cpu_active mask. If cpusets are
-+ * disabled, cpuset_update_active_cpus() becomes a simple wrapper
-+ * around partition_sched_domains().
-+ *
-+ * If we come here as part of a suspend/resume, don't touch cpusets because we
-+ * want to restore it back to its original state upon resume anyway.
-+ */
-+static void cpuset_cpu_active(void)
-+{
-+ if (cpuhp_tasks_frozen) {
-+ /*
-+ * num_cpus_frozen tracks how many CPUs are involved in suspend
-+ * resume sequence. As long as this is not the last online
-+ * operation in the resume sequence, just build a single sched
-+ * domain, ignoring cpusets.
-+ */
-+ partition_sched_domains(1, NULL, NULL);
-+ if (--num_cpus_frozen)
-+ return;
-+ /*
-+ * This is the last CPU online operation. So fall through and
-+ * restore the original sched domains by considering the
-+ * cpuset configurations.
-+ */
-+ cpuset_force_rebuild();
-+ }
-+
-+ cpuset_update_active_cpus();
-+}
-+
-+static int cpuset_cpu_inactive(unsigned int cpu)
-+{
-+ if (!cpuhp_tasks_frozen) {
-+ cpuset_update_active_cpus();
-+ } else {
-+ num_cpus_frozen++;
-+ partition_sched_domains(1, NULL, NULL);
-+ }
-+ return 0;
-+}
-+
-+int sched_cpu_activate(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ /*
-+ * Clear the balance_push callback and prepare to schedule
-+ * regular tasks.
-+ */
-+ balance_push_set(cpu, false);
-+
-+#ifdef CONFIG_SCHED_SMT
-+ /*
-+ * When going up, increment the number of cores with SMT present.
-+ */
-+ if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
-+ static_branch_inc_cpuslocked(&sched_smt_present);
-+#endif
-+ set_cpu_active(cpu, true);
-+
-+ if (sched_smp_initialized)
-+ cpuset_cpu_active();
-+
-+ /*
-+ * Put the rq online, if not already. This happens:
-+ *
-+ * 1) In the early boot process, because we build the real domains
-+ * after all cpus have been brought up.
-+ *
-+ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the
-+ * domains.
-+ */
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ set_rq_online(rq);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ return 0;
-+}
-+
-+int sched_cpu_deactivate(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+ int ret;
-+
-+ set_cpu_active(cpu, false);
-+
-+ /*
-+ * From this point forward, this CPU will refuse to run any task that
-+ * is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
-+ * push those tasks away until this gets cleared, see
-+ * sched_cpu_dying().
-+ */
-+ balance_push_set(cpu, true);
-+
-+ /*
-+ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU
-+ * users of this state to go away such that all new such users will
-+ * observe it.
-+ *
-+ * Specifically, we rely on ttwu to no longer target this CPU, see
-+ * ttwu_queue_cond() and is_cpu_allowed().
-+ *
-+ * Do sync before park smpboot threads to take care the rcu boost case.
-+ */
-+ synchronize_rcu();
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ update_rq_clock(rq);
-+ set_rq_offline(rq);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+#ifdef CONFIG_SCHED_SMT
-+ /*
-+ * When going down, decrement the number of cores with SMT present.
-+ */
-+ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) {
-+ static_branch_dec_cpuslocked(&sched_smt_present);
-+ if (!static_branch_likely(&sched_smt_present))
-+ cpumask_clear(&sched_sg_idle_mask);
-+ }
-+#endif
-+
-+ if (!sched_smp_initialized)
-+ return 0;
-+
-+ ret = cpuset_cpu_inactive(cpu);
-+ if (ret) {
-+ balance_push_set(cpu, false);
-+ set_cpu_active(cpu, true);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static void sched_rq_cpu_starting(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ rq->calc_load_update = calc_load_update;
-+}
-+
-+int sched_cpu_starting(unsigned int cpu)
-+{
-+ sched_rq_cpu_starting(cpu);
-+ sched_tick_start(cpu);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+
-+/*
-+ * Invoked immediately before the stopper thread is invoked to bring the
-+ * CPU down completely. At this point all per CPU kthreads except the
-+ * hotplug thread (current) and the stopper thread (inactive) have been
-+ * either parked or have been unbound from the outgoing CPU. Ensure that
-+ * any of those which might be on the way out are gone.
-+ *
-+ * If after this point a bound task is being woken on this CPU then the
-+ * responsible hotplug callback has failed to do it's job.
-+ * sched_cpu_dying() will catch it with the appropriate fireworks.
-+ */
-+int sched_cpu_wait_empty(unsigned int cpu)
-+{
-+ balance_hotplug_wait();
-+ return 0;
-+}
-+
-+/*
-+ * Since this CPU is going 'away' for a while, fold any nr_active delta we
-+ * might have. Called from the CPU stopper task after ensuring that the
-+ * stopper is the last running task on the CPU, so nr_active count is
-+ * stable. We need to take the teardown thread which is calling this into
-+ * account, so we hand in adjust = 1 to the load calculation.
-+ *
-+ * Also see the comment "Global load-average calculations".
-+ */
-+static void calc_load_migrate(struct rq *rq)
-+{
-+ long delta = calc_load_fold_active(rq, 1);
-+
-+ if (delta)
-+ atomic_long_add(delta, &calc_load_tasks);
-+}
-+
-+static void dump_rq_tasks(struct rq *rq, const char *loglvl)
-+{
-+ struct task_struct *g, *p;
-+ int cpu = cpu_of(rq);
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ printk("%sCPU%d enqueued tasks (%u total):\n", loglvl, cpu, rq->nr_running);
-+ for_each_process_thread(g, p) {
-+ if (task_cpu(p) != cpu)
-+ continue;
-+
-+ if (!task_on_rq_queued(p))
-+ continue;
-+
-+ printk("%s\tpid: %d, name: %s\n", loglvl, p->pid, p->comm);
-+ }
-+}
-+
-+int sched_cpu_dying(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ /* Handle pending wakeups and then migrate everything off */
-+ sched_tick_stop(cpu);
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) {
-+ WARN(true, "Dying CPU not properly vacated!");
-+ dump_rq_tasks(rq, KERN_WARNING);
-+ }
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ calc_load_migrate(rq);
-+ hrtick_clear(rq);
-+ return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_SMP
-+static void sched_init_topology_cpumask_early(void)
-+{
-+ int cpu;
-+ cpumask_t *tmp;
-+
-+ for_each_possible_cpu(cpu) {
-+ /* init topo masks */
-+ tmp = per_cpu(sched_cpu_topo_masks, cpu);
-+
-+ cpumask_copy(tmp, cpumask_of(cpu));
-+ tmp++;
-+ cpumask_copy(tmp, cpu_possible_mask);
-+ per_cpu(sched_cpu_llc_mask, cpu) = tmp;
-+ per_cpu(sched_cpu_topo_end_mask, cpu) = ++tmp;
-+ /*per_cpu(sd_llc_id, cpu) = cpu;*/
-+ }
-+}
-+
-+#define TOPOLOGY_CPUMASK(name, mask, last)\
-+ if (cpumask_and(topo, topo, mask)) { \
-+ cpumask_copy(topo, mask); \
-+ printk(KERN_INFO "sched: cpu#%02d topo: 0x%08lx - "#name, \
-+ cpu, (topo++)->bits[0]); \
-+ } \
-+ if (!last) \
-+ cpumask_complement(topo, mask)
-+
-+static void sched_init_topology_cpumask(void)
-+{
-+ int cpu;
-+ cpumask_t *topo;
-+
-+ for_each_online_cpu(cpu) {
-+ /* take chance to reset time slice for idle tasks */
-+ cpu_rq(cpu)->idle->time_slice = sched_timeslice_ns;
-+
-+ topo = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+
-+ cpumask_complement(topo, cpumask_of(cpu));
-+#ifdef CONFIG_SCHED_SMT
-+ TOPOLOGY_CPUMASK(smt, topology_sibling_cpumask(cpu), false);
-+#endif
-+ per_cpu(sd_llc_id, cpu) = cpumask_first(cpu_coregroup_mask(cpu));
-+ per_cpu(sched_cpu_llc_mask, cpu) = topo;
-+ TOPOLOGY_CPUMASK(coregroup, cpu_coregroup_mask(cpu), false);
-+
-+ TOPOLOGY_CPUMASK(core, topology_core_cpumask(cpu), false);
-+
-+ TOPOLOGY_CPUMASK(others, cpu_online_mask, true);
-+
-+ per_cpu(sched_cpu_topo_end_mask, cpu) = topo;
-+ printk(KERN_INFO "sched: cpu#%02d llc_id = %d, llc_mask idx = %d\n",
-+ cpu, per_cpu(sd_llc_id, cpu),
-+ (int) (per_cpu(sched_cpu_llc_mask, cpu) -
-+ per_cpu(sched_cpu_topo_masks, cpu)));
-+ }
-+}
-+#endif
-+
-+void __init sched_init_smp(void)
-+{
-+ /* Move init over to a non-isolated CPU */
-+ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0)
-+ BUG();
-+ current->flags &= ~PF_NO_SETAFFINITY;
-+
-+ sched_init_topology_cpumask();
-+
-+ sched_smp_initialized = true;
-+}
-+#else
-+void __init sched_init_smp(void)
-+{
-+ cpu_rq(0)->idle->time_slice = sched_timeslice_ns;
-+}
-+#endif /* CONFIG_SMP */
-+
-+int in_sched_functions(unsigned long addr)
-+{
-+ return in_lock_functions(addr) ||
-+ (addr >= (unsigned long)__sched_text_start
-+ && addr < (unsigned long)__sched_text_end);
-+}
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+/* task group related information */
-+struct task_group {
-+ struct cgroup_subsys_state css;
-+
-+ struct rcu_head rcu;
-+ struct list_head list;
-+
-+ struct task_group *parent;
-+ struct list_head siblings;
-+ struct list_head children;
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+ unsigned long shares;
-+#endif
-+};
-+
-+/*
-+ * Default task group.
-+ * Every task in system belongs to this group at bootup.
-+ */
-+struct task_group root_task_group;
-+LIST_HEAD(task_groups);
-+
-+/* Cacheline aligned slab cache for task_group */
-+static struct kmem_cache *task_group_cache __read_mostly;
-+#endif /* CONFIG_CGROUP_SCHED */
-+
-+void __init sched_init(void)
-+{
-+ int i;
-+ struct rq *rq;
-+
-+ printk(KERN_INFO ALT_SCHED_VERSION_MSG);
-+
-+ wait_bit_init();
-+
-+#ifdef CONFIG_SMP
-+ for (i = 0; i < SCHED_BITS; i++)
-+ cpumask_copy(sched_rq_watermark + i, cpu_present_mask);
-+#endif
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+ task_group_cache = KMEM_CACHE(task_group, 0);
-+
-+ list_add(&root_task_group.list, &task_groups);
-+ INIT_LIST_HEAD(&root_task_group.children);
-+ INIT_LIST_HEAD(&root_task_group.siblings);
-+#endif /* CONFIG_CGROUP_SCHED */
-+ for_each_possible_cpu(i) {
-+ rq = cpu_rq(i);
-+
-+ sched_queue_init(&rq->queue);
-+ rq->watermark = IDLE_TASK_SCHED_PRIO;
-+ rq->skip = NULL;
-+
-+ raw_spin_lock_init(&rq->lock);
-+ rq->nr_running = rq->nr_uninterruptible = 0;
-+ rq->calc_load_active = 0;
-+ rq->calc_load_update = jiffies + LOAD_FREQ;
-+#ifdef CONFIG_SMP
-+ rq->online = false;
-+ rq->cpu = i;
-+
-+#ifdef CONFIG_SCHED_SMT
-+ rq->active_balance = 0;
-+#endif
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+ INIT_CSD(&rq->nohz_csd, nohz_csd_func, rq);
-+#endif
-+ rq->balance_callback = &balance_push_callback;
-+#ifdef CONFIG_HOTPLUG_CPU
-+ rcuwait_init(&rq->hotplug_wait);
-+#endif
-+#endif /* CONFIG_SMP */
-+ rq->nr_switches = 0;
-+
-+ hrtick_rq_init(rq);
-+ atomic_set(&rq->nr_iowait, 0);
-+ }
-+#ifdef CONFIG_SMP
-+ /* Set rq->online for cpu 0 */
-+ cpu_rq(0)->online = true;
-+#endif
-+ /*
-+ * The boot idle thread does lazy MMU switching as well:
-+ */
-+ mmgrab(&init_mm);
-+ enter_lazy_tlb(&init_mm, current);
-+
-+ /*
-+ * Make us the idle thread. Technically, schedule() should not be
-+ * called from this thread, however somewhere below it might be,
-+ * but because we are the idle thread, we just pick up running again
-+ * when this runqueue becomes "idle".
-+ */
-+ init_idle(current, smp_processor_id());
-+
-+ calc_load_update = jiffies + LOAD_FREQ;
-+
-+#ifdef CONFIG_SMP
-+ idle_thread_set_boot_cpu();
-+ balance_push_set(smp_processor_id(), false);
-+
-+ sched_init_topology_cpumask_early();
-+#endif /* SMP */
-+
-+ psi_init();
-+}
-+
-+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
-+static inline int preempt_count_equals(int preempt_offset)
-+{
-+ int nested = preempt_count() + rcu_preempt_depth();
-+
-+ return (nested == preempt_offset);
-+}
-+
-+void __might_sleep(const char *file, int line, int preempt_offset)
-+{
-+ unsigned int state = get_current_state();
-+ /*
-+ * Blocking primitives will set (and therefore destroy) current->state,
-+ * since we will exit with TASK_RUNNING make sure we enter with it,
-+ * otherwise we will destroy state.
-+ */
-+ WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
-+ "do not call blocking ops when !TASK_RUNNING; "
-+ "state=%x set at [<%p>] %pS\n", state,
-+ (void *)current->task_state_change,
-+ (void *)current->task_state_change);
-+
-+ ___might_sleep(file, line, preempt_offset);
-+}
-+EXPORT_SYMBOL(__might_sleep);
-+
-+void ___might_sleep(const char *file, int line, int preempt_offset)
-+{
-+ /* Ratelimiting timestamp: */
-+ static unsigned long prev_jiffy;
-+
-+ unsigned long preempt_disable_ip;
-+
-+ /* WARN_ON_ONCE() by default, no rate limit required: */
-+ rcu_sleep_check();
-+
-+ if ((preempt_count_equals(preempt_offset) && !irqs_disabled() &&
-+ !is_idle_task(current) && !current->non_block_count) ||
-+ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING ||
-+ oops_in_progress)
-+ return;
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ /* Save this before calling printk(), since that will clobber it: */
-+ preempt_disable_ip = get_preempt_disable_ip(current);
-+
-+ printk(KERN_ERR
-+ "BUG: sleeping function called from invalid context at %s:%d\n",
-+ file, line);
-+ printk(KERN_ERR
-+ "in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(), current->non_block_count,
-+ current->pid, current->comm);
-+
-+ if (task_stack_end_corrupted(current))
-+ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
-+
-+ debug_show_held_locks(current);
-+ if (irqs_disabled())
-+ print_irqtrace_events(current);
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ if (!preempt_count_equals(preempt_offset)) {
-+ pr_err("Preemption disabled at:");
-+ print_ip_sym(KERN_ERR, preempt_disable_ip);
-+ }
-+#endif
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL(___might_sleep);
-+
-+void __cant_sleep(const char *file, int line, int preempt_offset)
-+{
-+ static unsigned long prev_jiffy;
-+
-+ if (irqs_disabled())
-+ return;
-+
-+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
-+ return;
-+
-+ if (preempt_count() > preempt_offset)
-+ return;
-+
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line);
-+ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(),
-+ current->pid, current->comm);
-+
-+ debug_show_held_locks(current);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL_GPL(__cant_sleep);
-+
-+#ifdef CONFIG_SMP
-+void __cant_migrate(const char *file, int line)
-+{
-+ static unsigned long prev_jiffy;
-+
-+ if (irqs_disabled())
-+ return;
-+
-+ if (is_migration_disabled(current))
-+ return;
-+
-+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
-+ return;
-+
-+ if (preempt_count() > 0)
-+ return;
-+
-+ if (current->migration_flags & MDF_FORCE_ENABLED)
-+ return;
-+
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ pr_err("BUG: assuming non migratable context at %s:%d\n", file, line);
-+ pr_err("in_atomic(): %d, irqs_disabled(): %d, migration_disabled() %u pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(), is_migration_disabled(current),
-+ current->pid, current->comm);
-+
-+ debug_show_held_locks(current);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL_GPL(__cant_migrate);
-+#endif
-+#endif
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+void normalize_rt_tasks(void)
-+{
-+ struct task_struct *g, *p;
-+ struct sched_attr attr = {
-+ .sched_policy = SCHED_NORMAL,
-+ };
-+
-+ read_lock(&tasklist_lock);
-+ for_each_process_thread(g, p) {
-+ /*
-+ * Only normalize user tasks:
-+ */
-+ if (p->flags & PF_KTHREAD)
-+ continue;
-+
-+ if (!rt_task(p)) {
-+ /*
-+ * Renice negative nice level userspace
-+ * tasks back to 0:
-+ */
-+ if (task_nice(p) < 0)
-+ set_user_nice(p, 0);
-+ continue;
-+ }
-+
-+ __sched_setscheduler(p, &attr, false, false);
-+ }
-+ read_unlock(&tasklist_lock);
-+}
-+#endif /* CONFIG_MAGIC_SYSRQ */
-+
-+#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB)
-+/*
-+ * These functions are only useful for the IA64 MCA handling, or kdb.
-+ *
-+ * They can only be called when the whole system has been
-+ * stopped - every CPU needs to be quiescent, and no scheduling
-+ * activity can take place. Using them for anything else would
-+ * be a serious bug, and as a result, they aren't even visible
-+ * under any other configuration.
-+ */
-+
-+/**
-+ * curr_task - return the current task for a given CPU.
-+ * @cpu: the processor in question.
-+ *
-+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
-+ *
-+ * Return: The current task for @cpu.
-+ */
-+struct task_struct *curr_task(int cpu)
-+{
-+ return cpu_curr(cpu);
-+}
-+
-+#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */
-+
-+#ifdef CONFIG_IA64
-+/**
-+ * ia64_set_curr_task - set the current task for a given CPU.
-+ * @cpu: the processor in question.
-+ * @p: the task pointer to set.
-+ *
-+ * Description: This function must only be used when non-maskable interrupts
-+ * are serviced on a separate stack. It allows the architecture to switch the
-+ * notion of the current task on a CPU in a non-blocking manner. This function
-+ * must be called with all CPU's synchronised, and interrupts disabled, the
-+ * and caller must save the original value of the current task (see
-+ * curr_task() above) and restore that value before reenabling interrupts and
-+ * re-starting the system.
-+ *
-+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
-+ */
-+void ia64_set_curr_task(int cpu, struct task_struct *p)
-+{
-+ cpu_curr(cpu) = p;
-+}
-+
-+#endif
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+static void sched_free_group(struct task_group *tg)
-+{
-+ kmem_cache_free(task_group_cache, tg);
-+}
-+
-+/* allocate runqueue etc for a new task group */
-+struct task_group *sched_create_group(struct task_group *parent)
-+{
-+ struct task_group *tg;
-+
-+ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO);
-+ if (!tg)
-+ return ERR_PTR(-ENOMEM);
-+
-+ return tg;
-+}
-+
-+void sched_online_group(struct task_group *tg, struct task_group *parent)
-+{
-+}
-+
-+/* rcu callback to free various structures associated with a task group */
-+static void sched_free_group_rcu(struct rcu_head *rhp)
-+{
-+ /* Now it should be safe to free those cfs_rqs */
-+ sched_free_group(container_of(rhp, struct task_group, rcu));
-+}
-+
-+void sched_destroy_group(struct task_group *tg)
-+{
-+ /* Wait for possible concurrent references to cfs_rqs complete */
-+ call_rcu(&tg->rcu, sched_free_group_rcu);
-+}
-+
-+void sched_offline_group(struct task_group *tg)
-+{
-+}
-+
-+static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
-+{
-+ return css ? container_of(css, struct task_group, css) : NULL;
-+}
-+
-+static struct cgroup_subsys_state *
-+cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
-+{
-+ struct task_group *parent = css_tg(parent_css);
-+ struct task_group *tg;
-+
-+ if (!parent) {
-+ /* This is early initialization for the top cgroup */
-+ return &root_task_group.css;
-+ }
-+
-+ tg = sched_create_group(parent);
-+ if (IS_ERR(tg))
-+ return ERR_PTR(-ENOMEM);
-+ return &tg->css;
-+}
-+
-+/* Expose task group only after completing cgroup initialization */
-+static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+ struct task_group *parent = css_tg(css->parent);
-+
-+ if (parent)
-+ sched_online_group(tg, parent);
-+ return 0;
-+}
-+
-+static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ sched_offline_group(tg);
-+}
-+
-+static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ /*
-+ * Relies on the RCU grace period between css_released() and this.
-+ */
-+ sched_free_group(tg);
-+}
-+
-+static void cpu_cgroup_fork(struct task_struct *task)
-+{
-+}
-+
-+static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
-+{
-+ return 0;
-+}
-+
-+static void cpu_cgroup_attach(struct cgroup_taskset *tset)
-+{
-+}
-+
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+static DEFINE_MUTEX(shares_mutex);
-+
-+int sched_group_set_shares(struct task_group *tg, unsigned long shares)
-+{
-+ /*
-+ * We can't change the weight of the root cgroup.
-+ */
-+ if (&root_task_group == tg)
-+ return -EINVAL;
-+
-+ shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES));
-+
-+ mutex_lock(&shares_mutex);
-+ if (tg->shares == shares)
-+ goto done;
-+
-+ tg->shares = shares;
-+done:
-+ mutex_unlock(&shares_mutex);
-+ return 0;
-+}
-+
-+static int cpu_shares_write_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, u64 shareval)
-+{
-+ if (shareval > scale_load_down(ULONG_MAX))
-+ shareval = MAX_SHARES;
-+ return sched_group_set_shares(css_tg(css), scale_load(shareval));
-+}
-+
-+static u64 cpu_shares_read_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ return (u64) scale_load_down(tg->shares);
-+}
-+#endif
-+
-+static struct cftype cpu_legacy_files[] = {
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+ {
-+ .name = "shares",
-+ .read_u64 = cpu_shares_read_u64,
-+ .write_u64 = cpu_shares_write_u64,
-+ },
-+#endif
-+ { } /* Terminate */
-+};
-+
-+
-+static struct cftype cpu_files[] = {
-+ { } /* terminate */
-+};
-+
-+static int cpu_extra_stat_show(struct seq_file *sf,
-+ struct cgroup_subsys_state *css)
-+{
-+ return 0;
-+}
-+
-+struct cgroup_subsys cpu_cgrp_subsys = {
-+ .css_alloc = cpu_cgroup_css_alloc,
-+ .css_online = cpu_cgroup_css_online,
-+ .css_released = cpu_cgroup_css_released,
-+ .css_free = cpu_cgroup_css_free,
-+ .css_extra_stat_show = cpu_extra_stat_show,
-+ .fork = cpu_cgroup_fork,
-+ .can_attach = cpu_cgroup_can_attach,
-+ .attach = cpu_cgroup_attach,
-+ .legacy_cftypes = cpu_files,
-+ .legacy_cftypes = cpu_legacy_files,
-+ .dfl_cftypes = cpu_files,
-+ .early_init = true,
-+ .threaded = true,
-+};
-+#endif /* CONFIG_CGROUP_SCHED */
-+
-+#undef CREATE_TRACE_POINTS
-diff -urN linux-5.15.3/kernel/sched/alt_debug.c linux-prjc-v5.15-prjc-r1/kernel/sched/alt_debug.c
---- linux-5.15.3/kernel/sched/alt_debug.c 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/alt_debug.c 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,31 @@
-+/*
-+ * kernel/sched/alt_debug.c
-+ *
-+ * Print the alt scheduler debugging details
-+ *
-+ * Author: Alfred Chen
-+ * Date : 2020
-+ */
-+#include "sched.h"
-+
-+/*
-+ * This allows printing both to /proc/sched_debug and
-+ * to the console
-+ */
-+#define SEQ_printf(m, x...) \
-+ do { \
-+ if (m) \
-+ seq_printf(m, x); \
-+ else \
-+ pr_cont(x); \
-+ } while (0)
-+
-+void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
-+ struct seq_file *m)
-+{
-+ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns),
-+ get_nr_threads(p));
-+}
-+
-+void proc_sched_set_task(struct task_struct *p)
-+{}
-diff -urN linux-5.15.3/kernel/sched/alt_sched.h linux-prjc-v5.15-prjc-r1/kernel/sched/alt_sched.h
---- linux-5.15.3/kernel/sched/alt_sched.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/alt_sched.h 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,666 @@
-+#ifndef ALT_SCHED_H
-+#define ALT_SCHED_H
-+
-+#include <linux/sched.h>
-+
-+#include <linux/sched/clock.h>
-+#include <linux/sched/cpufreq.h>
-+#include <linux/sched/cputime.h>
-+#include <linux/sched/debug.h>
-+#include <linux/sched/init.h>
-+#include <linux/sched/isolation.h>
-+#include <linux/sched/loadavg.h>
-+#include <linux/sched/mm.h>
-+#include <linux/sched/nohz.h>
-+#include <linux/sched/signal.h>
-+#include <linux/sched/stat.h>
-+#include <linux/sched/sysctl.h>
-+#include <linux/sched/task.h>
-+#include <linux/sched/topology.h>
-+#include <linux/sched/wake_q.h>
-+
-+#include <uapi/linux/sched/types.h>
-+
-+#include <linux/cgroup.h>
-+#include <linux/cpufreq.h>
-+#include <linux/cpuidle.h>
-+#include <linux/cpuset.h>
-+#include <linux/ctype.h>
-+#include <linux/debugfs.h>
-+#include <linux/kthread.h>
-+#include <linux/livepatch.h>
-+#include <linux/membarrier.h>
-+#include <linux/proc_fs.h>
-+#include <linux/psi.h>
-+#include <linux/slab.h>
-+#include <linux/stop_machine.h>
-+#include <linux/suspend.h>
-+#include <linux/swait.h>
-+#include <linux/syscalls.h>
-+#include <linux/tsacct_kern.h>
-+
-+#include <asm/tlb.h>
-+
-+#ifdef CONFIG_PARAVIRT
-+# include <asm/paravirt.h>
-+#endif
-+
-+#include "cpupri.h"
-+
-+#include <trace/events/sched.h>
-+
-+#ifdef CONFIG_SCHED_BMQ
-+/* bits:
-+ * RT(0-99), (Low prio adj range, nice width, high prio adj range) / 2, cpu idle task */
-+#define SCHED_BITS (MAX_RT_PRIO + NICE_WIDTH / 2 + MAX_PRIORITY_ADJ + 1)
-+#endif
-+
-+#ifdef CONFIG_SCHED_PDS
-+/* bits: RT(0-99), reserved(100-127), NORMAL_PRIO_NUM, cpu idle task */
-+#define SCHED_BITS (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM + 1)
-+#endif /* CONFIG_SCHED_PDS */
-+
-+#define IDLE_TASK_SCHED_PRIO (SCHED_BITS - 1)
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+# define SCHED_WARN_ON(x) WARN_ONCE(x, #x)
-+extern void resched_latency_warn(int cpu, u64 latency);
-+#else
-+# define SCHED_WARN_ON(x) ({ (void)(x), 0; })
-+static inline void resched_latency_warn(int cpu, u64 latency) {}
-+#endif
-+
-+/*
-+ * Increase resolution of nice-level calculations for 64-bit architectures.
-+ * The extra resolution improves shares distribution and load balancing of
-+ * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
-+ * hierarchies, especially on larger systems. This is not a user-visible change
-+ * and does not change the user-interface for setting shares/weights.
-+ *
-+ * We increase resolution only if we have enough bits to allow this increased
-+ * resolution (i.e. 64-bit). The costs for increasing resolution when 32-bit
-+ * are pretty high and the returns do not justify the increased costs.
-+ *
-+ * Really only required when CONFIG_FAIR_GROUP_SCHED=y is also set, but to
-+ * increase coverage and consistency always enable it on 64-bit platforms.
-+ */
-+#ifdef CONFIG_64BIT
-+# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load_down(w) \
-+({ \
-+ unsigned long __w = (w); \
-+ if (__w) \
-+ __w = max(2UL, __w >> SCHED_FIXEDPOINT_SHIFT); \
-+ __w; \
-+})
-+#else
-+# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load(w) (w)
-+# define scale_load_down(w) (w)
-+#endif
-+
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+#define ROOT_TASK_GROUP_LOAD NICE_0_LOAD
-+
-+/*
-+ * A weight of 0 or 1 can cause arithmetics problems.
-+ * A weight of a cfs_rq is the sum of weights of which entities
-+ * are queued on this cfs_rq, so a weight of a entity should not be
-+ * too large, so as the shares value of a task group.
-+ * (The default weight is 1024 - so there's no practical
-+ * limitation from this.)
-+ */
-+#define MIN_SHARES (1UL << 1)
-+#define MAX_SHARES (1UL << 18)
-+#endif
-+
-+/* task_struct::on_rq states: */
-+#define TASK_ON_RQ_QUEUED 1
-+#define TASK_ON_RQ_MIGRATING 2
-+
-+static inline int task_on_rq_queued(struct task_struct *p)
-+{
-+ return p->on_rq == TASK_ON_RQ_QUEUED;
-+}
-+
-+static inline int task_on_rq_migrating(struct task_struct *p)
-+{
-+ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING;
-+}
-+
-+/*
-+ * wake flags
-+ */
-+#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */
-+#define WF_FORK 0x02 /* child wakeup after fork */
-+#define WF_MIGRATED 0x04 /* internal use, task got migrated */
-+#define WF_ON_CPU 0x08 /* Wakee is on_rq */
-+
-+#define SCHED_QUEUE_BITS (SCHED_BITS - 1)
-+
-+struct sched_queue {
-+ DECLARE_BITMAP(bitmap, SCHED_QUEUE_BITS);
-+ struct list_head heads[SCHED_BITS];
-+};
-+
-+/*
-+ * This is the main, per-CPU runqueue data structure.
-+ * This data should only be modified by the local cpu.
-+ */
-+struct rq {
-+ /* runqueue lock: */
-+ raw_spinlock_t lock;
-+
-+ struct task_struct __rcu *curr;
-+ struct task_struct *idle, *stop, *skip;
-+ struct mm_struct *prev_mm;
-+
-+ struct sched_queue queue;
-+#ifdef CONFIG_SCHED_PDS
-+ u64 time_edge;
-+#endif
-+ unsigned long watermark;
-+
-+ /* switch count */
-+ u64 nr_switches;
-+
-+ atomic_t nr_iowait;
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+ u64 last_seen_need_resched_ns;
-+ int ticks_without_resched;
-+#endif
-+
-+#ifdef CONFIG_MEMBARRIER
-+ int membarrier_state;
-+#endif
-+
-+#ifdef CONFIG_SMP
-+ int cpu; /* cpu of this runqueue */
-+ bool online;
-+
-+ unsigned int ttwu_pending;
-+ unsigned char nohz_idle_balance;
-+ unsigned char idle_balance;
-+
-+#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
-+ struct sched_avg avg_irq;
-+#endif
-+
-+#ifdef CONFIG_SCHED_SMT
-+ int active_balance;
-+ struct cpu_stop_work active_balance_work;
-+#endif
-+ struct callback_head *balance_callback;
-+#ifdef CONFIG_HOTPLUG_CPU
-+ struct rcuwait hotplug_wait;
-+#endif
-+ unsigned int nr_pinned;
-+
-+#endif /* CONFIG_SMP */
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+ u64 prev_irq_time;
-+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-+#ifdef CONFIG_PARAVIRT
-+ u64 prev_steal_time;
-+#endif /* CONFIG_PARAVIRT */
-+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
-+ u64 prev_steal_time_rq;
-+#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */
-+
-+ /* For genenal cpu load util */
-+ s32 load_history;
-+ u64 load_block;
-+ u64 load_stamp;
-+
-+ /* calc_load related fields */
-+ unsigned long calc_load_update;
-+ long calc_load_active;
-+
-+ u64 clock, last_tick;
-+ u64 last_ts_switch;
-+ u64 clock_task;
-+
-+ unsigned int nr_running;
-+ unsigned long nr_uninterruptible;
-+
-+#ifdef CONFIG_SCHED_HRTICK
-+#ifdef CONFIG_SMP
-+ call_single_data_t hrtick_csd;
-+#endif
-+ struct hrtimer hrtick_timer;
-+ ktime_t hrtick_time;
-+#endif
-+
-+#ifdef CONFIG_SCHEDSTATS
-+
-+ /* latency stats */
-+ struct sched_info rq_sched_info;
-+ unsigned long long rq_cpu_time;
-+ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */
-+
-+ /* sys_sched_yield() stats */
-+ unsigned int yld_count;
-+
-+ /* schedule() stats */
-+ unsigned int sched_switch;
-+ unsigned int sched_count;
-+ unsigned int sched_goidle;
-+
-+ /* try_to_wake_up() stats */
-+ unsigned int ttwu_count;
-+ unsigned int ttwu_local;
-+#endif /* CONFIG_SCHEDSTATS */
-+
-+#ifdef CONFIG_CPU_IDLE
-+ /* Must be inspected within a rcu lock section */
-+ struct cpuidle_state *idle_state;
-+#endif
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+#ifdef CONFIG_SMP
-+ call_single_data_t nohz_csd;
-+#endif
-+ atomic_t nohz_flags;
-+#endif /* CONFIG_NO_HZ_COMMON */
-+};
-+
-+extern unsigned long rq_load_util(struct rq *rq, unsigned long max);
-+
-+extern unsigned long calc_load_update;
-+extern atomic_long_t calc_load_tasks;
-+
-+extern void calc_global_load_tick(struct rq *this_rq);
-+extern long calc_load_fold_active(struct rq *this_rq, long adjust);
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-+#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
-+#define this_rq() this_cpu_ptr(&runqueues)
-+#define task_rq(p) cpu_rq(task_cpu(p))
-+#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
-+#define raw_rq() raw_cpu_ptr(&runqueues)
-+
-+#ifdef CONFIG_SMP
-+#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
-+void register_sched_domain_sysctl(void);
-+void unregister_sched_domain_sysctl(void);
-+#else
-+static inline void register_sched_domain_sysctl(void)
-+{
-+}
-+static inline void unregister_sched_domain_sysctl(void)
-+{
-+}
-+#endif
-+
-+extern bool sched_smp_initialized;
-+
-+enum {
-+ ITSELF_LEVEL_SPACE_HOLDER,
-+#ifdef CONFIG_SCHED_SMT
-+ SMT_LEVEL_SPACE_HOLDER,
-+#endif
-+ COREGROUP_LEVEL_SPACE_HOLDER,
-+ CORE_LEVEL_SPACE_HOLDER,
-+ OTHER_LEVEL_SPACE_HOLDER,
-+ NR_CPU_AFFINITY_LEVELS
-+};
-+
-+DECLARE_PER_CPU(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
-+DECLARE_PER_CPU(cpumask_t *, sched_cpu_llc_mask);
-+
-+static inline int
-+__best_mask_cpu(const cpumask_t *cpumask, const cpumask_t *mask)
-+{
-+ int cpu;
-+
-+ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids)
-+ mask++;
-+
-+ return cpu;
-+}
-+
-+static inline int best_mask_cpu(int cpu, const cpumask_t *mask)
-+{
-+ return __best_mask_cpu(mask, per_cpu(sched_cpu_topo_masks, cpu));
-+}
-+
-+extern void flush_smp_call_function_from_idle(void);
-+
-+#else /* !CONFIG_SMP */
-+static inline void flush_smp_call_function_from_idle(void) { }
-+#endif
-+
-+#ifndef arch_scale_freq_tick
-+static __always_inline
-+void arch_scale_freq_tick(void)
-+{
-+}
-+#endif
-+
-+#ifndef arch_scale_freq_capacity
-+static __always_inline
-+unsigned long arch_scale_freq_capacity(int cpu)
-+{
-+ return SCHED_CAPACITY_SCALE;
-+}
-+#endif
-+
-+static inline u64 __rq_clock_broken(struct rq *rq)
-+{
-+ return READ_ONCE(rq->clock);
-+}
-+
-+static inline u64 rq_clock(struct rq *rq)
-+{
-+ /*
-+ * Relax lockdep_assert_held() checking as in VRQ, call to
-+ * sched_info_xxxx() may not held rq->lock
-+ * lockdep_assert_held(&rq->lock);
-+ */
-+ return rq->clock;
-+}
-+
-+static inline u64 rq_clock_task(struct rq *rq)
-+{
-+ /*
-+ * Relax lockdep_assert_held() checking as in VRQ, call to
-+ * sched_info_xxxx() may not held rq->lock
-+ * lockdep_assert_held(&rq->lock);
-+ */
-+ return rq->clock_task;
-+}
-+
-+/*
-+ * {de,en}queue flags:
-+ *
-+ * DEQUEUE_SLEEP - task is no longer runnable
-+ * ENQUEUE_WAKEUP - task just became runnable
-+ *
-+ */
-+
-+#define DEQUEUE_SLEEP 0x01
-+
-+#define ENQUEUE_WAKEUP 0x01
-+
-+
-+/*
-+ * Below are scheduler API which using in other kernel code
-+ * It use the dummy rq_flags
-+ * ToDo : BMQ need to support these APIs for compatibility with mainline
-+ * scheduler code.
-+ */
-+struct rq_flags {
-+ unsigned long flags;
-+};
-+
-+struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(rq->lock);
-+
-+struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(p->pi_lock)
-+ __acquires(rq->lock);
-+
-+static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+static inline void
-+task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
-+ __releases(rq->lock)
-+ __releases(p->pi_lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
-+}
-+
-+static inline void
-+rq_lock(struct rq *rq, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ raw_spin_lock(&rq->lock);
-+}
-+
-+static inline void
-+rq_unlock_irq(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock_irq(&rq->lock);
-+}
-+
-+static inline void
-+rq_unlock(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+static inline struct rq *
-+this_rq_lock_irq(struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ local_irq_disable();
-+ rq = this_rq();
-+ raw_spin_lock(&rq->lock);
-+
-+ return rq;
-+}
-+
-+extern void raw_spin_rq_lock_nested(struct rq *rq, int subclass);
-+extern void raw_spin_rq_unlock(struct rq *rq);
-+
-+static inline raw_spinlock_t *__rq_lockp(struct rq *rq)
-+{
-+ return &rq->lock;
-+}
-+
-+static inline raw_spinlock_t *rq_lockp(struct rq *rq)
-+{
-+ return __rq_lockp(rq);
-+}
-+
-+static inline void raw_spin_rq_lock(struct rq *rq)
-+{
-+ raw_spin_rq_lock_nested(rq, 0);
-+}
-+
-+static inline void raw_spin_rq_lock_irq(struct rq *rq)
-+{
-+ local_irq_disable();
-+ raw_spin_rq_lock(rq);
-+}
-+
-+static inline void raw_spin_rq_unlock_irq(struct rq *rq)
-+{
-+ raw_spin_rq_unlock(rq);
-+ local_irq_enable();
-+}
-+
-+static inline int task_current(struct rq *rq, struct task_struct *p)
-+{
-+ return rq->curr == p;
-+}
-+
-+static inline bool task_running(struct task_struct *p)
-+{
-+ return p->on_cpu;
-+}
-+
-+extern int task_running_nice(struct task_struct *p);
-+
-+extern struct static_key_false sched_schedstats;
-+
-+#ifdef CONFIG_CPU_IDLE
-+static inline void idle_set_state(struct rq *rq,
-+ struct cpuidle_state *idle_state)
-+{
-+ rq->idle_state = idle_state;
-+}
-+
-+static inline struct cpuidle_state *idle_get_state(struct rq *rq)
-+{
-+ WARN_ON(!rcu_read_lock_held());
-+ return rq->idle_state;
-+}
-+#else
-+static inline void idle_set_state(struct rq *rq,
-+ struct cpuidle_state *idle_state)
-+{
-+}
-+
-+static inline struct cpuidle_state *idle_get_state(struct rq *rq)
-+{
-+ return NULL;
-+}
-+#endif
-+
-+static inline int cpu_of(const struct rq *rq)
-+{
-+#ifdef CONFIG_SMP
-+ return rq->cpu;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+#include "stats.h"
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+#define NOHZ_BALANCE_KICK_BIT 0
-+#define NOHZ_STATS_KICK_BIT 1
-+
-+#define NOHZ_BALANCE_KICK BIT(NOHZ_BALANCE_KICK_BIT)
-+#define NOHZ_STATS_KICK BIT(NOHZ_STATS_KICK_BIT)
-+
-+#define NOHZ_KICK_MASK (NOHZ_BALANCE_KICK | NOHZ_STATS_KICK)
-+
-+#define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags)
-+
-+/* TODO: needed?
-+extern void nohz_balance_exit_idle(struct rq *rq);
-+#else
-+static inline void nohz_balance_exit_idle(struct rq *rq) { }
-+*/
-+#endif
-+
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+struct irqtime {
-+ u64 total;
-+ u64 tick_delta;
-+ u64 irq_start_time;
-+ struct u64_stats_sync sync;
-+};
-+
-+DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
-+
-+/*
-+ * Returns the irqtime minus the softirq time computed by ksoftirqd.
-+ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime
-+ * and never move forward.
-+ */
-+static inline u64 irq_time_read(int cpu)
-+{
-+ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu);
-+ unsigned int seq;
-+ u64 total;
-+
-+ do {
-+ seq = __u64_stats_fetch_begin(&irqtime->sync);
-+ total = irqtime->total;
-+ } while (__u64_stats_fetch_retry(&irqtime->sync, seq));
-+
-+ return total;
-+}
-+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-+
-+#ifdef CONFIG_CPU_FREQ
-+DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
-+#endif /* CONFIG_CPU_FREQ */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+extern int __init sched_tick_offload_init(void);
-+#else
-+static inline int sched_tick_offload_init(void) { return 0; }
-+#endif
-+
-+#ifdef arch_scale_freq_capacity
-+#ifndef arch_scale_freq_invariant
-+#define arch_scale_freq_invariant() (true)
-+#endif
-+#else /* arch_scale_freq_capacity */
-+#define arch_scale_freq_invariant() (false)
-+#endif
-+
-+extern void schedule_idle(void);
-+
-+#define cap_scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT)
-+
-+/*
-+ * !! For sched_setattr_nocheck() (kernel) only !!
-+ *
-+ * This is actually gross. :(
-+ *
-+ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE
-+ * tasks, but still be able to sleep. We need this on platforms that cannot
-+ * atomically change clock frequency. Remove once fast switching will be
-+ * available on such platforms.
-+ *
-+ * SUGOV stands for SchedUtil GOVernor.
-+ */
-+#define SCHED_FLAG_SUGOV 0x10000000
-+
-+#ifdef CONFIG_MEMBARRIER
-+/*
-+ * The scheduler provides memory barriers required by membarrier between:
-+ * - prior user-space memory accesses and store to rq->membarrier_state,
-+ * - store to rq->membarrier_state and following user-space memory accesses.
-+ * In the same way it provides those guarantees around store to rq->curr.
-+ */
-+static inline void membarrier_switch_mm(struct rq *rq,
-+ struct mm_struct *prev_mm,
-+ struct mm_struct *next_mm)
-+{
-+ int membarrier_state;
-+
-+ if (prev_mm == next_mm)
-+ return;
-+
-+ membarrier_state = atomic_read(&next_mm->membarrier_state);
-+ if (READ_ONCE(rq->membarrier_state) == membarrier_state)
-+ return;
-+
-+ WRITE_ONCE(rq->membarrier_state, membarrier_state);
-+}
-+#else
-+static inline void membarrier_switch_mm(struct rq *rq,
-+ struct mm_struct *prev_mm,
-+ struct mm_struct *next_mm)
-+{
-+}
-+#endif
-+
-+#ifdef CONFIG_NUMA
-+extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu);
-+#else
-+static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
-+{
-+ return nr_cpu_ids;
-+}
-+#endif
-+
-+extern void swake_up_all_locked(struct swait_queue_head *q);
-+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+extern int preempt_dynamic_mode;
-+extern int sched_dynamic_mode(const char *str);
-+extern void sched_dynamic_update(int mode);
-+#endif
-+
-+static inline void nohz_run_idle_balance(int cpu) { }
-+#endif /* ALT_SCHED_H */
-diff -urN linux-5.15.3/kernel/sched/bmq.h linux-prjc-v5.15-prjc-r1/kernel/sched/bmq.h
---- linux-5.15.3/kernel/sched/bmq.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/bmq.h 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,111 @@
-+#define ALT_SCHED_VERSION_MSG "sched/bmq: BMQ CPU Scheduler "ALT_SCHED_VERSION" by Alfred Chen.\n"
-+
-+/*
-+ * BMQ only routines
-+ */
-+#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch)
-+#define boost_threshold(p) (sched_timeslice_ns >>\
-+ (15 - MAX_PRIORITY_ADJ - (p)->boost_prio))
-+
-+static inline void boost_task(struct task_struct *p)
-+{
-+ int limit;
-+
-+ switch (p->policy) {
-+ case SCHED_NORMAL:
-+ limit = -MAX_PRIORITY_ADJ;
-+ break;
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ limit = 0;
-+ break;
-+ default:
-+ return;
-+ }
-+
-+ if (p->boost_prio > limit)
-+ p->boost_prio--;
-+}
-+
-+static inline void deboost_task(struct task_struct *p)
-+{
-+ if (p->boost_prio < MAX_PRIORITY_ADJ)
-+ p->boost_prio++;
-+}
-+
-+/*
-+ * Common interfaces
-+ */
-+static inline void sched_timeslice_imp(const int timeslice_ms) {}
-+
-+static inline int
-+task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
-+{
-+ return p->prio + p->boost_prio - MAX_RT_PRIO;
-+}
-+
-+static inline int task_sched_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MAX_RT_PRIO)? p->prio : MAX_RT_PRIO / 2 + (p->prio + p->boost_prio) / 2;
-+}
-+
-+static inline int
-+task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
-+{
-+ return task_sched_prio(p);
-+}
-+
-+static inline int sched_prio2idx(int prio, struct rq *rq)
-+{
-+ return prio;
-+}
-+
-+static inline int sched_idx2prio(int idx, struct rq *rq)
-+{
-+ return idx;
-+}
-+
-+static inline void time_slice_expired(struct task_struct *p, struct rq *rq)
-+{
-+ p->time_slice = sched_timeslice_ns;
-+
-+ if (SCHED_FIFO != p->policy && task_on_rq_queued(p)) {
-+ if (SCHED_RR != p->policy)
-+ deboost_task(p);
-+ requeue_task(p, rq);
-+ }
-+}
-+
-+static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq) {}
-+
-+inline int task_running_nice(struct task_struct *p)
-+{
-+ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ);
-+}
-+
-+static void sched_task_fork(struct task_struct *p, struct rq *rq)
-+{
-+ p->boost_prio = (p->boost_prio < 0) ?
-+ p->boost_prio + MAX_PRIORITY_ADJ : MAX_PRIORITY_ADJ;
-+}
-+
-+static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
-+{
-+ p->boost_prio = MAX_PRIORITY_ADJ;
-+}
-+
-+#ifdef CONFIG_SMP
-+static inline void sched_task_ttwu(struct task_struct *p)
-+{
-+ if(this_rq()->clock_task - p->last_ran > sched_timeslice_ns)
-+ boost_task(p);
-+}
-+#endif
-+
-+static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq)
-+{
-+ if (rq_switch_time(rq) < boost_threshold(p))
-+ boost_task(p);
-+}
-+
-+static inline void update_rq_time_edge(struct rq *rq) {}
-diff -urN linux-5.15.3/kernel/sched/cpufreq_schedutil.c linux-prjc-v5.15-prjc-r1/kernel/sched/cpufreq_schedutil.c
---- linux-5.15.3/kernel/sched/cpufreq_schedutil.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/cpufreq_schedutil.c 2021-11-20 02:15:12.000000000 +1100
-@@ -167,9 +167,14 @@
- unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu);
-
- sg_cpu->max = max;
-+#ifndef CONFIG_SCHED_ALT
- sg_cpu->bw_dl = cpu_bw_dl(rq);
- sg_cpu->util = effective_cpu_util(sg_cpu->cpu, cpu_util_cfs(rq), max,
- FREQUENCY_UTIL, NULL);
-+#else
-+ sg_cpu->bw_dl = 0;
-+ sg_cpu->util = rq_load_util(rq, max);
-+#endif /* CONFIG_SCHED_ALT */
- }
-
- /**
-@@ -312,8 +317,10 @@
- */
- static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
- {
-+#ifndef CONFIG_SCHED_ALT
- if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
- sg_cpu->sg_policy->limits_changed = true;
-+#endif
- }
-
- static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
-@@ -607,6 +614,7 @@
- }
-
- ret = sched_setattr_nocheck(thread, &attr);
-+
- if (ret) {
- kthread_stop(thread);
- pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__);
-@@ -839,7 +847,9 @@
- #ifdef CONFIG_ENERGY_MODEL
- static void rebuild_sd_workfn(struct work_struct *work)
- {
-+#ifndef CONFIG_SCHED_ALT
- rebuild_sched_domains_energy();
-+#endif /* CONFIG_SCHED_ALT */
- }
- static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn);
-
-diff -urN linux-5.15.3/kernel/sched/cputime.c linux-prjc-v5.15-prjc-r1/kernel/sched/cputime.c
---- linux-5.15.3/kernel/sched/cputime.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/cputime.c 2021-11-20 02:15:12.000000000 +1100
-@@ -123,7 +123,7 @@
- p->utime += cputime;
- account_group_user_time(p, cputime);
-
-- index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
-+ index = task_running_nice(p) ? CPUTIME_NICE : CPUTIME_USER;
-
- /* Add user time to cpustat. */
- task_group_account_field(p, index, cputime);
-@@ -147,7 +147,7 @@
- p->gtime += cputime;
-
- /* Add guest time to cpustat. */
-- if (task_nice(p) > 0) {
-+ if (task_running_nice(p)) {
- task_group_account_field(p, CPUTIME_NICE, cputime);
- cpustat[CPUTIME_GUEST_NICE] += cputime;
- } else {
-@@ -270,7 +270,7 @@
- #ifdef CONFIG_64BIT
- static inline u64 read_sum_exec_runtime(struct task_struct *t)
- {
-- return t->se.sum_exec_runtime;
-+ return tsk_seruntime(t);
- }
- #else
- static u64 read_sum_exec_runtime(struct task_struct *t)
-@@ -280,7 +280,7 @@
- struct rq *rq;
-
- rq = task_rq_lock(t, &rf);
-- ns = t->se.sum_exec_runtime;
-+ ns = tsk_seruntime(t);
- task_rq_unlock(rq, t, &rf);
-
- return ns;
-@@ -612,7 +612,7 @@
- void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
- {
- struct task_cputime cputime = {
-- .sum_exec_runtime = p->se.sum_exec_runtime,
-+ .sum_exec_runtime = tsk_seruntime(p),
- };
-
- task_cputime(p, &cputime.utime, &cputime.stime);
-diff -urN linux-5.15.3/kernel/sched/debug.c linux-prjc-v5.15-prjc-r1/kernel/sched/debug.c
---- linux-5.15.3/kernel/sched/debug.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/debug.c 2021-11-20 02:15:12.000000000 +1100
-@@ -8,6 +8,7 @@
- */
- #include "sched.h"
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * This allows printing both to /proc/sched_debug and
- * to the console
-@@ -216,6 +217,7 @@
- };
-
- #endif /* SMP */
-+#endif /* !CONFIG_SCHED_ALT */
-
- #ifdef CONFIG_PREEMPT_DYNAMIC
-
-@@ -279,6 +281,7 @@
-
- #endif /* CONFIG_PREEMPT_DYNAMIC */
-
-+#ifndef CONFIG_SCHED_ALT
- __read_mostly bool sched_debug_verbose;
-
- static const struct seq_operations sched_debug_sops;
-@@ -294,6 +297,7 @@
- .llseek = seq_lseek,
- .release = seq_release,
- };
-+#endif /* !CONFIG_SCHED_ALT */
-
- static struct dentry *debugfs_sched;
-
-@@ -303,12 +307,15 @@
-
- debugfs_sched = debugfs_create_dir("sched", NULL);
-
-+#ifndef CONFIG_SCHED_ALT
- debugfs_create_file("features", 0644, debugfs_sched, NULL, &sched_feat_fops);
- debugfs_create_bool("verbose", 0644, debugfs_sched, &sched_debug_verbose);
-+#endif /* !CONFIG_SCHED_ALT */
- #ifdef CONFIG_PREEMPT_DYNAMIC
- debugfs_create_file("preempt", 0644, debugfs_sched, NULL, &sched_dynamic_fops);
- #endif
-
-+#ifndef CONFIG_SCHED_ALT
- debugfs_create_u32("latency_ns", 0644, debugfs_sched, &sysctl_sched_latency);
- debugfs_create_u32("min_granularity_ns", 0644, debugfs_sched, &sysctl_sched_min_granularity);
- debugfs_create_u32("wakeup_granularity_ns", 0644, debugfs_sched, &sysctl_sched_wakeup_granularity);
-@@ -336,11 +343,13 @@
- #endif
-
- debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);
-+#endif /* !CONFIG_SCHED_ALT */
-
- return 0;
- }
- late_initcall(sched_init_debug);
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_SMP
-
- static cpumask_var_t sd_sysctl_cpus;
-@@ -1063,6 +1072,7 @@
- memset(&p->se.statistics, 0, sizeof(p->se.statistics));
- #endif
- }
-+#endif /* !CONFIG_SCHED_ALT */
-
- void resched_latency_warn(int cpu, u64 latency)
- {
-diff -urN linux-5.15.3/kernel/sched/idle.c linux-prjc-v5.15-prjc-r1/kernel/sched/idle.c
---- linux-5.15.3/kernel/sched/idle.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/idle.c 2021-11-20 02:15:12.000000000 +1100
-@@ -403,6 +403,7 @@
- do_idle();
- }
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * idle-task scheduling class.
- */
-@@ -525,3 +526,4 @@
- .switched_to = switched_to_idle,
- .update_curr = update_curr_idle,
- };
-+#endif
-diff -urN linux-5.15.3/kernel/sched/pds.h linux-prjc-v5.15-prjc-r1/kernel/sched/pds.h
---- linux-5.15.3/kernel/sched/pds.h 1970-01-01 10:00:00.000000000 +1000
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/pds.h 2021-11-20 02:15:12.000000000 +1100
-@@ -0,0 +1,127 @@
-+#define ALT_SCHED_VERSION_MSG "sched/pds: PDS CPU Scheduler "ALT_SCHED_VERSION" by Alfred Chen.\n"
-+
-+static int sched_timeslice_shift = 22;
-+
-+#define NORMAL_PRIO_MOD(x) ((x) & (NORMAL_PRIO_NUM - 1))
-+
-+/*
-+ * Common interfaces
-+ */
-+static inline void sched_timeslice_imp(const int timeslice_ms)
-+{
-+ if (2 == timeslice_ms)
-+ sched_timeslice_shift = 21;
-+}
-+
-+static inline int
-+task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
-+{
-+ s64 delta = p->deadline - rq->time_edge + NORMAL_PRIO_NUM - NICE_WIDTH;
-+
-+ if (WARN_ONCE(delta > NORMAL_PRIO_NUM - 1,
-+ "pds: task_sched_prio_normal() delta %lld\n", delta))
-+ return NORMAL_PRIO_NUM - 1;
-+
-+ return (delta < 0) ? 0 : delta;
-+}
-+
-+static inline int task_sched_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MAX_RT_PRIO) ? p->prio :
-+ MIN_NORMAL_PRIO + task_sched_prio_normal(p, task_rq(p));
-+}
-+
-+static inline int
-+task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
-+{
-+ return (p->prio < MAX_RT_PRIO) ? p->prio : MIN_NORMAL_PRIO +
-+ NORMAL_PRIO_MOD(task_sched_prio_normal(p, rq) + rq->time_edge);
-+}
-+
-+static inline int sched_prio2idx(int prio, struct rq *rq)
-+{
-+ return (IDLE_TASK_SCHED_PRIO == prio || prio < MAX_RT_PRIO) ? prio :
-+ MIN_NORMAL_PRIO + NORMAL_PRIO_MOD((prio - MIN_NORMAL_PRIO) +
-+ rq->time_edge);
-+}
-+
-+static inline int sched_idx2prio(int idx, struct rq *rq)
-+{
-+ return (idx < MAX_RT_PRIO) ? idx : MIN_NORMAL_PRIO +
-+ NORMAL_PRIO_MOD((idx - MIN_NORMAL_PRIO) + NORMAL_PRIO_NUM -
-+ NORMAL_PRIO_MOD(rq->time_edge));
-+}
-+
-+static inline void sched_renew_deadline(struct task_struct *p, const struct rq *rq)
-+{
-+ if (p->prio >= MAX_RT_PRIO)
-+ p->deadline = (rq->clock >> sched_timeslice_shift) +
-+ p->static_prio - (MAX_PRIO - NICE_WIDTH);
-+}
-+
-+int task_running_nice(struct task_struct *p)
-+{
-+ return (p->prio > DEFAULT_PRIO);
-+}
-+
-+static inline void update_rq_time_edge(struct rq *rq)
-+{
-+ struct list_head head;
-+ u64 old = rq->time_edge;
-+ u64 now = rq->clock >> sched_timeslice_shift;
-+ u64 prio, delta;
-+
-+ if (now == old)
-+ return;
-+
-+ delta = min_t(u64, NORMAL_PRIO_NUM, now - old);
-+ INIT_LIST_HEAD(&head);
-+
-+ for_each_set_bit(prio, &rq->queue.bitmap[2], delta)
-+ list_splice_tail_init(rq->queue.heads + MIN_NORMAL_PRIO +
-+ NORMAL_PRIO_MOD(prio + old), &head);
-+
-+ rq->queue.bitmap[2] = (NORMAL_PRIO_NUM == delta) ? 0UL :
-+ rq->queue.bitmap[2] >> delta;
-+ rq->time_edge = now;
-+ if (!list_empty(&head)) {
-+ u64 idx = MIN_NORMAL_PRIO + NORMAL_PRIO_MOD(now);
-+ struct task_struct *p;
-+
-+ list_for_each_entry(p, &head, sq_node)
-+ p->sq_idx = idx;
-+
-+ list_splice(&head, rq->queue.heads + idx);
-+ rq->queue.bitmap[2] |= 1UL;
-+ }
-+}
-+
-+static inline void time_slice_expired(struct task_struct *p, struct rq *rq)
-+{
-+ p->time_slice = sched_timeslice_ns;
-+ sched_renew_deadline(p, rq);
-+ if (SCHED_FIFO != p->policy && task_on_rq_queued(p))
-+ requeue_task(p, rq);
-+}
-+
-+static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq)
-+{
-+ u64 max_dl = rq->time_edge + NICE_WIDTH - 1;
-+ if (unlikely(p->deadline > max_dl))
-+ p->deadline = max_dl;
-+}
-+
-+static void sched_task_fork(struct task_struct *p, struct rq *rq)
-+{
-+ sched_renew_deadline(p, rq);
-+}
-+
-+static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
-+{
-+ time_slice_expired(p, rq);
-+}
-+
-+#ifdef CONFIG_SMP
-+static inline void sched_task_ttwu(struct task_struct *p) {}
-+#endif
-+static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq) {}
-diff -urN linux-5.15.3/kernel/sched/pelt.c linux-prjc-v5.15-prjc-r1/kernel/sched/pelt.c
---- linux-5.15.3/kernel/sched/pelt.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/pelt.c 2021-11-20 02:15:12.000000000 +1100
-@@ -270,6 +270,7 @@
- WRITE_ONCE(sa->util_avg, sa->util_sum / divider);
- }
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * sched_entity:
- *
-@@ -387,8 +388,9 @@
-
- return 0;
- }
-+#endif
-
--#ifdef CONFIG_SCHED_THERMAL_PRESSURE
-+#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
- /*
- * thermal:
- *
-diff -urN linux-5.15.3/kernel/sched/pelt.h linux-prjc-v5.15-prjc-r1/kernel/sched/pelt.h
---- linux-5.15.3/kernel/sched/pelt.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/pelt.h 2021-11-20 02:15:12.000000000 +1100
-@@ -1,13 +1,15 @@
- #ifdef CONFIG_SMP
- #include "sched-pelt.h"
-
-+#ifndef CONFIG_SCHED_ALT
- int __update_load_avg_blocked_se(u64 now, struct sched_entity *se);
- int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se);
- int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq);
- int update_rt_rq_load_avg(u64 now, struct rq *rq, int running);
- int update_dl_rq_load_avg(u64 now, struct rq *rq, int running);
-+#endif
-
--#ifdef CONFIG_SCHED_THERMAL_PRESSURE
-+#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
- int update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity);
-
- static inline u64 thermal_load_avg(struct rq *rq)
-@@ -42,6 +44,7 @@
- return LOAD_AVG_MAX - 1024 + avg->period_contrib;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- static inline void cfs_se_util_change(struct sched_avg *avg)
- {
- unsigned int enqueued;
-@@ -153,9 +156,11 @@
- return rq_clock_pelt(rq_of(cfs_rq));
- }
- #endif
-+#endif /* CONFIG_SCHED_ALT */
-
- #else
-
-+#ifndef CONFIG_SCHED_ALT
- static inline int
- update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
- {
-@@ -173,6 +178,7 @@
- {
- return 0;
- }
-+#endif
-
- static inline int
- update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity)
-diff -urN linux-5.15.3/kernel/sched/sched.h linux-prjc-v5.15-prjc-r1/kernel/sched/sched.h
---- linux-5.15.3/kernel/sched/sched.h 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/sched.h 2021-11-20 02:15:12.000000000 +1100
-@@ -2,6 +2,10 @@
- /*
- * Scheduler internal types and methods:
- */
-+#ifdef CONFIG_SCHED_ALT
-+#include "alt_sched.h"
-+#else
-+
- #include <linux/sched.h>
-
- #include <linux/sched/autogroup.h>
-@@ -3064,3 +3068,8 @@
- extern void sched_dynamic_update(int mode);
- #endif
-
-+static inline int task_running_nice(struct task_struct *p)
-+{
-+ return (task_nice(p) > 0);
-+}
-+#endif /* !CONFIG_SCHED_ALT */
-diff -urN linux-5.15.3/kernel/sched/stats.c linux-prjc-v5.15-prjc-r1/kernel/sched/stats.c
---- linux-5.15.3/kernel/sched/stats.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/stats.c 2021-11-20 02:15:12.000000000 +1100
-@@ -22,9 +22,11 @@
- } else {
- struct rq *rq;
- #ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- struct sched_domain *sd;
- int dcount = 0;
- #endif
-+#endif
- cpu = (unsigned long)(v - 2);
- rq = cpu_rq(cpu);
-
-@@ -40,6 +42,7 @@
- seq_printf(seq, "\n");
-
- #ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- /* domain-specific stats */
- rcu_read_lock();
- for_each_domain(cpu, sd) {
-@@ -69,6 +72,7 @@
- }
- rcu_read_unlock();
- #endif
-+#endif
- }
- return 0;
- }
-diff -urN linux-5.15.3/kernel/sched/topology.c linux-prjc-v5.15-prjc-r1/kernel/sched/topology.c
---- linux-5.15.3/kernel/sched/topology.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sched/topology.c 2021-11-20 02:15:12.000000000 +1100
-@@ -4,6 +4,7 @@
- */
- #include "sched.h"
-
-+#ifndef CONFIG_SCHED_ALT
- DEFINE_MUTEX(sched_domains_mutex);
-
- /* Protected by sched_domains_mutex: */
-@@ -1382,8 +1383,10 @@
- */
-
- static int default_relax_domain_level = -1;
-+#endif /* CONFIG_SCHED_ALT */
- int sched_domain_level_max;
-
-+#ifndef CONFIG_SCHED_ALT
- static int __init setup_relax_domain_level(char *str)
- {
- if (kstrtoint(str, 0, &default_relax_domain_level))
-@@ -1619,6 +1622,7 @@
-
- return sd;
- }
-+#endif /* CONFIG_SCHED_ALT */
-
- /*
- * Topology list, bottom-up.
-@@ -1648,6 +1652,7 @@
- sched_domain_topology = tl;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_NUMA
-
- static const struct cpumask *sd_numa_mask(int cpu)
-@@ -2516,3 +2521,17 @@
- partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
- mutex_unlock(&sched_domains_mutex);
- }
-+#else /* CONFIG_SCHED_ALT */
-+void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
-+ struct sched_domain_attr *dattr_new)
-+{}
-+
-+#ifdef CONFIG_NUMA
-+int __read_mostly node_reclaim_distance = RECLAIM_DISTANCE;
-+
-+int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
-+{
-+ return best_mask_cpu(cpu, cpus);
-+}
-+#endif /* CONFIG_NUMA */
-+#endif
-diff -urN linux-5.15.3/kernel/sysctl.c linux-prjc-v5.15-prjc-r1/kernel/sysctl.c
---- linux-5.15.3/kernel/sysctl.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/sysctl.c 2021-11-20 02:15:12.000000000 +1100
-@@ -122,6 +122,10 @@
- static int one_hundred = 100;
- static int two_hundred = 200;
- static int one_thousand = 1000;
-+#ifdef CONFIG_SCHED_ALT
-+static int __maybe_unused zero = 0;
-+extern int sched_yield_type;
-+#endif
- #ifdef CONFIG_PRINTK
- static int ten_thousand = 10000;
- #endif
-@@ -1771,6 +1775,24 @@
- }
-
- static struct ctl_table kern_table[] = {
-+#ifdef CONFIG_SCHED_ALT
-+/* In ALT, only supported "sched_schedstats" */
-+#ifdef CONFIG_SCHED_DEBUG
-+#ifdef CONFIG_SMP
-+#ifdef CONFIG_SCHEDSTATS
-+ {
-+ .procname = "sched_schedstats",
-+ .data = NULL,
-+ .maxlen = sizeof(unsigned int),
-+ .mode = 0644,
-+ .proc_handler = sysctl_schedstats,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+#endif /* CONFIG_SCHEDSTATS */
-+#endif /* CONFIG_SMP */
-+#endif /* CONFIG_SCHED_DEBUG */
-+#else /* !CONFIG_SCHED_ALT */
- {
- .procname = "sched_child_runs_first",
- .data = &sysctl_sched_child_runs_first,
-@@ -1901,6 +1923,7 @@
- .extra2 = SYSCTL_ONE,
- },
- #endif
-+#endif /* !CONFIG_SCHED_ALT */
- #ifdef CONFIG_PROVE_LOCKING
- {
- .procname = "prove_locking",
-@@ -2477,6 +2500,17 @@
- .proc_handler = proc_dointvec,
- },
- #endif
-+#ifdef CONFIG_SCHED_ALT
-+ {
-+ .procname = "yield_type",
-+ .data = &sched_yield_type,
-+ .maxlen = sizeof (int),
-+ .mode = 0644,
-+ .proc_handler = &proc_dointvec_minmax,
-+ .extra1 = &zero,
-+ .extra2 = &two,
-+ },
-+#endif
- #if defined(CONFIG_S390) && defined(CONFIG_SMP)
- {
- .procname = "spin_retry",
-diff -urN linux-5.15.3/kernel/time/hrtimer.c linux-prjc-v5.15-prjc-r1/kernel/time/hrtimer.c
---- linux-5.15.3/kernel/time/hrtimer.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/time/hrtimer.c 2021-11-20 02:15:12.000000000 +1100
-@@ -2088,8 +2088,10 @@
- int ret = 0;
- u64 slack;
-
-+#ifndef CONFIG_SCHED_ALT
- slack = current->timer_slack_ns;
- if (dl_task(current) || rt_task(current))
-+#endif
- slack = 0;
-
- hrtimer_init_sleeper_on_stack(&t, clockid, mode);
-diff -urN linux-5.15.3/kernel/time/posix-cpu-timers.c linux-prjc-v5.15-prjc-r1/kernel/time/posix-cpu-timers.c
---- linux-5.15.3/kernel/time/posix-cpu-timers.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/time/posix-cpu-timers.c 2021-11-20 02:15:12.000000000 +1100
-@@ -216,7 +216,7 @@
- u64 stime, utime;
-
- task_cputime(p, &utime, &stime);
-- store_samples(samples, stime, utime, p->se.sum_exec_runtime);
-+ store_samples(samples, stime, utime, tsk_seruntime(p));
- }
-
- static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
-@@ -859,6 +859,7 @@
- }
- }
-
-+#ifndef CONFIG_SCHED_ALT
- static inline void check_dl_overrun(struct task_struct *tsk)
- {
- if (tsk->dl.dl_overrun) {
-@@ -866,6 +867,7 @@
- __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
- }
- }
-+#endif
-
- static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
- {
-@@ -893,8 +895,10 @@
- u64 samples[CPUCLOCK_MAX];
- unsigned long soft;
-
-+#ifndef CONFIG_SCHED_ALT
- if (dl_task(tsk))
- check_dl_overrun(tsk);
-+#endif
-
- if (expiry_cache_is_inactive(pct))
- return;
-@@ -908,7 +912,7 @@
- soft = task_rlimit(tsk, RLIMIT_RTTIME);
- if (soft != RLIM_INFINITY) {
- /* Task RT timeout is accounted in jiffies. RTTIME is usec */
-- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
-+ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ);
- unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
-
- /* At the hard limit, send SIGKILL. No further action. */
-@@ -1144,8 +1148,10 @@
- return true;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- if (dl_task(tsk) && tsk->dl.dl_overrun)
- return true;
-+#endif
-
- return false;
- }
-diff -urN linux-5.15.3/kernel/trace/trace_selftest.c linux-prjc-v5.15-prjc-r1/kernel/trace/trace_selftest.c
---- linux-5.15.3/kernel/trace/trace_selftest.c 2021-11-19 05:17:21.000000000 +1100
-+++ linux-prjc-v5.15-prjc-r1/kernel/trace/trace_selftest.c 2021-11-20 02:15:12.000000000 +1100
-@@ -1052,10 +1052,15 @@
- {
- /* Make this a -deadline thread */
- static const struct sched_attr attr = {
-+#ifdef CONFIG_SCHED_ALT
-+ /* No deadline on BMQ/PDS, use RR */
-+ .sched_policy = SCHED_RR,
-+#else
- .sched_policy = SCHED_DEADLINE,
- .sched_runtime = 100000ULL,
- .sched_deadline = 10000000ULL,
- .sched_period = 10000000ULL
-+#endif
- };
- struct wakeup_test_data *x = data;
-
diff --git a/system/easy-kernel/0251-projectc-5.15-r1-zv-fix-5.15.28.patch b/system/easy-kernel/0251-projectc-5.15-r1-zv-fix-5.15.28.patch
deleted file mode 100644
index c08d9d0cc..000000000
--- a/system/easy-kernel/0251-projectc-5.15-r1-zv-fix-5.15.28.patch
+++ /dev/null
@@ -1,125 +0,0 @@
-diff -ur a/init/Kconfig b/init/Kconfig
---- a/init/Kconfig 2022-04-20 17:30:09.904751692 -0500
-+++ b/init/Kconfig 2022-04-20 17:32:51.173376197 -0500
-@@ -814,35 +814,6 @@
-
- menu "Scheduler features"
-
--menuconfig SCHED_ALT
-- bool "Alternative CPU Schedulers"
-- default y
-- help
-- This feature enable alternative CPU scheduler"
--
--if SCHED_ALT
--
--choice
-- prompt "Alternative CPU Scheduler"
-- default SCHED_BMQ
--
--config SCHED_BMQ
-- bool "BMQ CPU scheduler"
-- help
-- The BitMap Queue CPU scheduler for excellent interactivity and
-- responsiveness on the desktop and solid scalability on normal
-- hardware and commodity servers.
--
--config SCHED_PDS
-- bool "PDS CPU scheduler"
-- help
-- The Priority and Deadline based Skip list multiple queue CPU
-- Scheduler.
--
--endchoice
--
--endif
--
- config UCLAMP_TASK
- bool "Enable utilization clamping for RT/FAIR tasks"
- depends on CPU_FREQ_GOV_SCHEDUTIL
-@@ -893,6 +864,35 @@
-
- If in doubt, use the default value.
-
-+menuconfig SCHED_ALT
-+ bool "Alternative CPU Schedulers"
-+ default y
-+ help
-+ This feature enable alternative CPU scheduler"
-+
-+if SCHED_ALT
-+
-+choice
-+ prompt "Alternative CPU Scheduler"
-+ default SCHED_BMQ
-+
-+config SCHED_BMQ
-+ bool "BMQ CPU scheduler"
-+ help
-+ The BitMap Queue CPU scheduler for excellent interactivity and
-+ responsiveness on the desktop and solid scalability on normal
-+ hardware and commodity servers.
-+
-+config SCHED_PDS
-+ bool "PDS CPU scheduler"
-+ help
-+ The Priority and Deadline based Skip list multiple queue CPU
-+ Scheduler.
-+
-+endchoice
-+
-+endif
-+
- endmenu
-
- #
-diff -ur a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
---- a/kernel/sched/alt_core.c 2022-04-20 17:30:09.908751806 -0500
-+++ b/kernel/sched/alt_core.c 2022-04-20 17:32:51.169376082 -0500
-@@ -2954,7 +2954,7 @@
- return 0;
- }
-
--void sched_post_fork(struct task_struct *p, struct kernel_clone_args *kargs)
-+void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs)
- {
- unsigned long flags;
- struct rq *rq;
-@@ -2997,6 +2997,13 @@
- raw_spin_unlock_irqrestore(&p->pi_lock, flags);
- }
-
-+void sched_post_fork(struct task_struct *p)
-+{
-+#ifdef CONFIG_UCLAMP_TASK
-+ uclamp_post_fork(p);
-+#endif
-+}
-+
- #ifdef CONFIG_SCHEDSTATS
-
- DEFINE_STATIC_KEY_FALSE(sched_schedstats);
-diff -ur a/kernel/sched/alt_sched.h b/kernel/sched/alt_sched.h
---- a/kernel/sched/alt_sched.h 2022-04-20 17:30:09.908751806 -0500
-+++ b/kernel/sched/alt_sched.h 2022-04-20 17:32:51.173376197 -0500
-@@ -653,6 +653,20 @@
- }
- #endif
-
-+static inline
-+unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long boost,
-+ struct task_struct *p)
-+{
-+ return boost;
-+}
-+
-+static inline bool uclamp_rq_is_capped(struct rq *rq) { return false; }
-+
-+static inline bool uclamp_is_used(void)
-+{
-+ return false;
-+}
-+
- extern void swake_up_all_locked(struct swait_queue_head *q);
- extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
-
diff --git a/system/easy-kernel/0500-print-fw-info.patch b/system/easy-kernel/0500-print-fw-info.patch
index a630cfbea..ba8c60930 100644
--- a/system/easy-kernel/0500-print-fw-info.patch
+++ b/system/easy-kernel/0500-print-fw-info.patch
@@ -1,13 +1,11 @@
--- a/drivers/base/firmware_loader/main.c 2021-08-24 15:42:07.025482085 -0400
+++ b/drivers/base/firmware_loader/main.c 2021-08-24 15:44:40.782975313 -0400
-@@ -809,6 +809,11 @@ _request_firmware(const struct firmware
+@@ -809,6 +809,9 @@ _request_firmware(const struct firmware
ret = _request_firmware_prepare(&fw, name, device, buf, size,
offset, opt_flags);
+
-+#ifdef CONFIG_GENTOO_PRINT_FIRMWARE_INFO
-+ printk(KERN_NOTICE "Loading firmware: %s\n", name);
-+#endif
++ printk(KERN_NOTICE "Loading firmware: %s\n", name);
+
if (ret <= 0) /* error or already assigned */
goto out;
diff --git a/system/easy-kernel/1000-version.patch b/system/easy-kernel/1000-version.patch
index 4ac6ecdca..d2ea9f86f 100644
--- a/system/easy-kernel/1000-version.patch
+++ b/system/easy-kernel/1000-version.patch
@@ -4,10 +4,10 @@ diff -Naur linux-5.15-stock/Makefile linux-5.15-branded/Makefile
@@ -2,8 +2,8 @@
VERSION = 5
PATCHLEVEL = 15
- SUBLEVEL = 28
+ SUBLEVEL = 44
-EXTRAVERSION =
-NAME = Trick or Treat
-+EXTRAVERSION = -mc1
++EXTRAVERSION = -mc2
+NAME = Ponder the Icosahedron
# *DOCUMENTATION*
diff --git a/system/easy-kernel/APKBUILD b/system/easy-kernel/APKBUILD
index d0a153ef1..ba9feadc2 100644
--- a/system/easy-kernel/APKBUILD
+++ b/system/easy-kernel/APKBUILD
@@ -2,10 +2,10 @@
# Maintainer: Adelie Platform Group <adelie-devel@lists.adelielinux.org>
# KEEP THIS IN SYNC with the other easy-kernel packages.
_kflavour=""
-_patchver=1 # must match 1000-version.patch ???
+_patchver=2 # must match 1000-version.patch
_pkgname=easy-kernel$_kflavour
-pkgver=5.15.28
-pkgrel=1
+pkgver=5.15.44
+pkgrel=0
pkgname=$_pkgname-$pkgver-mc$_patchver
pkgdesc="The Linux kernel, packaged for your convenience"
url="https://kernel.org/"
@@ -32,15 +32,12 @@ source="https://cdn.kernel.org/pub/linux/kernel/v${_pkgmajver}.x/linux-${_pkgmin
config-x86_64
kernel.h
- 0100-linux-5.15.28.patch
+ 0100-linux.5.15.44.patch
0120-XATTR_USER_PREFIX.patch
0122-link-security-restrictions.patch
0124-bluetooth-keysize-check.patch
0126-sign-file-libressl.patch
- 0130-lrng.patch
0200-x86-compile.patch
- 0250-projectc-5.15-r1.patch
- 0251-projectc-5.15-r1-zv-fix-5.15.28.patch
0255-ultra-ksm.patch
0260-reduce-swappiness.patch
0300-tmp513-regression-fix.patch
@@ -166,21 +163,18 @@ c6b7f7cb0c6a155465b2db849187a95ff1a31dd157699019a3f3f44e522c62c6e6ec29532b1b1b0c
e0c859b385140a390ef696a6c26ff28843282d0a0d57cabb50b0d8da66bbb17c37ee5733010d57bd58c6eac5f4e1eb4accf33216d8638115d376f0a431803f78 config-sparc64
d02dad2531c13ccb8dc9b0bdb31943ba12b374f559b6c0ffaac7cf7d3b809e35b83df705758ce1ea223611ffe6f399295a06286e6ad9033ae8b861ad4933f049 config-x86_64
1ca1bc094a8106b33176ab6cfb55c9514e7d69f1ed30c580eee419a3c422a2e6625d71c4581702e911f36c4bbac175010f46b7123bb81fda3303d4decdc57287 kernel.h
-aa22c4a18ae302356010cac4f375feeb9ce1b6a13eeb7a5c98b3c2bebee7249154cfb747aa138440b60bc1b62a4329bd08c151e55cd318c788a267ef51cbb752 0100-linux-5.15.28.patch
+59c34a15a469977ea167f5dc5c02b45cc9dc7ffe2a1f2b87ec756ec8776e111d0542d0ea8ea1ace2106debe7fd6bb2d29f49f8f1b496ce905e6f310f0d4dc5e0 0100-linux.5.15.44.patch
3ed100909f9aed72836a3c712e45e0116cd3c4331961a76a27b867a7098d0df9458387b656c9ea01385c3c37585436e48168ac35666b0e46dca7da05e5e38a61 0120-XATTR_USER_PREFIX.patch
c97a3799a2d5e4da9c9dfe129756da629fba8183479b02ca82f9b6d9993f17a165a96bd35ac50eb25fb293785b9b529a95165b1a2eb79c05134bee8ccf22a5d3 0122-link-security-restrictions.patch
dc47b18749d95a456f8bc47fd6a0618c286b646b38466c3d950dfbeb25adf3fc1a794e95552e4da1abb58e49f0bd841f7222e71c4d04cb0264ca23476ca9caef 0124-bluetooth-keysize-check.patch
79eaf814d76402a445efc961666a7c7c74207e552b0cb32d93d5cb828da580f7dbe93509dc9f53321c7844663205a8dce4e518ba047e4c57fc55f5c3498088ec 0126-sign-file-libressl.patch
-27b0a76966f5ea36217a1686e9504e5cf34a319d7036f856c94ddc22f5e737b3c49bf8cc50508c20f476c4b24607eba194305d7073c50faad00046b0d72350a1 0130-lrng.patch
16b8b8333fe89a68bc7f9a49b1bae263ab830692c12981640ac3dd9a0fb687f90b53783be05d47e5b38759ace4d99e82b59edd537a85a7ee27e21e65bbfa40a6 0200-x86-compile.patch
-3cc9156e321f6b20d8adcc7c3baeb27f1f4b2d91b514b241244b93ea69b5b54e2055fe0365f25db17033bdae38dddbb029378b40032992fda6534004893a1b31 0250-projectc-5.15-r1.patch
-d1fb1981173e775c8c76f64957984c64d17b8a0d25185e7ab9e6731735b2cec976513011efb90aceb0bcd5dda27987d6f45c6736f5568fe9932ef19088c077be 0251-projectc-5.15-r1-zv-fix-5.15.28.patch
4c901fe38e197b0397702ec46329fac6cdd5b7ff6e2601f76f0cbabcf452581936c58028c3a93471782541ad3045b10d1030fad4b25121f35d091495d17fd308 0255-ultra-ksm.patch
5f74e6a72876d3cf3b3188a43b999b981b6ea0ca401ad72b3c7d5cc65bf505f50e7ee17d435ec95b7a012dc92e6540aea1bdb501f48690c242705c47d2403513 0260-reduce-swappiness.patch
4e637935c2f37cc18f347293e3c94b18f90e2caccca726304a95c4891257a5b2bb3093aee7a97571038b29c0c987cc60a9a80aefd0d4c9a063b33d102f03579e 0300-tmp513-regression-fix.patch
-a43fd7004715f4efd545fe27abad46cc6f8c4c5f3ba9ab27c74a004e74bd5e4106beaecd54ca785fee03a0b466021acfdba0afa07e9ee2965493334a24403ffc 0500-print-fw-info.patch
+8ddac562bd16fd96aea4b5165cf4a93eaee49011805c5d648913cea6865a1415c61aed5a34bfc319e4cd394dbaebad1360a6e07dab6e02b6b425a0e414107984 0500-print-fw-info.patch
f0e532539e93d19fc65b417b4a0663e3757823340b968f63bd3a2665f99524feebb843ecf88ccf6909f93a8e7e9290721677c8f43bc3a2a37d99a51c1281a469 0502-gcc9-kcflags.patch
-dbf38da48cd5ddf287201c5537019e80a50ff5cef497c474324c634e140dc0106c394c5166747010914b11fc462e508a4ddda9b5b103de1f9a1d995fc9aafa4e 1000-version.patch
+9763a7d100dc1abb33ab57d6e96be20d99f49c03bb926592e0b01318b066ad232ae6cf1fd6e6a4f15cfbdc4593c8b0f0a8d9ea49eaf6643dfbe9b3eadad3a344 1000-version.patch
03a73db9eda84a52315499cb511f730946939d2de1b3aa52c60f9bd3a364377a65ddf2b62f505689a84d3e2f0fc7da5ca90429629d93d9909360ee0c3c599bbe no-require-gnu-tar.patch
aadf8a3cc46a08e3a396ebd45656aee235103db7a2155cc6980df20b750151a9938b8b73c9319c6cd1b5f8aba6ce707f857a47dabf69df8d91dd93d440cffcb5 no-require-lilo.patch
7bb07eb22002cc48caf0cd55d17ce4097aa583e0ca4048c11c92e1519761b2ae982ffe98311543d4b0dfc991c8bc411b2e1c7be9488b6c6f19ffaa08e69e2f47 no-autoload-fb.conf