From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 3E1F31382C5 for ; Wed, 3 Jun 2020 11:44:58 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 5B68AE0784; Wed, 3 Jun 2020 11:44:57 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 0B543E0784 for ; Wed, 3 Jun 2020 11:44:57 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 52B163432C1 for ; Wed, 3 Jun 2020 11:44:55 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id D04839C for ; Wed, 3 Jun 2020 11:44:53 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1591184681.17359e12cf00380c018b7bb205be730390d8db4c.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:5.6 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1015_linux-5.6.16.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: 17359e12cf00380c018b7bb205be730390d8db4c X-VCS-Branch: 5.6 Date: Wed, 3 Jun 2020 11:44:53 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 2a09e2db-02fb-4fff-9513-01a36cfe0a69 X-Archives-Hash: e5bd8de3d27e386c092ef5e0bb1060a3 commit: 17359e12cf00380c018b7bb205be730390d8db4c Author: Mike Pagano gentoo org> AuthorDate: Wed Jun 3 11:44:41 2020 +0000 Commit: Mike Pagano gentoo org> CommitDate: Wed Jun 3 11:44:41 2020 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=17359e12 Linux patch 5.6.16 Signed-off-by: Mike Pagano gentoo.org> 0000_README | 4 + 1015_linux-5.6.16.patch | 7460 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 7464 insertions(+) diff --git a/0000_README b/0000_README index 1c0ea04..eb1d2c7 100644 --- a/0000_README +++ b/0000_README @@ -103,6 +103,10 @@ Patch: 1014_linux-5.6.15.patch From: http://www.kernel.org Desc: Linux 5.6.15 +Patch: 1015_linux-5.6.16.patch +From: http://www.kernel.org +Desc: Linux 5.6.16 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1015_linux-5.6.16.patch b/1015_linux-5.6.16.patch new file mode 100644 index 0000000..d0d4b81 --- /dev/null +++ b/1015_linux-5.6.16.patch @@ -0,0 +1,7460 @@ +diff --git a/Makefile b/Makefile +index 3eca0c523098..1befb37dcc58 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 6 +-SUBLEVEL = 15 ++SUBLEVEL = 16 + EXTRAVERSION = + NAME = Kleptomaniac Octopus + +diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S +index fc7ed03d8b93..51b078604978 100644 +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -43,7 +43,7 @@ SECTIONS + } + .table : ALIGN(4) { + _table_start = .; +- LONG(ZIMAGE_MAGIC(2)) ++ LONG(ZIMAGE_MAGIC(4)) + LONG(ZIMAGE_MAGIC(0x5a534c4b)) + LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start)) + LONG(ZIMAGE_MAGIC(_kernel_bss_size)) +diff --git a/arch/arm/boot/dts/bcm-hr2.dtsi b/arch/arm/boot/dts/bcm-hr2.dtsi +index 6142c672811e..5e5f5ca3c86f 100644 +--- a/arch/arm/boot/dts/bcm-hr2.dtsi ++++ b/arch/arm/boot/dts/bcm-hr2.dtsi +@@ -75,7 +75,7 @@ + timer@20200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0x20200 0x100>; +- interrupts = ; ++ interrupts = ; + clocks = <&periph_clk>; + }; + +@@ -83,7 +83,7 @@ + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x20600 0x20>; + interrupts = ; ++ IRQ_TYPE_EDGE_RISING)>; + clocks = <&periph_clk>; + }; + +@@ -91,7 +91,7 @@ + compatible = "arm,cortex-a9-twd-wdt"; + reg = <0x20620 0x20>; + interrupts = ; ++ IRQ_TYPE_EDGE_RISING)>; + clocks = <&periph_clk>; + }; + +diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +index 4c3f606e5b8d..f65448c01e31 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +@@ -24,7 +24,7 @@ + + leds { + act { +- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>; ++ gpios = <&gpio 47 GPIO_ACTIVE_LOW>; + }; + }; + +diff --git a/arch/arm/boot/dts/imx6q-b450v3.dts b/arch/arm/boot/dts/imx6q-b450v3.dts +index 95b8f2d71821..fb0980190aa0 100644 +--- a/arch/arm/boot/dts/imx6q-b450v3.dts ++++ b/arch/arm/boot/dts/imx6q-b450v3.dts +@@ -65,13 +65,6 @@ + }; + }; + +-&clks { +- assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, +- <&clks IMX6QDL_CLK_LDB_DI1_SEL>; +- assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>, +- <&clks IMX6QDL_CLK_PLL3_USB_OTG>; +-}; +- + &ldb { + status = "okay"; + +diff --git a/arch/arm/boot/dts/imx6q-b650v3.dts b/arch/arm/boot/dts/imx6q-b650v3.dts +index 611cb7ae7e55..8f762d9c5ae9 100644 +--- a/arch/arm/boot/dts/imx6q-b650v3.dts ++++ b/arch/arm/boot/dts/imx6q-b650v3.dts +@@ -65,13 +65,6 @@ + }; + }; + +-&clks { +- assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, +- <&clks IMX6QDL_CLK_LDB_DI1_SEL>; +- assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>, +- <&clks IMX6QDL_CLK_PLL3_USB_OTG>; +-}; +- + &ldb { + status = "okay"; + +diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts +index e4cb118f88c6..1ea64ecf4291 100644 +--- a/arch/arm/boot/dts/imx6q-b850v3.dts ++++ b/arch/arm/boot/dts/imx6q-b850v3.dts +@@ -53,17 +53,6 @@ + }; + }; + +-&clks { +- assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, +- <&clks IMX6QDL_CLK_LDB_DI1_SEL>, +- <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>, +- <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>; +- assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, +- <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, +- <&clks IMX6QDL_CLK_PLL2_PFD2_396M>, +- <&clks IMX6QDL_CLK_PLL2_PFD2_396M>; +-}; +- + &ldb { + fsl,dual-channel; + status = "okay"; +diff --git a/arch/arm/boot/dts/imx6q-bx50v3.dtsi b/arch/arm/boot/dts/imx6q-bx50v3.dtsi +index fa27dcdf06f1..1938b04199c4 100644 +--- a/arch/arm/boot/dts/imx6q-bx50v3.dtsi ++++ b/arch/arm/boot/dts/imx6q-bx50v3.dtsi +@@ -377,3 +377,18 @@ + #interrupt-cells = <1>; + }; + }; ++ ++&clks { ++ assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, ++ <&clks IMX6QDL_CLK_LDB_DI1_SEL>, ++ <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>, ++ <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>, ++ <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>, ++ <&clks IMX6QDL_CLK_IPU2_DI1_PRE_SEL>; ++ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, ++ <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, ++ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>, ++ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>, ++ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>, ++ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>; ++}; +diff --git a/arch/arm/boot/dts/mmp3-dell-ariel.dts b/arch/arm/boot/dts/mmp3-dell-ariel.dts +index 15449c72c042..b0ec14c42164 100644 +--- a/arch/arm/boot/dts/mmp3-dell-ariel.dts ++++ b/arch/arm/boot/dts/mmp3-dell-ariel.dts +@@ -98,19 +98,19 @@ + status = "okay"; + }; + +-&ssp3 { ++&ssp1 { + status = "okay"; +- cs-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; + + firmware-flash@0 { +- compatible = "st,m25p80", "jedec,spi-nor"; ++ compatible = "winbond,w25q32", "jedec,spi-nor"; + reg = <0>; +- spi-max-frequency = <40000000>; ++ spi-max-frequency = <104000000>; + m25p,fast-read; + }; + }; + +-&ssp4 { +- cs-gpios = <&gpio 56 GPIO_ACTIVE_HIGH>; ++&ssp2 { ++ cs-gpios = <&gpio 56 GPIO_ACTIVE_LOW>; + status = "okay"; + }; +diff --git a/arch/arm/boot/dts/mmp3.dtsi b/arch/arm/boot/dts/mmp3.dtsi +index 59a108e49b41..1e25bf998ab5 100644 +--- a/arch/arm/boot/dts/mmp3.dtsi ++++ b/arch/arm/boot/dts/mmp3.dtsi +@@ -202,8 +202,7 @@ + }; + + hsic_phy0: hsic-phy@f0001800 { +- compatible = "marvell,mmp3-hsic-phy", +- "usb-nop-xceiv"; ++ compatible = "marvell,mmp3-hsic-phy"; + reg = <0xf0001800 0x40>; + #phy-cells = <0>; + status = "disabled"; +@@ -224,8 +223,7 @@ + }; + + hsic_phy1: hsic-phy@f0002800 { +- compatible = "marvell,mmp3-hsic-phy", +- "usb-nop-xceiv"; ++ compatible = "marvell,mmp3-hsic-phy"; + reg = <0xf0002800 0x40>; + #phy-cells = <0>; + status = "disabled"; +@@ -531,7 +529,7 @@ + }; + + soc_clocks: clocks@d4050000 { +- compatible = "marvell,mmp2-clock"; ++ compatible = "marvell,mmp3-clock"; + reg = <0xd4050000 0x1000>, + <0xd4282800 0x400>, + <0xd4015000 0x1000>; +diff --git a/arch/arm/boot/dts/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/motorola-mapphone-common.dtsi +index 9067e0ef4240..06fbffa81636 100644 +--- a/arch/arm/boot/dts/motorola-mapphone-common.dtsi ++++ b/arch/arm/boot/dts/motorola-mapphone-common.dtsi +@@ -367,6 +367,8 @@ + }; + + &mmc3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins>; + vmmc-supply = <&wl12xx_vmmc>; + /* uart2_tx.sdmmc3_dat1 pad as wakeirq */ + interrupts-extended = <&wakeupgen GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH +@@ -472,6 +474,37 @@ + >; + }; + ++ /* ++ * Android uses PIN_OFF_INPUT_PULLDOWN | PIN_INPUT_PULLUP | MUX_MODE3 ++ * for gpio_100, but the internal pull makes wlan flakey on some ++ * devices. Off mode value should be tested if we have off mode working ++ * later on. ++ */ ++ mmc3_pins: pinmux_mmc3_pins { ++ pinctrl-single,pins = < ++ /* 0x4a10008e gpmc_wait2.gpio_100 d23 */ ++ OMAP4_IOPAD(0x08e, PIN_INPUT | MUX_MODE3) ++ ++ /* 0x4a100102 abe_mcbsp1_dx.sdmmc3_dat2 ab25 */ ++ OMAP4_IOPAD(0x102, PIN_INPUT_PULLUP | MUX_MODE1) ++ ++ /* 0x4a100104 abe_mcbsp1_fsx.sdmmc3_dat3 ac27 */ ++ OMAP4_IOPAD(0x104, PIN_INPUT_PULLUP | MUX_MODE1) ++ ++ /* 0x4a100118 uart2_cts.sdmmc3_clk ab26 */ ++ OMAP4_IOPAD(0x118, PIN_INPUT | MUX_MODE1) ++ ++ /* 0x4a10011a uart2_rts.sdmmc3_cmd ab27 */ ++ OMAP4_IOPAD(0x11a, PIN_INPUT_PULLUP | MUX_MODE1) ++ ++ /* 0x4a10011c uart2_rx.sdmmc3_dat0 aa25 */ ++ OMAP4_IOPAD(0x11c, PIN_INPUT_PULLUP | MUX_MODE1) ++ ++ /* 0x4a10011e uart2_tx.sdmmc3_dat1 aa26 */ ++ OMAP4_IOPAD(0x11e, PIN_INPUT_PULLUP | MUX_MODE1) ++ >; ++ }; ++ + /* gpmc_ncs0.gpio_50 */ + poweroff_gpio: pinmux_poweroff_pins { + pinctrl-single,pins = < +@@ -690,14 +723,18 @@ + }; + + /* +- * As uart1 is wired to mdm6600 with rts and cts, we can use the cts pin for +- * uart1 wakeirq. ++ * The uart1 port is wired to mdm6600 with rts and cts. The modem uses gpio_149 ++ * for wake-up events for both the USB PHY and the UART. We can use gpio_149 ++ * pad as the shared wakeirq for the UART rather than the RX or CTS pad as we ++ * have gpio_149 trigger before the UART transfer starts. + */ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + interrupts-extended = <&wakeupgen GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH +- &omap4_pmx_core 0xfc>; ++ &omap4_pmx_core 0x110>; ++ uart-has-rtscts; ++ current-speed = <115200>; + }; + + &uart3 { +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index cf36e25195b4..8c4b8f56c9e0 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -128,7 +128,7 @@ + assigned-clocks = <&cru SCLK_GPU>; + assigned-clock-rates = <100000000>; + clocks = <&cru SCLK_GPU>, <&cru SCLK_GPU>; +- clock-names = "core", "bus"; ++ clock-names = "bus", "core"; + resets = <&cru SRST_GPU>; + status = "disabled"; + }; +diff --git a/arch/arm/boot/dts/rk3228-evb.dts b/arch/arm/boot/dts/rk3228-evb.dts +index 5670b33fd1bd..aed879db6c15 100644 +--- a/arch/arm/boot/dts/rk3228-evb.dts ++++ b/arch/arm/boot/dts/rk3228-evb.dts +@@ -46,7 +46,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- phy: phy@0 { ++ phy: ethernet-phy@0 { + compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22"; + reg = <0>; + clocks = <&cru SCLK_MAC_PHY>; +diff --git a/arch/arm/boot/dts/rk3229-xms6.dts b/arch/arm/boot/dts/rk3229-xms6.dts +index 679fc2b00e5a..933ef69da32a 100644 +--- a/arch/arm/boot/dts/rk3229-xms6.dts ++++ b/arch/arm/boot/dts/rk3229-xms6.dts +@@ -150,7 +150,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- phy: phy@0 { ++ phy: ethernet-phy@0 { + compatible = "ethernet-phy-id1234.d400", + "ethernet-phy-ieee802.3-c22"; + reg = <0>; +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 4e90efdc9630..a83f65486ad4 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -561,7 +561,7 @@ + "pp1", + "ppmmu1"; + clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; +- clock-names = "core", "bus"; ++ clock-names = "bus", "core"; + resets = <&cru SRST_GPU_A>; + status = "disabled"; + }; +@@ -1033,7 +1033,7 @@ + }; + }; + +- spi-0 { ++ spi0 { + spi0_clk: spi0-clk { + rockchip,pins = <0 RK_PB1 2 &pcfg_pull_up>; + }; +@@ -1051,7 +1051,7 @@ + }; + }; + +- spi-1 { ++ spi1 { + spi1_clk: spi1-clk { + rockchip,pins = <0 RK_PC7 2 &pcfg_pull_up>; + }; +diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi +index 241f43e29c77..bb5ff10b9110 100644 +--- a/arch/arm/boot/dts/rk3xxx.dtsi ++++ b/arch/arm/boot/dts/rk3xxx.dtsi +@@ -84,7 +84,7 @@ + compatible = "arm,mali-400"; + reg = <0x10090000 0x10000>; + clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; +- clock-names = "core", "bus"; ++ clock-names = "bus", "core"; + assigned-clocks = <&cru ACLK_GPU>; + assigned-clock-rates = <100000000>; + resets = <&cru SRST_GPU>; +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index 99929122dad7..3546d294d55f 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -18,11 +18,11 @@ + #endif + + #include +-#include + #include + #include + #include + #include ++#include + + #define IOMEM(x) (x) + +@@ -446,79 +446,6 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) + .size \name , . - \name + .endm + +- .macro csdb +-#ifdef CONFIG_THUMB2_KERNEL +- .inst.w 0xf3af8014 +-#else +- .inst 0xe320f014 +-#endif +- .endm +- +- .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +-#ifndef CONFIG_CPU_USE_DOMAINS +- adds \tmp, \addr, #\size - 1 +- sbcscc \tmp, \tmp, \limit +- bcs \bad +-#ifdef CONFIG_CPU_SPECTRE +- movcs \addr, #0 +- csdb +-#endif +-#endif +- .endm +- +- .macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req +-#ifdef CONFIG_CPU_SPECTRE +- sub \tmp, \limit, #1 +- subs \tmp, \tmp, \addr @ tmp = limit - 1 - addr +- addhs \tmp, \tmp, #1 @ if (tmp >= 0) { +- subshs \tmp, \tmp, \size @ tmp = limit - (addr + size) } +- movlo \addr, #0 @ if (tmp < 0) addr = NULL +- csdb +-#endif +- .endm +- +- .macro uaccess_disable, tmp, isb=1 +-#ifdef CONFIG_CPU_SW_DOMAIN_PAN +- /* +- * Whenever we re-enter userspace, the domains should always be +- * set appropriately. +- */ +- mov \tmp, #DACR_UACCESS_DISABLE +- mcr p15, 0, \tmp, c3, c0, 0 @ Set domain register +- .if \isb +- instr_sync +- .endif +-#endif +- .endm +- +- .macro uaccess_enable, tmp, isb=1 +-#ifdef CONFIG_CPU_SW_DOMAIN_PAN +- /* +- * Whenever we re-enter userspace, the domains should always be +- * set appropriately. +- */ +- mov \tmp, #DACR_UACCESS_ENABLE +- mcr p15, 0, \tmp, c3, c0, 0 +- .if \isb +- instr_sync +- .endif +-#endif +- .endm +- +- .macro uaccess_save, tmp +-#ifdef CONFIG_CPU_SW_DOMAIN_PAN +- mrc p15, 0, \tmp, c3, c0, 0 +- str \tmp, [sp, #SVC_DACR] +-#endif +- .endm +- +- .macro uaccess_restore +-#ifdef CONFIG_CPU_SW_DOMAIN_PAN +- ldr r0, [sp, #SVC_DACR] +- mcr p15, 0, r0, c3, c0, 0 +-#endif +- .endm +- + .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo + .macro ret\c, reg + #if __LINUX_ARM_ARCH__ < 6 +diff --git a/arch/arm/include/asm/uaccess-asm.h b/arch/arm/include/asm/uaccess-asm.h +new file mode 100644 +index 000000000000..907571fd05c6 +--- /dev/null ++++ b/arch/arm/include/asm/uaccess-asm.h +@@ -0,0 +1,117 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef __ASM_UACCESS_ASM_H__ ++#define __ASM_UACCESS_ASM_H__ ++ ++#include ++#include ++#include ++#include ++ ++ .macro csdb ++#ifdef CONFIG_THUMB2_KERNEL ++ .inst.w 0xf3af8014 ++#else ++ .inst 0xe320f014 ++#endif ++ .endm ++ ++ .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req ++#ifndef CONFIG_CPU_USE_DOMAINS ++ adds \tmp, \addr, #\size - 1 ++ sbcscc \tmp, \tmp, \limit ++ bcs \bad ++#ifdef CONFIG_CPU_SPECTRE ++ movcs \addr, #0 ++ csdb ++#endif ++#endif ++ .endm ++ ++ .macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req ++#ifdef CONFIG_CPU_SPECTRE ++ sub \tmp, \limit, #1 ++ subs \tmp, \tmp, \addr @ tmp = limit - 1 - addr ++ addhs \tmp, \tmp, #1 @ if (tmp >= 0) { ++ subshs \tmp, \tmp, \size @ tmp = limit - (addr + size) } ++ movlo \addr, #0 @ if (tmp < 0) addr = NULL ++ csdb ++#endif ++ .endm ++ ++ .macro uaccess_disable, tmp, isb=1 ++#ifdef CONFIG_CPU_SW_DOMAIN_PAN ++ /* ++ * Whenever we re-enter userspace, the domains should always be ++ * set appropriately. ++ */ ++ mov \tmp, #DACR_UACCESS_DISABLE ++ mcr p15, 0, \tmp, c3, c0, 0 @ Set domain register ++ .if \isb ++ instr_sync ++ .endif ++#endif ++ .endm ++ ++ .macro uaccess_enable, tmp, isb=1 ++#ifdef CONFIG_CPU_SW_DOMAIN_PAN ++ /* ++ * Whenever we re-enter userspace, the domains should always be ++ * set appropriately. ++ */ ++ mov \tmp, #DACR_UACCESS_ENABLE ++ mcr p15, 0, \tmp, c3, c0, 0 ++ .if \isb ++ instr_sync ++ .endif ++#endif ++ .endm ++ ++#if defined(CONFIG_CPU_SW_DOMAIN_PAN) || defined(CONFIG_CPU_USE_DOMAINS) ++#define DACR(x...) x ++#else ++#define DACR(x...) ++#endif ++ ++ /* ++ * Save the address limit on entry to a privileged exception. ++ * ++ * If we are using the DACR for kernel access by the user accessors ++ * (CONFIG_CPU_USE_DOMAINS=y), always reset the DACR kernel domain ++ * back to client mode, whether or not \disable is set. ++ * ++ * If we are using SW PAN, set the DACR user domain to no access ++ * if \disable is set. ++ */ ++ .macro uaccess_entry, tsk, tmp0, tmp1, tmp2, disable ++ ldr \tmp1, [\tsk, #TI_ADDR_LIMIT] ++ mov \tmp2, #TASK_SIZE ++ str \tmp2, [\tsk, #TI_ADDR_LIMIT] ++ DACR( mrc p15, 0, \tmp0, c3, c0, 0) ++ DACR( str \tmp0, [sp, #SVC_DACR]) ++ str \tmp1, [sp, #SVC_ADDR_LIMIT] ++ .if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN) ++ /* kernel=client, user=no access */ ++ mov \tmp2, #DACR_UACCESS_DISABLE ++ mcr p15, 0, \tmp2, c3, c0, 0 ++ instr_sync ++ .elseif IS_ENABLED(CONFIG_CPU_USE_DOMAINS) ++ /* kernel=client */ ++ bic \tmp2, \tmp0, #domain_mask(DOMAIN_KERNEL) ++ orr \tmp2, \tmp2, #domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT) ++ mcr p15, 0, \tmp2, c3, c0, 0 ++ instr_sync ++ .endif ++ .endm ++ ++ /* Restore the user access state previously saved by uaccess_entry */ ++ .macro uaccess_exit, tsk, tmp0, tmp1 ++ ldr \tmp1, [sp, #SVC_ADDR_LIMIT] ++ DACR( ldr \tmp0, [sp, #SVC_DACR]) ++ str \tmp1, [\tsk, #TI_ADDR_LIMIT] ++ DACR( mcr p15, 0, \tmp0, c3, c0, 0) ++ .endm ++ ++#undef DACR ++ ++#endif /* __ASM_UACCESS_ASM_H__ */ +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index 77f54830554c..55a47df04773 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "entry-header.S" + #include +@@ -179,15 +180,7 @@ ENDPROC(__und_invalid) + stmia r7, {r2 - r6} + + get_thread_info tsk +- ldr r0, [tsk, #TI_ADDR_LIMIT] +- mov r1, #TASK_SIZE +- str r1, [tsk, #TI_ADDR_LIMIT] +- str r0, [sp, #SVC_ADDR_LIMIT] +- +- uaccess_save r0 +- .if \uaccess +- uaccess_disable r0 +- .endif ++ uaccess_entry tsk, r0, r1, r2, \uaccess + + .if \trace + #ifdef CONFIG_TRACE_IRQFLAGS +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index 32051ec5b33f..40db0f9188b6 100644 +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + @ Bad Abort numbers +@@ -217,9 +218,7 @@ + blne trace_hardirqs_off + #endif + .endif +- ldr r1, [sp, #SVC_ADDR_LIMIT] +- uaccess_restore +- str r1, [tsk, #TI_ADDR_LIMIT] ++ uaccess_exit tsk, r0, r1 + + #ifndef CONFIG_THUMB2_KERNEL + @ ARM mode SVC restore +@@ -263,9 +262,7 @@ + @ on the stack remains correct). + @ + .macro svc_exit_via_fiq +- ldr r1, [sp, #SVC_ADDR_LIMIT] +- uaccess_restore +- str r1, [tsk, #TI_ADDR_LIMIT] ++ uaccess_exit tsk, r0, r1 + #ifndef CONFIG_THUMB2_KERNEL + @ ARM mode restore + mov r0, sp +diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +index 8b4e806d5119..125c78321ab4 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +@@ -1401,8 +1401,8 @@ + "venc_lt_sel"; + assigned-clocks = <&topckgen CLK_TOP_VENC_SEL>, + <&topckgen CLK_TOP_VENC_LT_SEL>; +- assigned-clock-parents = <&topckgen CLK_TOP_VENCPLL_D2>, +- <&topckgen CLK_TOP_UNIVPLL1_D2>; ++ assigned-clock-parents = <&topckgen CLK_TOP_VCODECPLL>, ++ <&topckgen CLK_TOP_VCODECPLL_370P5>; + }; + + jpegdec: jpegdec@18004000 { +diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +index a85b85d85a5f..3c7c9b52623c 100644 +--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi ++++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +@@ -908,10 +908,27 @@ + status = "okay"; + }; + ++&q6asmdai { ++ dai@0 { ++ reg = <0>; ++ }; ++ ++ dai@1 { ++ reg = <1>; ++ }; ++ ++ dai@2 { ++ reg = <2>; ++ }; ++}; ++ + &sound { + compatible = "qcom,apq8096-sndcard"; + model = "DB820c"; +- audio-routing = "RX_BIAS", "MCLK"; ++ audio-routing = "RX_BIAS", "MCLK", ++ "MM_DL1", "MultiMedia1 Playback", ++ "MM_DL2", "MultiMedia2 Playback", ++ "MultiMedia3 Capture", "MM_UL3"; + + mm1-dai-link { + link-name = "MultiMedia1"; +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 7ae082ea14ea..f925a6c7d293 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -2053,6 +2053,8 @@ + reg = ; + q6asmdai: dais { + compatible = "qcom,q6asm-dais"; ++ #address-cells = <1>; ++ #size-cells = <0>; + #sound-dai-cells = <1>; + iommus = <&lpass_q6_smmu 1>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +index 6abc6f4a86cf..05265b38cc02 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +@@ -86,7 +86,7 @@ + assigned-clock-rate = <50000000>; + assigned-clocks = <&cru SCLK_MAC2PHY>; + assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; +- ++ status = "okay"; + }; + + &i2c1 { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 5c4238a80144..c341172ec208 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1890,10 +1890,10 @@ + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; +- interrupts = , +- , +- ; +- interrupt-names = "gpu", "job", "mmu"; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; + clocks = <&cru ACLK_GPU>; + #cooling-cells = <2>; + power-domains = <&power RK3399_PD_GPU>; +diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h +index 5056ebb902d1..61d94ec7dd16 100644 +--- a/arch/csky/abiv1/inc/abi/entry.h ++++ b/arch/csky/abiv1/inc/abi/entry.h +@@ -167,8 +167,8 @@ + * BA Reserved C D V + */ + cprcr r6, cpcr30 +- lsri r6, 28 +- lsli r6, 28 ++ lsri r6, 29 ++ lsli r6, 29 + addi r6, 0xe + cpwcr r6, cpcr30 + +diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h +index 111973c6c713..9023828ede97 100644 +--- a/arch/csky/abiv2/inc/abi/entry.h ++++ b/arch/csky/abiv2/inc/abi/entry.h +@@ -225,8 +225,8 @@ + */ + mfcr r6, cr<30, 15> /* Get MSA0 */ + 2: +- lsri r6, 28 +- lsli r6, 28 ++ lsri r6, 29 ++ lsli r6, 29 + addi r6, 0x1ce + mtcr r6, cr<30, 15> /* Set MSA0 */ + +diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h +index eaa1c3403a42..60f8a4112588 100644 +--- a/arch/csky/include/asm/uaccess.h ++++ b/arch/csky/include/asm/uaccess.h +@@ -254,7 +254,7 @@ do { \ + + extern int __get_user_bad(void); + +-#define __copy_user(to, from, n) \ ++#define ___copy_to_user(to, from, n) \ + do { \ + int w0, w1, w2, w3; \ + asm volatile( \ +@@ -289,31 +289,34 @@ do { \ + " subi %0, 4 \n" \ + " br 3b \n" \ + "5: cmpnei %0, 0 \n" /* 1B */ \ +- " bf 8f \n" \ ++ " bf 13f \n" \ + " ldb %3, (%2, 0) \n" \ + "6: stb %3, (%1, 0) \n" \ + " addi %2, 1 \n" \ + " addi %1, 1 \n" \ + " subi %0, 1 \n" \ + " br 5b \n" \ +- "7: br 8f \n" \ ++ "7: subi %0, 4 \n" \ ++ "8: subi %0, 4 \n" \ ++ "12: subi %0, 4 \n" \ ++ " br 13f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ +- ".long 2b, 7b \n" \ +- ".long 9b, 7b \n" \ +- ".long 10b, 7b \n" \ ++ ".long 2b, 13f \n" \ ++ ".long 4b, 13f \n" \ ++ ".long 6b, 13f \n" \ ++ ".long 9b, 12b \n" \ ++ ".long 10b, 8b \n" \ + ".long 11b, 7b \n" \ +- ".long 4b, 7b \n" \ +- ".long 6b, 7b \n" \ + ".previous \n" \ +- "8: \n" \ ++ "13: \n" \ + : "=r"(n), "=r"(to), "=r"(from), "=r"(w0), \ + "=r"(w1), "=r"(w2), "=r"(w3) \ + : "0"(n), "1"(to), "2"(from) \ + : "memory"); \ + } while (0) + +-#define __copy_user_zeroing(to, from, n) \ ++#define ___copy_from_user(to, from, n) \ + do { \ + int tmp; \ + int nsave; \ +@@ -356,22 +359,22 @@ do { \ + " addi %1, 1 \n" \ + " subi %0, 1 \n" \ + " br 5b \n" \ +- "8: mov %3, %0 \n" \ +- " movi %4, 0 \n" \ +- "9: stb %4, (%1, 0) \n" \ +- " addi %1, 1 \n" \ +- " subi %3, 1 \n" \ +- " cmpnei %3, 0 \n" \ +- " bt 9b \n" \ +- " br 7f \n" \ ++ "8: stw %3, (%1, 0) \n" \ ++ " subi %0, 4 \n" \ ++ " bf 7f \n" \ ++ "9: subi %0, 8 \n" \ ++ " bf 7f \n" \ ++ "13: stw %3, (%1, 8) \n" \ ++ " subi %0, 12 \n" \ ++ " bf 7f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ +- ".long 2b, 8b \n" \ ++ ".long 2b, 7f \n" \ ++ ".long 4b, 7f \n" \ ++ ".long 6b, 7f \n" \ + ".long 10b, 8b \n" \ +- ".long 11b, 8b \n" \ +- ".long 12b, 8b \n" \ +- ".long 4b, 8b \n" \ +- ".long 6b, 8b \n" \ ++ ".long 11b, 9b \n" \ ++ ".long 12b,13b \n" \ + ".previous \n" \ + "7: \n" \ + : "=r"(n), "=r"(to), "=r"(from), "=r"(nsave), \ +diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S +index 007706328000..9718388448a4 100644 +--- a/arch/csky/kernel/entry.S ++++ b/arch/csky/kernel/entry.S +@@ -318,8 +318,6 @@ ENTRY(__switch_to) + + mfcr a2, psr /* Save PSR value */ + stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ +- bclri a2, 6 /* Disable interrupts */ +- mtcr a2, psr + + SAVE_SWITCH_STACK + +diff --git a/arch/csky/kernel/perf_callchain.c b/arch/csky/kernel/perf_callchain.c +index e68ff375c8f8..ab55e98ee8f6 100644 +--- a/arch/csky/kernel/perf_callchain.c ++++ b/arch/csky/kernel/perf_callchain.c +@@ -12,12 +12,17 @@ struct stackframe { + + static int unwind_frame_kernel(struct stackframe *frame) + { +- if (kstack_end((void *)frame->fp)) ++ unsigned long low = (unsigned long)task_stack_page(current); ++ unsigned long high = low + THREAD_SIZE; ++ ++ if (unlikely(frame->fp < low || frame->fp > high)) + return -EPERM; +- if (frame->fp & 0x3 || frame->fp < TASK_SIZE) ++ ++ if (kstack_end((void *)frame->fp) || frame->fp & 0x3) + return -EPERM; + + *frame = *(struct stackframe *)frame->fp; ++ + if (__kernel_text_address(frame->lr)) { + int graph = 0; + +diff --git a/arch/csky/lib/usercopy.c b/arch/csky/lib/usercopy.c +index 647a23986fb5..3c9bd645e643 100644 +--- a/arch/csky/lib/usercopy.c ++++ b/arch/csky/lib/usercopy.c +@@ -7,10 +7,7 @@ + unsigned long raw_copy_from_user(void *to, const void *from, + unsigned long n) + { +- if (access_ok(from, n)) +- __copy_user_zeroing(to, from, n); +- else +- memset(to, 0, n); ++ ___copy_from_user(to, from, n); + return n; + } + EXPORT_SYMBOL(raw_copy_from_user); +@@ -18,8 +15,7 @@ EXPORT_SYMBOL(raw_copy_from_user); + unsigned long raw_copy_to_user(void *to, const void *from, + unsigned long n) + { +- if (access_ok(to, n)) +- __copy_user(to, from, n); ++ ___copy_to_user(to, from, n); + return n; + } + EXPORT_SYMBOL(raw_copy_to_user); +diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c +index 5224fb38d766..01d7071b23f7 100644 +--- a/arch/parisc/mm/init.c ++++ b/arch/parisc/mm/init.c +@@ -562,7 +562,7 @@ void __init mem_init(void) + > BITS_PER_LONG); + + high_memory = __va((max_pfn << PAGE_SHIFT)); +- set_max_mapnr(page_to_pfn(virt_to_page(high_memory - 1)) + 1); ++ set_max_mapnr(max_low_pfn); + memblock_free_all(); + + #ifdef CONFIG_PA11 +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index b0fb42b0bf4b..35608b9feb14 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -125,6 +125,7 @@ config PPC + select ARCH_HAS_MMIOWB if PPC64 + select ARCH_HAS_PHYS_TO_DMA + select ARCH_HAS_PMEM_API ++ select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE + select ARCH_HAS_PTE_DEVMAP if PPC_BOOK3S_64 + select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_MEMBARRIER_CALLBACKS +diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs +index a131174a0a77..f310ad8ffcf7 100644 +--- a/arch/riscv/Kconfig.socs ++++ b/arch/riscv/Kconfig.socs +@@ -11,13 +11,14 @@ config SOC_SIFIVE + This enables support for SiFive SoC platform hardware. + + config SOC_VIRT +- bool "QEMU Virt Machine" +- select POWER_RESET_SYSCON +- select POWER_RESET_SYSCON_POWEROFF +- select GOLDFISH +- select RTC_DRV_GOLDFISH +- select SIFIVE_PLIC +- help +- This enables support for QEMU Virt Machine. ++ bool "QEMU Virt Machine" ++ select POWER_RESET ++ select POWER_RESET_SYSCON ++ select POWER_RESET_SYSCON_POWEROFF ++ select GOLDFISH ++ select RTC_DRV_GOLDFISH if RTC_CLASS ++ select SIFIVE_PLIC ++ help ++ This enables support for QEMU Virt Machine. + + endmenu +diff --git a/arch/riscv/include/asm/mmio.h b/arch/riscv/include/asm/mmio.h +index a2c809df2733..56053c9838b2 100644 +--- a/arch/riscv/include/asm/mmio.h ++++ b/arch/riscv/include/asm/mmio.h +@@ -16,6 +16,8 @@ + + #ifndef CONFIG_MMU + #define pgprot_noncached(x) (x) ++#define pgprot_writecombine(x) (x) ++#define pgprot_device(x) (x) + #endif /* CONFIG_MMU */ + + /* Generic IO read/write. These perform native-endian accesses. */ +diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h +index 393f2014dfee..31d912944d8d 100644 +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -460,12 +460,15 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, + + #else /* CONFIG_MMU */ + ++#define PAGE_SHARED __pgprot(0) + #define PAGE_KERNEL __pgprot(0) + #define swapper_pg_dir NULL + #define VMALLOC_START 0 + + #define TASK_SIZE 0xffffffffUL + ++static inline void __kernel_map_pages(struct page *page, int numpages, int enable) {} ++ + #endif /* !CONFIG_MMU */ + + #define kern_addr_valid(addr) (1) /* FIXME */ +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 0940681d2f68..19e46f4160cc 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -63,7 +63,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + + #else /* !CONFIG_FRAME_POINTER */ + +-static void notrace walk_stackframe(struct task_struct *task, ++void notrace walk_stackframe(struct task_struct *task, + struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg) + { + unsigned long sp, pc; +diff --git a/arch/x86/include/asm/dma.h b/arch/x86/include/asm/dma.h +index 00f7cf45e699..8e95aa4b0d17 100644 +--- a/arch/x86/include/asm/dma.h ++++ b/arch/x86/include/asm/dma.h +@@ -74,7 +74,7 @@ + #define MAX_DMA_PFN ((16UL * 1024 * 1024) >> PAGE_SHIFT) + + /* 4GB broken PCI/AGP hardware bus master zone */ +-#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) ++#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT)) + + #ifdef CONFIG_X86_32 + /* The maximum address that we can perform a DMA transfer to on this platform */ +diff --git a/arch/x86/include/asm/io_bitmap.h b/arch/x86/include/asm/io_bitmap.h +index 07344d82e88e..ac1a99ffbd8d 100644 +--- a/arch/x86/include/asm/io_bitmap.h ++++ b/arch/x86/include/asm/io_bitmap.h +@@ -17,7 +17,7 @@ struct task_struct; + + #ifdef CONFIG_X86_IOPL_IOPERM + void io_bitmap_share(struct task_struct *tsk); +-void io_bitmap_exit(void); ++void io_bitmap_exit(struct task_struct *tsk); + + void native_tss_update_io_bitmap(void); + +@@ -29,7 +29,7 @@ void native_tss_update_io_bitmap(void); + + #else + static inline void io_bitmap_share(struct task_struct *tsk) { } +-static inline void io_bitmap_exit(void) { } ++static inline void io_bitmap_exit(struct task_struct *tsk) { } + static inline void tss_update_io_bitmap(void) { } + #endif + +diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c +index a1806598aaa4..cf2f2a85f087 100644 +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -954,18 +954,31 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures) + return true; + } + +-/* +- * This is similar to user_regset_copyout(), but will not add offset to +- * the source data pointer or increment pos, count, kbuf, and ubuf. +- */ +-static inline void +-__copy_xstate_to_kernel(void *kbuf, const void *data, +- unsigned int offset, unsigned int size, unsigned int size_total) ++static void fill_gap(unsigned to, void **kbuf, unsigned *pos, unsigned *count) + { +- if (offset < size_total) { +- unsigned int copy = min(size, size_total - offset); ++ if (*pos < to) { ++ unsigned size = to - *pos; ++ ++ if (size > *count) ++ size = *count; ++ memcpy(*kbuf, (void *)&init_fpstate.xsave + *pos, size); ++ *kbuf += size; ++ *pos += size; ++ *count -= size; ++ } ++} + +- memcpy(kbuf + offset, data, copy); ++static void copy_part(unsigned offset, unsigned size, void *from, ++ void **kbuf, unsigned *pos, unsigned *count) ++{ ++ fill_gap(offset, kbuf, pos, count); ++ if (size > *count) ++ size = *count; ++ if (size) { ++ memcpy(*kbuf, from, size); ++ *kbuf += size; ++ *pos += size; ++ *count -= size; + } + } + +@@ -978,8 +991,9 @@ __copy_xstate_to_kernel(void *kbuf, const void *data, + */ + int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total) + { +- unsigned int offset, size; + struct xstate_header header; ++ const unsigned off_mxcsr = offsetof(struct fxregs_state, mxcsr); ++ unsigned count = size_total; + int i; + + /* +@@ -995,46 +1009,42 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of + header.xfeatures = xsave->header.xfeatures; + header.xfeatures &= ~XFEATURE_MASK_SUPERVISOR; + ++ if (header.xfeatures & XFEATURE_MASK_FP) ++ copy_part(0, off_mxcsr, ++ &xsave->i387, &kbuf, &offset_start, &count); ++ if (header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM)) ++ copy_part(off_mxcsr, MXCSR_AND_FLAGS_SIZE, ++ &xsave->i387.mxcsr, &kbuf, &offset_start, &count); ++ if (header.xfeatures & XFEATURE_MASK_FP) ++ copy_part(offsetof(struct fxregs_state, st_space), 128, ++ &xsave->i387.st_space, &kbuf, &offset_start, &count); ++ if (header.xfeatures & XFEATURE_MASK_SSE) ++ copy_part(xstate_offsets[XFEATURE_MASK_SSE], 256, ++ &xsave->i387.xmm_space, &kbuf, &offset_start, &count); ++ /* ++ * Fill xsave->i387.sw_reserved value for ptrace frame: ++ */ ++ copy_part(offsetof(struct fxregs_state, sw_reserved), 48, ++ xstate_fx_sw_bytes, &kbuf, &offset_start, &count); + /* + * Copy xregs_state->header: + */ +- offset = offsetof(struct xregs_state, header); +- size = sizeof(header); +- +- __copy_xstate_to_kernel(kbuf, &header, offset, size, size_total); ++ copy_part(offsetof(struct xregs_state, header), sizeof(header), ++ &header, &kbuf, &offset_start, &count); + +- for (i = 0; i < XFEATURE_MAX; i++) { ++ for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { + /* + * Copy only in-use xstates: + */ + if ((header.xfeatures >> i) & 1) { + void *src = __raw_xsave_addr(xsave, i); + +- offset = xstate_offsets[i]; +- size = xstate_sizes[i]; +- +- /* The next component has to fit fully into the output buffer: */ +- if (offset + size > size_total) +- break; +- +- __copy_xstate_to_kernel(kbuf, src, offset, size, size_total); ++ copy_part(xstate_offsets[i], xstate_sizes[i], ++ src, &kbuf, &offset_start, &count); + } + + } +- +- if (xfeatures_mxcsr_quirk(header.xfeatures)) { +- offset = offsetof(struct fxregs_state, mxcsr); +- size = MXCSR_AND_FLAGS_SIZE; +- __copy_xstate_to_kernel(kbuf, &xsave->i387.mxcsr, offset, size, size_total); +- } +- +- /* +- * Fill xsave->i387.sw_reserved value for ptrace frame: +- */ +- offset = offsetof(struct fxregs_state, sw_reserved); +- size = sizeof(xstate_fx_sw_bytes); +- +- __copy_xstate_to_kernel(kbuf, xstate_fx_sw_bytes, offset, size, size_total); ++ fill_gap(size_total, &kbuf, &offset_start, &count); + + return 0; + } +diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c +index 8abeee0dd7bf..fce678f4471e 100644 +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -32,15 +32,15 @@ void io_bitmap_share(struct task_struct *tsk) + set_tsk_thread_flag(tsk, TIF_IO_BITMAP); + } + +-static void task_update_io_bitmap(void) ++static void task_update_io_bitmap(struct task_struct *tsk) + { +- struct thread_struct *t = ¤t->thread; ++ struct thread_struct *t = &tsk->thread; + + if (t->iopl_emul == 3 || t->io_bitmap) { + /* TSS update is handled on exit to user space */ +- set_thread_flag(TIF_IO_BITMAP); ++ set_tsk_thread_flag(tsk, TIF_IO_BITMAP); + } else { +- clear_thread_flag(TIF_IO_BITMAP); ++ clear_tsk_thread_flag(tsk, TIF_IO_BITMAP); + /* Invalidate TSS */ + preempt_disable(); + tss_update_io_bitmap(); +@@ -48,12 +48,12 @@ static void task_update_io_bitmap(void) + } + } + +-void io_bitmap_exit(void) ++void io_bitmap_exit(struct task_struct *tsk) + { +- struct io_bitmap *iobm = current->thread.io_bitmap; ++ struct io_bitmap *iobm = tsk->thread.io_bitmap; + +- current->thread.io_bitmap = NULL; +- task_update_io_bitmap(); ++ tsk->thread.io_bitmap = NULL; ++ task_update_io_bitmap(tsk); + if (iobm && refcount_dec_and_test(&iobm->refcnt)) + kfree(iobm); + } +@@ -101,7 +101,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on) + if (!iobm) + return -ENOMEM; + refcount_set(&iobm->refcnt, 1); +- io_bitmap_exit(); ++ io_bitmap_exit(current); + } + + /* +@@ -133,7 +133,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on) + } + /* All permissions dropped? */ + if (max_long == UINT_MAX) { +- io_bitmap_exit(); ++ io_bitmap_exit(current); + return 0; + } + +@@ -191,7 +191,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) + } + + t->iopl_emul = level; +- task_update_io_bitmap(); ++ task_update_io_bitmap(current); + + return 0; + } +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 3053c85e0e42..9898f672b81d 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -97,7 +97,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) + } + + /* +- * Free current thread data structures etc.. ++ * Free thread data structures etc.. + */ + void exit_thread(struct task_struct *tsk) + { +@@ -105,7 +105,7 @@ void exit_thread(struct task_struct *tsk) + struct fpu *fpu = &t->fpu; + + if (test_thread_flag(TIF_IO_BITMAP)) +- io_bitmap_exit(); ++ io_bitmap_exit(tsk); + + free_vm86(t); + +diff --git a/block/blk-core.c b/block/blk-core.c +index 60dc9552ef8d..92232907605c 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -885,14 +885,11 @@ generic_make_request_checks(struct bio *bio) + } + + /* +- * Non-mq queues do not honor REQ_NOWAIT, so complete a bio +- * with BLK_STS_AGAIN status in order to catch -EAGAIN and +- * to give a chance to the caller to repeat request gracefully. ++ * For a REQ_NOWAIT based request, return -EOPNOTSUPP ++ * if queue is not a request based queue. + */ +- if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q)) { +- status = BLK_STS_AGAIN; +- goto end_io; +- } ++ if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q)) ++ goto not_supported; + + if (should_fail_bio(bio)) + goto end_io; +diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c +index 20877214acff..e3959ff5cb55 100644 +--- a/drivers/clk/qcom/gcc-sm8150.c ++++ b/drivers/clk/qcom/gcc-sm8150.c +@@ -75,8 +75,7 @@ static struct clk_alpha_pll_postdiv gpll0_out_even = { + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_data = &(const struct clk_parent_data){ +- .fw_name = "bi_tcxo", +- .name = "bi_tcxo", ++ .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_trion_pll_postdiv_ops, +diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c +index e001b9bcb6bf..7dc30dd6c8d5 100644 +--- a/drivers/clk/ti/clk-33xx.c ++++ b/drivers/clk/ti/clk-33xx.c +@@ -212,7 +212,7 @@ static const struct omap_clkctrl_reg_data am3_mpu_clkctrl_regs[] __initconst = { + }; + + static const struct omap_clkctrl_reg_data am3_l4_rtc_clkctrl_regs[] __initconst = { +- { AM3_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk_32768_ck" }, ++ { AM3_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk-24mhz-clkctrl:0000:0" }, + { 0 }, + }; + +diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c +index 5cf9b021220b..fdaed234ae92 100644 +--- a/drivers/crypto/chelsio/chtls/chtls_io.c ++++ b/drivers/crypto/chelsio/chtls/chtls_io.c +@@ -682,7 +682,7 @@ int chtls_push_frames(struct chtls_sock *csk, int comp) + make_tx_data_wr(sk, skb, immdlen, len, + credits_needed, completion); + tp->snd_nxt += len; +- tp->lsndtime = tcp_time_stamp(tp); ++ tp->lsndtime = tcp_jiffies32; + if (completion) + ULP_SKB_CB(skb)->flags &= ~ULPCB_FLAG_NEED_HDR; + } else { +diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c +index baee8c3f06ad..cf3687a7925f 100644 +--- a/drivers/gpio/gpio-bcm-kona.c ++++ b/drivers/gpio/gpio-bcm-kona.c +@@ -625,7 +625,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) + + kona_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(kona_gpio->reg_base)) { +- ret = -ENXIO; ++ ret = PTR_ERR(kona_gpio->reg_base); + goto err_irq_domain; + } + +diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c +index da1ef0b1c291..b1accfba017d 100644 +--- a/drivers/gpio/gpio-exar.c ++++ b/drivers/gpio/gpio-exar.c +@@ -148,8 +148,10 @@ static int gpio_exar_probe(struct platform_device *pdev) + mutex_init(&exar_gpio->lock); + + index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL); +- if (index < 0) +- goto err_destroy; ++ if (index < 0) { ++ ret = index; ++ goto err_mutex_destroy; ++ } + + sprintf(exar_gpio->name, "exar_gpio%d", index); + exar_gpio->gpio_chip.label = exar_gpio->name; +@@ -176,6 +178,7 @@ static int gpio_exar_probe(struct platform_device *pdev) + + err_destroy: + ida_simple_remove(&ida_index, index); ++err_mutex_destroy: + mutex_destroy(&exar_gpio->lock); + return ret; + } +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index d2b999c7987f..f0c5433a327f 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -782,6 +782,15 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + "marvell,armada-370-gpio")) + return 0; + ++ /* ++ * There are only two sets of PWM configuration registers for ++ * all the GPIO lines on those SoCs which this driver reserves ++ * for the first two GPIO chips. So if the resource is missing ++ * we can't treat it as an error. ++ */ ++ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm")) ++ return 0; ++ + if (IS_ERR(mvchip->clk)) + return PTR_ERR(mvchip->clk); + +@@ -804,12 +813,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + mvchip->mvpwm = mvpwm; + mvpwm->mvchip = mvchip; + +- /* +- * There are only two sets of PWM configuration registers for +- * all the GPIO lines on those SoCs which this driver reserves +- * for the first two GPIO chips. So if the resource is missing +- * we can't treat it as an error. +- */ + mvpwm->membase = devm_platform_ioremap_resource_byname(pdev, "pwm"); + if (IS_ERR(mvpwm->membase)) + return PTR_ERR(mvpwm->membase); +diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c +index 9888b62f37af..432c487f77b4 100644 +--- a/drivers/gpio/gpio-pxa.c ++++ b/drivers/gpio/gpio-pxa.c +@@ -663,8 +663,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) + pchip->irq1 = irq1; + + gpio_reg_base = devm_platform_ioremap_resource(pdev, 0); +- if (!gpio_reg_base) +- return -EINVAL; ++ if (IS_ERR(gpio_reg_base)) ++ return PTR_ERR(gpio_reg_base); + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { +diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c +index acb99eff9939..86568154cdb3 100644 +--- a/drivers/gpio/gpio-tegra.c ++++ b/drivers/gpio/gpio-tegra.c +@@ -368,6 +368,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) + struct tegra_gpio_info *tgi = bank->tgi; + unsigned int gpio = d->hwirq; + ++ tegra_gpio_irq_mask(d); + gpiochip_unlock_as_irq(&tgi->gc, gpio); + } + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 00fb91feba70..2f350e3df965 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -4025,7 +4025,9 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) + } + } + +- if (test_bit(FLAG_IS_OUT, &desc->flags)) { ++ /* To be valid for IRQ the line needs to be input or open drain */ ++ if (test_bit(FLAG_IS_OUT, &desc->flags) && ++ !test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { + chip_err(chip, + "%s: tried to flag a GPIO set as output for IRQ\n", + __func__); +@@ -4088,7 +4090,12 @@ void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset) + + if (!IS_ERR(desc) && + !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) { +- WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags)); ++ /* ++ * We must not be output when using IRQ UNLESS we are ++ * open drain. ++ */ ++ WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags) && ++ !test_bit(FLAG_OPEN_DRAIN, &desc->flags)); + set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags); + } + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index fa8ac9d19a7a..6326c1792270 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1304,7 +1304,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( + } + + /* Free the BO*/ +- amdgpu_bo_unref(&mem->bo); ++ drm_gem_object_put_unlocked(&mem->bo->tbo.base); + mutex_destroy(&mem->lock); + kfree(mem); + +@@ -1647,7 +1647,8 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, + ALLOC_MEM_FLAGS_VRAM : ALLOC_MEM_FLAGS_GTT) | + ALLOC_MEM_FLAGS_WRITABLE | ALLOC_MEM_FLAGS_EXECUTABLE; + +- (*mem)->bo = amdgpu_bo_ref(bo); ++ drm_gem_object_get(&bo->tbo.base); ++ (*mem)->bo = bo; + (*mem)->va = va; + (*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ? + AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT; +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index 02702597ddeb..012df3d574bf 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -4241,11 +4241,7 @@ static int gfx_v10_0_set_powergating_state(void *handle, + switch (adev->asic_type) { + case CHIP_NAVI10: + case CHIP_NAVI14: +- if (!enable) { +- amdgpu_gfx_off_ctrl(adev, false); +- cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work); +- } else +- amdgpu_gfx_off_ctrl(adev, true); ++ amdgpu_gfx_off_ctrl(adev, enable); + break; + default: + break; +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +index 906648fca9ef..914dbd901b98 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -4734,10 +4734,9 @@ static int gfx_v9_0_set_powergating_state(void *handle, + switch (adev->asic_type) { + case CHIP_RAVEN: + case CHIP_RENOIR: +- if (!enable) { ++ if (!enable) + amdgpu_gfx_off_ctrl(adev, false); +- cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work); +- } ++ + if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) { + gfx_v9_0_enable_sck_slow_down_on_power_up(adev, true); + gfx_v9_0_enable_sck_slow_down_on_power_down(adev, true); +@@ -4761,12 +4760,7 @@ static int gfx_v9_0_set_powergating_state(void *handle, + amdgpu_gfx_off_ctrl(adev, true); + break; + case CHIP_VEGA12: +- if (!enable) { +- amdgpu_gfx_off_ctrl(adev, false); +- cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work); +- } else { +- amdgpu_gfx_off_ctrl(adev, true); +- } ++ amdgpu_gfx_off_ctrl(adev, enable); + break; + default: + break; +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 0cd11d3d4cf4..8e7cffe10cc5 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7746,13 +7746,6 @@ static int dm_update_plane_state(struct dc *dc, + return -EINVAL; + } + +- if (new_plane_state->crtc_x <= -new_acrtc->max_cursor_width || +- new_plane_state->crtc_y <= -new_acrtc->max_cursor_height) { +- DRM_DEBUG_ATOMIC("Bad cursor position %d, %d\n", +- new_plane_state->crtc_x, new_plane_state->crtc_y); +- return -EINVAL; +- } +- + return 0; + } + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +index 3abeff7722e3..e80371542622 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +@@ -316,15 +316,15 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) + struct mod_hdcp_display *display = &hdcp_work[link_index].display; + struct mod_hdcp_link *link = &hdcp_work[link_index].link; + +- memset(display, 0, sizeof(*display)); +- memset(link, 0, sizeof(*link)); +- +- display->index = aconnector->base.index; +- + if (config->dpms_off) { + hdcp_remove_display(hdcp_work, link_index, aconnector); + return; + } ++ ++ memset(display, 0, sizeof(*display)); ++ memset(link, 0, sizeof(*link)); ++ ++ display->index = aconnector->base.index; + display->state = MOD_HDCP_DISPLAY_ACTIVE; + + if (aconnector->dc_sink != NULL) +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index b3987124183a..32a07665863f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -763,6 +763,29 @@ static bool disable_all_writeback_pipes_for_stream( + return true; + } + ++void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream, bool lock) ++{ ++ int i = 0; ++ ++ /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */ ++ if (dc->hwss.interdependent_update_lock) ++ dc->hwss.interdependent_update_lock(dc, context, lock); ++ else { ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; ++ ++ // Copied conditions that were previously in dce110_apply_ctx_for_surface ++ if (stream == pipe_ctx->stream) { ++ if (!pipe_ctx->top_pipe && ++ (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) ++ dc->hwss.pipe_control_lock(dc, pipe_ctx, lock); ++ break; ++ } ++ } ++ } ++} ++ + static void disable_dangling_plane(struct dc *dc, struct dc_state *context) + { + int i, j; +@@ -788,11 +811,20 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) + if (should_disable && old_stream) { + dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); + disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); +- if (dc->hwss.apply_ctx_for_surface) ++ ++ if (dc->hwss.apply_ctx_for_surface) { ++ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true); + dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); ++ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false); ++ dc->hwss.post_unlock_program_front_end(dc, dangling_context); ++ } ++ if (dc->hwss.program_front_end_for_ctx) { ++ dc->hwss.interdependent_update_lock(dc, dc->current_state, true); ++ dc->hwss.program_front_end_for_ctx(dc, dangling_context); ++ dc->hwss.interdependent_update_lock(dc, dc->current_state, false); ++ dc->hwss.post_unlock_program_front_end(dc, dangling_context); ++ } + } +- if (dc->hwss.program_front_end_for_ctx) +- dc->hwss.program_front_end_for_ctx(dc, dangling_context); + } + + current_ctx = dc->current_state; +@@ -1211,16 +1243,19 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + /* re-program planes for existing stream, in case we need to + * free up plane resource for later use + */ +- if (dc->hwss.apply_ctx_for_surface) ++ if (dc->hwss.apply_ctx_for_surface) { + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i]->mode_changed) + continue; +- ++ apply_ctx_interdependent_lock(dc, context, context->streams[i], true); + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); /* use new pipe config in new context */ ++ apply_ctx_interdependent_lock(dc, context, context->streams[i], false); ++ dc->hwss.post_unlock_program_front_end(dc, context); + } ++ } + + /* Program hardware */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { +@@ -1239,19 +1274,27 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + } + + /* Program all planes within new context*/ +- if (dc->hwss.program_front_end_for_ctx) ++ if (dc->hwss.program_front_end_for_ctx) { ++ dc->hwss.interdependent_update_lock(dc, context, true); + dc->hwss.program_front_end_for_ctx(dc, context); ++ dc->hwss.interdependent_update_lock(dc, context, false); ++ dc->hwss.post_unlock_program_front_end(dc, context); ++ } + for (i = 0; i < context->stream_count; i++) { + const struct dc_link *link = context->streams[i]->link; + + if (!context->streams[i]->mode_changed) + continue; + +- if (dc->hwss.apply_ctx_for_surface) ++ if (dc->hwss.apply_ctx_for_surface) { ++ apply_ctx_interdependent_lock(dc, context, context->streams[i], true); + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); ++ apply_ctx_interdependent_lock(dc, context, context->streams[i], false); ++ dc->hwss.post_unlock_program_front_end(dc, context); ++ } + + /* + * enable stereo +@@ -1735,14 +1778,15 @@ static enum surface_update_type check_update_surfaces_for_stream( + + if (stream_update->wb_update) + su_flags->bits.wb_update = 1; ++ ++ if (stream_update->dsc_config) ++ su_flags->bits.dsc_changed = 1; ++ + if (su_flags->raw != 0) + overall_type = UPDATE_TYPE_FULL; + + if (stream_update->output_csc_transform || stream_update->output_color_space) + su_flags->bits.out_csc = 1; +- +- if (stream_update->dsc_config) +- overall_type = UPDATE_TYPE_FULL; + } + + for (i = 0 ; i < surface_count; i++) { +@@ -1777,8 +1821,11 @@ enum surface_update_type dc_check_update_surfaces_for_stream( + + type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status); + if (type == UPDATE_TYPE_FULL) { +- if (stream_update) ++ if (stream_update) { ++ uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed; + stream_update->stream->update_flags.raw = 0xFFFFFFFF; ++ stream_update->stream->update_flags.bits.dsc_changed = dsc_changed; ++ } + for (i = 0; i < surface_count; i++) + updates[i].surface->update_flags.raw = 0xFFFFFFFF; + } +@@ -2094,18 +2141,14 @@ static void commit_planes_do_stream_update(struct dc *dc, + } + } + +- if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { +- dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true); +- dp_update_dsc_config(pipe_ctx); +- dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false); +- } + /* Full fe update*/ + if (update_type == UPDATE_TYPE_FAST) + continue; + +- if (stream_update->dpms_off) { +- dc->hwss.pipe_control_lock(dc, pipe_ctx, true); ++ if (stream_update->dsc_config) ++ dp_update_dsc_config(pipe_ctx); + ++ if (stream_update->dpms_off) { + if (*stream_update->dpms_off) { + core_link_disable_stream(pipe_ctx); + /* for dpms, keep acquired resources*/ +@@ -2119,8 +2162,6 @@ static void commit_planes_do_stream_update(struct dc *dc, + + core_link_enable_stream(dc->current_state, pipe_ctx); + } +- +- dc->hwss.pipe_control_lock(dc, pipe_ctx, false); + } + + if (stream_update->abm_level && pipe_ctx->stream_res.abm) { +@@ -2176,6 +2217,27 @@ static void commit_planes_for_stream(struct dc *dc, + context_clock_trace(dc, context); + } + ++ for (j = 0; j < dc->res_pool->pipe_count; j++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; ++ ++ if (!pipe_ctx->top_pipe && ++ !pipe_ctx->prev_odm_pipe && ++ pipe_ctx->stream && ++ pipe_ctx->stream == stream) { ++ top_pipe_to_program = pipe_ctx; ++ } ++ } ++ ++ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) ++ dc->hwss.interdependent_update_lock(dc, context, true); ++ else ++ /* Lock the top pipe while updating plane addrs, since freesync requires ++ * plane addr update event triggers to be synchronized. ++ * top_pipe_to_program is expected to never be NULL ++ */ ++ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); ++ ++ + // Stream updates + if (stream_update) + commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); +@@ -2190,6 +2252,12 @@ static void commit_planes_for_stream(struct dc *dc, + if (dc->hwss.program_front_end_for_ctx) + dc->hwss.program_front_end_for_ctx(dc, context); + ++ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) ++ dc->hwss.interdependent_update_lock(dc, context, false); ++ else ++ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); ++ ++ dc->hwss.post_unlock_program_front_end(dc, context); + return; + } + +@@ -2225,8 +2293,6 @@ static void commit_planes_for_stream(struct dc *dc, + pipe_ctx->stream == stream) { + struct dc_stream_status *stream_status = NULL; + +- top_pipe_to_program = pipe_ctx; +- + if (!pipe_ctx->plane_state) + continue; + +@@ -2271,12 +2337,6 @@ static void commit_planes_for_stream(struct dc *dc, + + // Update Type FAST, Surface updates + if (update_type == UPDATE_TYPE_FAST) { +- /* Lock the top pipe while updating plane addrs, since freesync requires +- * plane addr update event triggers to be synchronized. +- * top_pipe_to_program is expected to never be NULL +- */ +- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); +- + if (dc->hwss.set_flip_control_gsl) + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *plane_state = srf_updates[i].surface; +@@ -2318,9 +2378,15 @@ static void commit_planes_for_stream(struct dc *dc, + dc->hwss.update_plane_addr(dc, pipe_ctx); + } + } ++ } + ++ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) ++ dc->hwss.interdependent_update_lock(dc, context, false); ++ else + dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); +- } ++ ++ if (update_type != UPDATE_TYPE_FAST) ++ dc->hwss.post_unlock_program_front_end(dc, context); + + // Fire manual trigger only when bottom plane is flipped + for (j = 0; j < dc->res_pool->pipe_count; j++) { +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +index 8c20e9e907b2..4f0e7203dba4 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +@@ -231,34 +231,6 @@ struct dc_stream_status *dc_stream_get_status( + return dc_stream_get_status_from_state(dc->current_state, stream); + } + +-static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc) +-{ +-#if defined(CONFIG_DRM_AMD_DC_DCN) +- unsigned int vupdate_line; +- unsigned int lines_to_vupdate, us_to_vupdate, vpos, nvpos; +- struct dc_stream_state *stream = pipe_ctx->stream; +- unsigned int us_per_line; +- +- if (!dc->hwss.get_vupdate_offset_from_vsync) +- return; +- +- vupdate_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); +- if (!dc_stream_get_crtc_position(dc, &stream, 1, &vpos, &nvpos)) +- return; +- +- if (vpos >= vupdate_line) +- return; +- +- us_per_line = +- stream->timing.h_total * 10000 / stream->timing.pix_clk_100hz; +- lines_to_vupdate = vupdate_line - vpos; +- us_to_vupdate = lines_to_vupdate * us_per_line; +- +- /* 70 us is a conservative estimate of cursor update time*/ +- if (us_to_vupdate < 70) +- udelay(us_to_vupdate); +-#endif +-} + + /** + * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address +@@ -298,9 +270,7 @@ bool dc_stream_set_cursor_attributes( + + if (!pipe_to_program) { + pipe_to_program = pipe_ctx; +- +- delay_cursor_until_vupdate(pipe_ctx, dc); +- dc->hwss.pipe_control_lock(dc, pipe_to_program, true); ++ dc->hwss.cursor_lock(dc, pipe_to_program, true); + } + + dc->hwss.set_cursor_attribute(pipe_ctx); +@@ -309,7 +279,7 @@ bool dc_stream_set_cursor_attributes( + } + + if (pipe_to_program) +- dc->hwss.pipe_control_lock(dc, pipe_to_program, false); ++ dc->hwss.cursor_lock(dc, pipe_to_program, false); + + return true; + } +@@ -349,16 +319,14 @@ bool dc_stream_set_cursor_position( + + if (!pipe_to_program) { + pipe_to_program = pipe_ctx; +- +- delay_cursor_until_vupdate(pipe_ctx, dc); +- dc->hwss.pipe_control_lock(dc, pipe_to_program, true); ++ dc->hwss.cursor_lock(dc, pipe_to_program, true); + } + + dc->hwss.set_cursor_position(pipe_ctx); + } + + if (pipe_to_program) +- dc->hwss.pipe_control_lock(dc, pipe_to_program, false); ++ dc->hwss.cursor_lock(dc, pipe_to_program, false); + + return true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h +index 92096de79dec..a5c7ef47b8d3 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h +@@ -118,6 +118,7 @@ union stream_update_flags { + uint32_t dpms_off:1; + uint32_t gamut_remap:1; + uint32_t wb_update:1; ++ uint32_t dsc_changed : 1; + } bits; + + uint32_t raw; +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +index 5b689273ff44..454a123b92fc 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +@@ -2574,17 +2574,6 @@ static void dce110_apply_ctx_for_surface( + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +- struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; +- +- if (stream == pipe_ctx->stream) { +- if (!pipe_ctx->top_pipe && +- (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) +- dc->hwss.pipe_control_lock(dc, pipe_ctx, true); +- } +- } +- + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + +@@ -2607,20 +2596,16 @@ static void dce110_apply_ctx_for_surface( + + } + +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +- struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; +- +- if ((stream == pipe_ctx->stream) && +- (!pipe_ctx->top_pipe) && +- (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) +- dc->hwss.pipe_control_lock(dc, pipe_ctx, false); +- } +- + if (dc->fbc_compressor) + enable_fbc(dc, context); + } + ++static void dce110_post_unlock_program_front_end( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++} ++ + static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) + { + struct dce_hwseq *hws = dc->hwseq; +@@ -2722,6 +2707,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .init_hw = init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = dce110_apply_ctx_for_surface, ++ .post_unlock_program_front_end = dce110_post_unlock_program_front_end, + .update_plane_addr = update_plane_addr, + .update_pending_status = dce110_update_pending_status, + .enable_accelerated_mode = dce110_enable_accelerated_mode, +@@ -2736,6 +2722,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dce110_power_down_fe, + .pipe_control_lock = dce_pipe_control_lock, ++ .interdependent_update_lock = NULL, ++ .cursor_lock = dce_pipe_control_lock, + .prepare_bandwidth = dce110_prepare_bandwidth, + .optimize_bandwidth = dce110_optimize_bandwidth, + .set_drr = set_drr, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index 1008ac8a0f2a..0c987b5d68e2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -82,7 +82,7 @@ void print_microsec(struct dc_context *dc_ctx, + us_x10 % frac); + } + +-static void dcn10_lock_all_pipes(struct dc *dc, ++void dcn10_lock_all_pipes(struct dc *dc, + struct dc_state *context, + bool lock) + { +@@ -93,6 +93,7 @@ static void dcn10_lock_all_pipes(struct dc *dc, + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + tg = pipe_ctx->stream_res.tg; ++ + /* + * Only lock the top pipe's tg to prevent redundant + * (un)locking. Also skip if pipe is disabled. +@@ -103,9 +104,9 @@ static void dcn10_lock_all_pipes(struct dc *dc, + continue; + + if (lock) +- tg->funcs->lock(tg); ++ dc->hwss.pipe_control_lock(dc, pipe_ctx, true); + else +- tg->funcs->unlock(tg); ++ dc->hwss.pipe_control_lock(dc, pipe_ctx, false); + } + } + +@@ -1576,7 +1577,7 @@ void dcn10_pipe_control_lock( + /* use TG master update lock to lock everything on the TG + * therefore only top pipe need to lock + */ +- if (pipe->top_pipe) ++ if (!pipe || pipe->top_pipe) + return; + + if (dc->debug.sanity_checks) +@@ -1591,6 +1592,85 @@ void dcn10_pipe_control_lock( + hws->funcs.verify_allow_pstate_change_high(dc); + } + ++/** ++ * delay_cursor_until_vupdate() - Delay cursor update if too close to VUPDATE. ++ * ++ * Software keepout workaround to prevent cursor update locking from stalling ++ * out cursor updates indefinitely or from old values from being retained in ++ * the case where the viewport changes in the same frame as the cursor. ++ * ++ * The idea is to calculate the remaining time from VPOS to VUPDATE. If it's ++ * too close to VUPDATE, then stall out until VUPDATE finishes. ++ * ++ * TODO: Optimize cursor programming to be once per frame before VUPDATE ++ * to avoid the need for this workaround. ++ */ ++static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx) ++{ ++ struct dc_stream_state *stream = pipe_ctx->stream; ++ struct crtc_position position; ++ uint32_t vupdate_start, vupdate_end; ++ unsigned int lines_to_vupdate, us_to_vupdate, vpos; ++ unsigned int us_per_line, us_vupdate; ++ ++ if (!dc->hwss.calc_vupdate_position || !dc->hwss.get_position) ++ return; ++ ++ if (!pipe_ctx->stream_res.stream_enc || !pipe_ctx->stream_res.tg) ++ return; ++ ++ dc->hwss.calc_vupdate_position(dc, pipe_ctx, &vupdate_start, ++ &vupdate_end); ++ ++ dc->hwss.get_position(&pipe_ctx, 1, &position); ++ vpos = position.vertical_count; ++ ++ /* Avoid wraparound calculation issues */ ++ vupdate_start += stream->timing.v_total; ++ vupdate_end += stream->timing.v_total; ++ vpos += stream->timing.v_total; ++ ++ if (vpos <= vupdate_start) { ++ /* VPOS is in VACTIVE or back porch. */ ++ lines_to_vupdate = vupdate_start - vpos; ++ } else if (vpos > vupdate_end) { ++ /* VPOS is in the front porch. */ ++ return; ++ } else { ++ /* VPOS is in VUPDATE. */ ++ lines_to_vupdate = 0; ++ } ++ ++ /* Calculate time until VUPDATE in microseconds. */ ++ us_per_line = ++ stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz; ++ us_to_vupdate = lines_to_vupdate * us_per_line; ++ ++ /* 70 us is a conservative estimate of cursor update time*/ ++ if (us_to_vupdate > 70) ++ return; ++ ++ /* Stall out until the cursor update completes. */ ++ if (vupdate_end < vupdate_start) ++ vupdate_end += stream->timing.v_total; ++ us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line; ++ udelay(us_to_vupdate + us_vupdate); ++} ++ ++void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock) ++{ ++ /* cursor lock is per MPCC tree, so only need to lock one pipe per stream */ ++ if (!pipe || pipe->top_pipe) ++ return; ++ ++ /* Prevent cursor lock from stalling out cursor updates. */ ++ if (lock) ++ delay_cursor_until_vupdate(dc, pipe); ++ ++ dc->res_pool->mpc->funcs->cursor_lock(dc->res_pool->mpc, ++ pipe->stream_res.opp->inst, lock); ++} ++ + static bool wait_for_reset_trigger_to_occur( + struct dc_context *dc_ctx, + struct timing_generator *tg) +@@ -2512,7 +2592,6 @@ void dcn10_apply_ctx_for_surface( + int i; + struct timing_generator *tg; + uint32_t underflow_check_delay_us; +- bool removed_pipe[4] = { false }; + bool interdependent_update = false; + struct pipe_ctx *top_pipe_to_program = + dcn10_find_top_pipe_for_stream(dc, context, stream); +@@ -2531,11 +2610,6 @@ void dcn10_apply_ctx_for_surface( + if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) + ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); + +- if (interdependent_update) +- dcn10_lock_all_pipes(dc, context, true); +- else +- dcn10_pipe_control_lock(dc, top_pipe_to_program, true); +- + if (underflow_check_delay_us != 0xFFFFFFFF) + udelay(underflow_check_delay_us); + +@@ -2552,18 +2626,8 @@ void dcn10_apply_ctx_for_surface( + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; +- /* +- * Powergate reused pipes that are not powergated +- * fairly hacky right now, using opp_id as indicator +- * TODO: After move dc_post to dc_update, this will +- * be removed. +- */ +- if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { +- if (old_pipe_ctx->stream_res.tg == tg && +- old_pipe_ctx->plane_res.hubp && +- old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) +- dc->hwss.disable_plane(dc, old_pipe_ctx); +- } ++ ++ pipe_ctx->update_flags.raw = 0; + + if ((!pipe_ctx->plane_state || + pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && +@@ -2571,7 +2635,7 @@ void dcn10_apply_ctx_for_surface( + old_pipe_ctx->stream_res.tg == tg) { + + hws->funcs.plane_atomic_disconnect(dc, old_pipe_ctx); +- removed_pipe[i] = true; ++ pipe_ctx->update_flags.bits.disable = 1; + + DC_LOG_DC("Reset mpcc for pipe %d\n", + old_pipe_ctx->pipe_idx); +@@ -2597,21 +2661,41 @@ void dcn10_apply_ctx_for_surface( + &pipe_ctx->dlg_regs, + &pipe_ctx->ttu_regs); + } ++} + +- if (interdependent_update) +- dcn10_lock_all_pipes(dc, context, false); +- else +- dcn10_pipe_control_lock(dc, top_pipe_to_program, false); ++void dcn10_post_unlock_program_front_end( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++ int i, j; + +- if (num_planes == 0) +- false_optc_underflow_wa(dc, stream, tg); ++ DC_LOGGER_INIT(dc->ctx->logger); ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ ++ if (!pipe_ctx->top_pipe && ++ !pipe_ctx->prev_odm_pipe && ++ pipe_ctx->stream) { ++ struct dc_stream_status *stream_status = NULL; ++ struct timing_generator *tg = pipe_ctx->stream_res.tg; ++ ++ for (j = 0; j < context->stream_count; j++) { ++ if (pipe_ctx->stream == context->streams[j]) ++ stream_status = &context->stream_status[j]; ++ } ++ ++ if (context->stream_status[i].plane_count == 0) ++ false_optc_underflow_wa(dc, pipe_ctx->stream, tg); ++ } ++ } + + for (i = 0; i < dc->res_pool->pipe_count; i++) +- if (removed_pipe[i]) ++ if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) + dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + + for (i = 0; i < dc->res_pool->pipe_count; i++) +- if (removed_pipe[i]) { ++ if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { + dc->hwss.optimize_bandwidth(dc, context); + break; + } +@@ -3127,7 +3211,7 @@ int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx) + return vertical_line_start; + } + +-static void dcn10_calc_vupdate_position( ++void dcn10_calc_vupdate_position( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + uint32_t *start_line, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +index 4d20f6586bb5..42b6e016d71e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +@@ -34,6 +34,11 @@ struct dc; + void dcn10_hw_sequencer_construct(struct dc *dc); + + int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx); ++void dcn10_calc_vupdate_position( ++ struct dc *dc, ++ struct pipe_ctx *pipe_ctx, ++ uint32_t *start_line, ++ uint32_t *end_line); + void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx); + enum dc_status dcn10_enable_stream_timing( + struct pipe_ctx *pipe_ctx, +@@ -49,6 +54,7 @@ void dcn10_pipe_control_lock( + struct dc *dc, + struct pipe_ctx *pipe, + bool lock); ++void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock); + void dcn10_blank_pixel_data( + struct dc *dc, + struct pipe_ctx *pipe_ctx, +@@ -70,11 +76,18 @@ void dcn10_reset_hw_ctx_wrap( + struct dc *dc, + struct dc_state *context); + void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); ++void dcn10_lock_all_pipes( ++ struct dc *dc, ++ struct dc_state *context, ++ bool lock); + void dcn10_apply_ctx_for_surface( + struct dc *dc, + const struct dc_stream_state *stream, + int num_planes, + struct dc_state *context); ++void dcn10_post_unlock_program_front_end( ++ struct dc *dc, ++ struct dc_state *context); + void dcn10_hubp_pg_control( + struct dce_hwseq *hws, + unsigned int hubp_inst, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +index e7e5352ec424..0900c861204f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +@@ -32,6 +32,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .init_hw = dcn10_init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, ++ .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, + .update_plane_addr = dcn10_update_plane_addr, + .update_dchub = dcn10_update_dchub, + .update_pending_status = dcn10_update_pending_status, +@@ -49,6 +50,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dcn10_disable_plane, + .pipe_control_lock = dcn10_pipe_control_lock, ++ .cursor_lock = dcn10_cursor_lock, ++ .interdependent_update_lock = dcn10_lock_all_pipes, + .prepare_bandwidth = dcn10_prepare_bandwidth, + .optimize_bandwidth = dcn10_optimize_bandwidth, + .set_drr = dcn10_set_drr, +@@ -69,6 +72,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .set_clock = dcn10_set_clock, + .get_clock = dcn10_get_clock, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, ++ .calc_vupdate_position = dcn10_calc_vupdate_position, + }; + + static const struct hwseq_private_funcs dcn10_private_funcs = { +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +index 04f863499cfb..3fcd408e9103 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +@@ -223,6 +223,9 @@ struct mpcc *mpc1_insert_plane( + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); + ++ /* Configure VUPDATE lock set for this MPCC to map to the OPP */ ++ REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id); ++ + /* update mpc tree mux setting */ + if (tree->opp_list == insert_above_mpcc) { + /* insert the toppest mpcc */ +@@ -318,6 +321,7 @@ void mpc1_remove_mpcc( + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); ++ REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); + + /* mark this mpcc as not in use */ + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); +@@ -328,6 +332,7 @@ void mpc1_remove_mpcc( + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); ++ REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); + } + } + +@@ -361,6 +366,7 @@ void mpc1_mpc_init(struct mpc *mpc) + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); ++ REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); + + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); + } +@@ -381,6 +387,7 @@ void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id) + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); ++ REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); + + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); + +@@ -453,6 +460,13 @@ void mpc1_read_mpcc_state( + MPCC_BUSY, &s->busy); + } + ++void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock) ++{ ++ struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); ++ ++ REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0); ++} ++ + static const struct mpc_funcs dcn10_mpc_funcs = { + .read_mpcc_state = mpc1_read_mpcc_state, + .insert_plane = mpc1_insert_plane, +@@ -464,6 +478,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = { + .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, + .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, + .update_blending = mpc1_update_blending, ++ .cursor_lock = mpc1_cursor_lock, + .set_denorm = NULL, + .set_denorm_clamp = NULL, + .set_output_csc = NULL, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +index 962a68e322ee..66a4719c22a0 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +@@ -39,11 +39,12 @@ + SRII(MPCC_BG_G_Y, MPCC, inst),\ + SRII(MPCC_BG_R_CR, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ +- SRII(MPCC_BG_B_CB, MPCC, inst),\ +- SRII(MPCC_SM_CONTROL, MPCC, inst) ++ SRII(MPCC_SM_CONTROL, MPCC, inst),\ ++ SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) + + #define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ +- SRII(MUX, MPC_OUT, inst) ++ SRII(MUX, MPC_OUT, inst),\ ++ VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) + + #define MPC_COMMON_REG_VARIABLE_LIST \ + uint32_t MPCC_TOP_SEL[MAX_MPCC]; \ +@@ -55,7 +56,9 @@ + uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ + uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ + uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \ +- uint32_t MUX[MAX_OPP]; ++ uint32_t MUX[MAX_OPP]; \ ++ uint32_t MPCC_UPDATE_LOCK_SEL[MAX_MPCC]; \ ++ uint32_t CUR[MAX_OPP]; + + #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ +@@ -78,7 +81,8 @@ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\ +- SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) ++ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ ++ SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh) + + #define MPC_REG_FIELD_LIST(type) \ + type MPCC_TOP_SEL;\ +@@ -101,7 +105,9 @@ + type MPCC_SM_FIELD_ALT;\ + type MPCC_SM_FORCE_NEXT_FRAME_POL;\ + type MPCC_SM_FORCE_NEXT_TOP_POL;\ +- type MPC_OUT_MUX; ++ type MPC_OUT_MUX;\ ++ type MPCC_UPDATE_LOCK_SEL;\ ++ type CUR_VUPDATE_LOCK_SET; + + struct dcn_mpc_registers { + MPC_COMMON_REG_VARIABLE_LIST +@@ -192,4 +198,6 @@ void mpc1_read_mpcc_state( + int mpcc_inst, + struct mpcc_state *s); + ++void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock); ++ + #endif +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +index 3b71898e859e..e3c4c06ac191 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +@@ -181,6 +181,14 @@ enum dcn10_clk_src_array_id { + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + ++#define VUPDATE_SRII(reg_name, block, id)\ ++ .reg_name[id] = BASE(mm ## reg_name ## 0 ## _ ## block ## id ## _BASE_IDX) + \ ++ mm ## reg_name ## 0 ## _ ## block ## id ++ ++/* set field/register/bitfield name */ ++#define SFRB(field_name, reg_name, bitfield, post_fix)\ ++ .field_name = reg_name ## __ ## bitfield ## post_fix ++ + /* NBIO */ + #define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg +@@ -419,11 +427,13 @@ static const struct dcn_mpc_registers mpc_regs = { + }; + + static const struct dcn_mpc_shift mpc_shift = { +- MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) ++ MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT),\ ++ SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, __SHIFT) + }; + + static const struct dcn_mpc_mask mpc_mask = { +- MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), ++ MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),\ ++ SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, _MASK) + }; + + #define tg_regs(id)\ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +index ad422e00f9fe..611dac544bfe 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +@@ -1088,40 +1088,18 @@ void dcn20_enable_plane( + // } + } + +- +-void dcn20_pipe_control_lock_global( +- struct dc *dc, +- struct pipe_ctx *pipe, +- bool lock) +-{ +- if (lock) { +- pipe->stream_res.tg->funcs->lock_doublebuffer_enable( +- pipe->stream_res.tg); +- pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); +- } else { +- pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); +- pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, +- CRTC_STATE_VACTIVE); +- pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, +- CRTC_STATE_VBLANK); +- pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, +- CRTC_STATE_VACTIVE); +- pipe->stream_res.tg->funcs->lock_doublebuffer_disable( +- pipe->stream_res.tg); +- } +-} +- + void dcn20_pipe_control_lock( + struct dc *dc, + struct pipe_ctx *pipe, + bool lock) + { + bool flip_immediate = false; ++ bool dig_update_required = false; + + /* use TG master update lock to lock everything on the TG + * therefore only top pipe need to lock + */ +- if (pipe->top_pipe) ++ if (!pipe || pipe->top_pipe) + return; + + if (pipe->plane_state != NULL) +@@ -1154,6 +1132,19 @@ void dcn20_pipe_control_lock( + (!flip_immediate && pipe->stream_res.gsl_group > 0)) + dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate); + ++ if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed) ++ dig_update_required = true; ++ ++ /* Need double buffer lock mode in order to synchronize front end pipe ++ * updates with dig updates. ++ */ ++ if (dig_update_required) { ++ if (lock) { ++ pipe->stream_res.tg->funcs->lock_doublebuffer_enable( ++ pipe->stream_res.tg); ++ } ++ } ++ + if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { + if (lock) + pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); +@@ -1165,6 +1156,19 @@ void dcn20_pipe_control_lock( + else + pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); + } ++ ++ if (dig_update_required) { ++ if (!lock) { ++ pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, ++ CRTC_STATE_VACTIVE); ++ pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, ++ CRTC_STATE_VBLANK); ++ pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, ++ CRTC_STATE_VACTIVE); ++ pipe->stream_res.tg->funcs->lock_doublebuffer_disable( ++ pipe->stream_res.tg); ++ } ++ } + } + + static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) +@@ -1536,27 +1540,28 @@ static void dcn20_program_pipe( + } + } + +-static bool does_pipe_need_lock(struct pipe_ctx *pipe) +-{ +- if ((pipe->plane_state && pipe->plane_state->update_flags.raw) +- || pipe->update_flags.raw) +- return true; +- if (pipe->bottom_pipe) +- return does_pipe_need_lock(pipe->bottom_pipe); +- +- return false; +-} +- + void dcn20_program_front_end_for_ctx( + struct dc *dc, + struct dc_state *context) + { +- const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; + int i; + struct dce_hwseq *hws = dc->hwseq; +- bool pipe_locked[MAX_PIPES] = {false}; + DC_LOGGER_INIT(dc->ctx->logger); + ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ ++ if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { ++ ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); ++ if (dc->hwss.program_triplebuffer != NULL && ++ !dc->debug.disable_tri_buf) { ++ /*turn off triple buffer for full update*/ ++ dc->hwss.program_triplebuffer( ++ dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); ++ } ++ } ++ } ++ + /* Carry over GSL groups in case the context is changing. */ + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream) +@@ -1567,17 +1572,6 @@ void dcn20_program_front_end_for_ctx( + for (i = 0; i < dc->res_pool->pipe_count; i++) + dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], + &context->res_ctx.pipe_ctx[i]); +- for (i = 0; i < dc->res_pool->pipe_count; i++) +- if (!context->res_ctx.pipe_ctx[i].top_pipe && +- does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +- +- if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) +- dc->hwss.pipe_control_lock(dc, pipe_ctx, true); +- if (!pipe_ctx->update_flags.bits.enable) +- dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true); +- pipe_locked[i] = true; +- } + + /* OTG blank before disabling all front ends */ + for (i = 0; i < dc->res_pool->pipe_count; i++) +@@ -1615,17 +1609,16 @@ void dcn20_program_front_end_for_ctx( + hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context); + } + } ++} + +- /* Unlock all locked pipes */ +- for (i = 0; i < dc->res_pool->pipe_count; i++) +- if (pipe_locked[i]) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++void dcn20_post_unlock_program_front_end( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++ int i; ++ const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; + +- if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) +- dc->hwss.pipe_control_lock(dc, pipe_ctx, false); +- if (!pipe_ctx->update_flags.bits.enable) +- dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false); +- } ++ DC_LOGGER_INIT(dc->ctx->logger); + + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) +@@ -1655,7 +1648,6 @@ void dcn20_program_front_end_for_ctx( + dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); + } + +- + void dcn20_prepare_bandwidth( + struct dc *dc, + struct dc_state *context) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +index 02c9be5ebd47..63ce763f148e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +@@ -35,6 +35,9 @@ bool dcn20_set_shaper_3dlut( + void dcn20_program_front_end_for_ctx( + struct dc *dc, + struct dc_state *context); ++void dcn20_post_unlock_program_front_end( ++ struct dc *dc, ++ struct dc_state *context); + void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx); + void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx); + bool dcn20_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, +@@ -58,10 +61,6 @@ void dcn20_pipe_control_lock( + struct dc *dc, + struct pipe_ctx *pipe, + bool lock); +-void dcn20_pipe_control_lock_global( +- struct dc *dc, +- struct pipe_ctx *pipe, +- bool lock); + void dcn20_prepare_bandwidth( + struct dc *dc, + struct dc_state *context); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +index 5e640f17d3d4..71bfde2cf646 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +@@ -33,6 +33,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = NULL, + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, ++ .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, + .update_plane_addr = dcn20_update_plane_addr, + .update_dchub = dcn10_update_dchub, + .update_pending_status = dcn10_update_pending_status, +@@ -50,7 +51,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dcn20_disable_plane, + .pipe_control_lock = dcn20_pipe_control_lock, +- .pipe_control_lock_global = dcn20_pipe_control_lock_global, ++ .interdependent_update_lock = dcn10_lock_all_pipes, ++ .cursor_lock = dcn10_cursor_lock, + .prepare_bandwidth = dcn20_prepare_bandwidth, + .optimize_bandwidth = dcn20_optimize_bandwidth, + .update_bandwidth = dcn20_update_bandwidth, +@@ -81,6 +83,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { + .init_vm_ctx = dcn20_init_vm_ctx, + .set_flip_control_gsl = dcn20_set_flip_control_gsl, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, ++ .calc_vupdate_position = dcn10_calc_vupdate_position, + }; + + static const struct hwseq_private_funcs dcn20_private_funcs = { +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +index de9c857ab3e9..570dfd9a243f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +@@ -545,6 +545,7 @@ const struct mpc_funcs dcn20_mpc_funcs = { + .mpc_init = mpc1_mpc_init, + .mpc_init_single_inst = mpc1_mpc_init_single_inst, + .update_blending = mpc2_update_blending, ++ .cursor_lock = mpc1_cursor_lock, + .get_mpcc_for_dpp = mpc2_get_mpcc_for_dpp, + .wait_for_idle = mpc2_assert_idle_mpcc, + .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h +index c78fd5123497..496658f420db 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h +@@ -179,7 +179,8 @@ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ +- SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh) ++ SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ ++ SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) + + /* + * DCN2 MPC_OCSC debug status register: +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +index 1b0bca9587d0..1ba47f3a6857 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +@@ -506,6 +506,10 @@ enum dcn20_clk_src_array_id { + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + ++#define VUPDATE_SRII(reg_name, block, id)\ ++ .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ ++ mm ## reg_name ## _ ## block ## id ++ + /* NBIO */ + #define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +index fddbd59bf4f9..7f53bf724fce 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +@@ -34,6 +34,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = NULL, + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, ++ .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, + .update_plane_addr = dcn20_update_plane_addr, + .update_dchub = dcn10_update_dchub, + .update_pending_status = dcn10_update_pending_status, +@@ -51,7 +52,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dcn20_disable_plane, + .pipe_control_lock = dcn20_pipe_control_lock, +- .pipe_control_lock_global = dcn20_pipe_control_lock_global, ++ .interdependent_update_lock = dcn10_lock_all_pipes, ++ .cursor_lock = dcn10_cursor_lock, + .prepare_bandwidth = dcn20_prepare_bandwidth, + .optimize_bandwidth = dcn20_optimize_bandwidth, + .update_bandwidth = dcn20_update_bandwidth, +@@ -84,6 +86,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { + .optimize_pwr_state = dcn21_optimize_pwr_state, + .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, ++ .calc_vupdate_position = dcn10_calc_vupdate_position, + .set_cursor_position = dcn10_set_cursor_position, + .set_cursor_attribute = dcn10_set_cursor_attribute, + .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +index 122d3e734c59..5286cc7d1261 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +@@ -306,6 +306,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + ++#define VUPDATE_SRII(reg_name, block, id)\ ++ .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ ++ mm ## reg_name ## _ ## block ## id ++ + /* NBIO */ + #define NBIO_BASE_INNER(seg) \ + NBIF0_BASE__INST0_SEG ## seg +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +index 094afc4c8173..50ee8aa7ec3b 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +@@ -210,6 +210,22 @@ struct mpc_funcs { + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id); + ++ /* ++ * Lock cursor updates for the specified OPP. ++ * OPP defines the set of MPCC that are locked together for cursor. ++ * ++ * Parameters: ++ * [in] mpc - MPC context. ++ * [in] opp_id - The OPP to lock cursor updates on ++ * [in] lock - lock/unlock the OPP ++ * ++ * Return: void ++ */ ++ void (*cursor_lock)( ++ struct mpc *mpc, ++ int opp_id, ++ bool lock); ++ + struct mpcc* (*get_mpcc_for_dpp)( + struct mpc_tree *tree, + int dpp_id); +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +index 209118f9f193..08307f3796e3 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +@@ -66,6 +66,8 @@ struct hw_sequencer_funcs { + int num_planes, struct dc_state *context); + void (*program_front_end_for_ctx)(struct dc *dc, + struct dc_state *context); ++ void (*post_unlock_program_front_end)(struct dc *dc, ++ struct dc_state *context); + void (*update_plane_addr)(const struct dc *dc, + struct pipe_ctx *pipe_ctx); + void (*update_dchub)(struct dce_hwseq *hws, +@@ -78,17 +80,23 @@ struct hw_sequencer_funcs { + void (*update_pending_status)(struct pipe_ctx *pipe_ctx); + + /* Pipe Lock Related */ +- void (*pipe_control_lock_global)(struct dc *dc, +- struct pipe_ctx *pipe, bool lock); + void (*pipe_control_lock)(struct dc *dc, + struct pipe_ctx *pipe, bool lock); ++ void (*interdependent_update_lock)(struct dc *dc, ++ struct dc_state *context, bool lock); + void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx, + bool flip_immediate); ++ void (*cursor_lock)(struct dc *dc, struct pipe_ctx *pipe, bool lock); + + /* Timing Related */ + void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes, + struct crtc_position *position); + int (*get_vupdate_offset_from_vsync)(struct pipe_ctx *pipe_ctx); ++ void (*calc_vupdate_position)( ++ struct dc *dc, ++ struct pipe_ctx *pipe_ctx, ++ uint32_t *start_line, ++ uint32_t *end_line); + void (*enable_per_frame_crtc_position_reset)(struct dc *dc, + int group_size, struct pipe_ctx *grouped_pipes[]); + void (*enable_timing_synchronization)(struct dc *dc, +diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +index e4e5a53b2b4e..8e2acb4df860 100644 +--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +@@ -319,12 +319,12 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, + if (*level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + hwmgr->en_umd_pstate = true; +- amdgpu_device_ip_set_clockgating_state(hwmgr->adev, +- AMD_IP_BLOCK_TYPE_GFX, +- AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); ++ amdgpu_device_ip_set_clockgating_state(hwmgr->adev, ++ AMD_IP_BLOCK_TYPE_GFX, ++ AMD_CG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ +diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +index 96e81c7bc266..e2565967db07 100644 +--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +@@ -1675,12 +1675,12 @@ static int smu_enable_umd_pstate(void *handle, + if (*level & profile_mode_mask) { + smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; + smu_dpm_ctx->enable_umd_pstate = true; +- amdgpu_device_ip_set_clockgating_state(smu->adev, +- AMD_IP_BLOCK_TYPE_GFX, +- AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); ++ amdgpu_device_ip_set_clockgating_state(smu->adev, ++ AMD_IP_BLOCK_TYPE_GFX, ++ AMD_CG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ +diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c +index bcba2f024842..e9900e078d51 100644 +--- a/drivers/gpu/drm/ingenic/ingenic-drm.c ++++ b/drivers/gpu/drm/ingenic/ingenic-drm.c +@@ -328,8 +328,8 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, + if (!drm_atomic_crtc_needs_modeset(state)) + return 0; + +- if (state->mode.hdisplay > priv->soc_info->max_height || +- state->mode.vdisplay > priv->soc_info->max_width) ++ if (state->mode.hdisplay > priv->soc_info->max_width || ++ state->mode.vdisplay > priv->soc_info->max_height) + return -EINVAL; + + rate = clk_round_rate(priv->pix_clk, +@@ -474,7 +474,7 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, + + static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg) + { +- struct ingenic_drm *priv = arg; ++ struct ingenic_drm *priv = drm_device_get_priv(arg); + unsigned int state; + + regmap_read(priv->map, JZ_REG_LCD_STATE, &state); +diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c +index b5f5eb7b4bb9..8c2e1b47e81a 100644 +--- a/drivers/gpu/drm/meson/meson_drv.c ++++ b/drivers/gpu/drm/meson/meson_drv.c +@@ -412,9 +412,7 @@ static int __maybe_unused meson_drv_pm_resume(struct device *dev) + if (priv->afbcd.ops) + priv->afbcd.ops->init(priv); + +- drm_mode_config_helper_resume(priv->drm); +- +- return 0; ++ return drm_mode_config_helper_resume(priv->drm); + } + + static int compare_of(struct device *dev, void *data) +diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c +index 281c81edabc6..dfb122b5e1b7 100644 +--- a/drivers/hwmon/nct7904.c ++++ b/drivers/hwmon/nct7904.c +@@ -356,6 +356,7 @@ static int nct7904_read_temp(struct device *dev, u32 attr, int channel, + struct nct7904_data *data = dev_get_drvdata(dev); + int ret, temp; + unsigned int reg1, reg2, reg3; ++ s8 temps; + + switch (attr) { + case hwmon_temp_input: +@@ -461,7 +462,8 @@ static int nct7904_read_temp(struct device *dev, u32 attr, int channel, + + if (ret < 0) + return ret; +- *val = ret * 1000; ++ temps = ret; ++ *val = temps * 1000; + return 0; + } + +diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c +index bf8e149d3191..e0a5e897e4b1 100644 +--- a/drivers/infiniband/core/rdma_core.c ++++ b/drivers/infiniband/core/rdma_core.c +@@ -153,9 +153,9 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj, + uobj->context = NULL; + + /* +- * For DESTROY the usecnt is held write locked, the caller is expected +- * to put it unlock and put the object when done with it. Only DESTROY +- * can remove the IDR handle. ++ * For DESTROY the usecnt is not changed, the caller is expected to ++ * manage it via uobj_put_destroy(). Only DESTROY can remove the IDR ++ * handle. + */ + if (reason != RDMA_REMOVE_DESTROY) + atomic_set(&uobj->usecnt, 0); +@@ -187,7 +187,7 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj, + /* + * This calls uverbs_destroy_uobject() using the RDMA_REMOVE_DESTROY + * sequence. It should only be used from command callbacks. On success the +- * caller must pair this with rdma_lookup_put_uobject(LOOKUP_WRITE). This ++ * caller must pair this with uobj_put_destroy(). This + * version requires the caller to have already obtained an + * LOOKUP_DESTROY uobject kref. + */ +@@ -198,6 +198,13 @@ int uobj_destroy(struct ib_uobject *uobj, struct uverbs_attr_bundle *attrs) + + down_read(&ufile->hw_destroy_rwsem); + ++ /* ++ * Once the uobject is destroyed by RDMA_REMOVE_DESTROY then it is left ++ * write locked as the callers put it back with UVERBS_LOOKUP_DESTROY. ++ * This is because any other concurrent thread can still see the object ++ * in the xarray due to RCU. Leaving it locked ensures nothing else will ++ * touch it. ++ */ + ret = uverbs_try_lock_object(uobj, UVERBS_LOOKUP_WRITE); + if (ret) + goto out_unlock; +@@ -216,7 +223,7 @@ out_unlock: + /* + * uobj_get_destroy destroys the HW object and returns a handle to the uobj + * with a NULL object pointer. The caller must pair this with +- * uverbs_put_destroy. ++ * uobj_put_destroy(). + */ + struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj, + u32 id, struct uverbs_attr_bundle *attrs) +@@ -250,8 +257,7 @@ int __uobj_perform_destroy(const struct uverbs_api_object *obj, u32 id, + uobj = __uobj_get_destroy(obj, id, attrs); + if (IS_ERR(uobj)) + return PTR_ERR(uobj); +- +- rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE); ++ uobj_put_destroy(uobj); + return 0; + } + +diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c +index bb78d3280acc..fa7a5ff498c7 100644 +--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c ++++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c +@@ -1987,7 +1987,6 @@ static int i40iw_addr_resolve_neigh(struct i40iw_device *iwdev, + struct rtable *rt; + struct neighbour *neigh; + int rc = arpindex; +- struct net_device *netdev = iwdev->netdev; + __be32 dst_ipaddr = htonl(dst_ip); + __be32 src_ipaddr = htonl(src_ip); + +@@ -1997,9 +1996,6 @@ static int i40iw_addr_resolve_neigh(struct i40iw_device *iwdev, + return rc; + } + +- if (netif_is_bond_slave(netdev)) +- netdev = netdev_master_upper_dev_get(netdev); +- + neigh = dst_neigh_lookup(&rt->dst, &dst_ipaddr); + + rcu_read_lock(); +@@ -2065,7 +2061,6 @@ static int i40iw_addr_resolve_neigh_ipv6(struct i40iw_device *iwdev, + { + struct neighbour *neigh; + int rc = arpindex; +- struct net_device *netdev = iwdev->netdev; + struct dst_entry *dst; + struct sockaddr_in6 dst_addr; + struct sockaddr_in6 src_addr; +@@ -2086,9 +2081,6 @@ static int i40iw_addr_resolve_neigh_ipv6(struct i40iw_device *iwdev, + return rc; + } + +- if (netif_is_bond_slave(netdev)) +- netdev = netdev_master_upper_dev_get(netdev); +- + neigh = dst_neigh_lookup(dst, dst_addr.sin6_addr.in6_u.u6_addr32); + + rcu_read_lock(); +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index 6fa0a83c19de..9a1747a97fb6 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -1319,6 +1319,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + + if (is_odp_mr(mr)) { + to_ib_umem_odp(mr->umem)->private = mr; ++ init_waitqueue_head(&mr->q_deferred_work); + atomic_set(&mr->num_deferred_work, 0); + err = xa_err(xa_store(&dev->odp_mkeys, + mlx5_base_mkey(mr->mmkey.key), &mr->mmkey, +diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c +index 568b21eb6ea1..021df0654ba7 100644 +--- a/drivers/infiniband/hw/qib/qib_sysfs.c ++++ b/drivers/infiniband/hw/qib/qib_sysfs.c +@@ -760,7 +760,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, + qib_dev_err(dd, + "Skipping linkcontrol sysfs info, (err %d) port %u\n", + ret, port_num); +- goto bail; ++ goto bail_link; + } + kobject_uevent(&ppd->pport_kobj, KOBJ_ADD); + +@@ -770,7 +770,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, + qib_dev_err(dd, + "Skipping sl2vl sysfs info, (err %d) port %u\n", + ret, port_num); +- goto bail_link; ++ goto bail_sl; + } + kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); + +@@ -780,7 +780,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, + qib_dev_err(dd, + "Skipping diag_counters sysfs info, (err %d) port %u\n", + ret, port_num); +- goto bail_sl; ++ goto bail_diagc; + } + kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); + +@@ -793,7 +793,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, + qib_dev_err(dd, + "Skipping Congestion Control sysfs info, (err %d) port %u\n", + ret, port_num); +- goto bail_diagc; ++ goto bail_cc; + } + + kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); +@@ -854,6 +854,7 @@ void qib_verbs_unregister_sysfs(struct qib_devdata *dd) + &cc_table_bin_attr); + kobject_put(&ppd->pport_cc_kobj); + } ++ kobject_put(&ppd->diagc_kobj); + kobject_put(&ppd->sl2vl_kobj); + kobject_put(&ppd->pport_kobj); + } +diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +index e580ae9cc55a..780fd2dfc07e 100644 +--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c ++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +@@ -829,7 +829,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev, + !(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { + dev_err(&pdev->dev, "PCI BAR region not MMIO\n"); + ret = -ENOMEM; +- goto err_free_device; ++ goto err_disable_pdev; + } + + ret = pci_request_regions(pdev, DRV_NAME); +diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h +index 2aa3457a30ce..0e5f27caf2b2 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib.h ++++ b/drivers/infiniband/ulp/ipoib/ipoib.h +@@ -377,8 +377,12 @@ struct ipoib_dev_priv { + struct ipoib_rx_buf *rx_ring; + + struct ipoib_tx_buf *tx_ring; ++ /* cyclic ring variables for managing tx_ring, for UD only */ + unsigned int tx_head; + unsigned int tx_tail; ++ /* cyclic ring variables for counting overall outstanding send WRs */ ++ unsigned int global_tx_head; ++ unsigned int global_tx_tail; + struct ib_sge tx_sge[MAX_SKB_FRAGS + 1]; + struct ib_ud_wr tx_wr; + struct ib_wc send_wc[MAX_SEND_CQE]; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +index c59e00a0881f..9bf0fa30df28 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +@@ -756,7 +756,8 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ + return; + } + +- if ((priv->tx_head - priv->tx_tail) == ipoib_sendq_size - 1) { ++ if ((priv->global_tx_head - priv->global_tx_tail) == ++ ipoib_sendq_size - 1) { + ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", + tx->qp->qp_num); + netif_stop_queue(dev); +@@ -786,7 +787,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ + } else { + netif_trans_update(dev); + ++tx->tx_head; +- ++priv->tx_head; ++ ++priv->global_tx_head; + } + } + +@@ -820,10 +821,11 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) + netif_tx_lock(dev); + + ++tx->tx_tail; +- ++priv->tx_tail; ++ ++priv->global_tx_tail; + + if (unlikely(netif_queue_stopped(dev) && +- (priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1 && ++ ((priv->global_tx_head - priv->global_tx_tail) <= ++ ipoib_sendq_size >> 1) && + test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))) + netif_wake_queue(dev); + +@@ -1232,8 +1234,9 @@ timeout: + dev_kfree_skb_any(tx_req->skb); + netif_tx_lock_bh(p->dev); + ++p->tx_tail; +- ++priv->tx_tail; +- if (unlikely(priv->tx_head - priv->tx_tail == ipoib_sendq_size >> 1) && ++ ++priv->global_tx_tail; ++ if (unlikely((priv->global_tx_head - priv->global_tx_tail) <= ++ ipoib_sendq_size >> 1) && + netif_queue_stopped(p->dev) && + test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) + netif_wake_queue(p->dev); +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c +index c332b4761816..da3c5315bbb5 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c +@@ -407,9 +407,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) + dev_kfree_skb_any(tx_req->skb); + + ++priv->tx_tail; ++ ++priv->global_tx_tail; + + if (unlikely(netif_queue_stopped(dev) && +- ((priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1) && ++ ((priv->global_tx_head - priv->global_tx_tail) <= ++ ipoib_sendq_size >> 1) && + test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))) + netif_wake_queue(dev); + +@@ -634,7 +636,8 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb, + else + priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM; + /* increase the tx_head after send success, but use it for queue state */ +- if (priv->tx_head - priv->tx_tail == ipoib_sendq_size - 1) { ++ if ((priv->global_tx_head - priv->global_tx_tail) == ++ ipoib_sendq_size - 1) { + ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n"); + netif_stop_queue(dev); + } +@@ -662,6 +665,7 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb, + + rc = priv->tx_head; + ++priv->tx_head; ++ ++priv->global_tx_head; + } + return rc; + } +@@ -807,6 +811,7 @@ int ipoib_ib_dev_stop_default(struct net_device *dev) + ipoib_dma_unmap_tx(priv, tx_req); + dev_kfree_skb_any(tx_req->skb); + ++priv->tx_tail; ++ ++priv->global_tx_tail; + } + + for (i = 0; i < ipoib_recvq_size; ++i) { +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c +index 4a0d3a9e72e1..70d6d476ba90 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c +@@ -1188,9 +1188,11 @@ static void ipoib_timeout(struct net_device *dev, unsigned int txqueue) + + ipoib_warn(priv, "transmit timeout: latency %d msecs\n", + jiffies_to_msecs(jiffies - dev_trans_start(dev))); +- ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n", +- netif_queue_stopped(dev), +- priv->tx_head, priv->tx_tail); ++ ipoib_warn(priv, ++ "queue stopped %d, tx_head %u, tx_tail %u, global_tx_head %u, global_tx_tail %u\n", ++ netif_queue_stopped(dev), priv->tx_head, priv->tx_tail, ++ priv->global_tx_head, priv->global_tx_tail); ++ + /* XXX reset QP, etc. */ + } + +@@ -1705,7 +1707,7 @@ static int ipoib_dev_init_default(struct net_device *dev) + goto out_rx_ring_cleanup; + } + +- /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ ++ /* priv->tx_head, tx_tail and global_tx_tail/head are already 0 */ + + if (ipoib_transport_dev_init(dev, priv->ca)) { + pr_warn("%s: ipoib_transport_dev_init failed\n", +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index cb6e3a5f509c..0d57e51b8ba1 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -326,20 +326,6 @@ static int evdev_fasync(int fd, struct file *file, int on) + return fasync_helper(fd, file, on, &client->fasync); + } + +-static int evdev_flush(struct file *file, fl_owner_t id) +-{ +- struct evdev_client *client = file->private_data; +- struct evdev *evdev = client->evdev; +- +- mutex_lock(&evdev->mutex); +- +- if (evdev->exist && !client->revoked) +- input_flush_device(&evdev->handle, file); +- +- mutex_unlock(&evdev->mutex); +- return 0; +-} +- + static void evdev_free(struct device *dev) + { + struct evdev *evdev = container_of(dev, struct evdev, dev); +@@ -453,6 +439,10 @@ static int evdev_release(struct inode *inode, struct file *file) + unsigned int i; + + mutex_lock(&evdev->mutex); ++ ++ if (evdev->exist && !client->revoked) ++ input_flush_device(&evdev->handle, file); ++ + evdev_ungrab(evdev, client); + mutex_unlock(&evdev->mutex); + +@@ -1310,7 +1300,6 @@ static const struct file_operations evdev_fops = { + .compat_ioctl = evdev_ioctl_compat, + #endif + .fasync = evdev_fasync, +- .flush = evdev_flush, + .llseek = no_llseek, + }; + +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index 6b40a1c68f9f..c77cdb3b62b5 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -458,6 +458,16 @@ static const u8 xboxone_fw2015_init[] = { + 0x05, 0x20, 0x00, 0x01, 0x00 + }; + ++/* ++ * This packet is required for Xbox One S (0x045e:0x02ea) ++ * and Xbox One Elite Series 2 (0x045e:0x0b00) pads to ++ * initialize the controller that was previously used in ++ * Bluetooth mode. ++ */ ++static const u8 xboxone_s_init[] = { ++ 0x05, 0x20, 0x00, 0x0f, 0x06 ++}; ++ + /* + * This packet is required for the Titanfall 2 Xbox One pads + * (0x0e6f:0x0165) to finish initialization and for Hori pads +@@ -516,6 +526,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = { + XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), ++ XBOXONE_INIT_PKT(0x045e, 0x02ea, xboxone_s_init), ++ XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init), + XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1), + XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), +diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c +index b0ead7199c40..a69dcc3bd30c 100644 +--- a/drivers/input/keyboard/dlink-dir685-touchkeys.c ++++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c +@@ -143,7 +143,7 @@ MODULE_DEVICE_TABLE(of, dir685_tk_of_match); + + static struct i2c_driver dir685_tk_i2c_driver = { + .driver = { +- .name = "dlin-dir685-touchkeys", ++ .name = "dlink-dir685-touchkeys", + .of_match_table = of_match_ptr(dir685_tk_of_match), + }, + .probe = dir685_tk_probe, +diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c +index 190b9974526b..258d5fe3d395 100644 +--- a/drivers/input/rmi4/rmi_driver.c ++++ b/drivers/input/rmi4/rmi_driver.c +@@ -205,7 +205,7 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id) + + if (count) { + kfree(attn_data.data); +- attn_data.data = NULL; ++ drvdata->attn_data.data = NULL; + } + + if (!kfifo_is_empty(&drvdata->attn_fifo)) +@@ -1210,7 +1210,8 @@ static int rmi_driver_probe(struct device *dev) + if (data->input) { + rmi_driver_set_input_name(rmi_dev, data->input); + if (!rmi_dev->xport->input) { +- if (input_register_device(data->input)) { ++ retval = input_register_device(data->input); ++ if (retval) { + dev_err(dev, "%s: Failed to register input device.\n", + __func__); + goto err_destroy_functions; +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index 08e919dbeb5d..7e048b557462 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -662,6 +662,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"), + }, + }, ++ { ++ /* Lenovo ThinkPad Twist S230u */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"), ++ }, ++ }, + { } + }; + +diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c +index 16d70201de4a..397cb1d3f481 100644 +--- a/drivers/input/touchscreen/usbtouchscreen.c ++++ b/drivers/input/touchscreen/usbtouchscreen.c +@@ -182,6 +182,7 @@ static const struct usb_device_id usbtouch_devices[] = { + #endif + + #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH ++ {USB_DEVICE(0x255e, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, + {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, + {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, + {USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES}, +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index 22b28076d48e..b09de25df02e 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -509,7 +509,7 @@ struct iommu_group *iommu_group_alloc(void) + NULL, "%d", group->id); + if (ret) { + ida_simple_remove(&iommu_group_ida, group->id); +- kfree(group); ++ kobject_put(&group->kobj); + return ERR_PTR(ret); + } + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 32db16f6debc..2d19291ebc84 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2475,8 +2475,8 @@ static int mmc_rpmb_chrdev_release(struct inode *inode, struct file *filp) + struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev, + struct mmc_rpmb_data, chrdev); + +- put_device(&rpmb->dev); + mmc_blk_put(rpmb->md); ++ put_device(&rpmb->dev); + + return 0; + } +diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c +index 007481557191..9b8346638f69 100644 +--- a/drivers/net/bonding/bond_sysfs_slave.c ++++ b/drivers/net/bonding/bond_sysfs_slave.c +@@ -149,8 +149,10 @@ int bond_sysfs_slave_add(struct slave *slave) + + err = kobject_init_and_add(&slave->kobj, &slave_ktype, + &(slave->dev->dev.kobj), "bonding_slave"); +- if (err) ++ if (err) { ++ kobject_put(&slave->kobj); + return err; ++ } + + for (a = slave_attrs; *a; ++a) { + err = sysfs_create_file(&slave->kobj, &((*a)->attr)); +diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c +index 0123498242b9..b95425a63a13 100644 +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -639,11 +639,8 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv, + mt7530_write(priv, MT7530_PVC_P(port), + PORT_SPEC_TAG); + +- /* Disable auto learning on the cpu port */ +- mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); +- +- /* Unknown unicast frame fordwarding to the cpu port */ +- mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port))); ++ /* Unknown multicast frame forwarding to the cpu port */ ++ mt7530_rmw(priv, MT7530_MFC, UNM_FFP_MASK, UNM_FFP(BIT(port))); + + /* Set CPU port number */ + if (priv->id == ID_MT7621) +@@ -1247,8 +1244,6 @@ mt7530_setup(struct dsa_switch *ds) + /* Enable and reset MIB counters */ + mt7530_mib_reset(ds); + +- mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); +- + for (i = 0; i < MT7530_NUM_PORTS; i++) { + /* Disable forwarding by default on all ports */ + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, +diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h +index 756140b7dfd5..0e7e36d8f994 100644 +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -31,6 +31,7 @@ enum { + #define MT7530_MFC 0x10 + #define BC_FFP(x) (((x) & 0xff) << 24) + #define UNM_FFP(x) (((x) & 0xff) << 16) ++#define UNM_FFP_MASK UNM_FFP(~0) + #define UNU_FFP(x) (((x) & 0xff) << 8) + #define UNU_FFP_MASK UNU_FFP(~0) + #define CPU_EN BIT(7) +diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c +index a7780c06fa65..b74580e87be8 100644 +--- a/drivers/net/dsa/ocelot/felix.c ++++ b/drivers/net/dsa/ocelot/felix.c +@@ -385,6 +385,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) + struct ocelot *ocelot = &felix->ocelot; + phy_interface_t *port_phy_modes; + resource_size_t switch_base; ++ struct resource res; + int port, i, err; + + ocelot->num_phys_ports = num_phys_ports; +@@ -416,17 +417,16 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) + + for (i = 0; i < TARGET_MAX; i++) { + struct regmap *target; +- struct resource *res; + + if (!felix->info->target_io_res[i].name) + continue; + +- res = &felix->info->target_io_res[i]; +- res->flags = IORESOURCE_MEM; +- res->start += switch_base; +- res->end += switch_base; ++ memcpy(&res, &felix->info->target_io_res[i], sizeof(res)); ++ res.flags = IORESOURCE_MEM; ++ res.start += switch_base; ++ res.end += switch_base; + +- target = ocelot_regmap_init(ocelot, res); ++ target = ocelot_regmap_init(ocelot, &res); + if (IS_ERR(target)) { + dev_err(ocelot->dev, + "Failed to map device memory space\n"); +@@ -447,7 +447,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) + for (port = 0; port < num_phys_ports; port++) { + struct ocelot_port *ocelot_port; + void __iomem *port_regs; +- struct resource *res; + + ocelot_port = devm_kzalloc(ocelot->dev, + sizeof(struct ocelot_port), +@@ -459,12 +458,12 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) + return -ENOMEM; + } + +- res = &felix->info->port_io_res[port]; +- res->flags = IORESOURCE_MEM; +- res->start += switch_base; +- res->end += switch_base; ++ memcpy(&res, &felix->info->port_io_res[port], sizeof(res)); ++ res.flags = IORESOURCE_MEM; ++ res.start += switch_base; ++ res.end += switch_base; + +- port_regs = devm_ioremap_resource(ocelot->dev, res); ++ port_regs = devm_ioremap_resource(ocelot->dev, &res); + if (IS_ERR(port_regs)) { + dev_err(ocelot->dev, + "failed to map registers for port %d\n", port); +diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h +index 8771d40324f1..2c024cc901d4 100644 +--- a/drivers/net/dsa/ocelot/felix.h ++++ b/drivers/net/dsa/ocelot/felix.h +@@ -8,9 +8,9 @@ + + /* Platform-specific information */ + struct felix_info { +- struct resource *target_io_res; +- struct resource *port_io_res; +- struct resource *imdio_res; ++ const struct resource *target_io_res; ++ const struct resource *port_io_res; ++ const struct resource *imdio_res; + const struct reg_field *regfields; + const u32 *const *map; + const struct ocelot_ops *ops; +diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c +index edc1a67c002b..50074da3a1a0 100644 +--- a/drivers/net/dsa/ocelot/felix_vsc9959.c ++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c +@@ -328,10 +328,8 @@ static const u32 *vsc9959_regmap[] = { + [GCB] = vsc9959_gcb_regmap, + }; + +-/* Addresses are relative to the PCI device's base address and +- * will be fixed up at ioremap time. +- */ +-static struct resource vsc9959_target_io_res[] = { ++/* Addresses are relative to the PCI device's base address */ ++static const struct resource vsc9959_target_io_res[] = { + [ANA] = { + .start = 0x0280000, + .end = 0x028ffff, +@@ -374,7 +372,7 @@ static struct resource vsc9959_target_io_res[] = { + }, + }; + +-static struct resource vsc9959_port_io_res[] = { ++static const struct resource vsc9959_port_io_res[] = { + { + .start = 0x0100000, + .end = 0x010ffff, +@@ -410,7 +408,7 @@ static struct resource vsc9959_port_io_res[] = { + /* Port MAC 0 Internal MDIO bus through which the SerDes acting as an + * SGMII/QSGMII MAC PCS can be found. + */ +-static struct resource vsc9959_imdio_res = { ++static const struct resource vsc9959_imdio_res = { + .start = 0x8030, + .end = 0x8040, + .name = "imdio", +@@ -984,7 +982,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) + struct device *dev = ocelot->dev; + resource_size_t imdio_base; + void __iomem *imdio_regs; +- struct resource *res; ++ struct resource res; + struct enetc_hw *hw; + struct mii_bus *bus; + int port; +@@ -1001,12 +999,12 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) + imdio_base = pci_resource_start(felix->pdev, + felix->info->imdio_pci_bar); + +- res = felix->info->imdio_res; +- res->flags = IORESOURCE_MEM; +- res->start += imdio_base; +- res->end += imdio_base; ++ memcpy(&res, felix->info->imdio_res, sizeof(res)); ++ res.flags = IORESOURCE_MEM; ++ res.start += imdio_base; ++ res.end += imdio_base; + +- imdio_regs = devm_ioremap_resource(dev, res); ++ imdio_regs = devm_ioremap_resource(dev, &res); + if (IS_ERR(imdio_regs)) { + dev_err(dev, "failed to map internal MDIO registers\n"); + return PTR_ERR(imdio_regs); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index d0ddd08c4112..fce4e26c36cf 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -4184,14 +4184,12 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + int i, intr_process, rc, tmo_count; + struct input *req = msg; + u32 *data = msg; +- __le32 *resp_len; + u8 *valid; + u16 cp_ring_id, len = 0; + struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr; + u16 max_req_len = BNXT_HWRM_MAX_REQ_LEN; + struct hwrm_short_input short_input = {0}; + u32 doorbell_offset = BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER; +- u8 *resp_addr = (u8 *)bp->hwrm_cmd_resp_addr; + u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM; + u16 dst = BNXT_HWRM_CHNL_CHIMP; + +@@ -4209,7 +4207,6 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + bar_offset = BNXT_GRCPF_REG_KONG_COMM; + doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER; + resp = bp->hwrm_cmd_kong_resp_addr; +- resp_addr = (u8 *)bp->hwrm_cmd_kong_resp_addr; + } + + memset(resp, 0, PAGE_SIZE); +@@ -4278,7 +4275,6 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + tmo_count = HWRM_SHORT_TIMEOUT_COUNTER; + timeout = timeout - HWRM_SHORT_MIN_TIMEOUT * HWRM_SHORT_TIMEOUT_COUNTER; + tmo_count += DIV_ROUND_UP(timeout, HWRM_MIN_TIMEOUT); +- resp_len = (__le32 *)(resp_addr + HWRM_RESP_LEN_OFFSET); + + if (intr_process) { + u16 seq_id = bp->hwrm_intr_seq_id; +@@ -4306,9 +4302,8 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + le16_to_cpu(req->req_type)); + return -EBUSY; + } +- len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >> +- HWRM_RESP_LEN_SFT; +- valid = resp_addr + len - 1; ++ len = le16_to_cpu(resp->resp_len); ++ valid = ((u8 *)resp) + len - 1; + } else { + int j; + +@@ -4319,8 +4314,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + */ + if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) + return -EBUSY; +- len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >> +- HWRM_RESP_LEN_SFT; ++ len = le16_to_cpu(resp->resp_len); + if (len) + break; + /* on first few passes, just barely sleep */ +@@ -4342,7 +4336,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, + } + + /* Last byte of resp contains valid bit */ +- valid = resp_addr + len - 1; ++ valid = ((u8 *)resp) + len - 1; + for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; j++) { + /* make sure we read from updated DMA memory */ + dma_rmb(); +@@ -9324,7 +9318,7 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init, + bnxt_free_skbs(bp); + + /* Save ring stats before shutdown */ +- if (bp->bnapi) ++ if (bp->bnapi && irq_re_init) + bnxt_get_ring_stats(bp, &bp->net_stats_prev); + if (irq_re_init) { + bnxt_free_irq(bp); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index ef0268649822..f76c42652e1a 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -654,11 +654,6 @@ struct nqe_cn { + #define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout) + #define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) + #define HWRM_COREDUMP_TIMEOUT ((HWRM_CMD_TIMEOUT) * 12) +-#define HWRM_RESP_ERR_CODE_MASK 0xffff +-#define HWRM_RESP_LEN_OFFSET 4 +-#define HWRM_RESP_LEN_MASK 0xffff0000 +-#define HWRM_RESP_LEN_SFT 16 +-#define HWRM_RESP_VALID_MASK 0xff000000 + #define BNXT_HWRM_REQ_MAX_SIZE 128 + #define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \ + BNXT_HWRM_REQ_MAX_SIZE) +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index 2bd7ace0a953..bfc6bfe94d0a 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -77,6 +77,7 @@ config UCC_GETH + depends on QUICC_ENGINE && PPC32 + select FSL_PQ_MDIO + select PHYLIB ++ select FIXED_PHY + ---help--- + This driver supports the Gigabit Ethernet mode of the QUICC Engine, + which is available on some Freescale SOCs. +@@ -90,6 +91,7 @@ config GIANFAR + depends on HAS_DMA + select FSL_PQ_MDIO + select PHYLIB ++ select FIXED_PHY + select CRC32 + ---help--- + This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, +diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig +index 3b325733a4f8..0a54c7e0e4ae 100644 +--- a/drivers/net/ethernet/freescale/dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/dpaa/Kconfig +@@ -3,6 +3,7 @@ menuconfig FSL_DPAA_ETH + tristate "DPAA Ethernet" + depends on FSL_DPAA && FSL_FMAN + select PHYLIB ++ select FIXED_PHY + select FSL_FMAN_MAC + ---help--- + Data Path Acceleration Architecture Ethernet driver, +diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +index ca74a684a904..ab337632793b 100644 +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +@@ -2902,7 +2902,7 @@ static int dpaa_eth_probe(struct platform_device *pdev) + } + + /* Do this here, so we can be verbose early */ +- SET_NETDEV_DEV(net_dev, dev); ++ SET_NETDEV_DEV(net_dev, dev->parent); + dev_set_drvdata(dev, net_dev); + + priv = netdev_priv(net_dev); +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +index 4344a59c823f..6122057d60c0 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +@@ -1070,7 +1070,7 @@ void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port) + (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS)); + + val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG); +- val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id); ++ val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id); + mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c +index 6e501af0e532..f6ff9620a137 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/fw.c ++++ b/drivers/net/ethernet/mellanox/mlx4/fw.c +@@ -2734,7 +2734,7 @@ void mlx4_opreq_action(struct work_struct *work) + if (err) { + mlx4_err(dev, "Failed to retrieve required operation: %d\n", + err); +- return; ++ goto out; + } + MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET); + MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index cede5bdfd598..7a77fe40af3a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -848,6 +848,14 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); + static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, + struct mlx5_cmd_msg *msg); + ++static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode) ++{ ++ if (cmd->allowed_opcode == CMD_ALLOWED_OPCODE_ALL) ++ return true; ++ ++ return cmd->allowed_opcode == opcode; ++} ++ + static void cmd_work_handler(struct work_struct *work) + { + struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); +@@ -861,6 +869,7 @@ static void cmd_work_handler(struct work_struct *work) + int alloc_ret; + int cmd_mode; + ++ complete(&ent->handling); + sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + down(sem); + if (!ent->page_queue) { +@@ -913,7 +922,9 @@ static void cmd_work_handler(struct work_struct *work) + + /* Skip sending command to fw if internal error */ + if (pci_channel_offline(dev->pdev) || +- dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { ++ dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || ++ cmd->state != MLX5_CMDIF_STATE_UP || ++ !opcode_allowed(&dev->cmd, ent->op)) { + u8 status = 0; + u32 drv_synd; + +@@ -978,6 +989,11 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) + struct mlx5_cmd *cmd = &dev->cmd; + int err; + ++ if (!wait_for_completion_timeout(&ent->handling, timeout) && ++ cancel_work_sync(&ent->work)) { ++ ent->ret = -ECANCELED; ++ goto out_err; ++ } + if (cmd->mode == CMD_MODE_POLLING || ent->polling) { + wait_for_completion(&ent->done); + } else if (!wait_for_completion_timeout(&ent->done, timeout)) { +@@ -985,12 +1001,17 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) + mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); + } + ++out_err: + err = ent->ret; + + if (err == -ETIMEDOUT) { + mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n", + mlx5_command_str(msg_to_opcode(ent->in)), + msg_to_opcode(ent->in)); ++ } else if (err == -ECANCELED) { ++ mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n", ++ mlx5_command_str(msg_to_opcode(ent->in)), ++ msg_to_opcode(ent->in)); + } + mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n", + err, deliv_status_to_str(ent->status), ent->status); +@@ -1026,6 +1047,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, + ent->token = token; + ent->polling = force_polling; + ++ init_completion(&ent->handling); + if (!callback) + init_completion(&ent->done); + +@@ -1045,6 +1067,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, + err = wait_func(dev, ent); + if (err == -ETIMEDOUT) + goto out; ++ if (err == -ECANCELED) ++ goto out_free; + + ds = ent->ts2 - ent->ts1; + op = MLX5_GET(mbox_in, in->first.data, opcode); +@@ -1391,6 +1415,22 @@ static void create_debugfs_files(struct mlx5_core_dev *dev) + mlx5_cmdif_debugfs_init(dev); + } + ++void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode) ++{ ++ struct mlx5_cmd *cmd = &dev->cmd; ++ int i; ++ ++ for (i = 0; i < cmd->max_reg_cmds; i++) ++ down(&cmd->sem); ++ down(&cmd->pages_sem); ++ ++ cmd->allowed_opcode = opcode; ++ ++ up(&cmd->pages_sem); ++ for (i = 0; i < cmd->max_reg_cmds; i++) ++ up(&cmd->sem); ++} ++ + static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) + { + struct mlx5_cmd *cmd = &dev->cmd; +@@ -1667,12 +1707,14 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, + int err; + u8 status = 0; + u32 drv_synd; ++ u16 opcode; + u8 token; + ++ opcode = MLX5_GET(mbox_in, in, opcode); + if (pci_channel_offline(dev->pdev) || +- dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { +- u16 opcode = MLX5_GET(mbox_in, in, opcode); +- ++ dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || ++ dev->cmd.state != MLX5_CMDIF_STATE_UP || ++ !opcode_allowed(&dev->cmd, opcode)) { + err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status); + MLX5_SET(mbox_out, out, status, status); + MLX5_SET(mbox_out, out, syndrome, drv_synd); +@@ -1937,6 +1979,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) + goto err_free_page; + } + ++ cmd->state = MLX5_CMDIF_STATE_DOWN; + cmd->checksum_disabled = 1; + cmd->max_reg_cmds = (1 << cmd->log_sz) - 1; + cmd->bitmask = (1UL << cmd->max_reg_cmds) - 1; +@@ -1974,6 +2017,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) + mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma)); + + cmd->mode = CMD_MODE_POLLING; ++ cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL; + + create_msg_cache(dev); + +@@ -2013,3 +2057,10 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) + dma_pool_destroy(cmd->pool); + } + EXPORT_SYMBOL(mlx5_cmd_cleanup); ++ ++void mlx5_cmd_set_state(struct mlx5_core_dev *dev, ++ enum mlx5_cmdif_state cmdif_state) ++{ ++ dev->cmd.state = cmdif_state; ++} ++EXPORT_SYMBOL(mlx5_cmd_set_state); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 5a5e6a21c6e1..80c579948152 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -1104,7 +1104,7 @@ void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq); + int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv); + + int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc); +-void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc); ++void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv); + + int mlx5e_create_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs); + void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c +index 46725cd743a3..7d1985fa0d4f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c +@@ -69,8 +69,8 @@ static void mlx5e_ktls_del(struct net_device *netdev, + struct mlx5e_ktls_offload_context_tx *tx_priv = + mlx5e_get_ktls_tx_priv_ctx(tls_ctx); + +- mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id); + mlx5e_destroy_tis(priv->mdev, tx_priv->tisn); ++ mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id); + kvfree(tx_priv); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index d02db5aebac4..4fef7587165c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2747,7 +2747,8 @@ void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen) + mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen); + } + +- if (!mlx5e_tunnel_inner_ft_supported(priv->mdev)) ++ /* Verify inner tirs resources allocated */ ++ if (!priv->inner_indir_tir[0].tirn) + return; + + for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { +@@ -3394,14 +3395,15 @@ out: + return err; + } + +-void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc) ++void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv) + { + int i; + + for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++) + mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[i]); + +- if (!inner_ttc || !mlx5e_tunnel_inner_ft_supported(priv->mdev)) ++ /* Verify inner tirs resources allocated */ ++ if (!priv->inner_indir_tir[0].tirn) + return; + + for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++) +@@ -5107,7 +5109,7 @@ err_destroy_xsk_rqts: + err_destroy_direct_tirs: + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); + err_destroy_indirect_tirs: +- mlx5e_destroy_indirect_tirs(priv, true); ++ mlx5e_destroy_indirect_tirs(priv); + err_destroy_direct_rqts: + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + err_destroy_indirect_rqts: +@@ -5126,7 +5128,7 @@ static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv) + mlx5e_destroy_direct_tirs(priv, priv->xsk_tir); + mlx5e_destroy_direct_rqts(priv, priv->xsk_tir); + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); +- mlx5e_destroy_indirect_tirs(priv, true); ++ mlx5e_destroy_indirect_tirs(priv); + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + mlx5e_destroy_rqt(priv, &priv->indir_rqt); + mlx5e_close_drop_rq(&priv->drop_rq); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index 2ad0d09cc9bd..c3c3d89d9153 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -1667,7 +1667,7 @@ err_destroy_ttc_table: + err_destroy_direct_tirs: + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); + err_destroy_indirect_tirs: +- mlx5e_destroy_indirect_tirs(priv, false); ++ mlx5e_destroy_indirect_tirs(priv); + err_destroy_direct_rqts: + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + err_destroy_indirect_rqts: +@@ -1684,7 +1684,7 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) + mlx5_del_flow_rules(rpriv->vport_rx_rule); + mlx5e_destroy_ttc_table(priv, &priv->fs.ttc); + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); +- mlx5e_destroy_indirect_tirs(priv, false); ++ mlx5e_destroy_indirect_tirs(priv); + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + mlx5e_destroy_rqt(priv, &priv->indir_rqt); + mlx5e_close_drop_rq(&priv->drop_rq); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +index ee60383adc5b..c2b801b435cf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +@@ -538,10 +538,9 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) + void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq) + { + struct mlx5e_tx_wqe_info *wi; ++ u32 dma_fifo_cc, nbytes = 0; ++ u16 ci, sqcc, npkts = 0; + struct sk_buff *skb; +- u32 dma_fifo_cc; +- u16 sqcc; +- u16 ci; + int i; + + sqcc = sq->cc; +@@ -566,11 +565,15 @@ void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq) + } + + dev_kfree_skb_any(skb); ++ npkts++; ++ nbytes += wi->num_bytes; + sqcc += wi->num_wqebbs; + } + + sq->dma_fifo_cc = dma_fifo_cc; + sq->cc = sqcc; ++ ++ netdev_tx_completed_queue(sq->txq, npkts, nbytes); + } + + #ifdef CONFIG_MLX5_CORE_IPOIB +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +index cccea3a8eddd..ce6c621af043 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +@@ -611,11 +611,13 @@ static int create_async_eqs(struct mlx5_core_dev *dev) + .nent = MLX5_NUM_CMD_EQE, + .mask[0] = 1ull << MLX5_EVENT_TYPE_CMD, + }; ++ mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_CREATE_EQ); + err = setup_async_eq(dev, &table->cmd_eq, ¶m, "cmd"); + if (err) + goto err1; + + mlx5_cmd_use_events(dev); ++ mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); + + param = (struct mlx5_eq_param) { + .irq_index = 0, +@@ -645,6 +647,7 @@ err2: + mlx5_cmd_use_polling(dev); + cleanup_async_eq(dev, &table->cmd_eq, "cmd"); + err1: ++ mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); + mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); + return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c +index 8bcf3426b9c6..3ce17c3d7a00 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c +@@ -346,8 +346,10 @@ int mlx5_events_init(struct mlx5_core_dev *dev) + events->dev = dev; + dev->priv.events = events; + events->wq = create_singlethread_workqueue("mlx5_events"); +- if (!events->wq) ++ if (!events->wq) { ++ kfree(events); + return -ENOMEM; ++ } + INIT_WORK(&events->pcie_core_work, mlx5_pcie_event); + + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index 9dc24241dc91..cf09cfc33234 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -323,14 +323,13 @@ static void tree_put_node(struct fs_node *node, bool locked) + if (node->del_hw_func) + node->del_hw_func(node); + if (parent_node) { +- /* Only root namespace doesn't have parent and we just +- * need to free its node. +- */ + down_write_ref_node(parent_node, locked); + list_del_init(&node->list); + if (node->del_sw_func) + node->del_sw_func(node); + up_write_ref_node(parent_node, locked); ++ } else if (node->del_sw_func) { ++ node->del_sw_func(node); + } else { + kfree(node); + } +@@ -417,6 +416,12 @@ static void del_sw_ns(struct fs_node *node) + + static void del_sw_prio(struct fs_node *node) + { ++ struct mlx5_flow_root_namespace *root_ns; ++ struct mlx5_flow_namespace *ns; ++ ++ fs_get_obj(ns, node); ++ root_ns = container_of(ns, struct mlx5_flow_root_namespace, ns); ++ mutex_destroy(&root_ns->chain_lock); + kfree(node); + } + +@@ -447,8 +452,10 @@ static void del_sw_flow_table(struct fs_node *node) + fs_get_obj(ft, node); + + rhltable_destroy(&ft->fgs_hash); +- fs_get_obj(prio, ft->node.parent); +- prio->num_ft--; ++ if (ft->node.parent) { ++ fs_get_obj(prio, ft->node.parent); ++ prio->num_ft--; ++ } + kfree(ft); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +index 56078b23f1a0..0a334ceba7b1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +@@ -396,7 +396,7 @@ static int mlx5i_init_rx(struct mlx5e_priv *priv) + err_destroy_direct_tirs: + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); + err_destroy_indirect_tirs: +- mlx5e_destroy_indirect_tirs(priv, true); ++ mlx5e_destroy_indirect_tirs(priv); + err_destroy_direct_rqts: + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + err_destroy_indirect_rqts: +@@ -412,7 +412,7 @@ static void mlx5i_cleanup_rx(struct mlx5e_priv *priv) + { + mlx5i_destroy_flow_steering(priv); + mlx5e_destroy_direct_tirs(priv, priv->direct_tir); +- mlx5e_destroy_indirect_tirs(priv, true); ++ mlx5e_destroy_indirect_tirs(priv); + mlx5e_destroy_direct_rqts(priv, priv->direct_tir); + mlx5e_destroy_rqt(priv, &priv->indir_rqt); + mlx5e_close_drop_rq(&priv->drop_rq); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index f554cfddcf4e..4a08e4eef283 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -962,6 +962,8 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) + goto err_cmd_cleanup; + } + ++ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP); ++ + err = mlx5_core_enable_hca(dev, 0); + if (err) { + mlx5_core_err(dev, "enable hca failed\n"); +@@ -1023,6 +1025,7 @@ reclaim_boot_pages: + err_disable_hca: + mlx5_core_disable_hca(dev, 0); + err_cmd_cleanup: ++ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); + + return err; +@@ -1040,6 +1043,7 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) + } + mlx5_reclaim_startup_pages(dev); + mlx5_core_disable_hca(dev, 0); ++ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); + + return 0; +@@ -1179,7 +1183,7 @@ int mlx5_load_one(struct mlx5_core_dev *dev, bool boot) + + err = mlx5_function_setup(dev, boot); + if (err) +- goto out; ++ goto err_function; + + if (boot) { + err = mlx5_init_once(dev); +@@ -1225,6 +1229,7 @@ err_load: + mlx5_cleanup_once(dev); + function_teardown: + mlx5_function_teardown(dev, boot); ++err_function: + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + mutex_unlock(&dev->intf_state_mutex); + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index 7358b5bc7eb6..58ebabe99876 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -4043,6 +4043,7 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) + mlxsw_sp_port_remove(mlxsw_sp, i); + mlxsw_sp_cpu_port_remove(mlxsw_sp); + kfree(mlxsw_sp->ports); ++ mlxsw_sp->ports = NULL; + } + + static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) +@@ -4079,6 +4080,7 @@ err_port_create: + mlxsw_sp_cpu_port_remove(mlxsw_sp); + err_cpu_port_create: + kfree(mlxsw_sp->ports); ++ mlxsw_sp->ports = NULL; + return err; + } + +@@ -4200,6 +4202,14 @@ static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core, + return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id); + } + ++static struct mlxsw_sp_port * ++mlxsw_sp_port_get_by_local_port(struct mlxsw_sp *mlxsw_sp, u8 local_port) ++{ ++ if (mlxsw_sp->ports && mlxsw_sp->ports[local_port]) ++ return mlxsw_sp->ports[local_port]; ++ return NULL; ++} ++ + static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, + unsigned int count, + struct netlink_ext_ack *extack) +@@ -4213,7 +4223,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, + int i; + int err; + +- mlxsw_sp_port = mlxsw_sp->ports[local_port]; ++ mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port); + if (!mlxsw_sp_port) { + dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n", + local_port); +@@ -4308,7 +4318,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port, + int offset; + int i; + +- mlxsw_sp_port = mlxsw_sp->ports[local_port]; ++ mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port); + if (!mlxsw_sp_port) { + dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n", + local_port); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +index f0e98ec8f1ee..c69232445ab7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +@@ -1259,6 +1259,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) + if (mlxsw_sx_port_created(mlxsw_sx, i)) + mlxsw_sx_port_remove(mlxsw_sx, i); + kfree(mlxsw_sx->ports); ++ mlxsw_sx->ports = NULL; + } + + static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) +@@ -1293,6 +1294,7 @@ err_port_module_info_get: + if (mlxsw_sx_port_created(mlxsw_sx, i)) + mlxsw_sx_port_remove(mlxsw_sx, i); + kfree(mlxsw_sx->ports); ++ mlxsw_sx->ports = NULL; + return err; + } + +@@ -1376,6 +1378,12 @@ static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port, + u8 module, width; + int err; + ++ if (!mlxsw_sx->ports || !mlxsw_sx->ports[local_port]) { ++ dev_err(mlxsw_sx->bus_info->dev, "Port number \"%d\" does not exist\n", ++ local_port); ++ return -EINVAL; ++ } ++ + if (new_type == DEVLINK_PORT_TYPE_AUTO) + return -EOPNOTSUPP; + +diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c +index 39925e4bf2ec..b25a13da900a 100644 +--- a/drivers/net/ethernet/microchip/encx24j600.c ++++ b/drivers/net/ethernet/microchip/encx24j600.c +@@ -1070,7 +1070,7 @@ static int encx24j600_spi_probe(struct spi_device *spi) + if (unlikely(ret)) { + netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n", + ret); +- goto out_free; ++ goto out_stop; + } + + eidled = encx24j600_read_reg(priv, EIDLED); +@@ -1088,6 +1088,8 @@ static int encx24j600_spi_probe(struct spi_device *spi) + + out_unregister: + unregister_netdev(priv->ndev); ++out_stop: ++ kthread_stop(priv->kworker_task); + out_free: + free_netdev(ndev); + +@@ -1100,6 +1102,7 @@ static int encx24j600_spi_remove(struct spi_device *spi) + struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); + + unregister_netdev(priv->ndev); ++ kthread_stop(priv->kworker_task); + + free_netdev(priv->ndev); + +diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c +index 419e2ce2eac0..d5aa4e725853 100644 +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -1460,7 +1460,7 @@ static void ocelot_port_attr_ageing_set(struct ocelot *ocelot, int port, + unsigned long ageing_clock_t) + { + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t); +- u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000; ++ u32 ageing_time = jiffies_to_msecs(ageing_jiffies); + + ocelot_set_ageing_time(ocelot, ageing_time); + } +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +index 2a533280b124..29b9c728a65e 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +@@ -3651,7 +3651,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) + ahw->diag_cnt = 0; + ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); + if (ret) +- goto fail_diag_irq; ++ goto fail_mbx_args; + + if (adapter->flags & QLCNIC_MSIX_ENABLED) + intrpt_id = ahw->intr_tbl[0].id; +@@ -3681,6 +3681,8 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) + + done: + qlcnic_free_mbx_args(&cmd); ++ ++fail_mbx_args: + qlcnic_83xx_diag_free_res(netdev, drv_sds_rings); + + fail_diag_irq: +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 07a6b609f741..6e4fe2566f6b 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -1044,6 +1044,13 @@ static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr) + RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0; + } + ++static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type) ++{ ++ /* based on RTL8168FP_OOBMAC_BASE in vendor driver */ ++ if (tp->mac_version == RTL_GIGA_MAC_VER_52 && type == ERIAR_OOB) ++ *cmd |= 0x7f0 << 18; ++} ++ + DECLARE_RTL_COND(rtl_eriar_cond) + { + return RTL_R32(tp, ERIAR) & ERIAR_FLAG; +@@ -1052,9 +1059,12 @@ DECLARE_RTL_COND(rtl_eriar_cond) + static void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, + u32 val, int type) + { ++ u32 cmd = ERIAR_WRITE_CMD | type | mask | addr; ++ + BUG_ON((addr & 3) || (mask == 0)); + RTL_W32(tp, ERIDR, val); +- RTL_W32(tp, ERIAR, ERIAR_WRITE_CMD | type | mask | addr); ++ r8168fp_adjust_ocp_cmd(tp, &cmd, type); ++ RTL_W32(tp, ERIAR, cmd); + + rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100); + } +@@ -1067,7 +1077,10 @@ static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, + + static u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type) + { +- RTL_W32(tp, ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr); ++ u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr; ++ ++ r8168fp_adjust_ocp_cmd(tp, &cmd, type); ++ RTL_W32(tp, ERIAR, cmd); + + return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ? + RTL_R32(tp, ERIDR) : ~0; +diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c +index db6b2988e632..f4895777f5e3 100644 +--- a/drivers/net/ethernet/sgi/ioc3-eth.c ++++ b/drivers/net/ethernet/sgi/ioc3-eth.c +@@ -865,14 +865,14 @@ static int ioc3eth_probe(struct platform_device *pdev) + ip = netdev_priv(dev); + ip->dma_dev = pdev->dev.parent; + ip->regs = devm_platform_ioremap_resource(pdev, 0); +- if (!ip->regs) { +- err = -ENOMEM; ++ if (IS_ERR(ip->regs)) { ++ err = PTR_ERR(ip->regs); + goto out_free; + } + + ip->ssram = devm_platform_ioremap_resource(pdev, 1); +- if (!ip->ssram) { +- err = -ENOMEM; ++ if (IS_ERR(ip->ssram)) { ++ err = PTR_ERR(ip->ssram); + goto out_free; + } + +diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c +index 6ec9163e232c..b716f188188e 100644 +--- a/drivers/net/ethernet/sun/cassini.c ++++ b/drivers/net/ethernet/sun/cassini.c +@@ -4971,7 +4971,7 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + cas_cacheline_size)) { + dev_err(&pdev->dev, "Could not set PCI cache " + "line size\n"); +- goto err_write_cacheline; ++ goto err_out_free_res; + } + } + #endif +@@ -5144,7 +5144,6 @@ err_out_iounmap: + err_out_free_res: + pci_release_regions(pdev); + +-err_write_cacheline: + /* Try to restore it in case the error occurred after we + * set it. + */ +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 6ae4a72e6f43..5577ff0b7663 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -1752,11 +1752,15 @@ static int cpsw_suspend(struct device *dev) + struct cpsw_common *cpsw = dev_get_drvdata(dev); + int i; + ++ rtnl_lock(); ++ + for (i = 0; i < cpsw->data.slaves; i++) + if (cpsw->slaves[i].ndev) + if (netif_running(cpsw->slaves[i].ndev)) + cpsw_ndo_stop(cpsw->slaves[i].ndev); + ++ rtnl_unlock(); ++ + /* Select sleep pin state */ + pinctrl_pm_select_sleep_state(dev); + +diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c +index fbea6f232819..e2ad3c2e8df5 100644 +--- a/drivers/net/hamradio/bpqether.c ++++ b/drivers/net/hamradio/bpqether.c +@@ -127,7 +127,8 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev) + { + struct bpqdev *bpq; + +- list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) { ++ list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list, ++ lockdep_rtnl_is_held()) { + if (bpq->ethdev == dev) + return bpq->axdev; + } +diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c +index 0cdb2ce47645..a657943c9f01 100644 +--- a/drivers/net/usb/cdc_ether.c ++++ b/drivers/net/usb/cdc_ether.c +@@ -815,14 +815,21 @@ static const struct usb_device_id products[] = { + .driver_info = 0, + }, + +-/* Microsoft Surface 3 dock (based on Realtek RTL8153) */ ++/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */ + { + USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, + }, + +- /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ ++/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */ ++{ ++ USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM, ++ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), ++ .driver_info = 0, ++}, ++ ++/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ + { + USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 95b19ce96513..7c8c45984a5c 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -6901,6 +6901,7 @@ static const struct usb_device_id rtl8152_table[] = { + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)}, + {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, +diff --git a/drivers/net/wireguard/messages.h b/drivers/net/wireguard/messages.h +index b8a7b9ce32ba..208da72673fc 100644 +--- a/drivers/net/wireguard/messages.h ++++ b/drivers/net/wireguard/messages.h +@@ -32,7 +32,7 @@ enum cookie_values { + }; + + enum counter_values { +- COUNTER_BITS_TOTAL = 2048, ++ COUNTER_BITS_TOTAL = 8192, + COUNTER_REDUNDANT_BITS = BITS_PER_LONG, + COUNTER_WINDOW_SIZE = COUNTER_BITS_TOTAL - COUNTER_REDUNDANT_BITS + }; +diff --git a/drivers/net/wireguard/noise.c b/drivers/net/wireguard/noise.c +index 708dc61c974f..626433690abb 100644 +--- a/drivers/net/wireguard/noise.c ++++ b/drivers/net/wireguard/noise.c +@@ -104,6 +104,7 @@ static struct noise_keypair *keypair_create(struct wg_peer *peer) + + if (unlikely(!keypair)) + return NULL; ++ spin_lock_init(&keypair->receiving_counter.lock); + keypair->internal_id = atomic64_inc_return(&keypair_counter); + keypair->entry.type = INDEX_HASHTABLE_KEYPAIR; + keypair->entry.peer = peer; +@@ -358,25 +359,16 @@ out: + memzero_explicit(output, BLAKE2S_HASH_SIZE + 1); + } + +-static void symmetric_key_init(struct noise_symmetric_key *key) +-{ +- spin_lock_init(&key->counter.receive.lock); +- atomic64_set(&key->counter.counter, 0); +- memset(key->counter.receive.backtrack, 0, +- sizeof(key->counter.receive.backtrack)); +- key->birthdate = ktime_get_coarse_boottime_ns(); +- key->is_valid = true; +-} +- + static void derive_keys(struct noise_symmetric_key *first_dst, + struct noise_symmetric_key *second_dst, + const u8 chaining_key[NOISE_HASH_LEN]) + { ++ u64 birthdate = ktime_get_coarse_boottime_ns(); + kdf(first_dst->key, second_dst->key, NULL, NULL, + NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0, + chaining_key); +- symmetric_key_init(first_dst); +- symmetric_key_init(second_dst); ++ first_dst->birthdate = second_dst->birthdate = birthdate; ++ first_dst->is_valid = second_dst->is_valid = true; + } + + static bool __must_check mix_dh(u8 chaining_key[NOISE_HASH_LEN], +@@ -715,6 +707,7 @@ wg_noise_handshake_consume_response(struct message_handshake_response *src, + u8 e[NOISE_PUBLIC_KEY_LEN]; + u8 ephemeral_private[NOISE_PUBLIC_KEY_LEN]; + u8 static_private[NOISE_PUBLIC_KEY_LEN]; ++ u8 preshared_key[NOISE_SYMMETRIC_KEY_LEN]; + + down_read(&wg->static_identity.lock); + +@@ -733,6 +726,8 @@ wg_noise_handshake_consume_response(struct message_handshake_response *src, + memcpy(chaining_key, handshake->chaining_key, NOISE_HASH_LEN); + memcpy(ephemeral_private, handshake->ephemeral_private, + NOISE_PUBLIC_KEY_LEN); ++ memcpy(preshared_key, handshake->preshared_key, ++ NOISE_SYMMETRIC_KEY_LEN); + up_read(&handshake->lock); + + if (state != HANDSHAKE_CREATED_INITIATION) +@@ -750,7 +745,7 @@ wg_noise_handshake_consume_response(struct message_handshake_response *src, + goto fail; + + /* psk */ +- mix_psk(chaining_key, hash, key, handshake->preshared_key); ++ mix_psk(chaining_key, hash, key, preshared_key); + + /* {} */ + if (!message_decrypt(NULL, src->encrypted_nothing, +@@ -783,6 +778,7 @@ out: + memzero_explicit(chaining_key, NOISE_HASH_LEN); + memzero_explicit(ephemeral_private, NOISE_PUBLIC_KEY_LEN); + memzero_explicit(static_private, NOISE_PUBLIC_KEY_LEN); ++ memzero_explicit(preshared_key, NOISE_SYMMETRIC_KEY_LEN); + up_read(&wg->static_identity.lock); + return ret_peer; + } +diff --git a/drivers/net/wireguard/noise.h b/drivers/net/wireguard/noise.h +index f532d59d3f19..c527253dba80 100644 +--- a/drivers/net/wireguard/noise.h ++++ b/drivers/net/wireguard/noise.h +@@ -15,18 +15,14 @@ + #include + #include + +-union noise_counter { +- struct { +- u64 counter; +- unsigned long backtrack[COUNTER_BITS_TOTAL / BITS_PER_LONG]; +- spinlock_t lock; +- } receive; +- atomic64_t counter; ++struct noise_replay_counter { ++ u64 counter; ++ spinlock_t lock; ++ unsigned long backtrack[COUNTER_BITS_TOTAL / BITS_PER_LONG]; + }; + + struct noise_symmetric_key { + u8 key[NOISE_SYMMETRIC_KEY_LEN]; +- union noise_counter counter; + u64 birthdate; + bool is_valid; + }; +@@ -34,7 +30,9 @@ struct noise_symmetric_key { + struct noise_keypair { + struct index_hashtable_entry entry; + struct noise_symmetric_key sending; ++ atomic64_t sending_counter; + struct noise_symmetric_key receiving; ++ struct noise_replay_counter receiving_counter; + __le32 remote_index; + bool i_am_the_initiator; + struct kref refcount; +diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h +index 3432232afe06..c58df439dbbe 100644 +--- a/drivers/net/wireguard/queueing.h ++++ b/drivers/net/wireguard/queueing.h +@@ -87,12 +87,20 @@ static inline bool wg_check_packet_protocol(struct sk_buff *skb) + return real_protocol && skb->protocol == real_protocol; + } + +-static inline void wg_reset_packet(struct sk_buff *skb) ++static inline void wg_reset_packet(struct sk_buff *skb, bool encapsulating) + { ++ u8 l4_hash = skb->l4_hash; ++ u8 sw_hash = skb->sw_hash; ++ u32 hash = skb->hash; + skb_scrub_packet(skb, true); + memset(&skb->headers_start, 0, + offsetof(struct sk_buff, headers_end) - + offsetof(struct sk_buff, headers_start)); ++ if (encapsulating) { ++ skb->l4_hash = l4_hash; ++ skb->sw_hash = sw_hash; ++ skb->hash = hash; ++ } + skb->queue_mapping = 0; + skb->nohdr = 0; + skb->peeked = 0; +diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c +index 2566e13a292d..474bb69f0e1b 100644 +--- a/drivers/net/wireguard/receive.c ++++ b/drivers/net/wireguard/receive.c +@@ -246,20 +246,20 @@ static void keep_key_fresh(struct wg_peer *peer) + } + } + +-static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key) ++static bool decrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair) + { + struct scatterlist sg[MAX_SKB_FRAGS + 8]; + struct sk_buff *trailer; + unsigned int offset; + int num_frags; + +- if (unlikely(!key)) ++ if (unlikely(!keypair)) + return false; + +- if (unlikely(!READ_ONCE(key->is_valid) || +- wg_birthdate_has_expired(key->birthdate, REJECT_AFTER_TIME) || +- key->counter.receive.counter >= REJECT_AFTER_MESSAGES)) { +- WRITE_ONCE(key->is_valid, false); ++ if (unlikely(!READ_ONCE(keypair->receiving.is_valid) || ++ wg_birthdate_has_expired(keypair->receiving.birthdate, REJECT_AFTER_TIME) || ++ keypair->receiving_counter.counter >= REJECT_AFTER_MESSAGES)) { ++ WRITE_ONCE(keypair->receiving.is_valid, false); + return false; + } + +@@ -284,7 +284,7 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key) + + if (!chacha20poly1305_decrypt_sg_inplace(sg, skb->len, NULL, 0, + PACKET_CB(skb)->nonce, +- key->key)) ++ keypair->receiving.key)) + return false; + + /* Another ugly situation of pushing and pulling the header so as to +@@ -299,41 +299,41 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key) + } + + /* This is RFC6479, a replay detection bitmap algorithm that avoids bitshifts */ +-static bool counter_validate(union noise_counter *counter, u64 their_counter) ++static bool counter_validate(struct noise_replay_counter *counter, u64 their_counter) + { + unsigned long index, index_current, top, i; + bool ret = false; + +- spin_lock_bh(&counter->receive.lock); ++ spin_lock_bh(&counter->lock); + +- if (unlikely(counter->receive.counter >= REJECT_AFTER_MESSAGES + 1 || ++ if (unlikely(counter->counter >= REJECT_AFTER_MESSAGES + 1 || + their_counter >= REJECT_AFTER_MESSAGES)) + goto out; + + ++their_counter; + + if (unlikely((COUNTER_WINDOW_SIZE + their_counter) < +- counter->receive.counter)) ++ counter->counter)) + goto out; + + index = their_counter >> ilog2(BITS_PER_LONG); + +- if (likely(their_counter > counter->receive.counter)) { +- index_current = counter->receive.counter >> ilog2(BITS_PER_LONG); ++ if (likely(their_counter > counter->counter)) { ++ index_current = counter->counter >> ilog2(BITS_PER_LONG); + top = min_t(unsigned long, index - index_current, + COUNTER_BITS_TOTAL / BITS_PER_LONG); + for (i = 1; i <= top; ++i) +- counter->receive.backtrack[(i + index_current) & ++ counter->backtrack[(i + index_current) & + ((COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1)] = 0; +- counter->receive.counter = their_counter; ++ counter->counter = their_counter; + } + + index &= (COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1; + ret = !test_and_set_bit(their_counter & (BITS_PER_LONG - 1), +- &counter->receive.backtrack[index]); ++ &counter->backtrack[index]); + + out: +- spin_unlock_bh(&counter->receive.lock); ++ spin_unlock_bh(&counter->lock); + return ret; + } + +@@ -473,19 +473,19 @@ int wg_packet_rx_poll(struct napi_struct *napi, int budget) + if (unlikely(state != PACKET_STATE_CRYPTED)) + goto next; + +- if (unlikely(!counter_validate(&keypair->receiving.counter, ++ if (unlikely(!counter_validate(&keypair->receiving_counter, + PACKET_CB(skb)->nonce))) { + net_dbg_ratelimited("%s: Packet has invalid nonce %llu (max %llu)\n", + peer->device->dev->name, + PACKET_CB(skb)->nonce, +- keypair->receiving.counter.receive.counter); ++ keypair->receiving_counter.counter); + goto next; + } + + if (unlikely(wg_socket_endpoint_from_skb(&endpoint, skb))) + goto next; + +- wg_reset_packet(skb); ++ wg_reset_packet(skb, false); + wg_packet_consume_data_done(peer, skb, &endpoint); + free = false; + +@@ -512,8 +512,8 @@ void wg_packet_decrypt_worker(struct work_struct *work) + struct sk_buff *skb; + + while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) { +- enum packet_state state = likely(decrypt_packet(skb, +- &PACKET_CB(skb)->keypair->receiving)) ? ++ enum packet_state state = ++ likely(decrypt_packet(skb, PACKET_CB(skb)->keypair)) ? + PACKET_STATE_CRYPTED : PACKET_STATE_DEAD; + wg_queue_enqueue_per_peer_napi(skb, state); + if (need_resched()) +diff --git a/drivers/net/wireguard/selftest/counter.c b/drivers/net/wireguard/selftest/counter.c +index f4fbb9072ed7..ec3c156bf91b 100644 +--- a/drivers/net/wireguard/selftest/counter.c ++++ b/drivers/net/wireguard/selftest/counter.c +@@ -6,18 +6,24 @@ + #ifdef DEBUG + bool __init wg_packet_counter_selftest(void) + { ++ struct noise_replay_counter *counter; + unsigned int test_num = 0, i; +- union noise_counter counter; + bool success = true; + +-#define T_INIT do { \ +- memset(&counter, 0, sizeof(union noise_counter)); \ +- spin_lock_init(&counter.receive.lock); \ ++ counter = kmalloc(sizeof(*counter), GFP_KERNEL); ++ if (unlikely(!counter)) { ++ pr_err("nonce counter self-test malloc: FAIL\n"); ++ return false; ++ } ++ ++#define T_INIT do { \ ++ memset(counter, 0, sizeof(*counter)); \ ++ spin_lock_init(&counter->lock); \ + } while (0) + #define T_LIM (COUNTER_WINDOW_SIZE + 1) + #define T(n, v) do { \ + ++test_num; \ +- if (counter_validate(&counter, n) != (v)) { \ ++ if (counter_validate(counter, n) != (v)) { \ + pr_err("nonce counter self-test %u: FAIL\n", \ + test_num); \ + success = false; \ +@@ -99,6 +105,7 @@ bool __init wg_packet_counter_selftest(void) + + if (success) + pr_info("nonce counter self-tests: pass\n"); ++ kfree(counter); + return success; + } + #endif +diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c +index e8a7d0a0cb88..485d5d7a217b 100644 +--- a/drivers/net/wireguard/send.c ++++ b/drivers/net/wireguard/send.c +@@ -129,7 +129,7 @@ static void keep_key_fresh(struct wg_peer *peer) + rcu_read_lock_bh(); + keypair = rcu_dereference_bh(peer->keypairs.current_keypair); + if (likely(keypair && READ_ONCE(keypair->sending.is_valid)) && +- (unlikely(atomic64_read(&keypair->sending.counter.counter) > ++ (unlikely(atomic64_read(&keypair->sending_counter) > + REKEY_AFTER_MESSAGES) || + (keypair->i_am_the_initiator && + unlikely(wg_birthdate_has_expired(keypair->sending.birthdate, +@@ -170,6 +170,11 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair) + struct sk_buff *trailer; + int num_frags; + ++ /* Force hash calculation before encryption so that flow analysis is ++ * consistent over the inner packet. ++ */ ++ skb_get_hash(skb); ++ + /* Calculate lengths. */ + padding_len = calculate_skb_padding(skb); + trailer_len = padding_len + noise_encrypted_len(0); +@@ -298,7 +303,7 @@ void wg_packet_encrypt_worker(struct work_struct *work) + skb_list_walk_safe(first, skb, next) { + if (likely(encrypt_packet(skb, + PACKET_CB(first)->keypair))) { +- wg_reset_packet(skb); ++ wg_reset_packet(skb, true); + } else { + state = PACKET_STATE_DEAD; + break; +@@ -348,7 +353,6 @@ void wg_packet_purge_staged_packets(struct wg_peer *peer) + + void wg_packet_send_staged_packets(struct wg_peer *peer) + { +- struct noise_symmetric_key *key; + struct noise_keypair *keypair; + struct sk_buff_head packets; + struct sk_buff *skb; +@@ -368,10 +372,9 @@ void wg_packet_send_staged_packets(struct wg_peer *peer) + rcu_read_unlock_bh(); + if (unlikely(!keypair)) + goto out_nokey; +- key = &keypair->sending; +- if (unlikely(!READ_ONCE(key->is_valid))) ++ if (unlikely(!READ_ONCE(keypair->sending.is_valid))) + goto out_nokey; +- if (unlikely(wg_birthdate_has_expired(key->birthdate, ++ if (unlikely(wg_birthdate_has_expired(keypair->sending.birthdate, + REJECT_AFTER_TIME))) + goto out_invalid; + +@@ -386,7 +389,7 @@ void wg_packet_send_staged_packets(struct wg_peer *peer) + */ + PACKET_CB(skb)->ds = ip_tunnel_ecn_encap(0, ip_hdr(skb), skb); + PACKET_CB(skb)->nonce = +- atomic64_inc_return(&key->counter.counter) - 1; ++ atomic64_inc_return(&keypair->sending_counter) - 1; + if (unlikely(PACKET_CB(skb)->nonce >= REJECT_AFTER_MESSAGES)) + goto out_invalid; + } +@@ -398,7 +401,7 @@ void wg_packet_send_staged_packets(struct wg_peer *peer) + return; + + out_invalid: +- WRITE_ONCE(key->is_valid, false); ++ WRITE_ONCE(keypair->sending.is_valid, false); + out_nokey: + wg_noise_keypair_put(keypair, false); + +diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c +index db37144ae98c..87ee9f767b7a 100644 +--- a/drivers/soc/mediatek/mtk-cmdq-helper.c ++++ b/drivers/soc/mediatek/mtk-cmdq-helper.c +@@ -351,7 +351,9 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, + spin_unlock_irqrestore(&client->lock, flags); + } + +- mbox_send_message(client->chan, pkt); ++ err = mbox_send_message(client->chan, pkt); ++ if (err < 0) ++ return err; + /* We can send next packet immediately, so just call txdone. */ + mbox_client_txdone(client->chan, 0); + +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index 7051611229c9..b67372737dc9 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -114,6 +114,7 @@ static const struct property_entry dwc3_pci_intel_properties[] = { + + static const struct property_entry dwc3_pci_mrfld_properties[] = { + PROPERTY_ENTRY_STRING("dr_mode", "otg"), ++ PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + {} + }; +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index b47938dff1a2..238f555fe494 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -1361,7 +1361,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + + req->buf = dev->rbuf; + req->context = NULL; +- value = -EOPNOTSUPP; + switch (ctrl->bRequest) { + + case USB_REQ_GET_DESCRIPTOR: +@@ -1784,7 +1783,7 @@ static ssize_t + dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + { + struct dev_data *dev = fd->private_data; +- ssize_t value = len, length = len; ++ ssize_t value, length = len; + unsigned total; + u32 tag; + char *kbuf; +diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c +index bfebf1f2e991..9a7e655d5280 100644 +--- a/drivers/usb/phy/phy-twl6030-usb.c ++++ b/drivers/usb/phy/phy-twl6030-usb.c +@@ -377,7 +377,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) + if (status < 0) { + dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", + twl->irq1, status); +- return status; ++ goto err_put_regulator; + } + + status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, +@@ -386,8 +386,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) + if (status < 0) { + dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", + twl->irq2, status); +- free_irq(twl->irq1, twl); +- return status; ++ goto err_free_irq1; + } + + twl->asleep = 0; +@@ -396,6 +395,13 @@ static int twl6030_usb_probe(struct platform_device *pdev) + dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); + + return 0; ++ ++err_free_irq1: ++ free_irq(twl->irq1, twl); ++err_put_regulator: ++ regulator_put(twl->usb3v3); ++ ++ return status; + } + + static int twl6030_usb_remove(struct platform_device *pdev) +diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c +index 341458fd95ca..44375a22307b 100644 +--- a/drivers/virtio/virtio_balloon.c ++++ b/drivers/virtio/virtio_balloon.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -27,7 +28,9 @@ + */ + #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) + #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 +-#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80 ++/* Maximum number of (4k) pages to deflate on OOM notifications. */ ++#define VIRTIO_BALLOON_OOM_NR_PAGES 256 ++#define VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY 80 + + #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \ + __GFP_NOMEMALLOC) +@@ -112,8 +115,11 @@ struct virtio_balloon { + /* Memory statistics */ + struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; + +- /* To register a shrinker to shrink memory upon memory pressure */ ++ /* Shrinker to return free pages - VIRTIO_BALLOON_F_FREE_PAGE_HINT */ + struct shrinker shrinker; ++ ++ /* OOM notifier to deflate on OOM - VIRTIO_BALLOON_F_DEFLATE_ON_OOM */ ++ struct notifier_block oom_nb; + }; + + static struct virtio_device_id id_table[] = { +@@ -788,50 +794,13 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb, + return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES; + } + +-static unsigned long leak_balloon_pages(struct virtio_balloon *vb, +- unsigned long pages_to_free) +-{ +- return leak_balloon(vb, pages_to_free * VIRTIO_BALLOON_PAGES_PER_PAGE) / +- VIRTIO_BALLOON_PAGES_PER_PAGE; +-} +- +-static unsigned long shrink_balloon_pages(struct virtio_balloon *vb, +- unsigned long pages_to_free) +-{ +- unsigned long pages_freed = 0; +- +- /* +- * One invocation of leak_balloon can deflate at most +- * VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it +- * multiple times to deflate pages till reaching pages_to_free. +- */ +- while (vb->num_pages && pages_freed < pages_to_free) +- pages_freed += leak_balloon_pages(vb, +- pages_to_free - pages_freed); +- +- update_balloon_size(vb); +- +- return pages_freed; +-} +- + static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker, + struct shrink_control *sc) + { +- unsigned long pages_to_free, pages_freed = 0; + struct virtio_balloon *vb = container_of(shrinker, + struct virtio_balloon, shrinker); + +- pages_to_free = sc->nr_to_scan; +- +- if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) +- pages_freed = shrink_free_pages(vb, pages_to_free); +- +- if (pages_freed >= pages_to_free) +- return pages_freed; +- +- pages_freed += shrink_balloon_pages(vb, pages_to_free - pages_freed); +- +- return pages_freed; ++ return shrink_free_pages(vb, sc->nr_to_scan); + } + + static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker, +@@ -839,26 +808,22 @@ static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker, + { + struct virtio_balloon *vb = container_of(shrinker, + struct virtio_balloon, shrinker); +- unsigned long count; +- +- count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE; +- count += vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; + +- return count; ++ return vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; + } + +-static void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb) ++static int virtio_balloon_oom_notify(struct notifier_block *nb, ++ unsigned long dummy, void *parm) + { +- unregister_shrinker(&vb->shrinker); +-} ++ struct virtio_balloon *vb = container_of(nb, ++ struct virtio_balloon, oom_nb); ++ unsigned long *freed = parm; + +-static int virtio_balloon_register_shrinker(struct virtio_balloon *vb) +-{ +- vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; +- vb->shrinker.count_objects = virtio_balloon_shrinker_count; +- vb->shrinker.seeks = DEFAULT_SEEKS; ++ *freed += leak_balloon(vb, VIRTIO_BALLOON_OOM_NR_PAGES) / ++ VIRTIO_BALLOON_PAGES_PER_PAGE; ++ update_balloon_size(vb); + +- return register_shrinker(&vb->shrinker); ++ return NOTIFY_OK; + } + + static int virtballoon_probe(struct virtio_device *vdev) +@@ -935,22 +900,35 @@ static int virtballoon_probe(struct virtio_device *vdev) + virtio_cwrite(vb->vdev, struct virtio_balloon_config, + poison_val, &poison_val); + } +- } +- /* +- * We continue to use VIRTIO_BALLOON_F_DEFLATE_ON_OOM to decide if a +- * shrinker needs to be registered to relieve memory pressure. +- */ +- if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) { +- err = virtio_balloon_register_shrinker(vb); ++ ++ /* ++ * We're allowed to reuse any free pages, even if they are ++ * still to be processed by the host. ++ */ ++ vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; ++ vb->shrinker.count_objects = virtio_balloon_shrinker_count; ++ vb->shrinker.seeks = DEFAULT_SEEKS; ++ err = register_shrinker(&vb->shrinker); + if (err) + goto out_del_balloon_wq; + } ++ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) { ++ vb->oom_nb.notifier_call = virtio_balloon_oom_notify; ++ vb->oom_nb.priority = VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY; ++ err = register_oom_notifier(&vb->oom_nb); ++ if (err < 0) ++ goto out_unregister_shrinker; ++ } ++ + virtio_device_ready(vdev); + + if (towards_target(vb)) + virtballoon_changed(vdev); + return 0; + ++out_unregister_shrinker: ++ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) ++ unregister_shrinker(&vb->shrinker); + out_del_balloon_wq: + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) + destroy_workqueue(vb->balloon_wq); +@@ -989,8 +967,11 @@ static void virtballoon_remove(struct virtio_device *vdev) + { + struct virtio_balloon *vb = vdev->priv; + +- if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) +- virtio_balloon_unregister_shrinker(vb); ++ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) ++ unregister_oom_notifier(&vb->oom_nb); ++ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) ++ unregister_shrinker(&vb->shrinker); ++ + spin_lock_irq(&vb->stop_update_lock); + vb->stop_update = true; + spin_unlock_irq(&vb->stop_update_lock); +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index f4713ea76e82..54f888ddb8cc 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1733,7 +1733,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + (!regset->active || regset->active(t->task, regset) > 0)) { + int ret; + size_t size = regset_size(t->task, regset); +- void *data = kmalloc(size, GFP_KERNEL); ++ void *data = kzalloc(size, GFP_KERNEL); + if (unlikely(!data)) + return 0; + ret = regset->get(t->task, regset, +diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c +index d3d78176b23c..e7726f5f1241 100644 +--- a/fs/cachefiles/rdwr.c ++++ b/fs/cachefiles/rdwr.c +@@ -60,9 +60,9 @@ static int cachefiles_read_waiter(wait_queue_entry_t *wait, unsigned mode, + object = container_of(op->op.object, struct cachefiles_object, fscache); + spin_lock(&object->work_lock); + list_add_tail(&monitor->op_link, &op->to_do); ++ fscache_enqueue_retrieval(op); + spin_unlock(&object->work_lock); + +- fscache_enqueue_retrieval(op); + fscache_put_retrieval(op); + return 0; + } +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index f50204380a65..3ae88ca03ccd 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -3952,7 +3952,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, + __ceph_queue_cap_release(session, cap); + spin_unlock(&session->s_cap_lock); + } +- goto done; ++ goto flush_cap_releases; + } + + /* these will work even if we don't have a cap yet */ +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 5920820bfbd0..b30b03747dd6 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -4060,7 +4060,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) + * than it negotiated since it will refuse the read + * then. + */ +- if ((tcon->ses) && !(tcon->ses->capabilities & ++ if (!(tcon->ses->capabilities & + tcon->ses->server->vals->cap_large_files)) { + current_read_size = min_t(uint, + current_read_size, CIFSMaxBufSize); +diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c +index 60d911e293e6..2674feda1d7a 100644 +--- a/fs/gfs2/log.c ++++ b/fs/gfs2/log.c +@@ -603,13 +603,13 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) + struct buffer_head *bh = bd->bd_bh; + struct gfs2_glock *gl = bd->bd_gl; + ++ sdp->sd_log_num_revoke++; ++ if (atomic_inc_return(&gl->gl_revokes) == 1) ++ gfs2_glock_hold(gl); + bh->b_private = NULL; + bd->bd_blkno = bh->b_blocknr; + gfs2_remove_from_ail(bd); /* drops ref on bh */ + bd->bd_bh = NULL; +- sdp->sd_log_num_revoke++; +- if (atomic_inc_return(&gl->gl_revokes) == 1) +- gfs2_glock_hold(gl); + set_bit(GLF_LFLUSH, &gl->gl_flags); + list_add(&bd->bd_list, &sdp->sd_log_revokes); + } +diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c +index e9f93045eb01..832d44782f74 100644 +--- a/fs/gfs2/quota.c ++++ b/fs/gfs2/quota.c +@@ -1040,8 +1040,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) + u32 x; + int error = 0; + +- if (capable(CAP_SYS_RESOURCE) || +- sdp->sd_args.ar_quota != GFS2_QUOTA_ON) ++ if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON) + return 0; + + error = gfs2_quota_hold(ip, uid, gid); +diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h +index 765627d9a91e..fe68a91dc16f 100644 +--- a/fs/gfs2/quota.h ++++ b/fs/gfs2/quota.h +@@ -44,7 +44,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip, + int ret; + + ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */ +- if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) ++ if (capable(CAP_SYS_RESOURCE) || ++ sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) + return 0; + ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); + if (ret) +diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h +index 238873739550..5aa8705df87e 100644 +--- a/include/asm-generic/topology.h ++++ b/include/asm-generic/topology.h +@@ -48,7 +48,7 @@ + #ifdef CONFIG_NEED_MULTIPLE_NODES + #define cpumask_of_node(node) ((node) == 0 ? cpu_online_mask : cpu_none_mask) + #else +- #define cpumask_of_node(node) ((void)node, cpu_online_mask) ++ #define cpumask_of_node(node) ((void)(node), cpu_online_mask) + #endif + #endif + #ifndef pcibus_to_node +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 7f3486e32e5d..624d2643bfba 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2047,7 +2047,7 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) + } + + /* HE Operation defines */ +-#define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK 0x00000003 ++#define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK 0x00000007 + #define IEEE80211_HE_OPERATION_TWT_REQUIRED 0x00000008 + #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK 0x00003ff0 + #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET 4 +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index 277a51d3ec40..a1842ce8bd4e 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -230,6 +230,12 @@ struct mlx5_bfreg_info { + u32 num_dyn_bfregs; + }; + ++enum mlx5_cmdif_state { ++ MLX5_CMDIF_STATE_UNINITIALIZED, ++ MLX5_CMDIF_STATE_UP, ++ MLX5_CMDIF_STATE_DOWN, ++}; ++ + struct mlx5_cmd_first { + __be32 data[4]; + }; +@@ -275,6 +281,7 @@ struct mlx5_cmd_stats { + struct mlx5_cmd { + struct mlx5_nb nb; + ++ enum mlx5_cmdif_state state; + void *cmd_alloc_buf; + dma_addr_t alloc_dma; + int alloc_size; +@@ -301,6 +308,7 @@ struct mlx5_cmd { + struct semaphore sem; + struct semaphore pages_sem; + int mode; ++ u16 allowed_opcode; + struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS]; + struct dma_pool *pool; + struct mlx5_cmd_debug dbg; +@@ -761,6 +769,7 @@ struct mlx5_cmd_work_ent { + struct delayed_work cb_timeout_work; + void *context; + int idx; ++ struct completion handling; + struct completion done; + struct mlx5_cmd *cmd; + struct work_struct work; +@@ -892,10 +901,17 @@ mlx5_frag_buf_get_idx_last_contig_stride(struct mlx5_frag_buf_ctrl *fbc, u32 ix) + return min_t(u32, last_frag_stride_idx - fbc->strides_offset, fbc->sz_m1); + } + ++enum { ++ CMD_ALLOWED_OPCODE_ALL, ++}; ++ + int mlx5_cmd_init(struct mlx5_core_dev *dev); + void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); ++void mlx5_cmd_set_state(struct mlx5_core_dev *dev, ++ enum mlx5_cmdif_state cmdif_state); + void mlx5_cmd_use_events(struct mlx5_core_dev *dev); + void mlx5_cmd_use_polling(struct mlx5_core_dev *dev); ++void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode); + + struct mlx5_async_ctx { + struct mlx5_core_dev *dev; +diff --git a/include/linux/mm.h b/include/linux/mm.h +index c54fb96cb1e6..96deeecd9179 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -670,6 +670,11 @@ static inline void *kvcalloc(size_t n, size_t size, gfp_t flags) + + extern void kvfree(const void *addr); + ++/* ++ * Mapcount of compound page as a whole, does not include mapped sub-pages. ++ * ++ * Must be called only for compound pages or any their tail sub-pages. ++ */ + static inline int compound_mapcount(struct page *page) + { + VM_BUG_ON_PAGE(!PageCompound(page), page); +@@ -689,10 +694,16 @@ static inline void page_mapcount_reset(struct page *page) + + int __page_mapcount(struct page *page); + ++/* ++ * Mapcount of 0-order page; when compound sub-page, includes ++ * compound_mapcount(). ++ * ++ * Result is undefined for pages which cannot be mapped into userspace. ++ * For example SLAB or special types of pages. See function page_has_type(). ++ * They use this place in struct page differently. ++ */ + static inline int page_mapcount(struct page *page) + { +- VM_BUG_ON_PAGE(PageSlab(page), page); +- + if (unlikely(PageCompound(page))) + return __page_mapcount(page); + return atomic_read(&page->_mapcount) + 1; +diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h +index fcc409de31a4..a28aa289afdc 100644 +--- a/include/linux/netfilter/nf_conntrack_pptp.h ++++ b/include/linux/netfilter/nf_conntrack_pptp.h +@@ -10,7 +10,7 @@ + #include + #include + +-extern const char *const pptp_msg_name[]; ++const char *pptp_msg_name(u_int16_t msg); + + /* state of the control session */ + enum pptp_ctrlsess_state { +diff --git a/include/net/act_api.h b/include/net/act_api.h +index 71347a90a9d1..050c0246dee8 100644 +--- a/include/net/act_api.h ++++ b/include/net/act_api.h +@@ -69,7 +69,8 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm) + { + dtm->install = jiffies_to_clock_t(jiffies - stm->install); + dtm->lastuse = jiffies_to_clock_t(jiffies - stm->lastuse); +- dtm->firstuse = jiffies_to_clock_t(jiffies - stm->firstuse); ++ dtm->firstuse = stm->firstuse ? ++ jiffies_to_clock_t(jiffies - stm->firstuse) : 0; + dtm->expires = jiffies_to_clock_t(stm->expires); + } + +diff --git a/include/net/espintcp.h b/include/net/espintcp.h +index dd7026a00066..0335bbd76552 100644 +--- a/include/net/espintcp.h ++++ b/include/net/espintcp.h +@@ -25,6 +25,7 @@ struct espintcp_ctx { + struct espintcp_msg partial; + void (*saved_data_ready)(struct sock *sk); + void (*saved_write_space)(struct sock *sk); ++ void (*saved_destruct)(struct sock *sk); + struct work_struct work; + bool tx_running; + }; +diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h +index 6a1ae49809de..464772420206 100644 +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -257,7 +257,6 @@ struct fib_dump_filter { + u32 table_id; + /* filter_set is an optimization that an entry is set */ + bool filter_set; +- bool dump_all_families; + bool dump_routes; + bool dump_exceptions; + unsigned char protocol; +@@ -448,6 +447,16 @@ static inline int fib_num_tclassid_users(struct net *net) + #endif + int fib_unmerge(struct net *net); + ++static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc, ++const struct net_device *dev) ++{ ++ if (nhc->nhc_dev == dev || ++ l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) ++ return true; ++ ++ return false; ++} ++ + /* Exported by fib_semantics.c */ + int ip_fib_check_default(__be32 gw, struct net_device *dev); + int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force); +diff --git a/include/net/nexthop.h b/include/net/nexthop.h +index 331ebbc94fe7..3bb618e5ecf7 100644 +--- a/include/net/nexthop.h ++++ b/include/net/nexthop.h +@@ -70,6 +70,7 @@ struct nh_grp_entry { + }; + + struct nh_group { ++ struct nh_group *spare; /* spare group for removals */ + u16 num_nh; + bool mpath; + bool has_v4; +@@ -136,21 +137,20 @@ static inline unsigned int nexthop_num_path(const struct nexthop *nh) + { + unsigned int rc = 1; + +- if (nexthop_is_multipath(nh)) { ++ if (nh->is_group) { + struct nh_group *nh_grp; + + nh_grp = rcu_dereference_rtnl(nh->nh_grp); +- rc = nh_grp->num_nh; ++ if (nh_grp->mpath) ++ rc = nh_grp->num_nh; + } + + return rc; + } + + static inline +-struct nexthop *nexthop_mpath_select(const struct nexthop *nh, int nhsel) ++struct nexthop *nexthop_mpath_select(const struct nh_group *nhg, int nhsel) + { +- const struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp); +- + /* for_nexthops macros in fib_semantics.c grabs a pointer to + * the nexthop before checking nhsel + */ +@@ -185,12 +185,14 @@ static inline bool nexthop_is_blackhole(const struct nexthop *nh) + { + const struct nh_info *nhi; + +- if (nexthop_is_multipath(nh)) { +- if (nexthop_num_path(nh) > 1) +- return false; +- nh = nexthop_mpath_select(nh, 0); +- if (!nh) ++ if (nh->is_group) { ++ struct nh_group *nh_grp; ++ ++ nh_grp = rcu_dereference_rtnl(nh->nh_grp); ++ if (nh_grp->num_nh > 1) + return false; ++ ++ nh = nh_grp->nh_entries[0].nh; + } + + nhi = rcu_dereference_rtnl(nh->nh_info); +@@ -216,16 +218,46 @@ struct fib_nh_common *nexthop_fib_nhc(struct nexthop *nh, int nhsel) + BUILD_BUG_ON(offsetof(struct fib_nh, nh_common) != 0); + BUILD_BUG_ON(offsetof(struct fib6_nh, nh_common) != 0); + +- if (nexthop_is_multipath(nh)) { +- nh = nexthop_mpath_select(nh, nhsel); +- if (!nh) +- return NULL; ++ if (nh->is_group) { ++ struct nh_group *nh_grp; ++ ++ nh_grp = rcu_dereference_rtnl(nh->nh_grp); ++ if (nh_grp->mpath) { ++ nh = nexthop_mpath_select(nh_grp, nhsel); ++ if (!nh) ++ return NULL; ++ } + } + + nhi = rcu_dereference_rtnl(nh->nh_info); + return &nhi->fib_nhc; + } + ++static inline bool nexthop_uses_dev(const struct nexthop *nh, ++ const struct net_device *dev) ++{ ++ struct nh_info *nhi; ++ ++ if (nh->is_group) { ++ struct nh_group *nhg = rcu_dereference(nh->nh_grp); ++ int i; ++ ++ for (i = 0; i < nhg->num_nh; i++) { ++ struct nexthop *nhe = nhg->nh_entries[i].nh; ++ ++ nhi = rcu_dereference(nhe->nh_info); ++ if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev)) ++ return true; ++ } ++ } else { ++ nhi = rcu_dereference(nh->nh_info); ++ if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev)) ++ return true; ++ } ++ ++ return false; ++} ++ + static inline unsigned int fib_info_num_path(const struct fib_info *fi) + { + if (unlikely(fi->nh)) +@@ -263,8 +295,11 @@ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh) + { + struct nh_info *nhi; + +- if (nexthop_is_multipath(nh)) { +- nh = nexthop_mpath_select(nh, 0); ++ if (nh->is_group) { ++ struct nh_group *nh_grp; ++ ++ nh_grp = rcu_dereference_rtnl(nh->nh_grp); ++ nh = nexthop_mpath_select(nh_grp, 0); + if (!nh) + return NULL; + } +diff --git a/include/net/tls.h b/include/net/tls.h +index bf9eb4823933..18cd4f418464 100644 +--- a/include/net/tls.h ++++ b/include/net/tls.h +@@ -135,6 +135,8 @@ struct tls_sw_context_tx { + struct tls_rec *open_rec; + struct list_head tx_list; + atomic_t encrypt_pending; ++ /* protect crypto_wait with encrypt_pending */ ++ spinlock_t encrypt_compl_lock; + int async_notify; + u8 async_capable:1; + +@@ -155,6 +157,8 @@ struct tls_sw_context_rx { + u8 async_capable:1; + u8 decrypted:1; + atomic_t decrypt_pending; ++ /* protect crypto_wait with decrypt_pending*/ ++ spinlock_t decrypt_compl_lock; + bool async_notify; + }; + +diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h +index 1b28ce1aba07..325fdaa3bb66 100644 +--- a/include/rdma/uverbs_std_types.h ++++ b/include/rdma/uverbs_std_types.h +@@ -88,7 +88,7 @@ struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj, + + static inline void uobj_put_destroy(struct ib_uobject *uobj) + { +- rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE); ++ rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_DESTROY); + } + + static inline void uobj_put_read(struct ib_uobject *uobj) +diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h +index 5f3b9fec7b5f..ff7cfdc6cb44 100644 +--- a/include/uapi/linux/xfrm.h ++++ b/include/uapi/linux/xfrm.h +@@ -304,7 +304,7 @@ enum xfrm_attr_type_t { + XFRMA_PROTO, /* __u8 */ + XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ + XFRMA_PAD, +- XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */ ++ XFRMA_OFFLOAD_DEV, /* struct xfrm_user_offload */ + XFRMA_SET_MARK, /* __u32 */ + XFRMA_SET_MARK_MASK, /* __u32 */ + XFRMA_IF_ID, /* __u32 */ +diff --git a/mm/khugepaged.c b/mm/khugepaged.c +index b679908743cb..ba059e68cf50 100644 +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1673,6 +1673,7 @@ static void collapse_file(struct mm_struct *mm, + if (page_has_private(page) && + !try_to_release_page(page, GFP_KERNEL)) { + result = SCAN_PAGE_HAS_PRIVATE; ++ putback_lru_page(page); + goto out_unlock; + } + +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index ff57ea89c27e..fd91cd34f25e 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -635,8 +635,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + break; + + case SO_BINDTODEVICE: +- if (optlen > IFNAMSIZ) +- optlen = IFNAMSIZ; ++ if (optlen > IFNAMSIZ - 1) ++ optlen = IFNAMSIZ - 1; ++ ++ memset(devname, 0, sizeof(devname)); + + if (copy_from_user(devname, optval, optlen)) { + res = -EFAULT; +diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c +index b325b569e761..f48cf4cfb80f 100644 +--- a/net/bridge/netfilter/nft_reject_bridge.c ++++ b/net/bridge/netfilter/nft_reject_bridge.c +@@ -31,6 +31,12 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, + ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source); + eth->h_proto = eth_hdr(oldskb)->h_proto; + skb_pull(nskb, ETH_HLEN); ++ ++ if (skb_vlan_tag_present(oldskb)) { ++ u16 vid = skb_vlan_tag_get(oldskb); ++ ++ __vlan_hwaccel_put_tag(nskb, oldskb->vlan_proto, vid); ++ } + } + + static int nft_bridge_iphdr_validate(struct sk_buff *skb) +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index af868d3923b9..834019dbc6b1 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -3652,7 +3652,9 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg) + * supported. + */ + req->r_t.target_oloc.pool = m.redirect.oloc.pool; +- req->r_flags |= CEPH_OSD_FLAG_REDIRECTED; ++ req->r_flags |= CEPH_OSD_FLAG_REDIRECTED | ++ CEPH_OSD_FLAG_IGNORE_OVERLAY | ++ CEPH_OSD_FLAG_IGNORE_CACHE; + req->r_tid = 0; + __submit_request(req, false); + goto out_unlock_osdc; +diff --git a/net/core/dev.c b/net/core/dev.c +index c7047b40f569..87fd5424e205 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4988,11 +4988,12 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev, + return 0; + } + +-static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc, ++static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc, + struct packet_type **ppt_prev) + { + struct packet_type *ptype, *pt_prev; + rx_handler_func_t *rx_handler; ++ struct sk_buff *skb = *pskb; + struct net_device *orig_dev; + bool deliver_exact = false; + int ret = NET_RX_DROP; +@@ -5023,8 +5024,10 @@ another_round: + ret2 = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb); + preempt_enable(); + +- if (ret2 != XDP_PASS) +- return NET_RX_DROP; ++ if (ret2 != XDP_PASS) { ++ ret = NET_RX_DROP; ++ goto out; ++ } + skb_reset_mac_len(skb); + } + +@@ -5174,6 +5177,13 @@ drop: + } + + out: ++ /* The invariant here is that if *ppt_prev is not NULL ++ * then skb should also be non-NULL. ++ * ++ * Apparently *ppt_prev assignment above holds this invariant due to ++ * skb dereferencing near it. ++ */ ++ *pskb = skb; + return ret; + } + +@@ -5183,7 +5193,7 @@ static int __netif_receive_skb_one_core(struct sk_buff *skb, bool pfmemalloc) + struct packet_type *pt_prev = NULL; + int ret; + +- ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev); ++ ret = __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev); + if (pt_prev) + ret = INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb, + skb->dev, pt_prev, orig_dev); +@@ -5261,7 +5271,7 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo + struct packet_type *pt_prev = NULL; + + skb_list_del_init(skb); +- __netif_receive_skb_core(skb, pfmemalloc, &pt_prev); ++ __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev); + if (!pt_prev) + continue; + if (pt_curr != pt_prev || od_curr != orig_dev) { +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index ddc0f9236928..e2a3d198e8f5 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1393,6 +1393,7 @@ int dsa_slave_create(struct dsa_port *port) + if (ds->ops->port_vlan_add && ds->ops->port_vlan_del) + slave_dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + slave_dev->hw_features |= NETIF_F_HW_TC; ++ slave_dev->features |= NETIF_F_LLTX; + slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; + if (!IS_ERR_OR_NULL(port->mac)) + ether_addr_copy(slave_dev->dev_addr, port->mac); +diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c +index b5705cba8318..d6619edd53e5 100644 +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -15,6 +15,7 @@ + #define MTK_HDR_XMIT_TAGGED_TPID_8100 1 + #define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) + #define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0) ++#define MTK_HDR_XMIT_SA_DIS BIT(6) + + static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + struct net_device *dev) +@@ -22,6 +23,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + struct dsa_port *dp = dsa_slave_to_port(dev); + u8 *mtk_tag; + bool is_vlan_skb = true; ++ unsigned char *dest = eth_hdr(skb)->h_dest; ++ bool is_multicast_skb = is_multicast_ether_addr(dest) && ++ !is_broadcast_ether_addr(dest); + + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is +@@ -47,6 +51,10 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + MTK_HDR_XMIT_UNTAGGED; + mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; + ++ /* Disable SA learning for multicast frames */ ++ if (unlikely(is_multicast_skb)) ++ mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS; ++ + /* Tag control information is kept for 802.1Q */ + if (!is_vlan_skb) { + mtk_tag[2] = 0; +@@ -61,6 +69,9 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev, + { + int port; + __be16 *phdr, hdr; ++ unsigned char *dest = eth_hdr(skb)->h_dest; ++ bool is_multicast_skb = is_multicast_ether_addr(dest) && ++ !is_broadcast_ether_addr(dest); + + if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) + return NULL; +@@ -86,6 +97,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev, + if (!skb->dev) + return NULL; + ++ /* Only unicast or broadcast frames are offloaded */ ++ if (likely(!is_multicast_skb)) ++ skb->offload_fwd_mark = 1; ++ + return skb; + } + +diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c +index fc9e0b806889..d863dffbe53c 100644 +--- a/net/ethtool/netlink.c ++++ b/net/ethtool/netlink.c +@@ -334,7 +334,7 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) + ret = ops->reply_size(req_info, reply_data); + if (ret < 0) + goto err_cleanup; +- reply_len = ret; ++ reply_len = ret + ethnl_reply_header_size(); + ret = -ENOMEM; + rskb = ethnl_reply_init(reply_len, req_info->dev, ops->reply_cmd, + ops->hdr_attr, info, &reply_payload); +@@ -573,7 +573,7 @@ static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, + ret = ops->reply_size(req_info, reply_data); + if (ret < 0) + goto err_cleanup; +- reply_len = ret; ++ reply_len = ret + ethnl_reply_header_size(); + ret = -ENOMEM; + skb = genlmsg_new(reply_len, GFP_KERNEL); + if (!skb) +diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c +index 8e5911887b4c..fb7b3585458d 100644 +--- a/net/ethtool/strset.c ++++ b/net/ethtool/strset.c +@@ -309,7 +309,6 @@ static int strset_reply_size(const struct ethnl_req_info *req_base, + int len = 0; + int ret; + +- len += ethnl_reply_header_size(); + for (i = 0; i < ETH_SS_COUNT; i++) { + const struct strset_info *set_info = &data->sets[i]; + +diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c +index e2e219c7854a..25c8ba6732df 100644 +--- a/net/ipv4/esp4_offload.c ++++ b/net/ipv4/esp4_offload.c +@@ -63,10 +63,8 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head, + sp->olen++; + + xo = xfrm_offload(skb); +- if (!xo) { +- xfrm_state_put(x); ++ if (!xo) + goto out_reset; +- } + } + + xo->flags |= XFRM_GRO; +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 213be9c050ad..41079490a118 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -309,17 +309,18 @@ bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev) + { + bool dev_match = false; + #ifdef CONFIG_IP_ROUTE_MULTIPATH +- int ret; ++ if (unlikely(fi->nh)) { ++ dev_match = nexthop_uses_dev(fi->nh, dev); ++ } else { ++ int ret; + +- for (ret = 0; ret < fib_info_num_path(fi); ret++) { +- const struct fib_nh_common *nhc = fib_info_nhc(fi, ret); ++ for (ret = 0; ret < fib_info_num_path(fi); ret++) { ++ const struct fib_nh_common *nhc = fib_info_nhc(fi, ret); + +- if (nhc->nhc_dev == dev) { +- dev_match = true; +- break; +- } else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) { +- dev_match = true; +- break; ++ if (nhc_l3mdev_matches_dev(nhc, dev)) { ++ dev_match = true; ++ break; ++ } + } + } + #else +@@ -918,7 +919,6 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + else + filter->dump_exceptions = false; + +- filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC); + filter->flags = rtm->rtm_flags; + filter->protocol = rtm->rtm_protocol; + filter->rt_type = rtm->rtm_type; +@@ -990,7 +990,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) + if (filter.table_id) { + tb = fib_get_table(net, filter.table_id); + if (!tb) { +- if (filter.dump_all_families) ++ if (rtnl_msg_family(cb->nlh) != PF_INET) + return skb->len; + + NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist"); +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index d545fb99a8a1..76afe93904d5 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -24,17 +24,19 @@ + #include + + #if IS_ENABLED(CONFIG_IPV6) +-/* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6 +- * only, and any IPv4 addresses if not IPv6 only +- * match_wildcard == false: addresses must be exactly the same, i.e. +- * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY, +- * and 0.0.0.0 equals to 0.0.0.0 only ++/* match_sk*_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses ++ * if IPv6 only, and any IPv4 addresses ++ * if not IPv6 only ++ * match_sk*_wildcard == false: addresses must be exactly the same, i.e. ++ * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY, ++ * and 0.0.0.0 equals to 0.0.0.0 only + */ + static bool ipv6_rcv_saddr_equal(const struct in6_addr *sk1_rcv_saddr6, + const struct in6_addr *sk2_rcv_saddr6, + __be32 sk1_rcv_saddr, __be32 sk2_rcv_saddr, + bool sk1_ipv6only, bool sk2_ipv6only, +- bool match_wildcard) ++ bool match_sk1_wildcard, ++ bool match_sk2_wildcard) + { + int addr_type = ipv6_addr_type(sk1_rcv_saddr6); + int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; +@@ -44,8 +46,8 @@ static bool ipv6_rcv_saddr_equal(const struct in6_addr *sk1_rcv_saddr6, + if (!sk2_ipv6only) { + if (sk1_rcv_saddr == sk2_rcv_saddr) + return true; +- if (!sk1_rcv_saddr || !sk2_rcv_saddr) +- return match_wildcard; ++ return (match_sk1_wildcard && !sk1_rcv_saddr) || ++ (match_sk2_wildcard && !sk2_rcv_saddr); + } + return false; + } +@@ -53,11 +55,11 @@ static bool ipv6_rcv_saddr_equal(const struct in6_addr *sk1_rcv_saddr6, + if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY) + return true; + +- if (addr_type2 == IPV6_ADDR_ANY && match_wildcard && ++ if (addr_type2 == IPV6_ADDR_ANY && match_sk2_wildcard && + !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) + return true; + +- if (addr_type == IPV6_ADDR_ANY && match_wildcard && ++ if (addr_type == IPV6_ADDR_ANY && match_sk1_wildcard && + !(sk1_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) + return true; + +@@ -69,18 +71,19 @@ static bool ipv6_rcv_saddr_equal(const struct in6_addr *sk1_rcv_saddr6, + } + #endif + +-/* match_wildcard == true: 0.0.0.0 equals to any IPv4 addresses +- * match_wildcard == false: addresses must be exactly the same, i.e. +- * 0.0.0.0 only equals to 0.0.0.0 ++/* match_sk*_wildcard == true: 0.0.0.0 equals to any IPv4 addresses ++ * match_sk*_wildcard == false: addresses must be exactly the same, i.e. ++ * 0.0.0.0 only equals to 0.0.0.0 + */ + static bool ipv4_rcv_saddr_equal(__be32 sk1_rcv_saddr, __be32 sk2_rcv_saddr, +- bool sk2_ipv6only, bool match_wildcard) ++ bool sk2_ipv6only, bool match_sk1_wildcard, ++ bool match_sk2_wildcard) + { + if (!sk2_ipv6only) { + if (sk1_rcv_saddr == sk2_rcv_saddr) + return true; +- if (!sk1_rcv_saddr || !sk2_rcv_saddr) +- return match_wildcard; ++ return (match_sk1_wildcard && !sk1_rcv_saddr) || ++ (match_sk2_wildcard && !sk2_rcv_saddr); + } + return false; + } +@@ -96,10 +99,12 @@ bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, + sk2->sk_rcv_saddr, + ipv6_only_sock(sk), + ipv6_only_sock(sk2), ++ match_wildcard, + match_wildcard); + #endif + return ipv4_rcv_saddr_equal(sk->sk_rcv_saddr, sk2->sk_rcv_saddr, +- ipv6_only_sock(sk2), match_wildcard); ++ ipv6_only_sock(sk2), match_wildcard, ++ match_wildcard); + } + EXPORT_SYMBOL(inet_rcv_saddr_equal); + +@@ -273,10 +278,10 @@ static inline int sk_reuseport_match(struct inet_bind_bucket *tb, + tb->fast_rcv_saddr, + sk->sk_rcv_saddr, + tb->fast_ipv6_only, +- ipv6_only_sock(sk), true); ++ ipv6_only_sock(sk), true, false); + #endif + return ipv4_rcv_saddr_equal(tb->fast_rcv_saddr, sk->sk_rcv_saddr, +- ipv6_only_sock(sk), true); ++ ipv6_only_sock(sk), true, false); + } + + /* Obtain a reference to a local port for the given sock, +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index 1b4e6f298648..1dda7c155c48 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -93,7 +93,28 @@ static int vti_rcv_proto(struct sk_buff *skb) + + static int vti_rcv_tunnel(struct sk_buff *skb) + { +- return vti_rcv(skb, ip_hdr(skb)->saddr, true); ++ struct ip_tunnel_net *itn = net_generic(dev_net(skb->dev), vti_net_id); ++ const struct iphdr *iph = ip_hdr(skb); ++ struct ip_tunnel *tunnel; ++ ++ tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, ++ iph->saddr, iph->daddr, 0); ++ if (tunnel) { ++ struct tnl_ptk_info tpi = { ++ .proto = htons(ETH_P_IP), ++ }; ++ ++ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) ++ goto drop; ++ if (iptunnel_pull_header(skb, 0, tpi.proto, false)) ++ goto drop; ++ return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, false); ++ } ++ ++ return -EINVAL; ++drop: ++ kfree_skb(skb); ++ return 0; + } + + static int vti_rcv_cb(struct sk_buff *skb, int err) +diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c +index 2f01cf6fa0de..678575adaf3b 100644 +--- a/net/ipv4/ipip.c ++++ b/net/ipv4/ipip.c +@@ -698,7 +698,7 @@ out: + + rtnl_link_failed: + #if IS_ENABLED(CONFIG_MPLS) +- xfrm4_tunnel_deregister(&mplsip_handler, AF_INET); ++ xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS); + xfrm_tunnel_mplsip_failed: + + #endif +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 6e68def66822..2508b4c37af3 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -2611,7 +2611,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) + + mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id); + if (!mrt) { +- if (filter.dump_all_families) ++ if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR) + return skb->len; + + NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist"); +diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c +index b2aeb7bf5dac..2a1e10f4ae93 100644 +--- a/net/ipv4/netfilter/nf_nat_pptp.c ++++ b/net/ipv4/netfilter/nf_nat_pptp.c +@@ -166,8 +166,7 @@ pptp_outbound_pkt(struct sk_buff *skb, + break; + default: + pr_debug("unknown outbound packet 0x%04x:%s\n", msg, +- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : +- pptp_msg_name[0]); ++ pptp_msg_name(msg)); + /* fall through */ + case PPTP_SET_LINK_INFO: + /* only need to NAT in case PAC is behind NAT box */ +@@ -268,9 +267,7 @@ pptp_inbound_pkt(struct sk_buff *skb, + pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); + break; + default: +- pr_debug("unknown inbound packet %s\n", +- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : +- pptp_msg_name[0]); ++ pr_debug("unknown inbound packet %s\n", pptp_msg_name(msg)); + /* fall through */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index d072c326dd64..b6ecb30544f6 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -63,9 +63,16 @@ static void nexthop_free_mpath(struct nexthop *nh) + int i; + + nhg = rcu_dereference_raw(nh->nh_grp); +- for (i = 0; i < nhg->num_nh; ++i) +- WARN_ON(nhg->nh_entries[i].nh); ++ for (i = 0; i < nhg->num_nh; ++i) { ++ struct nh_grp_entry *nhge = &nhg->nh_entries[i]; ++ ++ WARN_ON(!list_empty(&nhge->nh_list)); ++ nexthop_put(nhge->nh); ++ } ++ ++ WARN_ON(nhg->spare == nhg); + ++ kfree(nhg->spare); + kfree(nhg); + } + +@@ -276,6 +283,7 @@ out: + return 0; + + nla_put_failure: ++ nlmsg_cancel(skb, nlh); + return -EMSGSIZE; + } + +@@ -433,7 +441,7 @@ static int nh_check_attr_group(struct net *net, struct nlattr *tb[], + if (!valid_group_nh(nh, len, extack)) + return -EINVAL; + } +- for (i = NHA_GROUP + 1; i < __NHA_MAX; ++i) { ++ for (i = NHA_GROUP_TYPE + 1; i < __NHA_MAX; ++i) { + if (!tb[i]) + continue; + +@@ -693,41 +701,56 @@ static void nh_group_rebalance(struct nh_group *nhg) + } + } + +-static void remove_nh_grp_entry(struct nh_grp_entry *nhge, +- struct nh_group *nhg, ++static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge, + struct nl_info *nlinfo) + { ++ struct nh_grp_entry *nhges, *new_nhges; ++ struct nexthop *nhp = nhge->nh_parent; + struct nexthop *nh = nhge->nh; +- struct nh_grp_entry *nhges; +- bool found = false; +- int i; ++ struct nh_group *nhg, *newg; ++ int i, j; + + WARN_ON(!nh); + +- nhges = nhg->nh_entries; +- for (i = 0; i < nhg->num_nh; ++i) { +- if (found) { +- nhges[i-1].nh = nhges[i].nh; +- nhges[i-1].weight = nhges[i].weight; +- list_del(&nhges[i].nh_list); +- list_add(&nhges[i-1].nh_list, &nhges[i-1].nh->grp_list); +- } else if (nhg->nh_entries[i].nh == nh) { +- found = true; +- } +- } ++ nhg = rtnl_dereference(nhp->nh_grp); ++ newg = nhg->spare; + +- if (WARN_ON(!found)) ++ /* last entry, keep it visible and remove the parent */ ++ if (nhg->num_nh == 1) { ++ remove_nexthop(net, nhp, nlinfo); + return; ++ } ++ ++ newg->has_v4 = nhg->has_v4; ++ newg->mpath = nhg->mpath; ++ newg->num_nh = nhg->num_nh; + +- nhg->num_nh--; +- nhg->nh_entries[nhg->num_nh].nh = NULL; ++ /* copy old entries to new except the one getting removed */ ++ nhges = nhg->nh_entries; ++ new_nhges = newg->nh_entries; ++ for (i = 0, j = 0; i < nhg->num_nh; ++i) { ++ /* current nexthop getting removed */ ++ if (nhg->nh_entries[i].nh == nh) { ++ newg->num_nh--; ++ continue; ++ } + +- nh_group_rebalance(nhg); ++ list_del(&nhges[i].nh_list); ++ new_nhges[j].nh_parent = nhges[i].nh_parent; ++ new_nhges[j].nh = nhges[i].nh; ++ new_nhges[j].weight = nhges[i].weight; ++ list_add(&new_nhges[j].nh_list, &new_nhges[j].nh->grp_list); ++ j++; ++ } + +- nexthop_put(nh); ++ nh_group_rebalance(newg); ++ rcu_assign_pointer(nhp->nh_grp, newg); ++ ++ list_del(&nhge->nh_list); ++ nexthop_put(nhge->nh); + + if (nlinfo) +- nexthop_notify(RTM_NEWNEXTHOP, nhge->nh_parent, nlinfo); ++ nexthop_notify(RTM_NEWNEXTHOP, nhp, nlinfo); + } + + static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, +@@ -735,17 +758,11 @@ static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, + { + struct nh_grp_entry *nhge, *tmp; + +- list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) { +- struct nh_group *nhg; +- +- list_del(&nhge->nh_list); +- nhg = rtnl_dereference(nhge->nh_parent->nh_grp); +- remove_nh_grp_entry(nhge, nhg, nlinfo); ++ list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) ++ remove_nh_grp_entry(net, nhge, nlinfo); + +- /* if this group has no more entries then remove it */ +- if (!nhg->num_nh) +- remove_nexthop(net, nhge->nh_parent, nlinfo); +- } ++ /* make sure all see the newly published array before releasing rtnl */ ++ synchronize_rcu(); + } + + static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo) +@@ -759,10 +776,7 @@ static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo) + if (WARN_ON(!nhge->nh)) + continue; + +- list_del(&nhge->nh_list); +- nexthop_put(nhge->nh); +- nhge->nh = NULL; +- nhg->num_nh--; ++ list_del_init(&nhge->nh_list); + } + } + +@@ -1085,6 +1099,7 @@ static struct nexthop *nexthop_create_group(struct net *net, + { + struct nlattr *grps_attr = cfg->nh_grp; + struct nexthop_grp *entry = nla_data(grps_attr); ++ u16 num_nh = nla_len(grps_attr) / sizeof(*entry); + struct nh_group *nhg; + struct nexthop *nh; + int i; +@@ -1095,12 +1110,21 @@ static struct nexthop *nexthop_create_group(struct net *net, + + nh->is_group = 1; + +- nhg = nexthop_grp_alloc(nla_len(grps_attr) / sizeof(*entry)); ++ nhg = nexthop_grp_alloc(num_nh); + if (!nhg) { + kfree(nh); + return ERR_PTR(-ENOMEM); + } + ++ /* spare group used for removals */ ++ nhg->spare = nexthop_grp_alloc(num_nh); ++ if (!nhg) { ++ kfree(nhg); ++ kfree(nh); ++ return NULL; ++ } ++ nhg->spare->spare = nhg; ++ + for (i = 0; i < nhg->num_nh; ++i) { + struct nexthop *nhe; + struct nh_info *nhi; +@@ -1132,6 +1156,7 @@ out_no_nh: + for (; i >= 0; --i) + nexthop_put(nhg->nh_entries[i].nh); + ++ kfree(nhg->spare); + kfree(nhg); + kfree(nh); + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index ef6b70774fe1..fea6a8a11183 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -491,18 +491,16 @@ u32 ip_idents_reserve(u32 hash, int segs) + atomic_t *p_id = ip_idents + hash % IP_IDENTS_SZ; + u32 old = READ_ONCE(*p_tstamp); + u32 now = (u32)jiffies; +- u32 new, delta = 0; ++ u32 delta = 0; + + if (old != now && cmpxchg(p_tstamp, old, now) == old) + delta = prandom_u32_max(now - old); + +- /* Do not use atomic_add_return() as it makes UBSAN unhappy */ +- do { +- old = (u32)atomic_read(p_id); +- new = old + delta + segs; +- } while (atomic_cmpxchg(p_id, old, new) != old); +- +- return new - segs; ++ /* If UBSAN reports an error there, please make sure your compiler ++ * supports -fno-strict-overflow before reporting it that was a bug ++ * in UBSAN, and it has been fixed in GCC-8. ++ */ ++ return atomic_add_return(segs + delta, p_id) - segs; + } + EXPORT_SYMBOL(ip_idents_reserve); + +diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c +index fd535053245b..93e086cf058a 100644 +--- a/net/ipv6/esp6_offload.c ++++ b/net/ipv6/esp6_offload.c +@@ -85,10 +85,8 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head, + sp->olen++; + + xo = xfrm_offload(skb); +- if (!xo) { +- xfrm_state_put(x); ++ if (!xo) + goto out_reset; +- } + } + + xo->flags |= XFRM_GRO; +@@ -123,9 +121,16 @@ static void esp6_gso_encap(struct xfrm_state *x, struct sk_buff *skb) + struct ip_esp_hdr *esph; + struct ipv6hdr *iph = ipv6_hdr(skb); + struct xfrm_offload *xo = xfrm_offload(skb); +- int proto = iph->nexthdr; ++ u8 proto = iph->nexthdr; + + skb_push(skb, -skb_network_offset(skb)); ++ ++ if (x->outer_mode.encap == XFRM_MODE_TRANSPORT) { ++ __be16 frag; ++ ++ ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &proto, &frag); ++ } ++ + esph = ip_esp_hdr(skb); + *skb_mac_header(skb) = IPPROTO_ESP; + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 72abf892302f..9a53590ef79c 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -664,7 +664,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) + if (arg.filter.table_id) { + tb = fib6_get_table(net, arg.filter.table_id); + if (!tb) { +- if (arg.filter.dump_all_families) ++ if (rtnl_msg_family(cb->nlh) != PF_INET6) + goto out; + + NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist"); +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index bfa49ff70531..2ddb7c513e54 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -2501,7 +2501,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) + + mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id); + if (!mrt) { +- if (filter.dump_all_families) ++ if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR) + return skb->len; + + NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist"); +diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c +index 38a0383dfbcf..aa5150929996 100644 +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -1103,7 +1103,14 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) + mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn, + target_flags, mpath->dst, mpath->sn, da, 0, + ttl, lifetime, 0, ifmsh->preq_id++, sdata); ++ ++ spin_lock_bh(&mpath->state_lock); ++ if (mpath->flags & MESH_PATH_DELETED) { ++ spin_unlock_bh(&mpath->state_lock); ++ goto enddiscovery; ++ } + mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); ++ spin_unlock_bh(&mpath->state_lock); + + enddiscovery: + rcu_read_unlock(); +diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c +index cd747c0962fd..5a67f7966574 100644 +--- a/net/netfilter/ipset/ip_set_list_set.c ++++ b/net/netfilter/ipset/ip_set_list_set.c +@@ -59,7 +59,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, + /* Don't lookup sub-counters at all */ + opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS; + if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) +- opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; ++ opt->cmdflags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; + list_for_each_entry_rcu(e, &map->members, list) { + ret = ip_set_test(e->id, skb, par, opt); + if (ret <= 0) +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index d11a58348133..7c503b4751c4 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -2014,22 +2014,18 @@ static void nf_conntrack_attach(struct sk_buff *nskb, const struct sk_buff *skb) + nf_conntrack_get(skb_nfct(nskb)); + } + +-static int nf_conntrack_update(struct net *net, struct sk_buff *skb) ++static int __nf_conntrack_update(struct net *net, struct sk_buff *skb, ++ struct nf_conn *ct, ++ enum ip_conntrack_info ctinfo) + { + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; +- enum ip_conntrack_info ctinfo; + struct nf_nat_hook *nat_hook; + unsigned int status; +- struct nf_conn *ct; + int dataoff; + u16 l3num; + u8 l4num; + +- ct = nf_ct_get(skb, &ctinfo); +- if (!ct || nf_ct_is_confirmed(ct)) +- return 0; +- + l3num = nf_ct_l3num(ct); + + dataoff = get_l4proto(skb, skb_network_offset(skb), l3num, &l4num); +@@ -2086,6 +2082,76 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb) + return 0; + } + ++/* This packet is coming from userspace via nf_queue, complete the packet ++ * processing after the helper invocation in nf_confirm(). ++ */ ++static int nf_confirm_cthelper(struct sk_buff *skb, struct nf_conn *ct, ++ enum ip_conntrack_info ctinfo) ++{ ++ const struct nf_conntrack_helper *helper; ++ const struct nf_conn_help *help; ++ int protoff; ++ ++ help = nfct_help(ct); ++ if (!help) ++ return 0; ++ ++ helper = rcu_dereference(help->helper); ++ if (!(helper->flags & NF_CT_HELPER_F_USERSPACE)) ++ return 0; ++ ++ switch (nf_ct_l3num(ct)) { ++ case NFPROTO_IPV4: ++ protoff = skb_network_offset(skb) + ip_hdrlen(skb); ++ break; ++#if IS_ENABLED(CONFIG_IPV6) ++ case NFPROTO_IPV6: { ++ __be16 frag_off; ++ u8 pnum; ++ ++ pnum = ipv6_hdr(skb)->nexthdr; ++ protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum, ++ &frag_off); ++ if (protoff < 0 || (frag_off & htons(~0x7)) != 0) ++ return 0; ++ break; ++ } ++#endif ++ default: ++ return 0; ++ } ++ ++ if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && ++ !nf_is_loopback_packet(skb)) { ++ if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) { ++ NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); ++ return -1; ++ } ++ } ++ ++ /* We've seen it coming out the other side: confirm it */ ++ return nf_conntrack_confirm(skb) == NF_DROP ? - 1 : 0; ++} ++ ++static int nf_conntrack_update(struct net *net, struct sk_buff *skb) ++{ ++ enum ip_conntrack_info ctinfo; ++ struct nf_conn *ct; ++ int err; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (!ct) ++ return 0; ++ ++ if (!nf_ct_is_confirmed(ct)) { ++ err = __nf_conntrack_update(net, skb, ct, ctinfo); ++ if (err < 0) ++ return err; ++ } ++ ++ return nf_confirm_cthelper(skb, ct, ctinfo); ++} ++ + static bool nf_conntrack_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple, + const struct sk_buff *skb) + { +diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c +index a971183f11af..1f44d523b512 100644 +--- a/net/netfilter/nf_conntrack_pptp.c ++++ b/net/netfilter/nf_conntrack_pptp.c +@@ -72,24 +72,32 @@ EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); + + #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) + /* PptpControlMessageType names */ +-const char *const pptp_msg_name[] = { +- "UNKNOWN_MESSAGE", +- "START_SESSION_REQUEST", +- "START_SESSION_REPLY", +- "STOP_SESSION_REQUEST", +- "STOP_SESSION_REPLY", +- "ECHO_REQUEST", +- "ECHO_REPLY", +- "OUT_CALL_REQUEST", +- "OUT_CALL_REPLY", +- "IN_CALL_REQUEST", +- "IN_CALL_REPLY", +- "IN_CALL_CONNECT", +- "CALL_CLEAR_REQUEST", +- "CALL_DISCONNECT_NOTIFY", +- "WAN_ERROR_NOTIFY", +- "SET_LINK_INFO" ++static const char *const pptp_msg_name_array[PPTP_MSG_MAX + 1] = { ++ [0] = "UNKNOWN_MESSAGE", ++ [PPTP_START_SESSION_REQUEST] = "START_SESSION_REQUEST", ++ [PPTP_START_SESSION_REPLY] = "START_SESSION_REPLY", ++ [PPTP_STOP_SESSION_REQUEST] = "STOP_SESSION_REQUEST", ++ [PPTP_STOP_SESSION_REPLY] = "STOP_SESSION_REPLY", ++ [PPTP_ECHO_REQUEST] = "ECHO_REQUEST", ++ [PPTP_ECHO_REPLY] = "ECHO_REPLY", ++ [PPTP_OUT_CALL_REQUEST] = "OUT_CALL_REQUEST", ++ [PPTP_OUT_CALL_REPLY] = "OUT_CALL_REPLY", ++ [PPTP_IN_CALL_REQUEST] = "IN_CALL_REQUEST", ++ [PPTP_IN_CALL_REPLY] = "IN_CALL_REPLY", ++ [PPTP_IN_CALL_CONNECT] = "IN_CALL_CONNECT", ++ [PPTP_CALL_CLEAR_REQUEST] = "CALL_CLEAR_REQUEST", ++ [PPTP_CALL_DISCONNECT_NOTIFY] = "CALL_DISCONNECT_NOTIFY", ++ [PPTP_WAN_ERROR_NOTIFY] = "WAN_ERROR_NOTIFY", ++ [PPTP_SET_LINK_INFO] = "SET_LINK_INFO" + }; ++ ++const char *pptp_msg_name(u_int16_t msg) ++{ ++ if (msg > PPTP_MSG_MAX) ++ return pptp_msg_name_array[0]; ++ ++ return pptp_msg_name_array[msg]; ++} + EXPORT_SYMBOL(pptp_msg_name); + #endif + +@@ -276,7 +284,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; + + msg = ntohs(ctlh->messageType); +- pr_debug("inbound control message %s\n", pptp_msg_name[msg]); ++ pr_debug("inbound control message %s\n", pptp_msg_name(msg)); + + switch (msg) { + case PPTP_START_SESSION_REPLY: +@@ -311,7 +319,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + pcid = pptpReq->ocack.peersCallID; + if (info->pns_call_id != pcid) + goto invalid; +- pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], ++ pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name(msg), + ntohs(cid), ntohs(pcid)); + + if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { +@@ -328,7 +336,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + goto invalid; + + cid = pptpReq->icreq.callID; +- pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); ++ pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); + info->cstate = PPTP_CALL_IN_REQ; + info->pac_call_id = cid; + break; +@@ -347,7 +355,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + if (info->pns_call_id != pcid) + goto invalid; + +- pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); ++ pr_debug("%s, PCID=%X\n", pptp_msg_name(msg), ntohs(pcid)); + info->cstate = PPTP_CALL_IN_CONF; + + /* we expect a GRE connection from PAC to PNS */ +@@ -357,7 +365,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + case PPTP_CALL_DISCONNECT_NOTIFY: + /* server confirms disconnect */ + cid = pptpReq->disc.callID; +- pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); ++ pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ +@@ -384,7 +392,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, + invalid: + pr_debug("invalid %s: type=%d cid=%u pcid=%u " + "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", +- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], ++ pptp_msg_name(msg), + msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, + ntohs(info->pns_call_id), ntohs(info->pac_call_id)); + return NF_ACCEPT; +@@ -404,7 +412,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, + typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; + + msg = ntohs(ctlh->messageType); +- pr_debug("outbound control message %s\n", pptp_msg_name[msg]); ++ pr_debug("outbound control message %s\n", pptp_msg_name(msg)); + + switch (msg) { + case PPTP_START_SESSION_REQUEST: +@@ -426,7 +434,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, + info->cstate = PPTP_CALL_OUT_REQ; + /* track PNS call id */ + cid = pptpReq->ocreq.callID; +- pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); ++ pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); + info->pns_call_id = cid; + break; + +@@ -440,7 +448,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, + pcid = pptpReq->icack.peersCallID; + if (info->pac_call_id != pcid) + goto invalid; +- pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], ++ pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name(msg), + ntohs(cid), ntohs(pcid)); + + if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { +@@ -480,7 +488,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, + invalid: + pr_debug("invalid %s: type=%d cid=%u pcid=%u " + "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", +- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], ++ pptp_msg_name(msg), + msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, + ntohs(info->pns_call_id), ntohs(info->pac_call_id)); + return NF_ACCEPT; +diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c +index a5f294aa8e4c..5b0d0a77379c 100644 +--- a/net/netfilter/nfnetlink_cthelper.c ++++ b/net/netfilter/nfnetlink_cthelper.c +@@ -103,7 +103,7 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + if (help->helper->data_len == 0) + return -EINVAL; + +- nla_memcpy(help->data, nla_data(attr), sizeof(help->data)); ++ nla_memcpy(help->data, attr, sizeof(help->data)); + return 0; + } + +@@ -240,6 +240,7 @@ nfnl_cthelper_create(const struct nlattr * const tb[], + ret = -ENOMEM; + goto err2; + } ++ helper->data_len = size; + + helper->flags |= NF_CT_HELPER_F_USERSPACE; + memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple)); +diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c +index b7b854621c26..9d38c14d251a 100644 +--- a/net/qrtr/qrtr.c ++++ b/net/qrtr/qrtr.c +@@ -855,7 +855,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, + } + mutex_unlock(&qrtr_node_lock); + +- qrtr_local_enqueue(node, skb, type, from, to); ++ qrtr_local_enqueue(NULL, skb, type, from, to); + + return 0; + } +diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c +index 2bc29463e1dc..9f36fe911d08 100644 +--- a/net/sctp/sm_sideeffect.c ++++ b/net/sctp/sm_sideeffect.c +@@ -1523,9 +1523,17 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type, + timeout = asoc->timeouts[cmd->obj.to]; + BUG_ON(!timeout); + +- timer->expires = jiffies + timeout; +- sctp_association_hold(asoc); +- add_timer(timer); ++ /* ++ * SCTP has a hard time with timer starts. Because we process ++ * timer starts as side effects, it can be hard to tell if we ++ * have already started a timer or not, which leads to BUG ++ * halts when we call add_timer. So here, instead of just starting ++ * a timer, if the timer is already started, and just mod ++ * the timer with the shorter of the two expiration times ++ */ ++ if (!timer_pending(timer)) ++ sctp_association_hold(asoc); ++ timer_reduce(timer, jiffies + timeout); + break; + + case SCTP_CMD_TIMER_RESTART: +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 26788f4a3b9e..e86620fbd90f 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -1856,12 +1856,13 @@ static enum sctp_disposition sctp_sf_do_dupcook_a( + /* Update the content of current association. */ + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); +- if (sctp_state(asoc, SHUTDOWN_PENDING) && ++ if ((sctp_state(asoc, SHUTDOWN_PENDING) || ++ sctp_state(asoc, SHUTDOWN_SENT)) && + (sctp_sstate(asoc->base.sk, CLOSING) || + sock_flag(asoc->base.sk, SOCK_DEAD))) { +- /* if were currently in SHUTDOWN_PENDING, but the socket +- * has been closed by user, don't transition to ESTABLISHED. +- * Instead trigger SHUTDOWN bundled with COOKIE_ACK. ++ /* If the socket has been closed by user, don't ++ * transition to ESTABLISHED. Instead trigger SHUTDOWN ++ * bundled with COOKIE_ACK. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); + return sctp_sf_do_9_2_start_shutdown(net, ep, asoc, +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index d6620ad53546..28a283f26a8d 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -161,9 +161,11 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, + struct udp_bearer *ub, struct udp_media_addr *src, + struct udp_media_addr *dst, struct dst_cache *cache) + { +- struct dst_entry *ndst = dst_cache_get(cache); ++ struct dst_entry *ndst; + int ttl, err = 0; + ++ local_bh_disable(); ++ ndst = dst_cache_get(cache); + if (dst->proto == htons(ETH_P_IP)) { + struct rtable *rt = (struct rtable *)ndst; + +@@ -210,9 +212,11 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, + src->port, dst->port, false); + #endif + } ++ local_bh_enable(); + return err; + + tx_error: ++ local_bh_enable(); + kfree_skb(skb); + return err; + } +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index e23f94a5549b..8c2763eb6aae 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -206,10 +206,12 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err) + + kfree(aead_req); + ++ spin_lock_bh(&ctx->decrypt_compl_lock); + pending = atomic_dec_return(&ctx->decrypt_pending); + +- if (!pending && READ_ONCE(ctx->async_notify)) ++ if (!pending && ctx->async_notify) + complete(&ctx->async_wait.completion); ++ spin_unlock_bh(&ctx->decrypt_compl_lock); + } + + static int tls_do_decryption(struct sock *sk, +@@ -467,10 +469,12 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err) + ready = true; + } + ++ spin_lock_bh(&ctx->encrypt_compl_lock); + pending = atomic_dec_return(&ctx->encrypt_pending); + +- if (!pending && READ_ONCE(ctx->async_notify)) ++ if (!pending && ctx->async_notify) + complete(&ctx->async_wait.completion); ++ spin_unlock_bh(&ctx->encrypt_compl_lock); + + if (!ready) + return; +@@ -780,7 +784,7 @@ static int tls_push_record(struct sock *sk, int flags, + + static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + bool full_record, u8 record_type, +- size_t *copied, int flags) ++ ssize_t *copied, int flags) + { + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); +@@ -796,9 +800,10 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + psock = sk_psock_get(sk); + if (!psock || !policy) { + err = tls_push_record(sk, flags, record_type); +- if (err && err != -EINPROGRESS) { ++ if (err && sk->sk_err == EBADMSG) { + *copied -= sk_msg_free(sk, msg); + tls_free_open_rec(sk); ++ err = -sk->sk_err; + } + if (psock) + sk_psock_put(sk, psock); +@@ -824,9 +829,10 @@ more_data: + switch (psock->eval) { + case __SK_PASS: + err = tls_push_record(sk, flags, record_type); +- if (err && err != -EINPROGRESS) { ++ if (err && sk->sk_err == EBADMSG) { + *copied -= sk_msg_free(sk, msg); + tls_free_open_rec(sk); ++ err = -sk->sk_err; + goto out_err; + } + break; +@@ -916,7 +922,8 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + unsigned char record_type = TLS_RECORD_TYPE_DATA; + bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); + bool eor = !(msg->msg_flags & MSG_MORE); +- size_t try_to_copy, copied = 0; ++ size_t try_to_copy; ++ ssize_t copied = 0; + struct sk_msg *msg_pl, *msg_en; + struct tls_rec *rec; + int required_size; +@@ -926,6 +933,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + int num_zc = 0; + int orig_size; + int ret = 0; ++ int pending; + + if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL)) + return -EOPNOTSUPP; +@@ -1092,13 +1100,19 @@ trim_sgl: + goto send_end; + } else if (num_zc) { + /* Wait for pending encryptions to get completed */ +- smp_store_mb(ctx->async_notify, true); ++ spin_lock_bh(&ctx->encrypt_compl_lock); ++ ctx->async_notify = true; + +- if (atomic_read(&ctx->encrypt_pending)) ++ pending = atomic_read(&ctx->encrypt_pending); ++ spin_unlock_bh(&ctx->encrypt_compl_lock); ++ if (pending) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + else + reinit_completion(&ctx->async_wait.completion); + ++ /* There can be no concurrent accesses, since we have no ++ * pending encrypt operations ++ */ + WRITE_ONCE(ctx->async_notify, false); + + if (ctx->async_wait.err) { +@@ -1118,7 +1132,7 @@ send_end: + + release_sock(sk); + mutex_unlock(&tls_ctx->tx_lock); +- return copied ? copied : ret; ++ return copied > 0 ? copied : ret; + } + + static int tls_sw_do_sendpage(struct sock *sk, struct page *page, +@@ -1132,7 +1146,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page, + struct sk_msg *msg_pl; + struct tls_rec *rec; + int num_async = 0; +- size_t copied = 0; ++ ssize_t copied = 0; + bool full_record; + int record_room; + int ret = 0; +@@ -1234,7 +1248,7 @@ wait_for_memory: + } + sendpage_end: + ret = sk_stream_error(sk, flags, ret); +- return copied ? copied : ret; ++ return copied > 0 ? copied : ret; + } + + int tls_sw_sendpage_locked(struct sock *sk, struct page *page, +@@ -1729,6 +1743,7 @@ int tls_sw_recvmsg(struct sock *sk, + bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); + bool is_peek = flags & MSG_PEEK; + int num_async = 0; ++ int pending; + + flags |= nonblock; + +@@ -1891,8 +1906,11 @@ pick_next_record: + recv_end: + if (num_async) { + /* Wait for all previously submitted records to be decrypted */ +- smp_store_mb(ctx->async_notify, true); +- if (atomic_read(&ctx->decrypt_pending)) { ++ spin_lock_bh(&ctx->decrypt_compl_lock); ++ ctx->async_notify = true; ++ pending = atomic_read(&ctx->decrypt_pending); ++ spin_unlock_bh(&ctx->decrypt_compl_lock); ++ if (pending) { + err = crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + if (err) { + /* one of async decrypt failed */ +@@ -1904,6 +1922,10 @@ recv_end: + } else { + reinit_completion(&ctx->async_wait.completion); + } ++ ++ /* There can be no concurrent accesses, since we have no ++ * pending decrypt operations ++ */ + WRITE_ONCE(ctx->async_notify, false); + + /* Drain records from the rx_list & copy if required */ +@@ -2290,6 +2312,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) + + if (tx) { + crypto_init_wait(&sw_ctx_tx->async_wait); ++ spin_lock_init(&sw_ctx_tx->encrypt_compl_lock); + crypto_info = &ctx->crypto_send.info; + cctx = &ctx->tx; + aead = &sw_ctx_tx->aead_send; +@@ -2298,6 +2321,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) + sw_ctx_tx->tx_work.sk = sk; + } else { + crypto_init_wait(&sw_ctx_rx->async_wait); ++ spin_lock_init(&sw_ctx_rx->decrypt_compl_lock); + crypto_info = &ctx->crypto_recv.info; + cctx = &ctx->rx; + skb_queue_head_init(&sw_ctx_rx->rx_list); +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 3e25229a059d..ee5bb8d8af04 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -142,7 +142,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, + if (result) + return result; + +- if (rdev->wiphy.debugfsdir) ++ if (!IS_ERR_OR_NULL(rdev->wiphy.debugfsdir)) + debugfs_rename(rdev->wiphy.debugfsdir->d_parent, + rdev->wiphy.debugfsdir, + rdev->wiphy.debugfsdir->d_parent, newname); +diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c +index ed7a6060f73c..3889bd9aec46 100644 +--- a/net/xdp/xdp_umem.c ++++ b/net/xdp/xdp_umem.c +@@ -341,8 +341,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + { + bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG; + u32 chunk_size = mr->chunk_size, headroom = mr->headroom; ++ u64 npgs, addr = mr->addr, size = mr->len; + unsigned int chunks, chunks_per_page; +- u64 addr = mr->addr, size = mr->len; + int err; + + if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { +@@ -372,6 +372,10 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + if ((addr + size) < addr) + return -EINVAL; + ++ npgs = div_u64(size, PAGE_SIZE); ++ if (npgs > U32_MAX) ++ return -EINVAL; ++ + chunks = (unsigned int)div_u64(size, chunk_size); + if (chunks == 0) + return -EINVAL; +@@ -391,7 +395,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + umem->size = size; + umem->headroom = headroom; + umem->chunk_size_nohr = chunk_size - headroom; +- umem->npgs = size / PAGE_SIZE; ++ umem->npgs = (u32)npgs; + umem->pgs = NULL; + umem->user = NULL; + umem->flags = mr->flags; +diff --git a/net/xfrm/espintcp.c b/net/xfrm/espintcp.c +index f15d6a564b0e..36abb6750ffe 100644 +--- a/net/xfrm/espintcp.c ++++ b/net/xfrm/espintcp.c +@@ -379,6 +379,7 @@ static void espintcp_destruct(struct sock *sk) + { + struct espintcp_ctx *ctx = espintcp_getctx(sk); + ++ ctx->saved_destruct(sk); + kfree(ctx); + } + +@@ -419,6 +420,7 @@ static int espintcp_init_sk(struct sock *sk) + sk->sk_socket->ops = &espintcp_ops; + ctx->saved_data_ready = sk->sk_data_ready; + ctx->saved_write_space = sk->sk_write_space; ++ ctx->saved_destruct = sk->sk_destruct; + sk->sk_data_ready = espintcp_data_ready; + sk->sk_write_space = espintcp_write_space; + sk->sk_destruct = espintcp_destruct; +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index e2db468cf50e..4c1b939616b3 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -25,12 +25,10 @@ static void __xfrm_transport_prep(struct xfrm_state *x, struct sk_buff *skb, + struct xfrm_offload *xo = xfrm_offload(skb); + + skb_reset_mac_len(skb); +- pskb_pull(skb, skb->mac_len + hsize + x->props.header_len); +- +- if (xo->flags & XFRM_GSO_SEGMENT) { +- skb_reset_transport_header(skb); ++ if (xo->flags & XFRM_GSO_SEGMENT) + skb->transport_header -= x->props.header_len; +- } ++ ++ pskb_pull(skb, skb_transport_offset(skb) + x->props.header_len); + } + + static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb, +diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c +index aa35f23c4912..8a202c44f89a 100644 +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@ -644,7 +644,7 @@ resume: + dev_put(skb->dev); + + spin_lock(&x->lock); +- if (nexthdr <= 0) { ++ if (nexthdr < 0) { + if (nexthdr == -EBADMSG) { + xfrm_audit_state_icvfail(x, skb, + x->type->proto); +diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c +index 3361e3ac5714..1e115cbf21d3 100644 +--- a/net/xfrm/xfrm_interface.c ++++ b/net/xfrm/xfrm_interface.c +@@ -750,7 +750,28 @@ static struct rtnl_link_ops xfrmi_link_ops __read_mostly = { + .get_link_net = xfrmi_get_link_net, + }; + ++static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list) ++{ ++ struct net *net; ++ LIST_HEAD(list); ++ ++ rtnl_lock(); ++ list_for_each_entry(net, net_exit_list, exit_list) { ++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); ++ struct xfrm_if __rcu **xip; ++ struct xfrm_if *xi; ++ ++ for (xip = &xfrmn->xfrmi[0]; ++ (xi = rtnl_dereference(*xip)) != NULL; ++ xip = &xi->next) ++ unregister_netdevice_queue(xi->dev, &list); ++ } ++ unregister_netdevice_many(&list); ++ rtnl_unlock(); ++} ++ + static struct pernet_operations xfrmi_net_ops = { ++ .exit_batch = xfrmi_exit_batch_net, + .id = &xfrmi_net_id, + .size = sizeof(struct xfrmi_net), + }; +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index fafc7aba705f..d5f5a787ebbc 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -583,18 +583,20 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) + xfrm_state_hold(x); + + if (skb_is_gso(skb)) { +- skb_shinfo(skb)->gso_type |= SKB_GSO_ESP; ++ if (skb->inner_protocol) ++ return xfrm_output_gso(net, sk, skb); + +- return xfrm_output2(net, sk, skb); ++ skb_shinfo(skb)->gso_type |= SKB_GSO_ESP; ++ goto out; + } + + if (x->xso.dev && x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM) + goto out; ++ } else { ++ if (skb_is_gso(skb)) ++ return xfrm_output_gso(net, sk, skb); + } + +- if (skb_is_gso(skb)) +- return xfrm_output_gso(net, sk, skb); +- + if (skb->ip_summed == CHECKSUM_PARTIAL) { + err = skb_checksum_help(skb); + if (err) { +@@ -640,7 +642,8 @@ void xfrm_local_error(struct sk_buff *skb, int mtu) + + if (skb->protocol == htons(ETH_P_IP)) + proto = AF_INET; +- else if (skb->protocol == htons(ETH_P_IPV6)) ++ else if (skb->protocol == htons(ETH_P_IPV6) && ++ skb->sk->sk_family == AF_INET6) + proto = AF_INET6; + else + return; +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 8a4af86a285e..580735652754 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1436,12 +1436,7 @@ static void xfrm_policy_requeue(struct xfrm_policy *old, + static bool xfrm_policy_mark_match(struct xfrm_policy *policy, + struct xfrm_policy *pol) + { +- u32 mark = policy->mark.v & policy->mark.m; +- +- if (policy->mark.v == pol->mark.v && policy->mark.m == pol->mark.m) +- return true; +- +- if ((mark & pol->mark.m) == pol->mark.v && ++ if (policy->mark.v == pol->mark.v && + policy->priority == pol->priority) + return true; + +diff --git a/samples/bpf/lwt_len_hist_user.c b/samples/bpf/lwt_len_hist_user.c +index 587b68b1f8dd..430a4b7e353e 100644 +--- a/samples/bpf/lwt_len_hist_user.c ++++ b/samples/bpf/lwt_len_hist_user.c +@@ -15,8 +15,6 @@ + #define MAX_INDEX 64 + #define MAX_STARS 38 + +-char bpf_log_buf[BPF_LOG_BUF_SIZE]; +- + static void stars(char *str, long val, long max, int width) + { + int i; +diff --git a/security/commoncap.c b/security/commoncap.c +index f4ee0ae106b2..0ca31c8bc0b1 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -812,6 +812,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) + int ret; + kuid_t root_uid; + ++ new->cap_ambient = old->cap_ambient; + if (WARN_ON(!cap_ambient_invariant_ok(old))) + return -EPERM; + +diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c +index b412d3b3d5ff..21edb8ac95eb 100644 +--- a/sound/core/hwdep.c ++++ b/sound/core/hwdep.c +@@ -216,12 +216,12 @@ static int snd_hwdep_dsp_load(struct snd_hwdep *hw, + if (info.index >= 32) + return -EINVAL; + /* check whether the dsp was already loaded */ +- if (hw->dsp_loaded & (1 << info.index)) ++ if (hw->dsp_loaded & (1u << info.index)) + return -EBUSY; + err = hw->ops.dsp_load(hw, &info); + if (err < 0) + return err; +- hw->dsp_loaded |= (1 << info.index); ++ hw->dsp_loaded |= (1u << info.index); + return 0; + } + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 041d2a32059b..e62d58872b6e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -384,6 +384,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) + case 0x10ec0282: + case 0x10ec0283: + case 0x10ec0286: ++ case 0x10ec0287: + case 0x10ec0288: + case 0x10ec0285: + case 0x10ec0298: +@@ -5484,18 +5485,9 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec, + { 0x19, 0x21a11010 }, /* dock mic */ + { } + }; +- /* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise +- * the speaker output becomes too low by some reason on Thinkpads with +- * ALC298 codec +- */ +- static const hda_nid_t preferred_pairs[] = { +- 0x14, 0x03, 0x17, 0x02, 0x21, 0x02, +- 0 +- }; + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { +- spec->gen.preferred_dacs = preferred_pairs; + spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; + snd_hda_apply_pincfgs(codec, pincfgs); + } else if (action == HDA_FIXUP_ACT_INIT) { +@@ -5508,6 +5500,23 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec, + } + } + ++static void alc_fixup_tpt470_dacs(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ /* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise ++ * the speaker output becomes too low by some reason on Thinkpads with ++ * ALC298 codec ++ */ ++ static const hda_nid_t preferred_pairs[] = { ++ 0x14, 0x03, 0x17, 0x02, 0x21, 0x02, ++ 0 ++ }; ++ struct alc_spec *spec = codec->spec; ++ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) ++ spec->gen.preferred_dacs = preferred_pairs; ++} ++ + static void alc_shutup_dell_xps13(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +@@ -6063,6 +6072,7 @@ enum { + ALC700_FIXUP_INTEL_REFERENCE, + ALC274_FIXUP_DELL_BIND_DACS, + ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, ++ ALC298_FIXUP_TPT470_DOCK_FIX, + ALC298_FIXUP_TPT470_DOCK, + ALC255_FIXUP_DUMMY_LINEOUT_VERB, + ALC255_FIXUP_DELL_HEADSET_MIC, +@@ -6994,12 +7004,18 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC274_FIXUP_DELL_BIND_DACS + }, +- [ALC298_FIXUP_TPT470_DOCK] = { ++ [ALC298_FIXUP_TPT470_DOCK_FIX] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_tpt470_dock, + .chained = true, + .chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE + }, ++ [ALC298_FIXUP_TPT470_DOCK] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc_fixup_tpt470_dacs, ++ .chained = true, ++ .chain_id = ALC298_FIXUP_TPT470_DOCK_FIX ++ }, + [ALC255_FIXUP_DUMMY_LINEOUT_VERB] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -7638,6 +7654,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"}, + {.id = ALC292_FIXUP_TPT440, .name = "tpt440"}, + {.id = ALC292_FIXUP_TPT460, .name = "tpt460"}, ++ {.id = ALC298_FIXUP_TPT470_DOCK_FIX, .name = "tpt470-dock-fix"}, + {.id = ALC298_FIXUP_TPT470_DOCK, .name = "tpt470-dock"}, + {.id = ALC233_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"}, + {.id = ALC700_FIXUP_INTEL_REFERENCE, .name = "alc700-ref"}, +@@ -8276,6 +8293,7 @@ static int patch_alc269(struct hda_codec *codec) + case 0x10ec0215: + case 0x10ec0245: + case 0x10ec0285: ++ case 0x10ec0287: + case 0x10ec0289: + spec->codec_variant = ALC269_TYPE_ALC215; + spec->shutup = alc225_shutup; +@@ -9554,6 +9572,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { + HDA_CODEC_ENTRY(0x10ec0284, "ALC284", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269), ++ HDA_CODEC_ENTRY(0x10ec0287, "ALC287", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0289, "ALC289", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269), +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 7a2961ad60de..68fefe55e5c0 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1171,6 +1171,14 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, + cval->res = 384; + } + break; ++ case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */ ++ if ((strstr(kctl->id.name, "Playback Volume") != NULL) || ++ strstr(kctl->id.name, "Capture Volume") != NULL) { ++ cval->min >>= 8; ++ cval->max = 0; ++ cval->res = 1; ++ } ++ break; + } + } + +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index 0260c750e156..9af7aa93f6fa 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -397,6 +397,21 @@ static const struct usbmix_connector_map trx40_mobo_connector_map[] = { + {} + }; + ++/* Rear panel + front mic on Gigabyte TRX40 Aorus Master with ALC1220-VB */ ++static const struct usbmix_name_map aorus_master_alc1220vb_map[] = { ++ { 17, NULL }, /* OT, IEC958?, disabled */ ++ { 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */ ++ { 16, "Line Out" }, /* OT */ ++ { 22, "Line Out Playback" }, /* FU */ ++ { 7, "Line" }, /* IT */ ++ { 19, "Line Capture" }, /* FU */ ++ { 8, "Mic" }, /* IT */ ++ { 20, "Mic Capture" }, /* FU */ ++ { 9, "Front Mic" }, /* IT */ ++ { 21, "Front Mic Capture" }, /* FU */ ++ {} ++}; ++ + /* + * Control map entries + */ +@@ -526,6 +541,10 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { + .id = USB_ID(0x1b1c, 0x0a42), + .map = corsair_virtuoso_map, + }, ++ { /* Gigabyte TRX40 Aorus Master (rear panel + front mic) */ ++ .id = USB_ID(0x0414, 0xa001), ++ .map = aorus_master_alc1220vb_map, ++ }, + { /* Gigabyte TRX40 Aorus Pro WiFi */ + .id = USB_ID(0x0414, 0xa002), + .map = trx40_mobo_map, +@@ -549,6 +568,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { + .map = trx40_mobo_map, + .connector_map = trx40_mobo_connector_map, + }, ++ { /* Asrock TRX40 Creator */ ++ .id = USB_ID(0x26ce, 0x0a01), ++ .map = trx40_mobo_map, ++ .connector_map = trx40_mobo_connector_map, ++ }, + { 0 } /* terminator */ + }; + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 8c2f5c23e1b4..bbae11605a4c 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3647,6 +3647,32 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + ALC1220_VB_DESKTOP(0x0414, 0xa002), /* Gigabyte TRX40 Aorus Pro WiFi */ + ALC1220_VB_DESKTOP(0x0db0, 0x0d64), /* MSI TRX40 Creator */ + ALC1220_VB_DESKTOP(0x0db0, 0x543d), /* MSI TRX40 */ ++ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */ + #undef ALC1220_VB_DESKTOP + ++/* Two entries for Gigabyte TRX40 Aorus Master: ++ * TRX40 Aorus Master has two USB-audio devices, one for the front headphone ++ * with ESS SABRE9218 DAC chip, while another for the rest I/O (the rear ++ * panel and the front mic) with Realtek ALC1220-VB. ++ * Here we provide two distinct names for making UCM profiles easier. ++ */ ++{ ++ USB_DEVICE(0x0414, 0xa000), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .vendor_name = "Gigabyte", ++ .product_name = "Aorus Master Front Headphone", ++ .profile_name = "Gigabyte-Aorus-Master-Front-Headphone", ++ .ifnum = QUIRK_NO_INTERFACE ++ } ++}, ++{ ++ USB_DEVICE(0x0414, 0xa001), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .vendor_name = "Gigabyte", ++ .product_name = "Aorus Master Main Audio", ++ .profile_name = "Gigabyte-Aorus-Master-Main-Audio", ++ .ifnum = QUIRK_NO_INTERFACE ++ } ++}, ++ + #undef USB_DEVICE_VENDOR_SPEC +diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +index cd5e1f602ac9..909da9cdda97 100644 +--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c ++++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +@@ -351,6 +351,7 @@ static int test_alloc_errors(char *heap_name) + } + + printf("Expected error checking passed\n"); ++ ret = 0; + out: + if (dmabuf_fd >= 0) + close(dmabuf_fd);