From f3dd19f890ae1163e4183d01285343e118fc96ab Mon Sep 17 00:00:00 2001 From: Werner Date: Sun, 20 Jun 2021 10:05:49 +0200 Subject: [PATCH] Bump Zero2 (H616) (#2907) * Update sun50iw6.conf * Extract patches from private kernel branch, remove 5.10, cleanup Co-authored-by: Igor Pecovnik --- config/boards/orangepizero2.wip | 2 +- config/kernel/linux-sunxi64-edge.config | 7 +- config/sources/families/sun50iw6.conf | 6 +- config/targets.conf | 4 +- ...axp20x-Add-AXP305-compatible-plus-op.patch | 46 + ...-AXP-806-chips-without-interrupt-lin.patch | 70 + ...inner-Add-Allwinner-H616-.dtsi-file.patch} | 285 +- ...sunxi-Add-two-H616-board-compatible-.patch | 41 + ...er-h616-Add-OrangePi-Zero-2-board-s.patch} | 130 +- ...ner-h616-Add-X96-Mate-TV-box-support.patch | 230 + ...sunxi-musb-Add-H616-compatible-strin.patch | 32 + ...dings-usb-Add-H616-compatible-string.patch | 35 + ...ework-HCI-PHY-aka.-pmu_unk1-handling.patch | 164 + ...4i-usb-Allow-reset-line-to-be-shared.patch | 36 + ...un4i-usb-Introduce-port2-SIDDQ-quirk.patch | 117 + ...usb-Add-support-for-the-H616-USB-PHY.patch | 51 + ...m64-dts-allwinner-h616-Add-USB-nodes.patch | 190 + ...ner-h616-OrangePi-Zero-2-Add-USB-nod.patch | 85 + ...llwinner-h616-X96-Mate-Add-USB-nodes.patch | 66 + ...sun8i-emac-Add-H616-compatible-strin.patch | 36 + ...-sun8i-Prepare-for-second-EMAC-clock.patch | 65 + ...rtc-sun6i-Add-H616-compatible-string.patch | 52 + ...i-Add-support-for-linear-day-storage.patch | 146 + ...pport-for-broken-down-alarm-register.patch | 112 + ...pport-for-RTCs-without-external-LOSC.patch | 67 + ...rtc-sun6i-Add-Allwinner-H616-support.patch | 55 + ...inner-h616-Add-RTC-and-its-32K-clock.patch | 93 + .../h616_999_fix-broken-hunks.patch | 24 - .../archive/sunxi-5.12/patch-5.12.9-10.patch | 6796 ----------------- 29 files changed, 1956 insertions(+), 7087 deletions(-) create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0001-dt-bindings-mfd-axp20x-Add-AXP305-compatible-plus-op.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0002-mfd-axp20x-Allow-AXP-806-chips-without-interrupt-lin.patch rename patch/kernel/archive/sunxi-5.12/{h616_007_Add-Allwinner-H616-.dtsi-file.patch => h616_0003-arm64-dts-allwinner-Add-Allwinner-H616-.dtsi-file.patch} (70%) create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0004-dt-bindings-arm-sunxi-Add-two-H616-board-compatible-.patch rename patch/kernel/archive/sunxi-5.12/{h616_008_Add-OrangePi-Zero-2-.dts.patch => h616_0005-arm64-dts-allwinner-h616-Add-OrangePi-Zero-2-board-s.patch} (68%) create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0006-arm64-dts-allwinner-h616-Add-X96-Mate-TV-box-support.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0007-dt-bindings-usb-sunxi-musb-Add-H616-compatible-strin.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0008-dt-bindings-usb-Add-H616-compatible-string.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0009-phy-sun4i-usb-Rework-HCI-PHY-aka.-pmu_unk1-handling.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0010-phy-sun4i-usb-Allow-reset-line-to-be-shared.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0011-phy-sun4i-usb-Introduce-port2-SIDDQ-quirk.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0012-phy-sun4i-usb-Add-support-for-the-H616-USB-PHY.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0013-arm64-dts-allwinner-h616-Add-USB-nodes.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0014-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0015-arm64-dts-allwinner-h616-X96-Mate-Add-USB-nodes.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0016-dt-bindings-net-sun8i-emac-Add-H616-compatible-strin.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0017-net-stmmac-dwmac-sun8i-Prepare-for-second-EMAC-clock.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0018-dt-bindings-rtc-sun6i-Add-H616-compatible-string.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0019-rtc-sun6i-Add-support-for-linear-day-storage.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0020-rtc-sun6i-Add-support-for-broken-down-alarm-register.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0021-rtc-sun6i-Add-support-for-RTCs-without-external-LOSC.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0022-rtc-sun6i-Add-Allwinner-H616-support.patch create mode 100644 patch/kernel/archive/sunxi-5.12/h616_0023-arm64-dts-allwinner-h616-Add-RTC-and-its-32K-clock.patch delete mode 100644 patch/kernel/archive/sunxi-5.12/h616_999_fix-broken-hunks.patch delete mode 100644 patch/kernel/archive/sunxi-5.12/patch-5.12.9-10.patch diff --git a/config/boards/orangepizero2.wip b/config/boards/orangepizero2.wip index fd47847d15..f836b15316 100644 --- a/config/boards/orangepizero2.wip +++ b/config/boards/orangepizero2.wip @@ -6,4 +6,4 @@ MODULES_BLACKLIST="lima" DEFAULT_CONSOLE="serial" BUILD_DESKTOP="no" SERIALCON="ttyS0" -KERNEL_TARGET="current,edge" +KERNEL_TARGET="edge" diff --git a/config/kernel/linux-sunxi64-edge.config b/config/kernel/linux-sunxi64-edge.config index f65bebd031..3dc99f07a5 100644 --- a/config/kernel/linux-sunxi64-edge.config +++ b/config/kernel/linux-sunxi64-edge.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 5.12.8 Kernel Configuration +# Linux/arm64 5.12.12 Kernel Configuration # CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0" CONFIG_CC_IS_GCC=y @@ -2067,7 +2067,12 @@ CONFIG_BLK_DEV_RBD=m # # NVME Support # +CONFIG_NVME_CORE=m +# CONFIG_NVME_MULTIPATH is not set +# CONFIG_NVME_HWMON is not set +CONFIG_NVME_FABRICS=m # CONFIG_NVME_FC is not set +CONFIG_NVME_TCP=m # CONFIG_NVME_TARGET is not set # end of NVME Support diff --git a/config/sources/families/sun50iw6.conf b/config/sources/families/sun50iw6.conf index 0862996d13..abd559ac1d 100644 --- a/config/sources/families/sun50iw6.conf +++ b/config/sources/families/sun50iw6.conf @@ -8,14 +8,10 @@ ASOUND_STATE='asound.state.sun50iw2-dev' if [[ $BOARD == orangepizero2 ]]; then - ATFSOURCE='https://github.com/apritzel/arm-trusted-firmware' - ATFBRANCH='branch:h616-beta' - ATF_PLAT="sun50i_h616"; ATF_TARGET_MAP='PLAT=sun50i_h616 DEBUG=1 bl31;;build/sun50i_h616/debug/bl31.bin' - BOOTSOURCE='https://github.com/jernejsk/u-boot' - BOOTBRANCH='branch:h616-v2' + BOOTBRANCH='branch:master' [[ -z $CPUMAX ]] && CPUMAX=1512000 diff --git a/config/targets.conf b/config/targets.conf index 8251b5c55e..88fe7260a4 100644 --- a/config/targets.conf +++ b/config/targets.conf @@ -555,8 +555,8 @@ orangepizero edge hirsute cli stable # orangepizero2 -orangepizero2 current buster cli stable yes -orangepizero2 current focal cli stable yes +orangepizero2 edge buster cli stable yes +orangepizero2 edge focal cli stable yes orangepizero2 edge hirsute cli stable yes diff --git a/patch/kernel/archive/sunxi-5.12/h616_0001-dt-bindings-mfd-axp20x-Add-AXP305-compatible-plus-op.patch b/patch/kernel/archive/sunxi-5.12/h616_0001-dt-bindings-mfd-axp20x-Add-AXP305-compatible-plus-op.patch new file mode 100644 index 0000000000..bc31194ca7 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0001-dt-bindings-mfd-axp20x-Add-AXP305-compatible-plus-op.patch @@ -0,0 +1,46 @@ +From 3a19442450cc2a248b6591f538527b4abb19065f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Thu, 21 Jan 2021 17:01:44 +0000 +Subject: [PATCH 01/23] dt-bindings: mfd: axp20x: Add AXP305 compatible (plus + optional IRQ) + +The AXP305 PMIC used on many boards with the H616 SoC seems to be fully +compatible to the AXP805 PMIC, so add the proper chain of compatible +strings. + +Also at least on one board (Orangepi Zero2) there is no interrupt line +connected to the CPU, so make the "interrupts" property optional. + +Signed-off-by: Andre Przywara +Acked-by: Rob Herring +--- + Documentation/devicetree/bindings/mfd/axp20x.txt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt +index 4991a6415796..2b53dcc0ea61 100644 +--- a/Documentation/devicetree/bindings/mfd/axp20x.txt ++++ b/Documentation/devicetree/bindings/mfd/axp20x.txt +@@ -26,10 +26,10 @@ Required properties: + * "x-powers,axp803" + * "x-powers,axp806" + * "x-powers,axp805", "x-powers,axp806" ++ * "x-powers,axp305", "x-powers,axp805", "x-powers,axp806" + * "x-powers,axp809" + * "x-powers,axp813" + - reg: The I2C slave address or RSB hardware address for the AXP chip +-- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin + - interrupt-controller: The PMIC has its own internal IRQs + - #interrupt-cells: Should be set to 1 + +@@ -43,6 +43,7 @@ more information: + AXP20x/LDO3: software-based implementation + + Optional properties: ++- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin + - x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz + AXP152/20X: range: 750-1875, Default: 1.5 MHz + AXP22X/8XX: range: 1800-4050, Default: 3 MHz +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0002-mfd-axp20x-Allow-AXP-806-chips-without-interrupt-lin.patch b/patch/kernel/archive/sunxi-5.12/h616_0002-mfd-axp20x-Allow-AXP-806-chips-without-interrupt-lin.patch new file mode 100644 index 0000000000..1ffa2dbefd --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0002-mfd-axp20x-Allow-AXP-806-chips-without-interrupt-lin.patch @@ -0,0 +1,70 @@ +From 106e37f49174a6269bcd4869105e1c23b1a01b14 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 7 Dec 2020 12:30:21 +0000 +Subject: [PATCH 02/23] mfd: axp20x: Allow AXP 806 chips without interrupt + lines + +Currently the AXP chip requires to have its IRQ line connected to some +interrupt controller, and will fail probing when this is not the case. + +On a new Allwinner SoC (H616) there is no NMI pin anymore, and at +least one board does not connect the AXP's IRQ pin to anything else, +so the interrupt functionality of the AXP chip is simply not available. + +Check whether the interrupt line number returned by the platform code is +valid, before trying to register the irqchip. If not, we skip this +registration, to avoid the driver to bail out completely. +Also we need to skip the power key functionality, as this relies on +a valid IRQ as well. + +Signed-off-by: Andre Przywara +--- + drivers/mfd/axp20x.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 3eae04e24ac8..4145a38b3890 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -884,8 +884,13 @@ int axp20x_match_device(struct axp20x_dev *axp20x) + axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; + break; + case AXP806_ID: ++ /* ++ * Don't register the power key part if in slave mode or ++ * if there is no interrupt line. ++ */ + if (of_property_read_bool(axp20x->dev->of_node, +- "x-powers,self-working-mode")) { ++ "x-powers,self-working-mode") && ++ axp20x->irq > 0) { + axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells); + axp20x->cells = axp806_self_working_cells; + } else { +@@ -959,12 +964,17 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) + AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE); + } + +- ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, +- IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags, +- -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc); +- if (ret) { +- dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret); +- return ret; ++ /* Only if there is an interrupt line connected towards the CPU. */ ++ if (axp20x->irq > 0) { ++ ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, ++ IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags, ++ -1, axp20x->regmap_irq_chip, ++ &axp20x->regmap_irqc); ++ if (ret) { ++ dev_err(axp20x->dev, "failed to add irq chip: %d\n", ++ ret); ++ return ret; ++ } + } + + ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_007_Add-Allwinner-H616-.dtsi-file.patch b/patch/kernel/archive/sunxi-5.12/h616_0003-arm64-dts-allwinner-Add-Allwinner-H616-.dtsi-file.patch similarity index 70% rename from patch/kernel/archive/sunxi-5.12/h616_007_Add-Allwinner-H616-.dtsi-file.patch rename to patch/kernel/archive/sunxi-5.12/h616_0003-arm64-dts-allwinner-Add-Allwinner-H616-.dtsi-file.patch index 32bf647160..3e6ca22cab 100644 --- a/patch/kernel/archive/sunxi-5.12/h616_007_Add-Allwinner-H616-.dtsi-file.patch +++ b/patch/kernel/archive/sunxi-5.12/h616_0003-arm64-dts-allwinner-Add-Allwinner-H616-.dtsi-file.patch @@ -1,9 +1,31 @@ +From d0a7d8cdefba02230e0fb1f97cb0c1210e7a077a Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 27 Nov 2020 15:28:12 +0000 +Subject: [PATCH 03/23] arm64: dts: allwinner: Add Allwinner H616 .dtsi file + +This (relatively) new SoC is similar to the H6, but drops the (broken) +PCIe support and the USB 3.0 controller. It also gets the management +controller removed, which in turn removes *some*, but not all of the +devices formerly dedicated to the ARISC (CPUS). +And while there is still the extra sunxi interrupt controller, the +package lacks the corresponding NMI pin, so no interrupts for the PMIC. + +The reserved memory node is actually handled by Trusted Firmware now, +but U-Boot fails to propagate this to a separately loaded DTB, so we +keep it in here for now, until U-Boot learns to do this properly. + +Signed-off-by: Andre Przywara +--- + .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 570 ++++++++++++++++++ + 1 file changed, 570 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi + diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi new file mode 100644 -index 000000000000..dcffbfdcd26b +index 000000000000..0ad0c25b4c83 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi -@@ -0,0 +1,704 @@ +@@ -0,0 +1,570 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2020 Arm Ltd. +// based on the H6 dtsi, which is: @@ -69,13 +91,20 @@ index 000000000000..dcffbfdcd26b + }; + }; + -+ osc24M: osc24M_clk { ++ osc24M: osc24M-clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + ++ osc32k_int: osc32k-int { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "osc32k-int"; ++ }; ++ + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = , @@ -110,8 +139,7 @@ index 000000000000..dcffbfdcd26b + ranges = <0x0 0x0 0x0 0x40000000>; + + syscon: syscon@3000000 { -+ compatible = "allwinner,sun50i-h616-system-control", -+ "allwinner,sun50i-a64-system-control"; ++ compatible = "allwinner,sun50i-h616-system-control"; + reg = <0x03000000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; @@ -124,26 +152,12 @@ index 000000000000..dcffbfdcd26b + #size-cells = <1>; + ranges = <0 0x00028000 0x30000>; + }; -+ -+ sram_c1: sram@1a00000 { -+ compatible = "mmio-sram"; -+ reg = <0x01a00000 0x200000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0x01a00000 0x200000>; -+ -+ ve_sram: sram-section@0 { -+ compatible = "allwinner,sun50i-h616-sram-c1", -+ "allwinner,sun4i-a10-sram-c1"; -+ reg = <0x000000 0x200000>; -+ }; -+ }; + }; + + ccu: clock@3001000 { + compatible = "allwinner,sun50i-h616-ccu"; + reg = <0x03001000 0x1000>; -+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>; ++ clocks = <&osc24M>, <&osc32k_int>, <&osc32k_int>; + clock-names = "hosc", "losc", "iosc"; + #clock-cells = <1>; + #reset-cells = <1>; @@ -155,18 +169,21 @@ index 000000000000..dcffbfdcd26b + reg = <0x030090a0 0x20>; + interrupts = ; + clocks = <&osc24M>; -+ status = "disabled"; ++ status = "okay"; + }; + + pio: pinctrl@300b000 { + compatible = "allwinner,sun50i-h616-pinctrl"; + reg = <0x0300b000 0x400>; -+ interrupts = , ++ interrupts = , ++ , ++ , ++ , + , + , + , + ; -+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>; ++ clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k_int>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; @@ -187,12 +204,12 @@ index 000000000000..dcffbfdcd26b + function = "i2c0"; + }; + -+ i2c3_pins_a: i2c1-pins-a { ++ i2c3_ph_pins: i2c3-ph-pins { + pins = "PH4", "PH5"; + function = "i2c3"; + }; + -+ ir_rx_pin: ir_rx_pin { ++ ir_rx_pin: ir-rx-pin { + pins = "PH10"; + function = "ir_rx"; + }; @@ -276,6 +293,11 @@ index 000000000000..dcffbfdcd26b + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + status = "disabled"; ++ max-frequency = <150000000>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ mmc-ddr-3_3v; ++ cap-sdio-irq; + #address-cells = <1>; + #size-cells = <0>; + }; @@ -292,13 +314,18 @@ index 000000000000..dcffbfdcd26b + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + status = "disabled"; ++ max-frequency = <150000000>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ mmc-ddr-3_3v; ++ cap-sdio-irq; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc2: mmc@4022000 { + compatible = "allwinner,sun50i-h616-emmc", -+ "allwinner,sun50i-a64-emmc"; ++ "allwinner,sun50i-a100-emmc"; + reg = <0x04022000 0x1000>; + clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>; + clock-names = "ahb", "mmc"; @@ -308,6 +335,11 @@ index 000000000000..dcffbfdcd26b + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + status = "disabled"; ++ max-frequency = <150000000>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ mmc-ddr-3_3v; ++ cap-sdio-irq; + #address-cells = <1>; + #size-cells = <0>; + }; @@ -483,181 +515,17 @@ index 000000000000..dcffbfdcd26b + clock-names = "stmmaceth"; + status = "disabled"; + -+ mdio: mdio { ++ mdio0: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + -+ usbotg: usb@5100000 { -+ compatible = "allwinner,sun50i-h616-musb", -+ "allwinner,sun8i-a33-musb"; -+ reg = <0x05100000 0x0400>; -+ clocks = <&ccu CLK_BUS_OTG>; -+ resets = <&ccu RST_BUS_OTG>; -+ interrupts = ; -+ interrupt-names = "mc"; -+ phys = <&usbphy 0>; -+ phy-names = "usb"; -+ extcon = <&usbphy 0>; -+ status = "disabled"; -+ }; -+ -+ usbphy: phy@5100400 { -+ compatible = "allwinner,sun50i-h616-usb-phy"; -+ reg = <0x05100400 0x24>, -+ <0x05101800 0x4>, -+ <0x05200800 0x4>, -+ <0x05310800 0x4>, -+ <0x05311800 0x4>; -+ reg-names = "phy_ctrl", -+ "pmu0", -+ "pmu1", -+ "pmu2", -+ "pmu3"; -+ clocks = <&ccu CLK_USB_PHY0>, -+ <&ccu CLK_USB_PHY1>, -+ <&ccu CLK_USB_PHY2>, -+ <&ccu CLK_USB_PHY3>; -+ clock-names = "usb0_phy", -+ "usb1_phy", -+ "usb2_phy", -+ "usb3_phy"; -+ resets = <&ccu RST_USB_PHY0>, -+ <&ccu RST_USB_PHY1>, -+ <&ccu RST_USB_PHY2>, -+ <&ccu RST_USB_PHY3>; -+ reset-names = "usb0_reset", -+ "usb1_reset", -+ "usb2_reset", -+ "usb3_reset"; -+ status = "disabled"; -+ #phy-cells = <1>; -+ }; -+ -+ ehci0: usb@5101000 { -+ compatible = "allwinner,sun50i-h616-ehci", -+ "generic-ehci"; -+ reg = <0x05101000 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI0>, -+ <&ccu CLK_BUS_EHCI0>, -+ <&ccu CLK_USB_OHCI0>; -+ resets = <&ccu RST_BUS_OHCI0>, -+ <&ccu RST_BUS_EHCI0>; -+ status = "disabled"; -+ }; -+ -+ ohci0: usb@5101400 { -+ compatible = "allwinner,sun50i-h616-ohci", -+ "generic-ohci"; -+ reg = <0x05101400 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI0>, -+ <&ccu CLK_USB_OHCI0>; -+ resets = <&ccu RST_BUS_OHCI0>; -+ status = "disabled"; -+ }; -+ -+ ehci1: usb@5200000 { -+ compatible = "allwinner,sun50i-h616-ehci", -+ "generic-ehci"; -+ reg = <0x05200000 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI1>, -+ <&ccu CLK_BUS_EHCI1>, -+ <&ccu CLK_USB_OHCI1>; -+ resets = <&ccu RST_BUS_OHCI1>, -+ <&ccu RST_BUS_EHCI1>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ohci1: usb@5200400 { -+ compatible = "allwinner,sun50i-h616-ohci", -+ "generic-ohci"; -+ reg = <0x05200400 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI1>, -+ <&ccu CLK_USB_OHCI1>; -+ resets = <&ccu RST_BUS_OHCI1>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ehci2: usb@5310000 { -+ compatible = "allwinner,sun50i-h616-ehci", -+ "generic-ehci"; -+ reg = <0x05310000 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI2>, -+ <&ccu CLK_BUS_EHCI2>, -+ <&ccu CLK_USB_OHCI2>; -+ resets = <&ccu RST_BUS_OHCI2>, -+ <&ccu RST_BUS_EHCI2>; -+ phys = <&usbphy 2>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ohci2: usb@5310400 { -+ compatible = "allwinner,sun50i-h616-ohci", -+ "generic-ohci"; -+ reg = <0x05310400 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI2>, -+ <&ccu CLK_USB_OHCI2>; -+ resets = <&ccu RST_BUS_OHCI2>; -+ phys = <&usbphy 2>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ehci3: usb@5311000 { -+ compatible = "allwinner,sun50i-h616-ehci", -+ "generic-ehci"; -+ reg = <0x05311000 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI3>, -+ <&ccu CLK_BUS_EHCI3>, -+ <&ccu CLK_USB_OHCI3>; -+ resets = <&ccu RST_BUS_OHCI3>, -+ <&ccu RST_BUS_EHCI3>; -+ phys = <&usbphy 3>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ohci3: usb@5311400 { -+ compatible = "allwinner,sun50i-h616-ohci", -+ "generic-ohci"; -+ reg = <0x05311400 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI3>, -+ <&ccu CLK_USB_OHCI3>; -+ resets = <&ccu RST_BUS_OHCI3>; -+ phys = <&usbphy 3>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ rtc: rtc@7000000 { -+ compatible = "allwinner,sun50i-h616-rtc", -+ "allwinner,sun50i-h6-rtc"; -+ reg = <0x07000000 0x400>; -+ interrupts = , -+ ; -+ clock-output-names = "osc32k", "osc32k-out", "iosc"; -+ #clock-cells = <1>; -+ }; -+ + r_ccu: clock@7010000 { + compatible = "allwinner,sun50i-h616-r-ccu"; -+ reg = <0x07010000 0x400>; -+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, ++ reg = <0x07010000 0x210>; ++ clocks = <&osc24M>, <&osc32k_int>, <&osc32k_int>, + <&ccu CLK_PLL_PERIPH0>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; + #clock-cells = <1>; @@ -668,7 +536,7 @@ index 000000000000..dcffbfdcd26b + compatible = "allwinner,sun50i-h616-r-pinctrl"; + reg = <0x07022000 0x400>; + interrupts = ; -+ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>; ++ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k_int>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; @@ -679,6 +547,11 @@ index 000000000000..dcffbfdcd26b + pins = "PL0", "PL1"; + function = "s_i2c"; + }; ++ ++ r_rsb_pins: r-rsb-pins { ++ pins = "PL0", "PL1"; ++ function = "s_rsb"; ++ }; + }; + + ir: ir@7040000 { @@ -686,10 +559,10 @@ index 000000000000..dcffbfdcd26b + "allwinner,sun6i-a31-ir"; + reg = <0x07040000 0x400>; + interrupts = ; -+ clocks = <&ccu CLK_R_APB1_IR>, -+ <&ccu CLK_IR>; ++ clocks = <&r_ccu CLK_R_APB1_IR>, ++ <&r_ccu CLK_IR>; + clock-names = "apb", "ir"; -+ resets = <&ccu RST_R_APB1_IR>; ++ resets = <&r_ccu RST_R_APB1_IR>; + pinctrl-names = "default"; + pinctrl-0 = <&ir_rx_pin>; + status = "disabled"; @@ -706,5 +579,23 @@ index 000000000000..dcffbfdcd26b + #address-cells = <1>; + #size-cells = <0>; + }; ++ ++ r_rsb: rsb@7083000 { ++ compatible = "allwinner,sun50i-h616-rsb", ++ "allwinner,sun8i-a23-rsb"; ++ reg = <0x07083000 0x400>; ++ interrupts = ; ++ clocks = <&r_ccu CLK_R_APB2_RSB>; ++ clock-frequency = <3000000>; ++ resets = <&r_ccu RST_R_APB2_RSB>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&r_rsb_pins>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; + }; +}; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0004-dt-bindings-arm-sunxi-Add-two-H616-board-compatible-.patch b/patch/kernel/archive/sunxi-5.12/h616_0004-dt-bindings-arm-sunxi-Add-two-H616-board-compatible-.patch new file mode 100644 index 0000000000..a9b62fb3c9 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0004-dt-bindings-arm-sunxi-Add-two-H616-board-compatible-.patch @@ -0,0 +1,41 @@ +From 9c292a40cfeaa1adedc893c468d4a772619e9b9f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 7 Dec 2020 21:35:46 +0000 +Subject: [PATCH 04/23] dt-bindings: arm: sunxi: Add two H616 board compatible + strings + +Signed-off-by: Andre Przywara +Acked-by: Rob Herring +--- + Documentation/devicetree/bindings/arm/sunxi.yaml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml +index ac750025a2eb..0b20d2260d0b 100644 +--- a/Documentation/devicetree/bindings/arm/sunxi.yaml ++++ b/Documentation/devicetree/bindings/arm/sunxi.yaml +@@ -837,6 +837,11 @@ properties: + - const: yones-toptech,bs1078-v2 + - const: allwinner,sun6i-a31s + ++ - description: X96 Mate TV box ++ items: ++ - const: hechuang,x96-mate ++ - const: allwinner,sun50i-h616 ++ + - description: Xunlong OrangePi + items: + - const: xunlong,orangepi +@@ -937,4 +942,9 @@ properties: + - const: xunlong,orangepi-zero-plus2-h3 + - const: allwinner,sun8i-h3 + ++ - description: Xunlong OrangePi Zero 2 ++ items: ++ - const: xunlong,orangepi-zero2 ++ - const: allwinner,sun50i-h616 ++ + additionalProperties: true +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_008_Add-OrangePi-Zero-2-.dts.patch b/patch/kernel/archive/sunxi-5.12/h616_0005-arm64-dts-allwinner-h616-Add-OrangePi-Zero-2-board-s.patch similarity index 68% rename from patch/kernel/archive/sunxi-5.12/h616_008_Add-OrangePi-Zero-2-.dts.patch rename to patch/kernel/archive/sunxi-5.12/h616_0005-arm64-dts-allwinner-h616-Add-OrangePi-Zero-2-board-s.patch index 1a6eb8e0c8..f9739661af 100644 --- a/patch/kernel/archive/sunxi-5.12/h616_008_Add-OrangePi-Zero-2-.dts.patch +++ b/patch/kernel/archive/sunxi-5.12/h616_0005-arm64-dts-allwinner-h616-Add-OrangePi-Zero-2-board-s.patch @@ -1,21 +1,51 @@ +From 9aa444ccb4c21267dc5d6ddb576342cc63f5d06c Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 27 Nov 2020 15:28:40 +0000 +Subject: [PATCH 05/23] arm64: dts: allwinner: h616: Add OrangePi Zero 2 board + support + +The OrangePi Zero 2 is a development board with the new H616 SoC. It +comes with the following features: + - Four ARM Cortex-A53 cores, Mali-G31 MP2 GPU + - 512MiB/1GiB DDR3 DRAM + - AXP305 PMIC + - Raspberry-Pi-1 compatible GPIO header + - extra 13 pin expansion header, exposing pins for 2x USB 2.0 ports + - 1 USB 2.0 host port + - 1 USB 2.0 type C port (power supply + OTG) + - MicroSD slot + - on-board 2MiB bootable SPI NOR flash + - 1Gbps Ethernet port (via RTL8211F PHY) + - micro-HDMI port + - unsupported Allwinner WiFi/BT chip + +For more details see: https://linux-sunxi.org/Orange_Pi_Zero_2 + +Signed-off-by: Andre Przywara +--- + arch/arm64/boot/dts/allwinner/Makefile | 1 + + .../allwinner/sun50i-h616-orangepi-zero2.dts | 203 ++++++++++++++++++ + 2 files changed, 204 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts + diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile -index 211d1e9d4701..0cf8299b1ce7 100644 +index 41ce680e5f8d..9ba4b5d92657 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile -@@ -35,6 +35,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb +@@ -38,6 +38,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-m1-plus2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-beelink-gs1.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-beelink-gs1.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts new file mode 100644 -index 000000000000..814f5b4fec7c +index 000000000000..ca07cae698ce --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts -@@ -0,0 +1,228 @@ +@@ -0,0 +1,203 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (C) 2020 Arm Ltd. @@ -27,6 +57,7 @@ index 000000000000..814f5b4fec7c + +#include +#include ++#include + +/ { + model = "OrangePi Zero2"; @@ -44,15 +75,17 @@ index 000000000000..814f5b4fec7c + leds { + compatible = "gpio-leds"; + -+ power { -+ label = "orangepi:red:power"; -+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */ ++ led-0 { ++ function = LED_FUNCTION_POWER; ++ color = ; ++ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */ + default-state = "on"; + }; + -+ status { -+ label = "orangepi:green:status"; -+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */ ++ led-1 { ++ function = LED_FUNCTION_STATUS; ++ color = ; ++ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */ + }; + }; + @@ -64,32 +97,12 @@ index 000000000000..814f5b4fec7c + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ -+ status = "okay"; -+ }; +}; + -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ehci1 { -+ status = "okay"; -+}; -+ -+/* USB 2 & 3 are on headers only. */ -+ +&emac0 { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; -+ phy-mode = "rgmii-id"; ++ phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_dcdce>; + allwinner,rx-delay-ps = <3100>; @@ -97,7 +110,7 @@ index 000000000000..814f5b4fec7c + status = "okay"; +}; + -+&mdio { ++&mdio0 { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; @@ -111,26 +124,15 @@ index 000000000000..814f5b4fec7c + status = "okay"; +}; + -+&ohci0 { -+ status = "okay"; -+}; -+ -+&ohci1 { -+ status = "okay"; -+}; -+ -+&r_i2c { ++&r_rsb { + status = "okay"; + -+ axp305: pmic@36 { ++ axp305: pmic@745 { + compatible = "x-powers,axp305", "x-powers,axp805", + "x-powers,axp806"; -+ reg = <0x36>; -+ -+ /* dummy interrupt to appease the driver for now */ -+ interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; ++ reg = <0x745>; + + x-powers,self-working-mode; + vina-supply = <®_vcc5v>; @@ -150,13 +152,15 @@ index 000000000000..814f5b4fec7c + regulator-name = "vcc-sys"; + }; + -+ reg_aldo2: aldo2 { ++ reg_aldo2: aldo2 { /* 3.3V on headers */ ++ regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3-ext"; + }; + -+ reg_aldo3: aldo3 { ++ reg_aldo3: aldo3 { /* 3.3V on headers */ ++ regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3-ext2"; @@ -228,19 +232,23 @@ index 000000000000..814f5b4fec7c + }; +}; + ++&spi0 { ++ status = "okay"; ++ ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <40000000>; ++ }; ++}; ++ +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; +}; -+ -+&usbotg { -+ dr_mode = "otg"; -+ status = "okay"; -+}; -+ -+&usbphy { -+ usb0_vbus-supply = <®_vcc5v>; -+ usb1_vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+}; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0006-arm64-dts-allwinner-h616-Add-X96-Mate-TV-box-support.patch b/patch/kernel/archive/sunxi-5.12/h616_0006-arm64-dts-allwinner-h616-Add-X96-Mate-TV-box-support.patch new file mode 100644 index 0000000000..8f4c3cc4f2 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0006-arm64-dts-allwinner-h616-Add-X96-Mate-TV-box-support.patch @@ -0,0 +1,230 @@ +From 73a6a2c5310654b57207ed9a6ad6e9c1e7b3515f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 28 Apr 2021 00:06:26 +0100 +Subject: [PATCH 06/23] arm64: dts: allwinner: h616: Add X96 Mate TV box + support + +The X96 Mate is an Allwinner H616 based TV box, featuring: + - Four ARM Cortex-A53 cores, Mali-G31 MP2 GPU + - 2GiB/4GiB RAM (fully usable!) + - 16/32/64GiB eMMC + - 100Mbps Ethernet (via embedded AC200 EPHY, not yet supported) + - Unsupported Allwinner WiFi chip + - 2 x USB 2.0 host ports + - HDMI port + - IR receiver + - 5V/2A DC power supply via barrel plug + +For more information see: https://linux-sunxi.org/X96_Mate + +Add a basic devicetree for it, with SD card and eMMC working, as +well as serial and the essential peripherals, like the AXP PMIC. + +This DT is somewhat minimal, and should work on many other similar TV +boxes with the Allwinner H616 chip. + +Signed-off-by: Andre Przywara +--- + arch/arm64/boot/dts/allwinner/Makefile | 1 + + .../dts/allwinner/sun50i-h616-x96-mate.dts | 177 ++++++++++++++++++ + 2 files changed, 178 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts + +diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile +index 9ba4b5d92657..370d24ebaacf 100644 +--- a/arch/arm64/boot/dts/allwinner/Makefile ++++ b/arch/arm64/boot/dts/allwinner/Makefile +@@ -38,6 +38,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-m1-plus2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb ++dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-x96-mate.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-beelink-gs1.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts +new file mode 100644 +index 000000000000..aedb3a3dff38 +--- /dev/null ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: (GPL-2.0+ or MIT) ++/* ++ * Copyright (C) 2021 Arm Ltd. ++ */ ++ ++/dts-v1/; ++ ++#include "sun50i-h616.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "X96 Mate"; ++ compatible = "hechuang,x96-mate", "allwinner,sun50i-h616"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ reg_vcc5v: vcc5v { ++ /* board wide 5V supply directly from the DC input */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++}; ++ ++&ir { ++ status = "okay"; ++}; ++ ++&mmc0 { ++ vmmc-supply = <®_dcdce>; ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&mmc2 { ++ vmmc-supply = <®_dcdce>; ++ vqmmc-supply = <®_bldo1>; ++ bus-width = <8>; ++ non-removable; ++ cap-mmc-hw-reset; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ status = "okay"; ++}; ++ ++&r_rsb { ++ status = "okay"; ++ ++ axp305: pmic@745 { ++ compatible = "x-powers,axp305", "x-powers,axp805", ++ "x-powers,axp806"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ reg = <0x745>; ++ ++ x-powers,self-working-mode; ++ vina-supply = <®_vcc5v>; ++ vinb-supply = <®_vcc5v>; ++ vinc-supply = <®_vcc5v>; ++ vind-supply = <®_vcc5v>; ++ vine-supply = <®_vcc5v>; ++ aldoin-supply = <®_vcc5v>; ++ bldoin-supply = <®_vcc5v>; ++ cldoin-supply = <®_vcc5v>; ++ ++ regulators { ++ reg_aldo1: aldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-sys"; ++ }; ++ ++ /* Enabled by the Android BSP */ ++ reg_aldo2: aldo2 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc3v3-ext"; ++ status = "disabled"; ++ }; ++ ++ /* Enabled by the Android BSP */ ++ reg_aldo3: aldo3 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc3v3-ext2"; ++ status = "disabled"; ++ }; ++ ++ reg_bldo1: bldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8"; ++ }; ++ ++ /* Enabled by the Android BSP */ ++ reg_bldo2: bldo2 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8-2"; ++ status = "disabled"; ++ }; ++ ++ bldo3 { ++ /* unused */ ++ }; ++ ++ bldo4 { ++ /* unused */ ++ }; ++ ++ cldo1 { ++ regulator-min-microvolt = <2500000>; ++ regulator-max-microvolt = <2500000>; ++ regulator-name = "vcc2v5"; ++ }; ++ ++ cldo2 { ++ /* unused */ ++ }; ++ ++ cldo3 { ++ /* unused */ ++ }; ++ ++ reg_dcdca: dcdca { ++ regulator-always-on; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <1080000>; ++ regulator-name = "vdd-cpu"; ++ }; ++ ++ reg_dcdcc: dcdcc { ++ regulator-always-on; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <1080000>; ++ regulator-name = "vdd-gpu-sys"; ++ }; ++ ++ reg_dcdcd: dcdcd { ++ regulator-always-on; ++ regulator-min-microvolt = <1360000>; ++ regulator-max-microvolt = <1360000>; ++ regulator-name = "vdd-dram"; ++ }; ++ ++ reg_dcdce: dcdce { ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-eth-mmc"; ++ }; ++ ++ sw { ++ /* unused */ ++ }; ++ }; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_ph_pins>; ++ status = "okay"; ++}; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0007-dt-bindings-usb-sunxi-musb-Add-H616-compatible-strin.patch b/patch/kernel/archive/sunxi-5.12/h616_0007-dt-bindings-usb-sunxi-musb-Add-H616-compatible-strin.patch new file mode 100644 index 0000000000..eca1a0a3d1 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0007-dt-bindings-usb-sunxi-musb-Add-H616-compatible-strin.patch @@ -0,0 +1,32 @@ +From 075bdd9f53190b9b9a41e24188c4d7d18af5607b Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Tue, 8 Dec 2020 01:22:29 +0000 +Subject: [PATCH 07/23] dt-bindings: usb: sunxi-musb: Add H616 compatible + string + +The H616 MUSB peripheral is compatible to the H3 one (8 endpoints). + +Signed-off-by: Andre Przywara +Acked-by: Maxime Ripard +Acked-by: Rob Herring +--- + .../devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml +index 0f520f17735e..933fa356d2ce 100644 +--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml ++++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml +@@ -22,6 +22,9 @@ properties: + - allwinner,sun8i-a83t-musb + - allwinner,sun50i-h6-musb + - const: allwinner,sun8i-a33-musb ++ - items: ++ - const: allwinner,sun50i-h616-musb ++ - const: allwinner,sun8i-h3-musb + + reg: + maxItems: 1 +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0008-dt-bindings-usb-Add-H616-compatible-string.patch b/patch/kernel/archive/sunxi-5.12/h616_0008-dt-bindings-usb-Add-H616-compatible-string.patch new file mode 100644 index 0000000000..7b9a4d545f --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0008-dt-bindings-usb-Add-H616-compatible-string.patch @@ -0,0 +1,35 @@ +From 1fb25d94dbf8218b1fb8cb2743cdc783fe1642ca Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Tue, 8 Dec 2020 00:44:17 +0000 +Subject: [PATCH 08/23] dt-bindings: usb: Add H616 compatible string + +The H616 has four PHYs as the H3, along with their respective clock +gates and resets, so the property description is identical. + +However the PHYs itself need some special bits, so we need a new +compatible string for it. + +Signed-off-by: Andre Przywara +Acked-by: Rob Herring +--- + .../devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml +index f80431060803..e288450e0844 100644 +--- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml +@@ -15,7 +15,9 @@ properties: + const: 1 + + compatible: +- const: allwinner,sun8i-h3-usb-phy ++ enum: ++ - allwinner,sun8i-h3-usb-phy ++ - allwinner,sun50i-h616-usb-phy + + reg: + items: +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0009-phy-sun4i-usb-Rework-HCI-PHY-aka.-pmu_unk1-handling.patch b/patch/kernel/archive/sunxi-5.12/h616_0009-phy-sun4i-usb-Rework-HCI-PHY-aka.-pmu_unk1-handling.patch new file mode 100644 index 0000000000..da25b87944 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0009-phy-sun4i-usb-Rework-HCI-PHY-aka.-pmu_unk1-handling.patch @@ -0,0 +1,164 @@ +From d20b27d83d5688e1109ba5e9a649b48297aa732c Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Sun, 6 Dec 2020 01:39:24 +0000 +Subject: [PATCH 09/23] phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") + handling + +As Icenowy pointed out, newer manuals (starting with H6) actually +document the register block at offset 0x800 as "HCI controller and PHY +interface", also describe the bits in our "PMU_UNK1" register. +Let's put proper names to those "unknown" variables and symbols. + +While we are at it, generalise the existing code by allowing a bitmap +of bits to clear and set, to cover newer SoCs: The A100 and H616 use a +different bit for the SIDDQ control. + +Signed-off-by: Andre Przywara +--- + drivers/phy/allwinner/phy-sun4i-usb.c | 30 ++++++++++++--------------- + 1 file changed, 13 insertions(+), 17 deletions(-) + +diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c +index 788dd5cdbb7d..142f4cafdc78 100644 +--- a/drivers/phy/allwinner/phy-sun4i-usb.c ++++ b/drivers/phy/allwinner/phy-sun4i-usb.c +@@ -43,7 +43,7 @@ + #define REG_PHYCTL_A33 0x10 + #define REG_PHY_OTGCTL 0x20 + +-#define REG_PMU_UNK1 0x10 ++#define REG_HCI_PHY_CTL 0x10 + + #define PHYCTL_DATA BIT(7) + +@@ -82,6 +82,7 @@ + /* A83T specific control bits for PHY0 */ + #define PHY_CTL_VBUSVLDEXT BIT(5) + #define PHY_CTL_SIDDQ BIT(3) ++#define PHY_CTL_H3_SIDDQ BIT(1) + + /* A83T specific control bits for PHY2 HSIC */ + #define SUNXI_EHCI_HS_FORCE BIT(20) +@@ -115,9 +116,9 @@ struct sun4i_usb_phy_cfg { + int hsic_index; + enum sun4i_usb_phy_type type; + u32 disc_thresh; ++ u32 hci_phy_ctl_clear; + u8 phyctl_offset; + bool dedicated_clocks; +- bool enable_pmu_unk1; + bool phy0_dual_route; + int missing_phys; + }; +@@ -288,6 +289,12 @@ static int sun4i_usb_phy_init(struct phy *_phy) + return ret; + } + ++ if (phy->pmu && data->cfg->hci_phy_ctl_clear) { ++ val = readl(phy->pmu + REG_HCI_PHY_CTL); ++ val &= ~data->cfg->hci_phy_ctl_clear; ++ writel(val, phy->pmu + REG_HCI_PHY_CTL); ++ } ++ + if (data->cfg->type == sun8i_a83t_phy || + data->cfg->type == sun50i_h6_phy) { + if (phy->index == 0) { +@@ -297,11 +304,6 @@ static int sun4i_usb_phy_init(struct phy *_phy) + writel(val, data->base + data->cfg->phyctl_offset); + } + } else { +- if (phy->pmu && data->cfg->enable_pmu_unk1) { +- val = readl(phy->pmu + REG_PMU_UNK1); +- writel(val & ~2, phy->pmu + REG_PMU_UNK1); +- } +- + /* Enable USB 45 Ohm resistor calibration */ + if (phy->index == 0) + sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); +@@ -863,7 +865,6 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { +@@ -872,7 +873,6 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { + .disc_thresh = 2, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { +@@ -881,7 +881,6 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = true, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { +@@ -890,7 +889,6 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { + .disc_thresh = 2, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { +@@ -899,7 +897,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = true, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { +@@ -908,7 +905,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, +- .enable_pmu_unk1 = false, + }; + + static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { +@@ -925,7 +921,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, +- .enable_pmu_unk1 = true, ++ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, + .phy0_dual_route = true, + }; + +@@ -935,7 +931,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, +- .enable_pmu_unk1 = true, ++ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, + .phy0_dual_route = true, + }; + +@@ -945,7 +941,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, +- .enable_pmu_unk1 = true, ++ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, + .phy0_dual_route = true, + }; + +@@ -955,7 +951,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, +- .enable_pmu_unk1 = true, ++ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, + .phy0_dual_route = true, + }; + +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0010-phy-sun4i-usb-Allow-reset-line-to-be-shared.patch b/patch/kernel/archive/sunxi-5.12/h616_0010-phy-sun4i-usb-Allow-reset-line-to-be-shared.patch new file mode 100644 index 0000000000..cb0d4597fc --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0010-phy-sun4i-usb-Allow-reset-line-to-be-shared.patch @@ -0,0 +1,36 @@ +From 70de28c88b747d01b33cdb9c3d4512ff5f8663aa Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 10 May 2021 11:01:31 +0100 +Subject: [PATCH 10/23] phy: sun4i-usb: Allow reset line to be shared + +The USB HCIs (and PHYs?) in Allwinner's newer generation SoCs (H616) +rely on the reset line of USB PHY 2 to be de-asserted, even when only +one of the other PHYs is actually in use. + +To make those ports work, we include this reset line in the HCIs' resets +property, which requires this line to be shareable. + +Change the call to allocate the reset line to mark it as shared, to +enable the other ports on those SoCs. + +Signed-off-by: Andre Przywara +--- + drivers/phy/allwinner/phy-sun4i-usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c +index 142f4cafdc78..126ef74d013c 100644 +--- a/drivers/phy/allwinner/phy-sun4i-usb.c ++++ b/drivers/phy/allwinner/phy-sun4i-usb.c +@@ -788,7 +788,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) + } + + snprintf(name, sizeof(name), "usb%d_reset", i); +- phy->reset = devm_reset_control_get(dev, name); ++ phy->reset = devm_reset_control_get_shared(dev, name); + if (IS_ERR(phy->reset)) { + dev_err(dev, "failed to get reset %s\n", name); + return PTR_ERR(phy->reset); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0011-phy-sun4i-usb-Introduce-port2-SIDDQ-quirk.patch b/patch/kernel/archive/sunxi-5.12/h616_0011-phy-sun4i-usb-Introduce-port2-SIDDQ-quirk.patch new file mode 100644 index 0000000000..b44a61a08c --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0011-phy-sun4i-usb-Introduce-port2-SIDDQ-quirk.patch @@ -0,0 +1,117 @@ +From 629a19cc09aab0005e51d9fd525ca66d7f3a7cd2 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 10 May 2021 11:01:31 +0100 +Subject: [PATCH 11/23] phy: sun4i-usb: Introduce port2 SIDDQ quirk + +At least the Allwinner H616 SoC requires a weird quirk to make most +USB PHYs work: Only port2 works out of the box, but all other ports +need some help from this port2 to work correctly: The CLK_BUS_PHY2 and +RST_USB_PHY2 clock and reset need to be enabled, and the SIDDQ bit in +the PMU PHY control register needs to be cleared. For this register to +be accessible, CLK_BUS_ECHI2 needs to be ungated. Don't ask .... + +Instead of disguising this as some generic feature, do exactly that +in our PHY init: +If the quirk bit is set, and we initialise a PHY other than PHY2, ungate +this one special clock, and clear the SIDDQ bit. We can pull in the +other required clocks via the DT. + +Signed-off-by: Andre Przywara +--- + drivers/phy/allwinner/phy-sun4i-usb.c | 59 +++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c +index 126ef74d013c..316ef5fca831 100644 +--- a/drivers/phy/allwinner/phy-sun4i-usb.c ++++ b/drivers/phy/allwinner/phy-sun4i-usb.c +@@ -120,6 +120,7 @@ struct sun4i_usb_phy_cfg { + u8 phyctl_offset; + bool dedicated_clocks; + bool phy0_dual_route; ++ bool needs_phy2_siddq; + int missing_phys; + }; + +@@ -289,6 +290,50 @@ static int sun4i_usb_phy_init(struct phy *_phy) + return ret; + } + ++ /* Some PHYs on some SoCs need the help of PHY2 to work. */ ++ if (data->cfg->needs_phy2_siddq && phy->index != 2) { ++ struct sun4i_usb_phy *phy2 = &data->phys[2]; ++ ++ ret = clk_prepare_enable(phy2->clk); ++ if (ret) { ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ ret = reset_control_deassert(phy2->reset); ++ if (ret) { ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ /* ++ * This extra clock is just needed to access the ++ * REG_HCI_PHY_CTL PMU register for PHY2. ++ */ ++ ret = clk_prepare_enable(phy2->clk2); ++ if (ret) { ++ reset_control_assert(phy2->reset); ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ if (phy2->pmu && data->cfg->hci_phy_ctl_clear) { ++ val = readl(phy2->pmu + REG_HCI_PHY_CTL); ++ val &= ~data->cfg->hci_phy_ctl_clear; ++ writel(val, phy2->pmu + REG_HCI_PHY_CTL); ++ } ++ ++ clk_disable_unprepare(phy->clk2); ++ } ++ + if (phy->pmu && data->cfg->hci_phy_ctl_clear) { + val = readl(phy->pmu + REG_HCI_PHY_CTL); + val &= ~data->cfg->hci_phy_ctl_clear; +@@ -354,6 +399,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy) + data->phy0_init = false; + } + ++ if (data->cfg->needs_phy2_siddq && phy->index != 2) { ++ struct sun4i_usb_phy *phy2 = &data->phys[2]; ++ ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy2->reset); ++ } ++ + sun4i_usb_phy_passby(phy, 0); + reset_control_assert(phy->reset); + clk_disable_unprepare(phy->clk2); +@@ -785,6 +837,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) + dev_err(dev, "failed to get clock %s\n", name); + return PTR_ERR(phy->clk2); + } ++ } else { ++ snprintf(name, sizeof(name), "pmu%d_clk", i); ++ phy->clk2 = devm_clk_get_optional(dev, name); ++ if (IS_ERR(phy->clk2)) { ++ dev_err(dev, "failed to get clock %s\n", name); ++ return PTR_ERR(phy->clk2); ++ } + } + + snprintf(name, sizeof(name), "usb%d_reset", i); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0012-phy-sun4i-usb-Add-support-for-the-H616-USB-PHY.patch b/patch/kernel/archive/sunxi-5.12/h616_0012-phy-sun4i-usb-Add-support-for-the-H616-USB-PHY.patch new file mode 100644 index 0000000000..d7e6b76e01 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0012-phy-sun4i-usb-Add-support-for-the-H616-USB-PHY.patch @@ -0,0 +1,51 @@ +From b7cee5b9fd53d18629de342c917a8fbea678aa39 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Sun, 6 Dec 2020 01:40:16 +0000 +Subject: [PATCH 12/23] phy: sun4i-usb: Add support for the H616 USB PHY + +The USB PHY used in the Allwinner H616 SoC inherits some traits from its +various predecessors: it has four full PHYs like the H3, needs some +extra bits to be set like the H6, and puts SIDDQ on a different bit like +the A100. Plus it needs this weird PHY2 quirk. + +Name all those properties in a new config struct and assign a new +compatible name to it. + +Signed-off-by: Andre Przywara +--- + drivers/phy/allwinner/phy-sun4i-usb.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c +index 316ef5fca831..85a9771280b7 100644 +--- a/drivers/phy/allwinner/phy-sun4i-usb.c ++++ b/drivers/phy/allwinner/phy-sun4i-usb.c +@@ -1024,6 +1024,17 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { + .missing_phys = BIT(1) | BIT(2), + }; + ++static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = { ++ .num_phys = 4, ++ .type = sun50i_h6_phy, ++ .disc_thresh = 3, ++ .phyctl_offset = REG_PHYCTL_A33, ++ .dedicated_clocks = true, ++ .phy0_dual_route = true, ++ .hci_phy_ctl_clear = PHY_CTL_SIDDQ, ++ .needs_phy2_siddq = true, ++}; ++ + static const struct of_device_id sun4i_usb_phy_of_match[] = { + { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, + { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, +@@ -1038,6 +1049,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { + { .compatible = "allwinner,sun50i-a64-usb-phy", + .data = &sun50i_a64_cfg}, + { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, ++ { .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg }, + { }, + }; + MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0013-arm64-dts-allwinner-h616-Add-USB-nodes.patch b/patch/kernel/archive/sunxi-5.12/h616_0013-arm64-dts-allwinner-h616-Add-USB-nodes.patch new file mode 100644 index 0000000000..b782601286 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0013-arm64-dts-allwinner-h616-Add-USB-nodes.patch @@ -0,0 +1,190 @@ +From b78f977c6abefecfc90c995f9808250da2a6fb9f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:20:47 +0100 +Subject: [PATCH 13/23] arm64: dts: allwinner: h616: Add USB nodes + +Add the nodes for the MUSB and the four USB host controllers to the SoC +.dtsi, along with the PHY node needed to bind all of them together. + +EHCI/OHCI and MUSB are compatible to previous SoCs, but the PHY requires +some quirks (handled in the driver). + +Signed-off-by: Andre Przywara +--- + .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 160 ++++++++++++++++++ + 1 file changed, 160 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +index 0ad0c25b4c83..7681f2a68dee 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +@@ -494,6 +494,166 @@ mdio0: mdio { + }; + }; + ++ usbotg: usb@5100000 { ++ compatible = "allwinner,sun50i-h616-musb", ++ "allwinner,sun8i-h3-musb"; ++ reg = <0x05100000 0x0400>; ++ clocks = <&ccu CLK_BUS_OTG>; ++ resets = <&ccu RST_BUS_OTG>; ++ interrupts = ; ++ interrupt-names = "mc"; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ extcon = <&usbphy 0>; ++ status = "disabled"; ++ }; ++ ++ usbphy: phy@5100400 { ++ compatible = "allwinner,sun50i-h616-usb-phy"; ++ reg = <0x05100400 0x24>, ++ <0x05101800 0x14>, ++ <0x05200800 0x14>, ++ <0x05310800 0x14>, ++ <0x05311800 0x14>; ++ reg-names = "phy_ctrl", ++ "pmu0", ++ "pmu1", ++ "pmu2", ++ "pmu3"; ++ clocks = <&ccu CLK_USB_PHY0>, ++ <&ccu CLK_USB_PHY1>, ++ <&ccu CLK_USB_PHY2>, ++ <&ccu CLK_USB_PHY3>, ++ <&ccu CLK_BUS_EHCI2>; ++ clock-names = "usb0_phy", ++ "usb1_phy", ++ "usb2_phy", ++ "usb3_phy", ++ "pmu2_clk"; ++ resets = <&ccu RST_USB_PHY0>, ++ <&ccu RST_USB_PHY1>, ++ <&ccu RST_USB_PHY2>, ++ <&ccu RST_USB_PHY3>; ++ reset-names = "usb0_reset", ++ "usb1_reset", ++ "usb2_reset", ++ "usb3_reset"; ++ status = "disabled"; ++ #phy-cells = <1>; ++ }; ++ ++ ehci0: usb@5101000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05101000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI0>, ++ <&ccu CLK_BUS_EHCI0>, ++ <&ccu CLK_USB_OHCI0>; ++ resets = <&ccu RST_BUS_OHCI0>, ++ <&ccu RST_BUS_EHCI0>; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@5101400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05101400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI0>, ++ <&ccu CLK_USB_OHCI0>; ++ resets = <&ccu RST_BUS_OHCI0>; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci1: usb@5200000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05200000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI1>, ++ <&ccu CLK_BUS_EHCI1>, ++ <&ccu CLK_USB_OHCI1>; ++ resets = <&ccu RST_BUS_OHCI1>, ++ <&ccu RST_BUS_EHCI1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci1: usb@5200400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05200400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI1>, ++ <&ccu CLK_USB_OHCI1>; ++ resets = <&ccu RST_BUS_OHCI1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci2: usb@5310000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05310000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI2>, ++ <&ccu CLK_BUS_EHCI2>, ++ <&ccu CLK_USB_OHCI2>; ++ resets = <&ccu RST_BUS_OHCI2>, ++ <&ccu RST_BUS_EHCI2>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci2: usb@5310400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05310400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI2>, ++ <&ccu CLK_USB_OHCI2>; ++ resets = <&ccu RST_BUS_OHCI2>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci3: usb@5311000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05311000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI3>, ++ <&ccu CLK_BUS_EHCI3>, ++ <&ccu CLK_USB_OHCI3>; ++ resets = <&ccu RST_BUS_OHCI3>, ++ <&ccu RST_BUS_EHCI3>; ++ phys = <&usbphy 3>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci3: usb@5311400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05311400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI3>, ++ <&ccu CLK_USB_OHCI3>; ++ resets = <&ccu RST_BUS_OHCI3>; ++ phys = <&usbphy 3>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + r_ccu: clock@7010000 { + compatible = "allwinner,sun50i-h616-r-ccu"; + reg = <0x07010000 0x210>; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0014-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch b/patch/kernel/archive/sunxi-5.12/h616_0014-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch new file mode 100644 index 0000000000..9d06505941 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0014-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch @@ -0,0 +1,85 @@ +From 11c36003850ca252017cca807e8aaad274645a8c Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:32:36 +0100 +Subject: [PATCH 14/23] arm64: dts: allwinner: h616: OrangePi Zero 2: Add USB + nodes + +The OrangePi Zero 2 has one USB-A host port, VBUS is provided by +a GPIO controlled regulator. +The USB-C port is meant to power the board, but is also connected to +the USB 0 port, which we configure as an MUSB peripheral. + +Signed-off-by: Andre Przywara +--- + .../allwinner/sun50i-h616-orangepi-zero2.dts | 42 +++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +index ca07cae698ce..a26201288872 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +@@ -49,8 +49,25 @@ reg_vcc5v: vcc5v { + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; ++ ++ reg_usb1_vbus: usb1-vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <®_vcc5v>; ++ enable-active-high; ++ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ ++ status = "okay"; ++ }; + }; + ++&ehci1 { ++ status = "okay"; ++}; ++ ++/* USB 2 & 3 are on headers only. */ ++ + &emac0 { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; +@@ -76,6 +93,10 @@ &mmc0 { + status = "okay"; + }; + ++&ohci1 { ++ status = "okay"; ++}; ++ + &r_rsb { + status = "okay"; + +@@ -201,3 +222,24 @@ &uart0 { + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; + }; ++ ++&usbotg { ++ /* ++ * PHY0 pins are connected to a USB-C socket, but a role switch ++ * is not implemented: both CC pins are pulled to GND. ++ * The VBUS pins power the device, so a fixed peripheral mode ++ * is the best choice. ++ * The board can be powered via GPIOs, in this case port0 *can* ++ * act as a host (with a cable/adapter ignoring CC), as VBUS is ++ * then provided by the GPIOs. Any user of this setup would ++ * need to adjust the DT accordingly: dr_mode set to "host", ++ * enabling OHCI0 and EHCI0. ++ */ ++ dr_mode = "peripheral"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ status = "okay"; ++}; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0015-arm64-dts-allwinner-h616-X96-Mate-Add-USB-nodes.patch b/patch/kernel/archive/sunxi-5.12/h616_0015-arm64-dts-allwinner-h616-X96-Mate-Add-USB-nodes.patch new file mode 100644 index 0000000000..bd585f68ea --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0015-arm64-dts-allwinner-h616-X96-Mate-Add-USB-nodes.patch @@ -0,0 +1,66 @@ +From 506dc58a250db76e2208ce329b9f39d3da049dab Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:33:42 +0100 +Subject: [PATCH 15/23] arm64: dts: allwinner: h616: X96 Mate: Add USB nodes + +The X96 Mate TV box has two USB-A ports, VBUS is always on and connected +to the DC input. +Since USB port 0 is connected to an USB-A receptable, we configure it +as a host port. Using it as a peripheral is dangerous, because VBUS is +always on. + +Signed-off-by: Andre Przywara +--- + .../dts/allwinner/sun50i-h616-x96-mate.dts | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts +index aedb3a3dff38..5c3586717c00 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts +@@ -32,6 +32,14 @@ reg_vcc5v: vcc5v { + }; + }; + ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ehci2 { ++ status = "okay"; ++}; ++ + &ir { + status = "okay"; + }; +@@ -54,6 +62,14 @@ &mmc2 { + status = "okay"; + }; + ++&ohci0 { ++ status = "okay"; ++}; ++ ++&ohci2 { ++ status = "okay"; ++}; ++ + &r_rsb { + status = "okay"; + +@@ -175,3 +191,12 @@ &uart0 { + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; + }; ++ ++&usbotg { ++ dr_mode = "host"; /* USB A type receptable */ ++ status = "okay"; ++}; ++ ++&usbphy { ++ status = "okay"; ++}; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0016-dt-bindings-net-sun8i-emac-Add-H616-compatible-strin.patch b/patch/kernel/archive/sunxi-5.12/h616_0016-dt-bindings-net-sun8i-emac-Add-H616-compatible-strin.patch new file mode 100644 index 0000000000..780f78dd25 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0016-dt-bindings-net-sun8i-emac-Add-H616-compatible-strin.patch @@ -0,0 +1,36 @@ +From 63c5e1db13fa936d46da486d4d312a8cb52da7d8 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 27 Jan 2021 13:27:39 +0000 +Subject: [PATCH 16/23] dt-bindings: net: sun8i-emac: Add H616 compatible + string + +Add the obvious compatible name to the existing EMAC binding, and pair +it with the existing A64 fallback compatible string, as the devices are +compatible. + +On the way use enums to group the compatible devices together. + +Signed-off-by: Andre Przywara +Acked-by: Rob Herring +--- + .../devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +index 7f2578d48e3f..0ccdab103f59 100644 +--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml ++++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +@@ -19,7 +19,9 @@ properties: + - const: allwinner,sun8i-v3s-emac + - const: allwinner,sun50i-a64-emac + - items: +- - const: allwinner,sun50i-h6-emac ++ - enum: ++ - allwinner,sun50i-h6-emac ++ - allwinner,sun50i-h616-emac + - const: allwinner,sun50i-a64-emac + + reg: +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0017-net-stmmac-dwmac-sun8i-Prepare-for-second-EMAC-clock.patch b/patch/kernel/archive/sunxi-5.12/h616_0017-net-stmmac-dwmac-sun8i-Prepare-for-second-EMAC-clock.patch new file mode 100644 index 0000000000..c527bef4c8 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0017-net-stmmac-dwmac-sun8i-Prepare-for-second-EMAC-clock.patch @@ -0,0 +1,65 @@ +From c873c54739d24511e65039e0a6a13dbf449f0822 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Thu, 10 Dec 2020 14:42:12 +0000 +Subject: [PATCH 17/23] net: stmmac: dwmac-sun8i: Prepare for second EMAC clock + register + +The Allwinner H616 SoC has two EMAC controllers, with the second one +being tied to the internal PHY, but also using a separate EMAC clock +register. + +To tell the driver about which clock register to use, we add a parameter +to our syscon phandle. The driver will use this value as an index into +the regmap, so that we can address more than the first register, if +needed. + +Signed-off-by: Andre Przywara +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index 4422baeed3d8..5f3fefd9a74e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -1147,11 +1147,13 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) + struct stmmac_resources stmmac_res; + struct sunxi_priv_data *gmac; + struct device *dev = &pdev->dev; ++ struct reg_field syscon_field; + phy_interface_t interface; + int ret; + struct stmmac_priv *priv; + struct net_device *ndev; + struct regmap *regmap; ++ u32 syscon_idx = 0; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) +@@ -1209,8 +1211,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) + return ret; + } + +- gmac->regmap_field = devm_regmap_field_alloc(dev, regmap, +- *gmac->variant->syscon_field); ++ syscon_field = *gmac->variant->syscon_field; ++ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, ++ &syscon_idx); ++ if (!ret) ++ syscon_field.reg += syscon_idx * sizeof(u32); ++ gmac->regmap_field = devm_regmap_field_alloc(dev, regmap, syscon_field); + if (IS_ERR(gmac->regmap_field)) { + ret = PTR_ERR(gmac->regmap_field); + dev_err(dev, "Unable to map syscon register: %d\n", ret); +@@ -1330,6 +1336,8 @@ static const struct of_device_id sun8i_dwmac_match[] = { + .data = &emac_variant_a64 }, + { .compatible = "allwinner,sun50i-h6-emac", + .data = &emac_variant_h6 }, ++ { .compatible = "allwinner,sun50i-h616-emac", ++ .data = &emac_variant_h6 }, + { } + }; + MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0018-dt-bindings-rtc-sun6i-Add-H616-compatible-string.patch b/patch/kernel/archive/sunxi-5.12/h616_0018-dt-bindings-rtc-sun6i-Add-H616-compatible-string.patch new file mode 100644 index 0000000000..6895b34fb9 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0018-dt-bindings-rtc-sun6i-Add-H616-compatible-string.patch @@ -0,0 +1,52 @@ +From b9dcf9e120fd83c7d4d3bceb45467cc239c8039f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Thu, 10 Dec 2020 22:42:55 +0000 +Subject: [PATCH 18/23] dt-bindings: rtc: sun6i: Add H616 compatible string + +Add the obvious compatible name to the existing RTC binding. +The actual RTC part of the device uses a different day/month/year +storage scheme, so it's not compatible with the previous devices. +Also the clock part is quite different, as there is no external 32K LOSC +oscillator input. + +Signed-off-by: Andre Przywara +--- + .../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml +index b1b0ee769b71..2c3fd72e17ee 100644 +--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml ++++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml +@@ -26,6 +26,7 @@ properties: + - const: allwinner,sun50i-a64-rtc + - const: allwinner,sun8i-h3-rtc + - const: allwinner,sun50i-h6-rtc ++ - const: allwinner,sun50i-h616-rtc + + reg: + maxItems: 1 +@@ -105,6 +106,20 @@ allOf: + minItems: 3 + maxItems: 3 + ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: allwinner,sun50i-h616-rtc ++ ++ then: ++ properties: ++ clock-output-names: ++ minItems: 3 ++ maxItems: 3 ++ clocks: ++ maxItems: 0 ++ + - if: + properties: + compatible: +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0019-rtc-sun6i-Add-support-for-linear-day-storage.patch b/patch/kernel/archive/sunxi-5.12/h616_0019-rtc-sun6i-Add-support-for-linear-day-storage.patch new file mode 100644 index 0000000000..cfc692eaec --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0019-rtc-sun6i-Add-support-for-linear-day-storage.patch @@ -0,0 +1,146 @@ +From eccdbbb097217408d1c14a11497717dd97df04d7 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 26 Feb 2021 10:27:51 +0000 +Subject: [PATCH 19/23] rtc: sun6i: Add support for linear day storage + +Newer versions of the Allwinner RTC, as for instance found in the H616 +SoC, no longer store a broken-down day/month/year representation in the +RTC_DAY_REG, but just a linear day number. +The user manual does not give any indication about the expected epoch +time of this day count, but the BSP kernel uses the UNIX epoch, which +allows easy support due to existing conversion functions in the kernel. + +Allow tagging a compatible string with a flag, and use that to mark +those new RTCs. Then convert between a UNIX day number (converted into +seconds) and the broken-down day representation using mktime64() and +time64_to_tm() in the set_time/get_time functions. + +That enables support for the RTC in those new chips. + +Reviewed-by: Andre Przywara +--- + drivers/rtc/rtc-sun6i.c | 66 +++++++++++++++++++++++++++-------------- + 1 file changed, 44 insertions(+), 22 deletions(-) + +diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c +index adec1b14a8de..e4fc6e4f2bfb 100644 +--- a/drivers/rtc/rtc-sun6i.c ++++ b/drivers/rtc/rtc-sun6i.c +@@ -110,6 +110,8 @@ + #define SUN6I_YEAR_MIN 1970 + #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) + ++#define SEC_PER_DAY (24 * 3600ULL) ++ + /* + * There are other differences between models, including: + * +@@ -133,12 +135,15 @@ struct sun6i_rtc_clk_data { + unsigned int has_auto_swt : 1; + }; + ++#define RTC_LINEAR_DAY BIT(0) ++ + struct sun6i_rtc_dev { + struct rtc_device *rtc; + const struct sun6i_rtc_clk_data *data; + void __iomem *base; + int irq; + unsigned long alarm; ++ unsigned long flags; + + struct clk_hw hw; + struct clk_hw *int_osc; +@@ -467,22 +472,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) + } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || + (time != readl(chip->base + SUN6I_RTC_HMS))); + ++ if (chip->flags & RTC_LINEAR_DAY) { ++ /* ++ * Newer chips store a linear day number, the manual ++ * does not mandate any epoch base. The BSP driver uses ++ * the UNIX epoch, let's just copy that, as it's the ++ * easiest anyway. ++ */ ++ rtc_time64_to_tm((date & 0xffff) * SEC_PER_DAY, rtc_tm); ++ } else { ++ rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); ++ rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date) - 1; ++ rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); ++ ++ /* ++ * switch from (data_year->min)-relative offset to ++ * a (1900)-relative one ++ */ ++ rtc_tm->tm_year += SUN6I_YEAR_OFF; ++ } ++ + rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); + rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); + rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); + +- rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); +- rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); +- rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); +- +- rtc_tm->tm_mon -= 1; +- +- /* +- * switch from (data_year->min)-relative offset to +- * a (1900)-relative one +- */ +- rtc_tm->tm_year += SUN6I_YEAR_OFF; +- + return 0; + } + +@@ -571,20 +584,27 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) + u32 date = 0; + u32 time = 0; + +- rtc_tm->tm_year -= SUN6I_YEAR_OFF; +- rtc_tm->tm_mon += 1; +- +- date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | +- SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | +- SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); +- +- if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) +- date |= SUN6I_LEAP_SET_VALUE(1); +- + time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | + SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | + SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); + ++ if (chip->flags & RTC_LINEAR_DAY) { ++ rtc_tm->tm_sec = 0; ++ rtc_tm->tm_min = 0; ++ rtc_tm->tm_hour = 0; ++ date = rtc_tm_to_time64(rtc_tm) / SEC_PER_DAY; ++ } else { ++ rtc_tm->tm_year -= SUN6I_YEAR_OFF; ++ rtc_tm->tm_mon += 1; ++ ++ date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | ++ SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | ++ SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); ++ ++ if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) ++ date |= SUN6I_LEAP_SET_VALUE(1); ++ } ++ + /* Check whether registers are writable */ + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_ACC_MASK, 50)) { +@@ -678,6 +698,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, chip); + ++ chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev); ++ + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) + return chip->irq; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0020-rtc-sun6i-Add-support-for-broken-down-alarm-register.patch b/patch/kernel/archive/sunxi-5.12/h616_0020-rtc-sun6i-Add-support-for-broken-down-alarm-register.patch new file mode 100644 index 0000000000..423f6e279a --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0020-rtc-sun6i-Add-support-for-broken-down-alarm-register.patch @@ -0,0 +1,112 @@ +From dc5413b704ec0f95d5b6c4f752f25214f2d05e2e Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 4 Jun 2021 12:12:27 +0100 +Subject: [PATCH 20/23] rtc: sun6i: Add support for broken-down alarm registers + +Newer versions of the Allwinner RTC, for instance as found in the H616 +SoC, not only store the current day as a linear number, but also change +the way the alarm is handled: There are now two registers, that +explicitly store the wakeup time, in the same format as the current +time. + +Add support for that variant by writing the requested wakeup time +directly into the registers, instead of programming the seconds left, as +the old SoCs required. + +Signed-off-by: Andre Przywara +--- + drivers/rtc/rtc-sun6i.c | 60 +++++++++++++++++++++++++++-------------- + 1 file changed, 40 insertions(+), 20 deletions(-) + +diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c +index e4fc6e4f2bfb..54bd47fb0a5f 100644 +--- a/drivers/rtc/rtc-sun6i.c ++++ b/drivers/rtc/rtc-sun6i.c +@@ -48,7 +48,8 @@ + + /* Alarm 0 (counter) */ + #define SUN6I_ALRM_COUNTER 0x0020 +-#define SUN6I_ALRM_CUR_VAL 0x0024 ++/* This holds the remaining alarm seconds on older SoCs (current value) */ ++#define SUN6I_ALRM_COUNTER_HMS 0x0024 + #define SUN6I_ALRM_EN 0x0028 + #define SUN6I_ALRM_EN_CNT_EN BIT(0) + #define SUN6I_ALRM_IRQ_EN 0x002c +@@ -523,36 +524,55 @@ 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; ++ unsigned long counter_val, counter_val_hms; + int ret = 0; + +- ret = sun6i_rtc_gettime(dev, &tm_now); +- if (ret < 0) { +- dev_err(dev, "Error in getting time\n"); +- return -EINVAL; +- } +- + time_set = rtc_tm_to_time64(alrm_tm); +- time_now = rtc_tm_to_time64(&tm_now); +- if (time_set <= time_now) { +- dev_err(dev, "Date to set in the past\n"); +- return -EINVAL; +- } +- +- time_gap = time_set - time_now; + +- if (time_gap > U32_MAX) { +- dev_err(dev, "Date too far in the future\n"); +- return -EINVAL; ++ if (chip->flags & RTC_LINEAR_DAY) { ++ /* ++ * The alarm registers hold the actual alarm time, encoded ++ * in the same way (linear day + HMS) as the current time. ++ */ ++ counter_val_hms = SUN6I_TIME_SET_SEC_VALUE(alrm_tm->tm_sec) | ++ SUN6I_TIME_SET_MIN_VALUE(alrm_tm->tm_min) | ++ SUN6I_TIME_SET_HOUR_VALUE(alrm_tm->tm_hour); ++ counter_val = mktime64(alrm_tm->tm_year + 1900, alrm_tm->tm_mon, ++ alrm_tm->tm_mday, 0, 0, 0) / SEC_PER_DAY; ++ } else { ++ /* The alarm register holds the number of seconds left. */ ++ unsigned long time_now; ++ ++ ret = sun6i_rtc_gettime(dev, &tm_now); ++ if (ret < 0) { ++ dev_err(dev, "Error in getting time\n"); ++ return -EINVAL; ++ } ++ ++ time_now = rtc_tm_to_time64(&tm_now); ++ if (time_set <= time_now) { ++ dev_err(dev, "Date to set in the past\n"); ++ return -EINVAL; ++ } ++ ++ counter_val = time_set - time_now; ++ ++ if (counter_val > U32_MAX) { ++ dev_err(dev, "Date too far in the future\n"); ++ return -EINVAL; ++ } + } + + sun6i_rtc_setaie(0, chip); + writel(0, chip->base + SUN6I_ALRM_COUNTER); ++ if (chip->flags & RTC_LINEAR_DAY) ++ writel(0, chip->base + SUN6I_ALRM_COUNTER_HMS); + usleep_range(100, 300); + +- writel(time_gap, chip->base + SUN6I_ALRM_COUNTER); ++ writel(counter_val, chip->base + SUN6I_ALRM_COUNTER); ++ if (chip->flags & RTC_LINEAR_DAY) ++ writel(counter_val_hms, chip->base + SUN6I_ALRM_COUNTER_HMS); + chip->alarm = time_set; + + sun6i_rtc_setaie(wkalrm->enabled, chip); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0021-rtc-sun6i-Add-support-for-RTCs-without-external-LOSC.patch b/patch/kernel/archive/sunxi-5.12/h616_0021-rtc-sun6i-Add-support-for-RTCs-without-external-LOSC.patch new file mode 100644 index 0000000000..986190153c --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0021-rtc-sun6i-Add-support-for-RTCs-without-external-LOSC.patch @@ -0,0 +1,67 @@ +From 9dcadc898af3795e1ec17c0656b884b2f802c609 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 14 Jun 2021 23:02:45 +0100 +Subject: [PATCH 21/23] rtc: sun6i: Add support for RTCs without external LOSCs + +Some newer Allwinner RTCs (for instance the one in the H616 SoC) lack +a pin for an external 32768 Hz oscillator. As a consequence, this LOSC +can't be selected as the RTC clock source, and we must rely on the +internal RC oscillator. +To allow additions of clocks to the RTC node, add a feature bit to ignore +any provided clocks for now (the current code would think this is the +external LOSC). Later DTs and code can then for instance add the PLL +based clock input, and older kernel won't get confused. + +Signed-off-by: Andre Przywara +--- + drivers/rtc/rtc-sun6i.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c +index 54bd47fb0a5f..1fabb3c69041 100644 +--- a/drivers/rtc/rtc-sun6i.c ++++ b/drivers/rtc/rtc-sun6i.c +@@ -134,6 +134,7 @@ struct sun6i_rtc_clk_data { + unsigned int export_iosc : 1; + unsigned int has_losc_en : 1; + unsigned int has_auto_swt : 1; ++ unsigned int no_ext_losc : 1; + }; + + #define RTC_LINEAR_DAY BIT(0) +@@ -256,7 +257,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, + } + + /* Switch to the external, more precise, oscillator, if present */ +- if (of_get_property(node, "clocks", NULL)) { ++ if (!rtc->data->no_ext_losc && of_get_property(node, "clocks", NULL)) { + reg |= SUN6I_LOSC_CTRL_EXT_OSC; + if (rtc->data->has_losc_en) + reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; +@@ -282,14 +283,19 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, + } + + parents[0] = clk_hw_get_name(rtc->int_osc); +- /* If there is no external oscillator, this will be NULL and ... */ +- parents[1] = of_clk_get_parent_name(node, 0); ++ if (rtc->data->no_ext_losc) { ++ parents[1] = NULL; ++ init.num_parents = 1; ++ } else { ++ /* If there is no external oscillator, this will be NULL and */ ++ parents[1] = of_clk_get_parent_name(node, 0); ++ /* ... number of clock parents will be 1. */ ++ init.num_parents = of_clk_get_parent_count(node) + 1; ++ } + + rtc->hw.init = &init; + + init.parent_names = parents; +- /* ... number of clock parents will be 1. */ +- init.num_parents = of_clk_get_parent_count(node) + 1; + of_property_read_string_index(node, "clock-output-names", 0, + &init.name); + +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0022-rtc-sun6i-Add-Allwinner-H616-support.patch b/patch/kernel/archive/sunxi-5.12/h616_0022-rtc-sun6i-Add-Allwinner-H616-support.patch new file mode 100644 index 0000000000..7e1e244391 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0022-rtc-sun6i-Add-Allwinner-H616-support.patch @@ -0,0 +1,55 @@ +From 8aa5764941546dbe3712fffb58e240c9b048ed2c Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 21 Apr 2021 12:46:43 +0100 +Subject: [PATCH 22/23] rtc: sun6i: Add Allwinner H616 support + +The H616 RTC changes its day storage to the newly introduced linear day +scheme, so pair the new compatible string with this feature flag. +The clock part is missing an external 32768 Hz oscillator input pin, +for future expansion we must thus ignore any provided clock for now. + +Signed-off-by: Andre Przywara +--- + drivers/rtc/rtc-sun6i.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c +index 1fabb3c69041..25dae50019af 100644 +--- a/drivers/rtc/rtc-sun6i.c ++++ b/drivers/rtc/rtc-sun6i.c +@@ -392,6 +392,23 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node) + CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc", + sun50i_h6_rtc_clk_init); + ++static const struct sun6i_rtc_clk_data sun50i_h616_rtc_data = { ++ .rc_osc_rate = 16000000, ++ .fixed_prescaler = 32, ++ .has_prescaler = 1, ++ .has_out_clk = 1, ++ .export_iosc = 1, ++ .no_ext_losc = 1, ++}; ++ ++static void __init sun50i_h616_rtc_clk_init(struct device_node *node) ++{ ++ sun6i_rtc_clk_init(node, &sun50i_h616_rtc_data); ++} ++ ++CLK_OF_DECLARE_DRIVER(sun50i_h616_rtc_clk, "allwinner,sun50i-h616-rtc", ++ sun50i_h616_rtc_clk_init); ++ + /* + * The R40 user manual is self-conflicting on whether the prescaler is + * fixed or configurable. The clock diagram shows it as fixed, but there +@@ -797,6 +814,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { + { .compatible = "allwinner,sun8i-v3-rtc" }, + { .compatible = "allwinner,sun50i-h5-rtc" }, + { .compatible = "allwinner,sun50i-h6-rtc" }, ++ { .compatible = "allwinner,sun50i-h616-rtc", ++ .data = (void *)RTC_LINEAR_DAY }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_0023-arm64-dts-allwinner-h616-Add-RTC-and-its-32K-clock.patch b/patch/kernel/archive/sunxi-5.12/h616_0023-arm64-dts-allwinner-h616-Add-RTC-and-its-32K-clock.patch new file mode 100644 index 0000000000..6babdf55c5 --- /dev/null +++ b/patch/kernel/archive/sunxi-5.12/h616_0023-arm64-dts-allwinner-h616-Add-RTC-and-its-32K-clock.patch @@ -0,0 +1,93 @@ +From d62a3e6540d0f8b2ff5444ba003e2074a714c452 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:37:38 +0100 +Subject: [PATCH 23/23] arm64: dts: allwinner: h616: Add RTC and its 32K clock + +The RTC in the new Allwinner H616 SoC has some extra "features", +also it does not support a 32768 Hz oscillator input anymore. + +Add the DT node describing it and change the preliminary fixed clock +to be the actual RTC provided clock. + +Signed-off-by: Andre Przywara +--- + .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 26 ++++++++++--------- + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +index 7681f2a68dee..c55933f32d99 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +@@ -63,20 +63,13 @@ secmon_reserved: secmon@40000000 { + }; + }; + +- osc24M: osc24M-clk { ++ osc24M: osc24M_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + +- osc32k_int: osc32k-int { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- clock-output-names = "osc32k-int"; +- }; +- + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = , +@@ -129,7 +122,7 @@ sram_c: sram@28000 { + ccu: clock@3001000 { + compatible = "allwinner,sun50i-h616-ccu"; + reg = <0x03001000 0x1000>; +- clocks = <&osc24M>, <&osc32k_int>, <&osc32k_int>; ++ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>; + clock-names = "hosc", "losc", "iosc"; + #clock-cells = <1>; + #reset-cells = <1>; +@@ -155,7 +148,7 @@ pio: pinctrl@300b000 { + , + , + ; +- clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k_int>; ++ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; +@@ -654,10 +647,19 @@ ohci3: usb@5311400 { + status = "disabled"; + }; + ++ rtc: rtc@7000000 { ++ compatible = "allwinner,sun50i-h616-rtc"; ++ reg = <0x07000000 0x400>; ++ interrupts = , ++ ; ++ clock-output-names = "osc32k", "osc32k-out", "iosc"; ++ #clock-cells = <1>; ++ }; ++ + r_ccu: clock@7010000 { + compatible = "allwinner,sun50i-h616-r-ccu"; + reg = <0x07010000 0x210>; +- clocks = <&osc24M>, <&osc32k_int>, <&osc32k_int>, ++ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, + <&ccu CLK_PLL_PERIPH0>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; + #clock-cells = <1>; +@@ -668,7 +670,7 @@ r_pio: pinctrl@7022000 { + compatible = "allwinner,sun50i-h616-r-pinctrl"; + reg = <0x07022000 0x400>; + interrupts = ; +- clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k_int>; ++ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; +-- +2.25.1 + diff --git a/patch/kernel/archive/sunxi-5.12/h616_999_fix-broken-hunks.patch b/patch/kernel/archive/sunxi-5.12/h616_999_fix-broken-hunks.patch deleted file mode 100644 index 4d258492bd..0000000000 --- a/patch/kernel/archive/sunxi-5.12/h616_999_fix-broken-hunks.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 7977d7caf7136da4254b9affb6c7a96ee5f4597d Mon Sep 17 00:00:00 2001 -From: EvilOlaf -Date: Sun, 6 Dec 2020 08:17:30 +0100 -Subject: [PATCH] fix broken patches from H616 series - -Signed-off-by: EvilOlaf ---- - arch/arm64/boot/dts/allwinner/Makefile | 1 + - drivers/mmc/host/sunxi-mmc.c | 2 ++ - 2 files changed, 3 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile -index d3eab3b57..e71c04a80 100644 ---- a/arch/arm64/boot/dts/allwinner/Makefile -+++ b/arch/arm64/boot/dts/allwinner/Makefile -@@ -44,5 +44,6 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb -+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb - - subdir-y := $(dts-dirs) overlay --- -Created with Armbian build tools https://github.com/armbian/build diff --git a/patch/kernel/archive/sunxi-5.12/patch-5.12.9-10.patch b/patch/kernel/archive/sunxi-5.12/patch-5.12.9-10.patch deleted file mode 100644 index d2017851fe..0000000000 --- a/patch/kernel/archive/sunxi-5.12/patch-5.12.9-10.patch +++ /dev/null @@ -1,6796 +0,0 @@ -diff --git a/Makefile b/Makefile -index d53577db10858..ebc02c56db03c 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - VERSION = 5 - PATCHLEVEL = 12 --SUBLEVEL = 9 -+SUBLEVEL = 10 - EXTRAVERSION = - NAME = Frozen Wasteland - -diff --git a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi -index 7d2c72562c735..9148a01ed6d9f 100644 ---- a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi -+++ b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi -@@ -105,9 +105,13 @@ - phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; - phy-reset-duration = <20>; - phy-supply = <&sw2_reg>; -- phy-handle = <ðphy0>; - status = "okay"; - -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ - mdio { - #address-cells = <1>; - #size-cells = <0>; -diff --git a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi -index 236fc205c3890..d0768ae429faa 100644 ---- a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi -+++ b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi -@@ -406,6 +406,18 @@ - vin-supply = <&sw1_reg>; - }; - -+®_pu { -+ vin-supply = <&sw1_reg>; -+}; -+ -+®_vdd1p1 { -+ vin-supply = <&sw2_reg>; -+}; -+ -+®_vdd2p5 { -+ vin-supply = <&sw2_reg>; -+}; -+ - &uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -diff --git a/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi b/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi -index 828cf3e39784a..c4e146f3341bb 100644 ---- a/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi -+++ b/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi -@@ -126,7 +126,7 @@ - compatible = "nxp,pca8574"; - reg = <0x3a>; - gpio-controller; -- #gpio-cells = <1>; -+ #gpio-cells = <2>; - }; - }; - -diff --git a/arch/arm/boot/dts/imx7d-meerkat96.dts b/arch/arm/boot/dts/imx7d-meerkat96.dts -index 5339210b63d0f..dd8003bd1fc09 100644 ---- a/arch/arm/boot/dts/imx7d-meerkat96.dts -+++ b/arch/arm/boot/dts/imx7d-meerkat96.dts -@@ -193,7 +193,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc1>; - keep-power-in-suspend; -- tuning-step = <2>; -+ fsl,tuning-step = <2>; - vmmc-supply = <®_3p3v>; - no-1-8-v; - broken-cd; -diff --git a/arch/arm/boot/dts/imx7d-pico.dtsi b/arch/arm/boot/dts/imx7d-pico.dtsi -index e57da0d32b98d..e519897fae082 100644 ---- a/arch/arm/boot/dts/imx7d-pico.dtsi -+++ b/arch/arm/boot/dts/imx7d-pico.dtsi -@@ -351,7 +351,7 @@ - pinctrl-2 = <&pinctrl_usdhc1_200mhz>; - cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; - bus-width = <4>; -- tuning-step = <2>; -+ fsl,tuning-step = <2>; - vmmc-supply = <®_3p3v>; - wakeup-source; - no-1-8-v; -diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c -index c40cf5ef86079..977b0b744c22a 100644 ---- a/arch/arm/mach-omap1/board-h2.c -+++ b/arch/arm/mach-omap1/board-h2.c -@@ -320,7 +320,7 @@ static int tps_setup(struct i2c_client *client, void *context) - { - if (!IS_BUILTIN(CONFIG_TPS65010)) - return -ENOSYS; -- -+ - tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | - TPS_LDO1_ENABLE | TPS_VLDO1_3_0V); - -@@ -394,6 +394,8 @@ static void __init h2_init(void) - BUG_ON(gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0); - gpio_direction_input(H2_NAND_RB_GPIO_PIN); - -+ gpiod_add_lookup_table(&isp1301_gpiod_table); -+ - omap_cfg_reg(L3_1610_FLASH_CS2B_OE); - omap_cfg_reg(M8_1610_FLASH_CS2B_WE); - -diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index cdfd5fed457ff..a3fdffcd1ce8b 100644 ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -168,6 +168,7 @@ config ARCH_MEDIATEK - - config ARCH_MESON - bool "Amlogic Platforms" -+ select COMMON_CLK - select MESON_IRQ_GPIO - help - This enables support for the arm64 based Amlogic SoCs -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts -index 6c309b97587df..e8d31279b7a34 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts -@@ -46,7 +46,8 @@ - eee-broken-100tx; - qca,clk-out-frequency = <125000000>; - qca,clk-out-strength = ; -- vddio-supply = <&vddh>; -+ qca,keep-pll-enabled; -+ vddio-supply = <&vddio>; - - vddio: vddio-regulator { - regulator-name = "VDDIO"; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts -index df212ed5bb942..e65d1c477e2ce 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts -@@ -31,11 +31,10 @@ - reg = <0x4>; - eee-broken-1000t; - eee-broken-100tx; -- - qca,clk-out-frequency = <125000000>; - qca,clk-out-strength = ; -- -- vddio-supply = <&vddh>; -+ qca,keep-pll-enabled; -+ vddio-supply = <&vddio>; - - vddio: vddio-regulator { - regulator-name = "VDDIO"; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -index 262fbad8f0ec5..1b264e5e947ac 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -@@ -201,8 +201,8 @@ - ddr: memory-controller@1080000 { - compatible = "fsl,qoriq-memory-controller"; - reg = <0x0 0x1080000 0x0 0x1000>; -- interrupts = ; -- big-endian; -+ interrupts = ; -+ little-endian; - }; - - dcfg: syscon@1e00000 { -diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts -index 631e01c1b9fd4..be1e7d6f0ecb5 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts -+++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts -@@ -88,11 +88,11 @@ - pinctrl-0 = <&pinctrl_codec2>; - reg = <0x18>; - #sound-dai-cells = <0>; -- HPVDD-supply = <®_3p3v>; -- SPRVDD-supply = <®_3p3v>; -- SPLVDD-supply = <®_3p3v>; -- AVDD-supply = <®_3p3v>; -- IOVDD-supply = <®_3p3v>; -+ HPVDD-supply = <®_gen_3p3>; -+ SPRVDD-supply = <®_gen_3p3>; -+ SPLVDD-supply = <®_gen_3p3>; -+ AVDD-supply = <®_gen_3p3>; -+ IOVDD-supply = <®_gen_3p3>; - DVDD-supply = <&vgen4_reg>; - reset-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; - }; -diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi -index 4dc8383478ee2..a08a568c31d92 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi -@@ -45,8 +45,8 @@ - reg_12p0_main: regulator-12p0-main { - compatible = "regulator-fixed"; - regulator-name = "12V_MAIN"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -+ regulator-min-microvolt = <12000000>; -+ regulator-max-microvolt = <12000000>; - regulator-always-on; - }; - -@@ -77,15 +77,6 @@ - regulator-always-on; - }; - -- reg_3p3v: regulator-3p3v { -- compatible = "regulator-fixed"; -- vin-supply = <®_3p3_main>; -- regulator-name = "GEN_3V3"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- - reg_usdhc2_vmmc: regulator-vsd-3v3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_usdhc2>; -@@ -415,11 +406,11 @@ - pinctrl-0 = <&pinctrl_codec1>; - reg = <0x18>; - #sound-dai-cells = <0>; -- HPVDD-supply = <®_3p3v>; -- SPRVDD-supply = <®_3p3v>; -- SPLVDD-supply = <®_3p3v>; -- AVDD-supply = <®_3p3v>; -- IOVDD-supply = <®_3p3v>; -+ HPVDD-supply = <®_gen_3p3>; -+ SPRVDD-supply = <®_gen_3p3>; -+ SPLVDD-supply = <®_gen_3p3>; -+ AVDD-supply = <®_gen_3p3>; -+ IOVDD-supply = <®_gen_3p3>; - DVDD-supply = <&vgen4_reg>; - reset-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>; - }; -diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -index 17477ab0fd8e1..3398f174f09b3 100644 ---- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -@@ -85,6 +85,8 @@ - #size-cells = <2>; - ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; - ti,sci-dev-id = <199>; -+ dma-coherent; -+ dma-ranges; - - main_navss_intr: interrupt-controller1 { - compatible = "ti,sci-intr"; -diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h -index a8578d650bb67..f362f72bcb508 100644 ---- a/arch/arm64/include/asm/kvm_asm.h -+++ b/arch/arm64/include/asm/kvm_asm.h -@@ -57,6 +57,7 @@ - #define __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 12 - #define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13 - #define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14 -+#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 15 - - #ifndef __ASSEMBLY__ - -diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c -index 84b5f79c9eab4..7730b81aad6d1 100644 ---- a/arch/arm64/kvm/arm.c -+++ b/arch/arm64/kvm/arm.c -@@ -715,11 +715,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) - return ret; - } - -- if (run->immediate_exit) -- return -EINTR; -- - vcpu_load(vcpu); - -+ if (run->immediate_exit) { -+ ret = -EINTR; -+ goto out; -+ } -+ - kvm_sigset_activate(vcpu); - - ret = 1; -@@ -892,6 +894,18 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) - - kvm_sigset_deactivate(vcpu); - -+out: -+ /* -+ * In the unlikely event that we are returning to userspace -+ * with pending exceptions or PC adjustment, commit these -+ * adjustments in order to give userspace a consistent view of -+ * the vcpu state. Note that this relies on __kvm_adjust_pc() -+ * being preempt-safe on VHE. -+ */ -+ if (unlikely(vcpu->arch.flags & (KVM_ARM64_PENDING_EXCEPTION | -+ KVM_ARM64_INCREMENT_PC))) -+ kvm_call_hyp(__kvm_adjust_pc, vcpu); -+ - vcpu_put(vcpu); - return ret; - } -diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c -index 0812a496725f6..11541b94b328f 100644 ---- a/arch/arm64/kvm/hyp/exception.c -+++ b/arch/arm64/kvm/hyp/exception.c -@@ -331,8 +331,8 @@ static void kvm_inject_exception(struct kvm_vcpu *vcpu) - } - - /* -- * Adjust the guest PC on entry, depending on flags provided by EL1 -- * for the purpose of emulation (MMIO, sysreg) or exception injection. -+ * Adjust the guest PC (and potentially exception state) depending on -+ * flags provided by the emulation code. - */ - void __kvm_adjust_pc(struct kvm_vcpu *vcpu) - { -diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c -index 936328207bde0..e52582e140873 100644 ---- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c -+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c -@@ -25,6 +25,13 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt) - cpu_reg(host_ctxt, 1) = __kvm_vcpu_run(kern_hyp_va(vcpu)); - } - -+static void handle___kvm_adjust_pc(struct kvm_cpu_context *host_ctxt) -+{ -+ DECLARE_REG(struct kvm_vcpu *, vcpu, host_ctxt, 1); -+ -+ __kvm_adjust_pc(kern_hyp_va(vcpu)); -+} -+ - static void handle___kvm_flush_vm_context(struct kvm_cpu_context *host_ctxt) - { - __kvm_flush_vm_context(); -@@ -112,6 +119,7 @@ typedef void (*hcall_t)(struct kvm_cpu_context *); - - static const hcall_t host_hcall[] = { - HANDLE_FUNC(__kvm_vcpu_run), -+ HANDLE_FUNC(__kvm_adjust_pc), - HANDLE_FUNC(__kvm_flush_vm_context), - HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa), - HANDLE_FUNC(__kvm_tlb_flush_vmid), -diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c -index 7719d632df8df..1754498b07174 100644 ---- a/arch/mips/mm/cache.c -+++ b/arch/mips/mm/cache.c -@@ -157,31 +157,29 @@ unsigned long _page_cachable_default; - EXPORT_SYMBOL(_page_cachable_default); - - #define PM(p) __pgprot(_page_cachable_default | (p)) --#define PVA(p) PM(_PAGE_VALID | _PAGE_ACCESSED | (p)) - - static inline void setup_protection_map(void) - { - protection_map[0] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ); -- protection_map[1] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC); -- protection_map[2] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ); -- protection_map[3] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC); -- protection_map[4] = PVA(_PAGE_PRESENT); -- protection_map[5] = PVA(_PAGE_PRESENT); -- protection_map[6] = PVA(_PAGE_PRESENT); -- protection_map[7] = PVA(_PAGE_PRESENT); -+ protection_map[1] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC); -+ protection_map[2] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ); -+ protection_map[3] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC); -+ protection_map[4] = PM(_PAGE_PRESENT); -+ protection_map[5] = PM(_PAGE_PRESENT); -+ protection_map[6] = PM(_PAGE_PRESENT); -+ protection_map[7] = PM(_PAGE_PRESENT); - - protection_map[8] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ); -- protection_map[9] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC); -- protection_map[10] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | -+ protection_map[9] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC); -+ protection_map[10] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | - _PAGE_NO_READ); -- protection_map[11] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE); -- protection_map[12] = PVA(_PAGE_PRESENT); -- protection_map[13] = PVA(_PAGE_PRESENT); -- protection_map[14] = PVA(_PAGE_PRESENT); -- protection_map[15] = PVA(_PAGE_PRESENT); -+ protection_map[11] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE); -+ protection_map[12] = PM(_PAGE_PRESENT); -+ protection_map[13] = PM(_PAGE_PRESENT); -+ protection_map[14] = PM(_PAGE_PRESENT | _PAGE_WRITE); -+ protection_map[15] = PM(_PAGE_PRESENT | _PAGE_WRITE); - } - --#undef _PVA - #undef PM - - void cpu_cache_init(void) -diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c -index 01ab2163659e4..e8c2a6373157d 100644 ---- a/arch/powerpc/kernel/kprobes.c -+++ b/arch/powerpc/kernel/kprobes.c -@@ -108,7 +108,6 @@ int arch_prepare_kprobe(struct kprobe *p) - int ret = 0; - struct kprobe *prev; - struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr); -- struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1)); - - if ((unsigned long)p->addr & 0x03) { - printk("Attempt to register kprobe at an unaligned address\n"); -@@ -116,7 +115,8 @@ int arch_prepare_kprobe(struct kprobe *p) - } else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) { - printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n"); - ret = -EINVAL; -- } else if (ppc_inst_prefixed(prefix)) { -+ } else if ((unsigned long)p->addr & ~PAGE_MASK && -+ ppc_inst_prefixed(ppc_inst_read((struct ppc_inst *)(p->addr - 1)))) { - printk("Cannot register a kprobe on the second word of prefixed instruction\n"); - ret = -EINVAL; - } -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 208a053c9adfd..60c5bc0c130cf 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -4418,7 +4418,6 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu) - mtspr(SPRN_EBBRR, ebb_regs[1]); - mtspr(SPRN_BESCR, ebb_regs[2]); - mtspr(SPRN_TAR, user_tar); -- mtspr(SPRN_FSCR, current->thread.fscr); - } - mtspr(SPRN_VRSAVE, user_vrsave); - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index 5e634db4809bf..004f0d4e665f8 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -59,6 +59,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) - #define STACK_SLOT_UAMOR (SFS-88) - #define STACK_SLOT_DAWR1 (SFS-96) - #define STACK_SLOT_DAWRX1 (SFS-104) -+#define STACK_SLOT_FSCR (SFS-112) - /* the following is used by the P9 short path */ - #define STACK_SLOT_NVGPRS (SFS-152) /* 18 gprs */ - -@@ -686,6 +687,8 @@ BEGIN_FTR_SECTION - std r6, STACK_SLOT_DAWR0(r1) - std r7, STACK_SLOT_DAWRX0(r1) - std r8, STACK_SLOT_IAMR(r1) -+ mfspr r5, SPRN_FSCR -+ std r5, STACK_SLOT_FSCR(r1) - END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - BEGIN_FTR_SECTION - mfspr r6, SPRN_DAWR1 -@@ -1663,6 +1666,10 @@ FTR_SECTION_ELSE - ld r7, STACK_SLOT_HFSCR(r1) - mtspr SPRN_HFSCR, r7 - ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) -+BEGIN_FTR_SECTION -+ ld r5, STACK_SLOT_FSCR(r1) -+ mtspr SPRN_FSCR, r5 -+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - /* - * Restore various registers to 0, where non-zero values - * set by the guest could disrupt the host. -diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile -index ca2b40dfd24b8..24d936c147cdf 100644 ---- a/arch/riscv/kernel/vdso/Makefile -+++ b/arch/riscv/kernel/vdso/Makefile -@@ -23,7 +23,7 @@ ifneq ($(c-gettimeofday-y),) - endif - - # Build rules --targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o -+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S - obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) - - obj-y += vdso.o vdso-syms.o -@@ -41,7 +41,7 @@ KASAN_SANITIZE := n - $(obj)/vdso.o: $(obj)/vdso.so - - # link rule for the .so file, .lds has to be first --$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE -+$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE - $(call if_changed,vdsold) - LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \ - --build-id=sha1 --hash-style=both --eh-frame-hdr -diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h -index 412b51e059c80..48067af946785 100644 ---- a/arch/x86/include/asm/apic.h -+++ b/arch/x86/include/asm/apic.h -@@ -174,6 +174,7 @@ static inline int apic_is_clustered_box(void) - extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask); - extern void lapic_assign_system_vectors(void); - extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace); -+extern void lapic_update_legacy_vectors(void); - extern void lapic_online(void); - extern void lapic_offline(void); - extern bool apic_needs_pit(void); -diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h -index b7dd944dc8673..8f28fafa98b32 100644 ---- a/arch/x86/include/asm/disabled-features.h -+++ b/arch/x86/include/asm/disabled-features.h -@@ -56,11 +56,8 @@ - # define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31)) - #endif - --#ifdef CONFIG_IOMMU_SUPPORT --# define DISABLE_ENQCMD 0 --#else --# define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31)) --#endif -+/* Force disable because it's broken beyond repair */ -+#define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31)) - - #ifdef CONFIG_X86_SGX - # define DISABLE_SGX 0 -diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h -index ed33a14188f66..23bef08a83880 100644 ---- a/arch/x86/include/asm/fpu/api.h -+++ b/arch/x86/include/asm/fpu/api.h -@@ -106,10 +106,6 @@ extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name); - */ - #define PASID_DISABLED 0 - --#ifdef CONFIG_IOMMU_SUPPORT --/* Update current's PASID MSR/state by mm's PASID. */ --void update_pasid(void); --#else - static inline void update_pasid(void) { } --#endif -+ - #endif /* _ASM_X86_FPU_API_H */ -diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h -index 8d33ad80704f2..ceeba9f631722 100644 ---- a/arch/x86/include/asm/fpu/internal.h -+++ b/arch/x86/include/asm/fpu/internal.h -@@ -584,13 +584,6 @@ static inline void switch_fpu_finish(struct fpu *new_fpu) - pkru_val = pk->pkru; - } - __write_pkru(pkru_val); -- -- /* -- * Expensive PASID MSR write will be avoided in update_pasid() because -- * TIF_NEED_FPU_LOAD was set. And the PASID state won't be updated -- * unless it's different from mm->pasid to reduce overhead. -- */ -- update_pasid(); - } - - #endif /* _ASM_X86_FPU_INTERNAL_H */ -diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h -index 3381198525126..69299878b200a 100644 ---- a/arch/x86/include/asm/kvm_para.h -+++ b/arch/x86/include/asm/kvm_para.h -@@ -7,8 +7,6 @@ - #include - #include - --extern void kvmclock_init(void); -- - #ifdef CONFIG_KVM_GUEST - bool kvm_check_and_clear_guest_paused(void); - #else -@@ -86,13 +84,14 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, - } - - #ifdef CONFIG_KVM_GUEST -+void kvmclock_init(void); -+void kvmclock_disable(void); - bool kvm_para_available(void); - unsigned int kvm_arch_para_features(void); - unsigned int kvm_arch_para_hints(void); - void kvm_async_pf_task_wait_schedule(u32 token); - void kvm_async_pf_task_wake(u32 token); - u32 kvm_read_and_reset_apf_flags(void); --void kvm_disable_steal_time(void); - bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token); - - DECLARE_STATIC_KEY_FALSE(kvm_async_pf_enabled); -@@ -137,11 +136,6 @@ static inline u32 kvm_read_and_reset_apf_flags(void) - return 0; - } - --static inline void kvm_disable_steal_time(void) --{ -- return; --} -- - static __always_inline bool kvm_handle_async_pf(struct pt_regs *regs, u32 token) - { - return false; -diff --git a/arch/x86/include/asm/thermal.h b/arch/x86/include/asm/thermal.h -index ddbdefd5b94f1..91a7b6687c3b9 100644 ---- a/arch/x86/include/asm/thermal.h -+++ b/arch/x86/include/asm/thermal.h -@@ -3,11 +3,13 @@ - #define _ASM_X86_THERMAL_H - - #ifdef CONFIG_X86_THERMAL_VECTOR -+void therm_lvt_init(void); - void intel_init_thermal(struct cpuinfo_x86 *c); - bool x86_thermal_enabled(void); - void intel_thermal_interrupt(void); - #else --static inline void intel_init_thermal(struct cpuinfo_x86 *c) { } -+static inline void therm_lvt_init(void) { } -+static inline void intel_init_thermal(struct cpuinfo_x86 *c) { } - #endif - - #endif /* _ASM_X86_THERMAL_H */ -diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c -index 4f26700f314d9..b967a2ba7494a 100644 ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -2604,6 +2604,7 @@ static void __init apic_bsp_setup(bool upmode) - end_local_APIC_setup(); - irq_remap_enable_fault_handling(); - setup_IO_APIC(); -+ lapic_update_legacy_vectors(); - } - - #ifdef CONFIG_UP_LATE_INIT -diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c -index 3c9c7492252f8..8c97a3468affa 100644 ---- a/arch/x86/kernel/apic/vector.c -+++ b/arch/x86/kernel/apic/vector.c -@@ -730,6 +730,26 @@ void lapic_assign_legacy_vector(unsigned int irq, bool replace) - irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace); - } - -+void __init lapic_update_legacy_vectors(void) -+{ -+ unsigned int i; -+ -+ if (IS_ENABLED(CONFIG_X86_IO_APIC) && nr_ioapics > 0) -+ return; -+ -+ /* -+ * If the IO/APIC is disabled via config, kernel command line or -+ * lack of enumeration then all legacy interrupts are routed -+ * through the PIC. Make sure that they are marked as legacy -+ * vectors. PIC_CASCADE_IRQ has already been marked in -+ * lapic_assign_system_vectors(). -+ */ -+ for (i = 0; i < nr_legacy_irqs(); i++) { -+ if (i != PIC_CASCADE_IR) -+ lapic_assign_legacy_vector(i, true); -+ } -+} -+ - void __init lapic_assign_system_vectors(void) - { - unsigned int i, vector = 0; -diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c -index 683749b80ae28..2ad57cc14b83f 100644 ---- a/arch/x86/kernel/fpu/xstate.c -+++ b/arch/x86/kernel/fpu/xstate.c -@@ -1402,60 +1402,3 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns, - return 0; - } - #endif /* CONFIG_PROC_PID_ARCH_STATUS */ -- --#ifdef CONFIG_IOMMU_SUPPORT --void update_pasid(void) --{ -- u64 pasid_state; -- u32 pasid; -- -- if (!cpu_feature_enabled(X86_FEATURE_ENQCMD)) -- return; -- -- if (!current->mm) -- return; -- -- pasid = READ_ONCE(current->mm->pasid); -- /* Set the valid bit in the PASID MSR/state only for valid pasid. */ -- pasid_state = pasid == PASID_DISABLED ? -- pasid : pasid | MSR_IA32_PASID_VALID; -- -- /* -- * No need to hold fregs_lock() since the task's fpstate won't -- * be changed by others (e.g. ptrace) while the task is being -- * switched to or is in IPI. -- */ -- if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { -- /* The MSR is active and can be directly updated. */ -- wrmsrl(MSR_IA32_PASID, pasid_state); -- } else { -- struct fpu *fpu = ¤t->thread.fpu; -- struct ia32_pasid_state *ppasid_state; -- struct xregs_state *xsave; -- -- /* -- * The CPU's xstate registers are not currently active. Just -- * update the PASID state in the memory buffer here. The -- * PASID MSR will be loaded when returning to user mode. -- */ -- xsave = &fpu->state.xsave; -- xsave->header.xfeatures |= XFEATURE_MASK_PASID; -- ppasid_state = get_xsave_addr(xsave, XFEATURE_PASID); -- /* -- * Since XFEATURE_MASK_PASID is set in xfeatures, ppasid_state -- * won't be NULL and no need to check its value. -- * -- * Only update the task's PASID state when it's different -- * from the mm's pasid. -- */ -- if (ppasid_state->pasid != pasid_state) { -- /* -- * Invalid fpregs so that state restoring will pick up -- * the PASID state. -- */ -- __fpu_invalidate_fpregs_state(fpu); -- ppasid_state->pasid = pasid_state; -- } -- } --} --#endif /* CONFIG_IOMMU_SUPPORT */ -diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c -index 78bb0fae39826..919411a0117df 100644 ---- a/arch/x86/kernel/kvm.c -+++ b/arch/x86/kernel/kvm.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -37,6 +38,7 @@ - #include - #include - #include -+#include - #include - - DEFINE_STATIC_KEY_FALSE(kvm_async_pf_enabled); -@@ -374,6 +376,14 @@ static void kvm_pv_disable_apf(void) - pr_info("Unregister pv shared memory for cpu %d\n", smp_processor_id()); - } - -+static void kvm_disable_steal_time(void) -+{ -+ if (!has_steal_clock) -+ return; -+ -+ wrmsr(MSR_KVM_STEAL_TIME, 0, 0); -+} -+ - static void kvm_pv_guest_cpu_reboot(void *unused) - { - /* -@@ -416,14 +426,6 @@ static u64 kvm_steal_clock(int cpu) - return steal; - } - --void kvm_disable_steal_time(void) --{ -- if (!has_steal_clock) -- return; -- -- wrmsr(MSR_KVM_STEAL_TIME, 0, 0); --} -- - static inline void __set_percpu_decrypted(void *ptr, unsigned long size) - { - early_set_memory_decrypted((unsigned long) ptr, size); -@@ -460,6 +462,27 @@ static bool pv_tlb_flush_supported(void) - - static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask); - -+static void kvm_guest_cpu_offline(bool shutdown) -+{ -+ kvm_disable_steal_time(); -+ if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) -+ wrmsrl(MSR_KVM_PV_EOI_EN, 0); -+ kvm_pv_disable_apf(); -+ if (!shutdown) -+ apf_task_wake_all(); -+ kvmclock_disable(); -+} -+ -+static int kvm_cpu_online(unsigned int cpu) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ kvm_guest_cpu_init(); -+ local_irq_restore(flags); -+ return 0; -+} -+ - #ifdef CONFIG_SMP - - static bool pv_ipi_supported(void) -@@ -587,29 +610,46 @@ static void __init kvm_smp_prepare_boot_cpu(void) - kvm_spinlock_init(); - } - --static void kvm_guest_cpu_offline(void) -+static int kvm_cpu_down_prepare(unsigned int cpu) - { -- kvm_disable_steal_time(); -- if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) -- wrmsrl(MSR_KVM_PV_EOI_EN, 0); -- kvm_pv_disable_apf(); -- apf_task_wake_all(); -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ kvm_guest_cpu_offline(false); -+ local_irq_restore(flags); -+ return 0; - } - --static int kvm_cpu_online(unsigned int cpu) -+#endif -+ -+static int kvm_suspend(void) - { -- local_irq_disable(); -- kvm_guest_cpu_init(); -- local_irq_enable(); -+ kvm_guest_cpu_offline(false); -+ - return 0; - } - --static int kvm_cpu_down_prepare(unsigned int cpu) -+static void kvm_resume(void) - { -- local_irq_disable(); -- kvm_guest_cpu_offline(); -- local_irq_enable(); -- return 0; -+ kvm_cpu_online(raw_smp_processor_id()); -+} -+ -+static struct syscore_ops kvm_syscore_ops = { -+ .suspend = kvm_suspend, -+ .resume = kvm_resume, -+}; -+ -+/* -+ * After a PV feature is registered, the host will keep writing to the -+ * registered memory location. If the guest happens to shutdown, this memory -+ * won't be valid. In cases like kexec, in which you install a new kernel, this -+ * means a random memory location will be kept being written. -+ */ -+#ifdef CONFIG_KEXEC_CORE -+static void kvm_crash_shutdown(struct pt_regs *regs) -+{ -+ kvm_guest_cpu_offline(true); -+ native_machine_crash_shutdown(regs); - } - #endif - -@@ -681,6 +721,12 @@ static void __init kvm_guest_init(void) - kvm_guest_cpu_init(); - #endif - -+#ifdef CONFIG_KEXEC_CORE -+ machine_ops.crash_shutdown = kvm_crash_shutdown; -+#endif -+ -+ register_syscore_ops(&kvm_syscore_ops); -+ - /* - * Hard lockup detection is enabled by default. Disable it, as guests - * can get false positives too easily, for example if the host is -diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c -index 1fc0962c89c08..b825c87c12ef7 100644 ---- a/arch/x86/kernel/kvmclock.c -+++ b/arch/x86/kernel/kvmclock.c -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - - static int kvmclock __initdata = 1; -@@ -203,28 +202,9 @@ static void kvm_setup_secondary_clock(void) - } - #endif - --/* -- * After the clock is registered, the host will keep writing to the -- * registered memory location. If the guest happens to shutdown, this memory -- * won't be valid. In cases like kexec, in which you install a new kernel, this -- * means a random memory location will be kept being written. So before any -- * kind of shutdown from our side, we unregister the clock by writing anything -- * that does not have the 'enable' bit set in the msr -- */ --#ifdef CONFIG_KEXEC_CORE --static void kvm_crash_shutdown(struct pt_regs *regs) --{ -- native_write_msr(msr_kvm_system_time, 0, 0); -- kvm_disable_steal_time(); -- native_machine_crash_shutdown(regs); --} --#endif -- --static void kvm_shutdown(void) -+void kvmclock_disable(void) - { - native_write_msr(msr_kvm_system_time, 0, 0); -- kvm_disable_steal_time(); -- native_machine_shutdown(); - } - - static void __init kvmclock_init_mem(void) -@@ -351,10 +331,6 @@ void __init kvmclock_init(void) - #endif - x86_platform.save_sched_clock_state = kvm_save_sched_clock_state; - x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state; -- machine_ops.shutdown = kvm_shutdown; --#ifdef CONFIG_KEXEC_CORE -- machine_ops.crash_shutdown = kvm_crash_shutdown; --#endif - kvm_get_preset_lpj(); - - /* -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index ccab6cf91283d..e79f21d13a0d7 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -44,6 +44,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1220,6 +1221,14 @@ void __init setup_arch(char **cmdline_p) - - x86_init.timers.wallclock_init(); - -+ /* -+ * This needs to run before setup_local_APIC() which soft-disables the -+ * local APIC temporarily and that masks the thermal LVT interrupt, -+ * leading to softlockups on machines which have configured SMI -+ * interrupt delivery. -+ */ -+ therm_lvt_init(); -+ - mcheck_init(); - - register_refined_jiffies(CLOCK_TICK_RATE); -diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c -index 9a6825feaf53f..30569bbbca9ac 100644 ---- a/arch/x86/kvm/svm/svm.c -+++ b/arch/x86/kvm/svm/svm.c -@@ -2532,7 +2532,7 @@ static int cr_interception(struct vcpu_svm *svm) - err = 0; - if (cr >= 16) { /* mov to cr */ - cr -= 16; -- val = kvm_register_read(&svm->vcpu, reg); -+ val = kvm_register_readl(&svm->vcpu, reg); - trace_kvm_cr_write(cr, val); - switch (cr) { - case 0: -@@ -2578,7 +2578,7 @@ static int cr_interception(struct vcpu_svm *svm) - kvm_queue_exception(&svm->vcpu, UD_VECTOR); - return 1; - } -- kvm_register_write(&svm->vcpu, reg, val); -+ kvm_register_writel(&svm->vcpu, reg, val); - trace_kvm_cr_read(cr, val); - } - return kvm_complete_insn_gp(&svm->vcpu, err); -@@ -2643,11 +2643,11 @@ static int dr_interception(struct vcpu_svm *svm) - dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0; - if (dr >= 16) { /* mov to DRn */ - dr -= 16; -- val = kvm_register_read(&svm->vcpu, reg); -+ val = kvm_register_readl(&svm->vcpu, reg); - err = kvm_set_dr(&svm->vcpu, dr, val); - } else { - kvm_get_dr(&svm->vcpu, dr, &val); -- kvm_register_write(&svm->vcpu, reg, val); -+ kvm_register_writel(&svm->vcpu, reg, val); - } - - return kvm_complete_insn_gp(&svm->vcpu, err); -diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c -index a73347e2cdfc5..ea3d0b73731bc 100644 ---- a/arch/x86/mm/fault.c -+++ b/arch/x86/mm/fault.c -@@ -836,8 +836,8 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, - - if (si_code == SEGV_PKUERR) - force_sig_pkuerr((void __user *)address, pkey); -- -- force_sig_fault(SIGSEGV, si_code, (void __user *)address); -+ else -+ force_sig_fault(SIGSEGV, si_code, (void __user *)address); - - local_irq_disable(); - } -diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c -index a19374d261013..65f599e9075bc 100644 ---- a/arch/x86/mm/mem_encrypt_identity.c -+++ b/arch/x86/mm/mem_encrypt_identity.c -@@ -504,10 +504,6 @@ void __init sme_enable(struct boot_params *bp) - #define AMD_SME_BIT BIT(0) - #define AMD_SEV_BIT BIT(1) - -- /* Check the SEV MSR whether SEV or SME is enabled */ -- sev_status = __rdmsr(MSR_AMD64_SEV); -- feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT; -- - /* - * Check for the SME/SEV feature: - * CPUID Fn8000_001F[EAX] -@@ -519,11 +515,16 @@ void __init sme_enable(struct boot_params *bp) - eax = 0x8000001f; - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); -- if (!(eax & feature_mask)) -+ /* Check whether SEV or SME is supported */ -+ if (!(eax & (AMD_SEV_BIT | AMD_SME_BIT))) - return; - - me_mask = 1UL << (ebx & 0x3f); - -+ /* Check the SEV MSR whether SEV or SME is enabled */ -+ sev_status = __rdmsr(MSR_AMD64_SEV); -+ feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT; -+ - /* Check if memory encryption is enabled */ - if (feature_mask == AMD_SME_BIT) { - /* -diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c -index 624a26794d558..e5ba9795ec696 100644 ---- a/drivers/acpi/acpica/utdelete.c -+++ b/drivers/acpi/acpica/utdelete.c -@@ -285,6 +285,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) - } - break; - -+ case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: -+ -+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, -+ "***** Address handler %p\n", object)); -+ -+ acpi_os_delete_mutex(object->address_space.context_mutex); -+ break; -+ - default: - - break; -diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c -index 68145e326eb90..30e9b700273e1 100644 ---- a/drivers/bus/ti-sysc.c -+++ b/drivers/bus/ti-sysc.c -@@ -1334,6 +1334,34 @@ err_allow_idle: - return error; - } - -+static int sysc_reinit_module(struct sysc *ddata, bool leave_enabled) -+{ -+ struct device *dev = ddata->dev; -+ int error; -+ -+ /* Disable target module if it is enabled */ -+ if (ddata->enabled) { -+ error = sysc_runtime_suspend(dev); -+ if (error) -+ dev_warn(dev, "reinit suspend failed: %i\n", error); -+ } -+ -+ /* Enable target module */ -+ error = sysc_runtime_resume(dev); -+ if (error) -+ dev_warn(dev, "reinit resume failed: %i\n", error); -+ -+ if (leave_enabled) -+ return error; -+ -+ /* Disable target module if no leave_enabled was set */ -+ error = sysc_runtime_suspend(dev); -+ if (error) -+ dev_warn(dev, "reinit suspend failed: %i\n", error); -+ -+ return error; -+} -+ - static int __maybe_unused sysc_noirq_suspend(struct device *dev) - { - struct sysc *ddata; -@@ -1344,12 +1372,18 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev) - (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) - return 0; - -- return pm_runtime_force_suspend(dev); -+ if (!ddata->enabled) -+ return 0; -+ -+ ddata->needs_resume = 1; -+ -+ return sysc_runtime_suspend(dev); - } - - static int __maybe_unused sysc_noirq_resume(struct device *dev) - { - struct sysc *ddata; -+ int error = 0; - - ddata = dev_get_drvdata(dev); - -@@ -1357,7 +1391,19 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev) - (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) - return 0; - -- return pm_runtime_force_resume(dev); -+ if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_RESUME) { -+ error = sysc_reinit_module(ddata, ddata->needs_resume); -+ if (error) -+ dev_warn(dev, "noirq_resume failed: %i\n", error); -+ } else if (ddata->needs_resume) { -+ error = sysc_runtime_resume(dev); -+ if (error) -+ dev_warn(dev, "noirq_resume failed: %i\n", error); -+ } -+ -+ ddata->needs_resume = 0; -+ -+ return error; - } - - static const struct dev_pm_ops sysc_pm_ops = { -@@ -1408,9 +1454,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { - SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), - /* Uarts on omap4 and later */ - SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, -- SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), -+ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), - SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, -- SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), -+ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), - - /* Quirks that need to be set based on the module address */ - SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff, -@@ -1466,7 +1512,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { - SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, - 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), - SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, -- SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), -+ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | -+ SYSC_QUIRK_REINIT_ON_RESUME), - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, - SYSC_MODULE_QUIRK_WDT), - /* PRUSS on am3, am4 and am5 */ -diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c -index 07cf7977a0450..59f2104ffc771 100644 ---- a/drivers/dma/idxd/init.c -+++ b/drivers/dma/idxd/init.c -@@ -675,12 +675,12 @@ static int __init idxd_init_module(void) - * If the CPU does not support MOVDIR64B or ENQCMDS, there's no point in - * enumerating the device. We can not utilize it. - */ -- if (!boot_cpu_has(X86_FEATURE_MOVDIR64B)) { -+ if (!cpu_feature_enabled(X86_FEATURE_MOVDIR64B)) { - pr_warn("idxd driver failed to load without MOVDIR64B.\n"); - return -ENODEV; - } - -- if (!boot_cpu_has(X86_FEATURE_ENQCMD)) -+ if (!cpu_feature_enabled(X86_FEATURE_ENQCMD)) - pr_warn("Platform does not have ENQCMD(S) support.\n"); - else - support_enqcmd = true; -diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c -index e15d484b6a5a7..ea7ca74fc1730 100644 ---- a/drivers/firmware/efi/cper.c -+++ b/drivers/firmware/efi/cper.c -@@ -276,8 +276,7 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) - if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE)) - return 0; - -- n = 0; -- len = CPER_REC_LEN - 1; -+ len = CPER_REC_LEN; - dmi_memdev_name(mem->mem_dev_handle, &bank, &device); - if (bank && device) - n = snprintf(msg, len, "DIMM location: %s %s ", bank, device); -@@ -286,7 +285,6 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) - "DIMM location: not present. DMI handle: 0x%.4x ", - mem->mem_dev_handle); - -- msg[n] = '\0'; - return n; - } - -diff --git a/drivers/firmware/efi/fdtparams.c b/drivers/firmware/efi/fdtparams.c -index bb042ab7c2be6..e901f8564ca0c 100644 ---- a/drivers/firmware/efi/fdtparams.c -+++ b/drivers/firmware/efi/fdtparams.c -@@ -98,6 +98,9 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm) - BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name)); - BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params)); - -+ if (!fdt) -+ return 0; -+ - for (i = 0; i < ARRAY_SIZE(dt_params); i++) { - node = fdt_path_offset(fdt, dt_params[i].path); - if (node < 0) -diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c -index 4e81c6077188e..dd95f330fe6e1 100644 ---- a/drivers/firmware/efi/libstub/file.c -+++ b/drivers/firmware/efi/libstub/file.c -@@ -103,7 +103,7 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, - return 0; - - /* Skip any leading slashes */ -- while (cmdline[i] == L'/' || cmdline[i] == L'\\') -+ while (i < cmdline_len && (cmdline[i] == L'/' || cmdline[i] == L'\\')) - i++; - - while (--result_len > 0 && i < cmdline_len) { -diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c -index 5737cb0fcd44e..0a9aba5f9ceff 100644 ---- a/drivers/firmware/efi/memattr.c -+++ b/drivers/firmware/efi/memattr.c -@@ -67,11 +67,6 @@ static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out) - return false; - } - -- if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) { -- pr_warn("Entry attributes invalid: RO and XP bits both cleared\n"); -- return false; -- } -- - if (PAGE_SIZE > EFI_PAGE_SIZE && - (!PAGE_ALIGNED(in->phys_addr) || - !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) { -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c -index 0350205c48974..6819fe5612d9e 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c -@@ -337,7 +337,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, - { - struct amdgpu_ctx *ctx; - struct amdgpu_ctx_mgr *mgr; -- unsigned long ras_counter; - - if (!fpriv) - return -EINVAL; -@@ -362,21 +361,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, - if (atomic_read(&ctx->guilty)) - out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY; - -- /*query ue count*/ -- ras_counter = amdgpu_ras_query_error_count(adev, false); -- /*ras counter is monotonic increasing*/ -- if (ras_counter != ctx->ras_counter_ue) { -- out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE; -- ctx->ras_counter_ue = ras_counter; -- } -- -- /*query ce count*/ -- ras_counter = amdgpu_ras_query_error_count(adev, true); -- if (ras_counter != ctx->ras_counter_ce) { -- out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE; -- ctx->ras_counter_ce = ras_counter; -- } -- - mutex_unlock(&mgr->lock); - return 0; - } -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c -index a2ac44cc2a6da..e80cc2928b583 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c -@@ -944,6 +944,7 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev, - domains = amdgpu_display_supported_domains(drm_to_adev(dev), bo->flags); - if (obj->import_attach && !(domains & AMDGPU_GEM_DOMAIN_GTT)) { - drm_dbg_kms(dev, "Cannot create framebuffer from imported dma_buf\n"); -+ drm_gem_object_put(obj); - return ERR_PTR(-EINVAL); - } - -diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c -index dc947c8ffe213..e6c4a36eaf9ae 100644 ---- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c -+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c -@@ -187,14 +187,14 @@ static int jpeg_v2_5_hw_init(void *handle) - static int jpeg_v2_5_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- struct amdgpu_ring *ring; - int i; - -+ cancel_delayed_work_sync(&adev->vcn.idle_work); -+ - for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { - if (adev->jpeg.harvest_config & (1 << i)) - continue; - -- ring = &adev->jpeg.inst[i].ring_dec; - if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS)) - jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE); -diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c -index 1d354245678d5..2ea68c84e6b48 100644 ---- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c -@@ -159,9 +159,9 @@ static int jpeg_v3_0_hw_init(void *handle) - static int jpeg_v3_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- struct amdgpu_ring *ring; - -- ring = &adev->jpeg.inst->ring_dec; -+ cancel_delayed_work_sync(&adev->vcn.idle_work); -+ - if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS)) - jpeg_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE); -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -index 760859880c1ed..4eebf973a0658 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -@@ -357,6 +357,7 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) - - error: - dma_fence_put(fence); -+ amdgpu_bo_unpin(bo); - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c -index ebbc04ff5da06..90138469648a9 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c -@@ -367,15 +367,14 @@ done: - static int vcn_v3_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- struct amdgpu_ring *ring; - int i; - -+ cancel_delayed_work_sync(&adev->vcn.idle_work); -+ - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; - -- ring = &adev->vcn.inst[i].ring_dec; -- - if (!amdgpu_sriov_vf(adev)) { - if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && -diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c -index d2a678a2497e4..411494005f0ec 100644 ---- a/drivers/gpu/drm/i915/selftests/i915_request.c -+++ b/drivers/gpu/drm/i915/selftests/i915_request.c -@@ -1392,8 +1392,8 @@ static int live_breadcrumbs_smoketest(void *arg) - - for (n = 0; n < smoke[0].ncontexts; n++) { - smoke[0].contexts[n] = live_context(i915, file); -- if (!smoke[0].contexts[n]) { -- ret = -ENOMEM; -+ if (IS_ERR(smoke[0].contexts[n])) { -+ ret = PTR_ERR(smoke[0].contexts[n]); - goto out_contexts; - } - } -diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -index 85f2c3564c966..fb061e666faa7 100644 ---- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -@@ -933,8 +933,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) - DPU_DEBUG("REG_DMA is not defined"); - } - -- if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) -- dpu_kms_parse_data_bus_icc_path(dpu_kms); -+ dpu_kms_parse_data_bus_icc_path(dpu_kms); - - pm_runtime_get_sync(&dpu_kms->pdev->dev); - -diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c -index cd4078807db1b..3416e9617ee9a 100644 ---- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c -+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c -@@ -31,40 +31,8 @@ struct dpu_mdss { - void __iomem *mmio; - struct dss_module_power mp; - struct dpu_irq_controller irq_controller; -- struct icc_path *path[2]; -- u32 num_paths; - }; - --static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev, -- struct dpu_mdss *dpu_mdss) --{ -- struct icc_path *path0 = of_icc_get(dev->dev, "mdp0-mem"); -- struct icc_path *path1 = of_icc_get(dev->dev, "mdp1-mem"); -- -- if (IS_ERR_OR_NULL(path0)) -- return PTR_ERR_OR_ZERO(path0); -- -- dpu_mdss->path[0] = path0; -- dpu_mdss->num_paths = 1; -- -- if (!IS_ERR_OR_NULL(path1)) { -- dpu_mdss->path[1] = path1; -- dpu_mdss->num_paths++; -- } -- -- return 0; --} -- --static void dpu_mdss_icc_request_bw(struct msm_mdss *mdss) --{ -- struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); -- int i; -- u64 avg_bw = dpu_mdss->num_paths ? MAX_BW / dpu_mdss->num_paths : 0; -- -- for (i = 0; i < dpu_mdss->num_paths; i++) -- icc_set_bw(dpu_mdss->path[i], avg_bw, kBps_to_icc(MAX_BW)); --} -- - static void dpu_mdss_irq(struct irq_desc *desc) - { - struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc); -@@ -178,8 +146,6 @@ static int dpu_mdss_enable(struct msm_mdss *mdss) - struct dss_module_power *mp = &dpu_mdss->mp; - int ret; - -- dpu_mdss_icc_request_bw(mdss); -- - ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); - if (ret) { - DPU_ERROR("clock enable failed, ret:%d\n", ret); -@@ -213,15 +179,12 @@ static int dpu_mdss_disable(struct msm_mdss *mdss) - { - struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); - struct dss_module_power *mp = &dpu_mdss->mp; -- int ret, i; -+ int ret; - - ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); - if (ret) - DPU_ERROR("clock disable failed, ret:%d\n", ret); - -- for (i = 0; i < dpu_mdss->num_paths; i++) -- icc_set_bw(dpu_mdss->path[i], 0, 0); -- - return ret; - } - -@@ -232,7 +195,6 @@ static void dpu_mdss_destroy(struct drm_device *dev) - struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss); - struct dss_module_power *mp = &dpu_mdss->mp; - int irq; -- int i; - - pm_runtime_suspend(dev->dev); - pm_runtime_disable(dev->dev); -@@ -242,9 +204,6 @@ static void dpu_mdss_destroy(struct drm_device *dev) - msm_dss_put_clk(mp->clk_config, mp->num_clk); - devm_kfree(&pdev->dev, mp->clk_config); - -- for (i = 0; i < dpu_mdss->num_paths; i++) -- icc_put(dpu_mdss->path[i]); -- - if (dpu_mdss->mmio) - devm_iounmap(&pdev->dev, dpu_mdss->mmio); - dpu_mdss->mmio = NULL; -@@ -276,12 +235,6 @@ int dpu_mdss_init(struct drm_device *dev) - - DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio); - -- if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) { -- ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); -- if (ret) -- return ret; -- } -- - mp = &dpu_mdss->mp; - ret = msm_dss_parse_clock(pdev, mp); - if (ret) { -@@ -307,8 +260,6 @@ int dpu_mdss_init(struct drm_device *dev) - - pm_runtime_enable(dev->dev); - -- dpu_mdss_icc_request_bw(priv->mdss); -- - return ret; - - irq_error: -diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c -index 2ab38b7153477..ea9a4913932d6 100644 ---- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c -+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c -@@ -88,6 +88,7 @@ static void amd_sfh_work(struct work_struct *work) - sensor_index = req_node->sensor_idx; - report_id = req_node->report_id; - node_type = req_node->report_type; -+ kfree(req_node); - - if (node_type == HID_FEATURE_REPORT) { - report_size = get_feature_report(sensor_index, report_id, -diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c -index d459e2dbe6474..f7710fb2f48d2 100644 ---- a/drivers/hid/hid-logitech-hidpp.c -+++ b/drivers/hid/hid-logitech-hidpp.c -@@ -1262,6 +1262,7 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage, - int status; - - long flags = (long) data[2]; -+ *level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; - - if (flags & 0x80) - switch (flags & 0x07) { -diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c -index abd86903875f0..fc4c074597539 100644 ---- a/drivers/hid/hid-magicmouse.c -+++ b/drivers/hid/hid-magicmouse.c -@@ -597,7 +597,7 @@ static int magicmouse_probe(struct hid_device *hdev, - if (id->vendor == USB_VENDOR_ID_APPLE && - id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && - hdev->type != HID_TYPE_USBMOUSE) -- return 0; -+ return -ENODEV; - - msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL); - if (msc == NULL) { -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index 9d9f3e1bd5f41..55dcb8536286b 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -604,9 +604,13 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, - if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) - continue; - -- for (n = 0; n < field->report_count; n++) { -- if (field->usage[n].hid == HID_DG_CONTACTID) -- rdata->is_mt_collection = true; -+ if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { -+ for (n = 0; n < field->report_count; n++) { -+ if (field->usage[n].hid == HID_DG_CONTACTID) { -+ rdata->is_mt_collection = true; -+ break; -+ } -+ } - } - } - -diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c -index 9993133989a58..46474612e73c6 100644 ---- a/drivers/hid/i2c-hid/i2c-hid-core.c -+++ b/drivers/hid/i2c-hid/i2c-hid-core.c -@@ -45,6 +45,7 @@ - #define I2C_HID_QUIRK_BOGUS_IRQ BIT(4) - #define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5) - #define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6) -+#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(7) - - - /* flags */ -@@ -178,6 +179,11 @@ static const struct i2c_hid_quirks { - I2C_HID_QUIRK_RESET_ON_RESUME }, - { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720, - I2C_HID_QUIRK_BAD_INPUT_SIZE }, -+ /* -+ * Sending the wakeup after reset actually break ELAN touchscreen controller -+ */ -+ { USB_VENDOR_ID_ELAN, HID_ANY_ID, -+ I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET }, - { 0, 0 } - }; - -@@ -461,7 +467,8 @@ static int i2c_hid_hwreset(struct i2c_client *client) - } - - /* At least some SIS devices need this after reset */ -- ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); -+ if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET)) -+ ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); - - out_unlock: - mutex_unlock(&ihid->reset_lock); -@@ -990,8 +997,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, - hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); - hid->product = le16_to_cpu(ihid->hdesc.wProductID); - -- snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", -- client->name, hid->vendor, hid->product); -+ snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", -+ client->name, (u16)hid->vendor, (u16)hid->product); - strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); - - ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); -diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c -index fddac7c72f645..07a9fe97d2e05 100644 ---- a/drivers/hid/usbhid/hid-pidff.c -+++ b/drivers/hid/usbhid/hid-pidff.c -@@ -1292,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid) - - if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && - pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { -+ error = -EPERM; - hid_notice(hid, - "device does not support device managed pool\n"); - goto fail; -diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c -index 73b9db9e3aab6..63b74e781c5d9 100644 ---- a/drivers/hwmon/dell-smm-hwmon.c -+++ b/drivers/hwmon/dell-smm-hwmon.c -@@ -838,10 +838,10 @@ static struct attribute *i8k_attrs[] = { - static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, - int index) - { -- if (disallow_fan_support && index >= 8) -+ if (disallow_fan_support && index >= 20) - return 0; - if (disallow_fan_type_call && -- (index == 9 || index == 12 || index == 15)) -+ (index == 21 || index == 25 || index == 28)) - return 0; - if (index >= 0 && index <= 1 && - !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) -diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c -index 2bee930d39002..789242ed72e5d 100644 ---- a/drivers/hwmon/pmbus/isl68137.c -+++ b/drivers/hwmon/pmbus/isl68137.c -@@ -244,8 +244,8 @@ static int isl68137_probe(struct i2c_client *client) - info->read_word_data = raa_dmpvr2_read_word_data; - break; - case raa_dmpvr2_2rail_nontc: -- info->func[0] &= ~PMBUS_HAVE_TEMP; -- info->func[1] &= ~PMBUS_HAVE_TEMP; -+ info->func[0] &= ~PMBUS_HAVE_TEMP3; -+ info->func[1] &= ~PMBUS_HAVE_TEMP3; - fallthrough; - case raa_dmpvr2_2rail: - info->pages = 2; -diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c -index 214b4c913a139..671f4a52275ec 100644 ---- a/drivers/i2c/busses/i2c-qcom-geni.c -+++ b/drivers/i2c/busses/i2c-qcom-geni.c -@@ -650,6 +650,14 @@ static int geni_i2c_remove(struct platform_device *pdev) - return 0; - } - -+static void geni_i2c_shutdown(struct platform_device *pdev) -+{ -+ struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); -+ -+ /* Make client i2c transfers start failing */ -+ i2c_mark_adapter_suspended(&gi2c->adap); -+} -+ - static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) - { - int ret; -@@ -690,6 +698,8 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev) - { - struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); - -+ i2c_mark_adapter_suspended(&gi2c->adap); -+ - if (!gi2c->suspended) { - geni_i2c_runtime_suspend(dev); - pm_runtime_disable(dev); -@@ -699,8 +709,16 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev) - return 0; - } - -+static int __maybe_unused geni_i2c_resume_noirq(struct device *dev) -+{ -+ struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); -+ -+ i2c_mark_adapter_resumed(&gi2c->adap); -+ return 0; -+} -+ - static const struct dev_pm_ops geni_i2c_pm_ops = { -- SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, NULL) -+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, geni_i2c_resume_noirq) - SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume, - NULL) - }; -@@ -714,6 +732,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match); - static struct platform_driver geni_i2c_driver = { - .probe = geni_i2c_probe, - .remove = geni_i2c_remove, -+ .shutdown = geni_i2c_shutdown, - .driver = { - .name = "geni_i2c", - .pm = &geni_i2c_pm_ops, -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h -index 314f8d8067231..9058f09f921ee 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h -@@ -2177,8 +2177,6 @@ int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid, - bool persistent, u8 *smt_idx); - int cxgb4_get_msix_idx_from_bmap(struct adapter *adap); - void cxgb4_free_msix_idx_in_bmap(struct adapter *adap, u32 msix_idx); --int cxgb_open(struct net_device *dev); --int cxgb_close(struct net_device *dev); - void cxgb4_enable_rx(struct adapter *adap, struct sge_rspq *q); - void cxgb4_quiesce_rx(struct sge_rspq *q); - int cxgb4_port_mirror_alloc(struct net_device *dev); -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -index 421bd9b88028d..1f601de02e706 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -@@ -2834,7 +2834,7 @@ static void cxgb_down(struct adapter *adapter) - /* - * net_device operations - */ --int cxgb_open(struct net_device *dev) -+static int cxgb_open(struct net_device *dev) - { - struct port_info *pi = netdev_priv(dev); - struct adapter *adapter = pi->adapter; -@@ -2882,7 +2882,7 @@ out_unlock: - return err; - } - --int cxgb_close(struct net_device *dev) -+static int cxgb_close(struct net_device *dev) - { - struct port_info *pi = netdev_priv(dev); - struct adapter *adapter = pi->adapter; -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c -index 1b88bd1c2dbe4..dd9be229819a5 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c -@@ -997,20 +997,16 @@ int cxgb4_tc_flower_destroy(struct net_device *dev, - if (!ch_flower) - return -ENOENT; - -+ rhashtable_remove_fast(&adap->flower_tbl, &ch_flower->node, -+ adap->flower_ht_params); -+ - ret = cxgb4_flow_rule_destroy(dev, ch_flower->fs.tc_prio, - &ch_flower->fs, ch_flower->filter_id); - if (ret) -- goto err; -+ netdev_err(dev, "Flow rule destroy failed for tid: %u, ret: %d", -+ ch_flower->filter_id, ret); - -- ret = rhashtable_remove_fast(&adap->flower_tbl, &ch_flower->node, -- adap->flower_ht_params); -- if (ret) { -- netdev_err(dev, "Flow remove from rhashtable failed"); -- goto err; -- } - kfree_rcu(ch_flower, rcu); -- --err: - return ret; - } - -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c -index 6c259de96f969..338b04f339b3d 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c -@@ -589,7 +589,8 @@ int cxgb4_setup_tc_mqprio(struct net_device *dev, - * down before configuring tc params. - */ - if (netif_running(dev)) { -- cxgb_close(dev); -+ netif_tx_stop_all_queues(dev); -+ netif_carrier_off(dev); - needs_bring_up = true; - } - -@@ -615,8 +616,10 @@ int cxgb4_setup_tc_mqprio(struct net_device *dev, - } - - out: -- if (needs_bring_up) -- cxgb_open(dev); -+ if (needs_bring_up) { -+ netif_tx_start_all_queues(dev); -+ netif_carrier_on(dev); -+ } - - mutex_unlock(&adap->tc_mqprio->mqprio_mutex); - return ret; -diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c -index 1e5f2edb70cf4..6a099cb34b122 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/sge.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c -@@ -2556,6 +2556,12 @@ int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc) - if (!eosw_txq) - return -ENOMEM; - -+ if (!(adap->flags & CXGB4_FW_OK)) { -+ /* Don't stall caller when access to FW is lost */ -+ complete(&eosw_txq->completion); -+ return -EIO; -+ } -+ - skb = alloc_skb(len, GFP_KERNEL); - if (!skb) - return -ENOMEM; -diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c -index 70b515049540f..c358d90498813 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c -@@ -2313,15 +2313,20 @@ static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp) - case XDP_TX: - xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index]; - result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring); -+ if (result == I40E_XDP_CONSUMED) -+ goto out_failure; - break; - case XDP_REDIRECT: - err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -- result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED; -+ if (err) -+ goto out_failure; -+ result = I40E_XDP_REDIR; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; /* handle aborts by dropping packet */ - case XDP_DROP: -diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c -index 12ca84113587d..5b39c457bd77b 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c -@@ -160,21 +160,28 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) - xdp_prog = READ_ONCE(rx_ring->xdp_prog); - act = bpf_prog_run_xdp(xdp_prog, xdp); - -+ if (likely(act == XDP_REDIRECT)) { -+ err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -+ if (err) -+ goto out_failure; -+ rcu_read_unlock(); -+ return I40E_XDP_REDIR; -+ } -+ - switch (act) { - case XDP_PASS: - break; - case XDP_TX: - xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index]; - result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring); -- break; -- case XDP_REDIRECT: -- err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -- result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED; -+ if (result == I40E_XDP_CONSUMED) -+ goto out_failure; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; /* handle aborts by dropping packet */ - case XDP_DROP: -diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h -index 17101c45cbcd8..f668296ca6779 100644 ---- a/drivers/net/ethernet/intel/ice/ice.h -+++ b/drivers/net/ethernet/intel/ice/ice.h -@@ -325,6 +325,7 @@ struct ice_vsi { - struct ice_tc_cfg tc_cfg; - struct bpf_prog *xdp_prog; - struct ice_ring **xdp_rings; /* XDP ring array */ -+ unsigned long *af_xdp_zc_qps; /* tracks AF_XDP ZC enabled qps */ - u16 num_xdp_txq; /* Used XDP queues */ - u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */ - -@@ -534,15 +535,16 @@ static inline void ice_set_ring_xdp(struct ice_ring *ring) - */ - static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_ring *ring) - { -+ struct ice_vsi *vsi = ring->vsi; - u16 qid = ring->q_index; - - if (ice_ring_is_xdp(ring)) -- qid -= ring->vsi->num_xdp_txq; -+ qid -= vsi->num_xdp_txq; - -- if (!ice_is_xdp_ena_vsi(ring->vsi)) -+ if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps)) - return NULL; - -- return xsk_get_pool_from_qid(ring->vsi->netdev, qid); -+ return xsk_get_pool_from_qid(vsi->netdev, qid); - } - - /** -diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c -index 32ba71a161652..f80fff97d8dce 100644 ---- a/drivers/net/ethernet/intel/ice/ice_ethtool.c -+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c -@@ -1797,49 +1797,6 @@ ice_phy_type_to_ethtool(struct net_device *netdev, - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseKR4_Full); - } -- -- /* Autoneg PHY types */ -- if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || -- phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || -- phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX || -- phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T || -- phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX || -- phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || -- phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR || -- phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || -- phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || -- phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 || -- phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || -- phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { -- ethtool_link_ksettings_add_link_mode(ks, supported, -- Autoneg); -- ethtool_link_ksettings_add_link_mode(ks, advertising, -- Autoneg); -- } -- if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || -- phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || -- phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || -- phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { -- ethtool_link_ksettings_add_link_mode(ks, supported, -- Autoneg); -- ethtool_link_ksettings_add_link_mode(ks, advertising, -- Autoneg); -- } -- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || -- phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || -- phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || -- phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { -- ethtool_link_ksettings_add_link_mode(ks, supported, -- Autoneg); -- ethtool_link_ksettings_add_link_mode(ks, advertising, -- Autoneg); -- } - } - - #define TEST_SET_BITS_TIMEOUT 50 -@@ -1996,9 +1953,7 @@ ice_get_link_ksettings(struct net_device *netdev, - ks->base.port = PORT_TP; - break; - case ICE_MEDIA_BACKPLANE: -- ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); - ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); -- ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); - ethtool_link_ksettings_add_link_mode(ks, advertising, - Backplane); - ks->base.port = PORT_NONE; -@@ -2073,6 +2028,12 @@ ice_get_link_ksettings(struct net_device *netdev, - if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - -+ /* Set supported and advertised autoneg */ -+ if (ice_is_phy_caps_an_enabled(caps)) { -+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); -+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); -+ } -+ - done: - kfree(caps); - return err; -diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h -index 093a1818a3929..1998821896c0f 100644 ---- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h -+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h -@@ -31,6 +31,7 @@ - #define PF_FW_ATQLEN_ATQOVFL_M BIT(29) - #define PF_FW_ATQLEN_ATQCRIT_M BIT(30) - #define VF_MBX_ARQLEN(_VF) (0x0022BC00 + ((_VF) * 4)) -+#define VF_MBX_ATQLEN(_VF) (0x0022A800 + ((_VF) * 4)) - #define PF_FW_ATQLEN_ATQENABLE_M BIT(31) - #define PF_FW_ATQT 0x00080400 - #define PF_MBX_ARQBAH 0x0022E400 -diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c -index 195d122c9cb22..27e439853c3b0 100644 ---- a/drivers/net/ethernet/intel/ice/ice_lib.c -+++ b/drivers/net/ethernet/intel/ice/ice_lib.c -@@ -105,8 +105,14 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) - if (!vsi->q_vectors) - goto err_vectors; - -+ vsi->af_xdp_zc_qps = bitmap_zalloc(max_t(int, vsi->alloc_txq, vsi->alloc_rxq), GFP_KERNEL); -+ if (!vsi->af_xdp_zc_qps) -+ goto err_zc_qps; -+ - return 0; - -+err_zc_qps: -+ devm_kfree(dev, vsi->q_vectors); - err_vectors: - devm_kfree(dev, vsi->rxq_map); - err_rxq_map: -@@ -192,6 +198,8 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) - break; - case ICE_VSI_VF: - vf = &pf->vf[vsi->vf_id]; -+ if (vf->num_req_qs) -+ vf->num_vf_qs = vf->num_req_qs; - vsi->alloc_txq = vf->num_vf_qs; - vsi->alloc_rxq = vf->num_vf_qs; - /* pf->num_msix_per_vf includes (VF miscellaneous vector + -@@ -286,6 +294,10 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi) - - dev = ice_pf_to_dev(pf); - -+ if (vsi->af_xdp_zc_qps) { -+ bitmap_free(vsi->af_xdp_zc_qps); -+ vsi->af_xdp_zc_qps = NULL; -+ } - /* free the ring and vector containers */ - if (vsi->q_vectors) { - devm_kfree(dev, vsi->q_vectors); -diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c -index b91dcfd12727d..113e53efffd71 100644 ---- a/drivers/net/ethernet/intel/ice/ice_txrx.c -+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c -@@ -523,7 +523,7 @@ ice_run_xdp(struct ice_ring *rx_ring, struct xdp_buff *xdp, - struct bpf_prog *xdp_prog) - { - struct ice_ring *xdp_ring; -- int err; -+ int err, result; - u32 act; - - act = bpf_prog_run_xdp(xdp_prog, xdp); -@@ -532,14 +532,20 @@ ice_run_xdp(struct ice_ring *rx_ring, struct xdp_buff *xdp, - return ICE_XDP_PASS; - case XDP_TX: - xdp_ring = rx_ring->vsi->xdp_rings[smp_processor_id()]; -- return ice_xmit_xdp_buff(xdp, xdp_ring); -+ result = ice_xmit_xdp_buff(xdp, xdp_ring); -+ if (result == ICE_XDP_CONSUMED) -+ goto out_failure; -+ return result; - case XDP_REDIRECT: - err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -- return !err ? ICE_XDP_REDIR : ICE_XDP_CONSUMED; -+ if (err) -+ goto out_failure; -+ return ICE_XDP_REDIR; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; - case XDP_DROP: -@@ -2331,6 +2337,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring) - struct ice_tx_offload_params offload = { 0 }; - struct ice_vsi *vsi = tx_ring->vsi; - struct ice_tx_buf *first; -+ struct ethhdr *eth; - unsigned int count; - int tso, csum; - -@@ -2377,7 +2384,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring) - goto out_drop; - - /* allow CONTROL frames egress from main VSI if FW LLDP disabled */ -- if (unlikely(skb->priority == TC_PRIO_CONTROL && -+ eth = (struct ethhdr *)skb_mac_header(skb); -+ if (unlikely((skb->priority == TC_PRIO_CONTROL || -+ eth->h_proto == htons(ETH_P_LLDP)) && - vsi->type == ICE_VSI_PF && - vsi->port_info->qos_cfg.is_sw_lldp)) - offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX | -diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -index 1f38a8d0c5254..48dee9c5d534b 100644 ---- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -@@ -435,13 +435,15 @@ static void ice_trigger_vf_reset(struct ice_vf *vf, bool is_vflr, bool is_pfr) - */ - clear_bit(ICE_VF_STATE_INIT, vf->vf_states); - -- /* VF_MBX_ARQLEN is cleared by PFR, so the driver needs to clear it -- * in the case of VFR. If this is done for PFR, it can mess up VF -- * resets because the VF driver may already have started cleanup -- * by the time we get here. -+ /* VF_MBX_ARQLEN and VF_MBX_ATQLEN are cleared by PFR, so the driver -+ * needs to clear them in the case of VFR/VFLR. If this is done for -+ * PFR, it can mess up VF resets because the VF driver may already -+ * have started cleanup by the time we get here. - */ -- if (!is_pfr) -+ if (!is_pfr) { - wr32(hw, VF_MBX_ARQLEN(vf->vf_id), 0); -+ wr32(hw, VF_MBX_ATQLEN(vf->vf_id), 0); -+ } - - /* In the case of a VFLR, the HW has already reset the VF and we - * just need to clean up, so don't hit the VFRTRIG register. -@@ -1375,7 +1377,12 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) - } - - ice_vf_pre_vsi_rebuild(vf); -- ice_vf_rebuild_vsi_with_release(vf); -+ -+ if (ice_vf_rebuild_vsi_with_release(vf)) { -+ dev_err(dev, "Failed to release and setup the VF%u's VSI\n", vf->vf_id); -+ return false; -+ } -+ - ice_vf_post_vsi_rebuild(vf); - - return true; -diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c -index 9f94d9159acde..f1d4240e57df3 100644 ---- a/drivers/net/ethernet/intel/ice/ice_xsk.c -+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c -@@ -273,6 +273,7 @@ static int ice_xsk_pool_disable(struct ice_vsi *vsi, u16 qid) - if (!pool) - return -EINVAL; - -+ clear_bit(qid, vsi->af_xdp_zc_qps); - xsk_pool_dma_unmap(pool, ICE_RX_DMA_ATTR); - - return 0; -@@ -303,6 +304,8 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid) - if (err) - return err; - -+ set_bit(qid, vsi->af_xdp_zc_qps); -+ - return 0; - } - -@@ -473,21 +476,29 @@ ice_run_xdp_zc(struct ice_ring *rx_ring, struct xdp_buff *xdp) - xdp_prog = READ_ONCE(rx_ring->xdp_prog); - - act = bpf_prog_run_xdp(xdp_prog, xdp); -+ -+ if (likely(act == XDP_REDIRECT)) { -+ err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -+ if (err) -+ goto out_failure; -+ rcu_read_unlock(); -+ return ICE_XDP_REDIR; -+ } -+ - switch (act) { - case XDP_PASS: - break; - case XDP_TX: - xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->q_index]; - result = ice_xmit_xdp_buff(xdp, xdp_ring); -- break; -- case XDP_REDIRECT: -- err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -- result = !err ? ICE_XDP_REDIR : ICE_XDP_CONSUMED; -+ if (result == ICE_XDP_CONSUMED) -+ goto out_failure; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; - case XDP_DROP: -diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h -index 7bda8c5edea5d..2d3daf022651c 100644 ---- a/drivers/net/ethernet/intel/igb/igb.h -+++ b/drivers/net/ethernet/intel/igb/igb.h -@@ -749,7 +749,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter); - void igb_ptp_tx_hang(struct igb_adapter *adapter); - void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); - int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -- struct sk_buff *skb); -+ ktime_t *timestamp); - int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); - int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); - void igb_set_flag_queue_pairs(struct igb_adapter *, const u32); -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index a45cd2b416c89..caa8929289ae7 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -8281,7 +8281,7 @@ static void igb_add_rx_frag(struct igb_ring *rx_ring, - static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, - struct igb_rx_buffer *rx_buffer, - struct xdp_buff *xdp, -- union e1000_adv_rx_desc *rx_desc) -+ ktime_t timestamp) - { - #if (PAGE_SIZE < 8192) - unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; -@@ -8301,12 +8301,8 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, - if (unlikely(!skb)) - return NULL; - -- if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) { -- if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) { -- xdp->data += IGB_TS_HDR_LEN; -- size -= IGB_TS_HDR_LEN; -- } -- } -+ if (timestamp) -+ skb_hwtstamps(skb)->hwtstamp = timestamp; - - /* Determine available headroom for copy */ - headlen = size; -@@ -8337,7 +8333,7 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, - static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring, - struct igb_rx_buffer *rx_buffer, - struct xdp_buff *xdp, -- union e1000_adv_rx_desc *rx_desc) -+ ktime_t timestamp) - { - #if (PAGE_SIZE < 8192) - unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; -@@ -8364,11 +8360,8 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring, - if (metasize) - skb_metadata_set(skb, metasize); - -- /* pull timestamp out of packet data */ -- if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { -- if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb)) -- __skb_pull(skb, IGB_TS_HDR_LEN); -- } -+ if (timestamp) -+ skb_hwtstamps(skb)->hwtstamp = timestamp; - - /* update buffer offset */ - #if (PAGE_SIZE < 8192) -@@ -8402,18 +8395,20 @@ static struct sk_buff *igb_run_xdp(struct igb_adapter *adapter, - break; - case XDP_TX: - result = igb_xdp_xmit_back(adapter, xdp); -+ if (result == IGB_XDP_CONSUMED) -+ goto out_failure; - break; - case XDP_REDIRECT: - err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); -- if (!err) -- result = IGB_XDP_REDIR; -- else -- result = IGB_XDP_CONSUMED; -+ if (err) -+ goto out_failure; -+ result = IGB_XDP_REDIR; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; - case XDP_DROP: -@@ -8683,7 +8678,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) - while (likely(total_packets < budget)) { - union e1000_adv_rx_desc *rx_desc; - struct igb_rx_buffer *rx_buffer; -+ ktime_t timestamp = 0; -+ int pkt_offset = 0; - unsigned int size; -+ void *pktbuf; - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= IGB_RX_BUFFER_WRITE) { -@@ -8703,14 +8701,24 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) - dma_rmb(); - - rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt); -+ pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset; -+ -+ /* pull rx packet timestamp if available and valid */ -+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { -+ int ts_hdr_len; -+ -+ ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector, -+ pktbuf, ×tamp); -+ -+ pkt_offset += ts_hdr_len; -+ size -= ts_hdr_len; -+ } - - /* retrieve a buffer from the ring */ - if (!skb) { -- unsigned int offset = igb_rx_offset(rx_ring); -- unsigned char *hard_start; -+ unsigned char *hard_start = pktbuf - igb_rx_offset(rx_ring); -+ unsigned int offset = pkt_offset + igb_rx_offset(rx_ring); - -- hard_start = page_address(rx_buffer->page) + -- rx_buffer->page_offset - offset; - xdp_prepare_buff(&xdp, hard_start, offset, size, true); - #if (PAGE_SIZE > 4096) - /* At larger PAGE_SIZE, frame_sz depend on len size */ -@@ -8733,10 +8741,11 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) - } else if (skb) - igb_add_rx_frag(rx_ring, rx_buffer, skb, size); - else if (ring_uses_build_skb(rx_ring)) -- skb = igb_build_skb(rx_ring, rx_buffer, &xdp, rx_desc); -+ skb = igb_build_skb(rx_ring, rx_buffer, &xdp, -+ timestamp); - else - skb = igb_construct_skb(rx_ring, rx_buffer, -- &xdp, rx_desc); -+ &xdp, timestamp); - - /* exit if we failed to retrieve a buffer */ - if (!skb) { -diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c -index 86a576201f5ff..58b25f26ea7f2 100644 ---- a/drivers/net/ethernet/intel/igb/igb_ptp.c -+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c -@@ -856,30 +856,28 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) - dev_kfree_skb_any(skb); - } - --#define IGB_RET_PTP_DISABLED 1 --#define IGB_RET_PTP_INVALID 2 -- - /** - * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp - * @q_vector: Pointer to interrupt specific structure - * @va: Pointer to address containing Rx buffer -- * @skb: Buffer containing timestamp and packet -+ * @timestamp: Pointer where timestamp will be stored - * - * This function is meant to retrieve a timestamp from the first buffer of an - * incoming frame. The value is stored in little endian format starting on - * byte 8 - * -- * Returns: 0 if success, nonzero if failure -+ * Returns: The timestamp header length or 0 if not available - **/ - int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -- struct sk_buff *skb) -+ ktime_t *timestamp) - { - struct igb_adapter *adapter = q_vector->adapter; -+ struct skb_shared_hwtstamps ts; - __le64 *regval = (__le64 *)va; - int adjust = 0; - - if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) -- return IGB_RET_PTP_DISABLED; -+ return 0; - - /* The timestamp is recorded in little endian format. - * DWORD: 0 1 2 3 -@@ -888,10 +886,9 @@ int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, - - /* check reserved dwords are zero, be/le doesn't matter for zero */ - if (regval[0]) -- return IGB_RET_PTP_INVALID; -+ return 0; - -- igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), -- le64_to_cpu(regval[1])); -+ igb_ptp_systim_to_hwtstamp(adapter, &ts, le64_to_cpu(regval[1])); - - /* adjust timestamp for the RX latency based on link speed */ - if (adapter->hw.mac.type == e1000_i210) { -@@ -907,10 +904,10 @@ int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, - break; - } - } -- skb_hwtstamps(skb)->hwtstamp = -- ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); - -- return 0; -+ *timestamp = ktime_sub_ns(ts.hwtstamp, adjust); -+ -+ return IGB_TS_HDR_LEN; - } - - /** -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -index cffb95f8f6326..c194158a421c7 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -@@ -2213,23 +2213,23 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter, - break; - case XDP_TX: - xdpf = xdp_convert_buff_to_frame(xdp); -- if (unlikely(!xdpf)) { -- result = IXGBE_XDP_CONSUMED; -- break; -- } -+ if (unlikely(!xdpf)) -+ goto out_failure; - result = ixgbe_xmit_xdp_ring(adapter, xdpf); -+ if (result == IXGBE_XDP_CONSUMED) -+ goto out_failure; - break; - case XDP_REDIRECT: - err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); -- if (!err) -- result = IXGBE_XDP_REDIR; -- else -- result = IXGBE_XDP_CONSUMED; -+ if (err) -+ goto out_failure; -+ result = IXGBE_XDP_REDIR; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; /* handle aborts by dropping packet */ - case XDP_DROP: -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c -index 3771857cf887c..f72d2978263b9 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c -@@ -104,25 +104,30 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter, - xdp_prog = READ_ONCE(rx_ring->xdp_prog); - act = bpf_prog_run_xdp(xdp_prog, xdp); - -+ if (likely(act == XDP_REDIRECT)) { -+ err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -+ if (err) -+ goto out_failure; -+ rcu_read_unlock(); -+ return IXGBE_XDP_REDIR; -+ } -+ - switch (act) { - case XDP_PASS: - break; - case XDP_TX: - xdpf = xdp_convert_buff_to_frame(xdp); -- if (unlikely(!xdpf)) { -- result = IXGBE_XDP_CONSUMED; -- break; -- } -+ if (unlikely(!xdpf)) -+ goto out_failure; - result = ixgbe_xmit_xdp_ring(adapter, xdpf); -- break; -- case XDP_REDIRECT: -- err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -- result = !err ? IXGBE_XDP_REDIR : IXGBE_XDP_CONSUMED; -+ if (result == IXGBE_XDP_CONSUMED) -+ goto out_failure; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; /* handle aborts by dropping packet */ - case XDP_DROP: -diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -index 449d7d5b280dd..b38860c485986 100644 ---- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -@@ -1067,11 +1067,14 @@ static struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_adapter *adapter, - case XDP_TX: - xdp_ring = adapter->xdp_ring[rx_ring->queue_index]; - result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp); -+ if (result == IXGBEVF_XDP_CONSUMED) -+ goto out_failure; - break; - default: - bpf_warn_invalid_xdp_action(act); - fallthrough; - case XDP_ABORTED: -+out_failure: - trace_xdp_exception(rx_ring->netdev, xdp_prog, act); - fallthrough; /* handle aborts by dropping packet */ - case XDP_DROP: -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -index 53802e18af900..04b49cb3adb32 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -@@ -1632,12 +1632,13 @@ static int mlx5e_set_fecparam(struct net_device *netdev, - { - struct mlx5e_priv *priv = netdev_priv(netdev); - struct mlx5_core_dev *mdev = priv->mdev; -+ unsigned long fec_bitmap; - u16 fec_policy = 0; - int mode; - int err; - -- if (bitmap_weight((unsigned long *)&fecparam->fec, -- ETHTOOL_FEC_LLRS_BIT + 1) > 1) -+ bitmap_from_arr32(&fec_bitmap, &fecparam->fec, sizeof(fecparam->fec) * BITS_PER_BYTE); -+ if (bitmap_weight(&fec_bitmap, ETHTOOL_FEC_LLRS_BIT + 1) > 1) - return -EOPNOTSUPP; - - for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) { -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -index 78a1403c98026..b633f669ea57f 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -@@ -1964,11 +1964,13 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, - misc_parameters); - struct flow_rule *rule = flow_cls_offload_flow_rule(f); - struct flow_dissector *dissector = rule->match.dissector; -+ enum fs_flow_table_type fs_type; - u16 addr_type = 0; - u8 ip_proto = 0; - u8 *match_level; - int err; - -+ fs_type = mlx5e_is_eswitch_flow(flow) ? FS_FT_FDB : FS_FT_NIC_RX; - match_level = outer_match_level; - - if (dissector->used_keys & -@@ -2093,6 +2095,13 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, - if (match.mask->vlan_id || - match.mask->vlan_priority || - match.mask->vlan_tpid) { -+ if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ft_field_support.outer_second_vid, -+ fs_type)) { -+ NL_SET_ERR_MSG_MOD(extack, -+ "Matching on CVLAN is not supported"); -+ return -EOPNOTSUPP; -+ } -+ - if (match.key->vlan_tpid == htons(ETH_P_8021AD)) { - MLX5_SET(fte_match_set_misc, misc_c, - outer_second_svlan_tag, 1); -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -index d4a2f8d1ee9f1..3719452a78035 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -@@ -349,7 +349,8 @@ esw_setup_slow_path_dest(struct mlx5_flow_destination *dest, - struct mlx5_fs_chains *chains, - int i) - { -- flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; -+ if (mlx5_chains_ignore_flow_level_supported(chains)) -+ flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; - dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest[i].ft = mlx5_chains_get_tc_end_ft(chains); - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c -index f9042e147c7f6..ee710ce007950 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c -@@ -354,6 +354,9 @@ 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)) -+ return; -+ - mlx5_sync_reset_clear_reset_requested(dev, true); - mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); - } -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 381325b4a863e..b607ed5a74bb4 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c -@@ -111,7 +111,7 @@ bool mlx5_chains_prios_supported(struct mlx5_fs_chains *chains) - return chains->flags & MLX5_CHAINS_AND_PRIOS_SUPPORTED; - } - --static bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains) -+bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains) - { - return chains->flags & MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED; - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.h -index 6d5be31b05dd7..9f53a08235582 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.h -@@ -27,6 +27,7 @@ struct mlx5_chains_attr { - - bool - mlx5_chains_prios_supported(struct mlx5_fs_chains *chains); -+bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains); - bool - mlx5_chains_backwards_supported(struct mlx5_fs_chains *chains); - u32 -@@ -72,6 +73,10 @@ mlx5_chains_set_end_ft(struct mlx5_fs_chains *chains, - - #else /* CONFIG_MLX5_CLS_ACT */ - -+static inline bool -+mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains) -+{ return false; } -+ - static inline struct mlx5_flow_table * - mlx5_chains_get_table(struct mlx5_fs_chains *chains, u32 chain, u32 prio, - u32 level) { return ERR_PTR(-EOPNOTSUPP); } -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 1fbcd012bb855..7ccfd40586cee 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c -@@ -112,7 +112,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn, - int ret; - - ft_attr.table_type = MLX5_FLOW_TABLE_TYPE_FDB; -- ft_attr.level = dmn->info.caps.max_ft_level - 2; -+ ft_attr.level = min_t(int, dmn->info.caps.max_ft_level - 2, -+ MLX5_FT_MAX_MULTIPATH_LEVEL); - ft_attr.reformat_en = reformat_req; - ft_attr.decap_en = reformat_req; - -diff --git a/drivers/net/wireguard/Makefile b/drivers/net/wireguard/Makefile -index fc52b2cb500b3..dbe1f8514efc3 100644 ---- a/drivers/net/wireguard/Makefile -+++ b/drivers/net/wireguard/Makefile -@@ -1,5 +1,4 @@ --ccflags-y := -O3 --ccflags-y += -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt' -+ccflags-y := -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt' - ccflags-$(CONFIG_WIREGUARD_DEBUG) += -DDEBUG - wireguard-y := main.o - wireguard-y += noise.o -diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c -index 3725e9cd85f4f..b7197e80f2264 100644 ---- a/drivers/net/wireguard/allowedips.c -+++ b/drivers/net/wireguard/allowedips.c -@@ -6,6 +6,8 @@ - #include "allowedips.h" - #include "peer.h" - -+static struct kmem_cache *node_cache; -+ - static void swap_endian(u8 *dst, const u8 *src, u8 bits) - { - if (bits == 32) { -@@ -28,8 +30,11 @@ static void copy_and_assign_cidr(struct allowedips_node *node, const u8 *src, - node->bitlen = bits; - memcpy(node->bits, src, bits / 8U); - } --#define CHOOSE_NODE(parent, key) \ -- parent->bit[(key[parent->bit_at_a] >> parent->bit_at_b) & 1] -+ -+static inline u8 choose(struct allowedips_node *node, const u8 *key) -+{ -+ return (key[node->bit_at_a] >> node->bit_at_b) & 1; -+} - - static void push_rcu(struct allowedips_node **stack, - struct allowedips_node __rcu *p, unsigned int *len) -@@ -40,6 +45,11 @@ static void push_rcu(struct allowedips_node **stack, - } - } - -+static void node_free_rcu(struct rcu_head *rcu) -+{ -+ kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu)); -+} -+ - static void root_free_rcu(struct rcu_head *rcu) - { - struct allowedips_node *node, *stack[128] = { -@@ -49,7 +59,7 @@ static void root_free_rcu(struct rcu_head *rcu) - while (len > 0 && (node = stack[--len])) { - push_rcu(stack, node->bit[0], &len); - push_rcu(stack, node->bit[1], &len); -- kfree(node); -+ kmem_cache_free(node_cache, node); - } - } - -@@ -66,60 +76,6 @@ static void root_remove_peer_lists(struct allowedips_node *root) - } - } - --static void walk_remove_by_peer(struct allowedips_node __rcu **top, -- struct wg_peer *peer, struct mutex *lock) --{ --#define REF(p) rcu_access_pointer(p) --#define DEREF(p) rcu_dereference_protected(*(p), lockdep_is_held(lock)) --#define PUSH(p) ({ \ -- WARN_ON(IS_ENABLED(DEBUG) && len >= 128); \ -- stack[len++] = p; \ -- }) -- -- struct allowedips_node __rcu **stack[128], **nptr; -- struct allowedips_node *node, *prev; -- unsigned int len; -- -- if (unlikely(!peer || !REF(*top))) -- return; -- -- for (prev = NULL, len = 0, PUSH(top); len > 0; prev = node) { -- nptr = stack[len - 1]; -- node = DEREF(nptr); -- if (!node) { -- --len; -- continue; -- } -- if (!prev || REF(prev->bit[0]) == node || -- REF(prev->bit[1]) == node) { -- if (REF(node->bit[0])) -- PUSH(&node->bit[0]); -- else if (REF(node->bit[1])) -- PUSH(&node->bit[1]); -- } else if (REF(node->bit[0]) == prev) { -- if (REF(node->bit[1])) -- PUSH(&node->bit[1]); -- } else { -- if (rcu_dereference_protected(node->peer, -- lockdep_is_held(lock)) == peer) { -- RCU_INIT_POINTER(node->peer, NULL); -- list_del_init(&node->peer_list); -- if (!node->bit[0] || !node->bit[1]) { -- rcu_assign_pointer(*nptr, DEREF( -- &node->bit[!REF(node->bit[0])])); -- kfree_rcu(node, rcu); -- node = DEREF(nptr); -- } -- } -- --len; -- } -- } -- --#undef REF --#undef DEREF --#undef PUSH --} -- - static unsigned int fls128(u64 a, u64 b) - { - return a ? fls64(a) + 64U : fls64(b); -@@ -159,7 +115,7 @@ static struct allowedips_node *find_node(struct allowedips_node *trie, u8 bits, - found = node; - if (node->cidr == bits) - break; -- node = rcu_dereference_bh(CHOOSE_NODE(node, key)); -+ node = rcu_dereference_bh(node->bit[choose(node, key)]); - } - return found; - } -@@ -191,8 +147,7 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key, - u8 cidr, u8 bits, struct allowedips_node **rnode, - struct mutex *lock) - { -- struct allowedips_node *node = rcu_dereference_protected(trie, -- lockdep_is_held(lock)); -+ struct allowedips_node *node = rcu_dereference_protected(trie, lockdep_is_held(lock)); - struct allowedips_node *parent = NULL; - bool exact = false; - -@@ -202,13 +157,24 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key, - exact = true; - break; - } -- node = rcu_dereference_protected(CHOOSE_NODE(parent, key), -- lockdep_is_held(lock)); -+ node = rcu_dereference_protected(parent->bit[choose(parent, key)], lockdep_is_held(lock)); - } - *rnode = parent; - return exact; - } - -+static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node) -+{ -+ node->parent_bit_packed = (unsigned long)parent | bit; -+ rcu_assign_pointer(*parent, node); -+} -+ -+static inline void choose_and_connect_node(struct allowedips_node *parent, struct allowedips_node *node) -+{ -+ u8 bit = choose(parent, node->bits); -+ connect_node(&parent->bit[bit], bit, node); -+} -+ - static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, - u8 cidr, struct wg_peer *peer, struct mutex *lock) - { -@@ -218,13 +184,13 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, - return -EINVAL; - - if (!rcu_access_pointer(*trie)) { -- node = kzalloc(sizeof(*node), GFP_KERNEL); -+ node = kmem_cache_zalloc(node_cache, GFP_KERNEL); - if (unlikely(!node)) - return -ENOMEM; - RCU_INIT_POINTER(node->peer, peer); - list_add_tail(&node->peer_list, &peer->allowedips_list); - copy_and_assign_cidr(node, key, cidr, bits); -- rcu_assign_pointer(*trie, node); -+ connect_node(trie, 2, node); - return 0; - } - if (node_placement(*trie, key, cidr, bits, &node, lock)) { -@@ -233,7 +199,7 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, - return 0; - } - -- newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); -+ newnode = kmem_cache_zalloc(node_cache, GFP_KERNEL); - if (unlikely(!newnode)) - return -ENOMEM; - RCU_INIT_POINTER(newnode->peer, peer); -@@ -243,10 +209,10 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, - if (!node) { - down = rcu_dereference_protected(*trie, lockdep_is_held(lock)); - } else { -- down = rcu_dereference_protected(CHOOSE_NODE(node, key), -- lockdep_is_held(lock)); -+ const u8 bit = choose(node, key); -+ down = rcu_dereference_protected(node->bit[bit], lockdep_is_held(lock)); - if (!down) { -- rcu_assign_pointer(CHOOSE_NODE(node, key), newnode); -+ connect_node(&node->bit[bit], bit, newnode); - return 0; - } - } -@@ -254,30 +220,29 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, - parent = node; - - if (newnode->cidr == cidr) { -- rcu_assign_pointer(CHOOSE_NODE(newnode, down->bits), down); -+ choose_and_connect_node(newnode, down); - if (!parent) -- rcu_assign_pointer(*trie, newnode); -+ connect_node(trie, 2, newnode); - else -- rcu_assign_pointer(CHOOSE_NODE(parent, newnode->bits), -- newnode); -- } else { -- node = kzalloc(sizeof(*node), GFP_KERNEL); -- if (unlikely(!node)) { -- list_del(&newnode->peer_list); -- kfree(newnode); -- return -ENOMEM; -- } -- INIT_LIST_HEAD(&node->peer_list); -- copy_and_assign_cidr(node, newnode->bits, cidr, bits); -+ choose_and_connect_node(parent, newnode); -+ return 0; -+ } - -- rcu_assign_pointer(CHOOSE_NODE(node, down->bits), down); -- rcu_assign_pointer(CHOOSE_NODE(node, newnode->bits), newnode); -- if (!parent) -- rcu_assign_pointer(*trie, node); -- else -- rcu_assign_pointer(CHOOSE_NODE(parent, node->bits), -- node); -+ node = kmem_cache_zalloc(node_cache, GFP_KERNEL); -+ if (unlikely(!node)) { -+ list_del(&newnode->peer_list); -+ kmem_cache_free(node_cache, newnode); -+ return -ENOMEM; - } -+ INIT_LIST_HEAD(&node->peer_list); -+ copy_and_assign_cidr(node, newnode->bits, cidr, bits); -+ -+ choose_and_connect_node(node, down); -+ choose_and_connect_node(node, newnode); -+ if (!parent) -+ connect_node(trie, 2, node); -+ else -+ choose_and_connect_node(parent, node); - return 0; - } - -@@ -335,9 +300,41 @@ int wg_allowedips_insert_v6(struct allowedips *table, const struct in6_addr *ip, - void wg_allowedips_remove_by_peer(struct allowedips *table, - struct wg_peer *peer, struct mutex *lock) - { -+ struct allowedips_node *node, *child, **parent_bit, *parent, *tmp; -+ bool free_parent; -+ -+ if (list_empty(&peer->allowedips_list)) -+ return; - ++table->seq; -- walk_remove_by_peer(&table->root4, peer, lock); -- walk_remove_by_peer(&table->root6, peer, lock); -+ list_for_each_entry_safe(node, tmp, &peer->allowedips_list, peer_list) { -+ list_del_init(&node->peer_list); -+ RCU_INIT_POINTER(node->peer, NULL); -+ if (node->bit[0] && node->bit[1]) -+ continue; -+ child = rcu_dereference_protected(node->bit[!rcu_access_pointer(node->bit[0])], -+ lockdep_is_held(lock)); -+ if (child) -+ child->parent_bit_packed = node->parent_bit_packed; -+ parent_bit = (struct allowedips_node **)(node->parent_bit_packed & ~3UL); -+ *parent_bit = child; -+ parent = (void *)parent_bit - -+ offsetof(struct allowedips_node, bit[node->parent_bit_packed & 1]); -+ free_parent = !rcu_access_pointer(node->bit[0]) && -+ !rcu_access_pointer(node->bit[1]) && -+ (node->parent_bit_packed & 3) <= 1 && -+ !rcu_access_pointer(parent->peer); -+ if (free_parent) -+ child = rcu_dereference_protected( -+ parent->bit[!(node->parent_bit_packed & 1)], -+ lockdep_is_held(lock)); -+ call_rcu(&node->rcu, node_free_rcu); -+ if (!free_parent) -+ continue; -+ if (child) -+ child->parent_bit_packed = parent->parent_bit_packed; -+ *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child; -+ call_rcu(&parent->rcu, node_free_rcu); -+ } - } - - int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr) -@@ -374,4 +371,16 @@ struct wg_peer *wg_allowedips_lookup_src(struct allowedips *table, - return NULL; - } - -+int __init wg_allowedips_slab_init(void) -+{ -+ node_cache = KMEM_CACHE(allowedips_node, 0); -+ return node_cache ? 0 : -ENOMEM; -+} -+ -+void wg_allowedips_slab_uninit(void) -+{ -+ rcu_barrier(); -+ kmem_cache_destroy(node_cache); -+} -+ - #include "selftest/allowedips.c" -diff --git a/drivers/net/wireguard/allowedips.h b/drivers/net/wireguard/allowedips.h -index e5c83cafcef4c..2346c797eb4d8 100644 ---- a/drivers/net/wireguard/allowedips.h -+++ b/drivers/net/wireguard/allowedips.h -@@ -15,14 +15,11 @@ struct wg_peer; - struct allowedips_node { - struct wg_peer __rcu *peer; - struct allowedips_node __rcu *bit[2]; -- /* While it may seem scandalous that we waste space for v4, -- * we're alloc'ing to the nearest power of 2 anyway, so this -- * doesn't actually make a difference. -- */ -- u8 bits[16] __aligned(__alignof(u64)); - u8 cidr, bit_at_a, bit_at_b, bitlen; -+ u8 bits[16] __aligned(__alignof(u64)); - -- /* Keep rarely used list at bottom to be beyond cache line. */ -+ /* Keep rarely used members at bottom to be beyond cache line. */ -+ unsigned long parent_bit_packed; - union { - struct list_head peer_list; - struct rcu_head rcu; -@@ -33,7 +30,7 @@ struct allowedips { - struct allowedips_node __rcu *root4; - struct allowedips_node __rcu *root6; - u64 seq; --}; -+} __aligned(4); /* We pack the lower 2 bits of &root, but m68k only gives 16-bit alignment. */ - - void wg_allowedips_init(struct allowedips *table); - void wg_allowedips_free(struct allowedips *table, struct mutex *mutex); -@@ -56,4 +53,7 @@ struct wg_peer *wg_allowedips_lookup_src(struct allowedips *table, - bool wg_allowedips_selftest(void); - #endif - -+int wg_allowedips_slab_init(void); -+void wg_allowedips_slab_uninit(void); -+ - #endif /* _WG_ALLOWEDIPS_H */ -diff --git a/drivers/net/wireguard/main.c b/drivers/net/wireguard/main.c -index 7a7d5f1a80fc7..75dbe77b0b4b4 100644 ---- a/drivers/net/wireguard/main.c -+++ b/drivers/net/wireguard/main.c -@@ -21,13 +21,22 @@ static int __init mod_init(void) - { - int ret; - -+ ret = wg_allowedips_slab_init(); -+ if (ret < 0) -+ goto err_allowedips; -+ - #ifdef DEBUG -+ ret = -ENOTRECOVERABLE; - if (!wg_allowedips_selftest() || !wg_packet_counter_selftest() || - !wg_ratelimiter_selftest()) -- return -ENOTRECOVERABLE; -+ goto err_peer; - #endif - wg_noise_init(); - -+ ret = wg_peer_init(); -+ if (ret < 0) -+ goto err_peer; -+ - ret = wg_device_init(); - if (ret < 0) - goto err_device; -@@ -44,6 +53,10 @@ static int __init mod_init(void) - err_netlink: - wg_device_uninit(); - err_device: -+ wg_peer_uninit(); -+err_peer: -+ wg_allowedips_slab_uninit(); -+err_allowedips: - return ret; - } - -@@ -51,6 +64,8 @@ static void __exit mod_exit(void) - { - wg_genetlink_uninit(); - wg_device_uninit(); -+ wg_peer_uninit(); -+ wg_allowedips_slab_uninit(); - } - - module_init(mod_init); -diff --git a/drivers/net/wireguard/peer.c b/drivers/net/wireguard/peer.c -index cd5cb0292cb67..1acd00ab2fbcb 100644 ---- a/drivers/net/wireguard/peer.c -+++ b/drivers/net/wireguard/peer.c -@@ -15,6 +15,7 @@ - #include - #include - -+static struct kmem_cache *peer_cache; - static atomic64_t peer_counter = ATOMIC64_INIT(0); - - struct wg_peer *wg_peer_create(struct wg_device *wg, -@@ -29,10 +30,10 @@ struct wg_peer *wg_peer_create(struct wg_device *wg, - if (wg->num_peers >= MAX_PEERS_PER_DEVICE) - return ERR_PTR(ret); - -- peer = kzalloc(sizeof(*peer), GFP_KERNEL); -+ peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL); - if (unlikely(!peer)) - return ERR_PTR(ret); -- if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)) -+ if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))) - goto err; - - peer->device = wg; -@@ -64,7 +65,7 @@ struct wg_peer *wg_peer_create(struct wg_device *wg, - return peer; - - err: -- kfree(peer); -+ kmem_cache_free(peer_cache, peer); - return ERR_PTR(ret); - } - -@@ -88,7 +89,7 @@ static void peer_make_dead(struct wg_peer *peer) - /* Mark as dead, so that we don't allow jumping contexts after. */ - WRITE_ONCE(peer->is_dead, true); - -- /* The caller must now synchronize_rcu() for this to take effect. */ -+ /* The caller must now synchronize_net() for this to take effect. */ - } - - static void peer_remove_after_dead(struct wg_peer *peer) -@@ -160,7 +161,7 @@ void wg_peer_remove(struct wg_peer *peer) - lockdep_assert_held(&peer->device->device_update_lock); - - peer_make_dead(peer); -- synchronize_rcu(); -+ synchronize_net(); - peer_remove_after_dead(peer); - } - -@@ -178,7 +179,7 @@ void wg_peer_remove_all(struct wg_device *wg) - peer_make_dead(peer); - list_add_tail(&peer->peer_list, &dead_peers); - } -- synchronize_rcu(); -+ synchronize_net(); - list_for_each_entry_safe(peer, temp, &dead_peers, peer_list) - peer_remove_after_dead(peer); - } -@@ -193,7 +194,8 @@ static void rcu_release(struct rcu_head *rcu) - /* The final zeroing takes care of clearing any remaining handshake key - * material and other potentially sensitive information. - */ -- kfree_sensitive(peer); -+ memzero_explicit(peer, sizeof(*peer)); -+ kmem_cache_free(peer_cache, peer); - } - - static void kref_release(struct kref *refcount) -@@ -225,3 +227,14 @@ void wg_peer_put(struct wg_peer *peer) - return; - kref_put(&peer->refcount, kref_release); - } -+ -+int __init wg_peer_init(void) -+{ -+ peer_cache = KMEM_CACHE(wg_peer, 0); -+ return peer_cache ? 0 : -ENOMEM; -+} -+ -+void wg_peer_uninit(void) -+{ -+ kmem_cache_destroy(peer_cache); -+} -diff --git a/drivers/net/wireguard/peer.h b/drivers/net/wireguard/peer.h -index 8d53b687a1d16..76e4d3128ad4e 100644 ---- a/drivers/net/wireguard/peer.h -+++ b/drivers/net/wireguard/peer.h -@@ -80,4 +80,7 @@ void wg_peer_put(struct wg_peer *peer); - void wg_peer_remove(struct wg_peer *peer); - void wg_peer_remove_all(struct wg_device *wg); - -+int wg_peer_init(void); -+void wg_peer_uninit(void); -+ - #endif /* _WG_PEER_H */ -diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c -index 846db14cb046b..e173204ae7d78 100644 ---- a/drivers/net/wireguard/selftest/allowedips.c -+++ b/drivers/net/wireguard/selftest/allowedips.c -@@ -19,32 +19,22 @@ - - #include - --static __init void swap_endian_and_apply_cidr(u8 *dst, const u8 *src, u8 bits, -- u8 cidr) --{ -- swap_endian(dst, src, bits); -- memset(dst + (cidr + 7) / 8, 0, bits / 8 - (cidr + 7) / 8); -- if (cidr) -- dst[(cidr + 7) / 8 - 1] &= ~0U << ((8 - (cidr % 8)) % 8); --} -- - static __init void print_node(struct allowedips_node *node, u8 bits) - { - char *fmt_connection = KERN_DEBUG "\t\"%p/%d\" -> \"%p/%d\";\n"; -- char *fmt_declaration = KERN_DEBUG -- "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n"; -+ char *fmt_declaration = KERN_DEBUG "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n"; -+ u8 ip1[16], ip2[16], cidr1, cidr2; - char *style = "dotted"; -- u8 ip1[16], ip2[16]; - u32 color = 0; - -+ if (node == NULL) -+ return; - if (bits == 32) { - fmt_connection = KERN_DEBUG "\t\"%pI4/%d\" -> \"%pI4/%d\";\n"; -- fmt_declaration = KERN_DEBUG -- "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n"; -+ fmt_declaration = KERN_DEBUG "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n"; - } else if (bits == 128) { - fmt_connection = KERN_DEBUG "\t\"%pI6/%d\" -> \"%pI6/%d\";\n"; -- fmt_declaration = KERN_DEBUG -- "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n"; -+ fmt_declaration = KERN_DEBUG "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n"; - } - if (node->peer) { - hsiphash_key_t key = { { 0 } }; -@@ -55,24 +45,20 @@ static __init void print_node(struct allowedips_node *node, u8 bits) - hsiphash_1u32(0xabad1dea, &key) % 200; - style = "bold"; - } -- swap_endian_and_apply_cidr(ip1, node->bits, bits, node->cidr); -- printk(fmt_declaration, ip1, node->cidr, style, color); -+ wg_allowedips_read_node(node, ip1, &cidr1); -+ printk(fmt_declaration, ip1, cidr1, style, color); - if (node->bit[0]) { -- swap_endian_and_apply_cidr(ip2, -- rcu_dereference_raw(node->bit[0])->bits, bits, -- node->cidr); -- printk(fmt_connection, ip1, node->cidr, ip2, -- rcu_dereference_raw(node->bit[0])->cidr); -- print_node(rcu_dereference_raw(node->bit[0]), bits); -+ wg_allowedips_read_node(rcu_dereference_raw(node->bit[0]), ip2, &cidr2); -+ printk(fmt_connection, ip1, cidr1, ip2, cidr2); - } - if (node->bit[1]) { -- swap_endian_and_apply_cidr(ip2, -- rcu_dereference_raw(node->bit[1])->bits, -- bits, node->cidr); -- printk(fmt_connection, ip1, node->cidr, ip2, -- rcu_dereference_raw(node->bit[1])->cidr); -- print_node(rcu_dereference_raw(node->bit[1]), bits); -+ wg_allowedips_read_node(rcu_dereference_raw(node->bit[1]), ip2, &cidr2); -+ printk(fmt_connection, ip1, cidr1, ip2, cidr2); - } -+ if (node->bit[0]) -+ print_node(rcu_dereference_raw(node->bit[0]), bits); -+ if (node->bit[1]) -+ print_node(rcu_dereference_raw(node->bit[1]), bits); - } - - static __init void print_tree(struct allowedips_node __rcu *top, u8 bits) -@@ -121,8 +107,8 @@ static __init inline union nf_inet_addr horrible_cidr_to_mask(u8 cidr) - { - union nf_inet_addr mask; - -- memset(&mask, 0x00, 128 / 8); -- memset(&mask, 0xff, cidr / 8); -+ memset(&mask, 0, sizeof(mask)); -+ memset(&mask.all, 0xff, cidr / 8); - if (cidr % 32) - mask.all[cidr / 32] = (__force u32)htonl( - (0xFFFFFFFFUL << (32 - (cidr % 32))) & 0xFFFFFFFFUL); -@@ -149,42 +135,36 @@ horrible_mask_self(struct horrible_allowedips_node *node) - } - - static __init inline bool --horrible_match_v4(const struct horrible_allowedips_node *node, -- struct in_addr *ip) -+horrible_match_v4(const struct horrible_allowedips_node *node, struct in_addr *ip) - { - return (ip->s_addr & node->mask.ip) == node->ip.ip; - } - - static __init inline bool --horrible_match_v6(const struct horrible_allowedips_node *node, -- struct in6_addr *ip) -+horrible_match_v6(const struct horrible_allowedips_node *node, struct in6_addr *ip) - { -- return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == -- node->ip.ip6[0] && -- (ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == -- node->ip.ip6[1] && -- (ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == -- node->ip.ip6[2] && -+ return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == node->ip.ip6[0] && -+ (ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == node->ip.ip6[1] && -+ (ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == node->ip.ip6[2] && - (ip->in6_u.u6_addr32[3] & node->mask.ip6[3]) == node->ip.ip6[3]; - } - - static __init void --horrible_insert_ordered(struct horrible_allowedips *table, -- struct horrible_allowedips_node *node) -+horrible_insert_ordered(struct horrible_allowedips *table, struct horrible_allowedips_node *node) - { - struct horrible_allowedips_node *other = NULL, *where = NULL; - u8 my_cidr = horrible_mask_to_cidr(node->mask); - - hlist_for_each_entry(other, &table->head, table) { -- if (!memcmp(&other->mask, &node->mask, -- sizeof(union nf_inet_addr)) && -- !memcmp(&other->ip, &node->ip, -- sizeof(union nf_inet_addr)) && -- other->ip_version == node->ip_version) { -+ if (other->ip_version == node->ip_version && -+ !memcmp(&other->mask, &node->mask, sizeof(union nf_inet_addr)) && -+ !memcmp(&other->ip, &node->ip, sizeof(union nf_inet_addr))) { - other->value = node->value; - kfree(node); - return; - } -+ } -+ hlist_for_each_entry(other, &table->head, table) { - where = other; - if (horrible_mask_to_cidr(other->mask) <= my_cidr) - break; -@@ -201,8 +181,7 @@ static __init int - horrible_allowedips_insert_v4(struct horrible_allowedips *table, - struct in_addr *ip, u8 cidr, void *value) - { -- struct horrible_allowedips_node *node = kzalloc(sizeof(*node), -- GFP_KERNEL); -+ struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); - - if (unlikely(!node)) - return -ENOMEM; -@@ -219,8 +198,7 @@ static __init int - horrible_allowedips_insert_v6(struct horrible_allowedips *table, - struct in6_addr *ip, u8 cidr, void *value) - { -- struct horrible_allowedips_node *node = kzalloc(sizeof(*node), -- GFP_KERNEL); -+ struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); - - if (unlikely(!node)) - return -ENOMEM; -@@ -234,39 +212,43 @@ horrible_allowedips_insert_v6(struct horrible_allowedips *table, - } - - static __init void * --horrible_allowedips_lookup_v4(struct horrible_allowedips *table, -- struct in_addr *ip) -+horrible_allowedips_lookup_v4(struct horrible_allowedips *table, struct in_addr *ip) - { - struct horrible_allowedips_node *node; -- void *ret = NULL; - - hlist_for_each_entry(node, &table->head, table) { -- if (node->ip_version != 4) -- continue; -- if (horrible_match_v4(node, ip)) { -- ret = node->value; -- break; -- } -+ if (node->ip_version == 4 && horrible_match_v4(node, ip)) -+ return node->value; - } -- return ret; -+ return NULL; - } - - static __init void * --horrible_allowedips_lookup_v6(struct horrible_allowedips *table, -- struct in6_addr *ip) -+horrible_allowedips_lookup_v6(struct horrible_allowedips *table, struct in6_addr *ip) - { - struct horrible_allowedips_node *node; -- void *ret = NULL; - - hlist_for_each_entry(node, &table->head, table) { -- if (node->ip_version != 6) -+ if (node->ip_version == 6 && horrible_match_v6(node, ip)) -+ return node->value; -+ } -+ return NULL; -+} -+ -+ -+static __init void -+horrible_allowedips_remove_by_value(struct horrible_allowedips *table, void *value) -+{ -+ struct horrible_allowedips_node *node; -+ struct hlist_node *h; -+ -+ hlist_for_each_entry_safe(node, h, &table->head, table) { -+ if (node->value != value) - continue; -- if (horrible_match_v6(node, ip)) { -- ret = node->value; -- break; -- } -+ hlist_del(&node->table); -+ kfree(node); - } -- return ret; -+ - } - - static __init bool randomized_test(void) -@@ -296,6 +278,7 @@ static __init bool randomized_test(void) - goto free; - } - kref_init(&peers[i]->refcount); -+ INIT_LIST_HEAD(&peers[i]->allowedips_list); - } - - mutex_lock(&mutex); -@@ -333,7 +316,7 @@ static __init bool randomized_test(void) - if (wg_allowedips_insert_v4(&t, - (struct in_addr *)mutated, - cidr, peer, &mutex) < 0) { -- pr_err("allowedips random malloc: FAIL\n"); -+ pr_err("allowedips random self-test malloc: FAIL\n"); - goto free_locked; - } - if (horrible_allowedips_insert_v4(&h, -@@ -396,23 +379,33 @@ static __init bool randomized_test(void) - print_tree(t.root6, 128); - } - -- for (i = 0; i < NUM_QUERIES; ++i) { -- prandom_bytes(ip, 4); -- if (lookup(t.root4, 32, ip) != -- horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) { -- pr_err("allowedips random self-test: FAIL\n"); -- goto free; -+ for (j = 0;; ++j) { -+ for (i = 0; i < NUM_QUERIES; ++i) { -+ prandom_bytes(ip, 4); -+ if (lookup(t.root4, 32, ip) != horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) { -+ horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip); -+ pr_err("allowedips random v4 self-test: FAIL\n"); -+ goto free; -+ } -+ prandom_bytes(ip, 16); -+ if (lookup(t.root6, 128, ip) != horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) { -+ pr_err("allowedips random v6 self-test: FAIL\n"); -+ goto free; -+ } - } -+ if (j >= NUM_PEERS) -+ break; -+ mutex_lock(&mutex); -+ wg_allowedips_remove_by_peer(&t, peers[j], &mutex); -+ mutex_unlock(&mutex); -+ horrible_allowedips_remove_by_value(&h, peers[j]); - } - -- for (i = 0; i < NUM_QUERIES; ++i) { -- prandom_bytes(ip, 16); -- if (lookup(t.root6, 128, ip) != -- horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) { -- pr_err("allowedips random self-test: FAIL\n"); -- goto free; -- } -+ if (t.root4 || t.root6) { -+ pr_err("allowedips random self-test removal: FAIL\n"); -+ goto free; - } -+ - ret = true; - - free: -diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c -index d9ad850daa793..8c496b7471082 100644 ---- a/drivers/net/wireguard/socket.c -+++ b/drivers/net/wireguard/socket.c -@@ -430,7 +430,7 @@ void wg_socket_reinit(struct wg_device *wg, struct sock *new4, - if (new4) - wg->incoming_port = ntohs(inet_sk(new4)->inet_sport); - mutex_unlock(&wg->socket_update_lock); -- synchronize_rcu(); -+ synchronize_net(); - sock_free(old4); - sock_free(old6); - } -diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c -index 02d0aa0b815e9..d2489dc9dc139 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c -+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c -@@ -87,7 +87,7 @@ static const struct ieee80211_ops mt76x0e_ops = { - .reconfig_complete = mt76x02_reconfig_complete, - }; - --static int mt76x0e_register_device(struct mt76x02_dev *dev) -+static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume) - { - int err; - -@@ -100,9 +100,11 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) - if (err < 0) - return err; - -- err = mt76x02_dma_init(dev); -- if (err < 0) -- return err; -+ if (!resume) { -+ err = mt76x02_dma_init(dev); -+ if (err < 0) -+ return err; -+ } - - err = mt76x0_init_hardware(dev); - if (err < 0) -@@ -123,6 +125,17 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) - mt76_clear(dev, 0x110, BIT(9)); - mt76_set(dev, MT_MAX_LEN_CFG, BIT(13)); - -+ return 0; -+} -+ -+static int mt76x0e_register_device(struct mt76x02_dev *dev) -+{ -+ int err; -+ -+ err = mt76x0e_init_hardware(dev, false); -+ if (err < 0) -+ return err; -+ - err = mt76x0_register_device(dev); - if (err < 0) - return err; -@@ -167,6 +180,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) - if (ret) - return ret; - -+ mt76_pci_disable_aspm(pdev); -+ - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops, - &drv_ops); - if (!mdev) -@@ -220,6 +235,60 @@ mt76x0e_remove(struct pci_dev *pdev) - mt76_free_device(mdev); - } - -+#ifdef CONFIG_PM -+static int mt76x0e_suspend(struct pci_dev *pdev, pm_message_t state) -+{ -+ struct mt76_dev *mdev = pci_get_drvdata(pdev); -+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); -+ int i; -+ -+ mt76_worker_disable(&mdev->tx_worker); -+ for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++) -+ mt76_queue_tx_cleanup(dev, mdev->phy.q_tx[i], true); -+ for (i = 0; i < ARRAY_SIZE(mdev->q_mcu); i++) -+ mt76_queue_tx_cleanup(dev, mdev->q_mcu[i], true); -+ napi_disable(&mdev->tx_napi); -+ -+ mt76_for_each_q_rx(mdev, i) -+ napi_disable(&mdev->napi[i]); -+ -+ mt76x02_dma_disable(dev); -+ mt76x02_mcu_cleanup(dev); -+ mt76x0_chip_onoff(dev, false, false); -+ -+ pci_enable_wake(pdev, pci_choose_state(pdev, state), true); -+ pci_save_state(pdev); -+ -+ return pci_set_power_state(pdev, pci_choose_state(pdev, state)); -+} -+ -+static int mt76x0e_resume(struct pci_dev *pdev) -+{ -+ struct mt76_dev *mdev = pci_get_drvdata(pdev); -+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); -+ int err, i; -+ -+ err = pci_set_power_state(pdev, PCI_D0); -+ if (err) -+ return err; -+ -+ pci_restore_state(pdev); -+ -+ mt76_worker_enable(&mdev->tx_worker); -+ -+ mt76_for_each_q_rx(mdev, i) { -+ mt76_queue_rx_reset(dev, i); -+ napi_enable(&mdev->napi[i]); -+ napi_schedule(&mdev->napi[i]); -+ } -+ -+ napi_enable(&mdev->tx_napi); -+ napi_schedule(&mdev->tx_napi); -+ -+ return mt76x0e_init_hardware(dev, true); -+} -+#endif /* CONFIG_PM */ -+ - static const struct pci_device_id mt76x0e_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7610) }, - { PCI_DEVICE(0x14c3, 0x7630) }, -@@ -237,6 +306,10 @@ static struct pci_driver mt76x0e_driver = { - .id_table = mt76x0e_device_table, - .probe = mt76x0e_probe, - .remove = mt76x0e_remove, -+#ifdef CONFIG_PM -+ .suspend = mt76x0e_suspend, -+ .resume = mt76x0e_resume, -+#endif /* CONFIG_PM */ - }; - - module_pci_driver(mt76x0e_driver); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -index 62afbad77596b..be88c9f5637a5 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -@@ -391,29 +391,37 @@ static void - mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb, - u16 wlan_idx) - { -- struct mt7921_mcu_wlan_info_event *wtbl_info = -- (struct mt7921_mcu_wlan_info_event *)(skb->data); -- struct rate_info rate = {}; -- u8 curr_idx = wtbl_info->rate_info.rate_idx; -- u16 curr = le16_to_cpu(wtbl_info->rate_info.rate[curr_idx]); -- struct mt7921_mcu_peer_cap peer = wtbl_info->peer_cap; -+ struct mt7921_mcu_wlan_info_event *wtbl_info; - struct mt76_phy *mphy = &dev->mphy; - struct mt7921_sta_stats *stats; -+ struct rate_info rate = {}; - struct mt7921_sta *msta; - struct mt76_wcid *wcid; -+ u8 idx; - - if (wlan_idx >= MT76_N_WCIDS) - return; -+ -+ wtbl_info = (struct mt7921_mcu_wlan_info_event *)skb->data; -+ idx = wtbl_info->rate_info.rate_idx; -+ if (idx >= ARRAY_SIZE(wtbl_info->rate_info.rate)) -+ return; -+ -+ rcu_read_lock(); -+ - wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); - if (!wcid) -- return; -+ goto out; - - msta = container_of(wcid, struct mt7921_sta, wcid); - stats = &msta->stats; - - /* current rate */ -- mt7921_mcu_tx_rate_parse(mphy, &peer, &rate, curr); -+ mt7921_mcu_tx_rate_parse(mphy, &wtbl_info->peer_cap, &rate, -+ le16_to_cpu(wtbl_info->rate_info.rate[idx])); - stats->tx_rate = rate; -+out: -+ rcu_read_unlock(); - } - - static void -diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c -index 193b723fe3bd7..c58996c1e2309 100644 ---- a/drivers/net/xen-netback/interface.c -+++ b/drivers/net/xen-netback/interface.c -@@ -684,6 +684,7 @@ static void xenvif_disconnect_queue(struct xenvif_queue *queue) - { - if (queue->task) { - kthread_stop(queue->task); -+ put_task_struct(queue->task); - queue->task = NULL; - } - -@@ -745,6 +746,11 @@ int xenvif_connect_data(struct xenvif_queue *queue, - if (IS_ERR(task)) - goto kthread_err; - queue->task = task; -+ /* -+ * Take a reference to the task in order to prevent it from being freed -+ * if the thread function returns before kthread_stop is called. -+ */ -+ get_task_struct(task); - - task = kthread_run(xenvif_dealloc_kthread, queue, - "%s-dealloc", queue->name); -diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c -index be905d4fdb47f..ce8b3ce7582be 100644 ---- a/drivers/nvme/host/rdma.c -+++ b/drivers/nvme/host/rdma.c -@@ -1319,16 +1319,17 @@ static int nvme_rdma_map_sg_inline(struct nvme_rdma_queue *queue, - int count) - { - struct nvme_sgl_desc *sg = &c->common.dptr.sgl; -- struct scatterlist *sgl = req->data_sgl.sg_table.sgl; - struct ib_sge *sge = &req->sge[1]; -+ struct scatterlist *sgl; - u32 len = 0; - int i; - -- for (i = 0; i < count; i++, sgl++, sge++) { -+ for_each_sg(req->data_sgl.sg_table.sgl, sgl, count, i) { - sge->addr = sg_dma_address(sgl); - sge->length = sg_dma_len(sgl); - sge->lkey = queue->device->pd->local_dma_lkey; - len += sge->length; -+ sge++; - } - - sg->addr = cpu_to_le64(queue->ctrl->ctrl.icdoff); -diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c -index 348057fdc568f..7d16cb4cd8acf 100644 ---- a/drivers/nvme/target/core.c -+++ b/drivers/nvme/target/core.c -@@ -999,19 +999,23 @@ static unsigned int nvmet_data_transfer_len(struct nvmet_req *req) - return req->transfer_len - req->metadata_len; - } - --static int nvmet_req_alloc_p2pmem_sgls(struct nvmet_req *req) -+static int nvmet_req_alloc_p2pmem_sgls(struct pci_dev *p2p_dev, -+ struct nvmet_req *req) - { -- req->sg = pci_p2pmem_alloc_sgl(req->p2p_dev, &req->sg_cnt, -+ req->sg = pci_p2pmem_alloc_sgl(p2p_dev, &req->sg_cnt, - nvmet_data_transfer_len(req)); - if (!req->sg) - goto out_err; - - if (req->metadata_len) { -- req->metadata_sg = pci_p2pmem_alloc_sgl(req->p2p_dev, -+ req->metadata_sg = pci_p2pmem_alloc_sgl(p2p_dev, - &req->metadata_sg_cnt, req->metadata_len); - if (!req->metadata_sg) - goto out_free_sg; - } -+ -+ req->p2p_dev = p2p_dev; -+ - return 0; - out_free_sg: - pci_p2pmem_free_sgl(req->p2p_dev, req->sg); -@@ -1019,25 +1023,19 @@ out_err: - return -ENOMEM; - } - --static bool nvmet_req_find_p2p_dev(struct nvmet_req *req) -+static struct pci_dev *nvmet_req_find_p2p_dev(struct nvmet_req *req) - { -- if (!IS_ENABLED(CONFIG_PCI_P2PDMA)) -- return false; -- -- if (req->sq->ctrl && req->sq->qid && req->ns) { -- req->p2p_dev = radix_tree_lookup(&req->sq->ctrl->p2p_ns_map, -- req->ns->nsid); -- if (req->p2p_dev) -- return true; -- } -- -- req->p2p_dev = NULL; -- return false; -+ if (!IS_ENABLED(CONFIG_PCI_P2PDMA) || -+ !req->sq->ctrl || !req->sq->qid || !req->ns) -+ return NULL; -+ return radix_tree_lookup(&req->sq->ctrl->p2p_ns_map, req->ns->nsid); - } - - int nvmet_req_alloc_sgls(struct nvmet_req *req) - { -- if (nvmet_req_find_p2p_dev(req) && !nvmet_req_alloc_p2pmem_sgls(req)) -+ struct pci_dev *p2p_dev = nvmet_req_find_p2p_dev(req); -+ -+ if (p2p_dev && !nvmet_req_alloc_p2pmem_sgls(p2p_dev, req)) - return 0; - - req->sg = sgl_alloc(nvmet_data_transfer_len(req), GFP_KERNEL, -@@ -1066,6 +1064,7 @@ void nvmet_req_free_sgls(struct nvmet_req *req) - pci_p2pmem_free_sgl(req->p2p_dev, req->sg); - if (req->metadata_sg) - pci_p2pmem_free_sgl(req->p2p_dev, req->metadata_sg); -+ req->p2p_dev = NULL; - } else { - sgl_free(req->sg); - if (req->metadata_sg) -diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c -index 920cf329268b5..f8a5a4eb5bcef 100644 ---- a/drivers/scsi/lpfc/lpfc_sli.c -+++ b/drivers/scsi/lpfc/lpfc_sli.c -@@ -20591,10 +20591,8 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - abtswqe = &abtsiocb->wqe; - memset(abtswqe, 0, sizeof(*abtswqe)); - -- if (lpfc_is_link_up(phba)) -+ if (!lpfc_is_link_up(phba)) - bf_set(abort_cmd_ia, &abtswqe->abort_cmd, 1); -- else -- bf_set(abort_cmd_ia, &abtswqe->abort_cmd, 0); - bf_set(abort_cmd_criteria, &abtswqe->abort_cmd, T_XRI_TAG); - abtswqe->abort_cmd.rsrvd5 = 0; - abtswqe->abort_cmd.wqe_com.abort_tag = xritag; -diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c -index 7a77e375b503c..6b52f0c526baa 100644 ---- a/drivers/tee/optee/call.c -+++ b/drivers/tee/optee/call.c -@@ -216,6 +216,7 @@ int optee_open_session(struct tee_context *ctx, - struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; - struct optee_session *sess = NULL; -+ uuid_t client_uuid; - - /* +2 for the meta parameters added below */ - shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg); -@@ -236,10 +237,11 @@ int optee_open_session(struct tee_context *ctx, - memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); - msg_arg->params[1].u.value.c = arg->clnt_login; - -- rc = tee_session_calc_client_uuid((uuid_t *)&msg_arg->params[1].u.value, -- arg->clnt_login, arg->clnt_uuid); -+ rc = tee_session_calc_client_uuid(&client_uuid, arg->clnt_login, -+ arg->clnt_uuid); - if (rc) - goto out; -+ export_uuid(msg_arg->params[1].u.octets, &client_uuid); - - rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param); - if (rc) -diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h -index 81ff593ac4ec2..e3d72d09c4848 100644 ---- a/drivers/tee/optee/optee_msg.h -+++ b/drivers/tee/optee/optee_msg.h -@@ -9,7 +9,7 @@ - #include - - /* -- * This file defines the OP-TEE message protocol used to communicate -+ * This file defines the OP-TEE message protocol (ABI) used to communicate - * with an instance of OP-TEE running in secure world. - * - * This file is divided into two sections. -@@ -144,9 +144,10 @@ struct optee_msg_param_value { - * @tmem: parameter by temporary memory reference - * @rmem: parameter by registered memory reference - * @value: parameter by opaque value -+ * @octets: parameter by octet string - * - * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in -- * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, -+ * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value or octets, - * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and - * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem, - * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. -@@ -157,6 +158,7 @@ struct optee_msg_param { - struct optee_msg_param_tmem tmem; - struct optee_msg_param_rmem rmem; - struct optee_msg_param_value value; -+ u8 octets[24]; - } u; - }; - -diff --git a/drivers/thermal/intel/therm_throt.c b/drivers/thermal/intel/therm_throt.c -index f8e882592ba5d..99abdc03c44ce 100644 ---- a/drivers/thermal/intel/therm_throt.c -+++ b/drivers/thermal/intel/therm_throt.c -@@ -621,6 +621,17 @@ bool x86_thermal_enabled(void) - return atomic_read(&therm_throt_en); - } - -+void __init therm_lvt_init(void) -+{ -+ /* -+ * This function is only called on boot CPU. Save the init thermal -+ * LVT value on BSP and use that value to restore APs' thermal LVT -+ * entry BIOS programmed later -+ */ -+ if (intel_thermal_supported(&boot_cpu_data)) -+ lvtthmr_init = apic_read(APIC_LVTTHMR); -+} -+ - void intel_init_thermal(struct cpuinfo_x86 *c) - { - unsigned int cpu = smp_processor_id(); -@@ -630,10 +641,6 @@ void intel_init_thermal(struct cpuinfo_x86 *c) - if (!intel_thermal_supported(c)) - return; - -- /* On the BSP? */ -- if (c == &boot_cpu_data) -- lvtthmr_init = apic_read(APIC_LVTTHMR); -- - /* - * First check if its enabled already, in which case there might - * be some SMM goo which handles it, so we can't even put a handler -diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c -index 99dfa884cbefb..68c6535bbf7f0 100644 ---- a/drivers/tty/serial/stm32-usart.c -+++ b/drivers/tty/serial/stm32-usart.c -@@ -214,14 +214,11 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) - struct tty_port *tport = &port->state->port; - struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -- unsigned long c, flags; -+ unsigned long c; - u32 sr; - char flag; - -- if (threaded) -- spin_lock_irqsave(&port->lock, flags); -- else -- spin_lock(&port->lock); -+ spin_lock(&port->lock); - - while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res, - threaded)) { -@@ -278,10 +275,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) - uart_insert_char(port, sr, USART_SR_ORE, c, flag); - } - -- if (threaded) -- spin_unlock_irqrestore(&port->lock, flags); -- else -- spin_unlock(&port->lock); -+ spin_unlock(&port->lock); - - tty_flip_buffer_push(tport); - } -@@ -654,7 +648,8 @@ static int stm32_usart_startup(struct uart_port *port) - - ret = request_threaded_irq(port->irq, stm32_usart_interrupt, - stm32_usart_threaded_interrupt, -- IRQF_NO_SUSPEND, name, port); -+ IRQF_ONESHOT | IRQF_NO_SUSPEND, -+ name, port); - if (ret) - return ret; - -@@ -1136,6 +1131,13 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, - struct dma_async_tx_descriptor *desc = NULL; - int ret; - -+ /* -+ * Using DMA and threaded handler for the console could lead to -+ * deadlocks. -+ */ -+ if (uart_console(port)) -+ return -ENODEV; -+ - /* Request DMA RX channel */ - stm32port->rx_ch = dma_request_slave_channel(dev, "rx"); - if (!stm32port->rx_ch) { -diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c -index 510fd0572feb1..e3f429f1575e9 100644 ---- a/drivers/usb/dwc2/core_intr.c -+++ b/drivers/usb/dwc2/core_intr.c -@@ -707,7 +707,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg, - dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN); - - hsotg->hibernated = 0; -+ -+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || \ -+ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) - hsotg->bus_suspended = 0; -+#endif - - if (gpwrdn & GPWRDN_IDSTS) { - hsotg->op_state = OTG_STATE_B_PERIPHERAL; -diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig -index 4abddbebd4b23..c691127bc805a 100644 ---- a/drivers/vfio/pci/Kconfig -+++ b/drivers/vfio/pci/Kconfig -@@ -2,6 +2,7 @@ - config VFIO_PCI - tristate "VFIO support for PCI devices" - depends on VFIO && PCI && EVENTFD -+ depends on MMU - select VFIO_VIRQFD - select IRQ_BYPASS_MANAGER - help -diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c -index a402adee8a215..47f21a6ca7fe9 100644 ---- a/drivers/vfio/pci/vfio_pci_config.c -+++ b/drivers/vfio/pci/vfio_pci_config.c -@@ -1581,7 +1581,7 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev) - if (len == 0xFF) { - len = vfio_ext_cap_len(vdev, ecap, epos); - if (len < 0) -- return ret; -+ return len; - } - } - -diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c -index fb4b385191f28..e83a7cd15c956 100644 ---- a/drivers/vfio/platform/vfio_platform_common.c -+++ b/drivers/vfio/platform/vfio_platform_common.c -@@ -289,7 +289,7 @@ err_irq: - vfio_platform_regions_cleanup(vdev); - err_reg: - mutex_unlock(&driver_lock); -- module_put(THIS_MODULE); -+ module_put(vdev->parent_module); - return ret; - } - -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 5b82050b871a7..27c3680074814 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -1868,7 +1868,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, - trace_run_delayed_ref_head(fs_info, head, 0); - btrfs_delayed_ref_unlock(head); - btrfs_put_delayed_ref_head(head); -- return 0; -+ return ret; - } - - static struct btrfs_delayed_ref_head *btrfs_obtain_ref_head( -diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c -index 47cd3a6dc6351..eed75bb0fedbf 100644 ---- a/fs/btrfs/file-item.c -+++ b/fs/btrfs/file-item.c -@@ -787,7 +787,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, - u64 end_byte = bytenr + len; - u64 csum_end; - struct extent_buffer *leaf; -- int ret; -+ int ret = 0; - const u32 csum_size = fs_info->csum_size; - u32 blocksize_bits = fs_info->sectorsize_bits; - -@@ -805,6 +805,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, - - ret = btrfs_search_slot(trans, root, &key, path, -1, 1); - if (ret > 0) { -+ ret = 0; - if (path->slots[0] == 0) - break; - path->slots[0]--; -@@ -861,7 +862,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, - ret = btrfs_del_items(trans, root, path, - path->slots[0], del_nr); - if (ret) -- goto out; -+ break; - if (key.offset == bytenr) - break; - } else if (key.offset < bytenr && csum_end > end_byte) { -@@ -905,8 +906,9 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, - ret = btrfs_split_item(trans, root, path, &key, offset); - if (ret && ret != -EAGAIN) { - btrfs_abort_transaction(trans, ret); -- goto out; -+ break; - } -+ ret = 0; - - key.offset = end_byte - 1; - } else { -@@ -916,12 +918,41 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, - } - btrfs_release_path(path); - } -- ret = 0; --out: - btrfs_free_path(path); - return ret; - } - -+static int find_next_csum_offset(struct btrfs_root *root, -+ struct btrfs_path *path, -+ u64 *next_offset) -+{ -+ const u32 nritems = btrfs_header_nritems(path->nodes[0]); -+ struct btrfs_key found_key; -+ int slot = path->slots[0] + 1; -+ int ret; -+ -+ if (nritems == 0 || slot >= nritems) { -+ ret = btrfs_next_leaf(root, path); -+ if (ret < 0) { -+ return ret; -+ } else if (ret > 0) { -+ *next_offset = (u64)-1; -+ return 0; -+ } -+ slot = path->slots[0]; -+ } -+ -+ btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); -+ -+ if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || -+ found_key.type != BTRFS_EXTENT_CSUM_KEY) -+ *next_offset = (u64)-1; -+ else -+ *next_offset = found_key.offset; -+ -+ return 0; -+} -+ - int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct btrfs_ordered_sum *sums) -@@ -937,7 +968,6 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, - u64 total_bytes = 0; - u64 csum_offset; - u64 bytenr; -- u32 nritems; - u32 ins_size; - int index = 0; - int found_next; -@@ -980,26 +1010,10 @@ again: - goto insert; - } - } else { -- int slot = path->slots[0] + 1; -- /* we didn't find a csum item, insert one */ -- nritems = btrfs_header_nritems(path->nodes[0]); -- if (!nritems || (path->slots[0] >= nritems - 1)) { -- ret = btrfs_next_leaf(root, path); -- if (ret < 0) { -- goto out; -- } else if (ret > 0) { -- found_next = 1; -- goto insert; -- } -- slot = path->slots[0]; -- } -- btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); -- if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || -- found_key.type != BTRFS_EXTENT_CSUM_KEY) { -- found_next = 1; -- goto insert; -- } -- next_offset = found_key.offset; -+ /* We didn't find a csum item, insert one. */ -+ ret = find_next_csum_offset(root, path, &next_offset); -+ if (ret < 0) -+ goto out; - found_next = 1; - goto insert; - } -@@ -1055,8 +1069,48 @@ extend_csum: - tmp = sums->len - total_bytes; - tmp >>= fs_info->sectorsize_bits; - WARN_ON(tmp < 1); -+ extend_nr = max_t(int, 1, tmp); -+ -+ /* -+ * A log tree can already have checksum items with a subset of -+ * the checksums we are trying to log. This can happen after -+ * doing a sequence of partial writes into prealloc extents and -+ * fsyncs in between, with a full fsync logging a larger subrange -+ * of an extent for which a previous fast fsync logged a smaller -+ * subrange. And this happens in particular due to merging file -+ * extent items when we complete an ordered extent for a range -+ * covered by a prealloc extent - this is done at -+ * btrfs_mark_extent_written(). -+ * -+ * So if we try to extend the previous checksum item, which has -+ * a range that ends at the start of the range we want to insert, -+ * make sure we don't extend beyond the start offset of the next -+ * checksum item. If we are at the last item in the leaf, then -+ * forget the optimization of extending and add a new checksum -+ * item - it is not worth the complexity of releasing the path, -+ * getting the first key for the next leaf, repeat the btree -+ * search, etc, because log trees are temporary anyway and it -+ * would only save a few bytes of leaf space. -+ */ -+ if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { -+ if (path->slots[0] + 1 >= -+ btrfs_header_nritems(path->nodes[0])) { -+ ret = find_next_csum_offset(root, path, &next_offset); -+ if (ret < 0) -+ goto out; -+ found_next = 1; -+ goto insert; -+ } -+ -+ ret = find_next_csum_offset(root, path, &next_offset); -+ if (ret < 0) -+ goto out; -+ -+ tmp = (next_offset - bytenr) >> fs_info->sectorsize_bits; -+ if (tmp <= INT_MAX) -+ extend_nr = min_t(int, extend_nr, tmp); -+ } - -- extend_nr = max_t(int, 1, (int)tmp); - diff = (csum_offset + extend_nr) * csum_size; - diff = min(diff, - MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size); -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 81b93c9c659b7..3bb8ce4969f31 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -3011,6 +3011,18 @@ out: - if (ret || truncated) { - u64 unwritten_start = start; - -+ /* -+ * If we failed to finish this ordered extent for any reason we -+ * need to make sure BTRFS_ORDERED_IOERR is set on the ordered -+ * extent, and mark the inode with the error if it wasn't -+ * already set. Any error during writeback would have already -+ * set the mapping error, so we need to set it if we're the ones -+ * marking this ordered extent as failed. -+ */ -+ if (ret && !test_and_set_bit(BTRFS_ORDERED_IOERR, -+ &ordered_extent->flags)) -+ mapping_set_error(ordered_extent->inode->i_mapping, -EIO); -+ - if (truncated) - unwritten_start += logical_len; - clear_extent_uptodate(io_tree, unwritten_start, end, NULL); -@@ -9076,6 +9088,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, - int ret2; - bool root_log_pinned = false; - bool dest_log_pinned = false; -+ bool need_abort = false; - - /* we only allow rename subvolume link between subvolumes */ - if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest) -@@ -9132,6 +9145,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, - old_idx); - if (ret) - goto out_fail; -+ need_abort = true; - } - - /* And now for the dest. */ -@@ -9147,8 +9161,11 @@ static int btrfs_rename_exchange(struct inode *old_dir, - new_ino, - btrfs_ino(BTRFS_I(old_dir)), - new_idx); -- if (ret) -+ if (ret) { -+ if (need_abort) -+ btrfs_abort_transaction(trans, ret); - goto out_fail; -+ } - } - - /* Update inode version and ctime/mtime. */ -diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c -index 53ee17f5e382c..238e713635d79 100644 ---- a/fs/btrfs/reflink.c -+++ b/fs/btrfs/reflink.c -@@ -207,10 +207,7 @@ static int clone_copy_inline_extent(struct inode *dst, - * inline extent's data to the page. - */ - ASSERT(key.offset > 0); -- ret = copy_inline_to_page(BTRFS_I(dst), new_key->offset, -- inline_data, size, datal, -- comp_type); -- goto out; -+ goto copy_to_page; - } - } else if (i_size_read(dst) <= datal) { - struct btrfs_file_extent_item *ei; -@@ -226,13 +223,10 @@ static int clone_copy_inline_extent(struct inode *dst, - BTRFS_FILE_EXTENT_INLINE) - goto copy_inline_extent; - -- ret = copy_inline_to_page(BTRFS_I(dst), new_key->offset, -- inline_data, size, datal, comp_type); -- goto out; -+ goto copy_to_page; - } - - copy_inline_extent: -- ret = 0; - /* - * We have no extent items, or we have an extent at offset 0 which may - * or may not be inlined. All these cases are dealt the same way. -@@ -244,11 +238,13 @@ copy_inline_extent: - * clone. Deal with all these cases by copying the inline extent - * data into the respective page at the destination inode. - */ -- ret = copy_inline_to_page(BTRFS_I(dst), new_key->offset, -- inline_data, size, datal, comp_type); -- goto out; -+ goto copy_to_page; - } - -+ /* -+ * Release path before starting a new transaction so we don't hold locks -+ * that would confuse lockdep. -+ */ - btrfs_release_path(path); - /* - * If we end up here it means were copy the inline extent into a leaf -@@ -285,11 +281,6 @@ copy_inline_extent: - ret = btrfs_inode_set_file_extent_range(BTRFS_I(dst), 0, aligned_end); - out: - if (!ret && !trans) { -- /* -- * Release path before starting a new transaction so we don't -- * hold locks that would confuse lockdep. -- */ -- btrfs_release_path(path); - /* - * No transaction here means we copied the inline extent into a - * page of the destination inode. -@@ -310,6 +301,21 @@ out: - *trans_out = trans; - - return ret; -+ -+copy_to_page: -+ /* -+ * Release our path because we don't need it anymore and also because -+ * copy_inline_to_page() needs to reserve data and metadata, which may -+ * need to flush delalloc when we are low on available space and -+ * therefore cause a deadlock if writeback of an inline extent needs to -+ * write to the same leaf or an ordered extent completion needs to write -+ * to the same leaf. -+ */ -+ btrfs_release_path(path); -+ -+ ret = copy_inline_to_page(BTRFS_I(dst), new_key->offset, -+ inline_data, size, datal, comp_type); -+ goto out; - } - - /** -diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c -index d7f1599e69b1f..faae6ebd8a279 100644 ---- a/fs/btrfs/tree-log.c -+++ b/fs/btrfs/tree-log.c -@@ -1574,7 +1574,9 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, - if (ret) - goto out; - -- btrfs_update_inode(trans, root, BTRFS_I(inode)); -+ ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); -+ if (ret) -+ goto out; - } - - ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + namelen; -@@ -1749,7 +1751,9 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, - - if (nlink != inode->i_nlink) { - set_nlink(inode, nlink); -- btrfs_update_inode(trans, root, BTRFS_I(inode)); -+ ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); -+ if (ret) -+ goto out; - } - BTRFS_I(inode)->index_cnt = (u64)-1; - -@@ -1787,6 +1791,7 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, - break; - - if (ret == 1) { -+ ret = 0; - if (path->slots[0] == 0) - break; - path->slots[0]--; -@@ -1799,17 +1804,19 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, - - ret = btrfs_del_item(trans, root, path); - if (ret) -- goto out; -+ break; - - btrfs_release_path(path); - inode = read_one_inode(root, key.offset); -- if (!inode) -- return -EIO; -+ if (!inode) { -+ ret = -EIO; -+ break; -+ } - - ret = fixup_inode_link_count(trans, root, inode); - iput(inode); - if (ret) -- goto out; -+ break; - - /* - * fixup on a directory may create new entries, -@@ -1818,8 +1825,6 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, - */ - key.offset = (u64)-1; - } -- ret = 0; --out: - btrfs_release_path(path); - return ret; - } -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 77c84d6f1af6b..cbf37b2cf871e 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -3206,7 +3206,10 @@ static int ext4_split_extent_at(handle_t *handle, - ext4_ext_mark_unwritten(ex2); - - err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags); -- if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { -+ if (err != -ENOSPC && err != -EDQUOT) -+ goto out; -+ -+ if (EXT4_EXT_MAY_ZEROOUT & split_flag) { - if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { - if (split_flag & EXT4_EXT_DATA_VALID1) { - err = ext4_ext_zeroout(inode, ex2); -@@ -3232,25 +3235,22 @@ static int ext4_split_extent_at(handle_t *handle, - ext4_ext_pblock(&orig_ex)); - } - -- if (err) -- goto fix_extent_len; -- /* update the extent length and mark as initialized */ -- ex->ee_len = cpu_to_le16(ee_len); -- ext4_ext_try_to_merge(handle, inode, path, ex); -- err = ext4_ext_dirty(handle, inode, path + path->p_depth); -- if (err) -- goto fix_extent_len; -- -- /* update extent status tree */ -- err = ext4_zeroout_es(inode, &zero_ex); -- -- goto out; -- } else if (err) -- goto fix_extent_len; -- --out: -- ext4_ext_show_leaf(inode, path); -- return err; -+ if (!err) { -+ /* update the extent length and mark as initialized */ -+ ex->ee_len = cpu_to_le16(ee_len); -+ ext4_ext_try_to_merge(handle, inode, path, ex); -+ err = ext4_ext_dirty(handle, inode, path + path->p_depth); -+ if (!err) -+ /* update extent status tree */ -+ err = ext4_zeroout_es(inode, &zero_ex); -+ /* If we failed at this point, we don't know in which -+ * state the extent tree exactly is so don't try to fix -+ * length of the original extent as it may do even more -+ * damage. -+ */ -+ goto out; -+ } -+ } - - fix_extent_len: - ex->ee_len = orig_ex.ee_len; -@@ -3260,6 +3260,9 @@ fix_extent_len: - */ - ext4_ext_dirty(handle, inode, path + path->p_depth); - return err; -+out: -+ ext4_ext_show_leaf(inode, path); -+ return err; - } - - /* -diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c -index eda14f630def4..c1c962b118012 100644 ---- a/fs/ext4/fast_commit.c -+++ b/fs/ext4/fast_commit.c -@@ -1288,28 +1288,29 @@ struct dentry_info_args { - }; - - static inline void tl_to_darg(struct dentry_info_args *darg, -- struct ext4_fc_tl *tl) -+ struct ext4_fc_tl *tl, u8 *val) - { -- struct ext4_fc_dentry_info *fcd; -+ struct ext4_fc_dentry_info fcd; - -- fcd = (struct ext4_fc_dentry_info *)ext4_fc_tag_val(tl); -+ memcpy(&fcd, val, sizeof(fcd)); - -- darg->parent_ino = le32_to_cpu(fcd->fc_parent_ino); -- darg->ino = le32_to_cpu(fcd->fc_ino); -- darg->dname = fcd->fc_dname; -- darg->dname_len = ext4_fc_tag_len(tl) - -- sizeof(struct ext4_fc_dentry_info); -+ darg->parent_ino = le32_to_cpu(fcd.fc_parent_ino); -+ darg->ino = le32_to_cpu(fcd.fc_ino); -+ darg->dname = val + offsetof(struct ext4_fc_dentry_info, fc_dname); -+ darg->dname_len = le16_to_cpu(tl->fc_len) - -+ sizeof(struct ext4_fc_dentry_info); - } - - /* Unlink replay function */ --static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl) -+static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl, -+ u8 *val) - { - struct inode *inode, *old_parent; - struct qstr entry; - struct dentry_info_args darg; - int ret = 0; - -- tl_to_darg(&darg, tl); -+ tl_to_darg(&darg, tl, val); - - trace_ext4_fc_replay(sb, EXT4_FC_TAG_UNLINK, darg.ino, - darg.parent_ino, darg.dname_len); -@@ -1399,13 +1400,14 @@ out: - } - - /* Link replay function */ --static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl) -+static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl, -+ u8 *val) - { - struct inode *inode; - struct dentry_info_args darg; - int ret = 0; - -- tl_to_darg(&darg, tl); -+ tl_to_darg(&darg, tl, val); - trace_ext4_fc_replay(sb, EXT4_FC_TAG_LINK, darg.ino, - darg.parent_ino, darg.dname_len); - -@@ -1450,9 +1452,10 @@ static int ext4_fc_record_modified_inode(struct super_block *sb, int ino) - /* - * Inode replay function - */ --static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) -+static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl, -+ u8 *val) - { -- struct ext4_fc_inode *fc_inode; -+ struct ext4_fc_inode fc_inode; - struct ext4_inode *raw_inode; - struct ext4_inode *raw_fc_inode; - struct inode *inode = NULL; -@@ -1460,9 +1463,9 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) - int inode_len, ino, ret, tag = le16_to_cpu(tl->fc_tag); - struct ext4_extent_header *eh; - -- fc_inode = (struct ext4_fc_inode *)ext4_fc_tag_val(tl); -+ memcpy(&fc_inode, val, sizeof(fc_inode)); - -- ino = le32_to_cpu(fc_inode->fc_ino); -+ ino = le32_to_cpu(fc_inode.fc_ino); - trace_ext4_fc_replay(sb, tag, ino, 0, 0); - - inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); -@@ -1474,12 +1477,13 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) - - ext4_fc_record_modified_inode(sb, ino); - -- raw_fc_inode = (struct ext4_inode *)fc_inode->fc_raw_inode; -+ raw_fc_inode = (struct ext4_inode *) -+ (val + offsetof(struct ext4_fc_inode, fc_raw_inode)); - ret = ext4_get_fc_inode_loc(sb, ino, &iloc); - if (ret) - goto out; - -- inode_len = ext4_fc_tag_len(tl) - sizeof(struct ext4_fc_inode); -+ inode_len = le16_to_cpu(tl->fc_len) - sizeof(struct ext4_fc_inode); - raw_inode = ext4_raw_inode(&iloc); - - memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block)); -@@ -1547,14 +1551,15 @@ out: - * inode for which we are trying to create a dentry here, should already have - * been replayed before we start here. - */ --static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl) -+static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl, -+ u8 *val) - { - int ret = 0; - struct inode *inode = NULL; - struct inode *dir = NULL; - struct dentry_info_args darg; - -- tl_to_darg(&darg, tl); -+ tl_to_darg(&darg, tl, val); - - trace_ext4_fc_replay(sb, EXT4_FC_TAG_CREAT, darg.ino, - darg.parent_ino, darg.dname_len); -@@ -1633,9 +1638,9 @@ static int ext4_fc_record_regions(struct super_block *sb, int ino, - - /* Replay add range tag */ - static int ext4_fc_replay_add_range(struct super_block *sb, -- struct ext4_fc_tl *tl) -+ struct ext4_fc_tl *tl, u8 *val) - { -- struct ext4_fc_add_range *fc_add_ex; -+ struct ext4_fc_add_range fc_add_ex; - struct ext4_extent newex, *ex; - struct inode *inode; - ext4_lblk_t start, cur; -@@ -1645,15 +1650,14 @@ static int ext4_fc_replay_add_range(struct super_block *sb, - struct ext4_ext_path *path = NULL; - int ret; - -- fc_add_ex = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); -- ex = (struct ext4_extent *)&fc_add_ex->fc_ex; -+ memcpy(&fc_add_ex, val, sizeof(fc_add_ex)); -+ ex = (struct ext4_extent *)&fc_add_ex.fc_ex; - - trace_ext4_fc_replay(sb, EXT4_FC_TAG_ADD_RANGE, -- le32_to_cpu(fc_add_ex->fc_ino), le32_to_cpu(ex->ee_block), -+ le32_to_cpu(fc_add_ex.fc_ino), le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); - -- inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino), -- EXT4_IGET_NORMAL); -+ inode = ext4_iget(sb, le32_to_cpu(fc_add_ex.fc_ino), EXT4_IGET_NORMAL); - if (IS_ERR(inode)) { - jbd_debug(1, "Inode not found."); - return 0; -@@ -1762,32 +1766,33 @@ next: - - /* Replay DEL_RANGE tag */ - static int --ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl) -+ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, -+ u8 *val) - { - struct inode *inode; -- struct ext4_fc_del_range *lrange; -+ struct ext4_fc_del_range lrange; - struct ext4_map_blocks map; - ext4_lblk_t cur, remaining; - int ret; - -- lrange = (struct ext4_fc_del_range *)ext4_fc_tag_val(tl); -- cur = le32_to_cpu(lrange->fc_lblk); -- remaining = le32_to_cpu(lrange->fc_len); -+ memcpy(&lrange, val, sizeof(lrange)); -+ cur = le32_to_cpu(lrange.fc_lblk); -+ remaining = le32_to_cpu(lrange.fc_len); - - trace_ext4_fc_replay(sb, EXT4_FC_TAG_DEL_RANGE, -- le32_to_cpu(lrange->fc_ino), cur, remaining); -+ le32_to_cpu(lrange.fc_ino), cur, remaining); - -- inode = ext4_iget(sb, le32_to_cpu(lrange->fc_ino), EXT4_IGET_NORMAL); -+ inode = ext4_iget(sb, le32_to_cpu(lrange.fc_ino), EXT4_IGET_NORMAL); - if (IS_ERR(inode)) { -- jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange->fc_ino)); -+ jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange.fc_ino)); - return 0; - } - - ret = ext4_fc_record_modified_inode(sb, inode->i_ino); - - jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", -- inode->i_ino, le32_to_cpu(lrange->fc_lblk), -- le32_to_cpu(lrange->fc_len)); -+ inode->i_ino, le32_to_cpu(lrange.fc_lblk), -+ le32_to_cpu(lrange.fc_len)); - while (remaining > 0) { - map.m_lblk = cur; - map.m_len = remaining; -@@ -1808,8 +1813,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl) - } - - ret = ext4_punch_hole(inode, -- le32_to_cpu(lrange->fc_lblk) << sb->s_blocksize_bits, -- le32_to_cpu(lrange->fc_len) << sb->s_blocksize_bits); -+ le32_to_cpu(lrange.fc_lblk) << sb->s_blocksize_bits, -+ le32_to_cpu(lrange.fc_len) << sb->s_blocksize_bits); - if (ret) - jbd_debug(1, "ext4_punch_hole returned %d", ret); - ext4_ext_replay_shrink_inode(inode, -@@ -1925,11 +1930,11 @@ static int ext4_fc_replay_scan(journal_t *journal, - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_fc_replay_state *state; - int ret = JBD2_FC_REPLAY_CONTINUE; -- struct ext4_fc_add_range *ext; -- struct ext4_fc_tl *tl; -- struct ext4_fc_tail *tail; -- __u8 *start, *end; -- struct ext4_fc_head *head; -+ struct ext4_fc_add_range ext; -+ struct ext4_fc_tl tl; -+ struct ext4_fc_tail tail; -+ __u8 *start, *end, *cur, *val; -+ struct ext4_fc_head head; - struct ext4_extent *ex; - - state = &sbi->s_fc_replay_state; -@@ -1956,15 +1961,17 @@ static int ext4_fc_replay_scan(journal_t *journal, - } - - state->fc_replay_expected_off++; -- fc_for_each_tl(start, end, tl) { -+ for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) { -+ memcpy(&tl, cur, sizeof(tl)); -+ val = cur + sizeof(tl); - jbd_debug(3, "Scan phase, tag:%s, blk %lld\n", -- tag2str(le16_to_cpu(tl->fc_tag)), bh->b_blocknr); -- switch (le16_to_cpu(tl->fc_tag)) { -+ tag2str(le16_to_cpu(tl.fc_tag)), bh->b_blocknr); -+ switch (le16_to_cpu(tl.fc_tag)) { - case EXT4_FC_TAG_ADD_RANGE: -- ext = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); -- ex = (struct ext4_extent *)&ext->fc_ex; -+ memcpy(&ext, val, sizeof(ext)); -+ ex = (struct ext4_extent *)&ext.fc_ex; - ret = ext4_fc_record_regions(sb, -- le32_to_cpu(ext->fc_ino), -+ le32_to_cpu(ext.fc_ino), - le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex), - ext4_ext_get_actual_len(ex)); - if (ret < 0) -@@ -1978,18 +1985,18 @@ static int ext4_fc_replay_scan(journal_t *journal, - case EXT4_FC_TAG_INODE: - case EXT4_FC_TAG_PAD: - state->fc_cur_tag++; -- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, -- sizeof(*tl) + ext4_fc_tag_len(tl)); -+ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, -+ sizeof(tl) + le16_to_cpu(tl.fc_len)); - break; - case EXT4_FC_TAG_TAIL: - state->fc_cur_tag++; -- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); -- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, -- sizeof(*tl) + -+ memcpy(&tail, val, sizeof(tail)); -+ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, -+ sizeof(tl) + - offsetof(struct ext4_fc_tail, - fc_crc)); -- if (le32_to_cpu(tail->fc_tid) == expected_tid && -- le32_to_cpu(tail->fc_crc) == state->fc_crc) { -+ if (le32_to_cpu(tail.fc_tid) == expected_tid && -+ le32_to_cpu(tail.fc_crc) == state->fc_crc) { - state->fc_replay_num_tags = state->fc_cur_tag; - state->fc_regions_valid = - state->fc_regions_used; -@@ -2000,19 +2007,19 @@ static int ext4_fc_replay_scan(journal_t *journal, - state->fc_crc = 0; - break; - case EXT4_FC_TAG_HEAD: -- head = (struct ext4_fc_head *)ext4_fc_tag_val(tl); -- if (le32_to_cpu(head->fc_features) & -+ memcpy(&head, val, sizeof(head)); -+ if (le32_to_cpu(head.fc_features) & - ~EXT4_FC_SUPPORTED_FEATURES) { - ret = -EOPNOTSUPP; - break; - } -- if (le32_to_cpu(head->fc_tid) != expected_tid) { -+ if (le32_to_cpu(head.fc_tid) != expected_tid) { - ret = JBD2_FC_REPLAY_STOP; - break; - } - state->fc_cur_tag++; -- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, -- sizeof(*tl) + ext4_fc_tag_len(tl)); -+ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, -+ sizeof(tl) + le16_to_cpu(tl.fc_len)); - break; - default: - ret = state->fc_replay_num_tags ? -@@ -2036,11 +2043,11 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, - { - struct super_block *sb = journal->j_private; - struct ext4_sb_info *sbi = EXT4_SB(sb); -- struct ext4_fc_tl *tl; -- __u8 *start, *end; -+ struct ext4_fc_tl tl; -+ __u8 *start, *end, *cur, *val; - int ret = JBD2_FC_REPLAY_CONTINUE; - struct ext4_fc_replay_state *state = &sbi->s_fc_replay_state; -- struct ext4_fc_tail *tail; -+ struct ext4_fc_tail tail; - - if (pass == PASS_SCAN) { - state->fc_current_pass = PASS_SCAN; -@@ -2067,49 +2074,52 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, - start = (u8 *)bh->b_data; - end = (__u8 *)bh->b_data + journal->j_blocksize - 1; - -- fc_for_each_tl(start, end, tl) { -+ for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) { -+ memcpy(&tl, cur, sizeof(tl)); -+ val = cur + sizeof(tl); -+ - if (state->fc_replay_num_tags == 0) { - ret = JBD2_FC_REPLAY_STOP; - ext4_fc_set_bitmaps_and_counters(sb); - break; - } - jbd_debug(3, "Replay phase, tag:%s\n", -- tag2str(le16_to_cpu(tl->fc_tag))); -+ tag2str(le16_to_cpu(tl.fc_tag))); - state->fc_replay_num_tags--; -- switch (le16_to_cpu(tl->fc_tag)) { -+ switch (le16_to_cpu(tl.fc_tag)) { - case EXT4_FC_TAG_LINK: -- ret = ext4_fc_replay_link(sb, tl); -+ ret = ext4_fc_replay_link(sb, &tl, val); - break; - case EXT4_FC_TAG_UNLINK: -- ret = ext4_fc_replay_unlink(sb, tl); -+ ret = ext4_fc_replay_unlink(sb, &tl, val); - break; - case EXT4_FC_TAG_ADD_RANGE: -- ret = ext4_fc_replay_add_range(sb, tl); -+ ret = ext4_fc_replay_add_range(sb, &tl, val); - break; - case EXT4_FC_TAG_CREAT: -- ret = ext4_fc_replay_create(sb, tl); -+ ret = ext4_fc_replay_create(sb, &tl, val); - break; - case EXT4_FC_TAG_DEL_RANGE: -- ret = ext4_fc_replay_del_range(sb, tl); -+ ret = ext4_fc_replay_del_range(sb, &tl, val); - break; - case EXT4_FC_TAG_INODE: -- ret = ext4_fc_replay_inode(sb, tl); -+ ret = ext4_fc_replay_inode(sb, &tl, val); - break; - case EXT4_FC_TAG_PAD: - trace_ext4_fc_replay(sb, EXT4_FC_TAG_PAD, 0, -- ext4_fc_tag_len(tl), 0); -+ le16_to_cpu(tl.fc_len), 0); - break; - case EXT4_FC_TAG_TAIL: - trace_ext4_fc_replay(sb, EXT4_FC_TAG_TAIL, 0, -- ext4_fc_tag_len(tl), 0); -- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); -- WARN_ON(le32_to_cpu(tail->fc_tid) != expected_tid); -+ le16_to_cpu(tl.fc_len), 0); -+ memcpy(&tail, val, sizeof(tail)); -+ WARN_ON(le32_to_cpu(tail.fc_tid) != expected_tid); - break; - case EXT4_FC_TAG_HEAD: - break; - default: -- trace_ext4_fc_replay(sb, le16_to_cpu(tl->fc_tag), 0, -- ext4_fc_tag_len(tl), 0); -+ trace_ext4_fc_replay(sb, le16_to_cpu(tl.fc_tag), 0, -+ le16_to_cpu(tl.fc_len), 0); - ret = -ECANCELED; - break; - } -diff --git a/fs/ext4/fast_commit.h b/fs/ext4/fast_commit.h -index b77f70f55a622..937c381b4c85e 100644 ---- a/fs/ext4/fast_commit.h -+++ b/fs/ext4/fast_commit.h -@@ -153,13 +153,6 @@ struct ext4_fc_replay_state { - #define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1) - #endif - --#define fc_for_each_tl(__start, __end, __tl) \ -- for (tl = (struct ext4_fc_tl *)(__start); \ -- (__u8 *)tl < (__u8 *)(__end); \ -- tl = (struct ext4_fc_tl *)((__u8 *)tl + \ -- sizeof(struct ext4_fc_tl) + \ -- + le16_to_cpu(tl->fc_len))) -- - static inline const char *tag2str(__u16 tag) - { - switch (tag) { -@@ -186,16 +179,4 @@ static inline const char *tag2str(__u16 tag) - } - } - --/* Get length of a particular tlv */ --static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl) --{ -- return le16_to_cpu(tl->fc_len); --} -- --/* Get a pointer to "value" of a tlv */ --static inline __u8 *ext4_fc_tag_val(struct ext4_fc_tl *tl) --{ -- return (__u8 *)tl + sizeof(*tl); --} -- - #endif /* __FAST_COMMIT_H__ */ -diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c -index 71d321b3b9844..edbaed073ac5c 100644 ---- a/fs/ext4/ialloc.c -+++ b/fs/ext4/ialloc.c -@@ -322,14 +322,16 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) - if (is_directory) { - count = ext4_used_dirs_count(sb, gdp) - 1; - ext4_used_dirs_set(sb, gdp, count); -- percpu_counter_dec(&sbi->s_dirs_counter); -+ if (percpu_counter_initialized(&sbi->s_dirs_counter)) -+ percpu_counter_dec(&sbi->s_dirs_counter); - } - ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, - EXT4_INODES_PER_GROUP(sb) / 8); - ext4_group_desc_csum_set(sb, block_group, gdp); - ext4_unlock_group(sb, block_group); - -- percpu_counter_inc(&sbi->s_freeinodes_counter); -+ if (percpu_counter_initialized(&sbi->s_freeinodes_counter)) -+ percpu_counter_inc(&sbi->s_freeinodes_counter); - if (sbi->s_log_groups_per_flex) { - struct flex_groups *fg; - -diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c -index a02fadf4fc84e..d24cb3dc79fff 100644 ---- a/fs/ext4/mballoc.c -+++ b/fs/ext4/mballoc.c -@@ -2715,7 +2715,7 @@ static int ext4_mb_init_backend(struct super_block *sb) - */ - if (sbi->s_es->s_log_groups_per_flex >= 32) { - ext4_msg(sb, KERN_ERR, "too many log groups per flexible block group"); -- goto err_freesgi; -+ goto err_freebuddy; - } - sbi->s_mb_prefetch = min_t(uint, 1 << sbi->s_es->s_log_groups_per_flex, - BLK_MAX_SEGMENT_SIZE >> (sb->s_blocksize_bits - 9)); -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 77c1cb2582623..0e3a847b5d279 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -4449,14 +4449,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) - } - - if (sb->s_blocksize != blocksize) { -+ /* -+ * bh must be released before kill_bdev(), otherwise -+ * it won't be freed and its page also. kill_bdev() -+ * is called by sb_set_blocksize(). -+ */ -+ brelse(bh); - /* Validate the filesystem blocksize */ - if (!sb_set_blocksize(sb, blocksize)) { - ext4_msg(sb, KERN_ERR, "bad block size %d", - blocksize); -+ bh = NULL; - goto failed_mount; - } - -- brelse(bh); - logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; - offset = do_div(logical_sb_block, blocksize); - bh = ext4_sb_bread_unmovable(sb, logical_sb_block); -@@ -5176,8 +5182,9 @@ failed_mount: - kfree(get_qf_name(sb, sbi, i)); - #endif - fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy); -- ext4_blkdev_remove(sbi); -+ /* ext4_blkdev_remove() calls kill_bdev(), release bh before it. */ - brelse(bh); -+ ext4_blkdev_remove(sbi); - out_fail: - sb->s_fs_info = NULL; - kfree(sbi->s_blockgroup_lock); -diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c -index 9567520d79f79..7c2ba81213da0 100644 ---- a/fs/gfs2/glock.c -+++ b/fs/gfs2/glock.c -@@ -1465,9 +1465,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh) - 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); -diff --git a/fs/io_uring.c b/fs/io_uring.c -index 144056b0cac92..359d1abb089c4 100644 ---- a/fs/io_uring.c -+++ b/fs/io_uring.c -@@ -653,7 +653,7 @@ struct io_unlink { - struct io_completion { - struct file *file; - struct list_head list; -- int cflags; -+ u32 cflags; - }; - - struct io_async_connect { -@@ -1476,7 +1476,33 @@ static bool io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool force, - return ret; - } - --static void __io_cqring_fill_event(struct io_kiocb *req, long res, long cflags) -+static inline bool req_ref_inc_not_zero(struct io_kiocb *req) -+{ -+ return refcount_inc_not_zero(&req->refs); -+} -+ -+static inline bool req_ref_sub_and_test(struct io_kiocb *req, int refs) -+{ -+ return refcount_sub_and_test(refs, &req->refs); -+} -+ -+static inline bool req_ref_put_and_test(struct io_kiocb *req) -+{ -+ return refcount_dec_and_test(&req->refs); -+} -+ -+static inline void req_ref_put(struct io_kiocb *req) -+{ -+ refcount_dec(&req->refs); -+} -+ -+static inline void req_ref_get(struct io_kiocb *req) -+{ -+ refcount_inc(&req->refs); -+} -+ -+static void __io_cqring_fill_event(struct io_kiocb *req, long res, -+ unsigned int cflags) - { - struct io_ring_ctx *ctx = req->ctx; - struct io_uring_cqe *cqe; -@@ -1511,7 +1537,7 @@ static void __io_cqring_fill_event(struct io_kiocb *req, long res, long cflags) - io_clean_op(req); - req->result = res; - req->compl.cflags = cflags; -- refcount_inc(&req->refs); -+ req_ref_get(req); - list_add_tail(&req->compl.list, &ctx->cq_overflow_list); - } - } -@@ -1533,7 +1559,7 @@ static void io_req_complete_post(struct io_kiocb *req, long res, - * If we're the last reference to this request, add to our locked - * free_list cache. - */ -- if (refcount_dec_and_test(&req->refs)) { -+ if (req_ref_put_and_test(req)) { - struct io_comp_state *cs = &ctx->submit_state.comp; - - if (req->flags & (REQ_F_LINK | REQ_F_HARDLINK)) { -@@ -2112,7 +2138,7 @@ static void io_submit_flush_completions(struct io_comp_state *cs, - req = cs->reqs[i]; - - /* submission and completion refs */ -- if (refcount_sub_and_test(2, &req->refs)) -+ if (req_ref_sub_and_test(req, 2)) - io_req_free_batch(&rb, req, &ctx->submit_state); - } - -@@ -2128,7 +2154,7 @@ static struct io_kiocb *io_put_req_find_next(struct io_kiocb *req) - { - struct io_kiocb *nxt = NULL; - -- if (refcount_dec_and_test(&req->refs)) { -+ if (req_ref_put_and_test(req)) { - nxt = io_req_find_next(req); - __io_free_req(req); - } -@@ -2137,7 +2163,7 @@ static struct io_kiocb *io_put_req_find_next(struct io_kiocb *req) - - static void io_put_req(struct io_kiocb *req) - { -- if (refcount_dec_and_test(&req->refs)) -+ if (req_ref_put_and_test(req)) - io_free_req(req); - } - -@@ -2160,14 +2186,14 @@ static void io_free_req_deferred(struct io_kiocb *req) - - static inline void io_put_req_deferred(struct io_kiocb *req, int refs) - { -- if (refcount_sub_and_test(refs, &req->refs)) -+ if (req_ref_sub_and_test(req, refs)) - io_free_req_deferred(req); - } - - static void io_double_put_req(struct io_kiocb *req) - { - /* drop both submit and complete references */ -- if (refcount_sub_and_test(2, &req->refs)) -+ if (req_ref_sub_and_test(req, 2)) - io_free_req(req); - } - -@@ -2253,7 +2279,7 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events, - __io_cqring_fill_event(req, req->result, cflags); - (*nr_events)++; - -- if (refcount_dec_and_test(&req->refs)) -+ if (req_ref_put_and_test(req)) - io_req_free_batch(&rb, req, &ctx->submit_state); - } - -@@ -2495,7 +2521,7 @@ static bool io_rw_reissue(struct io_kiocb *req) - lockdep_assert_held(&req->ctx->uring_lock); - - if (io_resubmit_prep(req)) { -- refcount_inc(&req->refs); -+ req_ref_get(req); - io_queue_async_work(req); - return true; - } -@@ -3208,7 +3234,7 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, - list_del_init(&wait->entry); - - /* submit ref gets dropped, acquire a new one */ -- refcount_inc(&req->refs); -+ req_ref_get(req); - io_req_task_queue(req); - return 1; - } -@@ -4953,7 +4979,7 @@ static void io_poll_remove_double(struct io_kiocb *req) - spin_lock(&head->lock); - list_del_init(&poll->wait.entry); - if (poll->wait.private) -- refcount_dec(&req->refs); -+ req_ref_put(req); - poll->head = NULL; - spin_unlock(&head->lock); - } -@@ -5019,7 +5045,7 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode, - poll->wait.func(&poll->wait, mode, sync, key); - } - } -- refcount_dec(&req->refs); -+ req_ref_put(req); - return 1; - } - -@@ -5062,7 +5088,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt, - return; - } - io_init_poll_iocb(poll, poll_one->events, io_poll_double_wake); -- refcount_inc(&req->refs); -+ req_ref_get(req); - poll->wait.private = req; - *poll_ptr = poll; - } -@@ -6211,7 +6237,7 @@ static void io_wq_submit_work(struct io_wq_work *work) - /* avoid locking problems by failing it from a clean context */ - if (ret) { - /* io-wq is going to take one down */ -- refcount_inc(&req->refs); -+ req_ref_get(req); - io_req_task_queue_fail(req, ret); - } - } -@@ -6263,15 +6289,17 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer) - * We don't expect the list to be empty, that will only happen if we - * race with the completion of the linked work. - */ -- if (prev && refcount_inc_not_zero(&prev->refs)) -+ if (prev) { - io_remove_next_linked(prev); -- else -- prev = NULL; -+ if (!req_ref_inc_not_zero(prev)) -+ prev = NULL; -+ } - spin_unlock_irqrestore(&ctx->completion_lock, flags); - - if (prev) { - io_async_find_and_cancel(ctx, req, prev->user_data, -ETIME); - io_put_req_deferred(prev, 1); -+ io_put_req_deferred(req, 1); - } else { - io_req_complete_post(req, -ETIME, 0); - io_put_req_deferred(req, 1); -diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c -index 5edc1d0cf115f..0e45893c0cda0 100644 ---- a/fs/ocfs2/file.c -+++ b/fs/ocfs2/file.c -@@ -1857,6 +1857,45 @@ out: - return ret; - } - -+/* -+ * zero out partial blocks of one cluster. -+ * -+ * start: file offset where zero starts, will be made upper block aligned. -+ * len: it will be trimmed to the end of current cluster if "start + len" -+ * is bigger than it. -+ */ -+static int ocfs2_zeroout_partial_cluster(struct inode *inode, -+ u64 start, u64 len) -+{ -+ int ret; -+ u64 start_block, end_block, nr_blocks; -+ u64 p_block, offset; -+ u32 cluster, p_cluster, nr_clusters; -+ struct super_block *sb = inode->i_sb; -+ u64 end = ocfs2_align_bytes_to_clusters(sb, start); -+ -+ if (start + len < end) -+ end = start + len; -+ -+ start_block = ocfs2_blocks_for_bytes(sb, start); -+ end_block = ocfs2_blocks_for_bytes(sb, end); -+ nr_blocks = end_block - start_block; -+ if (!nr_blocks) -+ return 0; -+ -+ cluster = ocfs2_bytes_to_clusters(sb, start); -+ ret = ocfs2_get_clusters(inode, cluster, &p_cluster, -+ &nr_clusters, NULL); -+ if (ret) -+ return ret; -+ if (!p_cluster) -+ return 0; -+ -+ offset = start_block - ocfs2_clusters_to_blocks(sb, cluster); -+ p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset; -+ return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS); -+} -+ - /* - * Parts of this function taken from xfs_change_file_space() - */ -@@ -1867,7 +1906,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, - { - int ret; - s64 llen; -- loff_t size; -+ loff_t size, orig_isize; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct buffer_head *di_bh = NULL; - handle_t *handle; -@@ -1898,6 +1937,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, - goto out_inode_unlock; - } - -+ orig_isize = i_size_read(inode); - switch (sr->l_whence) { - case 0: /*SEEK_SET*/ - break; -@@ -1905,7 +1945,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, - sr->l_start += f_pos; - break; - case 2: /*SEEK_END*/ -- sr->l_start += i_size_read(inode); -+ sr->l_start += orig_isize; - break; - default: - ret = -EINVAL; -@@ -1959,6 +1999,14 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, - default: - ret = -EINVAL; - } -+ -+ /* zeroout eof blocks in the cluster. */ -+ if (!ret && change_size && orig_isize < size) { -+ ret = ocfs2_zeroout_partial_cluster(inode, orig_isize, -+ size - orig_isize); -+ if (!ret) -+ i_size_write(inode, size); -+ } - up_write(&OCFS2_I(inode)->ip_alloc_sem); - if (ret) { - mlog_errno(ret); -@@ -1975,9 +2023,6 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, - goto out_inode_unlock; - } - -- if (change_size && i_size_read(inode) < size) -- i_size_write(inode, size); -- - inode->i_ctime = inode->i_mtime = current_time(inode); - ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); - if (ret < 0) -diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h -index 9c68b2da14c63..e5a4c68093fc2 100644 ---- a/include/linux/mlx5/mlx5_ifc.h -+++ b/include/linux/mlx5/mlx5_ifc.h -@@ -1260,6 +1260,8 @@ enum mlx5_fc_bulk_alloc_bitmask { - - #define MLX5_FC_BULK_NUM_FCS(fc_enum) (MLX5_FC_BULK_SIZE_FACTOR * (fc_enum)) - -+#define MLX5_FT_MAX_MULTIPATH_LEVEL 63 -+ - enum { - MLX5_STEERING_FORMAT_CONNECTX_5 = 0, - MLX5_STEERING_FORMAT_CONNECTX_6DX = 1, -diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h -index 5e772392a3795..136b1d996075c 100644 ---- a/include/linux/pgtable.h -+++ b/include/linux/pgtable.h -@@ -432,6 +432,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres - * To be differentiate with macro pte_mkyoung, this macro is used on platforms - * where software maintains page access bit. - */ -+#ifndef pte_sw_mkyoung -+static inline pte_t pte_sw_mkyoung(pte_t pte) -+{ -+ return pte; -+} -+#define pte_sw_mkyoung pte_sw_mkyoung -+#endif -+ - #ifndef pte_savedwrite - #define pte_savedwrite pte_write - #endif -diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h -index fafc1beea504a..9837fb011f2fb 100644 ---- a/include/linux/platform_data/ti-sysc.h -+++ b/include/linux/platform_data/ti-sysc.h -@@ -50,6 +50,7 @@ struct sysc_regbits { - s8 emufree_shift; - }; - -+#define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) - #define SYSC_QUIRK_GPMC_DEBUG BIT(26) - #define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) - #define SYSC_MODULE_QUIRK_PRUSS BIT(24) -diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h -index 48ecca8530ffa..b655d8666f555 100644 ---- a/include/net/caif/caif_dev.h -+++ b/include/net/caif/caif_dev.h -@@ -119,7 +119,7 @@ void caif_free_client(struct cflayer *adap_layer); - * The link_support layer is used to add any Link Layer specific - * framing. - */ --void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, -+int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, - struct cflayer *link_support, int head_room, - struct cflayer **layer, int (**rcv_func)( - struct sk_buff *, struct net_device *, -diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h -index 2aa5e91d84576..8819ff4db35a6 100644 ---- a/include/net/caif/cfcnfg.h -+++ b/include/net/caif/cfcnfg.h -@@ -62,7 +62,7 @@ void cfcnfg_remove(struct cfcnfg *cfg); - * @fcs: Specify if checksum is used in CAIF Framing Layer. - * @head_room: Head space needed by link specific protocol. - */ --void -+int - cfcnfg_add_phy_layer(struct cfcnfg *cnfg, - struct net_device *dev, struct cflayer *phy_layer, - enum cfcnfg_phy_preference pref, -diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h -index 14a55e03bb3ce..67cce8757175a 100644 ---- a/include/net/caif/cfserl.h -+++ b/include/net/caif/cfserl.h -@@ -9,4 +9,5 @@ - #include - - struct cflayer *cfserl_create(int instance, bool use_stx); -+void cfserl_release(struct cflayer *layer); - #endif -diff --git a/include/net/tls.h b/include/net/tls.h -index 3eccb525e8f79..8341a8d1e8073 100644 ---- a/include/net/tls.h -+++ b/include/net/tls.h -@@ -193,7 +193,11 @@ struct tls_offload_context_tx { - (sizeof(struct tls_offload_context_tx) + TLS_DRIVER_STATE_SIZE_TX) - - enum tls_context_flags { -- TLS_RX_SYNC_RUNNING = 0, -+ /* tls_device_down was called after the netdev went down, device state -+ * was released, and kTLS works in software, even though rx_conf is -+ * still TLS_HW (needed for transition). -+ */ -+ TLS_RX_DEV_DEGRADED = 0, - /* Unlike RX where resync is driven entirely by the core in TX only - * the driver knows when things went out of sync, so we need the flag - * to be atomic. -@@ -266,6 +270,7 @@ struct tls_context { - - /* cache cold stuff */ - struct proto *sk_proto; -+ struct sock *sk; - - void (*sk_destruct)(struct sock *sk); - -@@ -448,6 +453,9 @@ static inline u16 tls_user_config(struct tls_context *ctx, bool tx) - struct sk_buff * - tls_validate_xmit_skb(struct sock *sk, struct net_device *dev, - struct sk_buff *skb); -+struct sk_buff * -+tls_validate_xmit_skb_sw(struct sock *sk, struct net_device *dev, -+ struct sk_buff *skb); - - static inline bool tls_is_sk_tx_device_offloaded(struct sock *sk) - { -diff --git a/init/main.c b/init/main.c -index 53b278845b886..5bd1a25f1d6f5 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -1514,7 +1514,7 @@ static noinline void __init kernel_init_freeable(void) - */ - set_mems_allowed(node_states[N_MEMORY]); - -- cad_pid = task_pid(current); -+ cad_pid = get_pid(task_pid(current)); - - smp_prepare_cpus(setup_max_cpus); - -diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c -index 308427fe03a3a..6140e91e9c891 100644 ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include "../../lib/kstrtox.h" - -@@ -741,11 +742,13 @@ bpf_base_func_proto(enum bpf_func_id func_id) - case BPF_FUNC_probe_read_user: - return &bpf_probe_read_user_proto; - case BPF_FUNC_probe_read_kernel: -- return &bpf_probe_read_kernel_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_kernel_proto; - case BPF_FUNC_probe_read_user_str: - return &bpf_probe_read_user_str_proto; - case BPF_FUNC_probe_read_kernel_str: -- return &bpf_probe_read_kernel_str_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_kernel_str_proto; - case BPF_FUNC_snprintf_btf: - return &bpf_snprintf_btf_proto; - default: -diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c -index b0c45d923f0f9..9bb3d2823f442 100644 ---- a/kernel/trace/bpf_trace.c -+++ b/kernel/trace/bpf_trace.c -@@ -215,16 +215,11 @@ const struct bpf_func_proto bpf_probe_read_user_str_proto = { - static __always_inline int - bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr) - { -- int ret = security_locked_down(LOCKDOWN_BPF_READ); -+ int ret; - -- if (unlikely(ret < 0)) -- goto fail; - ret = copy_from_kernel_nofault(dst, unsafe_ptr, size); - if (unlikely(ret < 0)) -- goto fail; -- return ret; --fail: -- memset(dst, 0, size); -+ memset(dst, 0, size); - return ret; - } - -@@ -246,10 +241,7 @@ const struct bpf_func_proto bpf_probe_read_kernel_proto = { - static __always_inline int - bpf_probe_read_kernel_str_common(void *dst, u32 size, const void *unsafe_ptr) - { -- int ret = security_locked_down(LOCKDOWN_BPF_READ); -- -- if (unlikely(ret < 0)) -- goto fail; -+ int ret; - - /* - * The strncpy_from_kernel_nofault() call will likely not fill the -@@ -262,11 +254,7 @@ bpf_probe_read_kernel_str_common(void *dst, u32 size, const void *unsafe_ptr) - */ - ret = strncpy_from_kernel_nofault(dst, unsafe_ptr, size); - if (unlikely(ret < 0)) -- goto fail; -- -- return ret; --fail: -- memset(dst, 0, size); -+ memset(dst, 0, size); - return ret; - } - -@@ -1322,16 +1310,20 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) - case BPF_FUNC_probe_read_user: - return &bpf_probe_read_user_proto; - case BPF_FUNC_probe_read_kernel: -- return &bpf_probe_read_kernel_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_kernel_proto; - case BPF_FUNC_probe_read_user_str: - return &bpf_probe_read_user_str_proto; - case BPF_FUNC_probe_read_kernel_str: -- return &bpf_probe_read_kernel_str_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_kernel_str_proto; - #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE - case BPF_FUNC_probe_read: -- return &bpf_probe_read_compat_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_compat_proto; - case BPF_FUNC_probe_read_str: -- return &bpf_probe_read_compat_str_proto; -+ return security_locked_down(LOCKDOWN_BPF_READ) < 0 ? -+ NULL : &bpf_probe_read_compat_str_proto; - #endif - #ifdef CONFIG_CGROUPS - case BPF_FUNC_get_current_cgroup_id: -diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c -index a9bd6ce1ba02b..726fd2030f645 100644 ---- a/mm/debug_vm_pgtable.c -+++ b/mm/debug_vm_pgtable.c -@@ -192,7 +192,7 @@ static void __init pmd_advanced_tests(struct mm_struct *mm, - - pr_debug("Validating PMD advanced\n"); - /* Align the address wrt HPAGE_PMD_SIZE */ -- vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE; -+ vaddr &= HPAGE_PMD_MASK; - - pgtable_trans_huge_deposit(mm, pmdp, pgtable); - -@@ -330,7 +330,7 @@ static void __init pud_advanced_tests(struct mm_struct *mm, - - pr_debug("Validating PUD advanced\n"); - /* Align the address wrt HPAGE_PUD_SIZE */ -- vaddr = (vaddr & HPAGE_PUD_MASK) + HPAGE_PUD_SIZE; -+ vaddr &= HPAGE_PUD_MASK; - - set_pud_at(mm, vaddr, pudp, pud); - pudp_set_wrprotect(mm, vaddr, pudp); -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 96b722af092e7..ce63ec0187c55 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -4705,10 +4705,20 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, - struct page *page; - - if (!*pagep) { -- ret = -ENOMEM; -+ /* If a page already exists, then it's UFFDIO_COPY for -+ * a non-missing case. Return -EEXIST. -+ */ -+ if (vm_shared && -+ hugetlbfs_pagecache_present(h, dst_vma, dst_addr)) { -+ ret = -EEXIST; -+ goto out; -+ } -+ - page = alloc_huge_page(dst_vma, dst_addr, 0); -- if (IS_ERR(page)) -+ if (IS_ERR(page)) { -+ ret = -ENOMEM; - goto out; -+ } - - ret = copy_huge_page_from_user(page, - (const void __user *) src_addr, -diff --git a/mm/kfence/core.c b/mm/kfence/core.c -index f0be2c5038b5d..6f29981e317fe 100644 ---- a/mm/kfence/core.c -+++ b/mm/kfence/core.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -620,7 +621,16 @@ static void toggle_allocation_gate(struct work_struct *work) - /* Enable static key, and await allocation to happen. */ - static_branch_enable(&kfence_allocation_key); - -- wait_event_timeout(allocation_wait, atomic_read(&kfence_allocation_gate), HZ); -+ if (sysctl_hung_task_timeout_secs) { -+ /* -+ * During low activity with no allocations we might wait a -+ * while; let's avoid the hung task warning. -+ */ -+ wait_event_idle_timeout(allocation_wait, atomic_read(&kfence_allocation_gate), -+ sysctl_hung_task_timeout_secs * HZ / 2); -+ } else { -+ wait_event_idle(allocation_wait, atomic_read(&kfence_allocation_gate)); -+ } - - /* Disable static key and reset timer. */ - static_branch_disable(&kfence_allocation_key); -diff --git a/mm/memory.c b/mm/memory.c -index 550405fc3b5e6..14a6c66b37483 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -2896,6 +2896,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) - } - flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); - entry = mk_pte(new_page, vma->vm_page_prot); -+ entry = pte_sw_mkyoung(entry); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); - - /* -@@ -3561,6 +3562,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf) - __SetPageUptodate(page); - - entry = mk_pte(page, vma->vm_page_prot); -+ entry = pte_sw_mkyoung(entry); - if (vma->vm_flags & VM_WRITE) - entry = pte_mkwrite(pte_mkdirty(entry)); - -@@ -3745,6 +3747,8 @@ void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr) - - if (prefault && arch_wants_old_prefaulted_pte()) - entry = pte_mkold(entry); -+ else -+ entry = pte_sw_mkyoung(entry); - - if (write) - entry = maybe_mkwrite(pte_mkdirty(entry), vma); -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 4bb3cdfc47f87..d9dbf45f7590e 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -8951,6 +8951,8 @@ bool take_page_off_buddy(struct page *page) - del_page_from_free_list(page_head, zone, page_order); - break_down_buddy_pages(zone, page_head, page, 0, - page_order, migratetype); -+ if (!is_migrate_isolate(migratetype)) -+ __mod_zone_freepage_state(zone, -1, migratetype); - ret = true; - break; - } -diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c -index b0d9c36acc033..4fad2ca661ed9 100644 ---- a/net/bluetooth/hci_core.c -+++ b/net/bluetooth/hci_core.c -@@ -1608,8 +1608,13 @@ setup_failed: - } else { - /* Init failed, cleanup */ - flush_work(&hdev->tx_work); -- flush_work(&hdev->cmd_work); -+ -+ /* Since hci_rx_work() is possible to awake new cmd_work -+ * it should be flushed first to avoid unexpected call of -+ * hci_cmd_work() -+ */ - flush_work(&hdev->rx_work); -+ flush_work(&hdev->cmd_work); - - skb_queue_purge(&hdev->cmd_q); - skb_queue_purge(&hdev->rx_q); -diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c -index 251b9128f530a..eed0dd066e12c 100644 ---- a/net/bluetooth/hci_sock.c -+++ b/net/bluetooth/hci_sock.c -@@ -762,7 +762,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) - /* Detach sockets from device */ - read_lock(&hci_sk_list.lock); - sk_for_each(sk, &hci_sk_list.head) { -- bh_lock_sock_nested(sk); -+ lock_sock(sk); - if (hci_pi(sk)->hdev == hdev) { - hci_pi(sk)->hdev = NULL; - sk->sk_err = EPIPE; -@@ -771,7 +771,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) - - hci_dev_put(hdev); - } -- bh_unlock_sock(sk); -+ release_sock(sk); - } - read_unlock(&hci_sk_list.lock); - } -diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c -index c10e5a55758d2..440139706130a 100644 ---- a/net/caif/caif_dev.c -+++ b/net/caif/caif_dev.c -@@ -308,7 +308,7 @@ static void dev_flowctrl(struct net_device *dev, int on) - caifd_put(caifd); - } - --void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, -+int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, - struct cflayer *link_support, int head_room, - struct cflayer **layer, - int (**rcv_func)(struct sk_buff *, struct net_device *, -@@ -319,11 +319,12 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, - enum cfcnfg_phy_preference pref; - struct cfcnfg *cfg = get_cfcnfg(dev_net(dev)); - struct caif_device_entry_list *caifdevs; -+ int res; - - caifdevs = caif_device_list(dev_net(dev)); - caifd = caif_device_alloc(dev); - if (!caifd) -- return; -+ return -ENOMEM; - *layer = &caifd->layer; - spin_lock_init(&caifd->flow_lock); - -@@ -344,7 +345,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, - strlcpy(caifd->layer.name, dev->name, - sizeof(caifd->layer.name)); - caifd->layer.transmit = transmit; -- cfcnfg_add_phy_layer(cfg, -+ res = cfcnfg_add_phy_layer(cfg, - dev, - &caifd->layer, - pref, -@@ -354,6 +355,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, - mutex_unlock(&caifdevs->lock); - if (rcv_func) - *rcv_func = receive; -+ return res; - } - EXPORT_SYMBOL(caif_enroll_dev); - -@@ -368,6 +370,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, - struct cflayer *layer, *link_support; - int head_room = 0; - struct caif_device_entry_list *caifdevs; -+ int res; - - cfg = get_cfcnfg(dev_net(dev)); - caifdevs = caif_device_list(dev_net(dev)); -@@ -393,8 +396,10 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, - break; - } - } -- caif_enroll_dev(dev, caifdev, link_support, head_room, -+ res = caif_enroll_dev(dev, caifdev, link_support, head_room, - &layer, NULL); -+ if (res) -+ cfserl_release(link_support); - caifdev->flowctrl = dev_flowctrl; - break; - -diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c -index a0116b9503d9d..b02e1292f7f19 100644 ---- a/net/caif/caif_usb.c -+++ b/net/caif/caif_usb.c -@@ -115,6 +115,11 @@ static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], - return (struct cflayer *) this; - } - -+static void cfusbl_release(struct cflayer *layer) -+{ -+ kfree(layer); -+} -+ - static struct packet_type caif_usb_type __read_mostly = { - .type = cpu_to_be16(ETH_P_802_EX1), - }; -@@ -127,6 +132,7 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, - struct cflayer *layer, *link_support; - struct usbnet *usbnet; - struct usb_device *usbdev; -+ int res; - - /* Check whether we have a NCM device, and find its VID/PID. */ - if (!(dev->dev.parent && dev->dev.parent->driver && -@@ -169,8 +175,11 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, - if (dev->num_tx_queues > 1) - pr_warn("USB device uses more than one tx queue\n"); - -- caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, -+ res = caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, - &layer, &caif_usb_type.func); -+ if (res) -+ goto err; -+ - if (!pack_added) - dev_add_pack(&caif_usb_type); - pack_added = true; -@@ -178,6 +187,9 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, - strlcpy(layer->name, dev->name, sizeof(layer->name)); - - return 0; -+err: -+ cfusbl_release(link_support); -+ return res; - } - - static struct notifier_block caif_device_notifier = { -diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c -index 399239a14420f..cac30e676ac94 100644 ---- a/net/caif/cfcnfg.c -+++ b/net/caif/cfcnfg.c -@@ -450,7 +450,7 @@ unlock: - rcu_read_unlock(); - } - --void -+int - cfcnfg_add_phy_layer(struct cfcnfg *cnfg, - struct net_device *dev, struct cflayer *phy_layer, - enum cfcnfg_phy_preference pref, -@@ -459,7 +459,7 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, - { - struct cflayer *frml; - struct cfcnfg_phyinfo *phyinfo = NULL; -- int i; -+ int i, res = 0; - u8 phyid; - - mutex_lock(&cnfg->lock); -@@ -473,12 +473,15 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, - goto got_phyid; - } - pr_warn("Too many CAIF Link Layers (max 6)\n"); -+ res = -EEXIST; - goto out; - - got_phyid: - phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); -- if (!phyinfo) -+ if (!phyinfo) { -+ res = -ENOMEM; - goto out_err; -+ } - - phy_layer->id = phyid; - phyinfo->pref = pref; -@@ -492,8 +495,10 @@ got_phyid: - - frml = cffrml_create(phyid, fcs); - -- if (!frml) -+ if (!frml) { -+ res = -ENOMEM; - goto out_err; -+ } - phyinfo->frm_layer = frml; - layer_set_up(frml, cnfg->mux); - -@@ -511,11 +516,12 @@ got_phyid: - list_add_rcu(&phyinfo->node, &cnfg->phys); - out: - mutex_unlock(&cnfg->lock); -- return; -+ return res; - - out_err: - kfree(phyinfo); - mutex_unlock(&cnfg->lock); -+ return res; - } - EXPORT_SYMBOL(cfcnfg_add_phy_layer); - -diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c -index e11725a4bb0ed..40cd57ad0a0f4 100644 ---- a/net/caif/cfserl.c -+++ b/net/caif/cfserl.c -@@ -31,6 +31,11 @@ static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt); - static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, - int phyid); - -+void cfserl_release(struct cflayer *layer) -+{ -+ kfree(layer); -+} -+ - struct cflayer *cfserl_create(int instance, bool use_stx) - { - struct cfserl *this = kzalloc(sizeof(struct cfserl), GFP_ATOMIC); -diff --git a/net/core/devlink.c b/net/core/devlink.c -index 737b61c2976e1..4c363fa7d4d11 100644 ---- a/net/core/devlink.c -+++ b/net/core/devlink.c -@@ -705,7 +705,6 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg, - case DEVLINK_PORT_FLAVOUR_PHYSICAL: - case DEVLINK_PORT_FLAVOUR_CPU: - case DEVLINK_PORT_FLAVOUR_DSA: -- case DEVLINK_PORT_FLAVOUR_VIRTUAL: - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, - attrs->phys.port_number)) - return -EMSGSIZE; -@@ -8629,7 +8628,6 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, - - switch (attrs->flavour) { - case DEVLINK_PORT_FLAVOUR_PHYSICAL: -- case DEVLINK_PORT_FLAVOUR_VIRTUAL: - if (!attrs->split) - n = snprintf(name, len, "p%u", attrs->phys.port_number); - else -@@ -8670,6 +8668,8 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, - n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf, - attrs->pci_sf.sf); - break; -+ case DEVLINK_PORT_FLAVOUR_VIRTUAL: -+ return -EOPNOTSUPP; - } - - if (n >= len) -diff --git a/net/core/neighbour.c b/net/core/neighbour.c -index 98f20efbfadf2..bf774575ad716 100644 ---- a/net/core/neighbour.c -+++ b/net/core/neighbour.c -@@ -238,6 +238,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) - - write_lock(&n->lock); - if ((n->nud_state == NUD_FAILED) || -+ (n->nud_state == NUD_NOARP) || - (tbl->is_multicast && - tbl->is_multicast(n->primary_key)) || - time_after(tref, n->updated)) -diff --git a/net/core/sock.c b/net/core/sock.c -index 9c7b143e7a964..a266760cd65ea 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -815,10 +815,18 @@ void sock_set_rcvbuf(struct sock *sk, int val) - } - EXPORT_SYMBOL(sock_set_rcvbuf); - -+static void __sock_set_mark(struct sock *sk, u32 val) -+{ -+ if (val != sk->sk_mark) { -+ sk->sk_mark = val; -+ sk_dst_reset(sk); -+ } -+} -+ - void sock_set_mark(struct sock *sk, u32 val) - { - lock_sock(sk); -- sk->sk_mark = val; -+ __sock_set_mark(sk, val); - release_sock(sk); - } - EXPORT_SYMBOL(sock_set_mark); -@@ -1126,10 +1134,10 @@ set_sndbuf: - case SO_MARK: - if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { - ret = -EPERM; -- } else if (val != sk->sk_mark) { -- sk->sk_mark = val; -- sk_dst_reset(sk); -+ break; - } -+ -+ __sock_set_mark(sk, val); - break; - - case SO_RXQ_OVFL: -diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c -index 008c1ec6e20c1..122ad5833fb1c 100644 ---- a/net/dsa/tag_8021q.c -+++ b/net/dsa/tag_8021q.c -@@ -64,7 +64,7 @@ - #define DSA_8021Q_SUBVLAN_HI_SHIFT 9 - #define DSA_8021Q_SUBVLAN_HI_MASK GENMASK(9, 9) - #define DSA_8021Q_SUBVLAN_LO_SHIFT 4 --#define DSA_8021Q_SUBVLAN_LO_MASK GENMASK(4, 3) -+#define DSA_8021Q_SUBVLAN_LO_MASK GENMASK(5, 4) - #define DSA_8021Q_SUBVLAN_HI(x) (((x) & GENMASK(2, 2)) >> 2) - #define DSA_8021Q_SUBVLAN_LO(x) ((x) & GENMASK(1, 0)) - #define DSA_8021Q_SUBVLAN(x) \ -diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c -index 0c1b0770c59ea..c23c152860b73 100644 ---- a/net/ieee802154/nl-mac.c -+++ b/net/ieee802154/nl-mac.c -@@ -680,8 +680,10 @@ int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info) - nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) || - nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, - be32_to_cpu(params.frame_counter)) || -- ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) -+ ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) { -+ rc = -ENOBUFS; - goto out_free; -+ } - - dev_put(dev); - -diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c -index 2cdc7e63fe172..88215b5c93aa4 100644 ---- a/net/ieee802154/nl-phy.c -+++ b/net/ieee802154/nl-phy.c -@@ -241,8 +241,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) - } - - if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || -- nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name)) -+ nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name)) { -+ rc = -EMSGSIZE; - goto nla_put_failure; -+ } - dev_put(dev); - - wpan_phy_put(phy); -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 373d48073106f..36e80b3598b01 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -3676,11 +3676,11 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, - if (nh) { - if (rt->fib6_src.plen) { - NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing"); -- goto out; -+ goto out_free; - } - if (!nexthop_get(nh)) { - NL_SET_ERR_MSG(extack, "Nexthop has been deleted"); -- goto out; -+ goto out_free; - } - rt->nh = nh; - fib6_nh = nexthop_fib6_nh(rt->nh); -@@ -3717,6 +3717,10 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, - out: - fib6_info_release(rt); - return ERR_PTR(err); -+out_free: -+ ip_fib_metrics_put(rt->fib6_metrics); -+ kfree(rt); -+ return ERR_PTR(err); - } - - int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags, -diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c -index 228dd40828c4b..225b988215171 100644 ---- a/net/mptcp/protocol.c -+++ b/net/mptcp/protocol.c -@@ -937,6 +937,10 @@ static void __mptcp_update_wmem(struct sock *sk) - { - struct mptcp_sock *msk = mptcp_sk(sk); - -+#ifdef CONFIG_LOCKDEP -+ WARN_ON_ONCE(!lockdep_is_held(&sk->sk_lock.slock)); -+#endif -+ - if (!msk->wmem_reserved) - return; - -@@ -1075,10 +1079,20 @@ out: - - static void __mptcp_clean_una_wakeup(struct sock *sk) - { -+#ifdef CONFIG_LOCKDEP -+ WARN_ON_ONCE(!lockdep_is_held(&sk->sk_lock.slock)); -+#endif - __mptcp_clean_una(sk); - mptcp_write_space(sk); - } - -+static void mptcp_clean_una_wakeup(struct sock *sk) -+{ -+ mptcp_data_lock(sk); -+ __mptcp_clean_una_wakeup(sk); -+ mptcp_data_unlock(sk); -+} -+ - static void mptcp_enter_memory_pressure(struct sock *sk) - { - struct mptcp_subflow_context *subflow; -@@ -2288,7 +2302,7 @@ static void __mptcp_retrans(struct sock *sk) - struct sock *ssk; - int ret; - -- __mptcp_clean_una_wakeup(sk); -+ mptcp_clean_una_wakeup(sk); - dfrag = mptcp_rtx_head(sk); - if (!dfrag) { - if (mptcp_data_fin_enabled(msk)) { -diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c -index 1936db3574d2e..8425cd393bf3e 100644 ---- a/net/mptcp/subflow.c -+++ b/net/mptcp/subflow.c -@@ -608,21 +608,20 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, - - /* if the sk is MP_CAPABLE, we try to fetch the client key */ - if (subflow_req->mp_capable) { -- if (TCP_SKB_CB(skb)->seq != subflow_req->ssn_offset + 1) { -- /* here we can receive and accept an in-window, -- * out-of-order pkt, which will not carry the MP_CAPABLE -- * opt even on mptcp enabled paths -- */ -- goto create_msk; -- } -- -+ /* we can receive and accept an in-window, out-of-order pkt, -+ * which may not carry the MP_CAPABLE opt even on mptcp enabled -+ * paths: always try to extract the peer key, and fallback -+ * for packets missing it. -+ * Even OoO DSS packets coming legitly after dropped or -+ * reordered MPC will cause fallback, but we don't have other -+ * options. -+ */ - mptcp_get_options(skb, &mp_opt); - if (!mp_opt.mp_capable) { - fallback = true; - goto create_child; - } - --create_msk: - new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); - if (!new_msk) - fallback = true; -@@ -985,22 +984,11 @@ static bool subflow_check_data_avail(struct sock *ssk) - u64 old_ack; - - status = get_mapping_status(ssk, msk); -- pr_debug("msk=%p ssk=%p status=%d", msk, ssk, status); -- if (status == MAPPING_INVALID) { -- ssk->sk_err = EBADMSG; -- goto fatal; -- } -- if (status == MAPPING_DUMMY) { -- __mptcp_do_fallback(msk); -- skb = skb_peek(&ssk->sk_receive_queue); -- subflow->map_valid = 1; -- subflow->map_seq = READ_ONCE(msk->ack_seq); -- subflow->map_data_len = skb->len; -- subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq - -- subflow->ssn_offset; -- subflow->data_avail = MPTCP_SUBFLOW_DATA_AVAIL; -- return true; -- } -+ if (unlikely(status == MAPPING_INVALID)) -+ goto fallback; -+ -+ if (unlikely(status == MAPPING_DUMMY)) -+ goto fallback; - - if (status != MAPPING_OK) - goto no_data; -@@ -1013,10 +1001,8 @@ static bool subflow_check_data_avail(struct sock *ssk) - * MP_CAPABLE-based mapping - */ - if (unlikely(!READ_ONCE(msk->can_ack))) { -- if (!subflow->mpc_map) { -- ssk->sk_err = EBADMSG; -- goto fatal; -- } -+ if (!subflow->mpc_map) -+ goto fallback; - WRITE_ONCE(msk->remote_key, subflow->remote_key); - WRITE_ONCE(msk->ack_seq, subflow->map_seq); - WRITE_ONCE(msk->can_ack, true); -@@ -1044,15 +1030,29 @@ static bool subflow_check_data_avail(struct sock *ssk) - no_data: - subflow_sched_work_if_closed(msk, ssk); - return false; --fatal: -- /* fatal protocol error, close the socket */ -- /* This barrier is coupled with smp_rmb() in tcp_poll() */ -- smp_wmb(); -- ssk->sk_error_report(ssk); -- tcp_set_state(ssk, TCP_CLOSE); -- tcp_send_active_reset(ssk, GFP_ATOMIC); -- subflow->data_avail = 0; -- return false; -+ -+fallback: -+ /* RFC 8684 section 3.7. */ -+ if (subflow->mp_join || subflow->fully_established) { -+ /* fatal protocol error, close the socket. -+ * subflow_error_report() will introduce the appropriate barriers -+ */ -+ ssk->sk_err = EBADMSG; -+ ssk->sk_error_report(ssk); -+ tcp_set_state(ssk, TCP_CLOSE); -+ tcp_send_active_reset(ssk, GFP_ATOMIC); -+ subflow->data_avail = 0; -+ return false; -+ } -+ -+ __mptcp_do_fallback(msk); -+ skb = skb_peek(&ssk->sk_receive_queue); -+ subflow->map_valid = 1; -+ subflow->map_seq = READ_ONCE(msk->ack_seq); -+ subflow->map_data_len = skb->len; -+ subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq - subflow->ssn_offset; -+ subflow->data_avail = MPTCP_SUBFLOW_DATA_AVAIL; -+ return true; - } - - bool mptcp_subflow_data_available(struct sock *sk) -diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c -index d45dbcba8b49c..c25097092a060 100644 ---- a/net/netfilter/ipvs/ip_vs_ctl.c -+++ b/net/netfilter/ipvs/ip_vs_ctl.c -@@ -1367,7 +1367,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, - ip_vs_addr_copy(svc->af, &svc->addr, &u->addr); - svc->port = u->port; - svc->fwmark = u->fwmark; -- svc->flags = u->flags; -+ svc->flags = u->flags & ~IP_VS_SVC_F_HASHED; - svc->timeout = u->timeout * HZ; - svc->netmask = u->netmask; - svc->ipvs = ipvs; -diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c -index 47e9319d2cf31..71892822bbf5d 100644 ---- a/net/netfilter/nf_conntrack_proto.c -+++ b/net/netfilter/nf_conntrack_proto.c -@@ -660,7 +660,7 @@ int nf_conntrack_proto_init(void) - - #if IS_ENABLED(CONFIG_IPV6) - cleanup_sockopt: -- nf_unregister_sockopt(&so_getorigdst6); -+ nf_unregister_sockopt(&so_getorigdst); - #endif - return ret; - } -diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c -index 878ed49d0c569..31016c144c48b 100644 ---- a/net/netfilter/nf_tables_api.c -+++ b/net/netfilter/nf_tables_api.c -@@ -3288,8 +3288,10 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, - if (n == NFT_RULE_MAXEXPRS) - goto err1; - err = nf_tables_expr_parse(&ctx, tmp, &info[n]); -- if (err < 0) -+ if (err < 0) { -+ NL_SET_BAD_ATTR(extack, tmp); - goto err1; -+ } - size += info[n].ops->size; - n++; - } -diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c -index 0f94fce1d3ed3..04a12a264cf74 100644 ---- a/net/netfilter/nfnetlink_cthelper.c -+++ b/net/netfilter/nfnetlink_cthelper.c -@@ -380,10 +380,14 @@ static int - nfnl_cthelper_update(const struct nlattr * const tb[], - struct nf_conntrack_helper *helper) - { -+ u32 size; - int ret; - -- if (tb[NFCTH_PRIV_DATA_LEN]) -- return -EBUSY; -+ if (tb[NFCTH_PRIV_DATA_LEN]) { -+ size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); -+ if (size != helper->data_len) -+ return -EBUSY; -+ } - - if (tb[NFCTH_POLICY]) { - ret = nfnl_cthelper_update_policy(helper, tb[NFCTH_POLICY]); -diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c -index 882fe8648653d..6d2b382f5e075 100644 ---- a/net/netfilter/nft_ct.c -+++ b/net/netfilter/nft_ct.c -@@ -1216,7 +1216,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj, - struct nf_conn *ct; - - ct = nf_ct_get(pkt->skb, &ctinfo); -- if (!ct || ctinfo == IP_CT_UNTRACKED) { -+ if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct)) { - regs->verdict.code = NFT_BREAK; - return; - } -diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c -index 53dbe733f9981..6cfd30fc07985 100644 ---- a/net/nfc/llcp_sock.c -+++ b/net/nfc/llcp_sock.c -@@ -110,6 +110,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) - if (!llcp_sock->service_name) { - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; -+ llcp_sock->dev = NULL; - ret = -ENOMEM; - goto put_dev; - } -@@ -119,6 +120,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) - llcp_sock->local = NULL; - kfree(llcp_sock->service_name); - llcp_sock->service_name = NULL; -+ llcp_sock->dev = NULL; - ret = -EADDRINUSE; - goto put_dev; - } -diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c -index 48fdf7293deaa..ba7f57cb41c30 100644 ---- a/net/sched/act_ct.c -+++ b/net/sched/act_ct.c -@@ -984,7 +984,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, - */ - cached = tcf_ct_skb_nfct_cached(net, skb, p->zone, force); - if (!cached) { -- if (!commit && tcf_ct_flow_table_lookup(p, skb, family)) { -+ if (tcf_ct_flow_table_lookup(p, skb, family)) { - skip_add = true; - goto do_nat; - } -@@ -1024,10 +1024,11 @@ do_nat: - * even if the connection is already confirmed. - */ - nf_conntrack_confirm(skb); -- } else if (!skip_add) { -- tcf_ct_flow_table_process_conn(p->ct_ft, ct, ctinfo); - } - -+ if (!skip_add) -+ tcf_ct_flow_table_process_conn(p->ct_ft, ct, ctinfo); -+ - out_push: - skb_push_rcsum(skb, nh_ofs); - -@@ -1204,9 +1205,6 @@ static int tcf_ct_fill_params(struct net *net, - sizeof(p->zone)); - } - -- if (p->zone == NF_CT_DEFAULT_ZONE_ID) -- return 0; -- - nf_ct_zone_init(&zone, p->zone, NF_CT_DEFAULT_ZONE_DIR, 0); - tmpl = nf_ct_tmpl_alloc(net, &zone, GFP_KERNEL); - if (!tmpl) { -diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c -index 081c11d5717c4..8827987ba9034 100644 ---- a/net/sched/sch_htb.c -+++ b/net/sched/sch_htb.c -@@ -1488,7 +1488,8 @@ static void htb_parent_to_leaf_offload(struct Qdisc *sch, - struct Qdisc *old_q; - - /* One ref for cl->leaf.q, the other for dev_queue->qdisc. */ -- qdisc_refcount_inc(new_q); -+ if (new_q) -+ qdisc_refcount_inc(new_q); - old_q = htb_graft_helper(dev_queue, new_q); - WARN_ON(!(old_q->flags & TCQ_F_BUILTIN)); - } -@@ -1675,10 +1676,9 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg, - cl->parent->common.classid, - NULL); - if (q->offload) { -- if (new_q) { -+ if (new_q) - htb_set_lockdep_class_child(new_q); -- htb_parent_to_leaf_offload(sch, dev_queue, new_q); -- } -+ htb_parent_to_leaf_offload(sch, dev_queue, new_q); - } - } - -diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c -index a4389ef08a980..0c8882052ba08 100644 ---- a/net/tipc/bearer.c -+++ b/net/tipc/bearer.c -@@ -243,7 +243,8 @@ void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) - */ - static int tipc_enable_bearer(struct net *net, const char *name, - u32 disc_domain, u32 prio, -- struct nlattr *attr[]) -+ struct nlattr *attr[], -+ struct netlink_ext_ack *extack) - { - struct tipc_net *tn = tipc_net(net); - struct tipc_bearer_names b_names; -@@ -254,20 +255,24 @@ static int tipc_enable_bearer(struct net *net, const char *name, - int bearer_id = 0; - int res = -EINVAL; - char *errstr = ""; -+ u32 i; - - if (!bearer_name_validate(name, &b_names)) { - errstr = "illegal name"; -+ NL_SET_ERR_MSG(extack, "Illegal name"); - goto rejected; - } - - if (prio > TIPC_MAX_LINK_PRI && prio != TIPC_MEDIA_LINK_PRI) { - errstr = "illegal priority"; -+ NL_SET_ERR_MSG(extack, "Illegal priority"); - goto rejected; - } - - m = tipc_media_find(b_names.media_name); - if (!m) { - errstr = "media not registered"; -+ NL_SET_ERR_MSG(extack, "Media not registered"); - goto rejected; - } - -@@ -275,33 +280,43 @@ static int tipc_enable_bearer(struct net *net, const char *name, - prio = m->priority; - - /* Check new bearer vs existing ones and find free bearer id if any */ -- while (bearer_id < MAX_BEARERS) { -- b = rtnl_dereference(tn->bearer_list[bearer_id]); -- if (!b) -- break; -+ bearer_id = MAX_BEARERS; -+ i = MAX_BEARERS; -+ while (i-- != 0) { -+ b = rtnl_dereference(tn->bearer_list[i]); -+ if (!b) { -+ bearer_id = i; -+ continue; -+ } - if (!strcmp(name, b->name)) { - errstr = "already enabled"; -+ NL_SET_ERR_MSG(extack, "Already enabled"); - goto rejected; - } -- bearer_id++; -- if (b->priority != prio) -- continue; -- if (++with_this_prio <= 2) -- continue; -- pr_warn("Bearer <%s>: already 2 bearers with priority %u\n", -- name, prio); -- if (prio == TIPC_MIN_LINK_PRI) { -- errstr = "cannot adjust to lower"; -- goto rejected; -+ -+ if (b->priority == prio && -+ (++with_this_prio > 2)) { -+ pr_warn("Bearer <%s>: already 2 bearers with priority %u\n", -+ name, prio); -+ -+ if (prio == TIPC_MIN_LINK_PRI) { -+ errstr = "cannot adjust to lower"; -+ NL_SET_ERR_MSG(extack, "Cannot adjust to lower"); -+ goto rejected; -+ } -+ -+ pr_warn("Bearer <%s>: trying with adjusted priority\n", -+ name); -+ prio--; -+ bearer_id = MAX_BEARERS; -+ i = MAX_BEARERS; -+ with_this_prio = 1; - } -- pr_warn("Bearer <%s>: trying with adjusted priority\n", name); -- prio--; -- bearer_id = 0; -- with_this_prio = 1; - } - - if (bearer_id >= MAX_BEARERS) { - errstr = "max 3 bearers permitted"; -+ NL_SET_ERR_MSG(extack, "Max 3 bearers permitted"); - goto rejected; - } - -@@ -315,6 +330,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, - if (res) { - kfree(b); - errstr = "failed to enable media"; -+ NL_SET_ERR_MSG(extack, "Failed to enable media"); - goto rejected; - } - -@@ -331,6 +347,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, - if (res) { - bearer_disable(net, b); - errstr = "failed to create discoverer"; -+ NL_SET_ERR_MSG(extack, "Failed to create discoverer"); - goto rejected; - } - -@@ -909,6 +926,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) - bearer = tipc_bearer_find(net, name); - if (!bearer) { - err = -EINVAL; -+ NL_SET_ERR_MSG(info->extack, "Bearer not found"); - goto err_out; - } - -@@ -948,8 +966,10 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) - name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); - - bearer = tipc_bearer_find(net, name); -- if (!bearer) -+ if (!bearer) { -+ NL_SET_ERR_MSG(info->extack, "Bearer not found"); - return -EINVAL; -+ } - - bearer_disable(net, bearer); - -@@ -1007,7 +1027,8 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) - prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); - } - -- return tipc_enable_bearer(net, bearer, domain, prio, attrs); -+ return tipc_enable_bearer(net, bearer, domain, prio, attrs, -+ info->extack); - } - - int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) -@@ -1046,6 +1067,7 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info) - b = tipc_bearer_find(net, name); - if (!b) { - rtnl_unlock(); -+ NL_SET_ERR_MSG(info->extack, "Bearer not found"); - return -EINVAL; - } - -@@ -1086,8 +1108,10 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) - name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); - - b = tipc_bearer_find(net, name); -- if (!b) -+ if (!b) { -+ NL_SET_ERR_MSG(info->extack, "Bearer not found"); - return -EINVAL; -+ } - - if (attrs[TIPC_NLA_BEARER_PROP]) { - struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; -@@ -1106,12 +1130,18 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) - if (props[TIPC_NLA_PROP_WIN]) - b->max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); - if (props[TIPC_NLA_PROP_MTU]) { -- if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) -+ if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) { -+ NL_SET_ERR_MSG(info->extack, -+ "MTU property is unsupported"); - return -EINVAL; -+ } - #ifdef CONFIG_TIPC_MEDIA_UDP - if (tipc_udp_mtu_bad(nla_get_u32 -- (props[TIPC_NLA_PROP_MTU]))) -+ (props[TIPC_NLA_PROP_MTU]))) { -+ NL_SET_ERR_MSG(info->extack, -+ "MTU value is out-of-range"); - return -EINVAL; -+ } - b->mtu = nla_get_u32(props[TIPC_NLA_PROP_MTU]); - tipc_node_apply_property(net, b, TIPC_NLA_PROP_MTU); - #endif -@@ -1239,6 +1269,7 @@ int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info) - rtnl_lock(); - media = tipc_media_find(name); - if (!media) { -+ NL_SET_ERR_MSG(info->extack, "Media not found"); - err = -EINVAL; - goto err_out; - } -@@ -1275,9 +1306,10 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info) - name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]); - - m = tipc_media_find(name); -- if (!m) -+ if (!m) { -+ NL_SET_ERR_MSG(info->extack, "Media not found"); - return -EINVAL; -- -+ } - if (attrs[TIPC_NLA_MEDIA_PROP]) { - struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; - -@@ -1293,12 +1325,18 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info) - if (props[TIPC_NLA_PROP_WIN]) - m->max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); - if (props[TIPC_NLA_PROP_MTU]) { -- if (m->type_id != TIPC_MEDIA_TYPE_UDP) -+ if (m->type_id != TIPC_MEDIA_TYPE_UDP) { -+ NL_SET_ERR_MSG(info->extack, -+ "MTU property is unsupported"); - return -EINVAL; -+ } - #ifdef CONFIG_TIPC_MEDIA_UDP - if (tipc_udp_mtu_bad(nla_get_u32 -- (props[TIPC_NLA_PROP_MTU]))) -+ (props[TIPC_NLA_PROP_MTU]))) { -+ NL_SET_ERR_MSG(info->extack, -+ "MTU value is out-of-range"); - return -EINVAL; -+ } - m->mtu = nla_get_u32(props[TIPC_NLA_PROP_MTU]); - #endif - } -diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c -index d9cd229aa111b..9b1ea17f3b1dc 100644 ---- a/net/tls/tls_device.c -+++ b/net/tls/tls_device.c -@@ -50,6 +50,7 @@ static void tls_device_gc_task(struct work_struct *work); - static DECLARE_WORK(tls_device_gc_work, tls_device_gc_task); - static LIST_HEAD(tls_device_gc_list); - static LIST_HEAD(tls_device_list); -+static LIST_HEAD(tls_device_down_list); - static DEFINE_SPINLOCK(tls_device_lock); - - static void tls_device_free_ctx(struct tls_context *ctx) -@@ -680,15 +681,13 @@ static void tls_device_resync_rx(struct tls_context *tls_ctx, - struct tls_offload_context_rx *rx_ctx = tls_offload_ctx_rx(tls_ctx); - struct net_device *netdev; - -- if (WARN_ON(test_and_set_bit(TLS_RX_SYNC_RUNNING, &tls_ctx->flags))) -- return; -- - trace_tls_device_rx_resync_send(sk, seq, rcd_sn, rx_ctx->resync_type); -+ rcu_read_lock(); - netdev = READ_ONCE(tls_ctx->netdev); - if (netdev) - netdev->tlsdev_ops->tls_dev_resync(netdev, sk, seq, rcd_sn, - TLS_OFFLOAD_CTX_DIR_RX); -- clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags); -+ rcu_read_unlock(); - TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICERESYNC); - } - -@@ -761,6 +760,8 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq) - - if (tls_ctx->rx_conf != TLS_HW) - return; -+ if (unlikely(test_bit(TLS_RX_DEV_DEGRADED, &tls_ctx->flags))) -+ return; - - prot = &tls_ctx->prot_info; - rx_ctx = tls_offload_ctx_rx(tls_ctx); -@@ -963,6 +964,17 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx, - - ctx->sw.decrypted |= is_decrypted; - -+ if (unlikely(test_bit(TLS_RX_DEV_DEGRADED, &tls_ctx->flags))) { -+ if (likely(is_encrypted || is_decrypted)) -+ return 0; -+ -+ /* After tls_device_down disables the offload, the next SKB will -+ * likely have initial fragments decrypted, and final ones not -+ * decrypted. We need to reencrypt that single SKB. -+ */ -+ return tls_device_reencrypt(sk, skb); -+ } -+ - /* Return immediately if the record is either entirely plaintext or - * entirely ciphertext. Otherwise handle reencrypt partially decrypted - * record. -@@ -1292,6 +1304,26 @@ static int tls_device_down(struct net_device *netdev) - spin_unlock_irqrestore(&tls_device_lock, flags); - - list_for_each_entry_safe(ctx, tmp, &list, list) { -+ /* Stop offloaded TX and switch to the fallback. -+ * tls_is_sk_tx_device_offloaded will return false. -+ */ -+ WRITE_ONCE(ctx->sk->sk_validate_xmit_skb, tls_validate_xmit_skb_sw); -+ -+ /* Stop the RX and TX resync. -+ * tls_dev_resync must not be called after tls_dev_del. -+ */ -+ WRITE_ONCE(ctx->netdev, NULL); -+ -+ /* Start skipping the RX resync logic completely. */ -+ set_bit(TLS_RX_DEV_DEGRADED, &ctx->flags); -+ -+ /* Sync with inflight packets. After this point: -+ * TX: no non-encrypted packets will be passed to the driver. -+ * RX: resync requests from the driver will be ignored. -+ */ -+ synchronize_net(); -+ -+ /* Release the offload context on the driver side. */ - if (ctx->tx_conf == TLS_HW) - netdev->tlsdev_ops->tls_dev_del(netdev, ctx, - TLS_OFFLOAD_CTX_DIR_TX); -@@ -1299,15 +1331,21 @@ static int tls_device_down(struct net_device *netdev) - !test_bit(TLS_RX_DEV_CLOSED, &ctx->flags)) - netdev->tlsdev_ops->tls_dev_del(netdev, ctx, - TLS_OFFLOAD_CTX_DIR_RX); -- WRITE_ONCE(ctx->netdev, NULL); -- smp_mb__before_atomic(); /* pairs with test_and_set_bit() */ -- while (test_bit(TLS_RX_SYNC_RUNNING, &ctx->flags)) -- usleep_range(10, 200); -+ - dev_put(netdev); -- list_del_init(&ctx->list); - -- if (refcount_dec_and_test(&ctx->refcount)) -- tls_device_free_ctx(ctx); -+ /* Move the context to a separate list for two reasons: -+ * 1. When the context is deallocated, list_del is called. -+ * 2. It's no longer an offloaded context, so we don't want to -+ * run offload-specific code on this context. -+ */ -+ spin_lock_irqsave(&tls_device_lock, flags); -+ list_move_tail(&ctx->list, &tls_device_down_list); -+ spin_unlock_irqrestore(&tls_device_lock, flags); -+ -+ /* 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. -+ */ - } - - up_write(&device_offload_lock); -diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c -index cacf040872c74..e40bedd112b68 100644 ---- a/net/tls/tls_device_fallback.c -+++ b/net/tls/tls_device_fallback.c -@@ -431,6 +431,13 @@ struct sk_buff *tls_validate_xmit_skb(struct sock *sk, - } - EXPORT_SYMBOL_GPL(tls_validate_xmit_skb); - -+struct sk_buff *tls_validate_xmit_skb_sw(struct sock *sk, -+ struct net_device *dev, -+ struct sk_buff *skb) -+{ -+ return tls_sw_fallback(sk, skb); -+} -+ - struct sk_buff *tls_encrypt_skb(struct sk_buff *skb) - { - return tls_sw_fallback(skb->sk, skb); -diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c -index 47b7c5334c346..fde56ff491637 100644 ---- a/net/tls/tls_main.c -+++ b/net/tls/tls_main.c -@@ -636,6 +636,7 @@ struct tls_context *tls_ctx_create(struct sock *sk) - mutex_init(&ctx->tx_lock); - rcu_assign_pointer(icsk->icsk_ulp_data, ctx); - ctx->sk_proto = READ_ONCE(sk->sk_prot); -+ ctx->sk = sk; - return ctx; - } - -diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c -index 21dbf63d6e415..9ec93d90e8a5a 100644 ---- a/samples/vfio-mdev/mdpy-fb.c -+++ b/samples/vfio-mdev/mdpy-fb.c -@@ -117,22 +117,27 @@ static int mdpy_fb_probe(struct pci_dev *pdev, - if (format != DRM_FORMAT_XRGB8888) { - pci_err(pdev, "format mismatch (0x%x != 0x%x)\n", - format, DRM_FORMAT_XRGB8888); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_release_regions; - } - if (width < 100 || width > 10000) { - pci_err(pdev, "width (%d) out of range\n", width); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_release_regions; - } - if (height < 100 || height > 10000) { - pci_err(pdev, "height (%d) out of range\n", height); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_release_regions; - } - pci_info(pdev, "mdpy found: %dx%d framebuffer\n", - width, height); - - info = framebuffer_alloc(sizeof(struct mdpy_fb_par), &pdev->dev); -- if (!info) -+ if (!info) { -+ ret = -ENOMEM; - goto err_release_regions; -+ } - pci_set_drvdata(pdev, info); - par = info->par; - -diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal -index 735e11e9041b9..19468831fcc73 100644 ---- a/scripts/Makefile.modfinal -+++ b/scripts/Makefile.modfinal -@@ -59,7 +59,7 @@ quiet_cmd_ld_ko_o = LD [M] $@ - quiet_cmd_btf_ko = BTF [M] $@ - cmd_btf_ko = \ - if [ -f vmlinux ]; then \ -- LLVM_OBJCOPY=$(OBJCOPY) $(PAHOLE) -J --btf_base vmlinux $@; \ -+ LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J --btf_base vmlinux $@; \ - else \ - printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \ - fi; -diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh -index 3b261b0f74f0a..0a16928e495b9 100755 ---- a/scripts/link-vmlinux.sh -+++ b/scripts/link-vmlinux.sh -@@ -228,7 +228,7 @@ gen_btf() - vmlinux_link ${1} - - info "BTF" ${2} -- LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} -+ LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${1} - - # Create ${2} which contains just .BTF section but no symbols. Add - # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all -diff --git a/sound/core/timer.c b/sound/core/timer.c -index 6898b1ac0d7f4..92b7008fcdb86 100644 ---- a/sound/core/timer.c -+++ b/sound/core/timer.c -@@ -520,9 +520,10 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) - return; - if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) - return; -+ event += 10; /* convert to SNDRV_TIMER_EVENT_MXXX */ - list_for_each_entry(ts, &ti->slave_active_head, active_list) - if (ts->ccallback) -- ts->ccallback(ts, event + 100, &tstamp, resolution); -+ ts->ccallback(ts, event, &tstamp, resolution); - } - - /* start/continue a master timer */ -diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c -index 2026f1ccaf5a7..a220f7ac81263 100644 ---- a/sound/pci/hda/hda_codec.c -+++ b/sound/pci/hda/hda_codec.c -@@ -2973,6 +2973,7 @@ static int hda_codec_runtime_resume(struct device *dev) - #ifdef CONFIG_PM_SLEEP - static int hda_codec_pm_prepare(struct device *dev) - { -+ dev->power.power_state = PMSG_SUSPEND; - return pm_runtime_suspended(dev); - } - -@@ -2980,6 +2981,10 @@ static void hda_codec_pm_complete(struct device *dev) - { - struct hda_codec *codec = dev_to_hda_codec(dev); - -+ /* If no other pm-functions are called between prepare() and complete() */ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) -+ dev->power.power_state = PMSG_RESUME; -+ - if (pm_runtime_suspended(dev) && (codec->jackpoll_interval || - hda_codec_need_resume(codec) || codec->forced_resume)) - pm_request_resume(dev); -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index d8424d226714f..cc13a68197f3c 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -8289,6 +8289,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), -+ SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3), - SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), - 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), -diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c -index 7b2d471a6419d..4343356f3cf9a 100644 ---- a/tools/perf/util/dwarf-aux.c -+++ b/tools/perf/util/dwarf-aux.c -@@ -975,9 +975,13 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) - if ((tag == DW_TAG_formal_parameter || - tag == DW_TAG_variable) && - die_compare_name(die_mem, fvp->name) && -- /* Does the DIE have location information or external instance? */ -+ /* -+ * Does the DIE have location information or const value -+ * or external instance? -+ */ - (dwarf_attr(die_mem, DW_AT_external, &attr) || -- dwarf_attr(die_mem, DW_AT_location, &attr))) -+ dwarf_attr(die_mem, DW_AT_location, &attr) || -+ dwarf_attr(die_mem, DW_AT_const_value, &attr))) - return DIE_FIND_CB_END; - if (dwarf_haspc(die_mem, fvp->addr)) - return DIE_FIND_CB_CONTINUE; -diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c -index 1b118c9c86a69..bba61b95a37a8 100644 ---- a/tools/perf/util/probe-finder.c -+++ b/tools/perf/util/probe-finder.c -@@ -190,6 +190,9 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, - immediate_value_is_supported()) { - Dwarf_Sword snum; - -+ if (!tvar) -+ return 0; -+ - dwarf_formsdata(&attr, &snum); - ret = asprintf(&tvar->value, "\\%ld", (long)snum); - -diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh -index 7ed7cd95e58fe..ebc4ee0fe179f 100755 ---- a/tools/testing/selftests/wireguard/netns.sh -+++ b/tools/testing/selftests/wireguard/netns.sh -@@ -363,6 +363,7 @@ ip1 -6 rule add table main suppress_prefixlength 0 - ip1 -4 route add default dev wg0 table 51820 - ip1 -4 rule add not fwmark 51820 table 51820 - ip1 -4 rule add table main suppress_prefixlength 0 -+n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/vethc/rp_filter' - # Flood the pings instead of sending just one, to trigger routing table reference counting bugs. - n1 ping -W 1 -c 100 -f 192.168.99.7 - n1 ping -W 1 -c 100 -f abab::1111 -diff --git a/tools/testing/selftests/wireguard/qemu/kernel.config b/tools/testing/selftests/wireguard/qemu/kernel.config -index 4eecb432a66c1..74db83a0aedd8 100644 ---- a/tools/testing/selftests/wireguard/qemu/kernel.config -+++ b/tools/testing/selftests/wireguard/qemu/kernel.config -@@ -19,7 +19,6 @@ CONFIG_NETFILTER_XTABLES=y - CONFIG_NETFILTER_XT_NAT=y - CONFIG_NETFILTER_XT_MATCH_LENGTH=y - CONFIG_NETFILTER_XT_MARK=y --CONFIG_NF_CONNTRACK_IPV4=y - CONFIG_NF_NAT_IPV4=y - CONFIG_IP_NF_IPTABLES=y - CONFIG_IP_NF_FILTER=y