From 0cee8992334618eb7d75ea38147b7418e615e631 Mon Sep 17 00:00:00 2001 From: Julian Sikorski Date: Tue, 20 Aug 2024 07:32:38 +0000 Subject: [PATCH] Update odroidxu4-current to 6.6.47 --- .../odroidxu4-6.6/patch-6.6.44-45.patch | 5821 +++++++++++++++ .../odroidxu4-6.6/patch-6.6.45-46.patch | 6300 +++++++++++++++++ .../odroidxu4-6.6/patch-6.6.46-47.patch | 4211 +++++++++++ 3 files changed, 16332 insertions(+) create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.44-45.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.45-46.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.46-47.patch diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.44-45.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.44-45.patch new file mode 100644 index 0000000000..95da970d54 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.44-45.patch @@ -0,0 +1,5821 @@ +diff --git a/Makefile b/Makefile +index 2e5d92ce2774d..0bd4bee2128b4 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 44 ++SUBLEVEL = 45 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c +index 7147edbe56c67..1d230ac9d0eb5 100644 +--- a/arch/arm/kernel/perf_callchain.c ++++ b/arch/arm/kernel/perf_callchain.c +@@ -85,8 +85,7 @@ static bool + callchain_trace(void *data, unsigned long pc) + { + struct perf_callchain_entry_ctx *entry = data; +- perf_callchain_store(entry, pc); +- return true; ++ return perf_callchain_store(entry, pc) == 0; + } + + void +diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +index 5effd8180cc41..e5993a365870c 100644 +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -641,6 +641,7 @@ dwc_0: usb@8a00000 { + interrupts = ; + phys = <&qusb_phy_0>, <&usb0_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; ++ snps,parkmode-disable-ss-quirk; + snps,is-utmi-l1-suspend; + snps,hird-threshold = /bits/ 8 <0x0>; + snps,dis_u2_susphy_quirk; +@@ -683,6 +684,7 @@ dwc_1: usb@8c00000 { + interrupts = ; + phys = <&qusb_phy_1>, <&usb1_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; ++ snps,parkmode-disable-ss-quirk; + snps,is-utmi-l1-suspend; + snps,hird-threshold = /bits/ 8 <0x0>; + snps,dis_u2_susphy_quirk; +diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi +index 9c072ce197358..7fcc15b6946ae 100644 +--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi +@@ -2159,7 +2159,8 @@ usb3_dwc3: usb@a800000 { + interrupts = ; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; +- phys = <&qusb2phy>, <&usb1_ssphy>; ++ snps,parkmode-disable-ss-quirk; ++ phys = <&qusb2phy>, <&usb3phy>; + phy-names = "usb2-phy", "usb3-phy"; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; +@@ -2168,33 +2169,26 @@ usb3_dwc3: usb@a800000 { + + usb3phy: phy@c010000 { + compatible = "qcom,msm8998-qmp-usb3-phy"; +- reg = <0x0c010000 0x18c>; +- status = "disabled"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges; ++ reg = <0x0c010000 0x1000>; + + clocks = <&gcc GCC_USB3_PHY_AUX_CLK>, ++ <&gcc GCC_USB3_CLKREF_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, +- <&gcc GCC_USB3_CLKREF_CLK>; +- clock-names = "aux", "cfg_ahb", "ref"; ++ <&gcc GCC_USB3_PHY_PIPE_CLK>; ++ clock-names = "aux", ++ "ref", ++ "cfg_ahb", ++ "pipe"; ++ clock-output-names = "usb3_phy_pipe_clk_src"; ++ #clock-cells = <0>; ++ #phy-cells = <0>; + + resets = <&gcc GCC_USB3_PHY_BCR>, + <&gcc GCC_USB3PHY_PHY_BCR>; +- reset-names = "phy", "common"; ++ reset-names = "phy", ++ "phy_phy"; + +- usb1_ssphy: phy@c010200 { +- reg = <0xc010200 0x128>, +- <0xc010400 0x200>, +- <0xc010c00 0x20c>, +- <0xc010600 0x128>, +- <0xc010800 0x200>; +- #phy-cells = <0>; +- #clock-cells = <0>; +- clocks = <&gcc GCC_USB3_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; +- }; ++ status = "disabled"; + }; + + qusb2phy: phy@c012000 { +diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi +index f7c528ecb224b..68b1c017a9fd5 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2795,49 +2796,28 @@ usb_1_hsphy: phy@88e3000 { + nvmem-cells = <&qusb2p_hstx_trim>; + }; + +- usb_1_qmpphy: phy-wrapper@88e9000 { ++ usb_1_qmpphy: phy@88e8000 { + compatible = "qcom,sc7180-qmp-usb3-dp-phy"; +- reg = <0 0x088e9000 0 0x18c>, +- <0 0x088e8000 0 0x3c>, +- <0 0x088ea000 0 0x18c>; ++ reg = <0 0x088e8000 0 0x3000>; + status = "disabled"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, +- <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, +- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; +- clock-names = "aux", "cfg_ahb", "ref", "com_aux"; ++ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, ++ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>, ++ <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; ++ clock-names = "aux", ++ "ref", ++ "com_aux", ++ "usb3_pipe", ++ "cfg_ahb"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + +- usb_1_ssphy: usb3-phy@88e9200 { +- reg = <0 0x088e9200 0 0x128>, +- <0 0x088e9400 0 0x200>, +- <0 0x088e9c00 0 0x218>, +- <0 0x088e9600 0 0x128>, +- <0 0x088e9800 0 0x200>, +- <0 0x088e9a00 0 0x18>; +- #clock-cells = <0>; +- #phy-cells = <0>; +- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; +- }; +- +- dp_phy: dp-phy@88ea200 { +- reg = <0 0x088ea200 0 0x200>, +- <0 0x088ea400 0 0x200>, +- <0 0x088eaa00 0 0x200>, +- <0 0x088ea600 0 0x200>, +- <0 0x088ea800 0 0x200>; +- #clock-cells = <1>; +- #phy-cells = <0>; +- }; ++ #clock-cells = <1>; ++ #phy-cells = <1>; + }; + + pmu@90b6300 { +@@ -3001,7 +2981,8 @@ usb_1_dwc3: usb@a600000 { + iommus = <&apps_smmu 0x540 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; +- phys = <&usb_1_hsphy>, <&usb_1_ssphy>; ++ snps,parkmode-disable-ss-quirk; ++ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + maximum-speed = "super-speed"; + }; +@@ -3307,8 +3288,9 @@ mdss_dp: displayport-controller@ae90000 { + "ctrl_link_iface", "stream_pixel"; + assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; +- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>; +- phys = <&dp_phy>; ++ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; ++ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; +@@ -3365,8 +3347,8 @@ dispcc: clock-controller@af00000 { + <&gcc GCC_DISP_GPLL0_CLK_SRC>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>, +- <&dp_phy 0>, +- <&dp_phy 1>; ++ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; + clock-names = "bi_tcxo", + "gcc_disp_gpll0_clk_src", + "dsi0_phy_pll_out_byteclk", +diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi +index b75de7caaa7e5..149c7962f2cbb 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -858,7 +859,7 @@ gcc: clock-controller@100000 { + <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>, + <0>, <&pcie1_lane>, + <0>, <0>, <0>, +- <&usb_1_ssphy>; ++ <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>; + clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk", + "pcie_0_pipe_clk", "pcie_1_pipe_clk", + "ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk", +@@ -3351,49 +3352,26 @@ usb_2_hsphy: phy@88e4000 { + resets = <&gcc GCC_QUSB2PHY_SEC_BCR>; + }; + +- usb_1_qmpphy: phy-wrapper@88e9000 { +- compatible = "qcom,sc7280-qmp-usb3-dp-phy", +- "qcom,sm8250-qmp-usb3-dp-phy"; +- reg = <0 0x088e9000 0 0x200>, +- <0 0x088e8000 0 0x40>, +- <0 0x088ea000 0 0x200>; ++ usb_1_qmpphy: phy@88e8000 { ++ compatible = "qcom,sc7280-qmp-usb3-dp-phy"; ++ reg = <0 0x088e8000 0 0x3000>; + status = "disabled"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, +- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; +- clock-names = "aux", "ref_clk_src", "com_aux"; ++ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, ++ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; ++ clock-names = "aux", ++ "ref", ++ "com_aux", ++ "usb3_pipe"; + + resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>, + <&gcc GCC_USB3_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + +- usb_1_ssphy: usb3-phy@88e9200 { +- reg = <0 0x088e9200 0 0x200>, +- <0 0x088e9400 0 0x200>, +- <0 0x088e9c00 0 0x400>, +- <0 0x088e9600 0 0x200>, +- <0 0x088e9800 0 0x200>, +- <0 0x088e9a00 0 0x100>; +- #clock-cells = <0>; +- #phy-cells = <0>; +- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; +- }; +- +- dp_phy: dp-phy@88ea200 { +- reg = <0 0x088ea200 0 0x200>, +- <0 0x088ea400 0 0x200>, +- <0 0x088eaa00 0 0x200>, +- <0 0x088ea600 0 0x200>, +- <0 0x088ea800 0 0x200>; +- #phy-cells = <0>; +- #clock-cells = <1>; +- }; ++ #clock-cells = <1>; ++ #phy-cells = <1>; + }; + + usb_2: usb@8cf8800 { +@@ -3702,7 +3680,8 @@ usb_1_dwc3: usb@a600000 { + iommus = <&apps_smmu 0xe0 0x0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; +- phys = <&usb_1_hsphy>, <&usb_1_ssphy>; ++ snps,parkmode-disable-ss-quirk; ++ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + maximum-speed = "super-speed"; + }; +@@ -3807,8 +3786,8 @@ dispcc: clock-controller@af00000 { + <&gcc GCC_DISP_GPLL0_CLK_SRC>, + <&mdss_dsi_phy 0>, + <&mdss_dsi_phy 1>, +- <&dp_phy 0>, +- <&dp_phy 1>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, + <&mdss_edp_phy 0>, + <&mdss_edp_phy 1>; + clock-names = "bi_tcxo", +@@ -4144,8 +4123,9 @@ mdss_dp: displayport-controller@ae90000 { + "stream_pixel"; + assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; +- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>; +- phys = <&dp_phy>; ++ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; ++ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; +diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi +index 9d9b378c07e14..dcdc8a0cd1819 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3983,80 +3984,54 @@ usb_2_hsphy: phy@88e3000 { + nvmem-cells = <&qusb2s_hstx_trim>; + }; + +- usb_1_qmpphy: phy@88e9000 { ++ usb_1_qmpphy: phy@88e8000 { + compatible = "qcom,sdm845-qmp-usb3-dp-phy"; +- reg = <0 0x088e9000 0 0x18c>, +- <0 0x088e8000 0 0x38>, +- <0 0x088ea000 0 0x40>; ++ reg = <0 0x088e8000 0 0x3000>; + status = "disabled"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, +- <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, +- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; +- clock-names = "aux", "cfg_ahb", "ref", "com_aux"; ++ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, ++ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>, ++ <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; ++ clock-names = "aux", ++ "ref", ++ "com_aux", ++ "usb3_pipe", ++ "cfg_ahb"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + +- usb_1_ssphy: usb3-phy@88e9200 { +- reg = <0 0x088e9200 0 0x128>, +- <0 0x088e9400 0 0x200>, +- <0 0x088e9c00 0 0x218>, +- <0 0x088e9600 0 0x128>, +- <0 0x088e9800 0 0x200>, +- <0 0x088e9a00 0 0x100>; +- #clock-cells = <0>; +- #phy-cells = <0>; +- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; +- }; +- +- dp_phy: dp-phy@88ea200 { +- reg = <0 0x088ea200 0 0x200>, +- <0 0x088ea400 0 0x200>, +- <0 0x088eaa00 0 0x200>, +- <0 0x088ea600 0 0x200>, +- <0 0x088ea800 0 0x200>; +- #clock-cells = <1>; +- #phy-cells = <0>; +- }; ++ #clock-cells = <1>; ++ #phy-cells = <1>; + }; + + usb_2_qmpphy: phy@88eb000 { + compatible = "qcom,sdm845-qmp-usb3-uni-phy"; +- reg = <0 0x088eb000 0 0x18c>; +- status = "disabled"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; ++ reg = <0 0x088eb000 0 0x1000>; + + clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>, +- <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>; +- clock-names = "aux", "cfg_ahb", "ref", "com_aux"; ++ <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>, ++ <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; ++ clock-names = "aux", ++ "cfg_ahb", ++ "ref", ++ "com_aux", ++ "pipe"; ++ clock-output-names = "usb3_uni_phy_pipe_clk_src"; ++ #clock-cells = <0>; ++ #phy-cells = <0>; + +- resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>, +- <&gcc GCC_USB3_PHY_SEC_BCR>; +- reset-names = "phy", "common"; ++ resets = <&gcc GCC_USB3_PHY_SEC_BCR>, ++ <&gcc GCC_USB3PHY_PHY_SEC_BCR>; ++ reset-names = "phy", ++ "phy_phy"; + +- usb_2_ssphy: phy@88eb200 { +- reg = <0 0x088eb200 0 0x128>, +- <0 0x088eb400 0 0x1fc>, +- <0 0x088eb800 0 0x218>, +- <0 0x088eb600 0 0x70>; +- #clock-cells = <0>; +- #phy-cells = <0>; +- clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_uni_phy_pipe_clk_src"; +- }; ++ status = "disabled"; + }; + + usb_1: usb@a6f8800 { +@@ -4105,7 +4080,8 @@ usb_1_dwc3: usb@a600000 { + iommus = <&apps_smmu 0x740 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; +- phys = <&usb_1_hsphy>, <&usb_1_ssphy>; ++ snps,parkmode-disable-ss-quirk; ++ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; +@@ -4156,7 +4132,8 @@ usb_2_dwc3: usb@a800000 { + iommus = <&apps_smmu 0x760 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; +- phys = <&usb_2_hsphy>, <&usb_2_ssphy>; ++ snps,parkmode-disable-ss-quirk; ++ phys = <&usb_2_hsphy>, <&usb_2_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; +@@ -4573,8 +4550,9 @@ mdss_dp: displayport-controller@ae90000 { + "ctrl_link_iface", "stream_pixel"; + assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; +- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>; +- phys = <&dp_phy>; ++ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; ++ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; +@@ -4912,8 +4890,8 @@ dispcc: clock-controller@af00000 { + <&mdss_dsi0_phy 1>, + <&mdss_dsi1_phy 0>, + <&mdss_dsi1_phy 1>, +- <&dp_phy 0>, +- <&dp_phy 1>; ++ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; + clock-names = "bi_tcxo", + "gcc_disp_gpll0_clk_src", + "gcc_disp_gpll0_div_clk_src", +diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h +index 6aafbb7899916..4b99159150829 100644 +--- a/arch/arm64/include/asm/jump_label.h ++++ b/arch/arm64/include/asm/jump_label.h +@@ -13,6 +13,7 @@ + #include + #include + ++#define HAVE_JUMP_LABEL_BATCH + #define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE + + static __always_inline bool arch_static_branch(struct static_key * const key, +diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c +index faf88ec9c48e8..f63ea915d6ad2 100644 +--- a/arch/arm64/kernel/jump_label.c ++++ b/arch/arm64/kernel/jump_label.c +@@ -7,11 +7,12 @@ + */ + #include + #include ++#include + #include + #include + +-void arch_jump_label_transform(struct jump_entry *entry, +- enum jump_label_type type) ++bool arch_jump_label_transform_queue(struct jump_entry *entry, ++ enum jump_label_type type) + { + void *addr = (void *)jump_entry_code(entry); + u32 insn; +@@ -25,4 +26,10 @@ void arch_jump_label_transform(struct jump_entry *entry, + } + + aarch64_insn_patch_text_nosync(addr, insn); ++ return true; ++} ++ ++void arch_jump_label_transform_apply(void) ++{ ++ kick_all_cpus_sync(); + } +diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi +index c0be84a6e81fd..cc7747c5f21f3 100644 +--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi ++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi +@@ -99,8 +99,8 @@ liointc1: interrupt-controller@1fe11440 { + rtc0: rtc@1fe07800 { + compatible = "loongson,ls2k1000-rtc"; + reg = <0 0x1fe07800 0 0x78>; +- interrupt-parent = <&liointc0>; +- interrupts = <60 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-parent = <&liointc1>; ++ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + }; + + uart0: serial@1fe00000 { +@@ -108,7 +108,7 @@ uart0: serial@1fe00000 { + reg = <0 0x1fe00000 0 0x8>; + clock-frequency = <125000000>; + interrupt-parent = <&liointc0>; +- interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + no-loopback-test; + }; + +@@ -117,7 +117,6 @@ pci@1a000000 { + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; +- #interrupt-cells = <2>; + + reg = <0 0x1a000000 0 0x02000000>, + <0xfe 0x00000000 0 0x20000000>; +@@ -132,8 +131,8 @@ gmac@3,0 { + "pciclass0c03"; + + reg = <0x1800 0x0 0x0 0x0 0x0>; +- interrupts = <12 IRQ_TYPE_LEVEL_LOW>, +- <13 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <12 IRQ_TYPE_LEVEL_HIGH>, ++ <13 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; + interrupt-parent = <&liointc0>; + phy-mode = "rgmii-id"; +@@ -156,8 +155,8 @@ gmac@3,1 { + "loongson, pci-gmac"; + + reg = <0x1900 0x0 0x0 0x0 0x0>; +- interrupts = <14 IRQ_TYPE_LEVEL_LOW>, +- <15 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <14 IRQ_TYPE_LEVEL_HIGH>, ++ <15 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; + interrupt-parent = <&liointc0>; + phy-mode = "rgmii-id"; +@@ -179,7 +178,7 @@ ehci@4,1 { + "pciclass0c03"; + + reg = <0x2100 0x0 0x0 0x0 0x0>; +- interrupts = <18 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + }; + +@@ -190,7 +189,7 @@ ohci@4,2 { + "pciclass0c03"; + + reg = <0x2200 0x0 0x0 0x0 0x0>; +- interrupts = <19 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + }; + +@@ -201,97 +200,121 @@ sata@8,0 { + "pciclass0106"; + + reg = <0x4000 0x0 0x0 0x0 0x0>; +- interrupts = <19 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc0>; + }; + +- pci_bridge@9,0 { ++ pcie@9,0 { + compatible = "pci0014,7a19.0", + "pci0014,7a19", + "pciclass060400", + "pciclass0604"; + + reg = <0x4800 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +- pci_bridge@a,0 { ++ pcie@a,0 { + compatible = "pci0014,7a09.0", + "pci0014,7a09", + "pciclass060400", + "pciclass0604"; + + reg = <0x5000 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <1 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +- pci_bridge@b,0 { ++ pcie@b,0 { + compatible = "pci0014,7a09.0", + "pci0014,7a09", + "pciclass060400", + "pciclass0604"; + + reg = <0x5800 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <2 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +- pci_bridge@c,0 { ++ pcie@c,0 { + compatible = "pci0014,7a09.0", + "pci0014,7a09", + "pciclass060400", + "pciclass0604"; + + reg = <0x6000 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <3 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +- pci_bridge@d,0 { ++ pcie@d,0 { + compatible = "pci0014,7a19.0", + "pci0014,7a19", + "pciclass060400", + "pciclass0604"; + + reg = <0x6800 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <4 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +- pci_bridge@e,0 { ++ pcie@e,0 { + compatible = "pci0014,7a09.0", + "pci0014,7a09", + "pciclass060400", + "pciclass0604"; + + reg = <0x7000 0x0 0x0 0x0 0x0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; + #interrupt-cells = <1>; +- interrupts = <5 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&liointc1>; + interrupt-map-mask = <0 0 0 0>; +- interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; + external-facing; + }; + +diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c +index 5348d842c7453..e867fe465164e 100644 +--- a/arch/riscv/kernel/traps_misaligned.c ++++ b/arch/riscv/kernel/traps_misaligned.c +@@ -151,51 +151,19 @@ + #define PRECISION_S 0 + #define PRECISION_D 1 + +-#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ +-static inline type load_##type(const type *addr) \ +-{ \ +- type val; \ +- asm (#insn " %0, %1" \ +- : "=&r" (val) : "m" (*addr)); \ +- return val; \ +-} ++static inline u8 load_u8(const u8 *addr) ++{ ++ u8 val; + +-#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \ +-static inline void store_##type(type *addr, type val) \ +-{ \ +- asm volatile (#insn " %0, %1\n" \ +- : : "r" (val), "m" (*addr)); \ +-} ++ asm volatile("lbu %0, %1" : "=&r" (val) : "m" (*addr)); + +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8, lbu) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16, lhu) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s8, lb) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s16, lh) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s32, lw) +-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u8, sb) +-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u16, sh) +-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u32, sw) +-#if defined(CONFIG_64BIT) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lwu) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64, ld) +-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64, sd) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld) +-#else +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw) +-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw) +- +-static inline u64 load_u64(const u64 *addr) +-{ +- return load_u32((u32 *)addr) +- + ((u64)load_u32((u32 *)addr + 1) << 32); ++ return val; + } + +-static inline void store_u64(u64 *addr, u64 val) ++static inline void store_u8(u8 *addr, u8 val) + { +- store_u32((u32 *)addr, val); +- store_u32((u32 *)addr + 1, val >> 32); ++ asm volatile ("sb %0, %1\n" : : "r" (val), "m" (*addr)); + } +-#endif + + static inline ulong get_insn(ulong mepc) + { +diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c +index 90d4ba36d1d06..655b2b1bb529f 100644 +--- a/arch/riscv/mm/fault.c ++++ b/arch/riscv/mm/fault.c +@@ -61,26 +61,27 @@ static inline void no_context(struct pt_regs *regs, unsigned long addr) + + static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_fault_t fault) + { ++ if (!user_mode(regs)) { ++ no_context(regs, addr); ++ return; ++ } ++ + if (fault & VM_FAULT_OOM) { + /* + * We ran out of memory, call the OOM killer, and return the userspace + * (which will retry the fault, or kill us if we got oom-killed). + */ +- if (!user_mode(regs)) { +- no_context(regs, addr); +- return; +- } + pagefault_out_of_memory(); + return; + } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) { + /* Kernel mode? Handle exceptions or die */ +- if (!user_mode(regs)) { +- no_context(regs, addr); +- return; +- } + do_trap(regs, SIGBUS, BUS_ADRERR, addr); + return; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ do_trap(regs, SIGSEGV, SEGV_MAPERR, addr); ++ return; + } ++ + BUG(); + } + +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index 8adcb9419ad50..9b10e9655df8c 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -217,8 +217,6 @@ static void __init setup_bootmem(void) + */ + memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); + +- phys_ram_end = memblock_end_of_DRAM(); +- + /* + * Make sure we align the start of the memory on a PMD boundary so that + * at worst, we map the linear mapping with PMD mappings. +@@ -233,6 +231,16 @@ static void __init setup_bootmem(void) + if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU)) + kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base; + ++ /* ++ * The size of the linear page mapping may restrict the amount of ++ * usable RAM. ++ */ ++ if (IS_ENABLED(CONFIG_64BIT)) { ++ max_mapped_addr = __pa(PAGE_OFFSET) + KERN_VIRT_SIZE; ++ memblock_cap_memory_range(phys_ram_base, ++ max_mapped_addr - phys_ram_base); ++ } ++ + /* + * Reserve physical address space that would be mapped to virtual + * addresses greater than (void *)(-PAGE_SIZE) because: +@@ -249,6 +257,7 @@ static void __init setup_bootmem(void) + memblock_reserve(max_mapped_addr, (phys_addr_t)-max_mapped_addr); + } + ++ phys_ram_end = memblock_end_of_DRAM(); + min_low_pfn = PFN_UP(phys_ram_base); + max_low_pfn = max_pfn = PFN_DOWN(phys_ram_end); + high_memory = (void *)(__va(PFN_PHYS(max_low_pfn))); +@@ -1269,8 +1278,6 @@ static void __init create_linear_mapping_page_table(void) + if (start <= __pa(PAGE_OFFSET) && + __pa(PAGE_OFFSET) < end) + start = __pa(PAGE_OFFSET); +- if (end >= __pa(PAGE_OFFSET) + memory_limit) +- end = __pa(PAGE_OFFSET) + memory_limit; + + create_linear_mapping_range(start, end, 0); + } +diff --git a/arch/x86/include/asm/posted_intr.h b/arch/x86/include/asm/posted_intr.h +new file mode 100644 +index 0000000000000..f0324c56f7af5 +--- /dev/null ++++ b/arch/x86/include/asm/posted_intr.h +@@ -0,0 +1,88 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _X86_POSTED_INTR_H ++#define _X86_POSTED_INTR_H ++ ++#define POSTED_INTR_ON 0 ++#define POSTED_INTR_SN 1 ++ ++#define PID_TABLE_ENTRY_VALID 1 ++ ++/* Posted-Interrupt Descriptor */ ++struct pi_desc { ++ u32 pir[8]; /* Posted interrupt requested */ ++ union { ++ struct { ++ /* bit 256 - Outstanding Notification */ ++ u16 on : 1, ++ /* bit 257 - Suppress Notification */ ++ sn : 1, ++ /* bit 271:258 - Reserved */ ++ rsvd_1 : 14; ++ /* bit 279:272 - Notification Vector */ ++ u8 nv; ++ /* bit 287:280 - Reserved */ ++ u8 rsvd_2; ++ /* bit 319:288 - Notification Destination */ ++ u32 ndst; ++ }; ++ u64 control; ++ }; ++ u32 rsvd[6]; ++} __aligned(64); ++ ++static inline bool pi_test_and_set_on(struct pi_desc *pi_desc) ++{ ++ return test_and_set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); ++} ++ ++static inline bool pi_test_and_clear_on(struct pi_desc *pi_desc) ++{ ++ return test_and_clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); ++} ++ ++static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc) ++{ ++ return test_and_clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); ++} ++ ++static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc) ++{ ++ return test_and_set_bit(vector, (unsigned long *)pi_desc->pir); ++} ++ ++static inline bool pi_is_pir_empty(struct pi_desc *pi_desc) ++{ ++ return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS); ++} ++ ++static inline void pi_set_sn(struct pi_desc *pi_desc) ++{ ++ set_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); ++} ++ ++static inline void pi_set_on(struct pi_desc *pi_desc) ++{ ++ set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); ++} ++ ++static inline void pi_clear_on(struct pi_desc *pi_desc) ++{ ++ clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); ++} ++ ++static inline void pi_clear_sn(struct pi_desc *pi_desc) ++{ ++ clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); ++} ++ ++static inline bool pi_test_on(struct pi_desc *pi_desc) ++{ ++ return test_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); ++} ++ ++static inline bool pi_test_sn(struct pi_desc *pi_desc) ++{ ++ return test_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); ++} ++ ++#endif /* _X86_POSTED_INTR_H */ +diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile +index 80e3fe184d17e..a99ffc3f3a3fd 100644 +--- a/arch/x86/kvm/Makefile ++++ b/arch/x86/kvm/Makefile +@@ -26,6 +26,10 @@ kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \ + vmx/hyperv.o vmx/nested.o vmx/posted_intr.o + kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o + ++ifdef CONFIG_HYPERV ++kvm-intel-y += vmx/vmx_onhyperv.o ++endif ++ + kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \ + svm/sev.o svm/hyperv.o + +diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c +index 313b8bb5b8a7c..de13dc14fe1d2 100644 +--- a/arch/x86/kvm/vmx/hyperv.c ++++ b/arch/x86/kvm/vmx/hyperv.c +@@ -13,111 +13,6 @@ + + #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK + +-/* +- * Enlightened VMCSv1 doesn't support these: +- * +- * POSTED_INTR_NV = 0x00000002, +- * GUEST_INTR_STATUS = 0x00000810, +- * APIC_ACCESS_ADDR = 0x00002014, +- * POSTED_INTR_DESC_ADDR = 0x00002016, +- * EOI_EXIT_BITMAP0 = 0x0000201c, +- * EOI_EXIT_BITMAP1 = 0x0000201e, +- * EOI_EXIT_BITMAP2 = 0x00002020, +- * EOI_EXIT_BITMAP3 = 0x00002022, +- * GUEST_PML_INDEX = 0x00000812, +- * PML_ADDRESS = 0x0000200e, +- * VM_FUNCTION_CONTROL = 0x00002018, +- * EPTP_LIST_ADDRESS = 0x00002024, +- * VMREAD_BITMAP = 0x00002026, +- * VMWRITE_BITMAP = 0x00002028, +- * +- * TSC_MULTIPLIER = 0x00002032, +- * PLE_GAP = 0x00004020, +- * PLE_WINDOW = 0x00004022, +- * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E, +- * +- * Currently unsupported in KVM: +- * GUEST_IA32_RTIT_CTL = 0x00002814, +- */ +-#define EVMCS1_SUPPORTED_PINCTRL \ +- (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \ +- PIN_BASED_EXT_INTR_MASK | \ +- PIN_BASED_NMI_EXITING | \ +- PIN_BASED_VIRTUAL_NMIS) +- +-#define EVMCS1_SUPPORTED_EXEC_CTRL \ +- (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \ +- CPU_BASED_HLT_EXITING | \ +- CPU_BASED_CR3_LOAD_EXITING | \ +- CPU_BASED_CR3_STORE_EXITING | \ +- CPU_BASED_UNCOND_IO_EXITING | \ +- CPU_BASED_MOV_DR_EXITING | \ +- CPU_BASED_USE_TSC_OFFSETTING | \ +- CPU_BASED_MWAIT_EXITING | \ +- CPU_BASED_MONITOR_EXITING | \ +- CPU_BASED_INVLPG_EXITING | \ +- CPU_BASED_RDPMC_EXITING | \ +- CPU_BASED_INTR_WINDOW_EXITING | \ +- CPU_BASED_CR8_LOAD_EXITING | \ +- CPU_BASED_CR8_STORE_EXITING | \ +- CPU_BASED_RDTSC_EXITING | \ +- CPU_BASED_TPR_SHADOW | \ +- CPU_BASED_USE_IO_BITMAPS | \ +- CPU_BASED_MONITOR_TRAP_FLAG | \ +- CPU_BASED_USE_MSR_BITMAPS | \ +- CPU_BASED_NMI_WINDOW_EXITING | \ +- CPU_BASED_PAUSE_EXITING | \ +- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) +- +-#define EVMCS1_SUPPORTED_2NDEXEC \ +- (SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | \ +- SECONDARY_EXEC_WBINVD_EXITING | \ +- SECONDARY_EXEC_ENABLE_VPID | \ +- SECONDARY_EXEC_ENABLE_EPT | \ +- SECONDARY_EXEC_UNRESTRICTED_GUEST | \ +- SECONDARY_EXEC_DESC | \ +- SECONDARY_EXEC_ENABLE_RDTSCP | \ +- SECONDARY_EXEC_ENABLE_INVPCID | \ +- SECONDARY_EXEC_ENABLE_XSAVES | \ +- SECONDARY_EXEC_RDSEED_EXITING | \ +- SECONDARY_EXEC_RDRAND_EXITING | \ +- SECONDARY_EXEC_TSC_SCALING | \ +- SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE | \ +- SECONDARY_EXEC_PT_USE_GPA | \ +- SECONDARY_EXEC_PT_CONCEAL_VMX | \ +- SECONDARY_EXEC_BUS_LOCK_DETECTION | \ +- SECONDARY_EXEC_NOTIFY_VM_EXITING | \ +- SECONDARY_EXEC_ENCLS_EXITING) +- +-#define EVMCS1_SUPPORTED_3RDEXEC (0ULL) +- +-#define EVMCS1_SUPPORTED_VMEXIT_CTRL \ +- (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | \ +- VM_EXIT_SAVE_DEBUG_CONTROLS | \ +- VM_EXIT_ACK_INTR_ON_EXIT | \ +- VM_EXIT_HOST_ADDR_SPACE_SIZE | \ +- VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | \ +- VM_EXIT_SAVE_IA32_PAT | \ +- VM_EXIT_LOAD_IA32_PAT | \ +- VM_EXIT_SAVE_IA32_EFER | \ +- VM_EXIT_LOAD_IA32_EFER | \ +- VM_EXIT_CLEAR_BNDCFGS | \ +- VM_EXIT_PT_CONCEAL_PIP | \ +- VM_EXIT_CLEAR_IA32_RTIT_CTL) +- +-#define EVMCS1_SUPPORTED_VMENTRY_CTRL \ +- (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | \ +- VM_ENTRY_LOAD_DEBUG_CONTROLS | \ +- VM_ENTRY_IA32E_MODE | \ +- VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | \ +- VM_ENTRY_LOAD_IA32_PAT | \ +- VM_ENTRY_LOAD_IA32_EFER | \ +- VM_ENTRY_LOAD_BNDCFGS | \ +- VM_ENTRY_PT_CONCEAL_PIP | \ +- VM_ENTRY_LOAD_IA32_RTIT_CTL) +- +-#define EVMCS1_SUPPORTED_VMFUNC (0) +- + #define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x) + #define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \ + {EVMCS1_OFFSET(name), clean_field} +@@ -608,40 +503,6 @@ int nested_evmcs_check_controls(struct vmcs12 *vmcs12) + return 0; + } + +-#if IS_ENABLED(CONFIG_HYPERV) +-DEFINE_STATIC_KEY_FALSE(__kvm_is_using_evmcs); +- +-/* +- * KVM on Hyper-V always uses the latest known eVMCSv1 revision, the assumption +- * is: in case a feature has corresponding fields in eVMCS described and it was +- * exposed in VMX feature MSRs, KVM is free to use it. Warn if KVM meets a +- * feature which has no corresponding eVMCS field, this likely means that KVM +- * needs to be updated. +- */ +-#define evmcs_check_vmcs_conf(field, ctrl) \ +- do { \ +- typeof(vmcs_conf->field) unsupported; \ +- \ +- unsupported = vmcs_conf->field & ~EVMCS1_SUPPORTED_ ## ctrl; \ +- if (unsupported) { \ +- pr_warn_once(#field " unsupported with eVMCS: 0x%llx\n",\ +- (u64)unsupported); \ +- vmcs_conf->field &= EVMCS1_SUPPORTED_ ## ctrl; \ +- } \ +- } \ +- while (0) +- +-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) +-{ +- evmcs_check_vmcs_conf(cpu_based_exec_ctrl, EXEC_CTRL); +- evmcs_check_vmcs_conf(pin_based_exec_ctrl, PINCTRL); +- evmcs_check_vmcs_conf(cpu_based_2nd_exec_ctrl, 2NDEXEC); +- evmcs_check_vmcs_conf(cpu_based_3rd_exec_ctrl, 3RDEXEC); +- evmcs_check_vmcs_conf(vmentry_ctrl, VMENTRY_CTRL); +- evmcs_check_vmcs_conf(vmexit_ctrl, VMEXIT_CTRL); +-} +-#endif +- + int nested_enable_evmcs(struct kvm_vcpu *vcpu, + uint16_t *vmcs_version) + { +diff --git a/arch/x86/kvm/vmx/hyperv.h b/arch/x86/kvm/vmx/hyperv.h +index 9623fe1651c48..9401dbfaea7ce 100644 +--- a/arch/x86/kvm/vmx/hyperv.h ++++ b/arch/x86/kvm/vmx/hyperv.h +@@ -14,12 +14,113 @@ + #include "vmcs.h" + #include "vmcs12.h" + +-struct vmcs_config; +- +-#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs)) +- + #define KVM_EVMCS_VERSION 1 + ++/* ++ * Enlightened VMCSv1 doesn't support these: ++ * ++ * POSTED_INTR_NV = 0x00000002, ++ * GUEST_INTR_STATUS = 0x00000810, ++ * APIC_ACCESS_ADDR = 0x00002014, ++ * POSTED_INTR_DESC_ADDR = 0x00002016, ++ * EOI_EXIT_BITMAP0 = 0x0000201c, ++ * EOI_EXIT_BITMAP1 = 0x0000201e, ++ * EOI_EXIT_BITMAP2 = 0x00002020, ++ * EOI_EXIT_BITMAP3 = 0x00002022, ++ * GUEST_PML_INDEX = 0x00000812, ++ * PML_ADDRESS = 0x0000200e, ++ * VM_FUNCTION_CONTROL = 0x00002018, ++ * EPTP_LIST_ADDRESS = 0x00002024, ++ * VMREAD_BITMAP = 0x00002026, ++ * VMWRITE_BITMAP = 0x00002028, ++ * ++ * TSC_MULTIPLIER = 0x00002032, ++ * PLE_GAP = 0x00004020, ++ * PLE_WINDOW = 0x00004022, ++ * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E, ++ * ++ * Currently unsupported in KVM: ++ * GUEST_IA32_RTIT_CTL = 0x00002814, ++ */ ++#define EVMCS1_SUPPORTED_PINCTRL \ ++ (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \ ++ PIN_BASED_EXT_INTR_MASK | \ ++ PIN_BASED_NMI_EXITING | \ ++ PIN_BASED_VIRTUAL_NMIS) ++ ++#define EVMCS1_SUPPORTED_EXEC_CTRL \ ++ (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \ ++ CPU_BASED_HLT_EXITING | \ ++ CPU_BASED_CR3_LOAD_EXITING | \ ++ CPU_BASED_CR3_STORE_EXITING | \ ++ CPU_BASED_UNCOND_IO_EXITING | \ ++ CPU_BASED_MOV_DR_EXITING | \ ++ CPU_BASED_USE_TSC_OFFSETTING | \ ++ CPU_BASED_MWAIT_EXITING | \ ++ CPU_BASED_MONITOR_EXITING | \ ++ CPU_BASED_INVLPG_EXITING | \ ++ CPU_BASED_RDPMC_EXITING | \ ++ CPU_BASED_INTR_WINDOW_EXITING | \ ++ CPU_BASED_CR8_LOAD_EXITING | \ ++ CPU_BASED_CR8_STORE_EXITING | \ ++ CPU_BASED_RDTSC_EXITING | \ ++ CPU_BASED_TPR_SHADOW | \ ++ CPU_BASED_USE_IO_BITMAPS | \ ++ CPU_BASED_MONITOR_TRAP_FLAG | \ ++ CPU_BASED_USE_MSR_BITMAPS | \ ++ CPU_BASED_NMI_WINDOW_EXITING | \ ++ CPU_BASED_PAUSE_EXITING | \ ++ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) ++ ++#define EVMCS1_SUPPORTED_2NDEXEC \ ++ (SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | \ ++ SECONDARY_EXEC_WBINVD_EXITING | \ ++ SECONDARY_EXEC_ENABLE_VPID | \ ++ SECONDARY_EXEC_ENABLE_EPT | \ ++ SECONDARY_EXEC_UNRESTRICTED_GUEST | \ ++ SECONDARY_EXEC_DESC | \ ++ SECONDARY_EXEC_ENABLE_RDTSCP | \ ++ SECONDARY_EXEC_ENABLE_INVPCID | \ ++ SECONDARY_EXEC_ENABLE_XSAVES | \ ++ SECONDARY_EXEC_RDSEED_EXITING | \ ++ SECONDARY_EXEC_RDRAND_EXITING | \ ++ SECONDARY_EXEC_TSC_SCALING | \ ++ SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE | \ ++ SECONDARY_EXEC_PT_USE_GPA | \ ++ SECONDARY_EXEC_PT_CONCEAL_VMX | \ ++ SECONDARY_EXEC_BUS_LOCK_DETECTION | \ ++ SECONDARY_EXEC_NOTIFY_VM_EXITING | \ ++ SECONDARY_EXEC_ENCLS_EXITING) ++ ++#define EVMCS1_SUPPORTED_3RDEXEC (0ULL) ++ ++#define EVMCS1_SUPPORTED_VMEXIT_CTRL \ ++ (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | \ ++ VM_EXIT_SAVE_DEBUG_CONTROLS | \ ++ VM_EXIT_ACK_INTR_ON_EXIT | \ ++ VM_EXIT_HOST_ADDR_SPACE_SIZE | \ ++ VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | \ ++ VM_EXIT_SAVE_IA32_PAT | \ ++ VM_EXIT_LOAD_IA32_PAT | \ ++ VM_EXIT_SAVE_IA32_EFER | \ ++ VM_EXIT_LOAD_IA32_EFER | \ ++ VM_EXIT_CLEAR_BNDCFGS | \ ++ VM_EXIT_PT_CONCEAL_PIP | \ ++ VM_EXIT_CLEAR_IA32_RTIT_CTL) ++ ++#define EVMCS1_SUPPORTED_VMENTRY_CTRL \ ++ (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | \ ++ VM_ENTRY_LOAD_DEBUG_CONTROLS | \ ++ VM_ENTRY_IA32E_MODE | \ ++ VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | \ ++ VM_ENTRY_LOAD_IA32_PAT | \ ++ VM_ENTRY_LOAD_IA32_EFER | \ ++ VM_ENTRY_LOAD_BNDCFGS | \ ++ VM_ENTRY_PT_CONCEAL_PIP | \ ++ VM_ENTRY_LOAD_IA32_RTIT_CTL) ++ ++#define EVMCS1_SUPPORTED_VMFUNC (0) ++ + struct evmcs_field { + u16 offset; + u16 clean_field; +@@ -65,114 +166,6 @@ static inline u64 evmcs_read_any(struct hv_enlightened_vmcs *evmcs, + return vmcs12_read_any((void *)evmcs, field, offset); + } + +-#if IS_ENABLED(CONFIG_HYPERV) +- +-DECLARE_STATIC_KEY_FALSE(__kvm_is_using_evmcs); +- +-static __always_inline bool kvm_is_using_evmcs(void) +-{ +- return static_branch_unlikely(&__kvm_is_using_evmcs); +-} +- +-static __always_inline int get_evmcs_offset(unsigned long field, +- u16 *clean_field) +-{ +- int offset = evmcs_field_offset(field, clean_field); +- +- WARN_ONCE(offset < 0, "accessing unsupported EVMCS field %lx\n", field); +- return offset; +-} +- +-static __always_inline void evmcs_write64(unsigned long field, u64 value) +-{ +- u16 clean_field; +- int offset = get_evmcs_offset(field, &clean_field); +- +- if (offset < 0) +- return; +- +- *(u64 *)((char *)current_evmcs + offset) = value; +- +- current_evmcs->hv_clean_fields &= ~clean_field; +-} +- +-static __always_inline void evmcs_write32(unsigned long field, u32 value) +-{ +- u16 clean_field; +- int offset = get_evmcs_offset(field, &clean_field); +- +- if (offset < 0) +- return; +- +- *(u32 *)((char *)current_evmcs + offset) = value; +- current_evmcs->hv_clean_fields &= ~clean_field; +-} +- +-static __always_inline void evmcs_write16(unsigned long field, u16 value) +-{ +- u16 clean_field; +- int offset = get_evmcs_offset(field, &clean_field); +- +- if (offset < 0) +- return; +- +- *(u16 *)((char *)current_evmcs + offset) = value; +- current_evmcs->hv_clean_fields &= ~clean_field; +-} +- +-static __always_inline u64 evmcs_read64(unsigned long field) +-{ +- int offset = get_evmcs_offset(field, NULL); +- +- if (offset < 0) +- return 0; +- +- return *(u64 *)((char *)current_evmcs + offset); +-} +- +-static __always_inline u32 evmcs_read32(unsigned long field) +-{ +- int offset = get_evmcs_offset(field, NULL); +- +- if (offset < 0) +- return 0; +- +- return *(u32 *)((char *)current_evmcs + offset); +-} +- +-static __always_inline u16 evmcs_read16(unsigned long field) +-{ +- int offset = get_evmcs_offset(field, NULL); +- +- if (offset < 0) +- return 0; +- +- return *(u16 *)((char *)current_evmcs + offset); +-} +- +-static inline void evmcs_load(u64 phys_addr) +-{ +- struct hv_vp_assist_page *vp_ap = +- hv_get_vp_assist_page(smp_processor_id()); +- +- if (current_evmcs->hv_enlightenments_control.nested_flush_hypercall) +- vp_ap->nested_control.features.directhypercall = 1; +- vp_ap->current_nested_vmcs = phys_addr; +- vp_ap->enlighten_vmentry = 1; +-} +- +-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf); +-#else /* !IS_ENABLED(CONFIG_HYPERV) */ +-static __always_inline bool kvm_is_using_evmcs(void) { return false; } +-static __always_inline void evmcs_write64(unsigned long field, u64 value) {} +-static __always_inline void evmcs_write32(unsigned long field, u32 value) {} +-static __always_inline void evmcs_write16(unsigned long field, u16 value) {} +-static __always_inline u64 evmcs_read64(unsigned long field) { return 0; } +-static __always_inline u32 evmcs_read32(unsigned long field) { return 0; } +-static __always_inline u16 evmcs_read16(unsigned long field) { return 0; } +-static inline void evmcs_load(u64 phys_addr) {} +-#endif /* IS_ENABLED(CONFIG_HYPERV) */ +- + #define EVMPTR_INVALID (-1ULL) + #define EVMPTR_MAP_PENDING (-2ULL) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index d1b4a85def0a6..0ad66b9207e85 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -12,6 +12,7 @@ + #include "mmu.h" + #include "nested.h" + #include "pmu.h" ++#include "posted_intr.h" + #include "sgx.h" + #include "trace.h" + #include "vmx.h" +@@ -3830,8 +3831,8 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu) + if (!pi_test_and_clear_on(vmx->nested.pi_desc)) + return 0; + +- max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256); +- if (max_irr != 256) { ++ max_irr = pi_find_highest_vector(vmx->nested.pi_desc); ++ if (max_irr > 0) { + vapic_page = vmx->nested.virtual_apic_map.hva; + if (!vapic_page) + goto mmio_needed; +@@ -3964,8 +3965,40 @@ static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu) + + static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection) + { +- return nested_vmx_preemption_timer_pending(vcpu) || +- to_vmx(vcpu)->nested.mtf_pending; ++ struct vcpu_vmx *vmx = to_vmx(vcpu); ++ void *vapic = vmx->nested.virtual_apic_map.hva; ++ int max_irr, vppr; ++ ++ if (nested_vmx_preemption_timer_pending(vcpu) || ++ vmx->nested.mtf_pending) ++ return true; ++ ++ /* ++ * Virtual Interrupt Delivery doesn't require manual injection. Either ++ * the interrupt is already in GUEST_RVI and will be recognized by CPU ++ * at VM-Entry, or there is a KVM_REQ_EVENT pending and KVM will move ++ * the interrupt from the PIR to RVI prior to entering the guest. ++ */ ++ if (for_injection) ++ return false; ++ ++ if (!nested_cpu_has_vid(get_vmcs12(vcpu)) || ++ __vmx_interrupt_blocked(vcpu)) ++ return false; ++ ++ if (!vapic) ++ return false; ++ ++ vppr = *((u32 *)(vapic + APIC_PROCPRI)); ++ ++ if (vmx->nested.pi_pending && vmx->nested.pi_desc && ++ pi_test_on(vmx->nested.pi_desc)) { ++ max_irr = pi_find_highest_vector(vmx->nested.pi_desc); ++ if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0)) ++ return true; ++ } ++ ++ return false; + } + + /* +diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h +index 26992076552ef..1715d2ab07be5 100644 +--- a/arch/x86/kvm/vmx/posted_intr.h ++++ b/arch/x86/kvm/vmx/posted_intr.h +@@ -2,97 +2,8 @@ + #ifndef __KVM_X86_VMX_POSTED_INTR_H + #define __KVM_X86_VMX_POSTED_INTR_H + +-#define POSTED_INTR_ON 0 +-#define POSTED_INTR_SN 1 +- +-#define PID_TABLE_ENTRY_VALID 1 +- +-/* Posted-Interrupt Descriptor */ +-struct pi_desc { +- u32 pir[8]; /* Posted interrupt requested */ +- union { +- struct { +- /* bit 256 - Outstanding Notification */ +- u16 on : 1, +- /* bit 257 - Suppress Notification */ +- sn : 1, +- /* bit 271:258 - Reserved */ +- rsvd_1 : 14; +- /* bit 279:272 - Notification Vector */ +- u8 nv; +- /* bit 287:280 - Reserved */ +- u8 rsvd_2; +- /* bit 319:288 - Notification Destination */ +- u32 ndst; +- }; +- u64 control; +- }; +- u32 rsvd[6]; +-} __aligned(64); +- +-static inline bool pi_test_and_set_on(struct pi_desc *pi_desc) +-{ +- return test_and_set_bit(POSTED_INTR_ON, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline bool pi_test_and_clear_on(struct pi_desc *pi_desc) +-{ +- return test_and_clear_bit(POSTED_INTR_ON, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc) +-{ +- return test_and_clear_bit(POSTED_INTR_SN, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc) +-{ +- return test_and_set_bit(vector, (unsigned long *)pi_desc->pir); +-} +- +-static inline bool pi_is_pir_empty(struct pi_desc *pi_desc) +-{ +- return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS); +-} +- +-static inline void pi_set_sn(struct pi_desc *pi_desc) +-{ +- set_bit(POSTED_INTR_SN, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline void pi_set_on(struct pi_desc *pi_desc) +-{ +- set_bit(POSTED_INTR_ON, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline void pi_clear_on(struct pi_desc *pi_desc) +-{ +- clear_bit(POSTED_INTR_ON, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline void pi_clear_sn(struct pi_desc *pi_desc) +-{ +- clear_bit(POSTED_INTR_SN, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline bool pi_test_on(struct pi_desc *pi_desc) +-{ +- return test_bit(POSTED_INTR_ON, +- (unsigned long *)&pi_desc->control); +-} +- +-static inline bool pi_test_sn(struct pi_desc *pi_desc) +-{ +- return test_bit(POSTED_INTR_SN, +- (unsigned long *)&pi_desc->control); +-} ++#include ++#include + + void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu); + void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu); +@@ -103,4 +14,12 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq, bool set); + void vmx_pi_start_assignment(struct kvm *kvm); + ++static inline int pi_find_highest_vector(struct pi_desc *pi_desc) ++{ ++ int vec; ++ ++ vec = find_last_bit((unsigned long *)pi_desc->pir, 256); ++ return vec < 256 ? vec : -1; ++} ++ + #endif /* __KVM_X86_VMX_POSTED_INTR_H */ +diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c +index f5f652a546bf2..2e0106d9d371c 100644 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -66,6 +66,8 @@ + #include "vmx.h" + #include "x86.h" + #include "smm.h" ++#include "vmx_onhyperv.h" ++#include "posted_intr.h" + + MODULE_AUTHOR("Qumranet"); + MODULE_LICENSE("GPL"); +diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h +index 912b0c4697429..6be1627d888e5 100644 +--- a/arch/x86/kvm/vmx/vmx.h ++++ b/arch/x86/kvm/vmx/vmx.h +@@ -7,10 +7,10 @@ + #include + #include + #include ++#include + + #include "capabilities.h" + #include "../kvm_cache_regs.h" +-#include "posted_intr.h" + #include "vmcs.h" + #include "vmx_ops.h" + #include "../cpuid.h" +diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.c b/arch/x86/kvm/vmx/vmx_onhyperv.c +new file mode 100644 +index 0000000000000..b9a8b91166d02 +--- /dev/null ++++ b/arch/x86/kvm/vmx/vmx_onhyperv.c +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#include "capabilities.h" ++#include "vmx_onhyperv.h" ++ ++DEFINE_STATIC_KEY_FALSE(__kvm_is_using_evmcs); ++ ++/* ++ * KVM on Hyper-V always uses the latest known eVMCSv1 revision, the assumption ++ * is: in case a feature has corresponding fields in eVMCS described and it was ++ * exposed in VMX feature MSRs, KVM is free to use it. Warn if KVM meets a ++ * feature which has no corresponding eVMCS field, this likely means that KVM ++ * needs to be updated. ++ */ ++#define evmcs_check_vmcs_conf(field, ctrl) \ ++ do { \ ++ typeof(vmcs_conf->field) unsupported; \ ++ \ ++ unsupported = vmcs_conf->field & ~EVMCS1_SUPPORTED_ ## ctrl; \ ++ if (unsupported) { \ ++ pr_warn_once(#field " unsupported with eVMCS: 0x%llx\n",\ ++ (u64)unsupported); \ ++ vmcs_conf->field &= EVMCS1_SUPPORTED_ ## ctrl; \ ++ } \ ++ } \ ++ while (0) ++ ++void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) ++{ ++ evmcs_check_vmcs_conf(cpu_based_exec_ctrl, EXEC_CTRL); ++ evmcs_check_vmcs_conf(pin_based_exec_ctrl, PINCTRL); ++ evmcs_check_vmcs_conf(cpu_based_2nd_exec_ctrl, 2NDEXEC); ++ evmcs_check_vmcs_conf(cpu_based_3rd_exec_ctrl, 3RDEXEC); ++ evmcs_check_vmcs_conf(vmentry_ctrl, VMENTRY_CTRL); ++ evmcs_check_vmcs_conf(vmexit_ctrl, VMEXIT_CTRL); ++} +diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.h b/arch/x86/kvm/vmx/vmx_onhyperv.h +new file mode 100644 +index 0000000000000..11541d272dbd8 +--- /dev/null ++++ b/arch/x86/kvm/vmx/vmx_onhyperv.h +@@ -0,0 +1,124 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef __ARCH_X86_KVM_VMX_ONHYPERV_H__ ++#define __ARCH_X86_KVM_VMX_ONHYPERV_H__ ++ ++#include ++ ++#include ++ ++#include "capabilities.h" ++#include "hyperv.h" ++#include "vmcs12.h" ++ ++#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs)) ++ ++#if IS_ENABLED(CONFIG_HYPERV) ++ ++DECLARE_STATIC_KEY_FALSE(__kvm_is_using_evmcs); ++ ++static __always_inline bool kvm_is_using_evmcs(void) ++{ ++ return static_branch_unlikely(&__kvm_is_using_evmcs); ++} ++ ++static __always_inline int get_evmcs_offset(unsigned long field, ++ u16 *clean_field) ++{ ++ int offset = evmcs_field_offset(field, clean_field); ++ ++ WARN_ONCE(offset < 0, "accessing unsupported EVMCS field %lx\n", field); ++ return offset; ++} ++ ++static __always_inline void evmcs_write64(unsigned long field, u64 value) ++{ ++ u16 clean_field; ++ int offset = get_evmcs_offset(field, &clean_field); ++ ++ if (offset < 0) ++ return; ++ ++ *(u64 *)((char *)current_evmcs + offset) = value; ++ ++ current_evmcs->hv_clean_fields &= ~clean_field; ++} ++ ++static __always_inline void evmcs_write32(unsigned long field, u32 value) ++{ ++ u16 clean_field; ++ int offset = get_evmcs_offset(field, &clean_field); ++ ++ if (offset < 0) ++ return; ++ ++ *(u32 *)((char *)current_evmcs + offset) = value; ++ current_evmcs->hv_clean_fields &= ~clean_field; ++} ++ ++static __always_inline void evmcs_write16(unsigned long field, u16 value) ++{ ++ u16 clean_field; ++ int offset = get_evmcs_offset(field, &clean_field); ++ ++ if (offset < 0) ++ return; ++ ++ *(u16 *)((char *)current_evmcs + offset) = value; ++ current_evmcs->hv_clean_fields &= ~clean_field; ++} ++ ++static __always_inline u64 evmcs_read64(unsigned long field) ++{ ++ int offset = get_evmcs_offset(field, NULL); ++ ++ if (offset < 0) ++ return 0; ++ ++ return *(u64 *)((char *)current_evmcs + offset); ++} ++ ++static __always_inline u32 evmcs_read32(unsigned long field) ++{ ++ int offset = get_evmcs_offset(field, NULL); ++ ++ if (offset < 0) ++ return 0; ++ ++ return *(u32 *)((char *)current_evmcs + offset); ++} ++ ++static __always_inline u16 evmcs_read16(unsigned long field) ++{ ++ int offset = get_evmcs_offset(field, NULL); ++ ++ if (offset < 0) ++ return 0; ++ ++ return *(u16 *)((char *)current_evmcs + offset); ++} ++ ++static inline void evmcs_load(u64 phys_addr) ++{ ++ struct hv_vp_assist_page *vp_ap = ++ hv_get_vp_assist_page(smp_processor_id()); ++ ++ if (current_evmcs->hv_enlightenments_control.nested_flush_hypercall) ++ vp_ap->nested_control.features.directhypercall = 1; ++ vp_ap->current_nested_vmcs = phys_addr; ++ vp_ap->enlighten_vmentry = 1; ++} ++ ++void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf); ++#else /* !IS_ENABLED(CONFIG_HYPERV) */ ++static __always_inline bool kvm_is_using_evmcs(void) { return false; } ++static __always_inline void evmcs_write64(unsigned long field, u64 value) {} ++static __always_inline void evmcs_write32(unsigned long field, u32 value) {} ++static __always_inline void evmcs_write16(unsigned long field, u16 value) {} ++static __always_inline u64 evmcs_read64(unsigned long field) { return 0; } ++static __always_inline u32 evmcs_read32(unsigned long field) { return 0; } ++static __always_inline u16 evmcs_read16(unsigned long field) { return 0; } ++static inline void evmcs_load(u64 phys_addr) {} ++#endif /* IS_ENABLED(CONFIG_HYPERV) */ ++ ++#endif /* __ARCH_X86_KVM_VMX_ONHYPERV_H__ */ +diff --git a/arch/x86/kvm/vmx/vmx_ops.h b/arch/x86/kvm/vmx/vmx_ops.h +index 6a0c6e81f7f3e..8060e5fc6dbd8 100644 +--- a/arch/x86/kvm/vmx/vmx_ops.h ++++ b/arch/x86/kvm/vmx/vmx_ops.h +@@ -6,7 +6,7 @@ + + #include + +-#include "hyperv.h" ++#include "vmx_onhyperv.h" + #include "vmcs.h" + #include "../x86.h" + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 3da3c266a66f3..a936219aebb81 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2845,6 +2845,9 @@ static int btintel_setup_combined(struct hci_dev *hdev) + btintel_set_dsm_reset_method(hdev, &ver_tlv); + + err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); ++ if (err) ++ goto exit_error; ++ + btintel_register_devcoredump_support(hdev); + break; + default: +diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c +index 84d7033e5efe8..ef51dfb39baa9 100644 +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -40,10 +40,14 @@ struct qcom_cpufreq_match_data { + const char **genpd_names; + }; + ++struct qcom_cpufreq_drv_cpu { ++ int opp_token; ++}; ++ + struct qcom_cpufreq_drv { +- int *opp_tokens; + u32 versions; + const struct qcom_cpufreq_match_data *data; ++ struct qcom_cpufreq_drv_cpu cpus[]; + }; + + static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; +@@ -243,42 +247,39 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) + return -ENOENT; + } + +- drv = kzalloc(sizeof(*drv), GFP_KERNEL); +- if (!drv) ++ drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()), ++ GFP_KERNEL); ++ if (!drv) { ++ of_node_put(np); + return -ENOMEM; ++ } + + match = pdev->dev.platform_data; + drv->data = match->data; + if (!drv->data) { +- ret = -ENODEV; +- goto free_drv; ++ of_node_put(np); ++ return -ENODEV; + } + + if (drv->data->get_version) { + speedbin_nvmem = of_nvmem_cell_get(np, NULL); + if (IS_ERR(speedbin_nvmem)) { +- ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), +- "Could not get nvmem cell\n"); +- goto free_drv; ++ of_node_put(np); ++ return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), ++ "Could not get nvmem cell\n"); + } + + ret = drv->data->get_version(cpu_dev, + speedbin_nvmem, &pvs_name, drv); + if (ret) { ++ of_node_put(np); + nvmem_cell_put(speedbin_nvmem); +- goto free_drv; ++ return ret; + } + nvmem_cell_put(speedbin_nvmem); + } + of_node_put(np); + +- drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens), +- GFP_KERNEL); +- if (!drv->opp_tokens) { +- ret = -ENOMEM; +- goto free_drv; +- } +- + for_each_possible_cpu(cpu) { + struct dev_pm_opp_config config = { + .supported_hw = NULL, +@@ -304,9 +305,9 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) + } + + if (config.supported_hw || config.genpd_names) { +- drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config); +- if (drv->opp_tokens[cpu] < 0) { +- ret = drv->opp_tokens[cpu]; ++ drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config); ++ if (drv->cpus[cpu].opp_token < 0) { ++ ret = drv->cpus[cpu].opp_token; + dev_err(cpu_dev, "Failed to set OPP config\n"); + goto free_opp; + } +@@ -325,11 +326,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) + + free_opp: + for_each_possible_cpu(cpu) +- dev_pm_opp_clear_config(drv->opp_tokens[cpu]); +- kfree(drv->opp_tokens); +-free_drv: +- kfree(drv); +- ++ dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); + return ret; + } + +@@ -341,10 +338,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev) + platform_device_unregister(cpufreq_dt_pdev); + + for_each_possible_cpu(cpu) +- dev_pm_opp_clear_config(drv->opp_tokens[cpu]); +- +- kfree(drv->opp_tokens); +- kfree(drv); ++ dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); + } + + static struct platform_driver qcom_cpufreq_driver = { +diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c +index 793f1a7ad5e34..53fdfd32a7e77 100644 +--- a/drivers/dma/fsl-edma-common.c ++++ b/drivers/dma/fsl-edma-common.c +@@ -3,6 +3,7 @@ + // Copyright (c) 2013-2014 Freescale Semiconductor, Inc + // Copyright (c) 2017 Sysam, Angelo Dureghello + ++#include + #include + #include + #include +@@ -74,18 +75,10 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan) + + flags = fsl_edma_drvflags(fsl_chan); + val = edma_readl_chreg(fsl_chan, ch_sbr); +- /* Remote/local swapped wrongly on iMX8 QM Audio edma */ +- if (flags & FSL_EDMA_DRV_QUIRK_SWAPPED) { +- if (!fsl_chan->is_rxchan) +- val |= EDMA_V3_CH_SBR_RD; +- else +- val |= EDMA_V3_CH_SBR_WR; +- } else { +- if (fsl_chan->is_rxchan) +- val |= EDMA_V3_CH_SBR_RD; +- else +- val |= EDMA_V3_CH_SBR_WR; +- } ++ if (fsl_chan->is_rxchan) ++ val |= EDMA_V3_CH_SBR_RD; ++ else ++ val |= EDMA_V3_CH_SBR_WR; + + if (fsl_chan->is_remote) + val &= ~(EDMA_V3_CH_SBR_RD | EDMA_V3_CH_SBR_WR); +@@ -97,8 +90,8 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan) + * ch_mux: With the exception of 0, attempts to write a value + * already in use will be forced to 0. + */ +- if (!edma_readl_chreg(fsl_chan, ch_mux)) +- edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux); ++ if (!edma_readl(fsl_chan->edma, fsl_chan->mux_addr)) ++ edma_writel(fsl_chan->edma, fsl_chan->srcid, fsl_chan->mux_addr); + } + + val = edma_readl_chreg(fsl_chan, ch_csr); +@@ -134,7 +127,7 @@ static void fsl_edma3_disable_request(struct fsl_edma_chan *fsl_chan) + flags = fsl_edma_drvflags(fsl_chan); + + if (flags & FSL_EDMA_DRV_HAS_CHMUX) +- edma_writel_chreg(fsl_chan, 0, ch_mux); ++ edma_writel(fsl_chan->edma, 0, fsl_chan->mux_addr); + + val &= ~EDMA_V3_CH_CSR_ERQ; + edma_writel_chreg(fsl_chan, val, ch_csr); +@@ -754,6 +747,8 @@ struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan, + fsl_desc->iscyclic = false; + + fsl_chan->is_sw = true; ++ if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_MEM_REMOTE) ++ fsl_chan->is_remote = true; + + /* To match with copy_align and max_seg_size so 1 tcd is enough */ + fsl_edma_fill_tcd(fsl_chan, fsl_desc->tcd[0].vtcd, dma_src, dma_dst, +@@ -802,6 +797,9 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan) + { + struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); + ++ if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) ++ clk_prepare_enable(fsl_chan->clk); ++ + fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev, + sizeof(struct fsl_edma_hw_tcd), + 32, 0); +@@ -829,6 +827,9 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan) + fsl_chan->tcd_pool = NULL; + fsl_chan->is_sw = false; + fsl_chan->srcid = 0; ++ fsl_chan->is_remote = false; ++ if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) ++ clk_disable_unprepare(fsl_chan->clk); + } + + void fsl_edma_cleanup_vchan(struct dma_device *dmadev) +diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h +index 92fe53faa53b1..6028389de408b 100644 +--- a/drivers/dma/fsl-edma-common.h ++++ b/drivers/dma/fsl-edma-common.h +@@ -146,6 +146,7 @@ struct fsl_edma_chan { + enum dma_data_direction dma_dir; + char chan_name[32]; + struct fsl_edma_hw_tcd __iomem *tcd; ++ void __iomem *mux_addr; + u32 real_count; + struct work_struct issue_worker; + struct platform_device *pdev; +@@ -177,8 +178,7 @@ struct fsl_edma_desc { + #define FSL_EDMA_DRV_HAS_PD BIT(5) + #define FSL_EDMA_DRV_HAS_CHCLK BIT(6) + #define FSL_EDMA_DRV_HAS_CHMUX BIT(7) +-/* imx8 QM audio edma remote local swapped */ +-#define FSL_EDMA_DRV_QUIRK_SWAPPED BIT(8) ++#define FSL_EDMA_DRV_MEM_REMOTE BIT(8) + /* control and status register is in tcd address space, edma3 reg layout */ + #define FSL_EDMA_DRV_SPLIT_REG BIT(9) + #define FSL_EDMA_DRV_BUS_8BYTE BIT(10) +@@ -207,6 +207,8 @@ struct fsl_edma_drvdata { + u32 chreg_off; + u32 chreg_space_sz; + u32 flags; ++ u32 mux_off; /* channel mux register offset */ ++ u32 mux_skip; /* how much skip for each channel */ + int (*setup_irq)(struct platform_device *pdev, + struct fsl_edma_engine *fsl_edma); + }; +diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c +index 42a338cbe6143..8a0ae90548997 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -340,16 +340,19 @@ static struct fsl_edma_drvdata imx7ulp_data = { + }; + + static struct fsl_edma_drvdata imx8qm_data = { +- .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3, ++ .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE, + .chreg_space_sz = 0x10000, + .chreg_off = 0x10000, + .setup_irq = fsl_edma3_irq_init, + }; + +-static struct fsl_edma_drvdata imx8qm_audio_data = { +- .flags = FSL_EDMA_DRV_QUIRK_SWAPPED | FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3, ++static struct fsl_edma_drvdata imx8ulp_data = { ++ .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_CHCLK | FSL_EDMA_DRV_HAS_DMACLK | ++ FSL_EDMA_DRV_EDMA3, + .chreg_space_sz = 0x10000, + .chreg_off = 0x10000, ++ .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux), ++ .mux_skip = 0x10000, + .setup_irq = fsl_edma3_irq_init, + }; + +@@ -364,6 +367,8 @@ static struct fsl_edma_drvdata imx93_data4 = { + .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4, + .chreg_space_sz = 0x8000, + .chreg_off = 0x10000, ++ .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux), ++ .mux_skip = 0x8000, + .setup_irq = fsl_edma3_irq_init, + }; + +@@ -372,7 +377,7 @@ static const struct of_device_id fsl_edma_dt_ids[] = { + { .compatible = "fsl,ls1028a-edma", .data = &ls1028a_data}, + { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data}, + { .compatible = "fsl,imx8qm-edma", .data = &imx8qm_data}, +- { .compatible = "fsl,imx8qm-adma", .data = &imx8qm_audio_data}, ++ { .compatible = "fsl,imx8ulp-edma", .data = &imx8ulp_data}, + { .compatible = "fsl,imx93-edma3", .data = &imx93_data3}, + { .compatible = "fsl,imx93-edma4", .data = &imx93_data4}, + { /* sentinel */ } +@@ -427,6 +432,7 @@ static int fsl_edma_probe(struct platform_device *pdev) + struct fsl_edma_engine *fsl_edma; + const struct fsl_edma_drvdata *drvdata = NULL; + u32 chan_mask[2] = {0, 0}; ++ char clk_name[36]; + struct edma_regs *regs; + int chans; + int ret, i; +@@ -540,12 +546,23 @@ static int fsl_edma_probe(struct platform_device *pdev) + offsetof(struct fsl_edma3_ch_reg, tcd) : 0; + fsl_chan->tcd = fsl_edma->membase + + i * drvdata->chreg_space_sz + drvdata->chreg_off + len; ++ fsl_chan->mux_addr = fsl_edma->membase + drvdata->mux_off + i * drvdata->mux_skip; + ++ if (drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) { ++ snprintf(clk_name, sizeof(clk_name), "ch%02d", i); ++ fsl_chan->clk = devm_clk_get_enabled(&pdev->dev, ++ (const char *)clk_name); ++ ++ if (IS_ERR(fsl_chan->clk)) ++ return PTR_ERR(fsl_chan->clk); ++ } + fsl_chan->pdev = pdev; + vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev); + + edma_write_tcdreg(fsl_chan, 0, csr); + fsl_edma_chan_mux(fsl_chan, 0, false); ++ if (fsl_chan->edma->drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) ++ clk_disable_unprepare(fsl_chan->clk); + } + + ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma); +diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig +index b59e3041fd627..f0e9f250669e2 100644 +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -229,6 +229,7 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT + config SYSFB + bool + select BOOT_VESA_SUPPORT ++ select SCREEN_INFO + + config SYSFB_SIMPLEFB + bool "Mark VGA/VBE/EFI FB as generic system framebuffer" +diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c +index 3c197db42c9d9..defd7a36cb08a 100644 +--- a/drivers/firmware/sysfb.c ++++ b/drivers/firmware/sysfb.c +@@ -77,6 +77,8 @@ static __init int sysfb_init(void) + bool compatible; + int ret = 0; + ++ screen_info_apply_fixups(); ++ + mutex_lock(&disable_lock); + if (disabled) + goto unlock_mutex; +diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +index d0255ea98348d..247e7d675e2b9 100644 +--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c ++++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +@@ -1556,7 +1556,7 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params *params, + } + + static int +-skl_ddi_calculate_wrpll(int clock /* in Hz */, ++skl_ddi_calculate_wrpll(int clock, + int ref_clock, + struct skl_wrpll_params *wrpll_params) + { +@@ -1581,7 +1581,7 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, + }; + unsigned int dco, d, i; + unsigned int p0, p1, p2; +- u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ ++ u64 afe_clock = (u64)clock * 1000 * 5; /* AFE Clock is 5x Pixel clock, in Hz */ + + for (d = 0; d < ARRAY_SIZE(dividers); d++) { + for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { +@@ -1713,7 +1713,7 @@ static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) + + ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); + +- ret = skl_ddi_calculate_wrpll(crtc_state->port_clock * 1000, ++ ret = skl_ddi_calculate_wrpll(crtc_state->port_clock, + i915->display.dpll.ref_clks.nssc, &wrpll_params); + if (ret) + return ret; +diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h +index 8023c85c7fa0e..74059384892af 100644 +--- a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h ++++ b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h +@@ -249,7 +249,7 @@ + #define HDCP2_STREAM_STATUS(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_STREAM_STATUS(trans) : \ +- PIPE_HDCP2_STREAM_STATUS(pipe)) ++ PIPE_HDCP2_STREAM_STATUS(port)) + + #define _PORTA_HDCP2_AUTH_STREAM 0x66F00 + #define _PORTB_HDCP2_AUTH_STREAM 0x66F04 +diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c +index 3f90403d86cb4..0808b54d3c518 100644 +--- a/drivers/gpu/drm/i915/i915_perf.c ++++ b/drivers/gpu/drm/i915/i915_perf.c +@@ -2781,26 +2781,6 @@ oa_configure_all_contexts(struct i915_perf_stream *stream, + return 0; + } + +-static int +-gen12_configure_all_contexts(struct i915_perf_stream *stream, +- const struct i915_oa_config *oa_config, +- struct i915_active *active) +-{ +- struct flex regs[] = { +- { +- GEN8_R_PWR_CLK_STATE(RENDER_RING_BASE), +- CTX_R_PWR_CLK_STATE, +- }, +- }; +- +- if (stream->engine->class != RENDER_CLASS) +- return 0; +- +- return oa_configure_all_contexts(stream, +- regs, ARRAY_SIZE(regs), +- active); +-} +- + static int + lrc_configure_all_contexts(struct i915_perf_stream *stream, + const struct i915_oa_config *oa_config, +@@ -2907,7 +2887,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, + { + struct drm_i915_private *i915 = stream->perf->i915; + struct intel_uncore *uncore = stream->uncore; +- struct i915_oa_config *oa_config = stream->oa_config; + bool periodic = stream->periodic; + u32 period_exponent = stream->period_exponent; + u32 sqcnt1; +@@ -2951,15 +2930,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, + + intel_uncore_rmw(uncore, GEN12_SQCNT1, 0, sqcnt1); + +- /* +- * Update all contexts prior writing the mux configurations as we need +- * to make sure all slices/subslices are ON before writing to NOA +- * registers. +- */ +- ret = gen12_configure_all_contexts(stream, oa_config, active); +- if (ret) +- return ret; +- + /* + * For Gen12, performance counters are context + * saved/restored. Only enable it for the context that +@@ -3014,9 +2984,6 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream) + _MASKED_BIT_DISABLE(GEN12_DISABLE_DOP_GATING)); + } + +- /* Reset all contexts' slices/subslices configurations. */ +- gen12_configure_all_contexts(stream, NULL, NULL); +- + /* disable the context save/restore or OAR counters */ + if (stream->ctx) + gen12_configure_oar_context(stream, NULL); +diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c +index 1b2ff0c40fc1c..6c599a9f49ee4 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_prime.c ++++ b/drivers/gpu/drm/nouveau/nouveau_prime.c +@@ -64,7 +64,8 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, + * to the caller, instead of a normal nouveau_bo ttm reference. */ + ret = drm_gem_object_init(dev, &nvbo->bo.base, size); + if (ret) { +- nouveau_bo_ref(NULL, &nvbo); ++ drm_gem_object_release(&nvbo->bo.base); ++ kfree(nvbo); + obj = ERR_PTR(-ENOMEM); + goto unlock; + } +diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c b/drivers/gpu/drm/virtio/virtgpu_submit.c +index 5c514946bbad9..d530c058f53e2 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_submit.c ++++ b/drivers/gpu/drm/virtio/virtgpu_submit.c +@@ -48,7 +48,7 @@ struct virtio_gpu_submit { + static int virtio_gpu_do_fence_wait(struct virtio_gpu_submit *submit, + struct dma_fence *in_fence) + { +- u32 context = submit->fence_ctx + submit->ring_idx; ++ u64 context = submit->fence_ctx + submit->ring_idx; + + if (dma_fence_match_context(in_fence, context)) + return 0; +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +index 5efc6a766f64e..588d50ababf60 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -32,7 +32,6 @@ + #define VMW_FENCE_WRAP (1 << 31) + + struct vmw_fence_manager { +- int num_fence_objects; + struct vmw_private *dev_priv; + spinlock_t lock; + struct list_head fence_list; +@@ -124,13 +123,13 @@ static void vmw_fence_obj_destroy(struct dma_fence *f) + { + struct vmw_fence_obj *fence = + container_of(f, struct vmw_fence_obj, base); +- + struct vmw_fence_manager *fman = fman_from_fence(fence); + +- spin_lock(&fman->lock); +- list_del_init(&fence->head); +- --fman->num_fence_objects; +- spin_unlock(&fman->lock); ++ if (!list_empty(&fence->head)) { ++ spin_lock(&fman->lock); ++ list_del_init(&fence->head); ++ spin_unlock(&fman->lock); ++ } + fence->destroy(fence); + } + +@@ -257,7 +256,6 @@ static const struct dma_fence_ops vmw_fence_ops = { + .release = vmw_fence_obj_destroy, + }; + +- + /* + * Execute signal actions on fences recently signaled. + * This is done from a workqueue so we don't have to execute +@@ -355,7 +353,6 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, + goto out_unlock; + } + list_add_tail(&fence->head, &fman->fence_list); +- ++fman->num_fence_objects; + + out_unlock: + spin_unlock(&fman->lock); +@@ -403,7 +400,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, + u32 passed_seqno) + { + u32 goal_seqno; +- struct vmw_fence_obj *fence; ++ struct vmw_fence_obj *fence, *next_fence; + + if (likely(!fman->seqno_valid)) + return false; +@@ -413,7 +410,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, + return false; + + fman->seqno_valid = false; +- list_for_each_entry(fence, &fman->fence_list, head) { ++ list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { + if (!list_empty(&fence->seq_passed_actions)) { + fman->seqno_valid = true; + vmw_fence_goal_write(fman->dev_priv, +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +index c45b4724e4141..e20f64b67b266 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +@@ -92,7 +92,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, + { + struct vmw_escape_video_flush *flush; + size_t fifo_size; +- bool have_so = (dev_priv->active_display_unit == vmw_du_screen_object); ++ bool have_so = (dev_priv->active_display_unit != vmw_du_legacy); + int i, num_items; + SVGAGuestPtr ptr; + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +index 4ccab07faff08..cb03c589ab226 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +@@ -868,6 +868,32 @@ vmw_stdu_connector_mode_valid(struct drm_connector *connector, + return MODE_OK; + } + ++/* ++ * Trigger a modeset if the X,Y position of the Screen Target changes. ++ * This is needed when multi-mon is cycled. The original Screen Target will have ++ * the same mode but its relative X,Y position in the topology will change. ++ */ ++static int vmw_stdu_connector_atomic_check(struct drm_connector *conn, ++ struct drm_atomic_state *state) ++{ ++ struct drm_connector_state *conn_state; ++ struct vmw_screen_target_display_unit *du; ++ struct drm_crtc_state *new_crtc_state; ++ ++ conn_state = drm_atomic_get_connector_state(state, conn); ++ du = vmw_connector_to_stdu(conn); ++ ++ if (!conn_state->crtc) ++ return 0; ++ ++ new_crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); ++ if (du->base.gui_x != du->base.set_gui_x || ++ du->base.gui_y != du->base.set_gui_y) ++ new_crtc_state->mode_changed = true; ++ ++ return 0; ++} ++ + static const struct drm_connector_funcs vmw_stdu_connector_funcs = { + .dpms = vmw_du_connector_dpms, + .detect = vmw_du_connector_detect, +@@ -882,7 +908,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = { + static const struct + drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { + .get_modes = vmw_connector_get_modes, +- .mode_valid = vmw_stdu_connector_mode_valid ++ .mode_valid = vmw_stdu_connector_mode_valid, ++ .atomic_check = vmw_stdu_connector_atomic_check, + }; + + +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +index bdb578e0899f5..4b59687ff5d82 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +@@ -288,12 +288,22 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) + mp2_ops->start(privdata, info); + cl_data->sensor_sts[i] = amd_sfh_wait_for_response + (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); ++ ++ if (cl_data->sensor_sts[i] == SENSOR_ENABLED) ++ cl_data->is_any_sensor_enabled = true; ++ } ++ ++ if (!cl_data->is_any_sensor_enabled || ++ (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { ++ dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", ++ cl_data->is_any_sensor_enabled); ++ rc = -EOPNOTSUPP; ++ goto cleanup; + } + + for (i = 0; i < cl_data->num_hid_devices; i++) { + cl_data->cur_hid_dev = i; + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { +- cl_data->is_any_sensor_enabled = true; + rc = amdtp_hid_probe(i, cl_data); + if (rc) + goto cleanup; +@@ -305,12 +315,6 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) + cl_data->sensor_sts[i]); + } + +- if (!cl_data->is_any_sensor_enabled || +- (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { +- dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); +- rc = -EOPNOTSUPP; +- goto cleanup; +- } + schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); + return 0; + +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index 002cbaa16bd16..d2fe14ce423e2 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -714,13 +714,12 @@ static int wacom_intuos_get_tool_type(int tool_id) + case 0x8e2: /* IntuosHT2 pen */ + case 0x022: + case 0x200: /* Pro Pen 3 */ +- case 0x04200: /* Pro Pen 3 */ + case 0x10842: /* MobileStudio Pro Pro Pen slim */ + case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ + case 0x16802: /* Cintiq 13HD Pro Pen */ + case 0x18802: /* DTH2242 Pen */ + case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ +- case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */ ++ case 0x8842: /* Intuos Pro and Cintiq Pro 3D Pen */ + tool_type = BTN_TOOL_PEN; + break; + +diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c +index 4f5829b726a75..72fd2fe8f6fe8 100644 +--- a/drivers/leds/led-triggers.c ++++ b/drivers/leds/led-triggers.c +@@ -194,11 +194,24 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) + spin_unlock(&trig->leddev_list_lock); + led_cdev->trigger = trig; + ++ /* ++ * Some activate() calls use led_trigger_event() to initialize ++ * the brightness of the LED for which the trigger is being set. ++ * Ensure the led_cdev is visible on trig->led_cdevs for this. ++ */ ++ synchronize_rcu(); ++ ++ /* ++ * If "set brightness to 0" is pending in workqueue, ++ * we don't want that to be reordered after ->activate() ++ */ ++ flush_work(&led_cdev->set_brightness_work); ++ ++ ret = 0; + if (trig->activate) + ret = trig->activate(led_cdev); + else +- ret = 0; +- ++ led_set_brightness(led_cdev, trig->brightness); + if (ret) + goto err_activate; + +@@ -269,19 +282,6 @@ void led_trigger_set_default(struct led_classdev *led_cdev) + } + EXPORT_SYMBOL_GPL(led_trigger_set_default); + +-void led_trigger_rename_static(const char *name, struct led_trigger *trig) +-{ +- /* new name must be on a temporary string to prevent races */ +- BUG_ON(name == trig->name); +- +- down_write(&triggers_list_lock); +- /* this assumes that trig->name was originaly allocated to +- * non constant storage */ +- strcpy((char *)trig->name, name); +- up_write(&triggers_list_lock); +-} +-EXPORT_SYMBOL_GPL(led_trigger_rename_static); +- + /* LED Trigger Interface */ + + int led_trigger_register(struct led_trigger *trig) +@@ -386,6 +386,8 @@ void led_trigger_event(struct led_trigger *trig, + if (!trig) + return; + ++ trig->brightness = brightness; ++ + rcu_read_lock(); + list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) + led_set_brightness(led_cdev, brightness); +diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c +index b4688d1d9d2b2..1d213c999d40a 100644 +--- a/drivers/leds/trigger/ledtrig-timer.c ++++ b/drivers/leds/trigger/ledtrig-timer.c +@@ -110,11 +110,6 @@ static int timer_trig_activate(struct led_classdev *led_cdev) + led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER; + } + +- /* +- * If "set brightness to 0" is pending in workqueue, we don't +- * want that to be reordered after blink_set() +- */ +- flush_work(&led_cdev->set_brightness_work); + led_blink_set(led_cdev, &led_cdev->blink_delay_on, + &led_cdev->blink_delay_off); + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 24c914015973e..49b1fa9651161 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -456,7 +456,7 @@ void ice_free_rx_ring(struct ice_rx_ring *rx_ring) + if (rx_ring->vsi->type == ICE_VSI_PF) + if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) + xdp_rxq_info_unreg(&rx_ring->xdp_rxq); +- rx_ring->xdp_prog = NULL; ++ WRITE_ONCE(rx_ring->xdp_prog, NULL); + if (rx_ring->xsk_pool) { + kfree(rx_ring->xdp_buf); + rx_ring->xdp_buf = NULL; +diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c +index f53566cb6bfbd..67511153081ae 100644 +--- a/drivers/net/ethernet/intel/ice/ice_xsk.c ++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c +@@ -52,10 +52,8 @@ static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx) + static void ice_qp_clean_rings(struct ice_vsi *vsi, u16 q_idx) + { + ice_clean_tx_ring(vsi->tx_rings[q_idx]); +- if (ice_is_xdp_ena_vsi(vsi)) { +- synchronize_rcu(); ++ if (ice_is_xdp_ena_vsi(vsi)) + ice_clean_tx_ring(vsi->xdp_rings[q_idx]); +- } + ice_clean_rx_ring(vsi->rx_rings[q_idx]); + } + +@@ -180,11 +178,12 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) + usleep_range(1000, 2000); + } + ++ synchronize_net(); ++ netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); ++ + ice_qvec_dis_irq(vsi, rx_ring, q_vector); + ice_qvec_toggle_napi(vsi, q_vector, false); + +- netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); +- + ice_fill_txq_meta(vsi, tx_ring, &txq_meta); + err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta); + if (err) +@@ -199,10 +198,8 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) + if (err) + return err; + } +- err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true); +- if (err) +- return err; + ++ ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, false); + ice_qp_clean_rings(vsi, q_idx); + ice_qp_reset_stats(vsi, q_idx); + +@@ -1068,6 +1065,10 @@ bool ice_xmit_zc(struct ice_tx_ring *xdp_ring) + + ice_clean_xdp_irq_zc(xdp_ring); + ++ if (!netif_carrier_ok(xdp_ring->vsi->netdev) || ++ !netif_running(xdp_ring->vsi->netdev)) ++ return true; ++ + budget = ICE_DESC_UNUSED(xdp_ring); + budget = min_t(u16, budget, ICE_RING_QUARTER(xdp_ring)); + +@@ -1111,7 +1112,7 @@ ice_xsk_wakeup(struct net_device *netdev, u32 queue_id, + struct ice_vsi *vsi = np->vsi; + struct ice_tx_ring *ring; + +- if (test_bit(ICE_VSI_DOWN, vsi->state)) ++ if (test_bit(ICE_VSI_DOWN, vsi->state) || !netif_carrier_ok(netdev)) + return -ENETDOWN; + + if (!ice_is_xdp_ena_vsi(vsi)) +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index e83700ad7e622..d80bbcdeb93ed 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -6208,21 +6208,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + size_t n; + int i; + +- switch (qopt->cmd) { +- case TAPRIO_CMD_REPLACE: +- break; +- case TAPRIO_CMD_DESTROY: +- return igc_tsn_clear_schedule(adapter); +- case TAPRIO_CMD_STATS: +- igc_taprio_stats(adapter->netdev, &qopt->stats); +- return 0; +- case TAPRIO_CMD_QUEUE_STATS: +- igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); +- return 0; +- default: +- return -EOPNOTSUPP; +- } +- + if (qopt->base_time < 0) + return -ERANGE; + +@@ -6331,7 +6316,23 @@ static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter, + if (hw->mac.type != igc_i225) + return -EOPNOTSUPP; + +- err = igc_save_qbv_schedule(adapter, qopt); ++ switch (qopt->cmd) { ++ case TAPRIO_CMD_REPLACE: ++ err = igc_save_qbv_schedule(adapter, qopt); ++ break; ++ case TAPRIO_CMD_DESTROY: ++ err = igc_tsn_clear_schedule(adapter); ++ break; ++ case TAPRIO_CMD_STATS: ++ igc_taprio_stats(adapter->netdev, &qopt->stats); ++ return 0; ++ case TAPRIO_CMD_QUEUE_STATS: ++ igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); ++ return 0; ++ default: ++ return -EOPNOTSUPP; ++ } ++ + if (err) + return err; + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index 05f4aa11b95c3..34051c9abd97d 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -953,13 +953,13 @@ static void mvpp2_bm_pool_update_fc(struct mvpp2_port *port, + static void mvpp2_bm_pool_update_priv_fc(struct mvpp2 *priv, bool en) + { + struct mvpp2_port *port; +- int i; ++ int i, j; + + for (i = 0; i < priv->port_count; i++) { + port = priv->port_list[i]; + if (port->priv->percpu_pools) { +- for (i = 0; i < port->nrxqs; i++) +- mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], ++ for (j = 0; j < port->nrxqs; j++) ++ mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[j], + port->tx_fc & en); + } else { + mvpp2_bm_pool_update_fc(port, port->pool_long, port->tx_fc & en); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +index fadfa8b50bebe..8c4e3ecef5901 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +@@ -920,6 +920,7 @@ mlx5_tc_ct_entry_replace_rule(struct mlx5_tc_ct_priv *ct_priv, + mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, zone_rule->attr, mh); + mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id); + err_mod_hdr: ++ *attr = *old_attr; + kfree(old_attr); + err_attr: + kvfree(spec); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +index ce29e31721208..de83567aae791 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +@@ -50,9 +50,10 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) + caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; + +- if ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && +- MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || +- MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level)) ++ if (IS_ENABLED(CONFIG_MLX5_CLS_ACT) && ++ ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && ++ MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || ++ MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level))) + caps |= MLX5_IPSEC_CAP_PRIO; + + if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index 38263d5c98b34..50db127e6371b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -1223,7 +1223,12 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, + if (!an_changes && link_modes == eproto.admin) + goto out; + +- mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext); ++ err = mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext); ++ if (err) { ++ netdev_err(priv->netdev, "%s: failed to set ptys reg: %d\n", __func__, err); ++ goto out; ++ } ++ + mlx5_toggle_port_link(mdev); + + out: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 3a9cdf79403ae..6b17346aa4cef 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -206,6 +206,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) + static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) + { + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ struct devlink *devlink = priv_to_devlink(dev); + + /* if this is the driver that initiated the fw reset, devlink completed the reload */ + if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { +@@ -217,9 +218,11 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload + mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); + else + mlx5_load_one(dev, true); +- devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0, ++ devl_lock(devlink); ++ devlink_remote_reload_actions_performed(devlink, 0, + BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); ++ devl_unlock(devlink); + } + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +index 612e666ec2635..e2230c8f18152 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +@@ -48,6 +48,7 @@ static struct mlx5_irq * + irq_pool_request_irq(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_desc) + { + struct irq_affinity_desc auto_desc = {}; ++ struct mlx5_irq *irq; + u32 irq_index; + int err; + +@@ -64,9 +65,12 @@ irq_pool_request_irq(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_de + else + cpu_get(pool, cpumask_first(&af_desc->mask)); + } +- return mlx5_irq_alloc(pool, irq_index, +- cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc, +- NULL); ++ irq = mlx5_irq_alloc(pool, irq_index, ++ cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc, ++ NULL); ++ if (IS_ERR(irq)) ++ xa_erase(&pool->irqs, irq_index); ++ return irq; + } + + /* Looking for the IRQ with the smallest refcount that fits req_mask. +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index dfc2ba6f780a2..18cf756bad8cc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -1512,7 +1512,7 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev, + goto unlock; + + for (i = 0; i < ldev->ports; i++) { +- if (ldev->pf[MLX5_LAG_P1].netdev == slave) { ++ if (ldev->pf[i].netdev == slave) { + port = i; + break; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 2237b3d01e0e5..11f11248feb8b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -2130,7 +2130,6 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev *dev) + /* Panic tear down fw command will stop the PCI bus communication + * with the HCA, so the health poll is no longer needed. + */ +- mlx5_drain_health_wq(dev); + mlx5_stop_health_poll(dev, false); + + ret = mlx5_cmd_fast_teardown_hca(dev); +@@ -2165,6 +2164,7 @@ static void shutdown(struct pci_dev *pdev) + + mlx5_core_info(dev, "Shutdown was called\n"); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); ++ mlx5_drain_health_wq(dev); + err = mlx5_try_fast_unload(dev); + if (err) + mlx5_unload_one(dev, false); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +index 30218f37d5285..2028acbe85ca2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +@@ -90,6 +90,7 @@ static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev) + struct mlx5_core_dev *mdev = sf_dev->mdev; + + set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); ++ mlx5_drain_health_wq(mdev); + mlx5_unload_one(mdev, false); + } + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index d759f3373b175..8a732edac15a0 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -4256,7 +4256,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + if (unlikely(!rtl_tx_slots_avail(tp))) { + if (net_ratelimit()) + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); +- goto err_stop_0; ++ netif_stop_queue(dev); ++ return NETDEV_TX_BUSY; + } + + opts[1] = rtl8169_tx_vlan_tag(skb); +@@ -4312,11 +4313,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +- +-err_stop_0: +- netif_stop_queue(dev); +- dev->stats.tx_dropped++; +- return NETDEV_TX_BUSY; + } + + static unsigned int rtl_last_frag_len(struct sk_buff *skb) +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 3297aff969c80..11e08cb8d3c3e 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1826,9 +1826,9 @@ static void axienet_dma_err_handler(struct work_struct *work) + ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + axienet_set_mac_address(ndev, NULL); + axienet_set_multicast_list(ndev); +- axienet_setoptions(ndev, lp->options); + napi_enable(&lp->napi_rx); + napi_enable(&lp->napi_tx); ++ axienet_setoptions(ndev, lp->options); + } + + /** +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 029c82f88ee38..9a0432145645f 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -1293,6 +1293,8 @@ static int ksz9131_config_init(struct phy_device *phydev) + const struct device *dev_walker; + int ret; + ++ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; ++ + dev_walker = &phydev->mdio.dev; + do { + of_node = dev_walker->of_node; +@@ -1342,28 +1344,30 @@ static int ksz9131_config_init(struct phy_device *phydev) + #define MII_KSZ9131_AUTO_MDIX 0x1C + #define MII_KSZ9131_AUTO_MDI_SET BIT(7) + #define MII_KSZ9131_AUTO_MDIX_SWAP_OFF BIT(6) ++#define MII_KSZ9131_DIG_AXAN_STS 0x14 ++#define MII_KSZ9131_DIG_AXAN_STS_LINK_DET BIT(14) ++#define MII_KSZ9131_DIG_AXAN_STS_A_SELECT BIT(12) + + static int ksz9131_mdix_update(struct phy_device *phydev) + { + int ret; + +- ret = phy_read(phydev, MII_KSZ9131_AUTO_MDIX); +- if (ret < 0) +- return ret; +- +- if (ret & MII_KSZ9131_AUTO_MDIX_SWAP_OFF) { +- if (ret & MII_KSZ9131_AUTO_MDI_SET) +- phydev->mdix_ctrl = ETH_TP_MDI; +- else +- phydev->mdix_ctrl = ETH_TP_MDI_X; ++ if (phydev->mdix_ctrl != ETH_TP_MDI_AUTO) { ++ phydev->mdix = phydev->mdix_ctrl; + } else { +- phydev->mdix_ctrl = ETH_TP_MDI_AUTO; +- } ++ ret = phy_read(phydev, MII_KSZ9131_DIG_AXAN_STS); ++ if (ret < 0) ++ return ret; + +- if (ret & MII_KSZ9131_AUTO_MDI_SET) +- phydev->mdix = ETH_TP_MDI; +- else +- phydev->mdix = ETH_TP_MDI_X; ++ if (ret & MII_KSZ9131_DIG_AXAN_STS_LINK_DET) { ++ if (ret & MII_KSZ9131_DIG_AXAN_STS_A_SELECT) ++ phydev->mdix = ETH_TP_MDI; ++ else ++ phydev->mdix = ETH_TP_MDI_X; ++ } else { ++ phydev->mdix = ETH_TP_MDI_INVALID; ++ } ++ } + + return 0; + } +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 337899c69738e..2604d9663a5b2 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -1083,6 +1083,13 @@ static struct phy_driver realtek_drvs[] = { + .handle_interrupt = genphy_handle_interrupt_no_ack, + .suspend = genphy_suspend, + .resume = genphy_resume, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc960), ++ .name = "RTL8366S Gigabit Ethernet", ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_mmd = genphy_read_mmd_unsupported, ++ .write_mmd = genphy_write_mmd_unsupported, + }, + }; + +diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c +index 0a662e42ed965..cb7d2f798fb43 100644 +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -179,6 +179,7 @@ static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc) + struct usbnet *dev = netdev_priv(netdev); + __le16 res; + int rc = 0; ++ int err; + + if (phy_id) { + netdev_dbg(netdev, "Only internal phy supported\n"); +@@ -189,11 +190,17 @@ static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc) + if (loc == MII_BMSR) { + u8 value; + +- sr_read_reg(dev, SR_NSR, &value); ++ err = sr_read_reg(dev, SR_NSR, &value); ++ if (err < 0) ++ return err; ++ + if (value & NSR_LINKST) + rc = 1; + } +- sr_share_read_word(dev, 1, loc, &res); ++ err = sr_share_read_word(dev, 1, loc, &res); ++ if (err < 0) ++ return err; ++ + if (rc == 1) + res = le16_to_cpu(res) | BMSR_LSTATUS; + else +diff --git a/drivers/pci/search.c b/drivers/pci/search.c +index b4c138a6ec025..53840634fbfc2 100644 +--- a/drivers/pci/search.c ++++ b/drivers/pci/search.c +@@ -363,6 +363,37 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) + } + EXPORT_SYMBOL(pci_get_class); + ++/** ++ * pci_get_base_class - searching for a PCI device by matching against the base class code only ++ * @class: search for a PCI device with this base class code ++ * @from: Previous PCI device found in search, or %NULL for new search. ++ * ++ * Iterates through the list of known PCI devices. If a PCI device is found ++ * with a matching base class code, the reference count to the device is ++ * incremented. See pci_match_one_device() to figure out how does this works. ++ * A new search is initiated by passing %NULL as the @from argument. ++ * Otherwise if @from is not %NULL, searches continue from next device on the ++ * global list. The reference count for @from is always decremented if it is ++ * not %NULL. ++ * ++ * Returns: ++ * A pointer to a matched PCI device, %NULL Otherwise. ++ */ ++struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from) ++{ ++ struct pci_device_id id = { ++ .vendor = PCI_ANY_ID, ++ .device = PCI_ANY_ID, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .class_mask = 0xFF0000, ++ .class = class << 16, ++ }; ++ ++ return pci_get_dev_by_id(&id, from); ++} ++EXPORT_SYMBOL(pci_get_base_class); ++ + /** + * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. + * @ids: A pointer to a null terminated list of struct pci_device_id structures +diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c +index 5cf770a1bc312..4f6eade522024 100644 +--- a/drivers/perf/fsl_imx9_ddr_perf.c ++++ b/drivers/perf/fsl_imx9_ddr_perf.c +@@ -476,12 +476,12 @@ static int ddr_perf_event_add(struct perf_event *event, int flags) + hwc->idx = counter; + hwc->state |= PERF_HES_STOPPED; + +- if (flags & PERF_EF_START) +- ddr_perf_event_start(event, flags); +- + /* read trans, write trans, read beat */ + ddr_perf_monitor_config(pmu, cfg, cfg1, cfg2); + ++ if (flags & PERF_EF_START) ++ ddr_perf_event_start(event, flags); ++ + return 0; + } + +diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c +index ae16ecb15f2d9..901da688ea3f8 100644 +--- a/drivers/perf/riscv_pmu_sbi.c ++++ b/drivers/perf/riscv_pmu_sbi.c +@@ -355,7 +355,7 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event) + * but not in the user access mode as we want to use the other counters + * that support sampling/filtering. + */ +- if (hwc->flags & PERF_EVENT_FLAG_LEGACY) { ++ if ((hwc->flags & PERF_EVENT_FLAG_LEGACY) && (event->attr.type == PERF_TYPE_HARDWARE)) { + if (event->attr.config == PERF_COUNT_HW_CPU_CYCLES) { + cflags |= SBI_PMU_CFG_FLAG_SKIP_MATCH; + cmask = 1; +diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c +index 475a6dd72db6b..809fabef3b44a 100644 +--- a/drivers/platform/chrome/cros_ec_proto.c ++++ b/drivers/platform/chrome/cros_ec_proto.c +@@ -805,9 +805,11 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, + if (ret == -ENOPROTOOPT) { + dev_dbg(ec_dev->dev, + "GET_NEXT_EVENT returned invalid version error.\n"); ++ mutex_lock(&ec_dev->lock); + ret = cros_ec_get_host_command_version_mask(ec_dev, + EC_CMD_GET_NEXT_EVENT, + &ver_mask); ++ mutex_unlock(&ec_dev->lock); + if (ret < 0 || ver_mask == 0) + /* + * Do not change the MKBP supported version if we can't +diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c +index 3acc9288b3105..3b1030fc4fbfe 100644 +--- a/drivers/thermal/broadcom/bcm2835_thermal.c ++++ b/drivers/thermal/broadcom/bcm2835_thermal.c +@@ -185,7 +185,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) + return err; + } + +- data->clk = devm_clk_get(&pdev->dev, NULL); ++ data->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(data->clk)) { + err = PTR_ERR(data->clk); + if (err != -EPROBE_DEFER) +@@ -193,10 +193,6 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) + return err; + } + +- err = clk_prepare_enable(data->clk); +- if (err) +- return err; +- + rate = clk_get_rate(data->clk); + if ((rate < 1920000) || (rate > 5000000)) + dev_warn(&pdev->dev, +@@ -211,7 +207,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) + dev_err(&pdev->dev, + "Failed to register the thermal device: %d\n", + err); +- goto err_clk; ++ return err; + } + + /* +@@ -236,7 +232,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) + dev_err(&pdev->dev, + "Not able to read trip_temp: %d\n", + err); +- goto err_tz; ++ return err; + } + + /* set bandgap reference voltage and enable voltage regulator */ +@@ -269,32 +265,23 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) + */ + err = thermal_add_hwmon_sysfs(tz); + if (err) +- goto err_tz; ++ return err; + + bcm2835_thermal_debugfs(pdev); + + return 0; +-err_tz: +- devm_thermal_of_zone_unregister(&pdev->dev, tz); +-err_clk: +- clk_disable_unprepare(data->clk); +- +- return err; + } + +-static int bcm2835_thermal_remove(struct platform_device *pdev) ++static void bcm2835_thermal_remove(struct platform_device *pdev) + { + struct bcm2835_thermal_data *data = platform_get_drvdata(pdev); + + debugfs_remove_recursive(data->debugfsdir); +- clk_disable_unprepare(data->clk); +- +- return 0; + } + + static struct platform_driver bcm2835_thermal_driver = { + .probe = bcm2835_thermal_probe, +- .remove = bcm2835_thermal_remove, ++ .remove_new = bcm2835_thermal_remove, + .driver = { + .name = "bcm2835_thermal", + .of_match_table = bcm2835_thermal_of_match_table, +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index b694d7669d320..1eb755a94940a 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -11,6 +11,10 @@ config APERTURE_HELPERS + Support tracking and hand-over of aperture ownership. Required + by graphics drivers for firmware-provided framebuffers. + ++config SCREEN_INFO ++ bool ++ default n ++ + config STI_CORE + bool + depends on PARISC +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 6bbc039508995..6bbf87c1b579e 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -1,12 +1,16 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-$(CONFIG_APERTURE_HELPERS) += aperture.o ++obj-$(CONFIG_SCREEN_INFO) += screen_info.o + obj-$(CONFIG_STI_CORE) += sticore.o + obj-$(CONFIG_VGASTATE) += vgastate.o + obj-$(CONFIG_VIDEO_CMDLINE) += cmdline.o + obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o + obj-$(CONFIG_HDMI) += hdmi.o + ++screen_info-y := screen_info_generic.o ++screen_info-$(CONFIG_PCI) += screen_info_pci.o ++ + obj-$(CONFIG_VT) += console/ + obj-$(CONFIG_FB_STI) += console/ + obj-$(CONFIG_LOGO) += logo/ +diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c +index c0edceea0a793..a21581b40256c 100644 +--- a/drivers/video/fbdev/vesafb.c ++++ b/drivers/video/fbdev/vesafb.c +@@ -243,6 +243,7 @@ static int vesafb_setup(char *options) + + static int vesafb_probe(struct platform_device *dev) + { ++ struct screen_info *si = &screen_info; + struct fb_info *info; + struct vesafb_par *par; + int i, err; +@@ -255,17 +256,17 @@ static int vesafb_probe(struct platform_device *dev) + fb_get_options("vesafb", &option); + vesafb_setup(option); + +- if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) ++ if (si->orig_video_isVGA != VIDEO_TYPE_VLFB) + return -ENODEV; + +- vga_compat = (screen_info.capabilities & 2) ? 0 : 1; +- vesafb_fix.smem_start = screen_info.lfb_base; +- vesafb_defined.bits_per_pixel = screen_info.lfb_depth; ++ vga_compat = !__screen_info_vbe_mode_nonvga(si); ++ vesafb_fix.smem_start = si->lfb_base; ++ vesafb_defined.bits_per_pixel = si->lfb_depth; + if (15 == vesafb_defined.bits_per_pixel) + vesafb_defined.bits_per_pixel = 16; +- vesafb_defined.xres = screen_info.lfb_width; +- vesafb_defined.yres = screen_info.lfb_height; +- vesafb_fix.line_length = screen_info.lfb_linelength; ++ vesafb_defined.xres = si->lfb_width; ++ vesafb_defined.yres = si->lfb_height; ++ vesafb_fix.line_length = si->lfb_linelength; + vesafb_fix.visual = (vesafb_defined.bits_per_pixel == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + +@@ -277,7 +278,7 @@ static int vesafb_probe(struct platform_device *dev) + /* size_total -- all video memory we have. Used for mtrr + * entries, resource allocation and bounds + * checking. */ +- size_total = screen_info.lfb_size * 65536; ++ size_total = si->lfb_size * 65536; + if (vram_total) + size_total = vram_total * 1024 * 1024; + if (size_total < size_vmode) +@@ -297,7 +298,7 @@ static int vesafb_probe(struct platform_device *dev) + vesafb_fix.smem_len = size_remap; + + #ifndef __i386__ +- screen_info.vesapm_seg = 0; ++ si->vesapm_seg = 0; + #endif + + if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) { +@@ -317,23 +318,26 @@ static int vesafb_probe(struct platform_device *dev) + par = info->par; + info->pseudo_palette = par->pseudo_palette; + +- par->base = screen_info.lfb_base; ++ par->base = si->lfb_base; + par->size = size_total; + + printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", +- vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); ++ vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, ++ vesafb_fix.line_length, si->pages); + +- if (screen_info.vesapm_seg) { ++ if (si->vesapm_seg) { + printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", +- screen_info.vesapm_seg,screen_info.vesapm_off); ++ si->vesapm_seg, si->vesapm_off); + } + +- if (screen_info.vesapm_seg < 0xc000) ++ if (si->vesapm_seg < 0xc000) + ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */ + + if (ypan || pmi_setpal) { ++ unsigned long pmi_phys; + unsigned short *pmi_base; +- pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); ++ pmi_phys = ((unsigned long)si->vesapm_seg << 4) + si->vesapm_off; ++ pmi_base = (unsigned short *)phys_to_virt(pmi_phys); + pmi_start = (void*)((char*)pmi_base + pmi_base[1]); + pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); + printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal); +@@ -377,14 +381,14 @@ static int vesafb_probe(struct platform_device *dev) + vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8; + vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8; + +- vesafb_defined.red.offset = screen_info.red_pos; +- vesafb_defined.red.length = screen_info.red_size; +- vesafb_defined.green.offset = screen_info.green_pos; +- vesafb_defined.green.length = screen_info.green_size; +- vesafb_defined.blue.offset = screen_info.blue_pos; +- vesafb_defined.blue.length = screen_info.blue_size; +- vesafb_defined.transp.offset = screen_info.rsvd_pos; +- vesafb_defined.transp.length = screen_info.rsvd_size; ++ vesafb_defined.red.offset = si->red_pos; ++ vesafb_defined.red.length = si->red_size; ++ vesafb_defined.green.offset = si->green_pos; ++ vesafb_defined.green.length = si->green_size; ++ vesafb_defined.blue.offset = si->blue_pos; ++ vesafb_defined.blue.length = si->blue_size; ++ vesafb_defined.transp.offset = si->rsvd_pos; ++ vesafb_defined.transp.length = si->rsvd_size; + + if (vesafb_defined.bits_per_pixel <= 8) { + depth = vesafb_defined.green.length; +@@ -399,14 +403,14 @@ static int vesafb_probe(struct platform_device *dev) + (vesafb_defined.bits_per_pixel > 8) ? + "Truecolor" : (vga_compat || pmi_setpal) ? + "Pseudocolor" : "Static Pseudocolor", +- screen_info.rsvd_size, +- screen_info.red_size, +- screen_info.green_size, +- screen_info.blue_size, +- screen_info.rsvd_pos, +- screen_info.red_pos, +- screen_info.green_pos, +- screen_info.blue_pos); ++ si->rsvd_size, ++ si->red_size, ++ si->green_size, ++ si->blue_size, ++ si->rsvd_pos, ++ si->red_pos, ++ si->green_pos, ++ si->blue_pos); + + vesafb_fix.ypanstep = ypan ? 1 : 0; + vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0; +diff --git a/drivers/video/screen_info_generic.c b/drivers/video/screen_info_generic.c +new file mode 100644 +index 0000000000000..64117c6367abb +--- /dev/null ++++ b/drivers/video/screen_info_generic.c +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++ ++static void resource_init_named(struct resource *r, ++ resource_size_t start, resource_size_t size, ++ const char *name, unsigned int flags) ++{ ++ memset(r, 0, sizeof(*r)); ++ ++ r->start = start; ++ r->end = start + size - 1; ++ r->name = name; ++ r->flags = flags; ++} ++ ++static void resource_init_io_named(struct resource *r, ++ resource_size_t start, resource_size_t size, ++ const char *name) ++{ ++ resource_init_named(r, start, size, name, IORESOURCE_IO); ++} ++ ++static void resource_init_mem_named(struct resource *r, ++ resource_size_t start, resource_size_t size, ++ const char *name) ++{ ++ resource_init_named(r, start, size, name, IORESOURCE_MEM); ++} ++ ++static inline bool __screen_info_has_ega_gfx(unsigned int mode) ++{ ++ switch (mode) { ++ case 0x0d: /* 320x200-4 */ ++ case 0x0e: /* 640x200-4 */ ++ case 0x0f: /* 640x350-1 */ ++ case 0x10: /* 640x350-4 */ ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static inline bool __screen_info_has_vga_gfx(unsigned int mode) ++{ ++ switch (mode) { ++ case 0x10: /* 640x480-1 */ ++ case 0x12: /* 640x480-4 */ ++ case 0x13: /* 320-200-8 */ ++ case 0x6a: /* 800x600-4 (VESA) */ ++ return true; ++ default: ++ return __screen_info_has_ega_gfx(mode); ++ } ++} ++ ++/** ++ * screen_info_resources() - Get resources from screen_info structure ++ * @si: the screen_info ++ * @r: pointer to an array of resource structures ++ * @num: number of elements in @r: ++ * ++ * Returns: ++ * The number of resources stored in @r on success, or a negative errno code otherwise. ++ * ++ * A call to screen_info_resources() returns the resources consumed by the ++ * screen_info's device or framebuffer. The result is stored in the caller-supplied ++ * array @r with up to @num elements. The function returns the number of ++ * initialized elements. ++ */ ++ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num) ++{ ++ struct resource *pos = r; ++ unsigned int type = screen_info_video_type(si); ++ u64 base, size; ++ ++ switch (type) { ++ case VIDEO_TYPE_MDA: ++ if (num > 0) ++ resource_init_io_named(pos++, 0x3b0, 12, "mda"); ++ if (num > 1) ++ resource_init_io_named(pos++, 0x3bf, 0x01, "mda"); ++ if (num > 2) ++ resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda"); ++ break; ++ case VIDEO_TYPE_CGA: ++ if (num > 0) ++ resource_init_io_named(pos++, 0x3d4, 0x02, "cga"); ++ if (num > 1) ++ resource_init_mem_named(pos++, 0xb8000, 0x2000, "cga"); ++ break; ++ case VIDEO_TYPE_EGAM: ++ if (num > 0) ++ resource_init_io_named(pos++, 0x3bf, 0x10, "ega"); ++ if (num > 1) ++ resource_init_mem_named(pos++, 0xb0000, 0x8000, "ega"); ++ break; ++ case VIDEO_TYPE_EGAC: ++ if (num > 0) ++ resource_init_io_named(pos++, 0x3c0, 0x20, "ega"); ++ if (num > 1) { ++ if (__screen_info_has_ega_gfx(si->orig_video_mode)) ++ resource_init_mem_named(pos++, 0xa0000, 0x10000, "ega"); ++ else ++ resource_init_mem_named(pos++, 0xb8000, 0x8000, "ega"); ++ } ++ break; ++ case VIDEO_TYPE_VGAC: ++ if (num > 0) ++ resource_init_io_named(pos++, 0x3c0, 0x20, "vga+"); ++ if (num > 1) { ++ if (__screen_info_has_vga_gfx(si->orig_video_mode)) ++ resource_init_mem_named(pos++, 0xa0000, 0x10000, "vga+"); ++ else ++ resource_init_mem_named(pos++, 0xb8000, 0x8000, "vga+"); ++ } ++ break; ++ case VIDEO_TYPE_VLFB: ++ case VIDEO_TYPE_EFI: ++ base = __screen_info_lfb_base(si); ++ if (!base) ++ break; ++ size = __screen_info_lfb_size(si, type); ++ if (!size) ++ break; ++ if (num > 0) ++ resource_init_mem_named(pos++, base, size, "lfb"); ++ break; ++ case VIDEO_TYPE_PICA_S3: ++ case VIDEO_TYPE_MIPS_G364: ++ case VIDEO_TYPE_SGI: ++ case VIDEO_TYPE_TGAC: ++ case VIDEO_TYPE_SUN: ++ case VIDEO_TYPE_SUNPCI: ++ case VIDEO_TYPE_PMAC: ++ default: ++ /* not supported */ ++ return -EINVAL; ++ } ++ ++ return pos - r; ++} ++EXPORT_SYMBOL(screen_info_resources); +diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c +new file mode 100644 +index 0000000000000..6c58335171410 +--- /dev/null ++++ b/drivers/video/screen_info_pci.c +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++ ++static struct pci_dev *screen_info_lfb_pdev; ++static size_t screen_info_lfb_bar; ++static resource_size_t screen_info_lfb_offset; ++static struct resource screen_info_lfb_res = DEFINE_RES_MEM(0, 0); ++ ++static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr) ++{ ++ u64 size = __screen_info_lfb_size(si, screen_info_video_type(si)); ++ ++ if (screen_info_lfb_offset > resource_size(pr)) ++ return false; ++ if (size > resource_size(pr)) ++ return false; ++ if (resource_size(pr) - size < screen_info_lfb_offset) ++ return false; ++ ++ return true; ++} ++ ++void screen_info_apply_fixups(void) ++{ ++ struct screen_info *si = &screen_info; ++ ++ if (screen_info_lfb_pdev) { ++ struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar]; ++ ++ if (pr->start != screen_info_lfb_res.start) { ++ if (__screen_info_relocation_is_valid(si, pr)) { ++ /* ++ * Only update base if we have an actual ++ * relocation to a valid I/O range. ++ */ ++ __screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset); ++ pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n", ++ &screen_info_lfb_offset, pr); ++ } else { ++ pr_warn("Invalid relocating, disabling firmware framebuffer\n"); ++ } ++ } ++ } ++} ++ ++static void screen_info_fixup_lfb(struct pci_dev *pdev) ++{ ++ unsigned int type; ++ struct resource res[SCREEN_INFO_MAX_RESOURCES]; ++ size_t i, numres; ++ int ret; ++ const struct screen_info *si = &screen_info; ++ ++ if (screen_info_lfb_pdev) ++ return; // already found ++ ++ type = screen_info_video_type(si); ++ if (type != VIDEO_TYPE_EFI) ++ return; // only applies to EFI ++ ++ ret = screen_info_resources(si, res, ARRAY_SIZE(res)); ++ if (ret < 0) ++ return; ++ numres = ret; ++ ++ for (i = 0; i < numres; ++i) { ++ struct resource *r = &res[i]; ++ const struct resource *pr; ++ ++ if (!(r->flags & IORESOURCE_MEM)) ++ continue; ++ pr = pci_find_resource(pdev, r); ++ if (!pr) ++ continue; ++ ++ /* ++ * We've found a PCI device with the framebuffer ++ * resource. Store away the parameters to track ++ * relocation of the framebuffer aperture. ++ */ ++ screen_info_lfb_pdev = pdev; ++ screen_info_lfb_bar = pr - pdev->resource; ++ screen_info_lfb_offset = r->start - pr->start; ++ memcpy(&screen_info_lfb_res, r, sizeof(screen_info_lfb_res)); ++ } ++} ++DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16, ++ screen_info_fixup_lfb); ++ ++static struct pci_dev *__screen_info_pci_dev(struct resource *res) ++{ ++ struct pci_dev *pdev = NULL; ++ const struct resource *r = NULL; ++ ++ if (!(res->flags & IORESOURCE_MEM)) ++ return NULL; ++ ++ while (!r && (pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) { ++ r = pci_find_resource(pdev, res); ++ } ++ ++ return pdev; ++} ++ ++/** ++ * screen_info_pci_dev() - Return PCI parent device that contains screen_info's framebuffer ++ * @si: the screen_info ++ * ++ * Returns: ++ * The screen_info's parent device or NULL on success, or a pointer-encoded ++ * errno value otherwise. The value NULL is not an error. It signals that no ++ * PCI device has been found. ++ */ ++struct pci_dev *screen_info_pci_dev(const struct screen_info *si) ++{ ++ struct resource res[SCREEN_INFO_MAX_RESOURCES]; ++ ssize_t i, numres; ++ ++ numres = screen_info_resources(si, res, ARRAY_SIZE(res)); ++ if (numres < 0) ++ return ERR_PTR(numres); ++ ++ for (i = 0; i < numres; ++i) { ++ struct pci_dev *pdev = __screen_info_pci_dev(&res[i]); ++ ++ if (pdev) ++ return pdev; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(screen_info_pci_dev); +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index dd065349fae3a..4e999e1c14075 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1214,8 +1214,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, + block_group->space_info->total_bytes -= block_group->length; + block_group->space_info->bytes_readonly -= + (block_group->length - block_group->zone_unusable); +- block_group->space_info->bytes_zone_unusable -= +- block_group->zone_unusable; ++ btrfs_space_info_update_bytes_zone_unusable(fs_info, block_group->space_info, ++ -block_group->zone_unusable); + block_group->space_info->disk_total -= block_group->length * factor; + + spin_unlock(&block_group->space_info->lock); +@@ -1399,7 +1399,8 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force) + if (btrfs_is_zoned(cache->fs_info)) { + /* Migrate zone_unusable bytes to readonly */ + sinfo->bytes_readonly += cache->zone_unusable; +- sinfo->bytes_zone_unusable -= cache->zone_unusable; ++ btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo, ++ -cache->zone_unusable); + cache->zone_unusable = 0; + } + cache->ro++; +@@ -3023,9 +3024,11 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group *cache) + if (btrfs_is_zoned(cache->fs_info)) { + /* Migrate zone_unusable bytes back */ + cache->zone_unusable = +- (cache->alloc_offset - cache->used) + ++ (cache->alloc_offset - cache->used - cache->pinned - ++ cache->reserved) + + (cache->length - cache->zone_capacity); +- sinfo->bytes_zone_unusable += cache->zone_unusable; ++ btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo, ++ cache->zone_unusable); + sinfo->bytes_readonly -= cache->zone_unusable; + } + num_bytes = cache->length - cache->reserved - +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index b89b558b15926..c6ecfd05e1db9 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2749,7 +2749,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, + readonly = true; + } else if (btrfs_is_zoned(fs_info)) { + /* Need reset before reusing in a zoned block group */ +- space_info->bytes_zone_unusable += len; ++ btrfs_space_info_update_bytes_zone_unusable(fs_info, space_info, ++ len); + readonly = true; + } + spin_unlock(&cache->lock); +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index dcfc0425115e9..f59e599766662 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -2721,8 +2721,10 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, + * If the block group is read-only, we should account freed space into + * bytes_readonly. + */ +- if (!block_group->ro) ++ if (!block_group->ro) { + block_group->zone_unusable += to_unusable; ++ WARN_ON(block_group->zone_unusable > block_group->length); ++ } + spin_unlock(&ctl->tree_lock); + if (!used) { + spin_lock(&block_group->lock); +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 3f7a9605e2d3a..581bdd709ee0d 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -312,7 +312,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, + found->bytes_used += block_group->used; + found->disk_used += block_group->used * factor; + found->bytes_readonly += block_group->bytes_super; +- found->bytes_zone_unusable += block_group->zone_unusable; ++ btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable); + if (block_group->length > 0) + found->full = 0; + btrfs_try_granting_tickets(info, found); +@@ -524,8 +524,7 @@ void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, + + spin_lock(&cache->lock); + avail = cache->length - cache->used - cache->pinned - +- cache->reserved - cache->delalloc_bytes - +- cache->bytes_super - cache->zone_unusable; ++ cache->reserved - cache->bytes_super - cache->zone_unusable; + btrfs_info(fs_info, + "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %llu delalloc %llu super %llu zone_unusable (%llu bytes available) %s", + cache->start, cache->length, cache->used, cache->pinned, +diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h +index 0bb9d14e60a82..08a3bd10addcf 100644 +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -197,6 +197,7 @@ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ + + DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); + DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); ++DECLARE_SPACE_INFO_UPDATE(bytes_zone_unusable, "zone_unusable"); + + int btrfs_init_space_info(struct btrfs_fs_info *fs_info); + void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index d5eb8d44c6c81..cef119a2476bb 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -453,6 +453,35 @@ static void ext4_map_blocks_es_recheck(handle_t *handle, + } + #endif /* ES_AGGRESSIVE_TEST */ + ++static int ext4_map_query_blocks(handle_t *handle, struct inode *inode, ++ struct ext4_map_blocks *map) ++{ ++ unsigned int status; ++ int retval; ++ ++ if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) ++ retval = ext4_ext_map_blocks(handle, inode, map, 0); ++ else ++ retval = ext4_ind_map_blocks(handle, inode, map, 0); ++ ++ if (retval <= 0) ++ return retval; ++ ++ if (unlikely(retval != map->m_len)) { ++ ext4_warning(inode->i_sb, ++ "ES len assertion failed for inode " ++ "%lu: retval %d != map->m_len %d", ++ inode->i_ino, retval, map->m_len); ++ WARN_ON(1); ++ } ++ ++ status = map->m_flags & EXT4_MAP_UNWRITTEN ? ++ EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; ++ ext4_es_insert_extent(inode, map->m_lblk, map->m_len, ++ map->m_pblk, status); ++ return retval; ++} ++ + /* + * The ext4_map_blocks() function tries to look up the requested blocks, + * and returns if the blocks are already mapped. +@@ -1705,12 +1734,10 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + + /* Lookup extent status tree firstly */ + if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) { +- if (ext4_es_is_hole(&es)) { +- retval = 0; +- down_read(&EXT4_I(inode)->i_data_sem); ++ if (ext4_es_is_hole(&es)) + goto add_delayed; +- } + ++found: + /* + * Delayed extent could be allocated by fallocate. + * So we need to check it. +@@ -1747,49 +1774,42 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + down_read(&EXT4_I(inode)->i_data_sem); + if (ext4_has_inline_data(inode)) + retval = 0; +- else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +- retval = ext4_ext_map_blocks(NULL, inode, map, 0); + else +- retval = ext4_ind_map_blocks(NULL, inode, map, 0); ++ retval = ext4_map_query_blocks(NULL, inode, map); ++ up_read(&EXT4_I(inode)->i_data_sem); ++ if (retval) ++ return retval; + + add_delayed: +- if (retval == 0) { +- int ret; +- +- /* +- * XXX: __block_prepare_write() unmaps passed block, +- * is it OK? +- */ +- +- ret = ext4_insert_delayed_block(inode, map->m_lblk); +- if (ret != 0) { +- retval = ret; +- goto out_unlock; ++ down_write(&EXT4_I(inode)->i_data_sem); ++ /* ++ * Page fault path (ext4_page_mkwrite does not take i_rwsem) ++ * and fallocate path (no folio lock) can race. Make sure we ++ * lookup the extent status tree here again while i_data_sem ++ * is held in write mode, before inserting a new da entry in ++ * the extent status tree. ++ */ ++ if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) { ++ if (!ext4_es_is_hole(&es)) { ++ up_write(&EXT4_I(inode)->i_data_sem); ++ goto found; + } +- +- map_bh(bh, inode->i_sb, invalid_block); +- set_buffer_new(bh); +- set_buffer_delay(bh); +- } else if (retval > 0) { +- unsigned int status; +- +- if (unlikely(retval != map->m_len)) { +- ext4_warning(inode->i_sb, +- "ES len assertion failed for inode " +- "%lu: retval %d != map->m_len %d", +- inode->i_ino, retval, map->m_len); +- WARN_ON(1); ++ } else if (!ext4_has_inline_data(inode)) { ++ retval = ext4_map_query_blocks(NULL, inode, map); ++ if (retval) { ++ up_write(&EXT4_I(inode)->i_data_sem); ++ return retval; + } +- +- status = map->m_flags & EXT4_MAP_UNWRITTEN ? +- EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; +- ext4_es_insert_extent(inode, map->m_lblk, map->m_len, +- map->m_pblk, status); + } + +-out_unlock: +- up_read((&EXT4_I(inode)->i_data_sem)); ++ retval = ext4_insert_delayed_block(inode, map->m_lblk); ++ up_write(&EXT4_I(inode)->i_data_sem); ++ if (retval) ++ return retval; + ++ map_bh(bh, inode->i_sb, invalid_block); ++ set_buffer_new(bh); ++ set_buffer_delay(bh); + return retval; + } + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 22080606b8769..804958c6de34c 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -3350,7 +3350,9 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) + if (page_private_gcing(fio->page)) { + if (fio->sbi->am.atgc_enabled && + (fio->io_type == FS_DATA_IO) && +- (fio->sbi->gc_mode != GC_URGENT_HIGH)) ++ (fio->sbi->gc_mode != GC_URGENT_HIGH) && ++ __is_valid_data_blkaddr(fio->old_blkaddr) && ++ !is_inode_flag_set(inode, FI_OPU_WRITE)) + return CURSEG_ALL_DATA_ATGC; + else + return CURSEG_COLD_DATA; +diff --git a/fs/file.c b/fs/file.c +index a815f6eddc511..b64a84137c00f 100644 +--- a/fs/file.c ++++ b/fs/file.c +@@ -1124,6 +1124,7 @@ __releases(&files->file_lock) + * tables and this condition does not arise without those. + */ + fdt = files_fdtable(files); ++ fd = array_index_nospec(fd, fdt->max_fds); + tofree = fdt->fd[fd]; + if (!tofree && fd_is_open(fd, fdt)) + goto Ebusy; +diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c +index 5b5cdc747cef3..071a71eb1a2d4 100644 +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -480,12 +480,10 @@ static struct inode *proc_sys_make_inode(struct super_block *sb, + make_empty_dir_inode(inode); + } + ++ inode->i_uid = GLOBAL_ROOT_UID; ++ inode->i_gid = GLOBAL_ROOT_GID; + if (root->set_ownership) +- root->set_ownership(head, table, &inode->i_uid, &inode->i_gid); +- else { +- inode->i_uid = GLOBAL_ROOT_UID; +- inode->i_gid = GLOBAL_ROOT_GID; +- } ++ root->set_ownership(head, &inode->i_uid, &inode->i_gid); + + return inode; + } +diff --git a/include/linux/leds.h b/include/linux/leds.h +index aa16dc2a8230f..d3056bc6f0a1a 100644 +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -474,6 +474,9 @@ struct led_trigger { + int (*activate)(struct led_classdev *led_cdev); + void (*deactivate)(struct led_classdev *led_cdev); + ++ /* Brightness set by led_trigger_event */ ++ enum led_brightness brightness; ++ + /* LED-private triggers have this set */ + struct led_hw_trigger_type *trigger_type; + +@@ -527,22 +530,11 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) + return led_cdev->trigger_data; + } + +-/** +- * led_trigger_rename_static - rename a trigger +- * @name: the new trigger name +- * @trig: the LED trigger to rename +- * +- * Change a LED trigger name by copying the string passed in +- * name into current trigger name, which MUST be large +- * enough for the new string. +- * +- * Note that name must NOT point to the same string used +- * during LED registration, as that could lead to races. +- * +- * This is meant to be used on triggers with statically +- * allocated name. +- */ +-void led_trigger_rename_static(const char *name, struct led_trigger *trig); ++static inline enum led_brightness ++led_trigger_get_brightness(const struct led_trigger *trigger) ++{ ++ return trigger ? trigger->brightness : LED_OFF; ++} + + #define module_led_trigger(__led_trigger) \ + module_driver(__led_trigger, led_trigger_register, \ +@@ -580,6 +572,12 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) + return NULL; + } + ++static inline enum led_brightness ++led_trigger_get_brightness(const struct led_trigger *trigger) ++{ ++ return LED_OFF; ++} ++ + #endif /* CONFIG_LEDS_TRIGGERS */ + + /* Trigger specific enum */ +diff --git a/include/linux/pci.h b/include/linux/pci.h +index f141300116219..7b18a4b3efb0e 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -1182,6 +1182,8 @@ struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn); + struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, + unsigned int devfn); + struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); ++struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from); ++ + int pci_dev_present(const struct pci_device_id *ids); + + int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, +@@ -1958,6 +1960,9 @@ static inline struct pci_dev *pci_get_class(unsigned int class, + struct pci_dev *from) + { return NULL; } + ++static inline struct pci_dev *pci_get_base_class(unsigned int class, ++ struct pci_dev *from) ++{ return NULL; } + + static inline int pci_dev_present(const struct pci_device_id *ids) + { return 0; } +diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h +index eab7081392d50..6a4a3cec4638b 100644 +--- a/include/linux/screen_info.h ++++ b/include/linux/screen_info.h +@@ -4,6 +4,142 @@ + + #include + ++#include ++ ++/** ++ * SCREEN_INFO_MAX_RESOURCES - maximum number of resources per screen_info ++ */ ++#define SCREEN_INFO_MAX_RESOURCES 3 ++ ++struct pci_dev; ++struct resource; ++ ++static inline bool __screen_info_has_lfb(unsigned int type) ++{ ++ return (type == VIDEO_TYPE_VLFB) || (type == VIDEO_TYPE_EFI); ++} ++ ++static inline u64 __screen_info_lfb_base(const struct screen_info *si) ++{ ++ u64 lfb_base = si->lfb_base; ++ ++ if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE) ++ lfb_base |= (u64)si->ext_lfb_base << 32; ++ ++ return lfb_base; ++} ++ ++static inline void __screen_info_set_lfb_base(struct screen_info *si, u64 lfb_base) ++{ ++ si->lfb_base = lfb_base & GENMASK_ULL(31, 0); ++ si->ext_lfb_base = (lfb_base & GENMASK_ULL(63, 32)) >> 32; ++ ++ if (si->ext_lfb_base) ++ si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; ++ else ++ si->capabilities &= ~VIDEO_CAPABILITY_64BIT_BASE; ++} ++ ++static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned int type) ++{ ++ u64 lfb_size = si->lfb_size; ++ ++ if (type == VIDEO_TYPE_VLFB) ++ lfb_size <<= 16; ++ return lfb_size; ++} ++ ++static inline bool __screen_info_vbe_mode_nonvga(const struct screen_info *si) ++{ ++ /* ++ * VESA modes typically run on VGA hardware. Set bit 5 signals that this ++ * is not the case. Drivers can then not make use of VGA resources. See ++ * Sec 4.4 of the VBE 2.0 spec. ++ */ ++ return si->vesa_attributes & BIT(5); ++} ++ ++static inline unsigned int __screen_info_video_type(unsigned int type) ++{ ++ switch (type) { ++ case VIDEO_TYPE_MDA: ++ case VIDEO_TYPE_CGA: ++ case VIDEO_TYPE_EGAM: ++ case VIDEO_TYPE_EGAC: ++ case VIDEO_TYPE_VGAC: ++ case VIDEO_TYPE_VLFB: ++ case VIDEO_TYPE_PICA_S3: ++ case VIDEO_TYPE_MIPS_G364: ++ case VIDEO_TYPE_SGI: ++ case VIDEO_TYPE_TGAC: ++ case VIDEO_TYPE_SUN: ++ case VIDEO_TYPE_SUNPCI: ++ case VIDEO_TYPE_PMAC: ++ case VIDEO_TYPE_EFI: ++ return type; ++ default: ++ return 0; ++ } ++} ++ ++/** ++ * screen_info_video_type() - Decodes the video type from struct screen_info ++ * @si: an instance of struct screen_info ++ * ++ * Returns: ++ * A VIDEO_TYPE_ constant representing si's type of video display, or 0 otherwise. ++ */ ++static inline unsigned int screen_info_video_type(const struct screen_info *si) ++{ ++ unsigned int type; ++ ++ // check if display output is on ++ if (!si->orig_video_isVGA) ++ return 0; ++ ++ // check for a known VIDEO_TYPE_ constant ++ type = __screen_info_video_type(si->orig_video_isVGA); ++ if (type) ++ return si->orig_video_isVGA; ++ ++ // check if text mode has been initialized ++ if (!si->orig_video_lines || !si->orig_video_cols) ++ return 0; ++ ++ // 80x25 text, mono ++ if (si->orig_video_mode == 0x07) { ++ if ((si->orig_video_ega_bx & 0xff) != 0x10) ++ return VIDEO_TYPE_EGAM; ++ else ++ return VIDEO_TYPE_MDA; ++ } ++ ++ // EGA/VGA, 16 colors ++ if ((si->orig_video_ega_bx & 0xff) != 0x10) { ++ if (si->orig_video_isVGA) ++ return VIDEO_TYPE_VGAC; ++ else ++ return VIDEO_TYPE_EGAC; ++ } ++ ++ // the rest... ++ return VIDEO_TYPE_CGA; ++} ++ ++ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num); ++ ++#if defined(CONFIG_PCI) ++void screen_info_apply_fixups(void); ++struct pci_dev *screen_info_pci_dev(const struct screen_info *si); ++#else ++static inline void screen_info_apply_fixups(void) ++{ } ++static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si) ++{ ++ return NULL; ++} ++#endif ++ + extern struct screen_info screen_info; + + #endif /* _SCREEN_INFO_H */ +diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h +index 61b40ea81f4d3..698a71422a14b 100644 +--- a/include/linux/sysctl.h ++++ b/include/linux/sysctl.h +@@ -205,7 +205,6 @@ struct ctl_table_root { + struct ctl_table_set default_set; + struct ctl_table_set *(*lookup)(struct ctl_table_root *root); + void (*set_ownership)(struct ctl_table_header *head, +- struct ctl_table *table, + kuid_t *uid, kgid_t *gid); + int (*permissions)(struct ctl_table_header *head, struct ctl_table *table); + }; +diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h +index b2db2c2f1c577..3c4d5ef6d4463 100644 +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -2430,6 +2430,14 @@ DEFINE_EVENT(btrfs__space_info_update, update_bytes_pinned, + TP_ARGS(fs_info, sinfo, old, diff) + ); + ++DEFINE_EVENT(btrfs__space_info_update, update_bytes_zone_unusable, ++ ++ TP_PROTO(const struct btrfs_fs_info *fs_info, ++ const struct btrfs_space_info *sinfo, u64 old, s64 diff), ++ ++ TP_ARGS(fs_info, sinfo, old, diff) ++); ++ + DECLARE_EVENT_CLASS(btrfs_raid56_bio, + + TP_PROTO(const struct btrfs_raid_bio *rbio, +diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h +index 563e48617374d..54e8fb5a229cd 100644 +--- a/include/trace/events/mptcp.h ++++ b/include/trace/events/mptcp.h +@@ -34,7 +34,7 @@ TRACE_EVENT(mptcp_subflow_get_send, + struct sock *ssk; + + __entry->active = mptcp_subflow_active(subflow); +- __entry->backup = subflow->backup; ++ __entry->backup = subflow->backup || subflow->request_bkup; + + if (subflow->tcp_sock && sk_fullsock(subflow->tcp_sock)) + __entry->free = sk_stream_memory_free(subflow->tcp_sock); +diff --git a/init/Kconfig b/init/Kconfig +index e403a29256357..e173364abd6c0 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1898,6 +1898,7 @@ config RUST + depends on !MODVERSIONS + depends on !GCC_PLUGINS + depends on !RANDSTRUCT ++ depends on !SHADOW_CALL_STACK + depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE + help + Enables Rust support in the kernel. +diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c +index 8c62e443f78b3..b2f39a86f4734 100644 +--- a/ipc/ipc_sysctl.c ++++ b/ipc/ipc_sysctl.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include "util.h" + + static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, +@@ -190,25 +191,56 @@ static int set_is_seen(struct ctl_table_set *set) + return ¤t->nsproxy->ipc_ns->ipc_set == set; + } + ++static void ipc_set_ownership(struct ctl_table_header *head, ++ kuid_t *uid, kgid_t *gid) ++{ ++ struct ipc_namespace *ns = ++ container_of(head->set, struct ipc_namespace, ipc_set); ++ ++ kuid_t ns_root_uid = make_kuid(ns->user_ns, 0); ++ kgid_t ns_root_gid = make_kgid(ns->user_ns, 0); ++ ++ *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID; ++ *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID; ++} ++ + static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table) + { + int mode = table->mode; + + #ifdef CONFIG_CHECKPOINT_RESTORE +- struct ipc_namespace *ns = current->nsproxy->ipc_ns; ++ struct ipc_namespace *ns = ++ container_of(head->set, struct ipc_namespace, ipc_set); + + if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) || + (table->data == &ns->ids[IPC_MSG_IDS].next_id) || + (table->data == &ns->ids[IPC_SHM_IDS].next_id)) && + checkpoint_restore_ns_capable(ns->user_ns)) + mode = 0666; ++ else + #endif +- return mode; ++ { ++ kuid_t ns_root_uid; ++ kgid_t ns_root_gid; ++ ++ ipc_set_ownership(head, &ns_root_uid, &ns_root_gid); ++ ++ if (uid_eq(current_euid(), ns_root_uid)) ++ mode >>= 6; ++ ++ else if (in_egroup_p(ns_root_gid)) ++ mode >>= 3; ++ } ++ ++ mode &= 7; ++ ++ return (mode << 6) | (mode << 3) | mode; + } + + static struct ctl_table_root set_root = { + .lookup = set_lookup, + .permissions = ipc_permissions, ++ .set_ownership = ipc_set_ownership, + }; + + bool setup_ipc_sysctls(struct ipc_namespace *ns) +diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c +index ebb5ed81c151a..6bb1c5397c69b 100644 +--- a/ipc/mq_sysctl.c ++++ b/ipc/mq_sysctl.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + static int msg_max_limit_min = MIN_MSGMAX; + static int msg_max_limit_max = HARD_MSGMAX; +@@ -76,8 +77,42 @@ static int set_is_seen(struct ctl_table_set *set) + return ¤t->nsproxy->ipc_ns->mq_set == set; + } + ++static void mq_set_ownership(struct ctl_table_header *head, ++ kuid_t *uid, kgid_t *gid) ++{ ++ struct ipc_namespace *ns = ++ container_of(head->set, struct ipc_namespace, mq_set); ++ ++ kuid_t ns_root_uid = make_kuid(ns->user_ns, 0); ++ kgid_t ns_root_gid = make_kgid(ns->user_ns, 0); ++ ++ *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID; ++ *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID; ++} ++ ++static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table) ++{ ++ int mode = table->mode; ++ kuid_t ns_root_uid; ++ kgid_t ns_root_gid; ++ ++ mq_set_ownership(head, &ns_root_uid, &ns_root_gid); ++ ++ if (uid_eq(current_euid(), ns_root_uid)) ++ mode >>= 6; ++ ++ else if (in_egroup_p(ns_root_gid)) ++ mode >>= 3; ++ ++ mode &= 7; ++ ++ return (mode << 6) | (mode << 3) | mode; ++} ++ + static struct ctl_table_root set_root = { + .lookup = set_lookup, ++ .permissions = mq_permissions, ++ .set_ownership = mq_set_ownership, + }; + + bool setup_mq_sysctls(struct ipc_namespace *ns) +diff --git a/mm/Kconfig b/mm/Kconfig +index 264a2df5ecf5b..ece4f2847e2b4 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -704,6 +704,17 @@ config HUGETLB_PAGE_SIZE_VARIABLE + config CONTIG_ALLOC + def_bool (MEMORY_ISOLATION && COMPACTION) || CMA + ++config PCP_BATCH_SCALE_MAX ++ int "Maximum scale factor of PCP (Per-CPU pageset) batch allocate/free" ++ default 5 ++ range 0 6 ++ help ++ In page allocator, PCP (Per-CPU pageset) is refilled and drained in ++ batches. The batch number is scaled automatically to improve page ++ allocation/free throughput. But too large scale factor may hurt ++ latency. This option sets the upper limit of scale factor to limit ++ the maximum latency. ++ + config PHYS_ADDR_T_64BIT + def_bool 64BIT + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index e99d3223f0fc2..39bdbfb5313fb 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -2185,14 +2185,21 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp) + */ + static void drain_pages_zone(unsigned int cpu, struct zone *zone) + { +- struct per_cpu_pages *pcp; ++ struct per_cpu_pages *pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); ++ int count; + +- pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); +- if (pcp->count) { ++ do { + spin_lock(&pcp->lock); +- free_pcppages_bulk(zone, pcp->count, pcp, 0); ++ count = pcp->count; ++ if (count) { ++ int to_drain = min(count, ++ pcp->batch << CONFIG_PCP_BATCH_SCALE_MAX); ++ ++ free_pcppages_bulk(zone, to_drain, pcp, 0); ++ count -= to_drain; ++ } + spin_unlock(&pcp->lock); +- } ++ } while (count); + } + + /* +@@ -2343,7 +2350,7 @@ static int nr_pcp_free(struct per_cpu_pages *pcp, int high, bool free_high) + * freeing of pages without any allocation. + */ + batch <<= pcp->free_factor; +- if (batch < max_nr_free) ++ if (batch < max_nr_free && pcp->free_factor < CONFIG_PCP_BATCH_SCALE_MAX) + pcp->free_factor++; + batch = clamp(batch, min_nr_free, max_nr_free); + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index b3f5714dab342..6dab0c99c82c7 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -2862,6 +2862,27 @@ static int hci_passive_scan_sync(struct hci_dev *hdev) + */ + filter_policy = hci_update_accept_list_sync(hdev); + ++ /* If suspended and filter_policy set to 0x00 (no acceptlist) then ++ * passive scanning cannot be started since that would require the host ++ * to be woken up to process the reports. ++ */ ++ if (hdev->suspended && !filter_policy) { ++ /* Check if accept list is empty then there is no need to scan ++ * while suspended. ++ */ ++ if (list_empty(&hdev->le_accept_list)) ++ return 0; ++ ++ /* If there are devices is the accept_list that means some ++ * devices could not be programmed which in non-suspended case ++ * means filter_policy needs to be set to 0x00 so the host needs ++ * to filter, but since this is treating suspended case we ++ * can ignore device needing host to filter to allow devices in ++ * the acceptlist to be able to wakeup the system. ++ */ ++ filter_policy = 0x01; ++ } ++ + /* When the controller is using random resolvable addresses and + * with that having LE privacy enabled, then controllers with + * Extended Scanner Filter Policies support can now enable support +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 7ea66de1442cc..8573dad6d8171 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3263,7 +3263,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, + if (ifm->ifi_index > 0) + dev = __dev_get_by_index(tgt_net, ifm->ifi_index); + else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) +- dev = rtnl_dev_get(net, tb); ++ dev = rtnl_dev_get(tgt_net, tb); + else if (tb[IFLA_GROUP]) + err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP])); + else +diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c +index 56f6ecc43451e..12ca666d6e2c1 100644 +--- a/net/ipv4/netfilter/iptable_nat.c ++++ b/net/ipv4/netfilter/iptable_nat.c +@@ -145,25 +145,27 @@ static struct pernet_operations iptable_nat_net_ops = { + + static int __init iptable_nat_init(void) + { +- int ret = xt_register_template(&nf_nat_ipv4_table, +- iptable_nat_table_init); ++ int ret; + ++ /* net->gen->ptr[iptable_nat_net_id] must be allocated ++ * before calling iptable_nat_table_init(). ++ */ ++ ret = register_pernet_subsys(&iptable_nat_net_ops); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&iptable_nat_net_ops); +- if (ret < 0) { +- xt_unregister_template(&nf_nat_ipv4_table); +- return ret; +- } ++ ret = xt_register_template(&nf_nat_ipv4_table, ++ iptable_nat_table_init); ++ if (ret < 0) ++ unregister_pernet_subsys(&iptable_nat_net_ops); + + return ret; + } + + static void __exit iptable_nat_exit(void) + { +- unregister_pernet_subsys(&iptable_nat_net_ops); + xt_unregister_template(&nf_nat_ipv4_table); ++ unregister_pernet_subsys(&iptable_nat_net_ops); + } + + module_init(iptable_nat_init); +diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c +index 3b4dafefb4b03..e143562077958 100644 +--- a/net/ipv4/syncookies.c ++++ b/net/ipv4/syncookies.c +@@ -424,7 +424,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) + } + + /* Try to redo what tcp_v4_send_synack did. */ +- req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW); ++ req->rsk_window_clamp = READ_ONCE(tp->window_clamp) ? : ++ dst_metric(&rt->dst, RTAX_WINDOW); + /* limit the window selection if the user enforce a smaller rx buffer */ + full_space = tcp_full_space(sk); + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 91c3d8264059d..1e3202f2b7a87 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1723,7 +1723,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val) + space = tcp_space_from_win(sk, val); + if (space > sk->sk_rcvbuf) { + WRITE_ONCE(sk->sk_rcvbuf, space); +- tcp_sk(sk)->window_clamp = val; ++ WRITE_ONCE(tcp_sk(sk)->window_clamp, val); + } + return 0; + } +@@ -3386,7 +3386,7 @@ int tcp_set_window_clamp(struct sock *sk, int val) + if (!val) { + if (sk->sk_state != TCP_CLOSE) + return -EINVAL; +- tp->window_clamp = 0; ++ WRITE_ONCE(tp->window_clamp, 0); + } else { + u32 new_rcv_ssthresh, old_window_clamp = tp->window_clamp; + u32 new_window_clamp = val < SOCK_MIN_RCVBUF / 2 ? +@@ -3395,7 +3395,7 @@ int tcp_set_window_clamp(struct sock *sk, int val) + if (new_window_clamp == old_window_clamp) + return 0; + +- tp->window_clamp = new_window_clamp; ++ WRITE_ONCE(tp->window_clamp, new_window_clamp); + if (new_window_clamp < old_window_clamp) { + /* need to apply the reserved mem provisioning only + * when shrinking the window clamp +@@ -4020,7 +4020,7 @@ int do_tcp_getsockopt(struct sock *sk, int level, + TCP_RTO_MAX / HZ); + break; + case TCP_WINDOW_CLAMP: +- val = tp->window_clamp; ++ val = READ_ONCE(tp->window_clamp); + break; + case TCP_INFO: { + struct tcp_info info; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index c2e4dac42453b..d0364cff65c9f 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -570,19 +570,20 @@ static void tcp_init_buffer_space(struct sock *sk) + maxwin = tcp_full_space(sk); + + if (tp->window_clamp >= maxwin) { +- tp->window_clamp = maxwin; ++ WRITE_ONCE(tp->window_clamp, maxwin); + + if (tcp_app_win && maxwin > 4 * tp->advmss) +- tp->window_clamp = max(maxwin - +- (maxwin >> tcp_app_win), +- 4 * tp->advmss); ++ WRITE_ONCE(tp->window_clamp, ++ max(maxwin - (maxwin >> tcp_app_win), ++ 4 * tp->advmss)); + } + + /* Force reservation of one segment. */ + if (tcp_app_win && + tp->window_clamp > 2 * tp->advmss && + tp->window_clamp + tp->advmss > maxwin) +- tp->window_clamp = max(2 * tp->advmss, maxwin - tp->advmss); ++ WRITE_ONCE(tp->window_clamp, ++ max(2 * tp->advmss, maxwin - tp->advmss)); + + tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp); + tp->snd_cwnd_stamp = tcp_jiffies32; +@@ -747,8 +748,7 @@ void tcp_rcv_space_adjust(struct sock *sk) + * + */ + +- if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_moderate_rcvbuf) && +- !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { ++ if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_moderate_rcvbuf)) { + u64 rcvwin, grow; + int rcvbuf; + +@@ -764,11 +764,22 @@ void tcp_rcv_space_adjust(struct sock *sk) + + rcvbuf = min_t(u64, tcp_space_from_win(sk, rcvwin), + READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])); +- if (rcvbuf > sk->sk_rcvbuf) { +- WRITE_ONCE(sk->sk_rcvbuf, rcvbuf); ++ if (!(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { ++ if (rcvbuf > sk->sk_rcvbuf) { ++ WRITE_ONCE(sk->sk_rcvbuf, rcvbuf); + +- /* Make the window clamp follow along. */ +- tp->window_clamp = tcp_win_from_space(sk, rcvbuf); ++ /* Make the window clamp follow along. */ ++ WRITE_ONCE(tp->window_clamp, ++ tcp_win_from_space(sk, rcvbuf)); ++ } ++ } else { ++ /* Make the window clamp follow along while being bounded ++ * by SO_RCVBUF. ++ */ ++ int clamp = tcp_win_from_space(sk, min(rcvbuf, sk->sk_rcvbuf)); ++ ++ if (clamp > tp->window_clamp) ++ WRITE_ONCE(tp->window_clamp, clamp); + } + } + tp->rcvq_space.space = copied; +@@ -6347,7 +6358,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, + + if (!tp->rx_opt.wscale_ok) { + tp->rx_opt.snd_wscale = tp->rx_opt.rcv_wscale = 0; +- tp->window_clamp = min(tp->window_clamp, 65535U); ++ WRITE_ONCE(tp->window_clamp, ++ min(tp->window_clamp, 65535U)); + } + + if (tp->rx_opt.saw_tstamp) { +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 5631041ae12cb..15c49d559db53 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -203,16 +203,17 @@ static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) + * This MUST be enforced by all callers. + */ + void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss, +- __u32 *rcv_wnd, __u32 *window_clamp, ++ __u32 *rcv_wnd, __u32 *__window_clamp, + int wscale_ok, __u8 *rcv_wscale, + __u32 init_rcv_wnd) + { + unsigned int space = (__space < 0 ? 0 : __space); ++ u32 window_clamp = READ_ONCE(*__window_clamp); + + /* If no clamp set the clamp to the max possible scaled window */ +- if (*window_clamp == 0) +- (*window_clamp) = (U16_MAX << TCP_MAX_WSCALE); +- space = min(*window_clamp, space); ++ if (window_clamp == 0) ++ window_clamp = (U16_MAX << TCP_MAX_WSCALE); ++ space = min(window_clamp, space); + + /* Quantize space offering to a multiple of mss if possible. */ + if (space > mss) +@@ -239,12 +240,13 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss, + /* Set window scaling on max possible window */ + space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])); + space = max_t(u32, space, READ_ONCE(sysctl_rmem_max)); +- space = min_t(u32, space, *window_clamp); ++ space = min_t(u32, space, window_clamp); + *rcv_wscale = clamp_t(int, ilog2(space) - 15, + 0, TCP_MAX_WSCALE); + } + /* Set the clamp no higher than max representable value */ +- (*window_clamp) = min_t(__u32, U16_MAX << (*rcv_wscale), *window_clamp); ++ WRITE_ONCE(*__window_clamp, ++ min_t(__u32, U16_MAX << (*rcv_wscale), window_clamp)); + } + EXPORT_SYMBOL(tcp_select_initial_window); + +@@ -3787,7 +3789,7 @@ static void tcp_connect_init(struct sock *sk) + tcp_ca_dst_init(sk, dst); + + if (!tp->window_clamp) +- tp->window_clamp = dst_metric(dst, RTAX_WINDOW); ++ WRITE_ONCE(tp->window_clamp, dst_metric(dst, RTAX_WINDOW)); + tp->advmss = tcp_mss_clamp(tp, dst_metric_advmss(dst)); + + tcp_initialize_rcv_mss(sk); +@@ -3795,7 +3797,7 @@ static void tcp_connect_init(struct sock *sk) + /* limit the window selection if the user enforce a smaller rx buffer */ + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && + (tp->window_clamp > tcp_full_space(sk) || tp->window_clamp == 0)) +- tp->window_clamp = tcp_full_space(sk); ++ WRITE_ONCE(tp->window_clamp, tcp_full_space(sk)); + + rcv_wnd = tcp_rwnd_init_bpf(sk); + if (rcv_wnd == 0) +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 68debc78189c2..2062ab94721e3 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -227,6 +227,7 @@ struct ndisc_options *ndisc_parse_options(const struct net_device *dev, + return NULL; + memset(ndopts, 0, sizeof(*ndopts)); + while (opt_len) { ++ bool unknown = false; + int l; + if (opt_len < sizeof(struct nd_opt_hdr)) + return NULL; +@@ -262,22 +263,23 @@ struct ndisc_options *ndisc_parse_options(const struct net_device *dev, + break; + #endif + default: +- if (ndisc_is_useropt(dev, nd_opt)) { +- ndopts->nd_useropts_end = nd_opt; +- if (!ndopts->nd_useropts) +- ndopts->nd_useropts = nd_opt; +- } else { +- /* +- * Unknown options must be silently ignored, +- * to accommodate future extension to the +- * protocol. +- */ +- ND_PRINTK(2, notice, +- "%s: ignored unsupported option; type=%d, len=%d\n", +- __func__, +- nd_opt->nd_opt_type, +- nd_opt->nd_opt_len); +- } ++ unknown = true; ++ } ++ if (ndisc_is_useropt(dev, nd_opt)) { ++ ndopts->nd_useropts_end = nd_opt; ++ if (!ndopts->nd_useropts) ++ ndopts->nd_useropts = nd_opt; ++ } else if (unknown) { ++ /* ++ * Unknown options must be silently ignored, ++ * to accommodate future extension to the ++ * protocol. ++ */ ++ ND_PRINTK(2, notice, ++ "%s: ignored unsupported option; type=%d, len=%d\n", ++ __func__, ++ nd_opt->nd_opt_type, ++ nd_opt->nd_opt_len); + } + next_opt: + opt_len -= l; +diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c +index bf3cb3a13600c..52d597b16b658 100644 +--- a/net/ipv6/netfilter/ip6table_nat.c ++++ b/net/ipv6/netfilter/ip6table_nat.c +@@ -147,23 +147,27 @@ static struct pernet_operations ip6table_nat_net_ops = { + + static int __init ip6table_nat_init(void) + { +- int ret = xt_register_template(&nf_nat_ipv6_table, +- ip6table_nat_table_init); ++ int ret; + ++ /* net->gen->ptr[ip6table_nat_net_id] must be allocated ++ * before calling ip6t_nat_register_lookups(). ++ */ ++ ret = register_pernet_subsys(&ip6table_nat_net_ops); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&ip6table_nat_net_ops); ++ ret = xt_register_template(&nf_nat_ipv6_table, ++ ip6table_nat_table_init); + if (ret) +- xt_unregister_template(&nf_nat_ipv6_table); ++ unregister_pernet_subsys(&ip6table_nat_net_ops); + + return ret; + } + + static void __exit ip6table_nat_exit(void) + { +- unregister_pernet_subsys(&ip6table_nat_net_ops); + xt_unregister_template(&nf_nat_ipv6_table); ++ unregister_pernet_subsys(&ip6table_nat_net_ops); + } + + module_init(ip6table_nat_init); +diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c +index 8698b49dfc8de..593ead8a45d79 100644 +--- a/net/ipv6/syncookies.c ++++ b/net/ipv6/syncookies.c +@@ -243,7 +243,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) + goto out_free; + } + +- req->rsk_window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); ++ req->rsk_window_clamp = READ_ONCE(tp->window_clamp) ? :dst_metric(dst, RTAX_WINDOW); + /* limit the window selection if the user enforce a smaller rx buffer */ + full_space = tcp_full_space(sk); + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 498a0c35b7bb2..815b1df0b2d19 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -335,8 +335,8 @@ static void iucv_sever_path(struct sock *sk, int with_user_data) + struct iucv_sock *iucv = iucv_sk(sk); + struct iucv_path *path = iucv->path; + +- if (iucv->path) { +- iucv->path = NULL; ++ /* Whoever resets the path pointer, must sever and free it. */ ++ if (xchg(&iucv->path, NULL)) { + if (with_user_data) { + low_nmcpy(user_data, iucv->src_name); + high_nmcpy(user_data, iucv->dst_name); +diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c +index c30405e768337..7884217f33eb2 100644 +--- a/net/mptcp/mib.c ++++ b/net/mptcp/mib.c +@@ -19,7 +19,9 @@ static const struct snmp_mib mptcp_snmp_list[] = { + SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS), + SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN), + SNMP_MIB_ITEM("MPJoinSynRx", MPTCP_MIB_JOINSYNRX), ++ SNMP_MIB_ITEM("MPJoinSynBackupRx", MPTCP_MIB_JOINSYNBACKUPRX), + SNMP_MIB_ITEM("MPJoinSynAckRx", MPTCP_MIB_JOINSYNACKRX), ++ SNMP_MIB_ITEM("MPJoinSynAckBackupRx", MPTCP_MIB_JOINSYNACKBACKUPRX), + SNMP_MIB_ITEM("MPJoinSynAckHMacFailure", MPTCP_MIB_JOINSYNACKMAC), + SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX), + SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC), +diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h +index dd7fd1f246b5f..443604462ace8 100644 +--- a/net/mptcp/mib.h ++++ b/net/mptcp/mib.h +@@ -12,7 +12,9 @@ enum linux_mptcp_mib_field { + MPTCP_MIB_RETRANSSEGS, /* Segments retransmitted at the MPTCP-level */ + MPTCP_MIB_JOINNOTOKEN, /* Received MP_JOIN but the token was not found */ + MPTCP_MIB_JOINSYNRX, /* Received a SYN + MP_JOIN */ ++ MPTCP_MIB_JOINSYNBACKUPRX, /* Received a SYN + MP_JOIN + backup flag */ + MPTCP_MIB_JOINSYNACKRX, /* Received a SYN/ACK + MP_JOIN */ ++ MPTCP_MIB_JOINSYNACKBACKUPRX, /* Received a SYN/ACK + MP_JOIN + backup flag */ + MPTCP_MIB_JOINSYNACKMAC, /* HMAC was wrong on SYN/ACK + MP_JOIN */ + MPTCP_MIB_JOINACKRX, /* Received an ACK + MP_JOIN */ + MPTCP_MIB_JOINACKMAC, /* HMAC was wrong on ACK + MP_JOIN */ +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index 63fc0758c22d4..85aafa94cc8ab 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -909,7 +909,7 @@ bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, + return true; + } else if (subflow_req->mp_join) { + opts->suboptions = OPTION_MPTCP_MPJ_SYNACK; +- opts->backup = subflow_req->backup; ++ opts->backup = subflow_req->request_bkup; + opts->join_id = subflow_req->local_id; + opts->thmac = subflow_req->thmac; + opts->nonce = subflow_req->local_nonce; +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index f58bf77d76b81..db621933b2035 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -476,7 +476,6 @@ static void __mptcp_pm_send_ack(struct mptcp_sock *msk, struct mptcp_subflow_con + slow = lock_sock_fast(ssk); + if (prio) { + subflow->send_mp_prio = 1; +- subflow->backup = backup; + subflow->request_bkup = backup; + } + +@@ -1432,6 +1431,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, + ret = remove_anno_list_by_saddr(msk, addr); + if (ret || force) { + spin_lock_bh(&msk->pm.lock); ++ msk->pm.add_addr_signaled -= ret; + mptcp_pm_remove_addr(msk, &list); + spin_unlock_bh(&msk->pm.lock); + } +@@ -1565,16 +1565,25 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list) + { + struct mptcp_rm_list alist = { .nr = 0 }; + struct mptcp_pm_addr_entry *entry; ++ int anno_nr = 0; + + list_for_each_entry(entry, rm_list, list) { +- if ((remove_anno_list_by_saddr(msk, &entry->addr) || +- lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) && +- alist.nr < MPTCP_RM_IDS_MAX) +- alist.ids[alist.nr++] = entry->addr.id; ++ if (alist.nr >= MPTCP_RM_IDS_MAX) ++ break; ++ ++ /* only delete if either announced or matching a subflow */ ++ if (remove_anno_list_by_saddr(msk, &entry->addr)) ++ anno_nr++; ++ else if (!lookup_subflow_by_saddr(&msk->conn_list, ++ &entry->addr)) ++ continue; ++ ++ alist.ids[alist.nr++] = entry->addr.id; + } + + if (alist.nr) { + spin_lock_bh(&msk->pm.lock); ++ msk->pm.add_addr_signaled -= anno_nr; + mptcp_pm_remove_addr(msk, &alist); + spin_unlock_bh(&msk->pm.lock); + } +@@ -1587,17 +1596,18 @@ void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, + struct mptcp_pm_addr_entry *entry; + + list_for_each_entry(entry, rm_list, list) { +- if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) && +- slist.nr < MPTCP_RM_IDS_MAX) ++ if (slist.nr < MPTCP_RM_IDS_MAX && ++ lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) + slist.ids[slist.nr++] = entry->addr.id; + +- if (remove_anno_list_by_saddr(msk, &entry->addr) && +- alist.nr < MPTCP_RM_IDS_MAX) ++ if (alist.nr < MPTCP_RM_IDS_MAX && ++ remove_anno_list_by_saddr(msk, &entry->addr)) + alist.ids[alist.nr++] = entry->addr.id; + } + + if (alist.nr) { + spin_lock_bh(&msk->pm.lock); ++ msk->pm.add_addr_signaled -= alist.nr; + mptcp_pm_remove_addr(msk, &alist); + spin_unlock_bh(&msk->pm.lock); + } +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index fbf2b26760731..c1d652a3f7a9b 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -352,8 +352,10 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk, + skb_orphan(skb); + + /* try to fetch required memory from subflow */ +- if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) ++ if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) { ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); + goto drop; ++ } + + has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp; + +@@ -842,16 +844,13 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk) + sk_rbuf = ssk_rbuf; + + /* over limit? can't append more skbs to msk, Also, no need to wake-up*/ +- if (__mptcp_rmem(sk) > sk_rbuf) { +- MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); ++ if (__mptcp_rmem(sk) > sk_rbuf) + return; +- } + + /* Wake-up the reader only for in-sequence data */ + mptcp_data_lock(sk); +- if (move_skbs_to_msk(msk, ssk)) ++ if (move_skbs_to_msk(msk, ssk) && mptcp_epollin_ready(sk)) + sk->sk_data_ready(sk); +- + mptcp_data_unlock(sk); + } + +@@ -1418,13 +1417,15 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk) + } + + mptcp_for_each_subflow(msk, subflow) { ++ bool backup = subflow->backup || subflow->request_bkup; ++ + trace_mptcp_subflow_get_send(subflow); + ssk = mptcp_subflow_tcp_sock(subflow); + if (!mptcp_subflow_active(subflow)) + continue; + + tout = max(tout, mptcp_timeout_from_subflow(subflow)); +- nr_active += !subflow->backup; ++ nr_active += !backup; + pace = subflow->avg_pacing_rate; + if (unlikely(!pace)) { + /* init pacing rate from socket */ +@@ -1435,9 +1436,9 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk) + } + + linger_time = div_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pace); +- if (linger_time < send_info[subflow->backup].linger_time) { +- send_info[subflow->backup].ssk = ssk; +- send_info[subflow->backup].linger_time = linger_time; ++ if (linger_time < send_info[backup].linger_time) { ++ send_info[backup].ssk = ssk; ++ send_info[backup].linger_time = linger_time; + } + } + __mptcp_set_timeout(sk, tout); +@@ -1918,6 +1919,7 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk, + if (!(flags & MSG_PEEK)) { + MPTCP_SKB_CB(skb)->offset += count; + MPTCP_SKB_CB(skb)->map_seq += count; ++ msk->bytes_consumed += count; + } + break; + } +@@ -1928,6 +1930,7 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk, + WRITE_ONCE(msk->rmem_released, msk->rmem_released + skb->truesize); + __skb_unlink(skb, &msk->receive_queue); + __kfree_skb(skb); ++ msk->bytes_consumed += count; + } + + if (copied >= len) +@@ -2023,7 +2026,7 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied) + ssk = mptcp_subflow_tcp_sock(subflow); + slow = lock_sock_fast(ssk); + WRITE_ONCE(ssk->sk_rcvbuf, rcvbuf); +- tcp_sk(ssk)->window_clamp = window_clamp; ++ WRITE_ONCE(tcp_sk(ssk)->window_clamp, window_clamp); + tcp_cleanup_rbuf(ssk, 1); + unlock_sock_fast(ssk, slow); + } +@@ -2752,6 +2755,7 @@ static void __mptcp_init_sock(struct sock *sk) + msk->rmem_fwd_alloc = 0; + WRITE_ONCE(msk->rmem_released, 0); + msk->timer_ival = TCP_RTO_MIN; ++ msk->scaling_ratio = TCP_DEFAULT_SCALING_RATIO; + + WRITE_ONCE(msk->first, NULL); + inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss; +@@ -2984,16 +2988,9 @@ void __mptcp_unaccepted_force_close(struct sock *sk) + __mptcp_destroy_sock(sk); + } + +-static __poll_t mptcp_check_readable(struct mptcp_sock *msk) ++static __poll_t mptcp_check_readable(struct sock *sk) + { +- /* Concurrent splices from sk_receive_queue into receive_queue will +- * always show at least one non-empty queue when checked in this order. +- */ +- if (skb_queue_empty_lockless(&((struct sock *)msk)->sk_receive_queue) && +- skb_queue_empty_lockless(&msk->receive_queue)) +- return 0; +- +- return EPOLLIN | EPOLLRDNORM; ++ return mptcp_epollin_ready(sk) ? EPOLLIN | EPOLLRDNORM : 0; + } + + static void mptcp_check_listen_stop(struct sock *sk) +@@ -3031,7 +3028,7 @@ bool __mptcp_close(struct sock *sk, long timeout) + goto cleanup; + } + +- if (mptcp_check_readable(msk) || timeout < 0) { ++ if (mptcp_data_avail(msk) || timeout < 0) { + /* If the msk has read data, or the caller explicitly ask it, + * do the MPTCP equivalent of TCP reset, aka MPTCP fastclose + */ +@@ -3157,6 +3154,7 @@ static int mptcp_disconnect(struct sock *sk, int flags) + msk->snd_data_fin_enable = false; + msk->rcv_fastclose = false; + msk->use_64bit_ack = false; ++ msk->bytes_consumed = 0; + WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk))); + mptcp_pm_data_reset(msk); + mptcp_ca_reset(sk); +@@ -3983,7 +3981,7 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, + mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; + + if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) { +- mask |= mptcp_check_readable(msk); ++ mask |= mptcp_check_readable(sk); + if (shutdown & SEND_SHUTDOWN) + mask |= EPOLLOUT | EPOLLWRNORM; + else +@@ -4021,6 +4019,7 @@ static const struct proto_ops mptcp_stream_ops = { + .sendmsg = inet_sendmsg, + .recvmsg = inet_recvmsg, + .mmap = sock_no_mmap, ++ .set_rcvlowat = mptcp_set_rcvlowat, + }; + + static struct inet_protosw mptcp_protosw = { +@@ -4122,6 +4121,7 @@ static const struct proto_ops mptcp_v6_stream_ops = { + #ifdef CONFIG_COMPAT + .compat_ioctl = inet6_compat_ioctl, + #endif ++ .set_rcvlowat = mptcp_set_rcvlowat, + }; + + static struct proto mptcp_v6_prot; +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 93ba48f4ae386..c28ac5dfd0b58 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -268,6 +268,7 @@ struct mptcp_sock { + atomic64_t rcv_wnd_sent; + u64 rcv_data_fin_seq; + u64 bytes_retrans; ++ u64 bytes_consumed; + int rmem_fwd_alloc; + int snd_burst; + int old_wspace; +@@ -418,6 +419,7 @@ struct mptcp_subflow_request_sock { + u16 mp_capable : 1, + mp_join : 1, + backup : 1, ++ request_bkup : 1, + csum_reqd : 1, + allow_join_id0 : 1; + u8 local_id; +@@ -674,6 +676,24 @@ struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk); + int mptcp_sched_get_send(struct mptcp_sock *msk); + int mptcp_sched_get_retrans(struct mptcp_sock *msk); + ++static inline u64 mptcp_data_avail(const struct mptcp_sock *msk) ++{ ++ return READ_ONCE(msk->bytes_received) - READ_ONCE(msk->bytes_consumed); ++} ++ ++static inline bool mptcp_epollin_ready(const struct sock *sk) ++{ ++ /* mptcp doesn't have to deal with small skbs in the receive queue, ++ * at it can always coalesce them ++ */ ++ return (mptcp_data_avail(mptcp_sk(sk)) >= sk->sk_rcvlowat) || ++ (mem_cgroup_sockets_enabled && sk->sk_memcg && ++ mem_cgroup_under_socket_pressure(sk->sk_memcg)) || ++ READ_ONCE(tcp_memory_pressure); ++} ++ ++int mptcp_set_rcvlowat(struct sock *sk, int val); ++ + static inline bool __tcp_can_send(const struct sock *ssk) + { + /* only send if our side has not closed yet */ +@@ -748,6 +768,7 @@ static inline bool mptcp_is_fully_established(struct sock *sk) + return inet_sk_state_load(sk) == TCP_ESTABLISHED && + READ_ONCE(mptcp_sk(sk)->fully_established); + } ++ + void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk); + void mptcp_data_ready(struct sock *sk, struct sock *ssk); + bool mptcp_finish_join(struct sock *sk); +diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c +index cc04b5e29dd35..bdfeecea814f3 100644 +--- a/net/mptcp/sockopt.c ++++ b/net/mptcp/sockopt.c +@@ -1521,9 +1521,55 @@ void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk) + + msk_owned_by_me(msk); + ++ ssk->sk_rcvlowat = 0; ++ + if (READ_ONCE(subflow->setsockopt_seq) != msk->setsockopt_seq) { + sync_socket_options(msk, ssk); + + subflow->setsockopt_seq = msk->setsockopt_seq; + } + } ++ ++/* unfortunately this is different enough from the tcp version so ++ * that we can't factor it out ++ */ ++int mptcp_set_rcvlowat(struct sock *sk, int val) ++{ ++ struct mptcp_subflow_context *subflow; ++ int space, cap; ++ ++ /* bpf can land here with a wrong sk type */ ++ if (sk->sk_protocol == IPPROTO_TCP) ++ return -EINVAL; ++ ++ if (sk->sk_userlocks & SOCK_RCVBUF_LOCK) ++ cap = sk->sk_rcvbuf >> 1; ++ else ++ cap = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]) >> 1; ++ val = min(val, cap); ++ WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); ++ ++ /* Check if we need to signal EPOLLIN right now */ ++ if (mptcp_epollin_ready(sk)) ++ sk->sk_data_ready(sk); ++ ++ if (sk->sk_userlocks & SOCK_RCVBUF_LOCK) ++ return 0; ++ ++ space = __tcp_space_from_win(mptcp_sk(sk)->scaling_ratio, val); ++ if (space <= sk->sk_rcvbuf) ++ return 0; ++ ++ /* propagate the rcvbuf changes to all the subflows */ ++ WRITE_ONCE(sk->sk_rcvbuf, space); ++ mptcp_for_each_subflow(mptcp_sk(sk), subflow) { ++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ bool slow; ++ ++ slow = lock_sock_fast(ssk); ++ WRITE_ONCE(ssk->sk_rcvbuf, space); ++ WRITE_ONCE(tcp_sk(ssk)->window_clamp, val); ++ unlock_sock_fast(ssk, slow); ++ } ++ return 0; ++} +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index 23ee96c6abcbf..bc1efc1787720 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -166,6 +166,9 @@ static int subflow_check_req(struct request_sock *req, + return 0; + } else if (opt_mp_join) { + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); ++ ++ if (mp_opt.backup) ++ SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNBACKUPRX); + } + + if (opt_mp_capable && listener->request_mptcp) { +@@ -558,6 +561,9 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + subflow->mp_join = 1; + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); + ++ if (subflow->backup) ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKBACKUPRX); ++ + if (subflow_use_different_dport(msk, sk)) { + pr_debug("synack inet_dport=%d %d", + ntohs(inet_sk(sk)->inet_dport), +@@ -1192,14 +1198,22 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb, + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); + bool fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN; +- u32 incr; ++ struct tcp_sock *tp = tcp_sk(ssk); ++ u32 offset, incr, avail_len; ++ ++ offset = tp->copied_seq - TCP_SKB_CB(skb)->seq; ++ if (WARN_ON_ONCE(offset > skb->len)) ++ goto out; + +- incr = limit >= skb->len ? skb->len + fin : limit; ++ avail_len = skb->len - offset; ++ incr = limit >= avail_len ? avail_len + fin : limit; + +- pr_debug("discarding=%d len=%d seq=%d", incr, skb->len, +- subflow->map_subflow_seq); ++ pr_debug("discarding=%d len=%d offset=%d seq=%d", incr, skb->len, ++ offset, subflow->map_subflow_seq); + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DUPDATA); + tcp_sk(ssk)->copied_seq += incr; ++ ++out: + if (!before(tcp_sk(ssk)->copied_seq, TCP_SKB_CB(skb)->end_seq)) + sk_eat_skb(ssk, skb); + if (mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) +@@ -1432,10 +1446,18 @@ static void subflow_data_ready(struct sock *sk) + WARN_ON_ONCE(!__mptcp_check_fallback(msk) && !subflow->mp_capable && + !subflow->mp_join && !(state & TCPF_CLOSE)); + +- if (mptcp_subflow_data_available(sk)) ++ if (mptcp_subflow_data_available(sk)) { + mptcp_data_ready(parent, sk); +- else if (unlikely(sk->sk_err)) ++ ++ /* subflow-level lowat test are not relevant. ++ * respect the msk-level threshold eventually mandating an immediate ack ++ */ ++ if (mptcp_data_avail(msk) < parent->sk_rcvlowat && ++ (tcp_sk(sk)->rcv_nxt - tcp_sk(sk)->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss) ++ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW; ++ } else if (unlikely(sk->sk_err)) { + subflow_error_report(sk); ++ } + } + + static void subflow_write_space(struct sock *ssk) +@@ -1968,6 +1990,7 @@ static void subflow_ulp_clone(const struct request_sock *req, + new_ctx->fully_established = 1; + new_ctx->remote_key_valid = 1; + new_ctx->backup = subflow_req->backup; ++ new_ctx->request_bkup = subflow_req->request_bkup; + WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id); + new_ctx->token = subflow_req->token; + new_ctx->thmac = subflow_req->thmac; +diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c +index 3ac19516ed803..50d24e240e8fb 100644 +--- a/net/sched/act_ct.c ++++ b/net/sched/act_ct.c +@@ -44,6 +44,8 @@ static DEFINE_MUTEX(zones_mutex); + struct zones_ht_key { + struct net *net; + u16 zone; ++ /* Note : pad[] must be the last field. */ ++ u8 pad[]; + }; + + struct tcf_ct_flow_table { +@@ -60,7 +62,7 @@ struct tcf_ct_flow_table { + static const struct rhashtable_params zones_params = { + .head_offset = offsetof(struct tcf_ct_flow_table, node), + .key_offset = offsetof(struct tcf_ct_flow_table, key), +- .key_len = sizeof_field(struct tcf_ct_flow_table, key), ++ .key_len = offsetof(struct zones_ht_key, pad), + .automatic_shrinking = true, + }; + +diff --git a/net/sysctl_net.c b/net/sysctl_net.c +index 051ed5f6fc937..a0a7a79991f9f 100644 +--- a/net/sysctl_net.c ++++ b/net/sysctl_net.c +@@ -54,7 +54,6 @@ static int net_ctl_permissions(struct ctl_table_header *head, + } + + static void net_ctl_set_ownership(struct ctl_table_header *head, +- struct ctl_table *table, + kuid_t *uid, kgid_t *gid) + { + struct net *net = container_of(head->set, struct net, sysctls); +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index 9bba233b5a6ec..72d78dbc55ffd 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -1057,6 +1057,7 @@ void cfg80211_connect_done(struct net_device *dev, + cfg80211_hold_bss( + bss_from_pub(params->links[link].bss)); + ev->cr.links[link].bss = params->links[link].bss; ++ ev->cr.links[link].status = params->links[link].status; + + if (params->links[link].addr) { + ev->cr.links[link].addr = next; +diff --git a/sound/core/seq/seq_ump_convert.c b/sound/core/seq/seq_ump_convert.c +index e90b27a135e6f..d9dacfbe4a9ae 100644 +--- a/sound/core/seq/seq_ump_convert.c ++++ b/sound/core/seq/seq_ump_convert.c +@@ -1192,44 +1192,53 @@ static int cvt_sysex_to_ump(struct snd_seq_client *dest, + { + struct snd_seq_ump_event ev_cvt; + unsigned char status; +- u8 buf[6], *xbuf; ++ u8 buf[8], *xbuf; + int offset = 0; + int len, err; ++ bool finished = false; + + if (!snd_seq_ev_is_variable(event)) + return 0; + + setup_ump_event(&ev_cvt, event); +- for (;;) { ++ while (!finished) { + len = snd_seq_expand_var_event_at(event, sizeof(buf), buf, offset); + if (len <= 0) + break; +- if (WARN_ON(len > 6)) ++ if (WARN_ON(len > sizeof(buf))) + break; +- offset += len; ++ + xbuf = buf; ++ status = UMP_SYSEX_STATUS_CONTINUE; ++ /* truncate the sysex start-marker */ + if (*xbuf == UMP_MIDI1_MSG_SYSEX_START) { + status = UMP_SYSEX_STATUS_START; +- xbuf++; + len--; +- if (len > 0 && xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { ++ offset++; ++ xbuf++; ++ } ++ ++ /* if the last of this packet or the 1st byte of the next packet ++ * is the end-marker, finish the transfer with this packet ++ */ ++ if (len > 0 && len < 8 && ++ xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { ++ if (status == UMP_SYSEX_STATUS_START) + status = UMP_SYSEX_STATUS_SINGLE; +- len--; +- } +- } else { +- if (xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { ++ else + status = UMP_SYSEX_STATUS_END; +- len--; +- } else { +- status = UMP_SYSEX_STATUS_CONTINUE; +- } ++ len--; ++ finished = true; + } ++ ++ len = min(len, 6); + fill_sysex7_ump(dest_port, ev_cvt.ump, status, xbuf, len); + err = __snd_seq_deliver_single_event(dest, dest_port, + (struct snd_seq_event *)&ev_cvt, + atomic, hop); + if (err < 0) + return err; ++ offset += len; + } + return 0; + } +diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c +index c9f153f85ae6b..5f0f8d9c08d1e 100644 +--- a/sound/firewire/amdtp-stream.c ++++ b/sound/firewire/amdtp-stream.c +@@ -77,6 +77,8 @@ + // overrun. Actual device can skip more, then this module stops the packet streaming. + #define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES 5 + ++static void pcm_period_work(struct work_struct *work); ++ + /** + * amdtp_stream_init - initialize an AMDTP stream structure + * @s: the AMDTP stream to initialize +@@ -105,6 +107,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, + s->flags = flags; + s->context = ERR_PTR(-1); + mutex_init(&s->mutex); ++ INIT_WORK(&s->period_work, pcm_period_work); + s->packet_index = 0; + + init_waitqueue_head(&s->ready_wait); +@@ -347,6 +350,7 @@ EXPORT_SYMBOL(amdtp_stream_get_max_payload); + */ + void amdtp_stream_pcm_prepare(struct amdtp_stream *s) + { ++ cancel_work_sync(&s->period_work); + s->pcm_buffer_pointer = 0; + s->pcm_period_pointer = 0; + } +@@ -611,19 +615,21 @@ static void update_pcm_pointers(struct amdtp_stream *s, + // The program in user process should periodically check the status of intermediate + // buffer associated to PCM substream to process PCM frames in the buffer, instead + // of receiving notification of period elapsed by poll wait. +- if (!pcm->runtime->no_period_wakeup) { +- if (in_softirq()) { +- // In software IRQ context for 1394 OHCI. +- snd_pcm_period_elapsed(pcm); +- } else { +- // In process context of ALSA PCM application under acquired lock of +- // PCM substream. +- snd_pcm_period_elapsed_under_stream_lock(pcm); +- } +- } ++ if (!pcm->runtime->no_period_wakeup) ++ queue_work(system_highpri_wq, &s->period_work); + } + } + ++static void pcm_period_work(struct work_struct *work) ++{ ++ struct amdtp_stream *s = container_of(work, struct amdtp_stream, ++ period_work); ++ struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); ++ ++ if (pcm) ++ snd_pcm_period_elapsed(pcm); ++} ++ + static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, + bool sched_irq) + { +@@ -1852,11 +1858,14 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, + { + struct amdtp_stream *irq_target = d->irq_target; + +- // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. + if (irq_target && amdtp_stream_running(irq_target)) { +- // In software IRQ context, the call causes dead-lock to disable the tasklet +- // synchronously. +- if (!in_softirq()) ++ // use wq to prevent AB/BA deadlock competition for ++ // substream lock: ++ // fw_iso_context_flush_completions() acquires ++ // lock by ohci_flush_iso_completions(), ++ // amdtp-stream process_rx_packets() attempts to ++ // acquire same lock by snd_pcm_elapsed() ++ if (current_work() != &s->period_work) + fw_iso_context_flush_completions(irq_target->context); + } + +@@ -1912,6 +1921,7 @@ static void amdtp_stream_stop(struct amdtp_stream *s) + return; + } + ++ cancel_work_sync(&s->period_work); + fw_iso_context_stop(s->context); + fw_iso_context_destroy(s->context); + s->context = ERR_PTR(-1); +diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h +index a1ed2e80f91a7..775db3fc4959f 100644 +--- a/sound/firewire/amdtp-stream.h ++++ b/sound/firewire/amdtp-stream.h +@@ -191,6 +191,7 @@ struct amdtp_stream { + + /* For a PCM substream processing. */ + struct snd_pcm_substream *pcm; ++ struct work_struct period_work; + snd_pcm_uframes_t pcm_buffer_pointer; + unsigned int pcm_period_pointer; + unsigned int pcm_frame_multiplier; +diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h +index 8556031bcd68e..f31cb31d46362 100644 +--- a/sound/pci/hda/hda_controller.h ++++ b/sound/pci/hda/hda_controller.h +@@ -28,7 +28,7 @@ + #else + #define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ + #endif +-/* 14 unused */ ++#define AZX_DCAPS_AMD_ALLOC_FIX (1 << 14) /* AMD allocation workaround */ + #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ + #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ + #define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */ +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index a6a9d353fe635..d5c9f113e477a 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -40,6 +40,7 @@ + + #ifdef CONFIG_X86 + /* for snoop control */ ++#include + #include + #include + #endif +@@ -301,7 +302,7 @@ enum { + + /* quirks for ATI HDMI with snoop off */ + #define AZX_DCAPS_PRESET_ATI_HDMI_NS \ +- (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF) ++ (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_AMD_ALLOC_FIX) + + /* quirks for AMD SB */ + #define AZX_DCAPS_PRESET_AMD_SB \ +@@ -1715,6 +1716,13 @@ static void azx_check_snoop_available(struct azx *chip) + if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF) + snoop = false; + ++#ifdef CONFIG_X86 ++ /* check the presence of DMA ops (i.e. IOMMU), disable snoop conditionally */ ++ if ((chip->driver_caps & AZX_DCAPS_AMD_ALLOC_FIX) && ++ !get_dma_ops(chip->card->dev)) ++ snoop = false; ++#endif ++ + chip->snoop = snoop; + if (!snoop) { + dev_info(chip->card->dev, "Force to non-snoop mode\n"); +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index e8209178d87bb..af921364195e4 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -21,12 +21,6 @@ + #include "hda_jack.h" + #include "hda_generic.h" + +-enum { +- CX_HEADSET_NOPRESENT = 0, +- CX_HEADSET_PARTPRESENT, +- CX_HEADSET_ALLPRESENT, +-}; +- + struct conexant_spec { + struct hda_gen_spec gen; + +@@ -48,7 +42,6 @@ struct conexant_spec { + unsigned int gpio_led; + unsigned int gpio_mute_led_mask; + unsigned int gpio_mic_led_mask; +- unsigned int headset_present_flag; + bool is_cx8070_sn6140; + }; + +@@ -250,48 +243,19 @@ static void cx_process_headset_plugin(struct hda_codec *codec) + } + } + +-static void cx_update_headset_mic_vref(struct hda_codec *codec, unsigned int res) ++static void cx_update_headset_mic_vref(struct hda_codec *codec, struct hda_jack_callback *event) + { +- unsigned int phone_present, mic_persent, phone_tag, mic_tag; +- struct conexant_spec *spec = codec->spec; ++ unsigned int mic_present; + + /* In cx8070 and sn6140, the node 16 can only be config to headphone or disabled, + * the node 19 can only be config to microphone or disabled. + * Check hp&mic tag to process headset pulgin&plugout. + */ +- phone_tag = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); +- mic_tag = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); +- if ((phone_tag & (res >> AC_UNSOL_RES_TAG_SHIFT)) || +- (mic_tag & (res >> AC_UNSOL_RES_TAG_SHIFT))) { +- phone_present = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_PIN_SENSE, 0x0); +- if (!(phone_present & AC_PINSENSE_PRESENCE)) {/* headphone plugout */ +- spec->headset_present_flag = CX_HEADSET_NOPRESENT; +- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); +- return; +- } +- if (spec->headset_present_flag == CX_HEADSET_NOPRESENT) { +- spec->headset_present_flag = CX_HEADSET_PARTPRESENT; +- } else if (spec->headset_present_flag == CX_HEADSET_PARTPRESENT) { +- mic_persent = snd_hda_codec_read(codec, 0x19, 0, +- AC_VERB_GET_PIN_SENSE, 0x0); +- /* headset is present */ +- if ((phone_present & AC_PINSENSE_PRESENCE) && +- (mic_persent & AC_PINSENSE_PRESENCE)) { +- cx_process_headset_plugin(codec); +- spec->headset_present_flag = CX_HEADSET_ALLPRESENT; +- } +- } +- } +-} +- +-static void cx_jack_unsol_event(struct hda_codec *codec, unsigned int res) +-{ +- struct conexant_spec *spec = codec->spec; +- +- if (spec->is_cx8070_sn6140) +- cx_update_headset_mic_vref(codec, res); +- +- snd_hda_jack_unsol_event(codec, res); ++ mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0); ++ if (!(mic_present & AC_PINSENSE_PRESENCE)) /* mic plugout */ ++ snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); ++ else ++ cx_process_headset_plugin(codec); + } + + #ifdef CONFIG_PM +@@ -307,7 +271,7 @@ static const struct hda_codec_ops cx_auto_patch_ops = { + .build_pcms = snd_hda_gen_build_pcms, + .init = cx_auto_init, + .free = cx_auto_free, +- .unsol_event = cx_jack_unsol_event, ++ .unsol_event = snd_hda_jack_unsol_event, + #ifdef CONFIG_PM + .suspend = cx_auto_suspend, + .check_power_status = snd_hda_gen_check_power_status, +@@ -1167,7 +1131,7 @@ static int patch_conexant_auto(struct hda_codec *codec) + case 0x14f11f86: + case 0x14f11f87: + spec->is_cx8070_sn6140 = true; +- spec->headset_present_flag = CX_HEADSET_NOPRESENT; ++ snd_hda_jack_detect_enable_callback(codec, 0x19, cx_update_headset_mic_vref); + break; + } + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index f3aca1c38b77d..0b33a00771450 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9639,6 +9639,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), + SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x0840, "Acer Aspire E1", ALC269VB_FIXUP_ASPIRE_E1_COEF), ++ SND_PCI_QUIRK(0x1025, 0x100c, "Acer Aspire E5-574G", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC), +diff --git a/sound/usb/stream.c b/sound/usb/stream.c +index d5409f3879455..e14c725acebf2 100644 +--- a/sound/usb/stream.c ++++ b/sound/usb/stream.c +@@ -244,8 +244,8 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, + SNDRV_CHMAP_FR, /* right front */ + SNDRV_CHMAP_FC, /* center front */ + SNDRV_CHMAP_LFE, /* LFE */ +- SNDRV_CHMAP_SL, /* left surround */ +- SNDRV_CHMAP_SR, /* right surround */ ++ SNDRV_CHMAP_RL, /* left surround */ ++ SNDRV_CHMAP_RR, /* right surround */ + SNDRV_CHMAP_FLC, /* left of center */ + SNDRV_CHMAP_FRC, /* right of center */ + SNDRV_CHMAP_RC, /* surround */ +diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c +index aee937d14fbbf..09e6b4e1401c9 100644 +--- a/tools/perf/util/callchain.c ++++ b/tools/perf/util/callchain.c +@@ -1126,7 +1126,7 @@ int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *samp + int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node, + bool hide_unresolved) + { +- struct machine *machine = maps__machine(node->ms.maps); ++ struct machine *machine = node->ms.maps ? maps__machine(node->ms.maps) : NULL; + + maps__put(al->maps); + al->maps = maps__get(node->ms.maps); +diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c +index d2043ec3bf6d6..4209b95690394 100644 +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c +@@ -1115,11 +1115,11 @@ int main_loop_s(int listensock) + return 1; + } + +- if (--cfg_repeat > 0) { +- if (cfg_input) +- close(fd); ++ if (cfg_input) ++ close(fd); ++ ++ if (--cfg_repeat > 0) + goto again; +- } + + return 0; + } +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index 231a95a8de9ee..a2dae2a3a93e0 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -1778,6 +1778,8 @@ chk_prio_nr() + { + local mp_prio_nr_tx=$1 + local mp_prio_nr_rx=$2 ++ local mpj_syn=$3 ++ local mpj_syn_ack=$4 + local count + + print_check "ptx" +@@ -1799,6 +1801,26 @@ chk_prio_nr() + else + print_ok + fi ++ ++ print_check "syn backup" ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinSynBackupRx") ++ if [ -z "$count" ]; then ++ print_skip ++ elif [ "$count" != "$mpj_syn" ]; then ++ fail_test "got $count JOIN[s] syn with Backup expected $mpj_syn" ++ else ++ print_ok ++ fi ++ ++ print_check "synack backup" ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckBackupRx") ++ if [ -z "$count" ]; then ++ print_skip ++ elif [ "$count" != "$mpj_syn_ack" ]; then ++ fail_test "got $count JOIN[s] synack with Backup expected $mpj_syn_ack" ++ else ++ print_ok ++ fi + } + + chk_subflow_nr() +@@ -2751,11 +2773,24 @@ backup_tests() + sflags=nobackup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 +- chk_prio_nr 0 1 ++ chk_prio_nr 0 1 1 0 + fi + + # single address, backup + if reset "single address, backup" && ++ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then ++ pm_nl_set_limits $ns1 0 1 ++ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup ++ pm_nl_set_limits $ns2 1 1 ++ sflags=nobackup speed=slow \ ++ run_tests $ns1 $ns2 10.0.1.1 ++ chk_join_nr 1 1 1 ++ chk_add_nr 1 1 ++ chk_prio_nr 1 0 0 1 ++ fi ++ ++ # single address, switch to backup ++ if reset "single address, switch to backup" && + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then + pm_nl_set_limits $ns1 0 1 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal +@@ -2764,20 +2799,20 @@ backup_tests() + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 +- chk_prio_nr 1 1 ++ chk_prio_nr 1 1 0 0 + fi + + # single address with port, backup + if reset "single address with port, backup" && + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then + pm_nl_set_limits $ns1 0 1 +- pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100 ++ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup port 10100 + pm_nl_set_limits $ns2 1 1 +- sflags=backup speed=slow \ ++ sflags=nobackup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 +- chk_prio_nr 1 1 ++ chk_prio_nr 1 0 0 1 + fi + + if reset "mpc backup" && +@@ -2786,17 +2821,26 @@ backup_tests() + speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 +- chk_prio_nr 0 1 ++ chk_prio_nr 0 1 0 0 + fi + + if reset "mpc backup both sides" && + continue_if mptcp_lib_kallsyms_doesnt_have "T mptcp_subflow_send_ack$"; then +- pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow,backup ++ pm_nl_set_limits $ns1 0 2 ++ pm_nl_set_limits $ns2 1 2 ++ pm_nl_add_endpoint $ns1 10.0.1.1 flags signal,backup + pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup ++ ++ # 10.0.2.2 (non-backup) -> 10.0.1.1 (backup) ++ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow ++ # 10.0.1.2 (backup) -> 10.0.2.1 (non-backup) ++ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal ++ ip -net "$ns2" route add 10.0.2.1 via 10.0.1.1 dev ns2eth1 # force this path ++ + speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 +- chk_join_nr 0 0 0 +- chk_prio_nr 1 1 ++ chk_join_nr 2 2 2 ++ chk_prio_nr 1 1 1 1 + fi + + if reset "mpc switch to backup" && +@@ -2805,7 +2849,7 @@ backup_tests() + sflags=backup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 +- chk_prio_nr 0 1 ++ chk_prio_nr 0 1 0 0 + fi + + if reset "mpc switch to backup both sides" && +@@ -2815,7 +2859,7 @@ backup_tests() + sflags=backup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 +- chk_prio_nr 1 1 ++ chk_prio_nr 1 1 0 0 + fi + } + +@@ -3215,7 +3259,7 @@ fullmesh_tests() + addr_nr_ns2=1 sflags=backup,fullmesh speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 2 2 2 +- chk_prio_nr 0 1 ++ chk_prio_nr 0 1 1 0 + chk_rm_nr 0 1 + fi + +@@ -3228,7 +3272,7 @@ fullmesh_tests() + sflags=nobackup,nofullmesh speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 2 2 2 +- chk_prio_nr 0 1 ++ chk_prio_nr 0 1 1 0 + chk_rm_nr 0 1 + fi + } +@@ -3407,7 +3451,7 @@ userspace_tests() + sflags=backup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 0 +- chk_prio_nr 0 0 ++ chk_prio_nr 0 0 0 0 + fi + + # userspace pm type prevents rm_addr diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.45-46.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.45-46.patch new file mode 100644 index 0000000000..359d52eccf --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.45-46.patch @@ -0,0 +1,6300 @@ +diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst +index 20aba92dfc5f5..3de599cf0779a 100644 +--- a/Documentation/admin-guide/cifs/usage.rst ++++ b/Documentation/admin-guide/cifs/usage.rst +@@ -741,7 +741,7 @@ SecurityFlags Flags which control security negotiation and + may use NTLMSSP 0x00080 + must use NTLMSSP 0x80080 + seal (packet encryption) 0x00040 +- must seal (not implemented yet) 0x40040 ++ must seal 0x40040 + + cifsFYI If set to non-zero value, additional debug information + will be logged to the system error log. This field +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 8d2f9ed3f1076..a7fe113897361 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -664,12 +664,6 @@ + loops can be debugged more effectively on production + systems. + +- clocksource.max_cswd_read_retries= [KNL] +- Number of clocksource_watchdog() retries due to +- external delays before the clock will be marked +- unstable. Defaults to two retries, that is, +- three attempts to read the clock under test. +- + clocksource.verify_n_cpus= [KNL] + Limit the number of CPUs checked for clocksources + marked with CLOCK_SOURCE_VERIFY_PERCPU that +@@ -4655,11 +4649,9 @@ + + profile= [KNL] Enable kernel profiling via /proc/profile + Format: [,] +- Param: : "schedule", "sleep", or "kvm" ++ Param: : "schedule" or "kvm" + [defaults to kernel profiling] + Param: "schedule" - profile schedule points. +- Param: "sleep" - profile D-state sleeping (millisecs). +- Requires CONFIG_SCHEDSTATS + Param: "kvm" - profile VM exits. + Param: - step/bucket size as a power of 2 for + statistical time based profiling. +diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst +index 29fd5213eeb2b..357d6cb98161f 100644 +--- a/Documentation/arch/arm64/silicon-errata.rst ++++ b/Documentation/arch/arm64/silicon-errata.rst +@@ -119,32 +119,68 @@ stable kernels. + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A76 | #1463225 | ARM64_ERRATUM_1463225 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A76 | #3324349 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A77 | #1508412 | ARM64_ERRATUM_1508412 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A77 | #3324348 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A710 | #2224489 | ARM64_ERRATUM_2224489 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A715 | #2645198 | ARM64_ERRATUM_2645198 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X1C | #3324346 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-X2 | #2224489 | ARM64_ERRATUM_2224489 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X2 | #3324338 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X3 | #3324335 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X4 | #3194386 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Cortex-X925 | #3324334 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N1 | #1349291 | N/A | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N2 | #2139208 | ARM64_ERRATUM_2139208 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N2 | #2067961 | ARM64_ERRATUM_2067961 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-N2 | #2253138 | ARM64_ERRATUM_2253138 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ ++| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | MMU-500 | #841119,826419 | N/A | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | MMU-600 | #1076982,1209401| N/A | +diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst +index 16db34d464dd6..7ed794087f848 100644 +--- a/Documentation/hwmon/corsair-psu.rst ++++ b/Documentation/hwmon/corsair-psu.rst +@@ -15,11 +15,11 @@ Supported devices: + + Corsair HX850i + +- Corsair HX1000i (Series 2022 and 2023) ++ Corsair HX1000i (Legacy and Series 2023) + +- Corsair HX1200i ++ Corsair HX1200i (Legacy and Series 2023) + +- Corsair HX1500i (Series 2022 and 2023) ++ Corsair HX1500i (Legacy and Series 2023) + + Corsair RM550i + +diff --git a/Makefile b/Makefile +index 0bd4bee2128b4..77de99984c2f1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 45 ++SUBLEVEL = 46 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index f9777ce2ccb2d..9e0c1ac3d13ee 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1068,6 +1068,44 @@ config ARM64_ERRATUM_3117295 + + If unsure, say Y. + ++config ARM64_ERRATUM_3194386 ++ bool "Cortex-*/Neoverse-*: workaround for MSR SSBS not self-synchronizing" ++ default y ++ help ++ This option adds the workaround for the following errata: ++ ++ * ARM Cortex-A76 erratum 3324349 ++ * ARM Cortex-A77 erratum 3324348 ++ * ARM Cortex-A78 erratum 3324344 ++ * ARM Cortex-A78C erratum 3324346 ++ * ARM Cortex-A78C erratum 3324347 ++ * ARM Cortex-A710 erratam 3324338 ++ * ARM Cortex-A720 erratum 3456091 ++ * ARM Cortex-A725 erratum 3456106 ++ * ARM Cortex-X1 erratum 3324344 ++ * ARM Cortex-X1C erratum 3324346 ++ * ARM Cortex-X2 erratum 3324338 ++ * ARM Cortex-X3 erratum 3324335 ++ * ARM Cortex-X4 erratum 3194386 ++ * ARM Cortex-X925 erratum 3324334 ++ * ARM Neoverse-N1 erratum 3324349 ++ * ARM Neoverse N2 erratum 3324339 ++ * ARM Neoverse-V1 erratum 3324341 ++ * ARM Neoverse V2 erratum 3324336 ++ * ARM Neoverse-V3 erratum 3312417 ++ ++ On affected cores "MSR SSBS, #0" instructions may not affect ++ subsequent speculative instructions, which may permit unexepected ++ speculative store bypassing. ++ ++ Work around this problem by placing a Speculation Barrier (SB) or ++ Instruction Synchronization Barrier (ISB) after kernel changes to ++ SSBS. The presence of the SSBS special-purpose register is hidden ++ from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such that userspace ++ will use the PR_SPEC_STORE_BYPASS prctl to change SSBS. ++ ++ If unsure, say Y. ++ + config CAVIUM_ERRATUM_22375 + bool "Cavium erratum 22375, 24313" + default y +diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h +index cf2987464c186..1ca947d5c9396 100644 +--- a/arch/arm64/include/asm/barrier.h ++++ b/arch/arm64/include/asm/barrier.h +@@ -40,6 +40,10 @@ + */ + #define dgh() asm volatile("hint #6" : : : "memory") + ++#define spec_bar() asm volatile(ALTERNATIVE("dsb nsh\nisb\n", \ ++ SB_BARRIER_INSN"nop\n", \ ++ ARM64_HAS_SB)) ++ + #ifdef CONFIG_ARM64_PSEUDO_NMI + #define pmr_sync() \ + do { \ +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 52f076afeb960..5fd7caea44193 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -86,6 +86,14 @@ + #define ARM_CPU_PART_CORTEX_X2 0xD48 + #define ARM_CPU_PART_NEOVERSE_N2 0xD49 + #define ARM_CPU_PART_CORTEX_A78C 0xD4B ++#define ARM_CPU_PART_CORTEX_X1C 0xD4C ++#define ARM_CPU_PART_CORTEX_X3 0xD4E ++#define ARM_CPU_PART_NEOVERSE_V2 0xD4F ++#define ARM_CPU_PART_CORTEX_A720 0xD81 ++#define ARM_CPU_PART_CORTEX_X4 0xD82 ++#define ARM_CPU_PART_NEOVERSE_V3 0xD84 ++#define ARM_CPU_PART_CORTEX_X925 0xD85 ++#define ARM_CPU_PART_CORTEX_A725 0xD87 + + #define APM_CPU_PART_XGENE 0x000 + #define APM_CPU_VAR_POTENZA 0x00 +@@ -159,6 +167,14 @@ + #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) + #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) + #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) ++#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C) ++#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3) ++#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2) ++#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720) ++#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4) ++#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) ++#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) ++#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index 7bba831f62c33..57b1d6a68256b 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -448,6 +448,30 @@ static const struct midr_range erratum_spec_unpriv_load_list[] = { + }; + #endif + ++#ifdef CONFIG_ARM64_ERRATUM_3194386 ++static const struct midr_range erratum_spec_ssbs_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X4), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), ++ {} ++}; ++#endif ++ + const struct arm64_cpu_capabilities arm64_errata[] = { + #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE + { +@@ -746,6 +770,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + .cpu_enable = cpu_clear_bf16_from_user_emulation, + }, + #endif ++#ifdef CONFIG_ARM64_ERRATUM_3194386 ++ { ++ .desc = "SSBS not fully self-synchronizing", ++ .capability = ARM64_WORKAROUND_SPECULATIVE_SSBS, ++ ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list), ++ }, ++#endif + #ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD + { + .desc = "ARM errata 2966298, 3117295", +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 444a73c2e6385..7e96604559004 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -2190,6 +2190,17 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap) + } + #endif /* CONFIG_ARM64_MTE */ + ++static void user_feature_fixup(void) ++{ ++ if (cpus_have_cap(ARM64_WORKAROUND_SPECULATIVE_SSBS)) { ++ struct arm64_ftr_reg *regp; ++ ++ regp = get_arm64_ftr_reg(SYS_ID_AA64PFR1_EL1); ++ if (regp) ++ regp->user_mask &= ~ID_AA64PFR1_EL1_SSBS_MASK; ++ } ++} ++ + static void elf_hwcap_fixup(void) + { + #ifdef CONFIG_ARM64_ERRATUM_1742098 +@@ -3345,6 +3356,7 @@ void __init setup_cpu_features(void) + u32 cwg; + + setup_system_capabilities(); ++ user_feature_fixup(); + setup_elf_hwcaps(arm64_elf_hwcaps); + + if (system_supports_32bit_el0()) { +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 05f40c4e18fda..57503dc4b22fa 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -558,6 +558,18 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void) + + /* SCTLR_EL1.DSSBS was initialised to 0 during boot */ + set_pstate_ssbs(0); ++ ++ /* ++ * SSBS is self-synchronizing and is intended to affect subsequent ++ * speculative instructions, but some CPUs can speculate with a stale ++ * value of SSBS. ++ * ++ * Mitigate this with an unconditional speculation barrier, as CPUs ++ * could mis-speculate branches and bypass a conditional barrier. ++ */ ++ if (IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386)) ++ spec_bar(); ++ + return SPECTRE_MITIGATED; + } + +diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps +index 5511bee15603a..c251ef3caae56 100644 +--- a/arch/arm64/tools/cpucaps ++++ b/arch/arm64/tools/cpucaps +@@ -99,4 +99,5 @@ WORKAROUND_NVIDIA_CARMEL_CNP + WORKAROUND_QCOM_FALKOR_E1003 + WORKAROUND_REPEAT_TLBI + WORKAROUND_SPECULATIVE_AT ++WORKAROUND_SPECULATIVE_SSBS + WORKAROUND_SPECULATIVE_UNPRIV_LOAD +diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c +index 9fc10cea21e10..de4f3def4af0b 100644 +--- a/arch/loongarch/kernel/efi.c ++++ b/arch/loongarch/kernel/efi.c +@@ -66,6 +66,12 @@ void __init efi_runtime_init(void) + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); + } + ++bool efi_poweroff_required(void) ++{ ++ return efi_enabled(EFI_RUNTIME_SERVICES) && ++ (acpi_gbl_reduced_hardware || acpi_no_s5); ++} ++ + unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR; + + static void __init init_screen_info(void) +diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig +index 2834a64064970..a077e6bf9475f 100644 +--- a/arch/parisc/Kconfig ++++ b/arch/parisc/Kconfig +@@ -18,6 +18,7 @@ config PARISC + select ARCH_SUPPORTS_HUGETLBFS if PA20 + select ARCH_SUPPORTS_MEMORY_FAILURE + select ARCH_STACKWALK ++ select ARCH_HAS_CACHE_LINE_SIZE + select ARCH_HAS_DEBUG_VM_PGTABLE + select HAVE_RELIABLE_STACKTRACE + select DMA_OPS +diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h +index 2a60d7a72f1fa..a3f0f100f2194 100644 +--- a/arch/parisc/include/asm/cache.h ++++ b/arch/parisc/include/asm/cache.h +@@ -20,7 +20,16 @@ + + #define SMP_CACHE_BYTES L1_CACHE_BYTES + +-#define ARCH_DMA_MINALIGN L1_CACHE_BYTES ++#ifdef CONFIG_PA20 ++#define ARCH_DMA_MINALIGN 128 ++#else ++#define ARCH_DMA_MINALIGN 32 ++#endif ++#define ARCH_KMALLOC_MINALIGN 16 /* ldcw requires 16-byte alignment */ ++ ++#define arch_slab_minalign() ((unsigned)dcache_stride) ++#define cache_line_size() dcache_stride ++#define dma_get_cache_alignment cache_line_size + + #define __read_mostly __section(".data..read_mostly") + +diff --git a/arch/parisc/net/bpf_jit_core.c b/arch/parisc/net/bpf_jit_core.c +index d6ee2fd455503..7b9cb3cda27ee 100644 +--- a/arch/parisc/net/bpf_jit_core.c ++++ b/arch/parisc/net/bpf_jit_core.c +@@ -114,7 +114,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) + jit_data->header = + bpf_jit_binary_alloc(prog_size + extable_size, + &jit_data->image, +- sizeof(u32), ++ sizeof(long), + bpf_fill_ill_insns); + if (!jit_data->header) { + prog = orig_prog; +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index 621bac6b74011..24b7bd255e983 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -237,6 +237,7 @@ + #define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) + #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 + #define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) ++#define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9) + + #define MSR_LBR_NHM_FROM 0x00000680 + #define MSR_LBR_NHM_TO 0x000006c0 +diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h +index cde8357bb226d..e897046c5d2c6 100644 +--- a/arch/x86/include/asm/qspinlock.h ++++ b/arch/x86/include/asm/qspinlock.h +@@ -66,13 +66,15 @@ static inline bool vcpu_is_preempted(long cpu) + + #ifdef CONFIG_PARAVIRT + /* +- * virt_spin_lock_key - enables (by default) the virt_spin_lock() hijack. ++ * virt_spin_lock_key - disables by default the virt_spin_lock() hijack. + * +- * Native (and PV wanting native due to vCPU pinning) should disable this key. +- * It is done in this backwards fashion to only have a single direction change, +- * which removes ordering between native_pv_spin_init() and HV setup. ++ * Native (and PV wanting native due to vCPU pinning) should keep this key ++ * disabled. Native does not touch the key. ++ * ++ * When in a guest then native_pv_lock_init() enables the key first and ++ * KVM/XEN might conditionally disable it later in the boot process again. + */ +-DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key); ++DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key); + + /* + * Shortcut for the queued_spin_lock_slowpath() function that allows +diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c +index 767bf1c71aadd..2a2fc14955cd3 100644 +--- a/arch/x86/kernel/cpu/mtrr/mtrr.c ++++ b/arch/x86/kernel/cpu/mtrr/mtrr.c +@@ -609,7 +609,7 @@ void mtrr_save_state(void) + { + int first_cpu; + +- if (!mtrr_enabled()) ++ if (!mtrr_enabled() || !mtrr_state.have_fixed) + return; + + first_cpu = cpumask_first(cpu_online_mask); +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index 97f1436c1a203..8d51c86caa415 100644 +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -71,13 +71,12 @@ DEFINE_PARAVIRT_ASM(pv_native_irq_enable, "sti", .noinstr.text); + DEFINE_PARAVIRT_ASM(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text); + #endif + +-DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key); ++DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key); + + void __init native_pv_lock_init(void) + { +- if (IS_ENABLED(CONFIG_PARAVIRT_SPINLOCKS) && +- !boot_cpu_has(X86_FEATURE_HYPERVISOR)) +- static_branch_disable(&virt_spin_lock_key); ++ if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) ++ static_branch_enable(&virt_spin_lock_key); + } + + static void native_tlb_remove_table(struct mmu_gather *tlb, void *table) +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index 51b6b78e6b175..41d8c8f475a7c 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -374,14 +374,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end, + */ + *target_pmd = *pmd; + +- addr += PMD_SIZE; ++ addr = round_up(addr + 1, PMD_SIZE); + + } else if (level == PTI_CLONE_PTE) { + + /* Walk the page-table down to the pte level */ + pte = pte_offset_kernel(pmd, addr); + if (pte_none(*pte)) { +- addr += PAGE_SIZE; ++ addr = round_up(addr + 1, PAGE_SIZE); + continue; + } + +@@ -401,7 +401,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end, + /* Clone the PTE */ + *target_pte = *pte; + +- addr += PAGE_SIZE; ++ addr = round_up(addr + 1, PAGE_SIZE); + + } else { + BUG(); +@@ -496,7 +496,7 @@ static void pti_clone_entry_text(void) + { + pti_clone_pgtable((unsigned long) __entry_text_start, + (unsigned long) __entry_text_end, +- PTI_CLONE_PMD); ++ PTI_LEVEL_KERNEL_IMAGE); + } + + /* +diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c +index 969bf81e8d546..7f7ad94f22b91 100644 +--- a/drivers/acpi/battery.c ++++ b/drivers/acpi/battery.c +@@ -678,12 +678,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, + return count; + } + +-static const struct device_attribute alarm_attr = { ++static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, + }; + ++static struct attribute *acpi_battery_attrs[] = { ++ &alarm_attr.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(acpi_battery); ++ + /* + * The Battery Hooking API + * +@@ -823,7 +829,10 @@ static void __exit battery_hook_exit(void) + + static int sysfs_add_battery(struct acpi_battery *battery) + { +- struct power_supply_config psy_cfg = { .drv_data = battery, }; ++ struct power_supply_config psy_cfg = { ++ .drv_data = battery, ++ .attr_grp = acpi_battery_groups, ++ }; + bool full_cap_broken = false; + + if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && +@@ -868,7 +877,7 @@ static int sysfs_add_battery(struct acpi_battery *battery) + return result; + } + battery_hook_add_battery(battery); +- return device_create_file(&battery->bat->dev, &alarm_attr); ++ return 0; + } + + static void sysfs_remove_battery(struct acpi_battery *battery) +@@ -879,7 +888,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) + return; + } + battery_hook_remove_battery(battery); +- device_remove_file(&battery->bat->dev, &alarm_attr); + power_supply_unregister(battery->bat); + battery->bat = NULL; + mutex_unlock(&battery->sysfs_lock); +diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c +index 94e3c000df2e1..fdeb46ed21d69 100644 +--- a/drivers/acpi/sbs.c ++++ b/drivers/acpi/sbs.c +@@ -77,7 +77,6 @@ struct acpi_battery { + u16 spec; + u8 id; + u8 present:1; +- u8 have_sysfs_alarm:1; + }; + + #define to_acpi_battery(x) power_supply_get_drvdata(x) +@@ -462,12 +461,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, + return count; + } + +-static const struct device_attribute alarm_attr = { ++static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, + }; + ++static struct attribute *acpi_battery_attrs[] = { ++ &alarm_attr.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(acpi_battery); ++ + /* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ +@@ -518,7 +523,10 @@ static int acpi_battery_read(struct acpi_battery *battery) + static int acpi_battery_add(struct acpi_sbs *sbs, int id) + { + struct acpi_battery *battery = &sbs->battery[id]; +- struct power_supply_config psy_cfg = { .drv_data = battery, }; ++ struct power_supply_config psy_cfg = { ++ .drv_data = battery, ++ .attr_grp = acpi_battery_groups, ++ }; + int result; + + battery->id = id; +@@ -548,10 +556,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) + goto end; + } + +- result = device_create_file(&battery->bat->dev, &alarm_attr); +- if (result) +- goto end; +- battery->have_sysfs_alarm = 1; + end: + pr_info("%s [%s]: Battery Slot [%s] (battery %s)\n", + ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), +@@ -563,11 +567,8 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id) + { + struct acpi_battery *battery = &sbs->battery[id]; + +- if (battery->bat) { +- if (battery->have_sysfs_alarm) +- device_remove_file(&battery->bat->dev, &alarm_attr); ++ if (battery->bat) + power_supply_unregister(battery->bat); +- } + } + + static int acpi_charger_add(struct acpi_sbs *sbs) +diff --git a/drivers/base/core.c b/drivers/base/core.c +index aeb4644817d57..cb323700e952f 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2565,6 +2566,7 @@ static const char *dev_uevent_name(const struct kobject *kobj) + static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) + { + const struct device *dev = kobj_to_dev(kobj); ++ struct device_driver *driver; + int retval = 0; + + /* add device node properties if present */ +@@ -2593,8 +2595,12 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) + if (dev->type && dev->type->name) + add_uevent_var(env, "DEVTYPE=%s", dev->type->name); + +- if (dev->driver) +- add_uevent_var(env, "DRIVER=%s", dev->driver->name); ++ /* Synchronize with module_remove_driver() */ ++ rcu_read_lock(); ++ driver = READ_ONCE(dev->driver); ++ if (driver) ++ add_uevent_var(env, "DRIVER=%s", driver->name); ++ rcu_read_unlock(); + + /* Add common DT information about the device */ + of_device_uevent(dev, env); +@@ -2664,11 +2670,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, + if (!env) + return -ENOMEM; + +- /* Synchronize with really_probe() */ +- device_lock(dev); + /* let the kset specific function add its keys */ + retval = kset->uevent_ops->uevent(&dev->kobj, env); +- device_unlock(dev); + if (retval) + goto out; + +diff --git a/drivers/base/module.c b/drivers/base/module.c +index a1b55da07127d..b0b79b9c189d4 100644 +--- a/drivers/base/module.c ++++ b/drivers/base/module.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include "base.h" + + static char *make_driver_name(struct device_driver *drv) +@@ -97,6 +98,9 @@ void module_remove_driver(struct device_driver *drv) + if (!drv) + return; + ++ /* Synchronize with dev_uevent() */ ++ synchronize_rcu(); ++ + sysfs_remove_link(&drv->p->kobj, "module"); + + if (drv->owner) +diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c +index 83e8e27a5ecec..b5d40e0e05f31 100644 +--- a/drivers/bluetooth/btnxpuart.c ++++ b/drivers/bluetooth/btnxpuart.c +@@ -340,7 +340,7 @@ static void ps_cancel_timer(struct btnxpuart_dev *nxpdev) + struct ps_data *psdata = &nxpdev->psdata; + + flush_work(&psdata->work); +- del_timer_sync(&psdata->ps_timer); ++ timer_shutdown_sync(&psdata->ps_timer); + } + + static void ps_control(struct hci_dev *hdev, u8 ps_state) +diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c +index 26919556ef5f0..b72b36e0abed8 100644 +--- a/drivers/clocksource/sh_cmt.c ++++ b/drivers/clocksource/sh_cmt.c +@@ -528,6 +528,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta) + static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) + { + struct sh_cmt_channel *ch = dev_id; ++ unsigned long flags; + + /* clear flags */ + sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & +@@ -558,6 +559,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) + + ch->flags &= ~FLAG_SKIPEVENT; + ++ raw_spin_lock_irqsave(&ch->lock, flags); ++ + if (ch->flags & FLAG_REPROGRAM) { + ch->flags &= ~FLAG_REPROGRAM; + sh_cmt_clock_event_program_verify(ch, 1); +@@ -570,6 +573,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) + + ch->flags &= ~FLAG_IRQCONTEXT; + ++ raw_spin_unlock_irqrestore(&ch->lock, flags); ++ + return IRQ_HANDLED; + } + +@@ -780,12 +785,18 @@ static int sh_cmt_clock_event_next(unsigned long delta, + struct clock_event_device *ced) + { + struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); ++ unsigned long flags; + + BUG_ON(!clockevent_state_oneshot(ced)); ++ ++ raw_spin_lock_irqsave(&ch->lock, flags); ++ + if (likely(ch->flags & FLAG_IRQCONTEXT)) + ch->next_match_value = delta - 1; + else +- sh_cmt_set_next(ch, delta - 1); ++ __sh_cmt_set_next(ch, delta - 1); ++ ++ raw_spin_unlock_irqrestore(&ch->lock, flags); + + return 0; + } +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 1c512ed3fa6d9..5c0016c77d2ab 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -164,7 +165,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, + if (hwnum >= gdev->ngpio) + return ERR_PTR(-EINVAL); + +- return &gdev->descs[hwnum]; ++ return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)]; + } + EXPORT_SYMBOL_GPL(gpiochip_get_desc); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index ea1bce13db941..eb663eb811563 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -3561,6 +3561,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, + mutex_init(&adev->grbm_idx_mutex); + mutex_init(&adev->mn_lock); + mutex_init(&adev->virt.vf_errors.lock); ++ mutex_init(&adev->virt.rlcg_reg_lock); + hash_init(adev->mn_hash); + mutex_init(&adev->psp.mutex); + mutex_init(&adev->notifier_lock); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +index de9d7f3dc2336..99dd86337e841 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +@@ -258,9 +258,8 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job, + struct dma_fence *fence = NULL; + int r; + +- /* Ignore soft recovered fences here */ + r = drm_sched_entity_error(s_entity); +- if (r && r != -ENODATA) ++ if (r) + goto error; + + if (!fence && job->gang_submit) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +index ca5c86e5f7cd6..8e8afbd237bcd 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +@@ -334,7 +334,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size + + set_ta_context_funcs(psp, ta_type, &context); + +- if (!context->initialized) { ++ if (!context || !context->initialized) { + dev_err(adev->dev, "TA is not initialized\n"); + ret = -EINVAL; + goto err_free_shared_buf; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +index 67b75ff0f7c37..7cba98f8bbdca 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +@@ -1780,12 +1780,15 @@ static void amdgpu_ras_interrupt_process_handler(struct work_struct *work) + int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev, + struct ras_dispatch_if *info) + { +- struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head); +- struct ras_ih_data *data = &obj->ih_data; ++ struct ras_manager *obj; ++ struct ras_ih_data *data; + ++ obj = amdgpu_ras_find_obj(adev, &info->head); + if (!obj) + return -EINVAL; + ++ data = &obj->ih_data; ++ + if (data->inuse == 0) + return 0; + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +index 96857ae7fb5bc..ff4f52e07cc0d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +@@ -1003,6 +1003,9 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v + scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1; + scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2; + scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3; ++ ++ mutex_lock(&adev->virt.rlcg_reg_lock); ++ + if (reg_access_ctrl->spare_int) + spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int; + +@@ -1058,6 +1061,9 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v + } + + ret = readl(scratch_reg0); ++ ++ mutex_unlock(&adev->virt.rlcg_reg_lock); ++ + return ret; + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index fabb83e9d9aec..23b6efa9d25df 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -263,6 +263,8 @@ struct amdgpu_virt { + + /* the ucode id to signal the autoload */ + uint32_t autoload_ucode_id; ++ ++ struct mutex rlcg_reg_lock; + }; + + struct amdgpu_video_codec_info; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +index 349416e176a12..1cf1498204678 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +@@ -102,6 +102,11 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p, + if (!r) + r = amdgpu_sync_push_to_job(&sync, p->job); + amdgpu_sync_free(&sync); ++ ++ if (r) { ++ p->num_dw_left = 0; ++ amdgpu_job_free(p->job); ++ } + return r; + } + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 60db3800666ec..94059aef762be 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -2628,7 +2628,8 @@ static int dm_suspend(void *handle) + + dm->cached_dc_state = dc_copy_state(dm->dc->current_state); + +- dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); ++ if (dm->cached_dc_state) ++ dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); + + amdgpu_dm_commit_zero_streams(dm->dc); + +@@ -6483,7 +6484,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +- dc_sink_retain(aconnector->dc_sink); ++ if (aconnector->dc_sink) ++ dc_sink_retain(aconnector->dc_sink); + } + } + +@@ -7296,7 +7298,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) + drm_add_modes_noedid(connector, 1920, 1080); + } else { + amdgpu_dm_connector_ddc_get_modes(connector, edid); +- amdgpu_dm_connector_add_common_modes(encoder, connector); ++ if (encoder) ++ amdgpu_dm_connector_add_common_modes(encoder, connector); + amdgpu_dm_connector_add_freesync_modes(connector, edid); + } + amdgpu_dm_fbc_init(connector); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index 2104511f3b863..3880ddf1c820f 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1266,6 +1266,9 @@ static bool is_dsc_need_re_compute( + } + } + ++ if (new_stream_on_link_num == 0) ++ return false; ++ + /* check current_state if there stream on link but it is not in + * new request state + */ +diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c +index b621b97711b61..a7f5b0f6272ce 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c ++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c +@@ -162,7 +162,12 @@ static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin + link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( + link_res->hpo_dp_link_enc, tp_params); + } ++ + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); ++ ++ // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1 ++ if (tp_params->dp_phy_pattern == DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE) ++ msleep(30); + } + + static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link, +diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +index 9e4f8a4104a34..7bf46e4974f88 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +@@ -927,7 +927,7 @@ static int pp_dpm_switch_power_profile(void *handle, + enum PP_SMC_POWER_PROFILE type, bool en) + { + struct pp_hwmgr *hwmgr = handle; +- long workload; ++ long workload[1]; + uint32_t index; + + if (!hwmgr || !hwmgr->pm_en) +@@ -945,12 +945,12 @@ static int pp_dpm_switch_power_profile(void *handle, + hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]); + index = fls(hwmgr->workload_mask); + index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; +- workload = hwmgr->workload_setting[index]; ++ workload[0] = hwmgr->workload_setting[index]; + } else { + hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]); + index = fls(hwmgr->workload_mask); + index = index <= Workload_Policy_Max ? index - 1 : 0; +- workload = hwmgr->workload_setting[index]; ++ workload[0] = hwmgr->workload_setting[index]; + } + + if (type == PP_SMC_POWER_PROFILE_COMPUTE && +@@ -960,7 +960,7 @@ static int pp_dpm_switch_power_profile(void *handle, + } + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) +- hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); ++ hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0); + + return 0; + } +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +index 1d829402cd2e2..f4bd8e9357e22 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +@@ -269,7 +269,7 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set + struct pp_power_state *new_ps) + { + uint32_t index; +- long workload; ++ long workload[1]; + + if (hwmgr->not_vf) { + if (!skip_display_settings) +@@ -294,10 +294,10 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + index = fls(hwmgr->workload_mask); + index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; +- workload = hwmgr->workload_setting[index]; ++ workload[0] = hwmgr->workload_setting[index]; + +- if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode) +- hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); ++ if (hwmgr->power_profile_mode != workload[0] && hwmgr->hwmgr_func->set_power_profile_mode) ++ hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +index aa91730e4eaff..163864bd51c34 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +@@ -2957,6 +2957,7 @@ static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr) + + static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) + { ++ struct amdgpu_device *adev = hwmgr->adev; + struct smu7_hwmgr *data; + int result = 0; + +@@ -2993,40 +2994,37 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) + /* Initalize Dynamic State Adjustment Rule Settings */ + result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr); + +- if (0 == result) { +- struct amdgpu_device *adev = hwmgr->adev; ++ if (result) ++ goto fail; + +- data->is_tlu_enabled = false; ++ data->is_tlu_enabled = false; + +- hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = ++ hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + SMU7_MAX_HARDWARE_POWERLEVELS; +- hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; +- hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; ++ hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; ++ hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + +- data->pcie_gen_cap = adev->pm.pcie_gen_mask; +- if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) +- data->pcie_spc_cap = 20; +- else +- data->pcie_spc_cap = 16; +- data->pcie_lane_cap = adev->pm.pcie_mlw_mask; +- +- hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ +-/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ +- hwmgr->platform_descriptor.clockStep.engineClock = 500; +- hwmgr->platform_descriptor.clockStep.memoryClock = 500; +- smu7_thermal_parameter_init(hwmgr); +- } else { +- /* Ignore return value in here, we are cleaning up a mess. */ +- smu7_hwmgr_backend_fini(hwmgr); +- } ++ data->pcie_gen_cap = adev->pm.pcie_gen_mask; ++ if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) ++ data->pcie_spc_cap = 20; ++ else ++ data->pcie_spc_cap = 16; ++ data->pcie_lane_cap = adev->pm.pcie_mlw_mask; ++ ++ hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ ++ /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ ++ hwmgr->platform_descriptor.clockStep.engineClock = 500; ++ hwmgr->platform_descriptor.clockStep.memoryClock = 500; ++ smu7_thermal_parameter_init(hwmgr); + + result = smu7_update_edc_leakage_table(hwmgr); +- if (result) { +- smu7_hwmgr_backend_fini(hwmgr); +- return result; +- } ++ if (result) ++ goto fail; + + return 0; ++fail: ++ smu7_hwmgr_backend_fini(hwmgr); ++ return result; + } + + static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) +@@ -3316,8 +3314,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + const struct pp_power_state *current_ps) + { + struct amdgpu_device *adev = hwmgr->adev; +- struct smu7_power_state *smu7_ps = +- cast_phw_smu7_power_state(&request_ps->hardware); ++ struct smu7_power_state *smu7_ps; + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; +@@ -3334,6 +3331,10 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + uint32_t latency; + bool latency_allowed = false; + ++ smu7_ps = cast_phw_smu7_power_state(&request_ps->hardware); ++ if (!smu7_ps) ++ return -EINVAL; ++ + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + data->mclk_ignore_signal = false; +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +index b015a601b385a..eb744401e0567 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +@@ -1065,16 +1065,18 @@ static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps) + { +- struct smu8_power_state *smu8_ps = +- cast_smu8_power_state(&prequest_ps->hardware); +- +- const struct smu8_power_state *smu8_current_ps = +- cast_const_smu8_power_state(&pcurrent_ps->hardware); +- ++ struct smu8_power_state *smu8_ps; ++ const struct smu8_power_state *smu8_current_ps; + struct smu8_hwmgr *data = hwmgr->backend; + struct PP_Clocks clocks = {0, 0, 0, 0}; + bool force_high; + ++ smu8_ps = cast_smu8_power_state(&prequest_ps->hardware); ++ smu8_current_ps = cast_const_smu8_power_state(&pcurrent_ps->hardware); ++ ++ if (!smu8_ps || !smu8_current_ps) ++ return -EINVAL; ++ + smu8_ps->need_dfs_bypass = true; + + data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +index 6d6bc6a380b36..d43a530aba0e3 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +@@ -3259,8 +3259,7 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + const struct pp_power_state *current_ps) + { + struct amdgpu_device *adev = hwmgr->adev; +- struct vega10_power_state *vega10_ps = +- cast_phw_vega10_power_state(&request_ps->hardware); ++ struct vega10_power_state *vega10_ps; + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; +@@ -3278,6 +3277,10 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + uint32_t latency; + ++ vega10_ps = cast_phw_vega10_power_state(&request_ps->hardware); ++ if (!vega10_ps) ++ return -EINVAL; ++ + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + +@@ -3415,13 +3418,17 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co + const struct vega10_power_state *vega10_ps = + cast_const_phw_vega10_power_state(states->pnew_state); + struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); +- uint32_t sclk = vega10_ps->performance_levels +- [vega10_ps->performance_level_count - 1].gfx_clock; + struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); +- uint32_t mclk = vega10_ps->performance_levels +- [vega10_ps->performance_level_count - 1].mem_clock; ++ uint32_t sclk, mclk; + uint32_t i; + ++ if (vega10_ps == NULL) ++ return -EINVAL; ++ sclk = vega10_ps->performance_levels ++ [vega10_ps->performance_level_count - 1].gfx_clock; ++ mclk = vega10_ps->performance_levels ++ [vega10_ps->performance_level_count - 1].mem_clock; ++ + for (i = 0; i < sclk_table->count; i++) { + if (sclk == sclk_table->dpm_levels[i].value) + break; +@@ -3728,6 +3735,9 @@ static int vega10_generate_dpm_level_enable_mask( + cast_const_phw_vega10_power_state(states->pnew_state); + int i; + ++ if (vega10_ps == NULL) ++ return -EINVAL; ++ + PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps), + "Attempt to Trim DPM States Failed!", + return -1); +@@ -4995,6 +5005,8 @@ static int vega10_check_states_equal(struct pp_hwmgr *hwmgr, + + vega10_psa = cast_const_phw_vega10_power_state(pstate1); + vega10_psb = cast_const_phw_vega10_power_state(pstate2); ++ if (vega10_psa == NULL || vega10_psb == NULL) ++ return -EINVAL; + + /* If the two states don't even have the same number of performance levels + * they cannot be the same state. +@@ -5128,6 +5140,8 @@ static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); ++ if (vega10_ps == NULL) ++ return -EINVAL; + + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock = +@@ -5179,6 +5193,8 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); ++ if (vega10_ps == NULL) ++ return -EINVAL; + + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].mem_clock = +@@ -5420,6 +5436,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) + return; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); ++ if (vega10_ps == NULL) ++ return; ++ + max_level = vega10_ps->performance_level_count - 1; + + if (vega10_ps->performance_levels[max_level].gfx_clock != +@@ -5442,6 +5461,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) + + ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1)); + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); ++ if (vega10_ps == NULL) ++ return; ++ + max_level = vega10_ps->performance_level_count - 1; + + if (vega10_ps->performance_levels[max_level].gfx_clock != +@@ -5632,6 +5654,8 @@ static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_ + return -EINVAL; + + vega10_ps = cast_const_phw_vega10_power_state(state); ++ if (vega10_ps == NULL) ++ return -EINVAL; + + i = index > vega10_ps->performance_level_count - 1 ? + vega10_ps->performance_level_count - 1 : index; +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index 56e4c312cb7a9..1402e468aa90f 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -1846,7 +1846,7 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu, + { + int ret = 0; + int index = 0; +- long workload; ++ long workload[1]; + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + + if (!skip_display_settings) { +@@ -1886,10 +1886,10 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu, + smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) { + index = fls(smu->workload_mask); + index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; +- workload = smu->workload_setting[index]; ++ workload[0] = smu->workload_setting[index]; + +- if (smu->power_profile_mode != workload) +- smu_bump_power_profile_mode(smu, &workload, 0); ++ if (smu->power_profile_mode != workload[0]) ++ smu_bump_power_profile_mode(smu, workload, 0); + } + + return ret; +@@ -1939,7 +1939,7 @@ static int smu_switch_power_profile(void *handle, + { + struct smu_context *smu = handle; + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); +- long workload; ++ long workload[1]; + uint32_t index; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) +@@ -1952,17 +1952,17 @@ static int smu_switch_power_profile(void *handle, + smu->workload_mask &= ~(1 << smu->workload_prority[type]); + index = fls(smu->workload_mask); + index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; +- workload = smu->workload_setting[index]; ++ workload[0] = smu->workload_setting[index]; + } else { + smu->workload_mask |= (1 << smu->workload_prority[type]); + index = fls(smu->workload_mask); + index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; +- workload = smu->workload_setting[index]; ++ workload[0] = smu->workload_setting[index]; + } + + if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL && + smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) +- smu_bump_power_profile_mode(smu, &workload, 0); ++ smu_bump_power_profile_mode(smu, workload, 0); + + return 0; + } +diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +index 6a4f20fccf841..7b0bc9704eacb 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +@@ -1027,7 +1027,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, + u32 status_reg; + u8 *buffer = msg->buffer; + unsigned int i; +- int num_transferred = 0; + int ret; + + /* Buffer size of AUX CH is 16 bytes */ +@@ -1079,7 +1078,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, + reg = buffer[i]; + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * i); +- num_transferred++; + } + } + +@@ -1127,7 +1125,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * i); + buffer[i] = (unsigned char)reg; +- num_transferred++; + } + } + +@@ -1144,7 +1141,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, + (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) + msg->reply = DP_AUX_NATIVE_REPLY_ACK; + +- return num_transferred > 0 ? num_transferred : -EBUSY; ++ return msg->size; + + aux_error: + /* if aux err happen, reset aux */ +diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c +index 9023c0216a8a4..6ead31701e79e 100644 +--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c +@@ -4024,6 +4024,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { + const struct drm_dp_connection_status_notify *conn_stat = + &up_req->msg.u.conn_stat; ++ bool handle_csn; + + drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", + conn_stat->port_number, +@@ -4032,6 +4033,16 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + conn_stat->message_capability_status, + conn_stat->input_port, + conn_stat->peer_device_type); ++ ++ mutex_lock(&mgr->probe_lock); ++ handle_csn = mgr->mst_primary->link_address_sent; ++ mutex_unlock(&mgr->probe_lock); ++ ++ if (!handle_csn) { ++ drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it."); ++ kfree(up_req); ++ goto out; ++ } + } else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { + const struct drm_dp_resource_status_notify *res_stat = + &up_req->msg.u.resource_stat; +diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c +index 0683a129b3628..51df7244de718 100644 +--- a/drivers/gpu/drm/drm_client_modeset.c ++++ b/drivers/gpu/drm/drm_client_modeset.c +@@ -869,6 +869,11 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, + + kfree(modeset->mode); + modeset->mode = drm_mode_duplicate(dev, mode); ++ if (!modeset->mode) { ++ ret = -ENOMEM; ++ break; ++ } ++ + drm_connector_get(connector); + modeset->connectors[modeset->num_connectors++] = connector; + modeset->x = offset->x; +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c +index 310654542b42c..a59c17ec7fa36 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c +@@ -290,6 +290,41 @@ static vm_fault_t vm_fault_cpu(struct vm_fault *vmf) + return i915_error_to_vmf_fault(err); + } + ++static void set_address_limits(struct vm_area_struct *area, ++ struct i915_vma *vma, ++ unsigned long obj_offset, ++ unsigned long *start_vaddr, ++ unsigned long *end_vaddr) ++{ ++ unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */ ++ long start, end; /* memory boundaries */ ++ ++ /* ++ * Let's move into the ">> PAGE_SHIFT" ++ * domain to be sure not to lose bits ++ */ ++ vm_start = area->vm_start >> PAGE_SHIFT; ++ vm_end = area->vm_end >> PAGE_SHIFT; ++ vma_size = vma->size >> PAGE_SHIFT; ++ ++ /* ++ * Calculate the memory boundaries by considering the offset ++ * provided by the user during memory mapping and the offset ++ * provided for the partial mapping. ++ */ ++ start = vm_start; ++ start -= obj_offset; ++ start += vma->gtt_view.partial.offset; ++ end = start + vma_size; ++ ++ start = max_t(long, start, vm_start); ++ end = min_t(long, end, vm_end); ++ ++ /* Let's move back into the "<< PAGE_SHIFT" domain */ ++ *start_vaddr = (unsigned long)start << PAGE_SHIFT; ++ *end_vaddr = (unsigned long)end << PAGE_SHIFT; ++} ++ + static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) + { + #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT) +@@ -302,14 +337,18 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) + struct i915_ggtt *ggtt = to_gt(i915)->ggtt; + bool write = area->vm_flags & VM_WRITE; + struct i915_gem_ww_ctx ww; ++ unsigned long obj_offset; ++ unsigned long start, end; /* memory boundaries */ + intel_wakeref_t wakeref; + struct i915_vma *vma; + pgoff_t page_offset; ++ unsigned long pfn; + int srcu; + int ret; + +- /* We don't use vmf->pgoff since that has the fake offset */ ++ obj_offset = area->vm_pgoff - drm_vma_node_start(&mmo->vma_node); + page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT; ++ page_offset += obj_offset; + + trace_i915_gem_object_fault(obj, page_offset, true, write); + +@@ -402,12 +441,14 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) + if (ret) + goto err_unpin; + ++ set_address_limits(area, vma, obj_offset, &start, &end); ++ ++ pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT; ++ pfn += (start - area->vm_start) >> PAGE_SHIFT; ++ pfn += obj_offset - vma->gtt_view.partial.offset; ++ + /* Finally, remap it using the new GTT offset */ +- ret = remap_io_mapping(area, +- area->vm_start + (vma->gtt_view.partial.offset << PAGE_SHIFT), +- (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT, +- min_t(u64, vma->size, area->vm_end - area->vm_start), +- &ggtt->iomap); ++ ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap); + if (ret) + goto err_fence; + +@@ -1088,6 +1129,8 @@ int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma + mmo = mmap_offset_attach(obj, mmap_type, NULL); + if (IS_ERR(mmo)) + return PTR_ERR(mmo); ++ ++ vma->vm_pgoff += drm_vma_node_start(&mmo->vma_node); + } + + /* +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index 10fd9154cc465..8c9b656eeb59d 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -486,3 +486,4 @@ module_platform_driver(lima_platform_driver); + MODULE_AUTHOR("Lima Project Developers"); + MODULE_DESCRIPTION("Lima DRM Driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_SOFTDEP("pre: governor_simpleondemand"); +diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c +index 0c48bdf3e7f80..f5c5d06d0d4bb 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_i2c.c ++++ b/drivers/gpu/drm/mgag200/mgag200_i2c.c +@@ -31,6 +31,8 @@ + #include + #include + ++#include ++ + #include "mgag200_drv.h" + + static int mga_i2c_read_gpio(struct mga_device *mdev) +@@ -86,7 +88,7 @@ static int mga_gpio_getscl(void *data) + return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0; + } + +-static void mgag200_i2c_release(void *res) ++static void mgag200_i2c_release(struct drm_device *dev, void *res) + { + struct mga_i2c_chan *i2c = res; + +@@ -115,7 +117,7 @@ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c) + i2c->adapter.algo_data = &i2c->bit; + + i2c->bit.udelay = 10; +- i2c->bit.timeout = 2; ++ i2c->bit.timeout = usecs_to_jiffies(2200); + i2c->bit.data = i2c; + i2c->bit.setsda = mga_gpio_setsda; + i2c->bit.setscl = mga_gpio_setscl; +@@ -126,5 +128,5 @@ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c) + if (ret) + return ret; + +- return devm_add_action_or_reset(dev->dev, mgag200_i2c_release, i2c); ++ return drmm_add_action_or_reset(dev, mgag200_i2c_release, i2c); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c +index 2bbcdc649e862..3d41e590d4712 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c +@@ -1320,6 +1320,7 @@ nouveau_uvmm_bind_job_submit(struct nouveau_job *job) + + drm_gpuva_for_each_op(va_op, op->ops) { + struct drm_gem_object *obj = op_gem_obj(va_op); ++ struct nouveau_bo *nvbo; + + if (unlikely(!obj)) + continue; +@@ -1330,8 +1331,9 @@ nouveau_uvmm_bind_job_submit(struct nouveau_job *job) + if (unlikely(va_op->op == DRM_GPUVA_OP_UNMAP)) + continue; + +- ret = nouveau_bo_validate(nouveau_gem_object(obj), +- true, false); ++ nvbo = nouveau_gem_object(obj); ++ nouveau_bo_placement_set(nvbo, nvbo->valid_domains, 0); ++ ret = nouveau_bo_validate(nvbo, true, false); + if (ret) { + op = list_last_op(&bind_job->ops); + goto unwind; +diff --git a/drivers/gpu/drm/radeon/pptable.h b/drivers/gpu/drm/radeon/pptable.h +index 844f0490bf31f..ce8832916704f 100644 +--- a/drivers/gpu/drm/radeon/pptable.h ++++ b/drivers/gpu/drm/radeon/pptable.h +@@ -439,7 +439,7 @@ typedef struct _StateArray{ + //how many states we have + UCHAR ucNumEntries; + +- ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries); ++ ATOM_PPLIB_STATE_V2 states[] /* __counted_by(ucNumEntries) */; + }StateArray; + + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 2c7c92272fe39..f8f22b8a67cdf 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -875,15 +875,16 @@ static const struct hid_device_id corsairpsu_idtable[] = { + { HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */ + { HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */ + { HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */ +- { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */ +- { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */ ++ { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Legacy */ ++ { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i Legacy */ + { HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */ + { HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */ + { HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */ + { HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */ + { HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */ + { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */ +- { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */ ++ { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */ ++ { HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */ + { }, + }; + MODULE_DEVICE_TABLE(hid, corsairpsu_idtable); +diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c +index 5cc32a465f12e..b17411e97be68 100644 +--- a/drivers/i2c/busses/i2c-qcom-geni.c ++++ b/drivers/i2c/busses/i2c-qcom-geni.c +@@ -991,8 +991,11 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) + return ret; + + ret = geni_se_resources_on(&gi2c->se); +- if (ret) ++ if (ret) { ++ clk_disable_unprepare(gi2c->core_clk); ++ geni_icc_disable(&gi2c->se); + return ret; ++ } + + enable_irq(gi2c->irq); + gi2c->suspended = 0; +diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c +index 138c3f5e0093a..6520e09743912 100644 +--- a/drivers/i2c/i2c-smbus.c ++++ b/drivers/i2c/i2c-smbus.c +@@ -34,6 +34,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) + struct i2c_client *client = i2c_verify_client(dev); + struct alert_data *data = addrp; + struct i2c_driver *driver; ++ int ret; + + if (!client || client->addr != data->addr) + return 0; +@@ -47,16 +48,47 @@ static int smbus_do_alert(struct device *dev, void *addrp) + device_lock(dev); + if (client->dev.driver) { + driver = to_i2c_driver(client->dev.driver); +- if (driver->alert) ++ if (driver->alert) { ++ /* Stop iterating after we find the device */ + driver->alert(client, data->type, data->data); +- else ++ ret = -EBUSY; ++ } else { + dev_warn(&client->dev, "no driver alert()!\n"); +- } else ++ ret = -EOPNOTSUPP; ++ } ++ } else { + dev_dbg(&client->dev, "alert with no driver\n"); ++ ret = -ENODEV; ++ } ++ device_unlock(dev); ++ ++ return ret; ++} ++ ++/* Same as above, but call back all drivers with alert handler */ ++ ++static int smbus_do_alert_force(struct device *dev, void *addrp) ++{ ++ struct i2c_client *client = i2c_verify_client(dev); ++ struct alert_data *data = addrp; ++ struct i2c_driver *driver; ++ ++ if (!client || (client->flags & I2C_CLIENT_TEN)) ++ return 0; ++ ++ /* ++ * Drivers should either disable alerts, or provide at least ++ * a minimal handler. Lock so the driver won't change. ++ */ ++ device_lock(dev); ++ if (client->dev.driver) { ++ driver = to_i2c_driver(client->dev.driver); ++ if (driver->alert) ++ driver->alert(client, data->type, data->data); ++ } + device_unlock(dev); + +- /* Stop iterating after we find the device */ +- return -EBUSY; ++ return 0; + } + + /* +@@ -67,6 +99,7 @@ static irqreturn_t smbus_alert(int irq, void *d) + { + struct i2c_smbus_alert *alert = d; + struct i2c_client *ara; ++ unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */ + + ara = alert->ara; + +@@ -94,8 +127,25 @@ static irqreturn_t smbus_alert(int irq, void *d) + data.addr, data.data); + + /* Notify driver for the device which issued the alert */ +- device_for_each_child(&ara->adapter->dev, &data, +- smbus_do_alert); ++ status = device_for_each_child(&ara->adapter->dev, &data, ++ smbus_do_alert); ++ /* ++ * If we read the same address more than once, and the alert ++ * was not handled by a driver, it won't do any good to repeat ++ * the loop because it will never terminate. Try again, this ++ * time calling the alert handlers of all devices connected to ++ * the bus, and abort the loop afterwards. If this helps, we ++ * are all set. If it doesn't, there is nothing else we can do, ++ * so we might as well abort the loop. ++ * Note: This assumes that a driver with alert handler handles ++ * the alert properly and clears it if necessary. ++ */ ++ if (data.addr == prev_addr && status != -EBUSY) { ++ device_for_each_child(&ara->adapter->dev, &data, ++ smbus_do_alert_force); ++ break; ++ } ++ prev_addr = data.addr; + } + + return IRQ_HANDLED; +diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c +index 9d8f2c4060431..b35903a06902f 100644 +--- a/drivers/irqchip/irq-loongarch-cpu.c ++++ b/drivers/irqchip/irq-loongarch-cpu.c +@@ -18,11 +18,13 @@ struct fwnode_handle *cpuintc_handle; + + static u32 lpic_gsi_to_irq(u32 gsi) + { ++ int irq = 0; ++ + /* Only pch irqdomain transferring is required for LoongArch. */ + if (gsi >= GSI_MIN_PCH_IRQ && gsi <= GSI_MAX_PCH_IRQ) +- return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); ++ irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + +- return 0; ++ return (irq > 0) ? irq : 0; + } + + static struct fwnode_handle *lpic_get_gsi_domain_id(u32 gsi) +diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c +index 58881d3139792..244a8d489cac6 100644 +--- a/drivers/irqchip/irq-mbigen.c ++++ b/drivers/irqchip/irq-mbigen.c +@@ -64,6 +64,20 @@ struct mbigen_device { + void __iomem *base; + }; + ++static inline unsigned int get_mbigen_node_offset(unsigned int nid) ++{ ++ unsigned int offset = nid * MBIGEN_NODE_OFFSET; ++ ++ /* ++ * To avoid touched clear register in unexpected way, we need to directly ++ * skip clear register when access to more than 10 mbigen nodes. ++ */ ++ if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET)) ++ offset += MBIGEN_NODE_OFFSET; ++ ++ return offset; ++} ++ + static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) + { + unsigned int nid, pin; +@@ -72,8 +86,7 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) + nid = hwirq / IRQS_PER_MBIGEN_NODE + 1; + pin = hwirq % IRQS_PER_MBIGEN_NODE; + +- return pin * 4 + nid * MBIGEN_NODE_OFFSET +- + REG_MBIGEN_VEC_OFFSET; ++ return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET; + } + + static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, +@@ -88,8 +101,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, + *mask = 1 << (irq_ofst % 32); + ofst = irq_ofst / 32 * 4; + +- *addr = ofst + nid * MBIGEN_NODE_OFFSET +- + REG_MBIGEN_TYPE_OFFSET; ++ *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET; + } + + static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq, +diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c +index f88df39f41291..471e04eaf3230 100644 +--- a/drivers/irqchip/irq-meson-gpio.c ++++ b/drivers/irqchip/irq-meson-gpio.c +@@ -173,7 +173,7 @@ struct meson_gpio_irq_controller { + void __iomem *base; + u32 channel_irqs[MAX_NUM_CHANNEL]; + DECLARE_BITMAP(channel_map, MAX_NUM_CHANNEL); +- spinlock_t lock; ++ raw_spinlock_t lock; + }; + + static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl, +@@ -182,14 +182,14 @@ static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl, + unsigned long flags; + u32 tmp; + +- spin_lock_irqsave(&ctl->lock, flags); ++ raw_spin_lock_irqsave(&ctl->lock, flags); + + tmp = readl_relaxed(ctl->base + reg); + tmp &= ~mask; + tmp |= val; + writel_relaxed(tmp, ctl->base + reg); + +- spin_unlock_irqrestore(&ctl->lock, flags); ++ raw_spin_unlock_irqrestore(&ctl->lock, flags); + } + + static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl) +@@ -239,12 +239,12 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, + unsigned long flags; + unsigned int idx; + +- spin_lock_irqsave(&ctl->lock, flags); ++ raw_spin_lock_irqsave(&ctl->lock, flags); + + /* Find a free channel */ + idx = find_first_zero_bit(ctl->channel_map, ctl->params->nr_channels); + if (idx >= ctl->params->nr_channels) { +- spin_unlock_irqrestore(&ctl->lock, flags); ++ raw_spin_unlock_irqrestore(&ctl->lock, flags); + pr_err("No channel available\n"); + return -ENOSPC; + } +@@ -252,7 +252,7 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, + /* Mark the channel as used */ + set_bit(idx, ctl->channel_map); + +- spin_unlock_irqrestore(&ctl->lock, flags); ++ raw_spin_unlock_irqrestore(&ctl->lock, flags); + + /* + * Setup the mux of the channel to route the signal of the pad +@@ -562,7 +562,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node * + if (!ctl) + return -ENOMEM; + +- spin_lock_init(&ctl->lock); ++ raw_spin_lock_init(&ctl->lock); + + ctl->base = of_iomap(node, 0); + if (!ctl->base) { +diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c +index 238d3d3449496..7e08714d507f4 100644 +--- a/drivers/irqchip/irq-xilinx-intc.c ++++ b/drivers/irqchip/irq-xilinx-intc.c +@@ -189,7 +189,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc, + irqc->intr_mask = 0; + } + +- if (irqc->intr_mask >> irqc->nr_irq) ++ if ((u64)irqc->intr_mask >> irqc->nr_irq) + pr_warn("irq-xilinx: mismatch in kind-of-intr param\n"); + + pr_info("irq-xilinx: %pOF: num_irq=%d, edge=0x%x\n", +diff --git a/drivers/md/md.c b/drivers/md/md.c +index b5dea664f946d..35b003b83ef1b 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -456,7 +456,6 @@ void mddev_suspend(struct mddev *mddev) + clear_bit_unlock(MD_ALLOW_SB_UPDATE, &mddev->flags); + wait_event(mddev->sb_wait, !test_bit(MD_UPDATING_SB, &mddev->flags)); + +- del_timer_sync(&mddev->safemode_timer); + /* restrict memory reclaim I/O during raid array is suspend */ + mddev->noio_flag = memalloc_noio_save(); + } +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 1507540a9cb4e..2c7f11e576673 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -6326,7 +6326,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk + safepos = conf->reshape_safe; + sector_div(safepos, data_disks); + if (mddev->reshape_backwards) { +- BUG_ON(writepos < reshape_sectors); ++ if (WARN_ON(writepos < reshape_sectors)) ++ return MaxSector; ++ + writepos -= reshape_sectors; + readpos += reshape_sectors; + safepos += reshape_sectors; +@@ -6344,14 +6346,18 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk + * to set 'stripe_addr' which is where we will write to. + */ + if (mddev->reshape_backwards) { +- BUG_ON(conf->reshape_progress == 0); ++ if (WARN_ON(conf->reshape_progress == 0)) ++ return MaxSector; ++ + stripe_addr = writepos; +- BUG_ON((mddev->dev_sectors & +- ~((sector_t)reshape_sectors - 1)) +- - reshape_sectors - stripe_addr +- != sector_nr); ++ if (WARN_ON((mddev->dev_sectors & ++ ~((sector_t)reshape_sectors - 1)) - ++ reshape_sectors - stripe_addr != sector_nr)) ++ return MaxSector; + } else { +- BUG_ON(writepos != sector_nr + reshape_sectors); ++ if (WARN_ON(writepos != sector_nr + reshape_sectors)) ++ return MaxSector; ++ + stripe_addr = sector_nr; + } + +diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c +index 133d77d1ea0c3..4f438eaa7d385 100644 +--- a/drivers/media/platform/amphion/vdec.c ++++ b/drivers/media/platform/amphion/vdec.c +@@ -195,7 +195,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) + struct vdec_t *vdec = inst->priv; + int ret = 0; + +- vpu_inst_lock(inst); + switch (ctrl->id) { + case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE: + vdec->params.display_delay_enable = ctrl->val; +@@ -207,7 +206,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) + ret = -EINVAL; + break; + } +- vpu_inst_unlock(inst); + + return ret; + } +diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c +index 4eb57d793a9c0..16ed4d21519cd 100644 +--- a/drivers/media/platform/amphion/venc.c ++++ b/drivers/media/platform/amphion/venc.c +@@ -518,7 +518,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) + struct venc_t *venc = inst->priv; + int ret = 0; + +- vpu_inst_lock(inst); + switch (ctrl->id) { + case V4L2_CID_MPEG_VIDEO_H264_PROFILE: + venc->params.profile = ctrl->val; +@@ -579,7 +578,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) + ret = -EINVAL; + break; + } +- vpu_inst_unlock(inst); + + return ret; + } +diff --git a/drivers/media/tuners/xc2028.c b/drivers/media/tuners/xc2028.c +index 5a967edceca93..352b8a3679b72 100644 +--- a/drivers/media/tuners/xc2028.c ++++ b/drivers/media/tuners/xc2028.c +@@ -1361,9 +1361,16 @@ static void load_firmware_cb(const struct firmware *fw, + void *context) + { + struct dvb_frontend *fe = context; +- struct xc2028_data *priv = fe->tuner_priv; ++ struct xc2028_data *priv; + int rc; + ++ if (!fe) { ++ pr_warn("xc2028: No frontend in %s\n", __func__); ++ return; ++ } ++ ++ priv = fe->tuner_priv; ++ + tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error"); + if (!fw) { + tuner_err("Could not load firmware %s.\n", priv->fname); +diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c +index 5eef560bc8cd8..91c350b254126 100644 +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -214,13 +214,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, + * Compute a bandwidth estimation by multiplying the frame + * size by the number of video frames per second, divide the + * result by the number of USB frames (or micro-frames for +- * high-speed devices) per second and add the UVC header size +- * (assumed to be 12 bytes long). ++ * high- and super-speed devices) per second and add the UVC ++ * header size (assumed to be 12 bytes long). + */ + bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; + bandwidth *= 10000000 / interval + 1; + bandwidth /= 1000; +- if (stream->dev->udev->speed == USB_SPEED_HIGH) ++ if (stream->dev->udev->speed >= USB_SPEED_HIGH) + bandwidth /= 8; + bandwidth += 12; + +@@ -478,6 +478,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, + ktime_t time; + u16 host_sof; + u16 dev_sof; ++ u32 dev_stc; + + switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { + case UVC_STREAM_PTS | UVC_STREAM_SCR: +@@ -526,6 +527,34 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, + if (dev_sof == stream->clock.last_sof) + return; + ++ dev_stc = get_unaligned_le32(&data[header_size - 6]); ++ ++ /* ++ * STC (Source Time Clock) is the clock used by the camera. The UVC 1.5 ++ * standard states that it "must be captured when the first video data ++ * of a video frame is put on the USB bus". This is generally understood ++ * as requiring devices to clear the payload header's SCR bit before ++ * the first packet containing video data. ++ * ++ * Most vendors follow that interpretation, but some (namely SunplusIT ++ * on some devices) always set the `UVC_STREAM_SCR` bit, fill the SCR ++ * field with 0's,and expect that the driver only processes the SCR if ++ * there is data in the packet. ++ * ++ * Ignore all the hardware timestamp information if we haven't received ++ * any data for this frame yet, the packet contains no data, and both ++ * STC and SOF are zero. This heuristics should be safe on compliant ++ * devices. This should be safe with compliant devices, as in the very ++ * unlikely case where a UVC 1.1 device would send timing information ++ * only before the first packet containing data, and both STC and SOF ++ * happen to be zero for a particular frame, we would only miss one ++ * clock sample from many and the clock recovery algorithm wouldn't ++ * suffer from this condition. ++ */ ++ if (buf && buf->bytesused == 0 && len == header_size && ++ dev_stc == 0 && dev_sof == 0) ++ return; ++ + stream->clock.last_sof = dev_sof; + + host_sof = usb_get_current_frame_number(stream->dev->udev); +@@ -575,7 +604,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, + spin_lock_irqsave(&stream->clock.lock, flags); + + sample = &stream->clock.samples[stream->clock.head]; +- sample->dev_stc = get_unaligned_le32(&data[header_size - 6]); ++ sample->dev_stc = dev_stc; + sample->dev_sof = dev_sof; + sample->host_sof = host_sof; + sample->host_time = time; +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c +index bfe4caa0c99d4..4cb79a4f24612 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c +@@ -485,6 +485,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) + clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags); + } + ++ tx_ring->obj_num_shift_to_u8 = BITS_PER_TYPE(tx_ring->obj_num) - ++ ilog2(tx_ring->obj_num); + tx_ring->obj_size = tx_obj_size; + + rem = priv->rx_obj_num; +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c +index e5bd57b65aafe..5b0c7890d4b44 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c +@@ -2,7 +2,7 @@ + // + // mcp251xfd - Microchip MCP251xFD Family CAN controller driver + // +-// Copyright (c) 2019, 2020, 2021 Pengutronix, ++// Copyright (c) 2019, 2020, 2021, 2023 Pengutronix, + // Marc Kleine-Budde + // + // Based on: +@@ -16,6 +16,11 @@ + + #include "mcp251xfd.h" + ++static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta) ++{ ++ return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF); ++} ++ + static inline int + mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv, + u8 *tef_tail) +@@ -55,56 +60,39 @@ static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv) + return 0; + } + +-static int +-mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) +-{ +- const struct mcp251xfd_tx_ring *tx_ring = priv->tx; +- u32 tef_sta; +- int err; +- +- err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta); +- if (err) +- return err; +- +- if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) { +- netdev_err(priv->ndev, +- "Transmit Event FIFO buffer overflow.\n"); +- return -ENOBUFS; +- } +- +- netdev_info(priv->ndev, +- "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n", +- tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? +- "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? +- "not empty" : "empty", +- seq, priv->tef->tail, priv->tef->head, tx_ring->head); +- +- /* The Sequence Number in the TEF doesn't match our tef_tail. */ +- return -EAGAIN; +-} +- + static int + mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, + const struct mcp251xfd_hw_tef_obj *hw_tef_obj, + unsigned int *frame_len_ptr) + { + struct net_device_stats *stats = &priv->ndev->stats; ++ u32 seq, tef_tail_masked, tef_tail; + struct sk_buff *skb; +- u32 seq, seq_masked, tef_tail_masked, tef_tail; + +- seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, ++ /* Use the MCP2517FD mask on the MCP2518FD, too. We only ++ * compare 7 bits, this is enough to detect old TEF objects. ++ */ ++ seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK, + hw_tef_obj->flags); +- +- /* Use the MCP2517FD mask on the MCP2518FD, too. We only +- * compare 7 bits, this should be enough to detect +- * net-yet-completed, i.e. old TEF objects. +- */ +- seq_masked = seq & +- field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); + tef_tail_masked = priv->tef->tail & + field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); +- if (seq_masked != tef_tail_masked) +- return mcp251xfd_handle_tefif_recover(priv, seq); ++ ++ /* According to mcp2518fd erratum DS80000789E 6. the FIFOCI ++ * bits of a FIFOSTA register, here the TX FIFO tail index ++ * might be corrupted and we might process past the TEF FIFO's ++ * head into old CAN frames. ++ * ++ * Compare the sequence number of the currently processed CAN ++ * frame with the expected sequence number. Abort with ++ * -EBADMSG if an old CAN frame is detected. ++ */ ++ if (seq != tef_tail_masked) { ++ netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__, ++ seq, tef_tail_masked); ++ stats->tx_fifo_errors++; ++ ++ return -EBADMSG; ++ } + + tef_tail = mcp251xfd_get_tef_tail(priv); + skb = priv->can.echo_skb[tef_tail]; +@@ -120,28 +108,44 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, + return 0; + } + +-static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv) ++static int ++mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p) + { + const struct mcp251xfd_tx_ring *tx_ring = priv->tx; +- unsigned int new_head; +- u8 chip_tx_tail; ++ const u8 shift = tx_ring->obj_num_shift_to_u8; ++ u8 chip_tx_tail, tail, len; ++ u32 fifo_sta; + int err; + +- err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); ++ err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr), ++ &fifo_sta); + if (err) + return err; + +- /* chip_tx_tail, is the next TX-Object send by the HW. +- * The new TEF head must be >= the old head, ... ++ if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) { ++ *len_p = tx_ring->obj_num; ++ return 0; ++ } ++ ++ chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); ++ ++ err = mcp251xfd_check_tef_tail(priv); ++ if (err) ++ return err; ++ tail = mcp251xfd_get_tef_tail(priv); ++ ++ /* First shift to full u8. The subtraction works on signed ++ * values, that keeps the difference steady around the u8 ++ * overflow. The right shift acts on len, which is an u8. + */ +- new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail; +- if (new_head <= priv->tef->head) +- new_head += tx_ring->obj_num; ++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail)); ++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail)); ++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len)); + +- /* ... but it cannot exceed the TX head. */ +- priv->tef->head = min(new_head, tx_ring->head); ++ len = (chip_tx_tail << shift) - (tail << shift); ++ *len_p = len >> shift; + +- return mcp251xfd_check_tef_tail(priv); ++ return 0; + } + + static inline int +@@ -182,13 +186,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) + u8 tef_tail, len, l; + int err, i; + +- err = mcp251xfd_tef_ring_update(priv); ++ err = mcp251xfd_get_tef_len(priv, &len); + if (err) + return err; + + tef_tail = mcp251xfd_get_tef_tail(priv); +- len = mcp251xfd_get_tef_len(priv); +- l = mcp251xfd_get_tef_linear_len(priv); ++ l = mcp251xfd_get_tef_linear_len(priv, len); + err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); + if (err) + return err; +@@ -203,12 +206,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) + unsigned int frame_len = 0; + + err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len); +- /* -EAGAIN means the Sequence Number in the TEF +- * doesn't match our tef_tail. This can happen if we +- * read the TEF objects too early. Leave loop let the +- * interrupt handler call us again. ++ /* -EBADMSG means we're affected by mcp2518fd erratum ++ * DS80000789E 6., i.e. the Sequence Number in the TEF ++ * doesn't match our tef_tail. Don't process any ++ * further and mark processed frames as good. + */ +- if (err == -EAGAIN) ++ if (err == -EBADMSG) + goto out_netif_wake_queue; + if (err) + return err; +@@ -223,6 +226,8 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) + struct mcp251xfd_tx_ring *tx_ring = priv->tx; + int offset; + ++ ring->head += len; ++ + /* Increment the TEF FIFO tail pointer 'len' times in + * a single SPI message. + * +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h +index b35bfebd23f29..4628bf847bc9b 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h +@@ -524,6 +524,7 @@ struct mcp251xfd_tef_ring { + + /* u8 obj_num equals tx_ring->obj_num */ + /* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */ ++ /* u8 obj_num_shift_to_u8 equals tx_ring->obj_num_shift_to_u8 */ + + union mcp251xfd_write_reg_buf irq_enable_buf; + struct spi_transfer irq_enable_xfer; +@@ -542,6 +543,7 @@ struct mcp251xfd_tx_ring { + u8 nr; + u8 fifo_nr; + u8 obj_num; ++ u8 obj_num_shift_to_u8; + u8 obj_size; + + struct mcp251xfd_tx_obj obj[MCP251XFD_TX_OBJ_NUM_MAX]; +@@ -861,17 +863,8 @@ static inline u8 mcp251xfd_get_tef_tail(const struct mcp251xfd_priv *priv) + return priv->tef->tail & (priv->tx->obj_num - 1); + } + +-static inline u8 mcp251xfd_get_tef_len(const struct mcp251xfd_priv *priv) ++static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv, u8 len) + { +- return priv->tef->head - priv->tef->tail; +-} +- +-static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv) +-{ +- u8 len; +- +- len = mcp251xfd_get_tef_len(priv); +- + return min_t(u8, len, priv->tx->obj_num - mcp251xfd_get_tef_tail(priv)); + } + +diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c +index cd1f240c90f39..257df16768750 100644 +--- a/drivers/net/dsa/bcm_sf2.c ++++ b/drivers/net/dsa/bcm_sf2.c +@@ -678,8 +678,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) + of_remove_property(child, prop); + + phydev = of_phy_find_device(child); +- if (phydev) ++ if (phydev) { + phy_device_remove(phydev); ++ phy_device_free(phydev); ++ } + } + + err = mdiobus_register(priv->slave_mii_bus); +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +index 1248792d7fd4d..0715ea5bf13ed 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +@@ -42,19 +42,15 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + struct bcmgenet_priv *priv = netdev_priv(dev); + struct device *kdev = &priv->pdev->dev; + +- if (dev->phydev) { ++ if (dev->phydev) + phy_ethtool_get_wol(dev->phydev, wol); +- if (wol->supported) +- return; +- } + +- if (!device_can_wakeup(kdev)) { +- wol->supported = 0; +- wol->wolopts = 0; ++ /* MAC is not wake-up capable, return what the PHY does */ ++ if (!device_can_wakeup(kdev)) + return; +- } + +- wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; ++ /* Overlay MAC capabilities with that of the PHY queried before */ ++ wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; + wol->wolopts = priv->wolopts; + memset(wol->sopass, 0, sizeof(wol->sopass)); + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index e32f6724f5681..2e4f3e1782a25 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -775,6 +775,9 @@ void fec_ptp_stop(struct platform_device *pdev) + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + ++ if (fep->pps_enable) ++ fec_ptp_enable_pps(fep, 0); ++ + cancel_delayed_work_sync(&fep->time_keep); + hrtimer_cancel(&fep->perout_timer); + if (fep->ptp_clock) +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 600a2f5370875..b168a37a5dfff 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -557,6 +557,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + if (test_bit(ICE_PREPARED_FOR_RESET, pf->state)) + return; + ++ synchronize_irq(pf->oicr_irq.virq); ++ + ice_unplug_aux_dev(pf); + + /* Notify VFs of impending reset */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +index 8d9743a5e42c7..79ec6fcc9e259 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +@@ -2374,6 +2374,9 @@ static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cq + if (likely(wi->consumed_strides < rq->mpwqe.num_strides)) + return; + ++ if (unlikely(!cstrides)) ++ return; ++ + wq = &rq->mpwqe.wq; + wqe = mlx5_wq_ll_get_wqe(wq, wqe_id); + mlx5_wq_ll_pop(wq, cqe->wqe_id, &wqe->next.next_wqe_index); +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +index d5d2a4c776c1c..ded1bbda5266f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +@@ -21,6 +21,7 @@ + #define RGMII_IO_MACRO_CONFIG2 0x1C + #define RGMII_IO_MACRO_DEBUG1 0x20 + #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 ++#define EMAC_WRAPPER_SGMII_PHY_CNTRL1 0xf4 + + /* RGMII_IO_MACRO_CONFIG fields */ + #define RGMII_CONFIG_FUNC_CLK_EN BIT(30) +@@ -79,6 +80,9 @@ + #define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14) + #define ETHQOS_MAC_CTRL_PORT_SEL BIT(15) + ++/* EMAC_WRAPPER_SGMII_PHY_CNTRL1 bits */ ++#define SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN BIT(3) ++ + #define SGMII_10M_RX_CLK_DVDR 0x31 + + struct ethqos_emac_por { +@@ -95,6 +99,7 @@ struct ethqos_emac_driver_data { + bool has_integrated_pcs; + u32 dma_addr_width; + struct dwmac4_addrs dwmac4_addrs; ++ bool needs_sgmii_loopback; + }; + + struct qcom_ethqos { +@@ -113,6 +118,7 @@ struct qcom_ethqos { + unsigned int num_por; + bool rgmii_config_loopback_en; + bool has_emac_ge_3; ++ bool needs_sgmii_loopback; + }; + + static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) +@@ -187,8 +193,22 @@ ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed) + clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate); + } + ++static void ++qcom_ethqos_set_sgmii_loopback(struct qcom_ethqos *ethqos, bool enable) ++{ ++ if (!ethqos->needs_sgmii_loopback || ++ ethqos->phy_mode != PHY_INTERFACE_MODE_2500BASEX) ++ return; ++ ++ rgmii_updatel(ethqos, ++ SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN, ++ enable ? SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN : 0, ++ EMAC_WRAPPER_SGMII_PHY_CNTRL1); ++} ++ + static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) + { ++ qcom_ethqos_set_sgmii_loopback(ethqos, true); + rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN, + RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); + } +@@ -273,6 +293,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { + .has_emac_ge_3 = true, + .link_clk_name = "phyaux", + .has_integrated_pcs = true, ++ .needs_sgmii_loopback = true, + .dma_addr_width = 36, + .dwmac4_addrs = { + .dma_chan = 0x00008100, +@@ -646,6 +667,7 @@ static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mo + { + struct qcom_ethqos *ethqos = priv; + ++ qcom_ethqos_set_sgmii_loopback(ethqos, false); + ethqos->speed = speed; + ethqos_update_link_clk(ethqos, speed); + ethqos_configure(ethqos); +@@ -781,6 +803,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) + ethqos->num_por = data->num_por; + ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en; + ethqos->has_emac_ge_3 = data->has_emac_ge_3; ++ ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback; + + ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); + if (IS_ERR(ethqos->link_clk)) +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index befbca01bfe37..b1380cf1b13ab 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -201,6 +201,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + break; + default: + /* not ip - do not know what to do */ ++ kfree_skb(skbn); + goto skip; + } + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index c926952c956ef..33f4706af880d 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -181,6 +181,8 @@ enum ath12k_dev_flags { + ATH12K_FLAG_REGISTERED, + ATH12K_FLAG_QMI_FAIL, + ATH12K_FLAG_HTC_SUSPEND_COMPLETE, ++ ATH12K_FLAG_CE_IRQ_ENABLED, ++ ATH12K_FLAG_EXT_IRQ_ENABLED, + }; + + enum ath12k_monitor_flags { +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 2c17b1e7681a5..d9bc07844fb71 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2759,6 +2759,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev + peer = ath12k_peer_find(ab, vdev_id, peer_mac); + if (!peer) { + spin_unlock_bh(&ab->base_lock); ++ crypto_free_shash(tfm); + ath12k_warn(ab, "failed to find the peer to set up fragment info\n"); + return -ENOENT; + } +diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h +index 4cbf9b5c04b9c..c653ca1f59b22 100644 +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -10,17 +10,17 @@ + #include "core.h" + + struct ath12k_hif_ops { +- u32 (*read32)(struct ath12k_base *sc, u32 address); +- void (*write32)(struct ath12k_base *sc, u32 address, u32 data); +- void (*irq_enable)(struct ath12k_base *sc); +- void (*irq_disable)(struct ath12k_base *sc); +- int (*start)(struct ath12k_base *sc); +- void (*stop)(struct ath12k_base *sc); +- int (*power_up)(struct ath12k_base *sc); +- void (*power_down)(struct ath12k_base *sc); ++ u32 (*read32)(struct ath12k_base *ab, u32 address); ++ void (*write32)(struct ath12k_base *ab, u32 address, u32 data); ++ void (*irq_enable)(struct ath12k_base *ab); ++ void (*irq_disable)(struct ath12k_base *ab); ++ int (*start)(struct ath12k_base *ab); ++ void (*stop)(struct ath12k_base *ab); ++ int (*power_up)(struct ath12k_base *ab); ++ void (*power_down)(struct ath12k_base *ab); + int (*suspend)(struct ath12k_base *ab); + int (*resume)(struct ath12k_base *ab); +- int (*map_service_to_pipe)(struct ath12k_base *sc, u16 service_id, ++ int (*map_service_to_pipe)(struct ath12k_base *ab, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe); + int (*get_user_msi_vector)(struct ath12k_base *ab, char *user_name, + int *num_vectors, u32 *user_base_data, +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 58cd678555964..041a9602f0e15 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -373,6 +373,8 @@ static void ath12k_pci_ce_irqs_disable(struct ath12k_base *ab) + { + int i; + ++ clear_bit(ATH12K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); ++ + for (i = 0; i < ab->hw_params->ce_count; i++) { + if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) + continue; +@@ -406,6 +408,10 @@ static void ath12k_pci_ce_tasklet(struct tasklet_struct *t) + static irqreturn_t ath12k_pci_ce_interrupt_handler(int irq, void *arg) + { + struct ath12k_ce_pipe *ce_pipe = arg; ++ struct ath12k_base *ab = ce_pipe->ab; ++ ++ if (!test_bit(ATH12K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags)) ++ return IRQ_HANDLED; + + /* last interrupt received for this CE */ + ce_pipe->timestamp = jiffies; +@@ -424,12 +430,15 @@ static void ath12k_pci_ext_grp_disable(struct ath12k_ext_irq_grp *irq_grp) + disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); + } + +-static void __ath12k_pci_ext_irq_disable(struct ath12k_base *sc) ++static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab) + { + int i; + ++ if (!test_and_clear_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) ++ return; ++ + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { +- struct ath12k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i]; ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + ath12k_pci_ext_grp_disable(irq_grp); + +@@ -483,6 +492,10 @@ static int ath12k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget) + static irqreturn_t ath12k_pci_ext_interrupt_handler(int irq, void *arg) + { + struct ath12k_ext_irq_grp *irq_grp = arg; ++ struct ath12k_base *ab = irq_grp->ab; ++ ++ if (!test_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) ++ return IRQ_HANDLED; + + ath12k_dbg(irq_grp->ab, ATH12K_DBG_PCI, "ext irq:%d\n", irq); + +@@ -626,6 +639,8 @@ static void ath12k_pci_ce_irqs_enable(struct ath12k_base *ab) + { + int i; + ++ set_bit(ATH12K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); ++ + for (i = 0; i < ab->hw_params->ce_count; i++) { + if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) + continue; +@@ -956,6 +971,8 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab) + { + int i; + ++ set_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); ++ + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 796c2a00fea4a..0fc7aa78b2e5b 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -826,9 +826,9 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req, + struct nvme_command *cmnd) + { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); ++ struct bio_vec bv = rq_integrity_vec(req); + +- iod->meta_dma = dma_map_bvec(dev->dev, rq_integrity_vec(req), +- rq_dma_dir(req), 0); ++ iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0); + if (dma_mapping_error(dev->dev, iod->meta_dma)) + return BLK_STS_IOERR; + cmnd->rw.metadata = cpu_to_le64(iod->meta_dma); +@@ -969,7 +969,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req) + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); + + dma_unmap_page(dev->dev, iod->meta_dma, +- rq_integrity_vec(req)->bv_len, rq_dma_dir(req)); ++ rq_integrity_vec(req).bv_len, rq_dma_dir(req)); + } + + if (blk_rq_nr_phys_segments(req)) +diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c +index 306f886b52d20..4ff2aa4b484bc 100644 +--- a/drivers/platform/x86/intel/ifs/core.c ++++ b/drivers/platform/x86/intel/ifs/core.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* Copyright(c) 2022 Intel Corporation. */ + ++#include + #include + #include + #include +@@ -94,6 +95,8 @@ static int __init ifs_init(void) + for (i = 0; i < IFS_NUMTESTS; i++) { + if (!(msrval & BIT(ifs_devices[i].test_caps->integrity_cap_bit))) + continue; ++ ifs_devices[i].rw_data.generation = FIELD_GET(MSR_INTEGRITY_CAPS_SAF_GEN_MASK, ++ msrval); + ret = misc_register(&ifs_devices[i].misc); + if (ret) + goto err_exit; +diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h +index 93191855890f2..6bc63ab705175 100644 +--- a/drivers/platform/x86/intel/ifs/ifs.h ++++ b/drivers/platform/x86/intel/ifs/ifs.h +@@ -174,9 +174,17 @@ union ifs_chunks_auth_status { + union ifs_scan { + u64 data; + struct { +- u32 start :8; +- u32 stop :8; +- u32 rsvd :16; ++ union { ++ struct { ++ u8 start; ++ u8 stop; ++ u16 rsvd; ++ } gen0; ++ struct { ++ u16 start; ++ u16 stop; ++ } gen2; ++ }; + u32 delay :31; + u32 sigmce :1; + }; +@@ -186,9 +194,17 @@ union ifs_scan { + union ifs_status { + u64 data; + struct { +- u32 chunk_num :8; +- u32 chunk_stop_index :8; +- u32 rsvd1 :16; ++ union { ++ struct { ++ u8 chunk_num; ++ u8 chunk_stop_index; ++ u16 rsvd1; ++ } gen0; ++ struct { ++ u16 chunk_num; ++ u16 chunk_stop_index; ++ } gen2; ++ }; + u32 error_code :8; + u32 rsvd2 :22; + u32 control_error :1; +@@ -229,6 +245,7 @@ struct ifs_test_caps { + * @status: it holds simple status pass/fail/untested + * @scan_details: opaque scan status code from h/w + * @cur_batch: number indicating the currently loaded test file ++ * @generation: IFS test generation enumerated by hardware + */ + struct ifs_data { + int loaded_version; +@@ -238,6 +255,7 @@ struct ifs_data { + int status; + u64 scan_details; + u32 cur_batch; ++ u32 generation; + }; + + struct ifs_work { +diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c +index 43c864add778f..c7a5bf24bef35 100644 +--- a/drivers/platform/x86/intel/ifs/runtest.c ++++ b/drivers/platform/x86/intel/ifs/runtest.c +@@ -167,25 +167,35 @@ static int doscan(void *data) + */ + static void ifs_test_core(int cpu, struct device *dev) + { ++ union ifs_status status = {}; + union ifs_scan activate; +- union ifs_status status; + unsigned long timeout; + struct ifs_data *ifsd; ++ int to_start, to_stop; ++ int status_chunk; + u64 msrvals[2]; + int retries; + + ifsd = ifs_get_data(dev); + +- activate.rsvd = 0; ++ activate.gen0.rsvd = 0; + activate.delay = IFS_THREAD_WAIT; + activate.sigmce = 0; +- activate.start = 0; +- activate.stop = ifsd->valid_chunks - 1; ++ to_start = 0; ++ to_stop = ifsd->valid_chunks - 1; ++ ++ if (ifsd->generation) { ++ activate.gen2.start = to_start; ++ activate.gen2.stop = to_stop; ++ } else { ++ activate.gen0.start = to_start; ++ activate.gen0.stop = to_stop; ++ } + + timeout = jiffies + HZ / 2; + retries = MAX_IFS_RETRIES; + +- while (activate.start <= activate.stop) { ++ while (to_start <= to_stop) { + if (time_after(jiffies, timeout)) { + status.error_code = IFS_SW_TIMEOUT; + break; +@@ -196,13 +206,14 @@ static void ifs_test_core(int cpu, struct device *dev) + + status.data = msrvals[1]; + +- trace_ifs_status(cpu, activate, status); ++ trace_ifs_status(cpu, to_start, to_stop, status.data); + + /* Some cases can be retried, give up for others */ + if (!can_restart(status)) + break; + +- if (status.chunk_num == activate.start) { ++ status_chunk = ifsd->generation ? status.gen2.chunk_num : status.gen0.chunk_num; ++ if (status_chunk == to_start) { + /* Check for forward progress */ + if (--retries == 0) { + if (status.error_code == IFS_NO_ERROR) +@@ -211,7 +222,11 @@ static void ifs_test_core(int cpu, struct device *dev) + } + } else { + retries = MAX_IFS_RETRIES; +- activate.start = status.chunk_num; ++ if (ifsd->generation) ++ activate.gen2.start = status_chunk; ++ else ++ activate.gen0.start = status_chunk; ++ to_start = status_chunk; + } + } + +diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c +index b5903193e2f96..ac05942e4e6ac 100644 +--- a/drivers/power/supply/axp288_charger.c ++++ b/drivers/power/supply/axp288_charger.c +@@ -178,18 +178,18 @@ static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv) + u8 reg_val; + int ret; + +- if (cv <= CV_4100MV) { +- reg_val = CHRG_CCCV_CV_4100MV; +- cv = CV_4100MV; +- } else if (cv <= CV_4150MV) { +- reg_val = CHRG_CCCV_CV_4150MV; +- cv = CV_4150MV; +- } else if (cv <= CV_4200MV) { ++ if (cv >= CV_4350MV) { ++ reg_val = CHRG_CCCV_CV_4350MV; ++ cv = CV_4350MV; ++ } else if (cv >= CV_4200MV) { + reg_val = CHRG_CCCV_CV_4200MV; + cv = CV_4200MV; ++ } else if (cv >= CV_4150MV) { ++ reg_val = CHRG_CCCV_CV_4150MV; ++ cv = CV_4150MV; + } else { +- reg_val = CHRG_CCCV_CV_4350MV; +- cv = CV_4350MV; ++ reg_val = CHRG_CCCV_CV_4100MV; ++ cv = CV_4100MV; + } + + reg_val = reg_val << CHRG_CCCV_CV_BIT_POS; +@@ -337,8 +337,8 @@ static int axp288_charger_usb_set_property(struct power_supply *psy, + } + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: +- scaled_val = min(val->intval, info->max_cv); +- scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); ++ scaled_val = DIV_ROUND_CLOSEST(val->intval, 1000); ++ scaled_val = min(scaled_val, info->max_cv); + ret = axp288_charger_set_cv(info, scaled_val); + if (ret < 0) { + dev_warn(&info->pdev->dev, "set charge voltage failed\n"); +diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c +index ec163d1bcd189..44c6301f5f174 100644 +--- a/drivers/power/supply/qcom_battmgr.c ++++ b/drivers/power/supply/qcom_battmgr.c +@@ -486,7 +486,7 @@ static int qcom_battmgr_bat_get_property(struct power_supply *psy, + int ret; + + if (!battmgr->service_up) +- return -ENODEV; ++ return -EAGAIN; + + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); +@@ -683,7 +683,7 @@ static int qcom_battmgr_ac_get_property(struct power_supply *psy, + int ret; + + if (!battmgr->service_up) +- return -ENODEV; ++ return -EAGAIN; + + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); + if (ret) +@@ -748,7 +748,7 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy, + int ret; + + if (!battmgr->service_up) +- return -ENODEV; ++ return -EAGAIN; + + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); +@@ -867,7 +867,7 @@ static int qcom_battmgr_wls_get_property(struct power_supply *psy, + int ret; + + if (!battmgr->service_up) +- return -ENODEV; ++ return -EAGAIN; + + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) + ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); +diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c +index f9e164be7568f..944e75beb160c 100644 +--- a/drivers/s390/char/sclp_sd.c ++++ b/drivers/s390/char/sclp_sd.c +@@ -320,8 +320,14 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di) + &esize); + if (rc) { + /* Cancel running request if interrupted */ +- if (rc == -ERESTARTSYS) +- sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL); ++ if (rc == -ERESTARTSYS) { ++ if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) { ++ pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n", ++ (size_t)dsize * PAGE_SIZE); ++ data = NULL; ++ asce = 0; ++ } ++ } + vfree(data); + goto out; + } +diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c +index 80d71041086e1..7f32619234696 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_os.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_os.c +@@ -3447,6 +3447,17 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, + scmd->sc_data_direction); + priv->meta_sg_valid = 1; /* To unmap meta sg DMA */ + } else { ++ /* ++ * Some firmware versions byte-swap the REPORT ZONES command ++ * reply from ATA-ZAC devices by directly accessing in the host ++ * buffer. This does not respect the default command DMA ++ * direction and causes IOMMU page faults on some architectures ++ * with an IOMMU enforcing write mappings (e.g. AMD hosts). ++ * Avoid such issue by making the REPORT ZONES buffer mapping ++ * bi-directional. ++ */ ++ if (scmd->cmnd[0] == ZBC_IN && scmd->cmnd[1] == ZI_REPORT_ZONES) ++ scmd->sc_data_direction = DMA_BIDIRECTIONAL; + sg_scmd = scsi_sglist(scmd); + sges_left = scsi_dma_map(scmd); + } +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c +index 04116e02ffe8c..8acf586dc8b2e 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c +@@ -2671,6 +2671,22 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) + _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1); + } + ++static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd) ++{ ++ /* ++ * Some firmware versions byte-swap the REPORT ZONES command reply from ++ * ATA-ZAC devices by directly accessing in the host buffer. This does ++ * not respect the default command DMA direction and causes IOMMU page ++ * faults on some architectures with an IOMMU enforcing write mappings ++ * (e.g. AMD hosts). Avoid such issue by making the report zones buffer ++ * mapping bi-directional. ++ */ ++ if (cmd->cmnd[0] == ZBC_IN && cmd->cmnd[1] == ZI_REPORT_ZONES) ++ cmd->sc_data_direction = DMA_BIDIRECTIONAL; ++ ++ return scsi_dma_map(cmd); ++} ++ + /** + * _base_build_sg_scmd - main sg creation routine + * pcie_device is unused here! +@@ -2717,7 +2733,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + + sg_scmd = scsi_sglist(scmd); +- sges_left = scsi_dma_map(scmd); ++ sges_left = _base_scsi_dma_map(scmd); + if (sges_left < 0) + return -ENOMEM; + +@@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, + } + + sg_scmd = scsi_sglist(scmd); +- sges_left = scsi_dma_map(scmd); ++ sges_left = _base_scsi_dma_map(scmd); + if (sges_left < 0) + return -ENOMEM; + +diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c +index 079035db7dd85..3c0f7dc9614d1 100644 +--- a/drivers/spi/spi-fsl-lpspi.c ++++ b/drivers/spi/spi-fsl-lpspi.c +@@ -296,7 +296,7 @@ static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) + static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) + { + struct lpspi_config config = fsl_lpspi->config; +- unsigned int perclk_rate, scldiv; ++ unsigned int perclk_rate, scldiv, div; + u8 prescale; + + perclk_rate = clk_get_rate(fsl_lpspi->clk_per); +@@ -313,8 +313,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) + return -EINVAL; + } + ++ div = DIV_ROUND_UP(perclk_rate, config.speed_hz); ++ + for (prescale = 0; prescale < 8; prescale++) { +- scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2; ++ scldiv = div / (1 << prescale) - 2; + if (scldiv < 256) { + fsl_lpspi->config.prescale = prescale; + break; +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index 1a8dd10012448..b97206d47ec6d 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -704,6 +704,7 @@ static const struct file_operations spidev_fops = { + static struct class *spidev_class; + + static const struct spi_device_id spidev_spi_ids[] = { ++ { .name = "bh2228fv" }, + { .name = "dh2228fv" }, + { .name = "ltc2488" }, + { .name = "sx1301" }, +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index 2eceef54e0b30..ed8798fdf522a 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -876,6 +876,14 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, + new_flags = (__force upf_t)new_info->flags; + old_custom_divisor = uport->custom_divisor; + ++ if (!(uport->flags & UPF_FIXED_PORT)) { ++ unsigned int uartclk = new_info->baud_base * 16; ++ /* check needs to be done here before other settings made */ ++ if (uartclk == 0) { ++ retval = -EINVAL; ++ goto exit; ++ } ++ } + if (!capable(CAP_SYS_ADMIN)) { + retval = -EPERM; + if (change_irq || change_port || +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 808979a093505..94edac17b95f8 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -3971,11 +3971,16 @@ static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) + min_sleep_time_us = + MIN_DELAY_BEFORE_DME_CMDS_US - delta; + else +- return; /* no more delay required */ ++ min_sleep_time_us = 0; /* no more delay required */ + } + +- /* allow sleep for extra 50us if needed */ +- usleep_range(min_sleep_time_us, min_sleep_time_us + 50); ++ if (min_sleep_time_us > 0) { ++ /* allow sleep for extra 50us if needed */ ++ usleep_range(min_sleep_time_us, min_sleep_time_us + 50); ++ } ++ ++ /* update the last_dme_cmd_tstamp */ ++ hba->last_dme_cmd_tstamp = ktime_get(); + } + + /** +@@ -10157,9 +10162,6 @@ int ufshcd_system_restore(struct device *dev) + */ + ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H); + +- /* Resuming from hibernate, assume that link was OFF */ +- ufshcd_set_link_off(hba); +- + return 0; + + } +diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c +index 0e38bb145e8f5..6908fdd4a83f3 100644 +--- a/drivers/usb/gadget/function/f_midi2.c ++++ b/drivers/usb/gadget/function/f_midi2.c +@@ -642,12 +642,21 @@ static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data) + if (format) + return; // invalid + blk = (*data >> 8) & 0xff; +- if (blk >= ep->num_blks) +- return; +- if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) +- reply_ump_stream_fb_info(ep, blk); +- if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) +- reply_ump_stream_fb_name(ep, blk); ++ if (blk == 0xff) { ++ /* inquiry for all blocks */ ++ for (blk = 0; blk < ep->num_blks; blk++) { ++ if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) ++ reply_ump_stream_fb_info(ep, blk); ++ if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) ++ reply_ump_stream_fb_name(ep, blk); ++ } ++ } else if (blk < ep->num_blks) { ++ /* only the specified block */ ++ if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) ++ reply_ump_stream_fb_info(ep, blk); ++ if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) ++ reply_ump_stream_fb_name(ep, blk); ++ } + return; + } + } +diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c +index ec1dceb087293..0be0966973c7f 100644 +--- a/drivers/usb/gadget/function/u_audio.c ++++ b/drivers/usb/gadget/function/u_audio.c +@@ -592,16 +592,25 @@ int u_audio_start_capture(struct g_audio *audio_dev) + struct usb_ep *ep, *ep_fback; + struct uac_rtd_params *prm; + struct uac_params *params = &audio_dev->params; +- int req_len, i; ++ int req_len, i, ret; + + prm = &uac->c_prm; + dev_dbg(dev, "start capture with rate %d\n", prm->srate); + ep = audio_dev->out_ep; +- config_ep_by_speed(gadget, &audio_dev->func, ep); ++ ret = config_ep_by_speed(gadget, &audio_dev->func, ep); ++ if (ret < 0) { ++ dev_err(dev, "config_ep_by_speed for out_ep failed (%d)\n", ret); ++ return ret; ++ } ++ + req_len = ep->maxpacket; + + prm->ep_enabled = true; +- usb_ep_enable(ep); ++ ret = usb_ep_enable(ep); ++ if (ret < 0) { ++ dev_err(dev, "usb_ep_enable failed for out_ep (%d)\n", ret); ++ return ret; ++ } + + for (i = 0; i < params->req_number; i++) { + if (!prm->reqs[i]) { +@@ -629,9 +638,18 @@ int u_audio_start_capture(struct g_audio *audio_dev) + return 0; + + /* Setup feedback endpoint */ +- config_ep_by_speed(gadget, &audio_dev->func, ep_fback); ++ ret = config_ep_by_speed(gadget, &audio_dev->func, ep_fback); ++ if (ret < 0) { ++ dev_err(dev, "config_ep_by_speed in_ep_fback failed (%d)\n", ret); ++ return ret; // TODO: Clean up out_ep ++ } ++ + prm->fb_ep_enabled = true; +- usb_ep_enable(ep_fback); ++ ret = usb_ep_enable(ep_fback); ++ if (ret < 0) { ++ dev_err(dev, "usb_ep_enable failed for in_ep_fback (%d)\n", ret); ++ return ret; // TODO: Clean up out_ep ++ } + req_len = ep_fback->maxpacket; + + req_fback = usb_ep_alloc_request(ep_fback, GFP_ATOMIC); +@@ -687,13 +705,17 @@ int u_audio_start_playback(struct g_audio *audio_dev) + struct uac_params *params = &audio_dev->params; + unsigned int factor; + const struct usb_endpoint_descriptor *ep_desc; +- int req_len, i; ++ int req_len, i, ret; + unsigned int p_pktsize; + + prm = &uac->p_prm; + dev_dbg(dev, "start playback with rate %d\n", prm->srate); + ep = audio_dev->in_ep; +- config_ep_by_speed(gadget, &audio_dev->func, ep); ++ ret = config_ep_by_speed(gadget, &audio_dev->func, ep); ++ if (ret < 0) { ++ dev_err(dev, "config_ep_by_speed for in_ep failed (%d)\n", ret); ++ return ret; ++ } + + ep_desc = ep->desc; + /* +@@ -720,7 +742,11 @@ int u_audio_start_playback(struct g_audio *audio_dev) + uac->p_residue_mil = 0; + + prm->ep_enabled = true; +- usb_ep_enable(ep); ++ ret = usb_ep_enable(ep); ++ if (ret < 0) { ++ dev_err(dev, "usb_ep_enable failed for in_ep (%d)\n", ret); ++ return ret; ++ } + + for (i = 0; i < params->req_number; i++) { + if (!prm->reqs[i]) { +diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c +index a92eb6d909768..8962f96ae7294 100644 +--- a/drivers/usb/gadget/function/u_serial.c ++++ b/drivers/usb/gadget/function/u_serial.c +@@ -1441,6 +1441,7 @@ void gserial_suspend(struct gserial *gser) + spin_lock(&port->port_lock); + spin_unlock(&serial_port_lock); + port->suspended = true; ++ port->start_delayed = true; + spin_unlock_irqrestore(&port->port_lock, flags); + } + EXPORT_SYMBOL_GPL(gserial_suspend); +diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c +index 358394fc3db93..9886e1cb13985 100644 +--- a/drivers/usb/gadget/udc/core.c ++++ b/drivers/usb/gadget/udc/core.c +@@ -118,12 +118,10 @@ int usb_ep_enable(struct usb_ep *ep) + goto out; + + /* UDC drivers can't handle endpoints with maxpacket size 0 */ +- if (usb_endpoint_maxp(ep->desc) == 0) { +- /* +- * We should log an error message here, but we can't call +- * dev_err() because there's no way to find the gadget +- * given only ep. +- */ ++ if (!ep->desc || usb_endpoint_maxp(ep->desc) == 0) { ++ WARN_ONCE(1, "%s: ep%d (%s) has %s\n", __func__, ep->address, ep->name, ++ (!ep->desc) ? "NULL descriptor" : "maxpacket 0"); ++ + ret = -EINVAL; + goto out; + } +diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c +index 6934970f180d7..5a8869cd95d52 100644 +--- a/drivers/usb/serial/usb_debug.c ++++ b/drivers/usb/serial/usb_debug.c +@@ -76,6 +76,11 @@ static void usb_debug_process_read_urb(struct urb *urb) + usb_serial_generic_process_read_urb(urb); + } + ++static void usb_debug_init_termios(struct tty_struct *tty) ++{ ++ tty->termios.c_lflag &= ~(ECHO | ECHONL); ++} ++ + static struct usb_serial_driver debug_device = { + .driver = { + .owner = THIS_MODULE, +@@ -85,6 +90,7 @@ static struct usb_serial_driver debug_device = { + .num_ports = 1, + .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, + .break_ctl = usb_debug_break_ctl, ++ .init_termios = usb_debug_init_termios, + .process_read_urb = usb_debug_process_read_urb, + }; + +@@ -96,6 +102,7 @@ static struct usb_serial_driver dbc_device = { + .id_table = dbc_id_table, + .num_ports = 1, + .break_ctl = usb_debug_break_ctl, ++ .init_termios = usb_debug_init_termios, + .process_read_urb = usb_debug_process_read_urb, + }; + +diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c +index 37d1fc34e8a56..14a5f55f24fc8 100644 +--- a/drivers/usb/usbip/vhci_hcd.c ++++ b/drivers/usb/usbip/vhci_hcd.c +@@ -745,6 +745,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + * + */ + if (usb_pipedevice(urb->pipe) == 0) { ++ struct usb_device *old; + __u8 type = usb_pipetype(urb->pipe); + struct usb_ctrlrequest *ctrlreq = + (struct usb_ctrlrequest *) urb->setup_packet; +@@ -755,14 +756,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + goto no_need_xmit; + } + ++ old = vdev->udev; + switch (ctrlreq->bRequest) { + case USB_REQ_SET_ADDRESS: + /* set_address may come when a device is reset */ + dev_info(dev, "SetAddress Request (%d) to port %d\n", + ctrlreq->wValue, vdev->rhport); + +- usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); ++ usb_put_dev(old); + + spin_lock(&vdev->ud.lock); + vdev->ud.status = VDEV_ST_USED; +@@ -781,8 +783,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + usbip_dbg_vhci_hc( + "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n"); + +- usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); ++ usb_put_dev(old); + goto out; + + default: +@@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud) + static void vhci_device_reset(struct usbip_device *ud) + { + struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); ++ struct usb_device *old = vdev->udev; + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); +@@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud) + vdev->speed = 0; + vdev->devid = 0; + +- usb_put_dev(vdev->udev); + vdev->udev = NULL; ++ usb_put_dev(old); + + if (ud->tcp_socket) { + sockfd_put(ud->tcp_socket); +diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c +index fb590e346e43d..da2c31ccc1380 100644 +--- a/drivers/vhost/vdpa.c ++++ b/drivers/vhost/vdpa.c +@@ -1378,13 +1378,7 @@ static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) + + notify = ops->get_vq_notification(vdpa, index); + +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- if (remap_pfn_range(vma, vmf->address & PAGE_MASK, +- PFN_DOWN(notify.addr), PAGE_SIZE, +- vma->vm_page_prot)) +- return VM_FAULT_SIGBUS; +- +- return VM_FAULT_NOPAGE; ++ return vmf_insert_pfn(vma, vmf->address & PAGE_MASK, PFN_DOWN(notify.addr)); + } + + static const struct vm_operations_struct vhost_vdpa_vm_ops = { +diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c +index da88173bac432..923f064c7e3e9 100644 +--- a/drivers/xen/privcmd.c ++++ b/drivers/xen/privcmd.c +@@ -841,7 +841,7 @@ static long privcmd_ioctl_mmap_resource(struct file *file, + #ifdef CONFIG_XEN_PRIVCMD_IRQFD + /* Irqfd support */ + static struct workqueue_struct *irqfd_cleanup_wq; +-static DEFINE_MUTEX(irqfds_lock); ++static DEFINE_SPINLOCK(irqfds_lock); + static LIST_HEAD(irqfds_list); + + struct privcmd_kernel_irqfd { +@@ -905,9 +905,11 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key) + irqfd_inject(kirqfd); + + if (flags & EPOLLHUP) { +- mutex_lock(&irqfds_lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&irqfds_lock, flags); + irqfd_deactivate(kirqfd); +- mutex_unlock(&irqfds_lock); ++ spin_unlock_irqrestore(&irqfds_lock, flags); + } + + return 0; +@@ -925,6 +927,7 @@ irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt) + static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd) + { + struct privcmd_kernel_irqfd *kirqfd, *tmp; ++ unsigned long flags; + __poll_t events; + struct fd f; + void *dm_op; +@@ -964,18 +967,18 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd) + init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup); + init_poll_funcptr(&kirqfd->pt, irqfd_poll_func); + +- mutex_lock(&irqfds_lock); ++ spin_lock_irqsave(&irqfds_lock, flags); + + list_for_each_entry(tmp, &irqfds_list, list) { + if (kirqfd->eventfd == tmp->eventfd) { + ret = -EBUSY; +- mutex_unlock(&irqfds_lock); ++ spin_unlock_irqrestore(&irqfds_lock, flags); + goto error_eventfd; + } + } + + list_add_tail(&kirqfd->list, &irqfds_list); +- mutex_unlock(&irqfds_lock); ++ spin_unlock_irqrestore(&irqfds_lock, flags); + + /* + * Check if there was an event already pending on the eventfd before we +@@ -1007,12 +1010,13 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd) + { + struct privcmd_kernel_irqfd *kirqfd; + struct eventfd_ctx *eventfd; ++ unsigned long flags; + + eventfd = eventfd_ctx_fdget(irqfd->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + +- mutex_lock(&irqfds_lock); ++ spin_lock_irqsave(&irqfds_lock, flags); + + list_for_each_entry(kirqfd, &irqfds_list, list) { + if (kirqfd->eventfd == eventfd) { +@@ -1021,7 +1025,7 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd) + } + } + +- mutex_unlock(&irqfds_lock); ++ spin_unlock_irqrestore(&irqfds_lock, flags); + + eventfd_ctx_put(eventfd); + +@@ -1069,13 +1073,14 @@ static int privcmd_irqfd_init(void) + static void privcmd_irqfd_exit(void) + { + struct privcmd_kernel_irqfd *kirqfd, *tmp; ++ unsigned long flags; + +- mutex_lock(&irqfds_lock); ++ spin_lock_irqsave(&irqfds_lock, flags); + + list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list) + irqfd_deactivate(kirqfd); + +- mutex_unlock(&irqfds_lock); ++ spin_unlock_irqrestore(&irqfds_lock, flags); + + destroy_workqueue(irqfd_cleanup_wq); + } +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 06333a74d6c4c..86c7f8ce1715e 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -445,6 +445,7 @@ struct btrfs_file_private { + void *filldir_buf; + u64 last_index; + struct extent_state *llseek_cached_state; ++ bool fsync_skip_inode_lock; + }; + + static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info) +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 9fbffd84b16c5..c6a95dfa59c81 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2172,10 +2172,8 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page, + + page = find_get_page(mapping, cur >> PAGE_SHIFT); + ASSERT(PageLocked(page)); +- if (pages_dirty && page != locked_page) { ++ if (pages_dirty && page != locked_page) + ASSERT(PageDirty(page)); +- clear_page_dirty_for_io(page); +- } + + ret = __extent_writepage_io(BTRFS_I(inode), page, &bio_ctrl, + i_size, &nr); +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index c997b790568fa..952cf145c6295 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -1535,21 +1535,37 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) + * So here we disable page faults in the iov_iter and then retry if we + * got -EFAULT, faulting in the pages before the retry. + */ ++again: + from->nofault = true; + dio = btrfs_dio_write(iocb, from, written); + from->nofault = false; + +- /* +- * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync +- * iocb, and that needs to lock the inode. So unlock it before calling +- * iomap_dio_complete() to avoid a deadlock. +- */ +- btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); +- +- if (IS_ERR_OR_NULL(dio)) ++ if (IS_ERR_OR_NULL(dio)) { + err = PTR_ERR_OR_ZERO(dio); +- else ++ } else { ++ struct btrfs_file_private stack_private = { 0 }; ++ struct btrfs_file_private *private; ++ const bool have_private = (file->private_data != NULL); ++ ++ if (!have_private) ++ file->private_data = &stack_private; ++ ++ /* ++ * If we have a synchoronous write, we must make sure the fsync ++ * triggered by the iomap_dio_complete() call below doesn't ++ * deadlock on the inode lock - we are already holding it and we ++ * can't call it after unlocking because we may need to complete ++ * partial writes due to the input buffer (or parts of it) not ++ * being already faulted in. ++ */ ++ private = file->private_data; ++ private->fsync_skip_inode_lock = true; + err = iomap_dio_complete(dio); ++ private->fsync_skip_inode_lock = false; ++ ++ if (!have_private) ++ file->private_data = NULL; ++ } + + /* No increment (+=) because iomap returns a cumulative value. */ + if (err > 0) +@@ -1576,10 +1592,12 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) + } else { + fault_in_iov_iter_readable(from, left); + prev_left = left; +- goto relock; ++ goto again; + } + } + ++ btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); ++ + /* + * If 'err' is -ENOTBLK or we have not written all data, then it means + * we must fallback to buffered IO. +@@ -1778,6 +1796,7 @@ static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx) + */ + int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + { ++ struct btrfs_file_private *private = file->private_data; + struct dentry *dentry = file_dentry(file); + struct inode *inode = d_inode(dentry); + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +@@ -1787,6 +1806,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + int ret = 0, err; + u64 len; + bool full_sync; ++ const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false); + + trace_btrfs_sync_file(file, datasync); + +@@ -1814,7 +1834,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + if (ret) + goto out; + +- btrfs_inode_lock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); ++ if (skip_ilock) ++ down_write(&BTRFS_I(inode)->i_mmap_lock); ++ else ++ btrfs_inode_lock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); + + atomic_inc(&root->log_batch); + +@@ -1838,7 +1861,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + */ + ret = start_ordered_ops(inode, start, end); + if (ret) { +- btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); ++ if (skip_ilock) ++ up_write(&BTRFS_I(inode)->i_mmap_lock); ++ else ++ btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); + goto out; + } + +@@ -1941,7 +1967,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + * file again, but that will end up using the synchronization + * inside btrfs_sync_log to keep things safe. + */ +- btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); ++ if (skip_ilock) ++ up_write(&BTRFS_I(inode)->i_mmap_lock); ++ else ++ btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); + + if (ret == BTRFS_NO_LOG_SYNC) { + ret = btrfs_end_transaction(trans); +@@ -2009,7 +2038,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + + out_release_extents: + btrfs_release_log_ctx_extents(&ctx); +- btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); ++ if (skip_ilock) ++ up_write(&BTRFS_I(inode)->i_mmap_lock); ++ else ++ btrfs_inode_unlock(BTRFS_I(inode), BTRFS_ILOCK_MMAP); + goto out; + } + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index f59e599766662..3e141c4dd2630 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -855,6 +855,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, + spin_unlock(&ctl->tree_lock); + btrfs_err(fs_info, + "Duplicate entries in free space cache, dumping"); ++ kmem_cache_free(btrfs_free_space_bitmap_cachep, e->bitmap); + kmem_cache_free(btrfs_free_space_cachep, e); + goto free_cache; + } +diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c +index 0c93439e929fb..815a5fc3ff9d8 100644 +--- a/fs/btrfs/print-tree.c ++++ b/fs/btrfs/print-tree.c +@@ -12,7 +12,7 @@ + + struct root_name_map { + u64 id; +- char name[16]; ++ const char *name; + }; + + static const struct root_name_map root_map[] = { +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 012d9259ff532..a604aa1d23aed 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1411,7 +1411,11 @@ int ext4_inlinedir_to_tree(struct file *dir_file, + hinfo->hash = EXT4_DIRENT_HASH(de); + hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de); + } else { +- ext4fs_dirhash(dir, de->name, de->name_len, hinfo); ++ err = ext4fs_dirhash(dir, de->name, de->name_len, hinfo); ++ if (err) { ++ ret = err; ++ goto out; ++ } + } + if ((hinfo->hash < start_hash) || + ((hinfo->hash == start_hash) && +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 0168d28427077..57264eb4d9da3 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -399,6 +399,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, + tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS); + if (!tmp) { + brelse(new_bh); ++ free_buffer_head(new_bh); + return -ENOMEM; + } + spin_lock(&jh_in->b_state_lock); +diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c +index c71ae5c043060..4a20e92474b23 100644 +--- a/fs/smb/client/cifs_debug.c ++++ b/fs/smb/client/cifs_debug.c +@@ -1072,7 +1072,7 @@ static int cifs_security_flags_proc_open(struct inode *inode, struct file *file) + static void + cifs_security_flags_handle_must_flags(unsigned int *flags) + { +- unsigned int signflags = *flags & CIFSSEC_MUST_SIGN; ++ unsigned int signflags = *flags & (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL); + + if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) + *flags = CIFSSEC_MUST_KRB5; +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index 53e00255d96b6..54a84003950a4 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -1922,7 +1922,7 @@ static inline bool is_replayable_error(int error) + #define CIFSSEC_MAY_SIGN 0x00001 + #define CIFSSEC_MAY_NTLMV2 0x00004 + #define CIFSSEC_MAY_KRB5 0x00008 +-#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ ++#define CIFSSEC_MAY_SEAL 0x00040 + #define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */ + + #define CIFSSEC_MUST_SIGN 0x01001 +@@ -1932,11 +1932,11 @@ require use of the stronger protocol */ + #define CIFSSEC_MUST_NTLMV2 0x04004 + #define CIFSSEC_MUST_KRB5 0x08008 + #ifdef CONFIG_CIFS_UPCALL +-#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ ++#define CIFSSEC_MASK 0xCF0CF /* flags supported if no weak allowed */ + #else +-#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */ ++#define CIFSSEC_MASK 0xC70C7 /* flags supported if no weak allowed */ + #endif /* UPCALL */ +-#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ ++#define CIFSSEC_MUST_SEAL 0x40040 + #define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ + + #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP | CIFSSEC_MAY_SEAL) +diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c +index 9cdbc3ccc1d14..e74ba047902d8 100644 +--- a/fs/smb/client/inode.c ++++ b/fs/smb/client/inode.c +@@ -1023,13 +1023,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, + } + + rc = -EOPNOTSUPP; +- switch ((data->reparse.tag = tag)) { +- case 0: /* SMB1 symlink */ ++ data->reparse.tag = tag; ++ if (!data->reparse.tag) { + if (server->ops->query_symlink) { + rc = server->ops->query_symlink(xid, tcon, + cifs_sb, full_path, + &data->symlink_target); + } ++ if (rc == -EOPNOTSUPP) ++ data->reparse.tag = IO_REPARSE_TAG_INTERNAL; ++ } ++ ++ switch (data->reparse.tag) { ++ case 0: /* SMB1 symlink */ ++ break; ++ case IO_REPARSE_TAG_INTERNAL: ++ rc = 0; ++ if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) { ++ cifs_create_junction_fattr(fattr, sb); ++ goto out; ++ } + break; + case IO_REPARSE_TAG_MOUNT_POINT: + cifs_create_junction_fattr(fattr, sb); +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index 07c468ddb88a8..65d4b72b4d51a 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -1288,6 +1288,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, + const char *full_path, + bool *islink) + { ++ struct TCP_Server_Info *server = tcon->ses->server; + struct cifs_ses *ses = tcon->ses; + size_t len; + char *path; +@@ -1304,12 +1305,12 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, + !is_tcon_dfs(tcon)) + return 0; + +- spin_lock(&tcon->tc_lock); +- if (!tcon->origin_fullpath) { +- spin_unlock(&tcon->tc_lock); ++ spin_lock(&server->srv_lock); ++ if (!server->leaf_fullpath) { ++ spin_unlock(&server->srv_lock); + return 0; + } +- spin_unlock(&tcon->tc_lock); ++ spin_unlock(&server->srv_lock); + + /* + * Slow path - tcon is DFS and @full_path has prefix path, so attempt +diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c +index a0ffbda907331..689d8a506d459 100644 +--- a/fs/smb/client/reparse.c ++++ b/fs/smb/client/reparse.c +@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, + } + + switch (tag) { ++ case IO_REPARSE_TAG_INTERNAL: ++ if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY)) ++ return false; ++ fallthrough; + case IO_REPARSE_TAG_DFS: + case IO_REPARSE_TAG_DFSR: + case IO_REPARSE_TAG_MOUNT_POINT: +diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h +index 6b55d1df9e2f8..2c0644bc4e65a 100644 +--- a/fs/smb/client/reparse.h ++++ b/fs/smb/client/reparse.h +@@ -12,6 +12,12 @@ + #include "fs_context.h" + #include "cifsglob.h" + ++/* ++ * Used only by cifs.ko to ignore reparse points from files when client or ++ * server doesn't support FSCTL_GET_REPARSE_POINT. ++ */ ++#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U) ++ + static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf) + { + u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); +@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode) + static inline bool reparse_inode_match(struct inode *inode, + struct cifs_fattr *fattr) + { ++ struct cifsInodeInfo *cinode = CIFS_I(inode); + struct timespec64 ctime = inode_get_ctime(inode); + +- return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) && +- CIFS_I(inode)->reparse_tag == fattr->cf_cifstag && ++ /* ++ * Do not match reparse tags when client or server doesn't support ++ * FSCTL_GET_REPARSE_POINT. @fattr->cf_cifstag should contain correct ++ * reparse tag from query dir response but the client won't be able to ++ * read the reparse point data anyway. This spares us a revalidation. ++ */ ++ if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL && ++ cinode->reparse_tag != fattr->cf_cifstag) ++ return false; ++ return (cinode->cifsAttrs & ATTR_REPARSE) && + timespec64_equal(&ctime, &fattr->cf_ctime); + } + +diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c +index 86f8c81791374..28031c7ba6b19 100644 +--- a/fs/smb/client/smb2inode.c ++++ b/fs/smb/client/smb2inode.c +@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid, + + switch (rc) { + case 0: ++ rc = parse_create_response(data, cifs_sb, &out_iov[0]); ++ break; + case -EOPNOTSUPP: + /* + * BB TODO: When support for special files added to Samba +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index a5efce03cb58e..61df8a5c68242 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -80,6 +80,9 @@ int smb3_encryption_required(const struct cifs_tcon *tcon) + if (tcon->seal && + (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) + return 1; ++ if (((global_secflags & CIFSSEC_MUST_SEAL) == CIFSSEC_MUST_SEAL) && ++ (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) ++ return 1; + return 0; + } + +diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c +index b406bb3430f3d..aa54be1ce1242 100644 +--- a/fs/tracefs/event_inode.c ++++ b/fs/tracefs/event_inode.c +@@ -113,7 +113,7 @@ static void release_ei(struct kref *ref) + entry->release(entry->name, ei->data); + } + +- call_rcu(&ei->rcu, free_ei_rcu); ++ call_srcu(&eventfs_srcu, &ei->rcu, free_ei_rcu); + } + + static inline void put_ei(struct eventfs_inode *ei) +@@ -806,7 +806,7 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode + /* Was the parent freed? */ + if (list_empty(&ei->list)) { + cleanup_ei(ei); +- ei = NULL; ++ ei = ERR_PTR(-EBUSY); + } + return ei; + } +diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c +index 4ea11d1f72ace..7d389dd5ed519 100644 +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -42,7 +42,7 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) + struct tracefs_inode *ti; + unsigned long flags; + +- ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL); ++ ti = alloc_inode_sb(sb, tracefs_inode_cachep, GFP_KERNEL); + if (!ti) + return NULL; + +@@ -53,15 +53,14 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) + return &ti->vfs_inode; + } + +-static void tracefs_free_inode_rcu(struct rcu_head *rcu) ++static void tracefs_free_inode(struct inode *inode) + { +- struct tracefs_inode *ti; ++ struct tracefs_inode *ti = get_tracefs(inode); + +- ti = container_of(rcu, struct tracefs_inode, rcu); + kmem_cache_free(tracefs_inode_cachep, ti); + } + +-static void tracefs_free_inode(struct inode *inode) ++static void tracefs_destroy_inode(struct inode *inode) + { + struct tracefs_inode *ti = get_tracefs(inode); + unsigned long flags; +@@ -69,8 +68,6 @@ static void tracefs_free_inode(struct inode *inode) + spin_lock_irqsave(&tracefs_inode_lock, flags); + list_del_rcu(&ti->list); + spin_unlock_irqrestore(&tracefs_inode_lock, flags); +- +- call_rcu(&ti->rcu, tracefs_free_inode_rcu); + } + + static ssize_t default_read_file(struct file *file, char __user *buf, +@@ -458,6 +455,7 @@ static int tracefs_drop_inode(struct inode *inode) + static const struct super_operations tracefs_super_operations = { + .alloc_inode = tracefs_alloc_inode, + .free_inode = tracefs_free_inode, ++ .destroy_inode = tracefs_destroy_inode, + .drop_inode = tracefs_drop_inode, + .statfs = simple_statfs, + .remount_fs = tracefs_remount, +diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h +index f704d8348357e..d83c2a25f288e 100644 +--- a/fs/tracefs/internal.h ++++ b/fs/tracefs/internal.h +@@ -10,10 +10,7 @@ enum { + }; + + struct tracefs_inode { +- union { +- struct inode vfs_inode; +- struct rcu_head rcu; +- }; ++ struct inode vfs_inode; + /* The below gets initialized with memset_after(ti, 0, vfs_inode) */ + struct list_head list; + unsigned long flags; +diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c +index 558ad046972ad..bb471ec364046 100644 +--- a/fs/udf/balloc.c ++++ b/fs/udf/balloc.c +@@ -18,6 +18,7 @@ + #include "udfdecl.h" + + #include ++#include + + #include "udf_i.h" + #include "udf_sb.h" +@@ -140,7 +141,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb, + { + struct udf_sb_info *sbi = UDF_SB(sb); + struct buffer_head *bh = NULL; +- struct udf_part_map *partmap; + unsigned long block; + unsigned long block_group; + unsigned long bit; +@@ -149,19 +149,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb, + unsigned long overflow; + + mutex_lock(&sbi->s_alloc_mutex); +- partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; +- if (bloc->logicalBlockNum + count < count || +- (bloc->logicalBlockNum + count) > partmap->s_partition_len) { +- udf_debug("%u < %d || %u + %u > %u\n", +- bloc->logicalBlockNum, 0, +- bloc->logicalBlockNum, count, +- partmap->s_partition_len); +- goto error_return; +- } +- ++ /* We make sure this cannot overflow when mounting the filesystem */ + block = bloc->logicalBlockNum + offset + + (sizeof(struct spaceBitmapDesc) << 3); +- + do { + overflow = 0; + block_group = block >> (sb->s_blocksize_bits + 3); +@@ -391,7 +381,6 @@ static void udf_table_free_blocks(struct super_block *sb, + uint32_t count) + { + struct udf_sb_info *sbi = UDF_SB(sb); +- struct udf_part_map *partmap; + uint32_t start, end; + uint32_t elen; + struct kernel_lb_addr eloc; +@@ -400,16 +389,6 @@ static void udf_table_free_blocks(struct super_block *sb, + struct udf_inode_info *iinfo; + + mutex_lock(&sbi->s_alloc_mutex); +- partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; +- if (bloc->logicalBlockNum + count < count || +- (bloc->logicalBlockNum + count) > partmap->s_partition_len) { +- udf_debug("%u < %d || %u + %u > %u\n", +- bloc->logicalBlockNum, 0, +- bloc->logicalBlockNum, count, +- partmap->s_partition_len); +- goto error_return; +- } +- + iinfo = UDF_I(table); + udf_add_free_space(sb, sbi->s_partition, count); + +@@ -684,6 +663,17 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode, + { + uint16_t partition = bloc->partitionReferenceNum; + struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; ++ uint32_t blk; ++ ++ if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) || ++ check_add_overflow(blk, count, &blk) || ++ bloc->logicalBlockNum + count > map->s_partition_len) { ++ udf_debug("Invalid request to free blocks: (%d, %u), off %u, " ++ "len %u, partition len %u\n", ++ partition, bloc->logicalBlockNum, offset, count, ++ map->s_partition_len); ++ return; ++ } + + if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { + udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap, +diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c +index 57f366c3d3554..9f9d3abad2cf3 100644 +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -2965,7 +2965,7 @@ xlog_do_recovery_pass( + int error = 0, h_size, h_len; + int error2 = 0; + int bblks, split_bblks; +- int hblks, split_hblks, wrapped_hblks; ++ int hblks = 1, split_hblks, wrapped_hblks; + int i; + struct hlist_head rhash[XLOG_RHASH_SIZE]; + LIST_HEAD (buffer_list); +@@ -3021,14 +3021,22 @@ xlog_do_recovery_pass( + if (error) + goto bread_err1; + +- hblks = xlog_logrec_hblks(log, rhead); +- if (hblks != 1) { +- kmem_free(hbp); +- hbp = xlog_alloc_buffer(log, hblks); ++ /* ++ * This open codes xlog_logrec_hblks so that we can reuse the ++ * fixed up h_size value calculated above. Without that we'd ++ * still allocate the buffer based on the incorrect on-disk ++ * size. ++ */ ++ if (h_size > XLOG_HEADER_CYCLE_SIZE && ++ (rhead->h_version & cpu_to_be32(XLOG_VERSION_2))) { ++ hblks = DIV_ROUND_UP(h_size, XLOG_HEADER_CYCLE_SIZE); ++ if (hblks > 1) { ++ kmem_free(hbp); ++ hbp = xlog_alloc_buffer(log, hblks); ++ } + } + } else { + ASSERT(log->l_sectBBsize == 1); +- hblks = 1; + hbp = xlog_alloc_buffer(log, 1); + h_size = XLOG_BIG_RECORD_BSIZE; + } +diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h +index 378b2459efe2d..f7cc8080672cc 100644 +--- a/include/linux/blk-integrity.h ++++ b/include/linux/blk-integrity.h +@@ -105,14 +105,13 @@ static inline bool blk_integrity_rq(struct request *rq) + } + + /* +- * Return the first bvec that contains integrity data. Only drivers that are +- * limited to a single integrity segment should use this helper. ++ * Return the current bvec that contains the integrity data. bip_iter may be ++ * advanced to iterate over the integrity data. + */ +-static inline struct bio_vec *rq_integrity_vec(struct request *rq) ++static inline struct bio_vec rq_integrity_vec(struct request *rq) + { +- if (WARN_ON_ONCE(queue_max_integrity_segments(rq->q) > 1)) +- return NULL; +- return rq->bio->bi_integrity->bip_vec; ++ return mp_bvec_iter_bvec(rq->bio->bi_integrity->bip_vec, ++ rq->bio->bi_integrity->bip_iter); + } + #else /* CONFIG_BLK_DEV_INTEGRITY */ + static inline int blk_rq_count_integrity_sg(struct request_queue *q, +@@ -176,9 +175,10 @@ static inline int blk_integrity_rq(struct request *rq) + return 0; + } + +-static inline struct bio_vec *rq_integrity_vec(struct request *rq) ++static inline struct bio_vec rq_integrity_vec(struct request *rq) + { +- return NULL; ++ /* the optimizer will remove all calls to this function */ ++ return (struct bio_vec){ }; + } + #endif /* CONFIG_BLK_DEV_INTEGRITY */ + #endif /* _LINUX_BLK_INTEGRITY_H */ +diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h +index 1d42d4b173271..0ad8b550bb4b4 100644 +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -291,7 +291,19 @@ static inline void timer_probe(void) {} + #define TIMER_ACPI_DECLARE(name, table_id, fn) \ + ACPI_DECLARE_PROBE_ENTRY(timer, name, table_id, 0, NULL, 0, fn) + +-extern ulong max_cswd_read_retries; ++static inline unsigned int clocksource_get_max_watchdog_retry(void) ++{ ++ /* ++ * When system is in the boot phase or under heavy workload, there ++ * can be random big latencies during the clocksource/watchdog ++ * read, so allow retries to filter the noise latency. As the ++ * latency's frequency and maximum value goes up with the number of ++ * CPUs, scale the number of retries with the number of online ++ * CPUs. ++ */ ++ return (ilog2(num_online_cpus()) / 2) + 1; ++} ++ + void clocksource_verify_percpu(struct clocksource *cs); + + #endif /* _LINUX_CLOCKSOURCE_H */ +diff --git a/include/linux/fs.h b/include/linux/fs.h +index ee5efad0d7801..56dce38c47862 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -642,6 +642,7 @@ struct inode { + umode_t i_mode; + unsigned short i_opflags; + kuid_t i_uid; ++ struct list_head i_lru; /* inode LRU list */ + kgid_t i_gid; + unsigned int i_flags; + +@@ -703,7 +704,6 @@ struct inode { + u16 i_wb_frn_avg_time; + u16 i_wb_frn_history; + #endif +- struct list_head i_lru; /* inode LRU list */ + struct list_head i_sb_list; + struct list_head i_wb_list; /* backing dev writeback list */ + union { +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 0a85ff5c8db3c..abff4e3b6a58b 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2124,6 +2124,8 @@ + + #define PCI_VENDOR_ID_CHELSIO 0x1425 + ++#define PCI_VENDOR_ID_EDIMAX 0x1432 ++ + #define PCI_VENDOR_ID_ADLINK 0x144a + + #define PCI_VENDOR_ID_SAMSUNG 0x144d +diff --git a/include/linux/profile.h b/include/linux/profile.h +index 11db1ec516e27..12da750a88a04 100644 +--- a/include/linux/profile.h ++++ b/include/linux/profile.h +@@ -11,7 +11,6 @@ + + #define CPU_PROFILING 1 + #define SCHED_PROFILING 2 +-#define SLEEP_PROFILING 3 + #define KVM_PROFILING 4 + + struct proc_dir_entry; +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index 696f8dc4aa53c..cb8bd759e8005 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -869,7 +869,6 @@ do { \ + struct perf_event; + + DECLARE_PER_CPU(struct pt_regs, perf_trace_regs); +-DECLARE_PER_CPU(int, bpf_kprobe_override); + + extern int perf_trace_init(struct perf_event *event); + extern void perf_trace_destroy(struct perf_event *event); +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index d1d7825318c32..6c395a2600e8d 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -56,7 +56,6 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + unsigned int thlen = 0; + unsigned int p_off = 0; + unsigned int ip_proto; +- u64 ret, remainder, gso_size; + + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { +@@ -99,16 +98,6 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); + +- if (hdr->gso_size) { +- gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); +- ret = div64_u64_rem(skb->len, gso_size, &remainder); +- if (!(ret && (hdr->gso_size > needed) && +- ((remainder > needed) || (remainder == 0)))) { +- return -EINVAL; +- } +- skb_shinfo(skb)->tx_flags |= SKBFL_SHARED_FRAG; +- } +- + if (!pskb_may_pull(skb, needed)) + return -EINVAL; + +@@ -182,6 +171,11 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + if (gso_type != SKB_GSO_UDP_L4) + return -EINVAL; + break; ++ case SKB_GSO_TCPV4: ++ case SKB_GSO_TCPV6: ++ if (skb->csum_offset != offsetof(struct tcphdr, check)) ++ return -EINVAL; ++ break; + } + + /* Kernel has a special handling for GSO_BY_FRAGS. */ +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index b32539bb0fb05..61cfc8891f820 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -128,18 +128,26 @@ void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args, + + static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i, + const struct in6_addr *daddr, +- unsigned int prefs, ++ unsigned int prefs, int l3mdev_index, + struct in6_addr *saddr) + { ++ struct net_device *l3mdev; ++ struct net_device *dev; ++ bool same_vrf; + int err = 0; + +- if (f6i && f6i->fib6_prefsrc.plen) { ++ rcu_read_lock(); ++ ++ l3mdev = dev_get_by_index_rcu(net, l3mdev_index); ++ if (!f6i || !f6i->fib6_prefsrc.plen || l3mdev) ++ dev = f6i ? fib6_info_nh_dev(f6i) : NULL; ++ same_vrf = !l3mdev || l3mdev_master_dev_rcu(dev) == l3mdev; ++ if (f6i && f6i->fib6_prefsrc.plen && same_vrf) + *saddr = f6i->fib6_prefsrc.addr; +- } else { +- struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL; ++ else ++ err = ipv6_dev_get_saddr(net, same_vrf ? dev : l3mdev, daddr, prefs, saddr); + +- err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr); +- } ++ rcu_read_unlock(); + + return err; + } +diff --git a/include/trace/events/intel_ifs.h b/include/trace/events/intel_ifs.h +index d7353024016cc..af0af3f1d9b7c 100644 +--- a/include/trace/events/intel_ifs.h ++++ b/include/trace/events/intel_ifs.h +@@ -10,25 +10,25 @@ + + TRACE_EVENT(ifs_status, + +- TP_PROTO(int cpu, union ifs_scan activate, union ifs_status status), ++ TP_PROTO(int cpu, int start, int stop, u64 status), + +- TP_ARGS(cpu, activate, status), ++ TP_ARGS(cpu, start, stop, status), + + TP_STRUCT__entry( + __field( u64, status ) + __field( int, cpu ) +- __field( u8, start ) +- __field( u8, stop ) ++ __field( u16, start ) ++ __field( u16, stop ) + ), + + TP_fast_assign( + __entry->cpu = cpu; +- __entry->start = activate.start; +- __entry->stop = activate.stop; +- __entry->status = status.data; ++ __entry->start = start; ++ __entry->stop = stop; ++ __entry->status = status; + ), + +- TP_printk("cpu: %d, start: %.2x, stop: %.2x, status: %llx", ++ TP_printk("cpu: %d, start: %.4x, stop: %.4x, status: %.16llx", + __entry->cpu, + __entry->start, + __entry->stop, +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 5c9888901ef44..46094f0c9fcda 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -517,6 +517,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node, + flags = IRQD_AFFINITY_MANAGED | + IRQD_MANAGED_SHUTDOWN; + } ++ flags |= IRQD_AFFINITY_SET; + mask = &affinity->mask; + node = cpu_to_node(cpumask_first(mask)); + affinity++; +diff --git a/kernel/jump_label.c b/kernel/jump_label.c +index eec802175ccc6..1ed269b2c4035 100644 +--- a/kernel/jump_label.c ++++ b/kernel/jump_label.c +@@ -231,7 +231,7 @@ void static_key_disable_cpuslocked(struct static_key *key) + } + + jump_label_lock(); +- if (atomic_cmpxchg(&key->enabled, 1, 0)) ++ if (atomic_cmpxchg(&key->enabled, 1, 0) == 1) + jump_label_update(key); + jump_label_unlock(); + } +@@ -284,7 +284,7 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key) + return; + + guard(mutex)(&jump_label_mutex); +- if (atomic_cmpxchg(&key->enabled, 1, 0)) ++ if (atomic_cmpxchg(&key->enabled, 1, 0) == 1) + jump_label_update(key); + else + WARN_ON_ONCE(!static_key_slow_try_dec(key)); +diff --git a/kernel/kcov.c b/kernel/kcov.c +index 9f4affae4fad4..72d9aa6fb50c3 100644 +--- a/kernel/kcov.c ++++ b/kernel/kcov.c +@@ -161,6 +161,15 @@ static void kcov_remote_area_put(struct kcov_remote_area *area, + kmsan_unpoison_memory(&area->list, sizeof(area->list)); + } + ++/* ++ * Unlike in_serving_softirq(), this function returns false when called during ++ * a hardirq or an NMI that happened in the softirq context. ++ */ ++static inline bool in_softirq_really(void) ++{ ++ return in_serving_softirq() && !in_hardirq() && !in_nmi(); ++} ++ + static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) + { + unsigned int mode; +@@ -170,7 +179,7 @@ static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_stru + * so we ignore code executed in interrupts, unless we are in a remote + * coverage collection section in a softirq. + */ +- if (!in_task() && !(in_serving_softirq() && t->kcov_softirq)) ++ if (!in_task() && !(in_softirq_really() && t->kcov_softirq)) + return false; + mode = READ_ONCE(t->kcov_mode); + /* +@@ -848,7 +857,7 @@ void kcov_remote_start(u64 handle) + + if (WARN_ON(!kcov_check_handle(handle, true, true, true))) + return; +- if (!in_task() && !in_serving_softirq()) ++ if (!in_task() && !in_softirq_really()) + return; + + local_lock_irqsave(&kcov_percpu_data.lock, flags); +@@ -990,7 +999,7 @@ void kcov_remote_stop(void) + int sequence; + unsigned long flags; + +- if (!in_task() && !in_serving_softirq()) ++ if (!in_task() && !in_softirq_really()) + return; + + local_lock_irqsave(&kcov_percpu_data.lock, flags); +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index add63428c0b40..c10954bd84448 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -1558,8 +1558,8 @@ static bool is_cfi_preamble_symbol(unsigned long addr) + if (lookup_symbol_name(addr, symbuf)) + return false; + +- return str_has_prefix("__cfi_", symbuf) || +- str_has_prefix("__pfx_", symbuf); ++ return str_has_prefix(symbuf, "__cfi_") || ++ str_has_prefix(symbuf, "__pfx_"); + } + + static int check_kprobe_address_safe(struct kprobe *p, +diff --git a/kernel/module/main.c b/kernel/module/main.c +index 34d9e718c2c7d..b00e31721a73e 100644 +--- a/kernel/module/main.c ++++ b/kernel/module/main.c +@@ -3081,7 +3081,7 @@ static bool idempotent(struct idempotent *u, const void *cookie) + struct idempotent *existing; + bool first; + +- u->ret = 0; ++ u->ret = -EINTR; + u->cookie = cookie; + init_completion(&u->complete); + +@@ -3117,7 +3117,7 @@ static int idempotent_complete(struct idempotent *u, int ret) + hlist_for_each_entry_safe(pos, next, head, entry) { + if (pos->cookie != cookie) + continue; +- hlist_del(&pos->entry); ++ hlist_del_init(&pos->entry); + pos->ret = ret; + complete(&pos->complete); + } +@@ -3125,6 +3125,28 @@ static int idempotent_complete(struct idempotent *u, int ret) + return ret; + } + ++/* ++ * Wait for the idempotent worker. ++ * ++ * If we get interrupted, we need to remove ourselves from the ++ * the idempotent list, and the completion may still come in. ++ * ++ * The 'idem_lock' protects against the race, and 'idem.ret' was ++ * initialized to -EINTR and is thus always the right return ++ * value even if the idempotent work then completes between ++ * the wait_for_completion and the cleanup. ++ */ ++static int idempotent_wait_for_completion(struct idempotent *u) ++{ ++ if (wait_for_completion_interruptible(&u->complete)) { ++ spin_lock(&idem_lock); ++ if (!hlist_unhashed(&u->entry)) ++ hlist_del(&u->entry); ++ spin_unlock(&idem_lock); ++ } ++ return u->ret; ++} ++ + static int init_module_from_file(struct file *f, const char __user * uargs, int flags) + { + struct load_info info = { }; +@@ -3160,15 +3182,16 @@ static int idempotent_init_module(struct file *f, const char __user * uargs, int + if (!f || !(f->f_mode & FMODE_READ)) + return -EBADF; + +- /* See if somebody else is doing the operation? */ +- if (idempotent(&idem, file_inode(f))) { +- wait_for_completion(&idem.complete); +- return idem.ret; ++ /* Are we the winners of the race and get to do this? */ ++ if (!idempotent(&idem, file_inode(f))) { ++ int ret = init_module_from_file(f, uargs, flags); ++ return idempotent_complete(&idem, ret); + } + +- /* Otherwise, we'll do it and complete others */ +- return idempotent_complete(&idem, +- init_module_from_file(f, uargs, flags)); ++ /* ++ * Somebody else won the race and is loading the module. ++ */ ++ return idempotent_wait_for_completion(&idem); + } + + SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) +diff --git a/kernel/padata.c b/kernel/padata.c +index c974568f65f5d..29545dd6dd53d 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -516,6 +516,13 @@ void __init padata_do_multithreaded(struct padata_mt_job *job) + ps.chunk_size = max(ps.chunk_size, job->min_chunk); + ps.chunk_size = roundup(ps.chunk_size, job->align); + ++ /* ++ * chunk_size can be 0 if the caller sets min_chunk to 0. So force it ++ * to at least 1 to prevent divide-by-0 panic in padata_mt_helper().` ++ */ ++ if (!ps.chunk_size) ++ ps.chunk_size = 1U; ++ + list_for_each_entry(pw, &works, pw_list) + queue_work(system_unbound_wq, &pw->pw_work); + +diff --git a/kernel/profile.c b/kernel/profile.c +index 8a77769bc4b4c..984f819b701c9 100644 +--- a/kernel/profile.c ++++ b/kernel/profile.c +@@ -57,20 +57,11 @@ static DEFINE_MUTEX(profile_flip_mutex); + int profile_setup(char *str) + { + static const char schedstr[] = "schedule"; +- static const char sleepstr[] = "sleep"; + static const char kvmstr[] = "kvm"; + const char *select = NULL; + int par; + +- if (!strncmp(str, sleepstr, strlen(sleepstr))) { +-#ifdef CONFIG_SCHEDSTATS +- force_schedstat_enabled(); +- prof_on = SLEEP_PROFILING; +- select = sleepstr; +-#else +- pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n"); +-#endif /* CONFIG_SCHEDSTATS */ +- } else if (!strncmp(str, schedstr, strlen(schedstr))) { ++ if (!strncmp(str, schedstr, strlen(schedstr))) { + prof_on = SCHED_PROFILING; + select = schedstr; + } else if (!strncmp(str, kvmstr, strlen(kvmstr))) { +diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c +index 781146600aa49..46612fb15fc6d 100644 +--- a/kernel/rcu/rcutorture.c ++++ b/kernel/rcu/rcutorture.c +@@ -2592,7 +2592,7 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp) + spin_lock_irqsave(&rfp->rcu_fwd_lock, flags); + rfcpp = rfp->rcu_fwd_cb_tail; + rfp->rcu_fwd_cb_tail = &rfcp->rfc_next; +- WRITE_ONCE(*rfcpp, rfcp); ++ smp_store_release(rfcpp, rfcp); + WRITE_ONCE(rfp->n_launders_cb, rfp->n_launders_cb + 1); + i = ((jiffies - rfp->rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV)); + if (i >= ARRAY_SIZE(rfp->n_launders_hist)) +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 8cf6a6fef7965..583cc29080764 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -4595,11 +4595,15 @@ void rcutree_migrate_callbacks(int cpu) + struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu); + bool needwake; + +- if (rcu_rdp_is_offloaded(rdp) || +- rcu_segcblist_empty(&rdp->cblist)) +- return; /* No callbacks to migrate. */ ++ if (rcu_rdp_is_offloaded(rdp)) ++ return; + + raw_spin_lock_irqsave(&rcu_state.barrier_lock, flags); ++ if (rcu_segcblist_empty(&rdp->cblist)) { ++ raw_spin_unlock_irqrestore(&rcu_state.barrier_lock, flags); ++ return; /* No callbacks to migrate. */ ++ } ++ + WARN_ON_ONCE(rcu_rdp_cpu_online(rdp)); + rcu_barrier_entrain(rdp); + my_rdp = this_cpu_ptr(&rcu_data); +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 92e4afeb71add..97571d390f184 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -9596,6 +9596,30 @@ void set_rq_offline(struct rq *rq) + } + } + ++static inline void sched_set_rq_online(struct rq *rq, int cpu) ++{ ++ struct rq_flags rf; ++ ++ rq_lock_irqsave(rq, &rf); ++ if (rq->rd) { ++ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); ++ set_rq_online(rq); ++ } ++ rq_unlock_irqrestore(rq, &rf); ++} ++ ++static inline void sched_set_rq_offline(struct rq *rq, int cpu) ++{ ++ struct rq_flags rf; ++ ++ rq_lock_irqsave(rq, &rf); ++ if (rq->rd) { ++ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); ++ set_rq_offline(rq); ++ } ++ rq_unlock_irqrestore(rq, &rf); ++} ++ + /* + * used to mark begin/end of suspend/resume: + */ +@@ -9646,10 +9670,25 @@ static int cpuset_cpu_inactive(unsigned int cpu) + return 0; + } + ++static inline void sched_smt_present_inc(int cpu) ++{ ++#ifdef CONFIG_SCHED_SMT ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_inc_cpuslocked(&sched_smt_present); ++#endif ++} ++ ++static inline void sched_smt_present_dec(int cpu) ++{ ++#ifdef CONFIG_SCHED_SMT ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_dec_cpuslocked(&sched_smt_present); ++#endif ++} ++ + int sched_cpu_activate(unsigned int cpu) + { + struct rq *rq = cpu_rq(cpu); +- struct rq_flags rf; + + /* + * Clear the balance_push callback and prepare to schedule +@@ -9657,13 +9696,10 @@ int sched_cpu_activate(unsigned int cpu) + */ + balance_push_set(cpu, false); + +-#ifdef CONFIG_SCHED_SMT + /* + * When going up, increment the number of cores with SMT present. + */ +- if (cpumask_weight(cpu_smt_mask(cpu)) == 2) +- static_branch_inc_cpuslocked(&sched_smt_present); +-#endif ++ sched_smt_present_inc(cpu); + set_cpu_active(cpu, true); + + if (sched_smp_initialized) { +@@ -9681,12 +9717,7 @@ int sched_cpu_activate(unsigned int cpu) + * 2) At runtime, if cpuset_cpu_active() fails to rebuild the + * domains. + */ +- rq_lock_irqsave(rq, &rf); +- if (rq->rd) { +- BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); +- set_rq_online(rq); +- } +- rq_unlock_irqrestore(rq, &rf); ++ sched_set_rq_online(rq, cpu); + + return 0; + } +@@ -9694,7 +9725,6 @@ int sched_cpu_activate(unsigned int cpu) + int sched_cpu_deactivate(unsigned int cpu) + { + struct rq *rq = cpu_rq(cpu); +- struct rq_flags rf; + int ret; + + /* +@@ -9725,20 +9755,14 @@ int sched_cpu_deactivate(unsigned int cpu) + */ + synchronize_rcu(); + +- rq_lock_irqsave(rq, &rf); +- if (rq->rd) { +- BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); +- set_rq_offline(rq); +- } +- rq_unlock_irqrestore(rq, &rf); ++ sched_set_rq_offline(rq, cpu); + +-#ifdef CONFIG_SCHED_SMT + /* + * When going down, decrement the number of cores with SMT present. + */ +- if (cpumask_weight(cpu_smt_mask(cpu)) == 2) +- static_branch_dec_cpuslocked(&sched_smt_present); ++ sched_smt_present_dec(cpu); + ++#ifdef CONFIG_SCHED_SMT + sched_core_cpu_deactivate(cpu); + #endif + +@@ -9748,6 +9772,8 @@ int sched_cpu_deactivate(unsigned int cpu) + sched_update_numa(cpu, false); + ret = cpuset_cpu_inactive(cpu); + if (ret) { ++ sched_smt_present_inc(cpu); ++ sched_set_rq_online(rq, cpu); + balance_push_set(cpu, false); + set_cpu_active(cpu, true); + sched_update_numa(cpu, true); +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index af7952f12e6cf..b453f8a6a7c76 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -595,6 +595,12 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, + } + + stime = mul_u64_u64_div_u64(stime, rtime, stime + utime); ++ /* ++ * Because mul_u64_u64_div_u64() can approximate on some ++ * achitectures; enforce the constraint that: a*b/(b+c) <= a. ++ */ ++ if (unlikely(stime > rtime)) ++ stime = rtime; + + update: + /* +diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c +index 857f837f52cbe..966f4eacfe51d 100644 +--- a/kernel/sched/stats.c ++++ b/kernel/sched/stats.c +@@ -92,16 +92,6 @@ void __update_stats_enqueue_sleeper(struct rq *rq, struct task_struct *p, + + trace_sched_stat_blocked(p, delta); + +- /* +- * Blocking time is in units of nanosecs, so shift by +- * 20 to get a milliseconds-range estimation of the +- * amount of time that the task spent sleeping: +- */ +- if (unlikely(prof_on == SLEEP_PROFILING)) { +- profile_hits(SLEEP_PROFILING, +- (void *)get_wchan(p), +- delta >> 20); +- } + account_scheduler_latency(p, delta >> 10, 0); + } + } +diff --git a/kernel/time/clocksource-wdtest.c b/kernel/time/clocksource-wdtest.c +index df922f49d171b..d06185e054ea2 100644 +--- a/kernel/time/clocksource-wdtest.c ++++ b/kernel/time/clocksource-wdtest.c +@@ -104,8 +104,8 @@ static void wdtest_ktime_clocksource_reset(void) + static int wdtest_func(void *arg) + { + unsigned long j1, j2; ++ int i, max_retries; + char *s; +- int i; + + schedule_timeout_uninterruptible(holdoff * HZ); + +@@ -139,18 +139,19 @@ static int wdtest_func(void *arg) + WARN_ON_ONCE(time_before(j2, j1 + NSEC_PER_USEC)); + + /* Verify tsc-like stability with various numbers of errors injected. */ +- for (i = 0; i <= max_cswd_read_retries + 1; i++) { +- if (i <= 1 && i < max_cswd_read_retries) ++ max_retries = clocksource_get_max_watchdog_retry(); ++ for (i = 0; i <= max_retries + 1; i++) { ++ if (i <= 1 && i < max_retries) + s = ""; +- else if (i <= max_cswd_read_retries) ++ else if (i <= max_retries) + s = ", expect message"; + else + s = ", expect clock skew"; +- pr_info("--- Watchdog with %dx error injection, %lu retries%s.\n", i, max_cswd_read_retries, s); ++ pr_info("--- Watchdog with %dx error injection, %d retries%s.\n", i, max_retries, s); + WRITE_ONCE(wdtest_ktime_read_ndelays, i); + schedule_timeout_uninterruptible(2 * HZ); + WARN_ON_ONCE(READ_ONCE(wdtest_ktime_read_ndelays)); +- WARN_ON_ONCE((i <= max_cswd_read_retries) != ++ WARN_ON_ONCE((i <= max_retries) != + !(clocksource_wdtest_ktime.flags & CLOCK_SOURCE_UNSTABLE)); + wdtest_ktime_clocksource_reset(); + } +diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c +index 3052b1f1168e2..3260bbe98894b 100644 +--- a/kernel/time/clocksource.c ++++ b/kernel/time/clocksource.c +@@ -210,9 +210,6 @@ void clocksource_mark_unstable(struct clocksource *cs) + spin_unlock_irqrestore(&watchdog_lock, flags); + } + +-ulong max_cswd_read_retries = 2; +-module_param(max_cswd_read_retries, ulong, 0644); +-EXPORT_SYMBOL_GPL(max_cswd_read_retries); + static int verify_n_cpus = 8; + module_param(verify_n_cpus, int, 0644); + +@@ -224,11 +221,12 @@ enum wd_read_status { + + static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) + { +- unsigned int nretries; ++ unsigned int nretries, max_retries; + u64 wd_end, wd_end2, wd_delta; + int64_t wd_delay, wd_seq_delay; + +- for (nretries = 0; nretries <= max_cswd_read_retries; nretries++) { ++ max_retries = clocksource_get_max_watchdog_retry(); ++ for (nretries = 0; nretries <= max_retries; nretries++) { + local_irq_disable(); + *wdnow = watchdog->read(watchdog); + *csnow = cs->read(cs); +@@ -240,7 +238,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, + wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, + watchdog->shift); + if (wd_delay <= WATCHDOG_MAX_SKEW) { +- if (nretries > 1 || nretries >= max_cswd_read_retries) { ++ if (nretries > 1 && nretries >= max_retries) { + pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n", + smp_processor_id(), watchdog->name, nretries); + } +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index 406dccb79c2b6..8d2dd214ec682 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -727,17 +727,16 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc, + } + + if (txc->modes & ADJ_MAXERROR) +- time_maxerror = txc->maxerror; ++ time_maxerror = clamp(txc->maxerror, 0, NTP_PHASE_LIMIT); + + if (txc->modes & ADJ_ESTERROR) +- time_esterror = txc->esterror; ++ time_esterror = clamp(txc->esterror, 0, NTP_PHASE_LIMIT); + + if (txc->modes & ADJ_TIMECONST) { +- time_constant = txc->constant; ++ time_constant = clamp(txc->constant, 0, MAXTC); + if (!(time_status & STA_NANO)) + time_constant += 4; +- time_constant = min(time_constant, (long)MAXTC); +- time_constant = max(time_constant, 0l); ++ time_constant = clamp(time_constant, 0, MAXTC); + } + + if (txc->modes & ADJ_TAI && +diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c +index b4843099a8da7..ed58eebb4e8f4 100644 +--- a/kernel/time/tick-broadcast.c ++++ b/kernel/time/tick-broadcast.c +@@ -1141,7 +1141,6 @@ void tick_broadcast_switch_to_oneshot(void) + #ifdef CONFIG_HOTPLUG_CPU + void hotplug_cpu__broadcast_tick_pull(int deadcpu) + { +- struct tick_device *td = this_cpu_ptr(&tick_cpu_device); + struct clock_event_device *bc; + unsigned long flags; + +@@ -1167,6 +1166,8 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) + * device to avoid the starvation. + */ + if (tick_check_broadcast_expired()) { ++ struct tick_device *td = this_cpu_ptr(&tick_cpu_device); ++ + cpumask_clear_cpu(smp_processor_id(), tick_broadcast_force_mask); + tick_program_event(td->evtdev->next_event, 1); + } +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index 8aab7ed414907..11b7000d5e1d4 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -2476,7 +2476,7 @@ int do_adjtimex(struct __kernel_timex *txc) + clock_set |= timekeeping_advance(TK_ADV_FREQ); + + if (clock_set) +- clock_was_set(CLOCK_REALTIME); ++ clock_was_set(CLOCK_SET_WALL); + + ntp_notify_cmos_timer(); + +diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c +index a4dcf0f243521..3a56e7c8aa4f6 100644 +--- a/kernel/trace/tracing_map.c ++++ b/kernel/trace/tracing_map.c +@@ -454,7 +454,7 @@ static struct tracing_map_elt *get_free_elt(struct tracing_map *map) + struct tracing_map_elt *elt = NULL; + int idx; + +- idx = atomic_inc_return(&map->next_elt); ++ idx = atomic_fetch_add_unless(&map->next_elt, 1, map->max_elts); + if (idx < map->max_elts) { + elt = *(TRACING_MAP_ELT(map->elts, idx)); + if (map->ops && map->ops->elt_init) +@@ -699,7 +699,7 @@ void tracing_map_clear(struct tracing_map *map) + { + unsigned int i; + +- atomic_set(&map->next_elt, -1); ++ atomic_set(&map->next_elt, 0); + atomic64_set(&map->hits, 0); + atomic64_set(&map->drops, 0); + +@@ -783,7 +783,7 @@ struct tracing_map *tracing_map_create(unsigned int map_bits, + + map->map_bits = map_bits; + map->max_elts = (1 << map_bits); +- atomic_set(&map->next_elt, -1); ++ atomic_set(&map->next_elt, 0); + + map->map_size = (1 << (map_bits + 1)); + map->ops = ops; +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 79fbd6ddec49f..7ac2877e76629 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -601,6 +602,9 @@ static unsigned long __thp_get_unmapped_area(struct file *filp, + loff_t off_align = round_up(off, size); + unsigned long len_pad, ret; + ++ if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall()) ++ return 0; ++ + if (off_end <= off_align || (off_end - off_align) < size) + return 0; + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index a480affd475bf..fb7a531fce717 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -1769,13 +1769,6 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, + return; + } + +- /* +- * Move PageHWPoison flag from head page to the raw error pages, +- * which makes any healthy subpages reusable. +- */ +- if (unlikely(folio_test_hwpoison(folio))) +- folio_clear_hugetlb_hwpoison(folio); +- + /* + * If vmemmap pages were allocated above, then we need to clear the + * hugetlb destructor under the hugetlb lock. +@@ -1786,6 +1779,13 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, + spin_unlock_irq(&hugetlb_lock); + } + ++ /* ++ * Move PageHWPoison flag from head page to the raw error pages, ++ * which makes any healthy subpages reusable. ++ */ ++ if (unlikely(folio_test_hwpoison(folio))) ++ folio_clear_hugetlb_hwpoison(folio); ++ + /* + * Non-gigantic pages demoted from CMA allocated gigantic pages + * need to be given back to CMA in free_gigantic_folio. +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index dd854cc65fd9d..fd1b707f5de40 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5167,11 +5167,28 @@ static struct cftype mem_cgroup_legacy_files[] = { + + #define MEM_CGROUP_ID_MAX ((1UL << MEM_CGROUP_ID_SHIFT) - 1) + static DEFINE_IDR(mem_cgroup_idr); ++static DEFINE_SPINLOCK(memcg_idr_lock); ++ ++static int mem_cgroup_alloc_id(void) ++{ ++ int ret; ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock(&memcg_idr_lock); ++ ret = idr_alloc(&mem_cgroup_idr, NULL, 1, MEM_CGROUP_ID_MAX + 1, ++ GFP_NOWAIT); ++ spin_unlock(&memcg_idr_lock); ++ idr_preload_end(); ++ return ret; ++} + + static void mem_cgroup_id_remove(struct mem_cgroup *memcg) + { + if (memcg->id.id > 0) { ++ spin_lock(&memcg_idr_lock); + idr_remove(&mem_cgroup_idr, memcg->id.id); ++ spin_unlock(&memcg_idr_lock); ++ + memcg->id.id = 0; + } + } +@@ -5294,8 +5311,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void) + if (!memcg) + return ERR_PTR(error); + +- memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL, +- 1, MEM_CGROUP_ID_MAX + 1, GFP_KERNEL); ++ memcg->id.id = mem_cgroup_alloc_id(); + if (memcg->id.id < 0) { + error = memcg->id.id; + goto fail; +@@ -5430,7 +5446,9 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css) + * publish it here at the end of onlining. This matches the + * regular ID destruction during offlining. + */ ++ spin_lock(&memcg_idr_lock); + idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); ++ spin_unlock(&memcg_idr_lock); + + return 0; + offline_kmem: +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 6dab0c99c82c7..38fee34887d8a 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -2905,6 +2905,20 @@ static int hci_passive_scan_sync(struct hci_dev *hdev) + } else if (hci_is_adv_monitoring(hdev)) { + window = hdev->le_scan_window_adv_monitor; + interval = hdev->le_scan_int_adv_monitor; ++ ++ /* Disable duplicates filter when scanning for advertisement ++ * monitor for the following reasons. ++ * ++ * For HW pattern filtering (ex. MSFT), Realtek and Qualcomm ++ * controllers ignore RSSI_Sampling_Period when the duplicates ++ * filter is enabled. ++ * ++ * For SW pattern filtering, when we're not doing interleaved ++ * scanning, it is necessary to disable duplicates filter, ++ * otherwise hosts can only receive one advertisement and it's ++ * impossible to know if a peer is still in range. ++ */ ++ filter_dups = LE_SCAN_FILTER_DUP_DISABLE; + } else { + window = hdev->le_scan_window; + interval = hdev->le_scan_interval; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 1164c6d927281..2651cc2d5c283 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6775,6 +6775,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, + bt_cb(skb)->l2cap.psm = psm; + + if (!chan->ops->recv(chan, skb)) { ++ l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; + } +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 38373b4fb7ddf..c38244d60ff86 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -2044,16 +2044,14 @@ void br_multicast_del_port(struct net_bridge_port *port) + { + struct net_bridge *br = port->br; + struct net_bridge_port_group *pg; +- HLIST_HEAD(deleted_head); + struct hlist_node *n; + + /* Take care of the remaining groups, only perm ones should be left */ + spin_lock_bh(&br->multicast_lock); + hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) + br_multicast_find_del_pg(br, pg); +- hlist_move_list(&br->mcast_gc_list, &deleted_head); + spin_unlock_bh(&br->multicast_lock); +- br_multicast_gc(&deleted_head); ++ flush_work(&br->mcast_gc_work); + br_multicast_port_ctx_deinit(&port->multicast_ctx); + free_percpu(port->mcast_stats); + } +diff --git a/net/core/link_watch.c b/net/core/link_watch.c +index cb43f5aebfbcc..cf867f6e38bf1 100644 +--- a/net/core/link_watch.c ++++ b/net/core/link_watch.c +@@ -153,9 +153,9 @@ static void linkwatch_schedule_work(int urgent) + * override the existing timer. + */ + if (test_bit(LW_URGENT, &linkwatch_flags)) +- mod_delayed_work(system_wq, &linkwatch_work, 0); ++ mod_delayed_work(system_unbound_wq, &linkwatch_work, 0); + else +- schedule_delayed_work(&linkwatch_work, delay); ++ queue_delayed_work(system_unbound_wq, &linkwatch_work, delay); + } + + +diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c +index 8311c38267b55..69e6012ae82fb 100644 +--- a/net/ipv4/tcp_offload.c ++++ b/net/ipv4/tcp_offload.c +@@ -73,6 +73,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, + if (thlen < sizeof(*th)) + goto out; + ++ if (unlikely(skb_checksum_start(skb) != skb_transport_header(skb))) ++ goto out; ++ + if (!pskb_may_pull(skb, thlen)) + goto out; + +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index e5971890d637d..9cb13a50011ef 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -278,6 +278,10 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, + if (gso_skb->len <= sizeof(*uh) + mss) + return ERR_PTR(-EINVAL); + ++ if (unlikely(skb_checksum_start(gso_skb) != ++ skb_transport_header(gso_skb))) ++ return ERR_PTR(-EINVAL); ++ + if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) { + /* Packet is from an untrusted source, reset gso_segs. */ + skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh), +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index f97cb368e5a81..db8d0e1bf69ff 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1122,6 +1122,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, + from = rt ? rcu_dereference(rt->from) : NULL; + err = ip6_route_get_saddr(net, from, &fl6->daddr, + sk ? inet6_sk(sk)->srcprefs : 0, ++ fl6->flowi6_l3mdev, + &fl6->saddr); + rcu_read_unlock(); + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index eb3afaee62e8f..49ef5623c55e2 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -5678,7 +5678,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + goto nla_put_failure; + } else if (dest) { + struct in6_addr saddr_buf; +- if (ip6_route_get_saddr(net, rt, dest, 0, &saddr_buf) == 0 && ++ if (ip6_route_get_saddr(net, rt, dest, 0, 0, &saddr_buf) == 0 && + nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf)) + goto nla_put_failure; + } +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 8d21ff25f1602..70da78ab95202 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -88,6 +88,11 @@ + /* Default trace flags */ + #define L2TP_DEFAULT_DEBUG_FLAGS 0 + ++#define L2TP_DEPTH_NESTING 2 ++#if L2TP_DEPTH_NESTING == SINGLE_DEPTH_NESTING ++#error "L2TP requires its own lockdep subclass" ++#endif ++ + /* Private data stored for received packets in the skb. + */ + struct l2tp_skb_cb { +@@ -1041,7 +1046,13 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns + IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); + nf_reset_ct(skb); + +- bh_lock_sock_nested(sk); ++ /* L2TP uses its own lockdep subclass to avoid lockdep splats caused by ++ * nested socket calls on the same lockdep socket class. This can ++ * happen when data from a user socket is routed over l2tp, which uses ++ * another userspace socket. ++ */ ++ spin_lock_nested(&sk->sk_lock.slock, L2TP_DEPTH_NESTING); ++ + if (sock_owned_by_user(sk)) { + kfree_skb(skb); + ret = NET_XMIT_DROP; +@@ -1093,7 +1104,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns + ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl); + + out_unlock: +- bh_unlock_sock(sk); ++ spin_unlock(&sk->sk_lock.slock); + + return ret; + } +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index 85aafa94cc8ab..604724cca887f 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -958,7 +958,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, + + if (subflow->remote_key_valid && + (((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) || +- ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo))) { ++ ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && ++ (!mp_opt->echo || subflow->mp_join)))) { + /* subflows are fully established as soon as we get any + * additional ack, including ADD_ADDR. + */ +diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c +index d8da5374d9e13..cf70a376398be 100644 +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -427,6 +427,18 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc) + return mptcp_pm_nl_get_local_id(msk, &skc_local); + } + ++bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc) ++{ ++ struct mptcp_addr_info skc_local; ++ ++ mptcp_local_address((struct sock_common *)skc, &skc_local); ++ ++ if (mptcp_pm_is_userspace(msk)) ++ return mptcp_userspace_pm_is_backup(msk, &skc_local); ++ ++ return mptcp_pm_nl_is_backup(msk, &skc_local); ++} ++ + int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id, + u8 *flags, int *ifindex) + { +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index db621933b2035..2c49182c674f3 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -353,7 +353,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, + add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr); + + if (add_entry) { +- if (mptcp_pm_is_kernel(msk)) ++ if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk))) + return false; + + sk_reset_timer(sk, &add_entry->add_timer, +@@ -520,8 +520,8 @@ __lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info, + + static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + { ++ struct mptcp_pm_addr_entry *local, *signal_and_subflow = NULL; + struct sock *sk = (struct sock *)msk; +- struct mptcp_pm_addr_entry *local; + unsigned int add_addr_signal_max; + unsigned int local_addr_max; + struct pm_nl_pernet *pernet; +@@ -563,8 +563,6 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + + /* check first for announce */ + if (msk->pm.add_addr_signaled < add_addr_signal_max) { +- local = select_signal_address(pernet, msk); +- + /* due to racing events on both ends we can reach here while + * previous add address is still running: if we invoke now + * mptcp_pm_announce_addr(), that will fail and the +@@ -575,16 +573,26 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) + return; + +- if (local) { +- if (mptcp_pm_alloc_anno_list(msk, &local->addr)) { +- __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); +- msk->pm.add_addr_signaled++; +- mptcp_pm_announce_addr(msk, &local->addr, false); +- mptcp_pm_nl_addr_send_ack(msk); +- } +- } ++ local = select_signal_address(pernet, msk); ++ if (!local) ++ goto subflow; ++ ++ /* If the alloc fails, we are on memory pressure, not worth ++ * continuing, and trying to create subflows. ++ */ ++ if (!mptcp_pm_alloc_anno_list(msk, &local->addr)) ++ return; ++ ++ __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); ++ msk->pm.add_addr_signaled++; ++ mptcp_pm_announce_addr(msk, &local->addr, false); ++ mptcp_pm_nl_addr_send_ack(msk); ++ ++ if (local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) ++ signal_and_subflow = local; + } + ++subflow: + /* check if should create a new subflow */ + while (msk->pm.local_addr_used < local_addr_max && + msk->pm.subflows < subflows_max) { +@@ -592,9 +600,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + bool fullmesh; + int i, nr; + +- local = select_local_address(pernet, msk); +- if (!local) +- break; ++ if (signal_and_subflow) { ++ local = signal_and_subflow; ++ signal_and_subflow = NULL; ++ } else { ++ local = select_local_address(pernet, msk); ++ if (!local) ++ break; ++ } + + fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH); + +@@ -1109,6 +1122,24 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc + return ret; + } + ++bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc) ++{ ++ struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk); ++ struct mptcp_pm_addr_entry *entry; ++ bool backup = false; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { ++ if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) { ++ backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ return backup; ++} ++ + #define MPTCP_PM_CMD_GRP_OFFSET 0 + #define MPTCP_PM_EV_GRP_OFFSET 1 + +@@ -1341,8 +1372,8 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info) + if (ret < 0) + return ret; + +- if (addr.addr.port && !(addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) { +- GENL_SET_ERR_MSG(info, "flags must have signal when using port"); ++ if (addr.addr.port && !address_use_port(&addr)) { ++ GENL_SET_ERR_MSG(info, "flags must have signal and not subflow when using port"); + return -EINVAL; + } + +diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c +index f36f87a62dd0d..6738bad048cec 100644 +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -157,6 +157,24 @@ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, + return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true); + } + ++bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, ++ struct mptcp_addr_info *skc) ++{ ++ struct mptcp_pm_addr_entry *entry; ++ bool backup = false; ++ ++ spin_lock_bh(&msk->pm.lock); ++ list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { ++ if (mptcp_addresses_equal(&entry->addr, skc, false)) { ++ backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); ++ break; ++ } ++ } ++ spin_unlock_bh(&msk->pm.lock); ++ ++ return backup; ++} ++ + int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info) + { + struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index c28ac5dfd0b58..0201b1004a3b9 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -1032,6 +1032,9 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, + int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); + int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); + int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); ++bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc); ++bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); ++bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); + + static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow) + { +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index bc1efc1787720..927c2d5997dc7 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -100,6 +100,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) + return NULL; + } + subflow_req->local_id = local_id; ++ subflow_req->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)req); + + return msk; + } +@@ -601,6 +602,8 @@ static int subflow_chk_local_id(struct sock *sk) + return err; + + subflow_set_local_id(subflow, err); ++ subflow->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)sk); ++ + return 0; + } + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index dd044a47c8723..ea139fca74cb9 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -3743,6 +3743,15 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r + nf_tables_rule_destroy(ctx, rule); + } + ++/** nft_chain_validate - loop detection and hook validation ++ * ++ * @ctx: context containing call depth and base chain ++ * @chain: chain to validate ++ * ++ * Walk through the rules of the given chain and chase all jumps/gotos ++ * and set lookups until either the jump limit is hit or all reachable ++ * chains have been validated. ++ */ + int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain) + { + struct nft_expr *expr, *last; +@@ -3764,6 +3773,9 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain) + if (!expr->ops->validate) + continue; + ++ /* This may call nft_chain_validate() recursively, ++ * callers that do so must increment ctx->level. ++ */ + err = expr->ops->validate(ctx, expr, &data); + if (err < 0) + return err; +@@ -10621,146 +10633,6 @@ int nft_chain_validate_hooks(const struct nft_chain *chain, + } + EXPORT_SYMBOL_GPL(nft_chain_validate_hooks); + +-/* +- * Loop detection - walk through the ruleset beginning at the destination chain +- * of a new jump until either the source chain is reached (loop) or all +- * reachable chains have been traversed. +- * +- * The loop check is performed whenever a new jump verdict is added to an +- * expression or verdict map or a verdict map is bound to a new chain. +- */ +- +-static int nf_tables_check_loops(const struct nft_ctx *ctx, +- const struct nft_chain *chain); +- +-static int nft_check_loops(const struct nft_ctx *ctx, +- const struct nft_set_ext *ext) +-{ +- const struct nft_data *data; +- int ret; +- +- data = nft_set_ext_data(ext); +- switch (data->verdict.code) { +- case NFT_JUMP: +- case NFT_GOTO: +- ret = nf_tables_check_loops(ctx, data->verdict.chain); +- break; +- default: +- ret = 0; +- break; +- } +- +- return ret; +-} +- +-static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, +- struct nft_set *set, +- const struct nft_set_iter *iter, +- struct nft_set_elem *elem) +-{ +- const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); +- +- if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && +- *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END) +- return 0; +- +- return nft_check_loops(ctx, ext); +-} +- +-static int nft_set_catchall_loops(const struct nft_ctx *ctx, +- struct nft_set *set) +-{ +- u8 genmask = nft_genmask_next(ctx->net); +- struct nft_set_elem_catchall *catchall; +- struct nft_set_ext *ext; +- int ret = 0; +- +- list_for_each_entry_rcu(catchall, &set->catchall_list, list) { +- ext = nft_set_elem_ext(set, catchall->elem); +- if (!nft_set_elem_active(ext, genmask)) +- continue; +- +- ret = nft_check_loops(ctx, ext); +- if (ret < 0) +- return ret; +- } +- +- return ret; +-} +- +-static int nf_tables_check_loops(const struct nft_ctx *ctx, +- const struct nft_chain *chain) +-{ +- const struct nft_rule *rule; +- const struct nft_expr *expr, *last; +- struct nft_set *set; +- struct nft_set_binding *binding; +- struct nft_set_iter iter; +- +- if (ctx->chain == chain) +- return -ELOOP; +- +- if (fatal_signal_pending(current)) +- return -EINTR; +- +- list_for_each_entry(rule, &chain->rules, list) { +- nft_rule_for_each_expr(expr, last, rule) { +- struct nft_immediate_expr *priv; +- const struct nft_data *data; +- int err; +- +- if (strcmp(expr->ops->type->name, "immediate")) +- continue; +- +- priv = nft_expr_priv(expr); +- if (priv->dreg != NFT_REG_VERDICT) +- continue; +- +- data = &priv->data; +- switch (data->verdict.code) { +- case NFT_JUMP: +- case NFT_GOTO: +- err = nf_tables_check_loops(ctx, +- data->verdict.chain); +- if (err < 0) +- return err; +- break; +- default: +- break; +- } +- } +- } +- +- list_for_each_entry(set, &ctx->table->sets, list) { +- if (!nft_is_active_next(ctx->net, set)) +- continue; +- if (!(set->flags & NFT_SET_MAP) || +- set->dtype != NFT_DATA_VERDICT) +- continue; +- +- list_for_each_entry(binding, &set->bindings, list) { +- if (!(binding->flags & NFT_SET_MAP) || +- binding->chain != chain) +- continue; +- +- iter.genmask = nft_genmask_next(ctx->net); +- iter.skip = 0; +- iter.count = 0; +- iter.err = 0; +- iter.fn = nf_tables_loop_check_setelem; +- +- set->ops->walk(ctx, set, &iter); +- if (!iter.err) +- iter.err = nft_set_catchall_loops(ctx, set); +- +- if (iter.err < 0) +- return iter.err; +- } +- } +- +- return 0; +-} +- + /** + * nft_parse_u32_check - fetch u32 attribute and check for maximum value + * +@@ -10873,7 +10745,7 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + if (data != NULL && + (data->verdict.code == NFT_GOTO || + data->verdict.code == NFT_JUMP)) { +- err = nf_tables_check_loops(ctx, data->verdict.chain); ++ err = nft_chain_validate(ctx, data->verdict.chain); + if (err < 0) + return err; + } +diff --git a/net/sctp/input.c b/net/sctp/input.c +index 17fcaa9b0df94..a8a254a5008e5 100644 +--- a/net/sctp/input.c ++++ b/net/sctp/input.c +@@ -735,15 +735,19 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep) + struct sock *sk = ep->base.sk; + struct net *net = sock_net(sk); + struct sctp_hashbucket *head; ++ int err = 0; + + ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port); + head = &sctp_ep_hashtable[ep->hashent]; + ++ write_lock(&head->lock); + if (sk->sk_reuseport) { + bool any = sctp_is_ep_boundall(sk); + struct sctp_endpoint *ep2; + struct list_head *list; +- int cnt = 0, err = 1; ++ int cnt = 0; ++ ++ err = 1; + + list_for_each(list, &ep->base.bind_addr.address_list) + cnt++; +@@ -761,24 +765,24 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep) + if (!err) { + err = reuseport_add_sock(sk, sk2, any); + if (err) +- return err; ++ goto out; + break; + } else if (err < 0) { +- return err; ++ goto out; + } + } + + if (err) { + err = reuseport_alloc(sk, any); + if (err) +- return err; ++ goto out; + } + } + +- write_lock(&head->lock); + hlist_add_head(&ep->node, &head->chain); ++out: + write_unlock(&head->lock); +- return 0; ++ return err; + } + + /* Add an endpoint to the hash. Local BH-safe. */ +@@ -803,10 +807,9 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) + + head = &sctp_ep_hashtable[ep->hashent]; + ++ write_lock(&head->lock); + if (rcu_access_pointer(sk->sk_reuseport_cb)) + reuseport_detach_sock(sk); +- +- write_lock(&head->lock); + hlist_del_init(&ep->node); + write_unlock(&head->lock); + } +diff --git a/net/smc/smc_stats.h b/net/smc/smc_stats.h +index 9d32058db2b5d..e19177ce40923 100644 +--- a/net/smc/smc_stats.h ++++ b/net/smc/smc_stats.h +@@ -19,7 +19,7 @@ + + #include "smc_clc.h" + +-#define SMC_MAX_FBACK_RSN_CNT 30 ++#define SMC_MAX_FBACK_RSN_CNT 36 + + enum { + SMC_BUF_8K, +diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c +index 6debf4fd42d4e..cef623ea15060 100644 +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -369,8 +369,10 @@ static void rpc_make_runnable(struct workqueue_struct *wq, + if (RPC_IS_ASYNC(task)) { + INIT_WORK(&task->u.tk_work, rpc_async_schedule); + queue_work(wq, &task->u.tk_work); +- } else ++ } else { ++ smp_mb__after_atomic(); + wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED); ++ } + } + + /* +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index a551be47cb6c6..b7f62442d8268 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1483,6 +1483,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + struct unix_sock *u = unix_sk(sk), *newu, *otheru; + struct net *net = sock_net(sk); + struct sk_buff *skb = NULL; ++ unsigned char state; + long timeo; + int err; + +@@ -1529,7 +1530,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + goto out; + } + +- /* Latch state of peer */ + unix_state_lock(other); + + /* Apparently VFS overslept socket death. Retry. */ +@@ -1559,37 +1559,21 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + goto restart; + } + +- /* Latch our state. +- +- It is tricky place. We need to grab our state lock and cannot +- drop lock on peer. It is dangerous because deadlock is +- possible. Connect to self case and simultaneous +- attempt to connect are eliminated by checking socket +- state. other is TCP_LISTEN, if sk is TCP_LISTEN we +- check this before attempt to grab lock. +- +- Well, and we have to recheck the state after socket locked. ++ /* self connect and simultaneous connect are eliminated ++ * by rejecting TCP_LISTEN socket to avoid deadlock. + */ +- switch (READ_ONCE(sk->sk_state)) { +- case TCP_CLOSE: +- /* This is ok... continue with connect */ +- break; +- case TCP_ESTABLISHED: +- /* Socket is already connected */ +- err = -EISCONN; +- goto out_unlock; +- default: +- err = -EINVAL; ++ state = READ_ONCE(sk->sk_state); ++ if (unlikely(state != TCP_CLOSE)) { ++ err = state == TCP_ESTABLISHED ? -EISCONN : -EINVAL; + goto out_unlock; + } + + unix_state_lock_nested(sk, U_LOCK_SECOND); + +- if (sk->sk_state != TCP_CLOSE) { ++ if (unlikely(sk->sk_state != TCP_CLOSE)) { ++ err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EINVAL; + unix_state_unlock(sk); +- unix_state_unlock(other); +- sock_put(other); +- goto restart; ++ goto out_unlock; + } + + err = security_unix_stream_connect(sk, other, newsk); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 8f8f077e6cd40..be5c42d6ffbea 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3398,6 +3398,33 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, + if (chandef.chan != cur_chan) + return -EBUSY; + ++ /* only allow this for regular channel widths */ ++ switch (wdev->links[link_id].ap.chandef.width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_160: ++ case NL80211_CHAN_WIDTH_320: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (chandef.width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_160: ++ case NL80211_CHAN_WIDTH_320: ++ break; ++ default: ++ return -EINVAL; ++ } ++ + result = rdev_set_ap_chanwidth(rdev, dev, link_id, + &chandef); + if (result) +@@ -4446,10 +4473,7 @@ static void get_key_callback(void *c, struct key_params *params) + struct nlattr *key; + struct get_key_cookie *cookie = c; + +- if ((params->key && +- nla_put(cookie->msg, NL80211_ATTR_KEY_DATA, +- params->key_len, params->key)) || +- (params->seq && ++ if ((params->seq && + nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ, + params->seq_len, params->seq)) || + (params->cipher && +@@ -4461,10 +4485,7 @@ static void get_key_callback(void *c, struct key_params *params) + if (!key) + goto nla_put_failure; + +- if ((params->key && +- nla_put(cookie->msg, NL80211_KEY_DATA, +- params->key_len, params->key)) || +- (params->seq && ++ if ((params->seq && + nla_put(cookie->msg, NL80211_KEY_SEQ, + params->seq_len, params->seq)) || + (params->cipher && +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 038db8902c9ed..82c0d3a3327ab 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1989,6 +1989,8 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + } + + static const struct snd_pci_quirk force_connect_list[] = { ++ SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1), ++ SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1), + SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), + SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), + SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0b33a00771450..82dcea2b78000 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10360,6 +10360,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC295_FIXUP_CHROME_BOOK), + SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + + #if 0 + /* Below is a quirk table taken from the old code. +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index 36dddf230c2c4..d597e59863ee3 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -409,6 +409,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_BOARD_NAME, "8A43"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), ++ DMI_MATCH(DMI_BOARD_NAME, "8A44"), ++ } ++ }, + { + .driver_data = &acp6x_card, + .matches = { +diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c +index a1f04010da95f..132c1d24f8f6e 100644 +--- a/sound/soc/codecs/wcd938x-sdw.c ++++ b/sound/soc/codecs/wcd938x-sdw.c +@@ -1252,12 +1252,12 @@ static int wcd9380_probe(struct sdw_slave *pdev, + pdev->prop.lane_control_support = true; + pdev->prop.simple_clk_stop_capable = true; + if (wcd->is_tx) { +- pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0); ++ pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS - 1, 0); + pdev->prop.src_dpn_prop = wcd938x_dpn_prop; + wcd->ch_info = &wcd938x_sdw_tx_ch_info[0]; + pdev->prop.wake_capable = true; + } else { +- pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0); ++ pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS - 1, 0); + pdev->prop.sink_dpn_prop = wcd938x_dpn_prop; + wcd->ch_info = &wcd938x_sdw_rx_ch_info[0]; + } +diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c +index 1253695bebd86..53b828f681020 100644 +--- a/sound/soc/codecs/wsa881x.c ++++ b/sound/soc/codecs/wsa881x.c +@@ -1152,7 +1152,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, + wsa881x->sconfig.frame_rate = 48000; + wsa881x->sconfig.direction = SDW_DATA_DIR_RX; + wsa881x->sconfig.type = SDW_STREAM_PDM; +- pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); ++ pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS - 1, 0); + pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; + pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + pdev->prop.clk_stop_mode1 = true; +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +index a2e86ef7d18f5..2169d93989841 100644 +--- a/sound/soc/codecs/wsa883x.c ++++ b/sound/soc/codecs/wsa883x.c +@@ -1399,7 +1399,15 @@ static int wsa883x_probe(struct sdw_slave *pdev, + wsa883x->sconfig.direction = SDW_DATA_DIR_RX; + wsa883x->sconfig.type = SDW_STREAM_PDM; + +- pdev->prop.sink_ports = GENMASK(WSA883X_MAX_SWR_PORTS, 0); ++ /** ++ * Port map index starts with 0, however the data port for this codec ++ * are from index 1 ++ */ ++ if (of_property_read_u32_array(dev->of_node, "qcom,port-mapping", &pdev->m_port_map[1], ++ WSA883X_MAX_SWR_PORTS)) ++ dev_dbg(dev, "Static Port mapping not specified\n"); ++ ++ pdev->prop.sink_ports = GENMASK(WSA883X_MAX_SWR_PORTS - 1, 0); + pdev->prop.simple_clk_stop_capable = true; + pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; + pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; +diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c +index 993d76b18b536..1cd52fab7b40d 100644 +--- a/sound/soc/codecs/wsa884x.c ++++ b/sound/soc/codecs/wsa884x.c +@@ -1858,7 +1858,15 @@ static int wsa884x_probe(struct sdw_slave *pdev, + wsa884x->sconfig.direction = SDW_DATA_DIR_RX; + wsa884x->sconfig.type = SDW_STREAM_PDM; + +- pdev->prop.sink_ports = GENMASK(WSA884X_MAX_SWR_PORTS, 0); ++ /** ++ * Port map index starts with 0, however the data port for this codec ++ * are from index 1 ++ */ ++ if (of_property_read_u32_array(dev->of_node, "qcom,port-mapping", &pdev->m_port_map[1], ++ WSA884X_MAX_SWR_PORTS)) ++ dev_dbg(dev, "Static Port mapping not specified\n"); ++ ++ pdev->prop.sink_ports = GENMASK(WSA884X_MAX_SWR_PORTS - 1, 0); + pdev->prop.simple_clk_stop_capable = true; + pdev->prop.sink_dpn_prop = wsa884x_sink_dpn_prop; + pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; +diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c +index 94b169a5493b5..5218e40aeb1bb 100644 +--- a/sound/soc/meson/axg-fifo.c ++++ b/sound/soc/meson/axg-fifo.c +@@ -207,25 +207,18 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) + status = FIELD_GET(STATUS1_INT_STS, status); + axg_fifo_ack_irq(fifo, status); + +- /* Use the thread to call period elapsed on nonatomic links */ +- if (status & FIFO_INT_COUNT_REPEAT) +- return IRQ_WAKE_THREAD; ++ if (status & ~FIFO_INT_COUNT_REPEAT) ++ dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", ++ status); + +- dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", +- status); ++ if (status & FIFO_INT_COUNT_REPEAT) { ++ snd_pcm_period_elapsed(ss); ++ return IRQ_HANDLED; ++ } + + return IRQ_NONE; + } + +-static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id) +-{ +- struct snd_pcm_substream *ss = dev_id; +- +- snd_pcm_period_elapsed(ss); +- +- return IRQ_HANDLED; +-} +- + int axg_fifo_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *ss) + { +@@ -251,8 +244,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, + if (ret) + return ret; + +- ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block, +- axg_fifo_pcm_irq_block_thread, ++ /* Use the threaded irq handler only with non-atomic links */ ++ ret = request_threaded_irq(fifo->irq, NULL, ++ axg_fifo_pcm_irq_block, + IRQF_ONESHOT, dev_name(dev), ss); + if (ret) + return ret; +diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c +index 7d6a568556ea4..b5b4ea854da4b 100644 +--- a/sound/soc/sof/mediatek/mt8195/mt8195.c ++++ b/sound/soc/sof/mediatek/mt8195/mt8195.c +@@ -624,7 +624,7 @@ static struct snd_sof_dsp_ops sof_mt8195_ops = { + static struct snd_sof_of_mach sof_mt8195_machs[] = { + { + .compatible = "google,tomato", +- .sof_tplg_filename = "sof-mt8195-mt6359-rt1019-rt5682-dts.tplg" ++ .sof_tplg_filename = "sof-mt8195-mt6359-rt1019-rt5682.tplg" + }, { + .compatible = "mediatek,mt8195", + .sof_tplg_filename = "sof-mt8195.tplg" +diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c +index 2c21a86421e66..cc9a8122b9bc2 100644 +--- a/sound/soc/sti/sti_uniperif.c ++++ b/sound/soc/sti/sti_uniperif.c +@@ -352,7 +352,7 @@ static int sti_uniperiph_resume(struct snd_soc_component *component) + return ret; + } + +-static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai) ++int sti_uniperiph_dai_probe(struct snd_soc_dai *dai) + { + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); + struct sti_uniperiph_dai *dai_data = &priv->dai_data; +diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h +index 2a5de328501c1..74e51f0ff85c8 100644 +--- a/sound/soc/sti/uniperif.h ++++ b/sound/soc/sti/uniperif.h +@@ -1380,6 +1380,7 @@ int uni_reader_init(struct platform_device *pdev, + struct uniperif *reader); + + /* common */ ++int sti_uniperiph_dai_probe(struct snd_soc_dai *dai); + int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt); + +diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c +index dd9013c476649..6d1ce030963c6 100644 +--- a/sound/soc/sti/uniperif_player.c ++++ b/sound/soc/sti/uniperif_player.c +@@ -1038,6 +1038,7 @@ static const struct snd_soc_dai_ops uni_player_dai_ops = { + .startup = uni_player_startup, + .shutdown = uni_player_shutdown, + .prepare = uni_player_prepare, ++ .probe = sti_uniperiph_dai_probe, + .trigger = uni_player_trigger, + .hw_params = sti_uniperiph_dai_hw_params, + .set_fmt = sti_uniperiph_dai_set_fmt, +diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c +index 065c5f0d1f5f0..05ea2b794eb92 100644 +--- a/sound/soc/sti/uniperif_reader.c ++++ b/sound/soc/sti/uniperif_reader.c +@@ -401,6 +401,7 @@ static const struct snd_soc_dai_ops uni_reader_dai_ops = { + .startup = uni_reader_startup, + .shutdown = uni_reader_shutdown, + .prepare = uni_reader_prepare, ++ .probe = sti_uniperiph_dai_probe, + .trigger = uni_reader_trigger, + .hw_params = sti_uniperiph_dai_hw_params, + .set_fmt = sti_uniperiph_dai_set_fmt, +diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c +index f4437015d43a7..9df49a880b750 100644 +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -286,12 +286,14 @@ static void line6_data_received(struct urb *urb) + { + struct usb_line6 *line6 = (struct usb_line6 *)urb->context; + struct midi_buffer *mb = &line6->line6midi->midibuf_in; ++ unsigned long flags; + int done; + + if (urb->status == -ESHUTDOWN) + return; + + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { ++ spin_lock_irqsave(&line6->line6midi->lock, flags); + done = + line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + +@@ -300,12 +302,15 @@ static void line6_data_received(struct urb *urb) + dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", + done, urb->actual_length); + } ++ spin_unlock_irqrestore(&line6->line6midi->lock, flags); + + for (;;) { ++ spin_lock_irqsave(&line6->line6midi->lock, flags); + done = + line6_midibuf_read(mb, line6->buffer_message, + LINE6_MIDI_MESSAGE_MAXLEN, + LINE6_MIDIBUF_READ_RX); ++ spin_unlock_irqrestore(&line6->line6midi->lock, flags); + + if (done <= 0) + break; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 5d72dc8441cbb..af1b8cf5a9883 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -2594,6 +2594,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + ++/* Stanton ScratchAmp */ ++{ USB_DEVICE(0x103d, 0x0100) }, ++{ USB_DEVICE(0x103d, 0x0101) }, ++ + /* Novation EMS devices */ + { + USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), +diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h +index 5f6f84837a490..329d41f8c9237 100644 +--- a/tools/arch/arm64/include/asm/cputype.h ++++ b/tools/arch/arm64/include/asm/cputype.h +@@ -84,6 +84,9 @@ + #define ARM_CPU_PART_CORTEX_X2 0xD48 + #define ARM_CPU_PART_NEOVERSE_N2 0xD49 + #define ARM_CPU_PART_CORTEX_A78C 0xD4B ++#define ARM_CPU_PART_NEOVERSE_V2 0xD4F ++#define ARM_CPU_PART_CORTEX_X4 0xD82 ++#define ARM_CPU_PART_NEOVERSE_V3 0xD84 + + #define APM_CPU_PART_POTENZA 0x000 + +@@ -153,6 +156,9 @@ + #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) + #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) + #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) ++#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2) ++#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4) ++#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) +diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c +index b15b343ebb6b1..9adcda7f1fedc 100644 +--- a/tools/testing/selftests/bpf/prog_tests/send_signal.c ++++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c +@@ -156,7 +156,8 @@ static void test_send_signal_tracepoint(bool signal_thread) + static void test_send_signal_perf(bool signal_thread) + { + struct perf_event_attr attr = { +- .sample_period = 1, ++ .freq = 1, ++ .sample_freq = 1000, + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + }; +diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile +index 292359a542429..8b2b9bb8bad10 100644 +--- a/tools/testing/selftests/mm/Makefile ++++ b/tools/testing/selftests/mm/Makefile +@@ -101,7 +101,7 @@ endif + + endif + +-ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64)) ++ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64 s390)) + TEST_GEN_FILES += va_high_addr_switch + TEST_GEN_FILES += virtual_address_range + TEST_GEN_FILES += write_to_hugetlbfs +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index a2dae2a3a93e0..b16b8278c4cea 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -812,7 +812,7 @@ pm_nl_check_endpoint() + done + + if [ -z "$id" ]; then +- test_fail "bad test - missing endpoint id" ++ fail_test "bad test - missing endpoint id" + return + fi + +@@ -1559,18 +1559,28 @@ chk_add_nr() + local add_nr=$1 + local echo_nr=$2 + local port_nr=${3:-0} +- local syn_nr=${4:-$port_nr} +- local syn_ack_nr=${5:-$port_nr} +- local ack_nr=${6:-$port_nr} +- local mis_syn_nr=${7:-0} +- local mis_ack_nr=${8:-0} ++ local ns_invert=${4:-""} ++ local syn_nr=$port_nr ++ local syn_ack_nr=$port_nr ++ local ack_nr=$port_nr ++ local mis_syn_nr=0 ++ local mis_ack_nr=0 ++ local ns_tx=$ns1 ++ local ns_rx=$ns2 ++ local extra_msg="" + local count + local timeout + +- timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout) ++ if [[ $ns_invert = "invert" ]]; then ++ ns_tx=$ns2 ++ ns_rx=$ns1 ++ extra_msg="invert" ++ fi ++ ++ timeout=$(ip netns exec ${ns_tx} sysctl -n net.mptcp.add_addr_timeout) + + print_check "add" +- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr") + if [ -z "$count" ]; then + print_skip + # if the test configured a short timeout tolerate greater then expected +@@ -1582,7 +1592,7 @@ chk_add_nr() + fi + + print_check "echo" +- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$echo_nr" ]; then +@@ -1593,7 +1603,7 @@ chk_add_nr() + + if [ $port_nr -gt 0 ]; then + print_check "pt" +- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$port_nr" ]; then +@@ -1603,7 +1613,7 @@ chk_add_nr() + fi + + print_check "syn" +- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_nr" ]; then +@@ -1614,7 +1624,7 @@ chk_add_nr() + fi + + print_check "synack" +- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_ack_nr" ]; then +@@ -1625,7 +1635,7 @@ chk_add_nr() + fi + + print_check "ack" +- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$ack_nr" ]; then +@@ -1636,7 +1646,7 @@ chk_add_nr() + fi + + print_check "syn" +- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mis_syn_nr" ]; then +@@ -1647,7 +1657,7 @@ chk_add_nr() + fi + + print_check "ack" +- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mis_ack_nr" ]; then +@@ -1657,6 +1667,8 @@ chk_add_nr() + print_ok + fi + fi ++ ++ print_info "$extra_msg" + } + + chk_add_tx_nr() +@@ -2121,6 +2133,21 @@ signal_address_tests() + chk_add_nr 1 1 + fi + ++ # uncommon: subflow and signal flags on the same endpoint ++ # or because the user wrongly picked both, but still expects the client ++ # to create additional subflows ++ if reset "subflow and signal together"; then ++ pm_nl_set_limits $ns1 0 2 ++ pm_nl_set_limits $ns2 0 2 ++ pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow ++ run_tests $ns1 $ns2 10.0.1.1 ++ chk_join_nr 1 1 1 ++ chk_add_nr 1 1 0 invert # only initiated by ns2 ++ chk_add_nr 0 0 0 # none initiated by ns1 ++ chk_rst_nr 0 0 invert # no RST sent by the client ++ chk_rst_nr 0 0 # no RST sent by the server ++ fi ++ + # accept and use add_addr with additional subflows + if reset "multiple subflows and signal"; then + pm_nl_set_limits $ns1 0 3 +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index be97a7ed09503..f24bd2bf08311 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -262,7 +262,7 @@ run_test() + do_transfer $small $large $time + lret=$? + mptcp_lib_result_code "${lret}" "${msg}" +- if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then ++ if [ $lret -ne 0 ]; then + ret=$lret + [ $bail -eq 0 ] || exit $ret + fi +@@ -272,7 +272,7 @@ run_test() + do_transfer $large $small $time + lret=$? + mptcp_lib_result_code "${lret}" "${msg}" +- if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then ++ if [ $lret -ne 0 ]; then + ret=$lret + [ $bail -eq 0 ] || exit $ret + fi +@@ -305,7 +305,7 @@ run_test 10 10 0 0 "balanced bwidth" + run_test 10 10 1 25 "balanced bwidth with unbalanced delay" + + # we still need some additional infrastructure to pass the following test-cases +-MPTCP_LIB_SUBTEST_FLAKY=1 run_test 10 3 0 0 "unbalanced bwidth" ++run_test 10 3 0 0 "unbalanced bwidth" + run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay" + run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay" + +diff --git a/tools/testing/selftests/rcutorture/bin/torture.sh b/tools/testing/selftests/rcutorture/bin/torture.sh +index 12b50a4a881ac..89a82f6f140ef 100755 +--- a/tools/testing/selftests/rcutorture/bin/torture.sh ++++ b/tools/testing/selftests/rcutorture/bin/torture.sh +@@ -567,7 +567,7 @@ then + torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog" + torture_set "clocksourcewd-1" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make + +- torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 clocksource.max_cswd_read_retries=1 tsc=watchdog" ++ torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog" + torture_set "clocksourcewd-2" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make + + # In case our work is already done... diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.46-47.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.46-47.patch new file mode 100644 index 0000000000..830bd4b9a0 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.46-47.patch @@ -0,0 +1,4211 @@ +diff --git a/Documentation/bpf/map_lpm_trie.rst b/Documentation/bpf/map_lpm_trie.rst +index 74d64a30f50073..f9cd579496c9ce 100644 +--- a/Documentation/bpf/map_lpm_trie.rst ++++ b/Documentation/bpf/map_lpm_trie.rst +@@ -17,7 +17,7 @@ significant byte. + + LPM tries may be created with a maximum prefix length that is a multiple + of 8, in the range from 8 to 2048. The key used for lookup and update +-operations is a ``struct bpf_lpm_trie_key``, extended by ++operations is a ``struct bpf_lpm_trie_key_u8``, extended by + ``max_prefixlen/8`` bytes. + + - For IPv4 addresses the data length is 4 bytes +diff --git a/Documentation/mm/page_table_check.rst b/Documentation/mm/page_table_check.rst +index c12838ce6b8de2..c59f22eb6a0f9a 100644 +--- a/Documentation/mm/page_table_check.rst ++++ b/Documentation/mm/page_table_check.rst +@@ -14,7 +14,7 @@ Page table check performs extra verifications at the time when new pages become + accessible from the userspace by getting their page table entries (PTEs PMDs + etc.) added into the table. + +-In case of detected corruption, the kernel is crashed. There is a small ++In case of most detected corruption, the kernel is crashed. There is a small + performance and memory overhead associated with the page table check. Therefore, + it is disabled by default, but can be optionally enabled on systems where the + extra hardening outweighs the performance costs. Also, because page table check +@@ -22,6 +22,13 @@ is synchronous, it can help with debugging double map memory corruption issues, + by crashing kernel at the time wrong mapping occurs instead of later which is + often the case with memory corruptions bugs. + ++It can also be used to do page table entry checks over various flags, dump ++warnings when illegal combinations of entry flags are detected. Currently, ++userfaultfd is the only user of such to sanity check wr-protect bit against ++any writable flags. Illegal flag combinations will not directly cause data ++corruption in this case immediately, but that will cause read-only data to ++be writable, leading to corrupt when the page content is later modified. ++ + Double mapping detection logic + ============================== + +diff --git a/Makefile b/Makefile +index 77de99984c2f18..6b967e135c80f0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 46 ++SUBLEVEL = 47 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index 15aa9bad1c280b..ca0bf0b92ca09e 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -523,7 +523,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx, + + kvm_clear_pte(ctx->ptep); + dsb(ishst); +- __tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), ctx->level); ++ __tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), 0); + } else { + if (ctx->end - ctx->addr < granule) + return -EINVAL; +@@ -861,9 +861,13 @@ static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx, + if (kvm_pte_valid(ctx->old)) { + kvm_clear_pte(ctx->ptep); + +- if (!stage2_unmap_defer_tlb_flush(pgt)) +- kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, +- ctx->addr, ctx->level); ++ if (kvm_pte_table(ctx->old, ctx->level)) { ++ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ++ 0); ++ } else if (!stage2_unmap_defer_tlb_flush(pgt)) { ++ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ++ ctx->level); ++ } + } + + mm_ops->put_page(ctx->ptep); +diff --git a/arch/loongarch/include/uapi/asm/unistd.h b/arch/loongarch/include/uapi/asm/unistd.h +index fcb668984f0336..b344b1f917153b 100644 +--- a/arch/loongarch/include/uapi/asm/unistd.h ++++ b/arch/loongarch/include/uapi/asm/unistd.h +@@ -1,4 +1,5 @@ + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#define __ARCH_WANT_NEW_STAT + #define __ARCH_WANT_SYS_CLONE + #define __ARCH_WANT_SYS_CLONE3 + +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index e02b179ec65989..d03fe4fb41f43c 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -387,23 +387,7 @@ static inline pte_t pte_wrprotect(pte_t pte) + #ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP + static inline int pte_uffd_wp(pte_t pte) + { +- bool wp = pte_flags(pte) & _PAGE_UFFD_WP; +- +-#ifdef CONFIG_DEBUG_VM +- /* +- * Having write bit for wr-protect-marked present ptes is fatal, +- * because it means the uffd-wp bit will be ignored and write will +- * just go through. +- * +- * Use any chance of pgtable walking to verify this (e.g., when +- * page swapped out or being migrated for all purposes). It means +- * something is already wrong. Tell the admin even before the +- * process crashes. We also nail it with wrong pgtable setup. +- */ +- WARN_ON_ONCE(wp && pte_write(pte)); +-#endif +- +- return wp; ++ return pte_flags(pte) & _PAGE_UFFD_WP; + } + + static inline pte_t pte_mkuffd_wp(pte_t pte) +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 77dbd516a05463..277bf0e8ed0918 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -941,8 +941,19 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) + &sense_key, &asc, &ascq); + ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq); + } else { +- /* ATA PASS-THROUGH INFORMATION AVAILABLE */ +- ata_scsi_set_sense(qc->dev, cmd, RECOVERED_ERROR, 0, 0x1D); ++ /* ++ * ATA PASS-THROUGH INFORMATION AVAILABLE ++ * ++ * Note: we are supposed to call ata_scsi_set_sense(), which ++ * respects the D_SENSE bit, instead of unconditionally ++ * generating the sense data in descriptor format. However, ++ * because hdparm, hddtemp, and udisks incorrectly assume sense ++ * data in descriptor format, without even looking at the ++ * RESPONSE CODE field in the returned sense data (to see which ++ * format the returned sense data is in), we are stuck with ++ * being bug compatible with older kernels. ++ */ ++ scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D); + } + } + +diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c +index 2776ca5fc33f39..b215b28cad7b76 100644 +--- a/drivers/isdn/mISDN/socket.c ++++ b/drivers/isdn/mISDN/socket.c +@@ -401,23 +401,23 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) + } + + static int data_sock_setsockopt(struct socket *sock, int level, int optname, +- sockptr_t optval, unsigned int len) ++ sockptr_t optval, unsigned int optlen) + { + struct sock *sk = sock->sk; + int err = 0, opt = 0; + + if (*debug & DEBUG_SOCKET) + printk(KERN_DEBUG "%s(%p, %d, %x, optval, %d)\n", __func__, sock, +- level, optname, len); ++ level, optname, optlen); + + lock_sock(sk); + + switch (optname) { + case MISDN_TIME_STAMP: +- if (copy_from_sockptr(&opt, optval, sizeof(int))) { +- err = -EFAULT; ++ err = copy_safe_from_sockptr(&opt, sizeof(opt), ++ optval, optlen); ++ if (err) + break; +- } + + if (opt) + _pms(sk)->cmask |= MISDN_TIME_STAMP; +diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c +index 22d83ac18eb735..fbf58012becdf2 100644 +--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c +@@ -23,40 +23,11 @@ static int dvb_usb_force_pid_filter_usage; + module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); + MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); + +-static int dvb_usb_check_bulk_endpoint(struct dvb_usb_device *d, u8 endpoint) +-{ +- if (endpoint) { +- int ret; +- +- ret = usb_pipe_type_check(d->udev, usb_sndbulkpipe(d->udev, endpoint)); +- if (ret) +- return ret; +- ret = usb_pipe_type_check(d->udev, usb_rcvbulkpipe(d->udev, endpoint)); +- if (ret) +- return ret; +- } +- return 0; +-} +- +-static void dvb_usb_clear_halt(struct dvb_usb_device *d, u8 endpoint) +-{ +- if (endpoint) { +- usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, endpoint)); +- usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, endpoint)); +- } +-} +- + static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) + { + struct dvb_usb_adapter *adap; + int ret, n, o; + +- ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint); +- if (ret) +- return ret; +- ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint_response); +- if (ret) +- return ret; + for (n = 0; n < d->props.num_adapters; n++) { + adap = &d->adapter[n]; + adap->dev = d; +@@ -132,8 +103,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) + * when reloading the driver w/o replugging the device + * sometimes a timeout occurs, this helps + */ +- dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint); +- dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint_response); ++ if (d->props.generic_bulk_ctrl_endpoint != 0) { ++ usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); ++ usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); ++ } + + return 0; + +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index ba8b6bd8233cad..96cca4ee470a4b 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -1007,26 +1007,21 @@ static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, + struct sk_buff *skb; + int error = 0; + +- if (sk->sk_state & PPPOX_BOUND) { +- error = -EIO; +- goto end; +- } ++ if (sk->sk_state & PPPOX_BOUND) ++ return -EIO; + + skb = skb_recv_datagram(sk, flags, &error); +- if (error < 0) +- goto end; ++ if (!skb) ++ return error; + +- if (skb) { +- total_len = min_t(size_t, total_len, skb->len); +- error = skb_copy_datagram_msg(skb, 0, m, total_len); +- if (error == 0) { +- consume_skb(skb); +- return total_len; +- } ++ total_len = min_t(size_t, total_len, skb->len); ++ error = skb_copy_datagram_msg(skb, 0, m, total_len); ++ if (error == 0) { ++ consume_skb(skb); ++ return total_len; + } + + kfree_skb(skb); +-end: + return error; + } + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 0fc7aa78b2e5b9..2c3f55877a1134 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2931,6 +2931,13 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev) + return NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND; + } + ++ /* ++ * NVMe SSD drops off the PCIe bus after system idle ++ * for 10 hours on a Lenovo N60z board. ++ */ ++ if (dmi_match(DMI_BOARD_NAME, "LXKT-ZXEG-N6")) ++ return NVME_QUIRK_NO_APST; ++ + return 0; + } + +diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c +index c26545d71d39a3..cd6d5bbb4b9df5 100644 +--- a/fs/binfmt_flat.c ++++ b/fs/binfmt_flat.c +@@ -72,8 +72,10 @@ + + #ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET + #define DATA_START_OFFSET_WORDS (0) ++#define MAX_SHARED_LIBS_UPDATE (0) + #else + #define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS) ++#define MAX_SHARED_LIBS_UPDATE (MAX_SHARED_LIBS) + #endif + + struct lib_info { +@@ -880,7 +882,7 @@ static int load_flat_binary(struct linux_binprm *bprm) + return res; + + /* Update data segment pointers for all libraries */ +- for (i = 0; i < MAX_SHARED_LIBS; i++) { ++ for (i = 0; i < MAX_SHARED_LIBS_UPDATE; i++) { + if (!libinfo.lib_list[i].loaded) + continue; + for (j = 0; j < MAX_SHARED_LIBS; j++) { +diff --git a/fs/buffer.c b/fs/buffer.c +index 12e9a71c693d74..ecd8b47507ff80 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2179,6 +2179,8 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to) + struct buffer_head *bh, *head; + + bh = head = folio_buffers(folio); ++ if (!bh) ++ return; + blocksize = bh->b_size; + + block_start = 0; +diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c +index 5ee7d7bbb361ce..2fbf97077ce910 100644 +--- a/fs/cramfs/inode.c ++++ b/fs/cramfs/inode.c +@@ -495,7 +495,7 @@ static void cramfs_kill_sb(struct super_block *sb) + sb->s_mtd = NULL; + } else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV) && sb->s_bdev) { + sync_blockdev(sb->s_bdev); +- blkdev_put(sb->s_bdev, sb); ++ bdev_release(sb->s_bdev_handle); + } + kfree(sbi); + } +diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c +index d36b3963c0bf3c..aa59788a61e6e4 100644 +--- a/fs/erofs/decompressor.c ++++ b/fs/erofs/decompressor.c +@@ -248,15 +248,9 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx, + if (ret != rq->outputsize) { + erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", + ret, rq->inputsize, inputmargin, rq->outputsize); +- +- print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, +- 16, 1, src + inputmargin, rq->inputsize, true); +- print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, +- 16, 1, out, rq->outputsize, true); +- + if (ret >= 0) + memset(out + ret, 0, rq->outputsize - ret); +- ret = -EIO; ++ ret = -EFSCORRUPTED; + } else { + ret = 0; + } +diff --git a/fs/exec.c b/fs/exec.c +index 89a9017af7e86f..1cbbef281f8cfe 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1609,6 +1609,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) + unsigned int mode; + vfsuid_t vfsuid; + vfsgid_t vfsgid; ++ int err; + + if (!mnt_may_suid(file->f_path.mnt)) + return; +@@ -1625,12 +1626,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) + /* Be careful if suid/sgid is set */ + inode_lock(inode); + +- /* reload atomically mode/uid/gid now that lock held */ ++ /* Atomically reload and check mode/uid/gid now that lock held. */ + mode = inode->i_mode; + vfsuid = i_uid_into_vfsuid(idmap, inode); + vfsgid = i_gid_into_vfsgid(idmap, inode); ++ err = inode_permission(idmap, inode, MAY_EXEC); + inode_unlock(inode); + ++ /* Did the exec bit vanish out from under us? Give up. */ ++ if (err) ++ return; ++ + /* We ignore suid/sgid if there are no mappings for them in the ns */ + if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || + !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index cef119a2476bb4..a4ffd1acac6514 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2966,23 +2966,29 @@ static int ext4_da_should_update_i_disksize(struct folio *folio, + + static int ext4_da_do_write_end(struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, +- struct page *page) ++ struct folio *folio) + { + struct inode *inode = mapping->host; + loff_t old_size = inode->i_size; + bool disksize_changed = false; + loff_t new_i_size; + ++ if (unlikely(!folio_buffers(folio))) { ++ folio_unlock(folio); ++ folio_put(folio); ++ return -EIO; ++ } + /* + * block_write_end() will mark the inode as dirty with I_DIRTY_PAGES + * flag, which all that's needed to trigger page writeback. + */ +- copied = block_write_end(NULL, mapping, pos, len, copied, page, NULL); ++ copied = block_write_end(NULL, mapping, pos, len, copied, ++ &folio->page, NULL); + new_i_size = pos + copied; + + /* +- * It's important to update i_size while still holding page lock, +- * because page writeout could otherwise come in and zero beyond ++ * It's important to update i_size while still holding folio lock, ++ * because folio writeout could otherwise come in and zero beyond + * i_size. + * + * Since we are holding inode lock, we are sure i_disksize <= +@@ -3000,14 +3006,14 @@ static int ext4_da_do_write_end(struct address_space *mapping, + + i_size_write(inode, new_i_size); + end = (new_i_size - 1) & (PAGE_SIZE - 1); +- if (copied && ext4_da_should_update_i_disksize(page_folio(page), end)) { ++ if (copied && ext4_da_should_update_i_disksize(folio, end)) { + ext4_update_i_disksize(inode, new_i_size); + disksize_changed = true; + } + } + +- unlock_page(page); +- put_page(page); ++ folio_unlock(folio); ++ folio_put(folio); + + if (old_size < pos) + pagecache_isize_extended(inode, old_size, pos); +@@ -3046,10 +3052,10 @@ static int ext4_da_write_end(struct file *file, + return ext4_write_inline_data_end(inode, pos, len, copied, + folio); + +- if (unlikely(copied < len) && !PageUptodate(page)) ++ if (unlikely(copied < len) && !folio_test_uptodate(folio)) + copied = 0; + +- return ext4_da_do_write_end(mapping, pos, len, copied, &folio->page); ++ return ext4_da_do_write_end(mapping, pos, len, copied, folio); + } + + /* +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index c58cbe9f7809c1..c368ff671d7739 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1571,46 +1571,49 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value, + /* + * Add value of the EA in an inode. + */ +-static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode, +- const void *value, size_t value_len, +- struct inode **ret_inode) ++static struct inode *ext4_xattr_inode_lookup_create(handle_t *handle, ++ struct inode *inode, const void *value, size_t value_len) + { + struct inode *ea_inode; + u32 hash; + int err; + ++ /* Account inode & space to quota even if sharing... */ ++ err = ext4_xattr_inode_alloc_quota(inode, value_len); ++ if (err) ++ return ERR_PTR(err); ++ + hash = ext4_xattr_inode_hash(EXT4_SB(inode->i_sb), value, value_len); + ea_inode = ext4_xattr_inode_cache_find(inode, value, value_len, hash); + if (ea_inode) { + err = ext4_xattr_inode_inc_ref(handle, ea_inode); +- if (err) { +- iput(ea_inode); +- return err; +- } +- +- *ret_inode = ea_inode; +- return 0; ++ if (err) ++ goto out_err; ++ return ea_inode; + } + + /* Create an inode for the EA value */ + ea_inode = ext4_xattr_inode_create(handle, inode, hash); +- if (IS_ERR(ea_inode)) +- return PTR_ERR(ea_inode); ++ if (IS_ERR(ea_inode)) { ++ ext4_xattr_inode_free_quota(inode, NULL, value_len); ++ return ea_inode; ++ } + + err = ext4_xattr_inode_write(handle, ea_inode, value, value_len); + if (err) { + if (ext4_xattr_inode_dec_ref(handle, ea_inode)) + ext4_warning_inode(ea_inode, "cleanup dec ref error %d", err); +- iput(ea_inode); +- return err; ++ goto out_err; + } + + if (EA_INODE_CACHE(inode)) + mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash, + ea_inode->i_ino, true /* reusable */); +- +- *ret_inode = ea_inode; +- return 0; ++ return ea_inode; ++out_err: ++ iput(ea_inode); ++ ext4_xattr_inode_free_quota(inode, NULL, value_len); ++ return ERR_PTR(err); + } + + /* +@@ -1622,6 +1625,7 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode, + static int ext4_xattr_set_entry(struct ext4_xattr_info *i, + struct ext4_xattr_search *s, + handle_t *handle, struct inode *inode, ++ struct inode *new_ea_inode, + bool is_block) + { + struct ext4_xattr_entry *last, *next; +@@ -1629,7 +1633,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, + size_t min_offs = s->end - s->base, name_len = strlen(i->name); + int in_inode = i->in_inode; + struct inode *old_ea_inode = NULL; +- struct inode *new_ea_inode = NULL; + size_t old_size, new_size; + int ret; + +@@ -1714,43 +1717,11 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, + old_ea_inode = NULL; + goto out; + } +- } +- if (i->value && in_inode) { +- WARN_ON_ONCE(!i->value_len); +- +- ret = ext4_xattr_inode_alloc_quota(inode, i->value_len); +- if (ret) +- goto out; +- +- ret = ext4_xattr_inode_lookup_create(handle, inode, i->value, +- i->value_len, +- &new_ea_inode); +- if (ret) { +- new_ea_inode = NULL; +- ext4_xattr_inode_free_quota(inode, NULL, i->value_len); +- goto out; +- } +- } + +- if (old_ea_inode) { + /* We are ready to release ref count on the old_ea_inode. */ + ret = ext4_xattr_inode_dec_ref(handle, old_ea_inode); +- if (ret) { +- /* Release newly required ref count on new_ea_inode. */ +- if (new_ea_inode) { +- int err; +- +- err = ext4_xattr_inode_dec_ref(handle, +- new_ea_inode); +- if (err) +- ext4_warning_inode(new_ea_inode, +- "dec ref new_ea_inode err=%d", +- err); +- ext4_xattr_inode_free_quota(inode, new_ea_inode, +- i->value_len); +- } ++ if (ret) + goto out; +- } + + ext4_xattr_inode_free_quota(inode, old_ea_inode, + le32_to_cpu(here->e_value_size)); +@@ -1874,7 +1845,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, + ret = 0; + out: + iput(old_ea_inode); +- iput(new_ea_inode); + return ret; + } + +@@ -1937,9 +1907,21 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + size_t old_ea_inode_quota = 0; + unsigned int ea_ino; + +- + #define header(x) ((struct ext4_xattr_header *)(x)) + ++ /* If we need EA inode, prepare it before locking the buffer */ ++ if (i->value && i->in_inode) { ++ WARN_ON_ONCE(!i->value_len); ++ ++ ea_inode = ext4_xattr_inode_lookup_create(handle, inode, ++ i->value, i->value_len); ++ if (IS_ERR(ea_inode)) { ++ error = PTR_ERR(ea_inode); ++ ea_inode = NULL; ++ goto cleanup; ++ } ++ } ++ + if (s->base) { + int offset = (char *)s->here - bs->bh->b_data; + +@@ -1948,6 +1930,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + EXT4_JTR_NONE); + if (error) + goto cleanup; ++ + lock_buffer(bs->bh); + + if (header(s->base)->h_refcount == cpu_to_le32(1)) { +@@ -1974,7 +1957,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + } + ea_bdebug(bs->bh, "modifying in-place"); + error = ext4_xattr_set_entry(i, s, handle, inode, +- true /* is_block */); ++ ea_inode, true /* is_block */); + ext4_xattr_block_csum_set(inode, bs->bh); + unlock_buffer(bs->bh); + if (error == -EFSCORRUPTED) +@@ -2042,29 +2025,13 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + s->end = s->base + sb->s_blocksize; + } + +- error = ext4_xattr_set_entry(i, s, handle, inode, true /* is_block */); ++ error = ext4_xattr_set_entry(i, s, handle, inode, ea_inode, ++ true /* is_block */); + if (error == -EFSCORRUPTED) + goto bad_block; + if (error) + goto cleanup; + +- if (i->value && s->here->e_value_inum) { +- /* +- * A ref count on ea_inode has been taken as part of the call to +- * ext4_xattr_set_entry() above. We would like to drop this +- * extra ref but we have to wait until the xattr block is +- * initialized and has its own ref count on the ea_inode. +- */ +- ea_ino = le32_to_cpu(s->here->e_value_inum); +- error = ext4_xattr_inode_iget(inode, ea_ino, +- le32_to_cpu(s->here->e_hash), +- &ea_inode); +- if (error) { +- ea_inode = NULL; +- goto cleanup; +- } +- } +- + inserted: + if (!IS_LAST_ENTRY(s->first)) { + new_bh = ext4_xattr_block_cache_find(inode, header(s->base), +@@ -2217,17 +2184,16 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + + cleanup: + if (ea_inode) { +- int error2; +- +- error2 = ext4_xattr_inode_dec_ref(handle, ea_inode); +- if (error2) +- ext4_warning_inode(ea_inode, "dec ref error=%d", +- error2); ++ if (error) { ++ int error2; + +- /* If there was an error, revert the quota charge. */ +- if (error) ++ error2 = ext4_xattr_inode_dec_ref(handle, ea_inode); ++ if (error2) ++ ext4_warning_inode(ea_inode, "dec ref error=%d", ++ error2); + ext4_xattr_inode_free_quota(inode, ea_inode, + i_size_read(ea_inode)); ++ } + iput(ea_inode); + } + if (ce) +@@ -2285,14 +2251,38 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + { + struct ext4_xattr_ibody_header *header; + struct ext4_xattr_search *s = &is->s; ++ struct inode *ea_inode = NULL; + int error; + + if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return -ENOSPC; + +- error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); +- if (error) ++ /* If we need EA inode, prepare it before locking the buffer */ ++ if (i->value && i->in_inode) { ++ WARN_ON_ONCE(!i->value_len); ++ ++ ea_inode = ext4_xattr_inode_lookup_create(handle, inode, ++ i->value, i->value_len); ++ if (IS_ERR(ea_inode)) ++ return PTR_ERR(ea_inode); ++ } ++ error = ext4_xattr_set_entry(i, s, handle, inode, ea_inode, ++ false /* is_block */); ++ if (error) { ++ if (ea_inode) { ++ int error2; ++ ++ error2 = ext4_xattr_inode_dec_ref(handle, ea_inode); ++ if (error2) ++ ext4_warning_inode(ea_inode, "dec ref error=%d", ++ error2); ++ ++ ext4_xattr_inode_free_quota(inode, ea_inode, ++ i_size_read(ea_inode)); ++ iput(ea_inode); ++ } + return error; ++ } + header = IHDR(inode, ext4_raw_inode(&is->iloc)); + if (!IS_LAST_ENTRY(s->first)) { + header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); +@@ -2301,6 +2291,7 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + header->h_magic = cpu_to_le32(0); + ext4_clear_inode_state(inode, EXT4_STATE_XATTR); + } ++ iput(ea_inode); + return 0; + } + +diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c +index ad8dfac73bd446..6a9a470345bfc7 100644 +--- a/fs/f2fs/extent_cache.c ++++ b/fs/f2fs/extent_cache.c +@@ -19,34 +19,24 @@ + #include "node.h" + #include + +-bool sanity_check_extent_cache(struct inode *inode) ++bool sanity_check_extent_cache(struct inode *inode, struct page *ipage) + { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); +- struct f2fs_inode_info *fi = F2FS_I(inode); +- struct extent_tree *et = fi->extent_tree[EX_READ]; +- struct extent_info *ei; +- +- if (!et) +- return true; ++ struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; ++ struct extent_info ei; + +- ei = &et->largest; +- if (!ei->len) +- return true; ++ get_read_extent_info(&ei, i_ext); + +- /* Let's drop, if checkpoint got corrupted. */ +- if (is_set_ckpt_flags(sbi, CP_ERROR_FLAG)) { +- ei->len = 0; +- et->largest_updated = true; ++ if (!ei.len) + return true; +- } + +- if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) || +- !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, ++ if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) || ++ !f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1, + DATA_GENERIC_ENHANCE)) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", + __func__, inode->i_ino, +- ei->blk, ei->fofs, ei->len); ++ ei.blk, ei.fofs, ei.len); + return false; + } + return true; +@@ -395,24 +385,22 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) + + if (!__may_extent_tree(inode, EX_READ)) { + /* drop largest read extent */ +- if (i_ext && i_ext->len) { ++ if (i_ext->len) { + f2fs_wait_on_page_writeback(ipage, NODE, true, true); + i_ext->len = 0; + set_page_dirty(ipage); + } +- goto out; ++ set_inode_flag(inode, FI_NO_EXTENT); ++ return; + } + + et = __grab_extent_tree(inode, EX_READ); + +- if (!i_ext || !i_ext->len) +- goto out; +- + get_read_extent_info(&ei, i_ext); + + write_lock(&et->lock); +- if (atomic_read(&et->node_cnt)) +- goto unlock_out; ++ if (atomic_read(&et->node_cnt) || !ei.len) ++ goto skip; + + en = __attach_extent_node(sbi, et, &ei, NULL, + &et->root.rb_root.rb_node, true); +@@ -424,11 +412,13 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) + list_add_tail(&en->list, &eti->extent_list); + spin_unlock(&eti->extent_lock); + } +-unlock_out: ++skip: ++ /* Let's drop, if checkpoint got corrupted. */ ++ if (f2fs_cp_error(sbi)) { ++ et->largest.len = 0; ++ et->largest_updated = true; ++ } + write_unlock(&et->lock); +-out: +- if (!F2FS_I(inode)->extent_tree[EX_READ]) +- set_inode_flag(inode, FI_NO_EXTENT); + } + + void f2fs_init_age_extent_tree(struct inode *inode) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 19490dd8321943..00eff023cd9d63 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -4189,7 +4189,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); + /* + * extent_cache.c + */ +-bool sanity_check_extent_cache(struct inode *inode); ++bool sanity_check_extent_cache(struct inode *inode, struct page *ipage); + void f2fs_init_extent_tree(struct inode *inode); + void f2fs_drop_extent_tree(struct inode *inode); + void f2fs_destroy_extent_node(struct inode *inode); +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index afb7c88ba06b2c..888c301ffe8f4c 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1563,6 +1563,16 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + continue; + } + ++ if (f2fs_has_inline_data(inode)) { ++ iput(inode); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); ++ f2fs_err_ratelimited(sbi, ++ "inode %lx has both inline_data flag and " ++ "data block, nid=%u, ofs_in_node=%u", ++ inode->i_ino, dni.nid, ofs_in_node); ++ continue; ++ } ++ + err = f2fs_gc_pinned_control(inode, gc_type, segno); + if (err == -EAGAIN) { + iput(inode); +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 0172f4e503061d..26e857fee631d9 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -511,16 +511,16 @@ static int do_read_inode(struct inode *inode) + + init_idisk_time(inode); + +- /* Need all the flag bits */ +- f2fs_init_read_extent_tree(inode, node_page); +- f2fs_init_age_extent_tree(inode); +- +- if (!sanity_check_extent_cache(inode)) { ++ if (!sanity_check_extent_cache(inode, node_page)) { + f2fs_put_page(node_page, 1); + f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE); + return -EFSCORRUPTED; + } + ++ /* Need all the flag bits */ ++ f2fs_init_read_extent_tree(inode, node_page); ++ f2fs_init_age_extent_tree(inode); ++ + f2fs_put_page(node_page, 1); + + stat_inc_inline_xattr(inode); +diff --git a/fs/fhandle.c b/fs/fhandle.c +index 99dcf07cfecfe1..c361d7ff1b88dd 100644 +--- a/fs/fhandle.c ++++ b/fs/fhandle.c +@@ -40,7 +40,7 @@ static long do_sys_name_to_handle(const struct path *path, + if (f_handle.handle_bytes > MAX_HANDLE_SZ) + return -EINVAL; + +- handle = kzalloc(sizeof(struct file_handle) + f_handle.handle_bytes, ++ handle = kzalloc(struct_size(handle, f_handle, f_handle.handle_bytes), + GFP_KERNEL); + if (!handle) + return -ENOMEM; +@@ -75,7 +75,7 @@ static long do_sys_name_to_handle(const struct path *path, + /* copy the mount id */ + if (put_user(real_mount(path->mnt)->mnt_id, mnt_id) || + copy_to_user(ufh, handle, +- sizeof(struct file_handle) + handle_bytes)) ++ struct_size(handle, f_handle, handle_bytes))) + retval = -EFAULT; + kfree(handle); + return retval; +@@ -196,7 +196,7 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, + retval = -EINVAL; + goto out_err; + } +- handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, ++ handle = kmalloc(struct_size(handle, f_handle, f_handle.handle_bytes), + GFP_KERNEL); + if (!handle) { + retval = -ENOMEM; +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index cb3cda1390adb1..5713994328cbcb 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -1626,6 +1626,8 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) + } else if (rc == -ENOSPC) { + /* search for next smaller log2 block */ + l2nb = BLKSTOL2(nblocks) - 1; ++ if (unlikely(l2nb < 0)) ++ break; + nblocks = 1LL << l2nb; + } else { + /* Trim any already allocated blocks */ +diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c +index 031d8f570f581f..5d3127ca68a42d 100644 +--- a/fs/jfs/jfs_dtree.c ++++ b/fs/jfs/jfs_dtree.c +@@ -834,6 +834,8 @@ int dtInsert(tid_t tid, struct inode *ip, + * the full page. + */ + DT_GETSEARCH(ip, btstack->top, bn, mp, p, index); ++ if (p->header.freelist == 0) ++ return -EINVAL; + + /* + * insert entry for new key +diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c +index e855b8fde76ce1..cb6d1fda66a702 100644 +--- a/fs/jfs/jfs_logmgr.c ++++ b/fs/jfs/jfs_logmgr.c +@@ -1058,7 +1058,7 @@ void jfs_syncpt(struct jfs_log *log, int hard_sync) + int lmLogOpen(struct super_block *sb) + { + int rc; +- struct block_device *bdev; ++ struct bdev_handle *bdev_handle; + struct jfs_log *log; + struct jfs_sb_info *sbi = JFS_SBI(sb); + +@@ -1070,7 +1070,7 @@ int lmLogOpen(struct super_block *sb) + + mutex_lock(&jfs_log_mutex); + list_for_each_entry(log, &jfs_external_logs, journal_list) { +- if (log->bdev->bd_dev == sbi->logdev) { ++ if (log->bdev_handle->bdev->bd_dev == sbi->logdev) { + if (!uuid_equal(&log->uuid, &sbi->loguuid)) { + jfs_warn("wrong uuid on JFS journal"); + mutex_unlock(&jfs_log_mutex); +@@ -1100,14 +1100,14 @@ int lmLogOpen(struct super_block *sb) + * file systems to log may have n-to-1 relationship; + */ + +- bdev = blkdev_get_by_dev(sbi->logdev, BLK_OPEN_READ | BLK_OPEN_WRITE, +- log, NULL); +- if (IS_ERR(bdev)) { +- rc = PTR_ERR(bdev); ++ bdev_handle = bdev_open_by_dev(sbi->logdev, ++ BLK_OPEN_READ | BLK_OPEN_WRITE, log, NULL); ++ if (IS_ERR(bdev_handle)) { ++ rc = PTR_ERR(bdev_handle); + goto free; + } + +- log->bdev = bdev; ++ log->bdev_handle = bdev_handle; + uuid_copy(&log->uuid, &sbi->loguuid); + + /* +@@ -1141,7 +1141,7 @@ int lmLogOpen(struct super_block *sb) + lbmLogShutdown(log); + + close: /* close external log device */ +- blkdev_put(bdev, log); ++ bdev_release(bdev_handle); + + free: /* free log descriptor */ + mutex_unlock(&jfs_log_mutex); +@@ -1162,7 +1162,7 @@ static int open_inline_log(struct super_block *sb) + init_waitqueue_head(&log->syncwait); + + set_bit(log_INLINELOG, &log->flag); +- log->bdev = sb->s_bdev; ++ log->bdev_handle = sb->s_bdev_handle; + log->base = addressPXD(&JFS_SBI(sb)->logpxd); + log->size = lengthPXD(&JFS_SBI(sb)->logpxd) >> + (L2LOGPSIZE - sb->s_blocksize_bits); +@@ -1436,7 +1436,7 @@ int lmLogClose(struct super_block *sb) + { + struct jfs_sb_info *sbi = JFS_SBI(sb); + struct jfs_log *log = sbi->log; +- struct block_device *bdev; ++ struct bdev_handle *bdev_handle; + int rc = 0; + + jfs_info("lmLogClose: log:0x%p", log); +@@ -1482,10 +1482,10 @@ int lmLogClose(struct super_block *sb) + * external log as separate logical volume + */ + list_del(&log->journal_list); +- bdev = log->bdev; ++ bdev_handle = log->bdev_handle; + rc = lmLogShutdown(log); + +- blkdev_put(bdev, log); ++ bdev_release(bdev_handle); + + kfree(log); + +@@ -1972,7 +1972,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) + + bp->l_flag |= lbmREAD; + +- bio = bio_alloc(log->bdev, 1, REQ_OP_READ, GFP_NOFS); ++ bio = bio_alloc(log->bdev_handle->bdev, 1, REQ_OP_READ, GFP_NOFS); + bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9); + __bio_add_page(bio, bp->l_page, LOGPSIZE, bp->l_offset); + BUG_ON(bio->bi_iter.bi_size != LOGPSIZE); +@@ -2110,10 +2110,15 @@ static void lbmStartIO(struct lbuf * bp) + { + struct bio *bio; + struct jfs_log *log = bp->l_log; ++ struct block_device *bdev = NULL; + + jfs_info("lbmStartIO"); + +- bio = bio_alloc(log->bdev, 1, REQ_OP_WRITE | REQ_SYNC, GFP_NOFS); ++ if (!log->no_integrity) ++ bdev = log->bdev_handle->bdev; ++ ++ bio = bio_alloc(bdev, 1, REQ_OP_WRITE | REQ_SYNC, ++ GFP_NOFS); + bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9); + __bio_add_page(bio, bp->l_page, LOGPSIZE, bp->l_offset); + BUG_ON(bio->bi_iter.bi_size != LOGPSIZE); +diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h +index 805877ce502044..84aa2d25390743 100644 +--- a/fs/jfs/jfs_logmgr.h ++++ b/fs/jfs/jfs_logmgr.h +@@ -356,7 +356,7 @@ struct jfs_log { + * before writing syncpt. + */ + struct list_head journal_list; /* Global list */ +- struct block_device *bdev; /* 4: log lv pointer */ ++ struct bdev_handle *bdev_handle; /* 4: log lv pointer */ + int serial; /* 4: log mount serial number */ + + s64 base; /* @8: log extent address (inline log ) */ +diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c +index 631b8bd3e43849..9b5c6a20b30c83 100644 +--- a/fs/jfs/jfs_mount.c ++++ b/fs/jfs/jfs_mount.c +@@ -430,7 +430,8 @@ int updateSuper(struct super_block *sb, uint state) + + if (state == FM_MOUNT) { + /* record log's dev_t and mount serial number */ +- j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev)); ++ j_sb->s_logdev = cpu_to_le32( ++ new_encode_dev(sbi->log->bdev_handle->bdev->bd_dev)); + j_sb->s_logserial = cpu_to_le32(sbi->log->serial); + } else if (state == FM_CLEAN) { + /* +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index 6579948070a482..a62331487ebf16 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -712,8 +712,6 @@ static const struct svc_version *nlmsvc_version[] = { + #endif + }; + +-static struct svc_stat nlmsvc_stats; +- + #define NLM_NRVERS ARRAY_SIZE(nlmsvc_version) + static struct svc_program nlmsvc_program = { + .pg_prog = NLM_PROGRAM, /* program number */ +@@ -721,7 +719,6 @@ static struct svc_program nlmsvc_program = { + .pg_vers = nlmsvc_version, /* version table */ + .pg_name = "lockd", /* service name */ + .pg_class = "nfsd", /* share authentication with nfsd */ +- .pg_stats = &nlmsvc_stats, /* stats table */ + .pg_authenticate = &lockd_authenticate, /* export authentication */ + .pg_init_request = svc_generic_init_request, + .pg_rpcbind_set = svc_generic_rpcbind_set, +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index 466ebf1d41b2b7..869c88978899c0 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -399,15 +399,12 @@ static const struct svc_version *nfs4_callback_version[] = { + [4] = &nfs4_callback_version4, + }; + +-static struct svc_stat nfs4_callback_stats; +- + static struct svc_program nfs4_callback_program = { + .pg_prog = NFS4_CALLBACK, /* RPC service number */ + .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */ + .pg_vers = nfs4_callback_version, /* version table */ + .pg_name = "NFSv4 callback", /* service name */ + .pg_class = "nfs", /* authentication class */ +- .pg_stats = &nfs4_callback_stats, + .pg_authenticate = nfs_callback_authenticate, + .pg_init_request = svc_generic_init_request, + .pg_rpcbind_set = svc_generic_rpcbind_set, +diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h +index 4cbe0434cbb8ce..66a05fefae98ea 100644 +--- a/fs/nfsd/cache.h ++++ b/fs/nfsd/cache.h +@@ -80,8 +80,6 @@ enum { + + int nfsd_drc_slab_create(void); + void nfsd_drc_slab_free(void); +-int nfsd_net_reply_cache_init(struct nfsd_net *nn); +-void nfsd_net_reply_cache_destroy(struct nfsd_net *nn); + int nfsd_reply_cache_init(struct nfsd_net *); + void nfsd_reply_cache_shutdown(struct nfsd_net *); + int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, +diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c +index 11a0eaa2f91407..b7da17e530077e 100644 +--- a/fs/nfsd/export.c ++++ b/fs/nfsd/export.c +@@ -339,12 +339,16 @@ static int export_stats_init(struct export_stats *stats) + + static void export_stats_reset(struct export_stats *stats) + { +- nfsd_percpu_counters_reset(stats->counter, EXP_STATS_COUNTERS_NUM); ++ if (stats) ++ nfsd_percpu_counters_reset(stats->counter, ++ EXP_STATS_COUNTERS_NUM); + } + + static void export_stats_destroy(struct export_stats *stats) + { +- nfsd_percpu_counters_destroy(stats->counter, EXP_STATS_COUNTERS_NUM); ++ if (stats) ++ nfsd_percpu_counters_destroy(stats->counter, ++ EXP_STATS_COUNTERS_NUM); + } + + static void svc_export_put(struct kref *ref) +@@ -353,7 +357,8 @@ static void svc_export_put(struct kref *ref) + path_put(&exp->ex_path); + auth_domain_put(exp->ex_client); + nfsd4_fslocs_free(&exp->ex_fslocs); +- export_stats_destroy(&exp->ex_stats); ++ export_stats_destroy(exp->ex_stats); ++ kfree(exp->ex_stats); + kfree(exp->ex_uuid); + kfree_rcu(exp, ex_rcu); + } +@@ -767,13 +772,15 @@ static int svc_export_show(struct seq_file *m, + seq_putc(m, '\t'); + seq_escape(m, exp->ex_client->name, " \t\n\\"); + if (export_stats) { +- seq_printf(m, "\t%lld\n", exp->ex_stats.start_time); ++ struct percpu_counter *counter = exp->ex_stats->counter; ++ ++ seq_printf(m, "\t%lld\n", exp->ex_stats->start_time); + seq_printf(m, "\tfh_stale: %lld\n", +- percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_FH_STALE])); ++ percpu_counter_sum_positive(&counter[EXP_STATS_FH_STALE])); + seq_printf(m, "\tio_read: %lld\n", +- percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_IO_READ])); ++ percpu_counter_sum_positive(&counter[EXP_STATS_IO_READ])); + seq_printf(m, "\tio_write: %lld\n", +- percpu_counter_sum_positive(&exp->ex_stats.counter[EXP_STATS_IO_WRITE])); ++ percpu_counter_sum_positive(&counter[EXP_STATS_IO_WRITE])); + seq_putc(m, '\n'); + return 0; + } +@@ -819,7 +826,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) + new->ex_layout_types = 0; + new->ex_uuid = NULL; + new->cd = item->cd; +- export_stats_reset(&new->ex_stats); ++ export_stats_reset(new->ex_stats); + } + + static void export_update(struct cache_head *cnew, struct cache_head *citem) +@@ -856,7 +863,14 @@ static struct cache_head *svc_export_alloc(void) + if (!i) + return NULL; + +- if (export_stats_init(&i->ex_stats)) { ++ i->ex_stats = kmalloc(sizeof(*(i->ex_stats)), GFP_KERNEL); ++ if (!i->ex_stats) { ++ kfree(i); ++ return NULL; ++ } ++ ++ if (export_stats_init(i->ex_stats)) { ++ kfree(i->ex_stats); + kfree(i); + return NULL; + } +diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h +index 2df8ae25aad302..ca9dc230ae3d0b 100644 +--- a/fs/nfsd/export.h ++++ b/fs/nfsd/export.h +@@ -64,10 +64,10 @@ struct svc_export { + struct cache_head h; + struct auth_domain * ex_client; + int ex_flags; ++ int ex_fsid; + struct path ex_path; + kuid_t ex_anon_uid; + kgid_t ex_anon_gid; +- int ex_fsid; + unsigned char * ex_uuid; /* 16 byte fsid */ + struct nfsd4_fs_locations ex_fslocs; + uint32_t ex_nflavors; +@@ -76,8 +76,8 @@ struct svc_export { + struct nfsd4_deviceid_map *ex_devid_map; + struct cache_detail *cd; + struct rcu_head ex_rcu; +- struct export_stats ex_stats; + unsigned long ex_xprtsec_modes; ++ struct export_stats *ex_stats; + }; + + /* an "export key" (expkey) maps a filehandlefragement to an +diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h +index ec49b200b79762..9bfca3dda63d33 100644 +--- a/fs/nfsd/netns.h ++++ b/fs/nfsd/netns.h +@@ -11,8 +11,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + + /* Hash tables for nfs4_clientid state */ + #define CLIENT_HASH_BITS 4 +@@ -26,10 +28,22 @@ struct nfsd4_client_tracking_ops; + + enum { + /* cache misses due only to checksum comparison failures */ +- NFSD_NET_PAYLOAD_MISSES, ++ NFSD_STATS_PAYLOAD_MISSES, + /* amount of memory (in bytes) currently consumed by the DRC */ +- NFSD_NET_DRC_MEM_USAGE, +- NFSD_NET_COUNTERS_NUM ++ NFSD_STATS_DRC_MEM_USAGE, ++ NFSD_STATS_RC_HITS, /* repcache hits */ ++ NFSD_STATS_RC_MISSES, /* repcache misses */ ++ NFSD_STATS_RC_NOCACHE, /* uncached reqs */ ++ NFSD_STATS_FH_STALE, /* FH stale error */ ++ NFSD_STATS_IO_READ, /* bytes returned to read requests */ ++ NFSD_STATS_IO_WRITE, /* bytes passed in write requests */ ++#ifdef CONFIG_NFSD_V4 ++ NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */ ++ NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP, ++#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op)) ++ NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */ ++#endif ++ NFSD_STATS_COUNTERS_NUM + }; + + /* +@@ -169,7 +183,10 @@ struct nfsd_net { + atomic_t num_drc_entries; + + /* Per-netns stats counters */ +- struct percpu_counter counter[NFSD_NET_COUNTERS_NUM]; ++ struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM]; ++ ++ /* sunrpc svc stats */ ++ struct svc_stat nfsd_svcstats; + + /* longest hash chain seen */ + unsigned int longest_chain; +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 451026f9986b61..ae0057c54ef4ed 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -2478,10 +2478,10 @@ nfsd4_proc_null(struct svc_rqst *rqstp) + return rpc_success; + } + +-static inline void nfsd4_increment_op_stats(u32 opnum) ++static inline void nfsd4_increment_op_stats(struct nfsd_net *nn, u32 opnum) + { + if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP) +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_NFS4_OP(opnum)]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_NFS4_OP(opnum)]); + } + + static const struct nfsd4_operation nfsd4_ops[]; +@@ -2756,7 +2756,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) + status, nfsd4_op_name(op->opnum)); + + nfsd4_cstate_clear_replay(cstate); +- nfsd4_increment_op_stats(op->opnum); ++ nfsd4_increment_op_stats(nn, op->opnum); + } + + fh_put(current_fh); +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index c7e52d980cd75f..cdad1eaa4a3180 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -8422,6 +8422,7 @@ __be32 + nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode) + { + __be32 status; ++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct file_lock_context *ctx; + struct file_lock *fl; + struct nfs4_delegation *dp; +@@ -8451,7 +8452,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode) + } + break_lease: + spin_unlock(&ctx->flc_lock); +- nfsd_stats_wdeleg_getattr_inc(); ++ nfsd_stats_wdeleg_getattr_inc(nn); + status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ)); + if (status != nfserr_jukebox || + !nfsd_wait_for_delegreturn(rqstp, inode)) +diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c +index 6cd36af2f97e10..c52132ecb339d5 100644 +--- a/fs/nfsd/nfscache.c ++++ b/fs/nfsd/nfscache.c +@@ -176,27 +176,6 @@ void nfsd_drc_slab_free(void) + kmem_cache_destroy(drc_slab); + } + +-/** +- * nfsd_net_reply_cache_init - per net namespace reply cache set-up +- * @nn: nfsd_net being initialized +- * +- * Returns zero on succes; otherwise a negative errno is returned. +- */ +-int nfsd_net_reply_cache_init(struct nfsd_net *nn) +-{ +- return nfsd_percpu_counters_init(nn->counter, NFSD_NET_COUNTERS_NUM); +-} +- +-/** +- * nfsd_net_reply_cache_destroy - per net namespace reply cache tear-down +- * @nn: nfsd_net being freed +- * +- */ +-void nfsd_net_reply_cache_destroy(struct nfsd_net *nn) +-{ +- nfsd_percpu_counters_destroy(nn->counter, NFSD_NET_COUNTERS_NUM); +-} +- + int nfsd_reply_cache_init(struct nfsd_net *nn) + { + unsigned int hashsize; +@@ -502,7 +481,7 @@ nfsd_cache_insert(struct nfsd_drc_bucket *b, struct nfsd_cacherep *key, + int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, + unsigned int len, struct nfsd_cacherep **cacherep) + { +- struct nfsd_net *nn; ++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct nfsd_cacherep *rp, *found; + __wsum csum; + struct nfsd_drc_bucket *b; +@@ -512,7 +491,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, + int rtn = RC_DOIT; + + if (type == RC_NOCACHE) { +- nfsd_stats_rc_nocache_inc(); ++ nfsd_stats_rc_nocache_inc(nn); + goto out; + } + +@@ -522,7 +501,6 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, + * Since the common case is a cache miss followed by an insert, + * preallocate an entry. + */ +- nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + rp = nfsd_cacherep_alloc(rqstp, csum, nn); + if (!rp) + goto out; +@@ -540,7 +518,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, + freed = nfsd_cacherep_dispose(&dispose); + trace_nfsd_drc_gc(nn, freed); + +- nfsd_stats_rc_misses_inc(); ++ nfsd_stats_rc_misses_inc(nn); + atomic_inc(&nn->num_drc_entries); + nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp)); + goto out; +@@ -548,7 +526,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, + found_entry: + /* We found a matching entry which is either in progress or done. */ + nfsd_reply_cache_free_locked(NULL, rp, nn); +- nfsd_stats_rc_hits_inc(); ++ nfsd_stats_rc_hits_inc(nn); + rtn = RC_DROPIT; + rp = found; + +@@ -690,15 +668,15 @@ int nfsd_reply_cache_stats_show(struct seq_file *m, void *v) + atomic_read(&nn->num_drc_entries)); + seq_printf(m, "hash buckets: %u\n", 1 << nn->maskbits); + seq_printf(m, "mem usage: %lld\n", +- percpu_counter_sum_positive(&nn->counter[NFSD_NET_DRC_MEM_USAGE])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_DRC_MEM_USAGE])); + seq_printf(m, "cache hits: %lld\n", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS])); + seq_printf(m, "cache misses: %lld\n", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES])); + seq_printf(m, "not cached: %lld\n", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE])); + seq_printf(m, "payload misses: %lld\n", +- percpu_counter_sum_positive(&nn->counter[NFSD_NET_PAYLOAD_MISSES])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_PAYLOAD_MISSES])); + seq_printf(m, "longest chain len: %u\n", nn->longest_chain); + seq_printf(m, "cachesize at longest: %u\n", nn->longest_chain_cachesize); + return 0; +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index a13e81e450718a..887035b7446763 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -1524,14 +1524,17 @@ static __net_init int nfsd_net_init(struct net *net) + retval = nfsd_idmap_init(net); + if (retval) + goto out_idmap_error; +- retval = nfsd_net_reply_cache_init(nn); ++ retval = nfsd_stat_counters_init(nn); + if (retval) + goto out_repcache_error; ++ memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); ++ nn->nfsd_svcstats.program = &nfsd_program; + nn->nfsd_versions = NULL; + nn->nfsd4_minorversions = NULL; + nfsd4_init_leases_net(nn); + get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key)); + seqlock_init(&nn->writeverf_lock); ++ nfsd_proc_stat_init(net); + + return 0; + +@@ -1552,7 +1555,8 @@ static __net_exit void nfsd_net_exit(struct net *net) + { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +- nfsd_net_reply_cache_destroy(nn); ++ nfsd_proc_stat_shutdown(net); ++ nfsd_stat_counters_destroy(nn); + nfsd_idmap_shutdown(net); + nfsd_export_shutdown(net); + nfsd_netns_free_versions(nn); +@@ -1575,12 +1579,9 @@ static int __init init_nfsd(void) + retval = nfsd4_init_pnfs(); + if (retval) + goto out_free_slabs; +- retval = nfsd_stat_init(); /* Statistics */ +- if (retval) +- goto out_free_pnfs; + retval = nfsd_drc_slab_create(); + if (retval) +- goto out_free_stat; ++ goto out_free_pnfs; + nfsd_lockd_init(); /* lockd->nfsd callbacks */ + retval = create_proc_exports_entry(); + if (retval) +@@ -1610,8 +1611,6 @@ static int __init init_nfsd(void) + out_free_lockd: + nfsd_lockd_shutdown(); + nfsd_drc_slab_free(); +-out_free_stat: +- nfsd_stat_shutdown(); + out_free_pnfs: + nfsd4_exit_pnfs(); + out_free_slabs: +@@ -1628,7 +1627,6 @@ static void __exit exit_nfsd(void) + nfsd_drc_slab_free(); + remove_proc_entry("fs/nfs/exports", NULL); + remove_proc_entry("fs/nfs", NULL); +- nfsd_stat_shutdown(); + nfsd_lockd_shutdown(); + nfsd4_free_slabs(); + nfsd4_exit_pnfs(); +diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h +index fe846a360ae18d..d05bd2b811f377 100644 +--- a/fs/nfsd/nfsd.h ++++ b/fs/nfsd/nfsd.h +@@ -69,6 +69,7 @@ extern struct mutex nfsd_mutex; + extern spinlock_t nfsd_drc_lock; + extern unsigned long nfsd_drc_max_mem; + extern unsigned long nfsd_drc_mem_used; ++extern atomic_t nfsd_th_cnt; /* number of available threads */ + + extern const struct seq_operations nfs_exports_op; + +diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c +index 937be276bb6b48..c2495d98c18928 100644 +--- a/fs/nfsd/nfsfh.c ++++ b/fs/nfsd/nfsfh.c +@@ -327,6 +327,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) + __be32 + fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) + { ++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct svc_export *exp = NULL; + struct dentry *dentry; + __be32 error; +@@ -395,7 +396,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) + out: + trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error); + if (error == nfserr_stale) +- nfsd_stats_fh_stale_inc(exp); ++ nfsd_stats_fh_stale_inc(nn, exp); + return error; + } + +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 7ef6af908faacb..7911c4b3b5d355 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -34,6 +34,7 @@ + + #define NFSDDBG_FACILITY NFSDDBG_SVC + ++atomic_t nfsd_th_cnt = ATOMIC_INIT(0); + extern struct svc_program nfsd_program; + static int nfsd(void *vrqstp); + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) +@@ -89,7 +90,6 @@ unsigned long nfsd_drc_max_mem; + unsigned long nfsd_drc_mem_used; + + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) +-static struct svc_stat nfsd_acl_svcstats; + static const struct svc_version *nfsd_acl_version[] = { + # if defined(CONFIG_NFSD_V2_ACL) + [2] = &nfsd_acl_version2, +@@ -108,15 +108,11 @@ static struct svc_program nfsd_acl_program = { + .pg_vers = nfsd_acl_version, + .pg_name = "nfsacl", + .pg_class = "nfsd", +- .pg_stats = &nfsd_acl_svcstats, + .pg_authenticate = &svc_set_client, + .pg_init_request = nfsd_acl_init_request, + .pg_rpcbind_set = nfsd_acl_rpcbind_set, + }; + +-static struct svc_stat nfsd_acl_svcstats = { +- .program = &nfsd_acl_program, +-}; + #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ + + static const struct svc_version *nfsd_version[] = { +@@ -141,7 +137,6 @@ struct svc_program nfsd_program = { + .pg_vers = nfsd_version, /* version table */ + .pg_name = "nfsd", /* program name */ + .pg_class = "nfsd", /* authentication class */ +- .pg_stats = &nfsd_svcstats, /* version table */ + .pg_authenticate = &svc_set_client, /* export authentication */ + .pg_init_request = nfsd_init_request, + .pg_rpcbind_set = nfsd_rpcbind_set, +@@ -675,7 +670,8 @@ int nfsd_create_serv(struct net *net) + if (nfsd_max_blksize == 0) + nfsd_max_blksize = nfsd_get_default_max_blksize(); + nfsd_reset_versions(nn); +- serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, nfsd); ++ serv = svc_create_pooled(&nfsd_program, &nn->nfsd_svcstats, ++ nfsd_max_blksize, nfsd); + if (serv == NULL) + return -ENOMEM; + +@@ -950,7 +946,7 @@ nfsd(void *vrqstp) + + current->fs->umask = 0; + +- atomic_inc(&nfsdstats.th_cnt); ++ atomic_inc(&nfsd_th_cnt); + + set_freezable(); + +@@ -964,7 +960,7 @@ nfsd(void *vrqstp) + svc_recv(rqstp); + } + +- atomic_dec(&nfsdstats.th_cnt); ++ atomic_dec(&nfsd_th_cnt); + + out: + /* Release the thread */ +diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c +index 63797635e1c328..9f606fa08bd4b8 100644 +--- a/fs/nfsd/stats.c ++++ b/fs/nfsd/stats.c +@@ -27,25 +27,22 @@ + + #include "nfsd.h" + +-struct nfsd_stats nfsdstats; +-struct svc_stat nfsd_svcstats = { +- .program = &nfsd_program, +-}; +- + static int nfsd_show(struct seq_file *seq, void *v) + { ++ struct net *net = pde_data(file_inode(seq->file)); ++ struct nfsd_net *nn = net_generic(net, nfsd_net_id); + int i; + + seq_printf(seq, "rc %lld %lld %lld\nfh %lld 0 0 0 0\nio %lld %lld\n", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]), +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES]), +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]), +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_FH_STALE]), +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_READ]), +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]), ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]), ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]), ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_FH_STALE]), ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_READ]), ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_WRITE])); + + /* thread usage: */ +- seq_printf(seq, "th %u 0", atomic_read(&nfsdstats.th_cnt)); ++ seq_printf(seq, "th %u 0", atomic_read(&nfsd_th_cnt)); + + /* deprecated thread usage histogram stats */ + for (i = 0; i < 10; i++) +@@ -55,7 +52,7 @@ static int nfsd_show(struct seq_file *seq, void *v) + seq_puts(seq, "\nra 0 0 0 0 0 0 0 0 0 0 0 0\n"); + + /* show my rpc info */ +- svc_seq_show(seq, &nfsd_svcstats); ++ svc_seq_show(seq, &nn->nfsd_svcstats); + + #ifdef CONFIG_NFSD_V4 + /* Show count for individual nfsv4 operations */ +@@ -63,10 +60,10 @@ static int nfsd_show(struct seq_file *seq, void *v) + seq_printf(seq,"proc4ops %u", LAST_NFS4_OP + 1); + for (i = 0; i <= LAST_NFS4_OP; i++) { + seq_printf(seq, " %lld", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_NFS4_OP(i)])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_NFS4_OP(i)])); + } + seq_printf(seq, "\nwdeleg_getattr %lld", +- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR])); ++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_WDELEG_GETATTR])); + + seq_putc(seq, '\n'); + #endif +@@ -76,7 +73,7 @@ static int nfsd_show(struct seq_file *seq, void *v) + + DEFINE_PROC_SHOW_ATTRIBUTE(nfsd); + +-int nfsd_percpu_counters_init(struct percpu_counter counters[], int num) ++int nfsd_percpu_counters_init(struct percpu_counter *counters, int num) + { + int i, err = 0; + +@@ -108,31 +105,24 @@ void nfsd_percpu_counters_destroy(struct percpu_counter counters[], int num) + percpu_counter_destroy(&counters[i]); + } + +-static int nfsd_stat_counters_init(void) ++int nfsd_stat_counters_init(struct nfsd_net *nn) + { +- return nfsd_percpu_counters_init(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM); ++ return nfsd_percpu_counters_init(nn->counter, NFSD_STATS_COUNTERS_NUM); + } + +-static void nfsd_stat_counters_destroy(void) ++void nfsd_stat_counters_destroy(struct nfsd_net *nn) + { +- nfsd_percpu_counters_destroy(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM); ++ nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM); + } + +-int nfsd_stat_init(void) ++void nfsd_proc_stat_init(struct net *net) + { +- int err; +- +- err = nfsd_stat_counters_init(); +- if (err) +- return err; ++ struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +- svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops); +- +- return 0; ++ svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops); + } + +-void nfsd_stat_shutdown(void) ++void nfsd_proc_stat_shutdown(struct net *net) + { +- nfsd_stat_counters_destroy(); +- svc_proc_unregister(&init_net, "nfsd"); ++ svc_proc_unregister(net, "nfsd"); + } +diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h +index cf5524e7ca0623..d2753e975dfd34 100644 +--- a/fs/nfsd/stats.h ++++ b/fs/nfsd/stats.h +@@ -10,94 +10,72 @@ + #include + #include + +- +-enum { +- NFSD_STATS_RC_HITS, /* repcache hits */ +- NFSD_STATS_RC_MISSES, /* repcache misses */ +- NFSD_STATS_RC_NOCACHE, /* uncached reqs */ +- NFSD_STATS_FH_STALE, /* FH stale error */ +- NFSD_STATS_IO_READ, /* bytes returned to read requests */ +- NFSD_STATS_IO_WRITE, /* bytes passed in write requests */ +-#ifdef CONFIG_NFSD_V4 +- NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */ +- NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP, +-#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op)) +- NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */ +-#endif +- NFSD_STATS_COUNTERS_NUM +-}; +- +-struct nfsd_stats { +- struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM]; +- +- atomic_t th_cnt; /* number of available threads */ +-}; +- +-extern struct nfsd_stats nfsdstats; +- +-extern struct svc_stat nfsd_svcstats; +- +-int nfsd_percpu_counters_init(struct percpu_counter counters[], int num); +-void nfsd_percpu_counters_reset(struct percpu_counter counters[], int num); +-void nfsd_percpu_counters_destroy(struct percpu_counter counters[], int num); +-int nfsd_stat_init(void); +-void nfsd_stat_shutdown(void); +- +-static inline void nfsd_stats_rc_hits_inc(void) ++int nfsd_percpu_counters_init(struct percpu_counter *counters, int num); ++void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num); ++void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num); ++int nfsd_stat_counters_init(struct nfsd_net *nn); ++void nfsd_stat_counters_destroy(struct nfsd_net *nn); ++void nfsd_proc_stat_init(struct net *net); ++void nfsd_proc_stat_shutdown(struct net *net); ++ ++static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn) + { +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_HITS]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_HITS]); + } + +-static inline void nfsd_stats_rc_misses_inc(void) ++static inline void nfsd_stats_rc_misses_inc(struct nfsd_net *nn) + { +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_MISSES]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_MISSES]); + } + +-static inline void nfsd_stats_rc_nocache_inc(void) ++static inline void nfsd_stats_rc_nocache_inc(struct nfsd_net *nn) + { +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_NOCACHE]); + } + +-static inline void nfsd_stats_fh_stale_inc(struct svc_export *exp) ++static inline void nfsd_stats_fh_stale_inc(struct nfsd_net *nn, ++ struct svc_export *exp) + { +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_FH_STALE]); +- if (exp) +- percpu_counter_inc(&exp->ex_stats.counter[EXP_STATS_FH_STALE]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_FH_STALE]); ++ if (exp && exp->ex_stats) ++ percpu_counter_inc(&exp->ex_stats->counter[EXP_STATS_FH_STALE]); + } + +-static inline void nfsd_stats_io_read_add(struct svc_export *exp, s64 amount) ++static inline void nfsd_stats_io_read_add(struct nfsd_net *nn, ++ struct svc_export *exp, s64 amount) + { +- percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_READ], amount); +- if (exp) +- percpu_counter_add(&exp->ex_stats.counter[EXP_STATS_IO_READ], amount); ++ percpu_counter_add(&nn->counter[NFSD_STATS_IO_READ], amount); ++ if (exp && exp->ex_stats) ++ percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_READ], amount); + } + +-static inline void nfsd_stats_io_write_add(struct svc_export *exp, s64 amount) ++static inline void nfsd_stats_io_write_add(struct nfsd_net *nn, ++ struct svc_export *exp, s64 amount) + { +- percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_WRITE], amount); +- if (exp) +- percpu_counter_add(&exp->ex_stats.counter[EXP_STATS_IO_WRITE], amount); ++ percpu_counter_add(&nn->counter[NFSD_STATS_IO_WRITE], amount); ++ if (exp && exp->ex_stats) ++ percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_WRITE], amount); + } + + static inline void nfsd_stats_payload_misses_inc(struct nfsd_net *nn) + { +- percpu_counter_inc(&nn->counter[NFSD_NET_PAYLOAD_MISSES]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]); + } + + static inline void nfsd_stats_drc_mem_usage_add(struct nfsd_net *nn, s64 amount) + { +- percpu_counter_add(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount); ++ percpu_counter_add(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount); + } + + static inline void nfsd_stats_drc_mem_usage_sub(struct nfsd_net *nn, s64 amount) + { +- percpu_counter_sub(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount); ++ percpu_counter_sub(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount); + } + + #ifdef CONFIG_NFSD_V4 +-static inline void nfsd_stats_wdeleg_getattr_inc(void) ++static inline void nfsd_stats_wdeleg_getattr_inc(struct nfsd_net *nn) + { +- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR]); ++ percpu_counter_inc(&nn->counter[NFSD_STATS_WDELEG_GETATTR]); + } + #endif + #endif /* _NFSD_STATS_H */ +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index d0fdf70ab20d36..1f2a5b22b6498e 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -985,7 +985,9 @@ static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp, + unsigned long *count, u32 *eof, ssize_t host_err) + { + if (host_err >= 0) { +- nfsd_stats_io_read_add(fhp->fh_export, host_err); ++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); ++ ++ nfsd_stats_io_read_add(nn, fhp->fh_export, host_err); + *eof = nfsd_eof_on_read(file, offset, host_err, *count); + *count = host_err; + fsnotify_access(file); +@@ -1168,7 +1170,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + goto out_nfserr; + } + *cnt = host_err; +- nfsd_stats_io_write_add(exp, *cnt); ++ nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); + if (host_err < 0) +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 424865dfca74ba..45b687aff700be 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -1896,6 +1896,47 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, + return REPARSE_LINK; + } + ++/* ++ * fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent ++ * but it accepts kernel address for fi_extents_start ++ */ ++static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo, ++ u64 logical, u64 phys, u64 len, u32 flags) ++{ ++ struct fiemap_extent extent; ++ struct fiemap_extent __user *dest = fieinfo->fi_extents_start; ++ ++ /* only count the extents */ ++ if (fieinfo->fi_extents_max == 0) { ++ fieinfo->fi_extents_mapped++; ++ return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; ++ } ++ ++ if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max) ++ return 1; ++ ++ if (flags & FIEMAP_EXTENT_DELALLOC) ++ flags |= FIEMAP_EXTENT_UNKNOWN; ++ if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED) ++ flags |= FIEMAP_EXTENT_ENCODED; ++ if (flags & (FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_DATA_INLINE)) ++ flags |= FIEMAP_EXTENT_NOT_ALIGNED; ++ ++ memset(&extent, 0, sizeof(extent)); ++ extent.fe_logical = logical; ++ extent.fe_physical = phys; ++ extent.fe_length = len; ++ extent.fe_flags = flags; ++ ++ dest += fieinfo->fi_extents_mapped; ++ memcpy(dest, &extent, sizeof(extent)); ++ ++ fieinfo->fi_extents_mapped++; ++ if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max) ++ return 1; ++ return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; ++} ++ + /* + * ni_fiemap - Helper for file_fiemap(). + * +@@ -1906,6 +1947,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + __u64 vbo, __u64 len) + { + int err = 0; ++ struct fiemap_extent __user *fe_u = fieinfo->fi_extents_start; ++ struct fiemap_extent *fe_k = NULL; + struct ntfs_sb_info *sbi = ni->mi.sbi; + u8 cluster_bits = sbi->cluster_bits; + struct runs_tree *run; +@@ -1953,6 +1996,18 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + goto out; + } + ++ /* ++ * To avoid lock problems replace pointer to user memory by pointer to kernel memory. ++ */ ++ fe_k = kmalloc_array(fieinfo->fi_extents_max, ++ sizeof(struct fiemap_extent), ++ GFP_NOFS | __GFP_ZERO); ++ if (!fe_k) { ++ err = -ENOMEM; ++ goto out; ++ } ++ fieinfo->fi_extents_start = fe_k; ++ + end = vbo + len; + alloc_size = le64_to_cpu(attr->nres.alloc_size); + if (end > alloc_size) +@@ -2041,8 +2096,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + dlen >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen, +- flags); ++ err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, dlen, ++ flags); ++ + if (err < 0) + break; + if (err == 1) { +@@ -2062,7 +2118,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + bytes >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags); ++ err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, bytes, ++ flags); + if (err < 0) + break; + if (err == 1) { +@@ -2075,7 +2132,19 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + + up_read(run_lock); + ++ /* ++ * Copy to user memory out of lock ++ */ ++ if (copy_to_user(fe_u, fe_k, ++ fieinfo->fi_extents_max * ++ sizeof(struct fiemap_extent))) { ++ err = -EFAULT; ++ } ++ + out: ++ /* Restore original pointer. */ ++ fieinfo->fi_extents_start = fe_u; ++ kfree(fe_k); + return err; + } + +diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c +index 0f1493e0f6d059..254f6359b287fa 100644 +--- a/fs/quota/quota_tree.c ++++ b/fs/quota/quota_tree.c +@@ -21,6 +21,12 @@ MODULE_AUTHOR("Jan Kara"); + MODULE_DESCRIPTION("Quota trie support"); + MODULE_LICENSE("GPL"); + ++/* ++ * Maximum quota tree depth we support. Only to limit recursion when working ++ * with the tree. ++ */ ++#define MAX_QTREE_DEPTH 6 ++ + #define __QUOTA_QT_PARANOIA + + static int __get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) +@@ -327,27 +333,36 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, + + /* Insert reference to structure into the trie */ + static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, +- uint *treeblk, int depth) ++ uint *blks, int depth) + { + char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS); + int ret = 0, newson = 0, newact = 0; + __le32 *ref; + uint newblk; ++ int i; + + if (!buf) + return -ENOMEM; +- if (!*treeblk) { ++ if (!blks[depth]) { + ret = get_free_dqblk(info); + if (ret < 0) + goto out_buf; +- *treeblk = ret; ++ for (i = 0; i < depth; i++) ++ if (ret == blks[i]) { ++ quota_error(dquot->dq_sb, ++ "Free block already used in tree: block %u", ++ ret); ++ ret = -EIO; ++ goto out_buf; ++ } ++ blks[depth] = ret; + memset(buf, 0, info->dqi_usable_bs); + newact = 1; + } else { +- ret = read_blk(info, *treeblk, buf); ++ ret = read_blk(info, blks[depth], buf); + if (ret < 0) { + quota_error(dquot->dq_sb, "Can't read tree quota " +- "block %u", *treeblk); ++ "block %u", blks[depth]); + goto out_buf; + } + } +@@ -357,8 +372,20 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + info->dqi_blocks - 1); + if (ret) + goto out_buf; +- if (!newblk) ++ if (!newblk) { + newson = 1; ++ } else { ++ for (i = 0; i <= depth; i++) ++ if (newblk == blks[i]) { ++ quota_error(dquot->dq_sb, ++ "Cycle in quota tree detected: block %u index %u", ++ blks[depth], ++ get_index(info, dquot->dq_id, depth)); ++ ret = -EIO; ++ goto out_buf; ++ } ++ } ++ blks[depth + 1] = newblk; + if (depth == info->dqi_qtree_depth - 1) { + #ifdef __QUOTA_QT_PARANOIA + if (newblk) { +@@ -370,16 +397,16 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + goto out_buf; + } + #endif +- newblk = find_free_dqentry(info, dquot, &ret); ++ blks[depth + 1] = find_free_dqentry(info, dquot, &ret); + } else { +- ret = do_insert_tree(info, dquot, &newblk, depth+1); ++ ret = do_insert_tree(info, dquot, blks, depth + 1); + } + if (newson && ret >= 0) { + ref[get_index(info, dquot->dq_id, depth)] = +- cpu_to_le32(newblk); +- ret = write_blk(info, *treeblk, buf); ++ cpu_to_le32(blks[depth + 1]); ++ ret = write_blk(info, blks[depth], buf); + } else if (newact && ret < 0) { +- put_free_dqblk(info, buf, *treeblk); ++ put_free_dqblk(info, buf, blks[depth]); + } + out_buf: + kfree(buf); +@@ -390,7 +417,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, + struct dquot *dquot) + { +- int tmp = QT_TREEOFF; ++ uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF }; + + #ifdef __QUOTA_QT_PARANOIA + if (info->dqi_blocks <= QT_TREEOFF) { +@@ -398,7 +425,11 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, + return -EIO; + } + #endif +- return do_insert_tree(info, dquot, &tmp, 0); ++ if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) { ++ quota_error(dquot->dq_sb, "Quota tree depth too big!"); ++ return -EIO; ++ } ++ return do_insert_tree(info, dquot, blks, 0); + } + + /* +@@ -511,19 +542,20 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, + + /* Remove reference to dquot from tree */ + static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, +- uint *blk, int depth) ++ uint *blks, int depth) + { + char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS); + int ret = 0; + uint newblk; + __le32 *ref = (__le32 *)buf; ++ int i; + + if (!buf) + return -ENOMEM; +- ret = read_blk(info, *blk, buf); ++ ret = read_blk(info, blks[depth], buf); + if (ret < 0) { + quota_error(dquot->dq_sb, "Can't read quota data block %u", +- *blk); ++ blks[depth]); + goto out_buf; + } + newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); +@@ -532,29 +564,38 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + if (ret) + goto out_buf; + ++ for (i = 0; i <= depth; i++) ++ if (newblk == blks[i]) { ++ quota_error(dquot->dq_sb, ++ "Cycle in quota tree detected: block %u index %u", ++ blks[depth], ++ get_index(info, dquot->dq_id, depth)); ++ ret = -EIO; ++ goto out_buf; ++ } + if (depth == info->dqi_qtree_depth - 1) { + ret = free_dqentry(info, dquot, newblk); +- newblk = 0; ++ blks[depth + 1] = 0; + } else { +- ret = remove_tree(info, dquot, &newblk, depth+1); ++ blks[depth + 1] = newblk; ++ ret = remove_tree(info, dquot, blks, depth + 1); + } +- if (ret >= 0 && !newblk) { +- int i; ++ if (ret >= 0 && !blks[depth + 1]) { + ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0); + /* Block got empty? */ + for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++) + ; + /* Don't put the root block into the free block list */ + if (i == (info->dqi_usable_bs >> 2) +- && *blk != QT_TREEOFF) { +- put_free_dqblk(info, buf, *blk); +- *blk = 0; ++ && blks[depth] != QT_TREEOFF) { ++ put_free_dqblk(info, buf, blks[depth]); ++ blks[depth] = 0; + } else { +- ret = write_blk(info, *blk, buf); ++ ret = write_blk(info, blks[depth], buf); + if (ret < 0) + quota_error(dquot->dq_sb, + "Can't write quota tree block %u", +- *blk); ++ blks[depth]); + } + } + out_buf: +@@ -565,11 +606,15 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + /* Delete dquot from tree */ + int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) + { +- uint tmp = QT_TREEOFF; ++ uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF }; + + if (!dquot->dq_off) /* Even not allocated? */ + return 0; +- return remove_tree(info, dquot, &tmp, 0); ++ if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) { ++ quota_error(dquot->dq_sb, "Quota tree depth too big!"); ++ return -EIO; ++ } ++ return remove_tree(info, dquot, blks, 0); + } + EXPORT_SYMBOL(qtree_delete_dquot); + +@@ -613,18 +658,20 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, + + /* Find entry for given id in the tree */ + static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, +- struct dquot *dquot, uint blk, int depth) ++ struct dquot *dquot, uint *blks, int depth) + { + char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS); + loff_t ret = 0; + __le32 *ref = (__le32 *)buf; ++ uint blk; ++ int i; + + if (!buf) + return -ENOMEM; +- ret = read_blk(info, blk, buf); ++ ret = read_blk(info, blks[depth], buf); + if (ret < 0) { + quota_error(dquot->dq_sb, "Can't read quota tree block %u", +- blk); ++ blks[depth]); + goto out_buf; + } + ret = 0; +@@ -636,8 +683,19 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, + if (ret) + goto out_buf; + ++ /* Check for cycles in the tree */ ++ for (i = 0; i <= depth; i++) ++ if (blk == blks[i]) { ++ quota_error(dquot->dq_sb, ++ "Cycle in quota tree detected: block %u index %u", ++ blks[depth], ++ get_index(info, dquot->dq_id, depth)); ++ ret = -EIO; ++ goto out_buf; ++ } ++ blks[depth + 1] = blk; + if (depth < info->dqi_qtree_depth - 1) +- ret = find_tree_dqentry(info, dquot, blk, depth+1); ++ ret = find_tree_dqentry(info, dquot, blks, depth + 1); + else + ret = find_block_dqentry(info, dquot, blk); + out_buf: +@@ -649,7 +707,13 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, + static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info, + struct dquot *dquot) + { +- return find_tree_dqentry(info, dquot, QT_TREEOFF, 0); ++ uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF }; ++ ++ if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) { ++ quota_error(dquot->dq_sb, "Quota tree depth too big!"); ++ return -EIO; ++ } ++ return find_tree_dqentry(info, dquot, blks, 0); + } + + int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) +diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c +index ae99e7b88205b2..7978ab671e0c6a 100644 +--- a/fs/quota/quota_v2.c ++++ b/fs/quota/quota_v2.c +@@ -166,14 +166,17 @@ static int v2_read_file_info(struct super_block *sb, int type) + i_size_read(sb_dqopt(sb)->files[type])); + goto out_free; + } +- if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { +- quota_error(sb, "Free block number too big (%u >= %u).", +- qinfo->dqi_free_blk, qinfo->dqi_blocks); ++ if (qinfo->dqi_free_blk && (qinfo->dqi_free_blk <= QT_TREEOFF || ++ qinfo->dqi_free_blk >= qinfo->dqi_blocks)) { ++ quota_error(sb, "Free block number %u out of range (%u, %u).", ++ qinfo->dqi_free_blk, QT_TREEOFF, qinfo->dqi_blocks); + goto out_free; + } +- if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { +- quota_error(sb, "Block with free entry too big (%u >= %u).", +- qinfo->dqi_free_entry, qinfo->dqi_blocks); ++ if (qinfo->dqi_free_entry && (qinfo->dqi_free_entry <= QT_TREEOFF || ++ qinfo->dqi_free_entry >= qinfo->dqi_blocks)) { ++ quota_error(sb, "Block with free entry %u out of range (%u, %u).", ++ qinfo->dqi_free_entry, QT_TREEOFF, ++ qinfo->dqi_blocks); + goto out_free; + } + ret = 0; +diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c +index 3676e02a0232a4..4ab8cab6ea6147 100644 +--- a/fs/reiserfs/stree.c ++++ b/fs/reiserfs/stree.c +@@ -1407,7 +1407,7 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, + INITIALIZE_PATH(path); + int item_len = 0; + int tb_init = 0; +- struct cpu_key cpu_key; ++ struct cpu_key cpu_key = {}; + int retval; + int quota_cut_bytes = 0; + +diff --git a/fs/romfs/super.c b/fs/romfs/super.c +index 5c35f6c760377e..b1bdfbc211c3c0 100644 +--- a/fs/romfs/super.c ++++ b/fs/romfs/super.c +@@ -593,7 +593,7 @@ static void romfs_kill_sb(struct super_block *sb) + #ifdef CONFIG_ROMFS_ON_BLOCK + if (sb->s_bdev) { + sync_blockdev(sb->s_bdev); +- blkdev_put(sb->s_bdev, sb); ++ bdev_release(sb->s_bdev_handle); + } + #endif + } +diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c +index 581ce951933901..2dc730800f448d 100644 +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -321,7 +321,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length, + TRACE("Block @ 0x%llx, %scompressed size %d\n", index - 2, + compressed ? "" : "un", length); + } +- if (length < 0 || length > output->length || ++ if (length <= 0 || length > output->length || + (index + length) > msblk->bytes_used) { + res = -EIO; + goto out; +diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c +index 8ba8c4c5077078..e8df6430444b01 100644 +--- a/fs/squashfs/file.c ++++ b/fs/squashfs/file.c +@@ -544,7 +544,8 @@ static void squashfs_readahead(struct readahead_control *ractl) + struct squashfs_page_actor *actor; + unsigned int nr_pages = 0; + struct page **pages; +- int i, file_end = i_size_read(inode) >> msblk->block_log; ++ int i; ++ loff_t file_end = i_size_read(inode) >> msblk->block_log; + unsigned int max_pages = 1UL << shift; + + readahead_expand(ractl, start, (len | mask) + 1); +diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c +index f1ccad519e28cc..763a3f7a75f6dd 100644 +--- a/fs/squashfs/file_direct.c ++++ b/fs/squashfs/file_direct.c +@@ -26,10 +26,10 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize, + struct inode *inode = target_page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + +- int file_end = (i_size_read(inode) - 1) >> PAGE_SHIFT; ++ loff_t file_end = (i_size_read(inode) - 1) >> PAGE_SHIFT; + int mask = (1 << (msblk->block_log - PAGE_SHIFT)) - 1; +- int start_index = target_page->index & ~mask; +- int end_index = start_index | mask; ++ loff_t start_index = target_page->index & ~mask; ++ loff_t end_index = start_index | mask; + int i, n, pages, bytes, res = -ENOMEM; + struct page **page; + struct squashfs_page_actor *actor; +diff --git a/fs/super.c b/fs/super.c +index 576abb1ff0403d..b142e71eb8dfdd 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -1490,14 +1490,16 @@ int setup_bdev_super(struct super_block *sb, int sb_flags, + struct fs_context *fc) + { + blk_mode_t mode = sb_open_mode(sb_flags); ++ struct bdev_handle *bdev_handle; + struct block_device *bdev; + +- bdev = blkdev_get_by_dev(sb->s_dev, mode, sb, &fs_holder_ops); +- if (IS_ERR(bdev)) { ++ bdev_handle = bdev_open_by_dev(sb->s_dev, mode, sb, &fs_holder_ops); ++ if (IS_ERR(bdev_handle)) { + if (fc) + errorf(fc, "%s: Can't open blockdev", fc->source); +- return PTR_ERR(bdev); ++ return PTR_ERR(bdev_handle); + } ++ bdev = bdev_handle->bdev; + + /* + * This really should be in blkdev_get_by_dev, but right now can't due +@@ -1505,7 +1507,7 @@ int setup_bdev_super(struct super_block *sb, int sb_flags, + * writable from userspace even for a read-only block device. + */ + if ((mode & BLK_OPEN_WRITE) && bdev_read_only(bdev)) { +- blkdev_put(bdev, sb); ++ bdev_release(bdev_handle); + return -EACCES; + } + +@@ -1521,10 +1523,11 @@ int setup_bdev_super(struct super_block *sb, int sb_flags, + mutex_unlock(&bdev->bd_fsfreeze_mutex); + if (fc) + warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev); +- blkdev_put(bdev, sb); ++ bdev_release(bdev_handle); + return -EBUSY; + } + spin_lock(&sb_lock); ++ sb->s_bdev_handle = bdev_handle; + sb->s_bdev = bdev; + sb->s_bdi = bdi_get(bdev->bd_disk->bdi); + if (bdev_stable_writes(bdev)) +@@ -1657,7 +1660,7 @@ void kill_block_super(struct super_block *sb) + generic_shutdown_super(sb); + if (bdev) { + sync_blockdev(bdev); +- blkdev_put(bdev, sb); ++ bdev_release(sb->s_bdev_handle); + } + } + +diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h +index 265da00a1a8b1b..6eefe5153a6ff7 100644 +--- a/include/linux/cgroup-defs.h ++++ b/include/linux/cgroup-defs.h +@@ -543,6 +543,10 @@ struct cgroup_root { + /* Unique id for this hierarchy. */ + int hierarchy_id; + ++ /* A list running through the active hierarchies */ ++ struct list_head root_list; ++ struct rcu_head rcu; /* Must be near the top */ ++ + /* + * The root cgroup. The containing cgroup_root will be destroyed on its + * release. cgrp->ancestors[0] will be used overflowing into the +@@ -556,9 +560,6 @@ struct cgroup_root { + /* Number of cgroups in the hierarchy, used only for /proc/cgroups */ + atomic_t nr_cgrps; + +- /* A list running through the active hierarchies */ +- struct list_head root_list; +- + /* Hierarchy-specific flags */ + unsigned int flags; + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 56dce38c478627..43e640fb4a7f77 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1036,7 +1036,7 @@ struct file_handle { + __u32 handle_bytes; + int handle_type; + /* file identifier */ +- unsigned char f_handle[]; ++ unsigned char f_handle[] __counted_by(handle_bytes); + }; + + static inline struct file *get_file(struct file *f) +@@ -1223,6 +1223,7 @@ struct super_block { + struct hlist_bl_head s_roots; /* alternate root dentries for NFS */ + struct list_head s_mounts; /* list of mounts; _not_ for fs use */ + struct block_device *s_bdev; ++ struct bdev_handle *s_bdev_handle; + struct backing_dev_info *s_bdi; + struct mtd_info *s_mtd; + struct hlist_node s_instances; +diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h +index bae5e2369b4f7a..1c1a5d926b1713 100644 +--- a/include/linux/sockptr.h ++++ b/include/linux/sockptr.h +@@ -50,11 +50,36 @@ static inline int copy_from_sockptr_offset(void *dst, sockptr_t src, + return 0; + } + ++/* Deprecated. ++ * This is unsafe, unless caller checked user provided optlen. ++ * Prefer copy_safe_from_sockptr() instead. ++ */ + static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size) + { + return copy_from_sockptr_offset(dst, src, 0, size); + } + ++/** ++ * copy_safe_from_sockptr: copy a struct from sockptr ++ * @dst: Destination address, in kernel space. This buffer must be @ksize ++ * bytes long. ++ * @ksize: Size of @dst struct. ++ * @optval: Source address. (in user or kernel space) ++ * @optlen: Size of @optval data. ++ * ++ * Returns: ++ * * -EINVAL: @optlen < @ksize ++ * * -EFAULT: access to userspace failed. ++ * * 0 : @ksize bytes were copied ++ */ ++static inline int copy_safe_from_sockptr(void *dst, size_t ksize, ++ sockptr_t optval, unsigned int optlen) ++{ ++ if (optlen < ksize) ++ return -EINVAL; ++ return copy_from_sockptr(dst, optval, ksize); ++} ++ + static inline int copy_to_sockptr_offset(sockptr_t dst, size_t offset, + const void *src, size_t size) + { +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index dbf5b21feafe48..3d8b215f32d5b0 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -336,7 +336,6 @@ struct svc_program { + const struct svc_version **pg_vers; /* version array */ + char * pg_name; /* service name */ + char * pg_class; /* class name: services sharing authentication */ +- struct svc_stat * pg_stats; /* rpc statistics */ + enum svc_auth_status (*pg_authenticate)(struct svc_rqst *rqstp); + __be32 (*pg_init_request)(struct svc_rqst *, + const struct svc_program *, +@@ -408,7 +407,9 @@ bool svc_rqst_replace_page(struct svc_rqst *rqstp, + void svc_rqst_release_pages(struct svc_rqst *rqstp); + void svc_rqst_free(struct svc_rqst *); + void svc_exit_thread(struct svc_rqst *); +-struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int, ++struct svc_serv * svc_create_pooled(struct svc_program *prog, ++ struct svc_stat *stats, ++ unsigned int bufsize, + int (*threadfn)(void *data)); + int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int); + int svc_pool_stats_open(struct svc_serv *serv, struct file *file); +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index fb09fd1767f289..ba6e346c8d669a 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -77,12 +77,29 @@ struct bpf_insn { + __s32 imm; /* signed immediate constant */ + }; + +-/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ ++/* Deprecated: use struct bpf_lpm_trie_key_u8 (when the "data" member is needed for ++ * byte access) or struct bpf_lpm_trie_key_hdr (when using an alternative type for ++ * the trailing flexible array member) instead. ++ */ + struct bpf_lpm_trie_key { + __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ + __u8 data[0]; /* Arbitrary size */ + }; + ++/* Header for bpf_lpm_trie_key structs */ ++struct bpf_lpm_trie_key_hdr { ++ __u32 prefixlen; ++}; ++ ++/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry, with trailing byte array. */ ++struct bpf_lpm_trie_key_u8 { ++ union { ++ struct bpf_lpm_trie_key_hdr hdr; ++ __u32 prefixlen; ++ }; ++ __u8 data[]; /* Arbitrary size */ ++}; ++ + struct bpf_cgroup_storage_key { + __u64 cgroup_inode_id; /* cgroup inode id */ + __u32 attach_type; /* program attach type (enum bpf_attach_type) */ +diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c +index b32be680da6cdc..d0febf07051edf 100644 +--- a/kernel/bpf/lpm_trie.c ++++ b/kernel/bpf/lpm_trie.c +@@ -164,13 +164,13 @@ static inline int extract_bit(const u8 *data, size_t index) + */ + static size_t longest_prefix_match(const struct lpm_trie *trie, + const struct lpm_trie_node *node, +- const struct bpf_lpm_trie_key *key) ++ const struct bpf_lpm_trie_key_u8 *key) + { + u32 limit = min(node->prefixlen, key->prefixlen); + u32 prefixlen = 0, i = 0; + + BUILD_BUG_ON(offsetof(struct lpm_trie_node, data) % sizeof(u32)); +- BUILD_BUG_ON(offsetof(struct bpf_lpm_trie_key, data) % sizeof(u32)); ++ BUILD_BUG_ON(offsetof(struct bpf_lpm_trie_key_u8, data) % sizeof(u32)); + + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(CONFIG_64BIT) + +@@ -229,7 +229,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) + { + struct lpm_trie *trie = container_of(map, struct lpm_trie, map); + struct lpm_trie_node *node, *found = NULL; +- struct bpf_lpm_trie_key *key = _key; ++ struct bpf_lpm_trie_key_u8 *key = _key; + + if (key->prefixlen > trie->max_prefixlen) + return NULL; +@@ -308,8 +308,9 @@ static long trie_update_elem(struct bpf_map *map, + { + struct lpm_trie *trie = container_of(map, struct lpm_trie, map); + struct lpm_trie_node *node, *im_node = NULL, *new_node = NULL; ++ struct lpm_trie_node *free_node = NULL; + struct lpm_trie_node __rcu **slot; +- struct bpf_lpm_trie_key *key = _key; ++ struct bpf_lpm_trie_key_u8 *key = _key; + unsigned long irq_flags; + unsigned int next_bit; + size_t matchlen = 0; +@@ -382,7 +383,7 @@ static long trie_update_elem(struct bpf_map *map, + trie->n_entries--; + + rcu_assign_pointer(*slot, new_node); +- kfree_rcu(node, rcu); ++ free_node = node; + + goto out; + } +@@ -429,6 +430,7 @@ static long trie_update_elem(struct bpf_map *map, + } + + spin_unlock_irqrestore(&trie->lock, irq_flags); ++ kfree_rcu(free_node, rcu); + + return ret; + } +@@ -437,7 +439,8 @@ static long trie_update_elem(struct bpf_map *map, + static long trie_delete_elem(struct bpf_map *map, void *_key) + { + struct lpm_trie *trie = container_of(map, struct lpm_trie, map); +- struct bpf_lpm_trie_key *key = _key; ++ struct lpm_trie_node *free_node = NULL, *free_parent = NULL; ++ struct bpf_lpm_trie_key_u8 *key = _key; + struct lpm_trie_node __rcu **trim, **trim2; + struct lpm_trie_node *node, *parent; + unsigned long irq_flags; +@@ -506,8 +509,8 @@ static long trie_delete_elem(struct bpf_map *map, void *_key) + else + rcu_assign_pointer( + *trim2, rcu_access_pointer(parent->child[0])); +- kfree_rcu(parent, rcu); +- kfree_rcu(node, rcu); ++ free_parent = parent; ++ free_node = node; + goto out; + } + +@@ -521,10 +524,12 @@ static long trie_delete_elem(struct bpf_map *map, void *_key) + rcu_assign_pointer(*trim, rcu_access_pointer(node->child[1])); + else + RCU_INIT_POINTER(*trim, NULL); +- kfree_rcu(node, rcu); ++ free_node = node; + + out: + spin_unlock_irqrestore(&trie->lock, irq_flags); ++ kfree_rcu(free_parent, rcu); ++ kfree_rcu(free_node, rcu); + + return ret; + } +@@ -536,7 +541,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key) + sizeof(struct lpm_trie_node)) + #define LPM_VAL_SIZE_MIN 1 + +-#define LPM_KEY_SIZE(X) (sizeof(struct bpf_lpm_trie_key) + (X)) ++#define LPM_KEY_SIZE(X) (sizeof(struct bpf_lpm_trie_key_u8) + (X)) + #define LPM_KEY_SIZE_MAX LPM_KEY_SIZE(LPM_DATA_SIZE_MAX) + #define LPM_KEY_SIZE_MIN LPM_KEY_SIZE(LPM_DATA_SIZE_MIN) + +@@ -565,7 +570,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr) + /* copy mandatory map attributes */ + bpf_map_init_from_attr(&trie->map, attr); + trie->data_size = attr->key_size - +- offsetof(struct bpf_lpm_trie_key, data); ++ offsetof(struct bpf_lpm_trie_key_u8, data); + trie->max_prefixlen = trie->data_size * 8; + + spin_lock_init(&trie->lock); +@@ -616,7 +621,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) + { + struct lpm_trie_node *node, *next_node = NULL, *parent, *search_root; + struct lpm_trie *trie = container_of(map, struct lpm_trie, map); +- struct bpf_lpm_trie_key *key = _key, *next_key = _next_key; ++ struct bpf_lpm_trie_key_u8 *key = _key, *next_key = _next_key; + struct lpm_trie_node **node_stack = NULL; + int err = 0, stack_ptr = -1; + unsigned int next_bit; +@@ -703,7 +708,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) + } + do_copy: + next_key->prefixlen = next_node->prefixlen; +- memcpy((void *)next_key + offsetof(struct bpf_lpm_trie_key, data), ++ memcpy((void *)next_key + offsetof(struct bpf_lpm_trie_key_u8, data), + next_node->data, trie->data_size); + free_stack: + kfree(node_stack); +@@ -715,7 +720,7 @@ static int trie_check_btf(const struct bpf_map *map, + const struct btf_type *key_type, + const struct btf_type *value_type) + { +- /* Keys must have struct bpf_lpm_trie_key embedded. */ ++ /* Keys must have struct bpf_lpm_trie_key_u8 embedded. */ + return BTF_INFO_KIND(key_type->info) != BTF_KIND_STRUCT ? + -EINVAL : 0; + } +diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h +index c56071f150f2ae..5e17f01ced9fd2 100644 +--- a/kernel/cgroup/cgroup-internal.h ++++ b/kernel/cgroup/cgroup-internal.h +@@ -170,7 +170,8 @@ extern struct list_head cgroup_roots; + + /* iterate across the hierarchies */ + #define for_each_root(root) \ +- list_for_each_entry((root), &cgroup_roots, root_list) ++ list_for_each_entry_rcu((root), &cgroup_roots, root_list, \ ++ lockdep_is_held(&cgroup_mutex)) + + /** + * for_each_subsys - iterate all enabled cgroup subsystems +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 094f513319259d..d872fff901073f 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -1313,7 +1313,7 @@ static void cgroup_exit_root_id(struct cgroup_root *root) + + void cgroup_free_root(struct cgroup_root *root) + { +- kfree(root); ++ kfree_rcu(root, rcu); + } + + static void cgroup_destroy_root(struct cgroup_root *root) +@@ -1346,7 +1346,7 @@ static void cgroup_destroy_root(struct cgroup_root *root) + spin_unlock_irq(&css_set_lock); + + if (!list_empty(&root->root_list)) { +- list_del(&root->root_list); ++ list_del_rcu(&root->root_list); + cgroup_root_count--; + } + +@@ -1386,7 +1386,15 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset, + } + } + +- BUG_ON(!res_cgroup); ++ /* ++ * If cgroup_mutex is not held, the cgrp_cset_link will be freed ++ * before we remove the cgroup root from the root_list. Consequently, ++ * when accessing a cgroup root, the cset_link may have already been ++ * freed, resulting in a NULL res_cgroup. However, by holding the ++ * cgroup_mutex, we ensure that res_cgroup can't be NULL. ++ * If we don't hold cgroup_mutex in the caller, we must do the NULL ++ * check. ++ */ + return res_cgroup; + } + +@@ -1445,7 +1453,6 @@ static struct cgroup *current_cgns_cgroup_dfl(void) + static struct cgroup *cset_cgroup_from_root(struct css_set *cset, + struct cgroup_root *root) + { +- lockdep_assert_held(&cgroup_mutex); + lockdep_assert_held(&css_set_lock); + + return __cset_cgroup_from_root(cset, root); +@@ -1453,7 +1460,9 @@ static struct cgroup *cset_cgroup_from_root(struct css_set *cset, + + /* + * Return the cgroup for "task" from the given hierarchy. Must be +- * called with cgroup_mutex and css_set_lock held. ++ * called with css_set_lock held to prevent task's groups from being modified. ++ * Must be called with either cgroup_mutex or rcu read lock to prevent the ++ * cgroup root from being destroyed. + */ + struct cgroup *task_cgroup_from_root(struct task_struct *task, + struct cgroup_root *root) +@@ -2014,7 +2023,7 @@ void init_cgroup_root(struct cgroup_fs_context *ctx) + struct cgroup_root *root = ctx->root; + struct cgroup *cgrp = &root->cgrp; + +- INIT_LIST_HEAD(&root->root_list); ++ INIT_LIST_HEAD_RCU(&root->root_list); + atomic_set(&root->nr_cgrps, 1); + cgrp->root = root; + init_cgroup_housekeeping(cgrp); +@@ -2097,7 +2106,7 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) + * care of subsystems' refcounts, which are explicitly dropped in + * the failure exit path. + */ +- list_add(&root->root_list, &cgroup_roots); ++ list_add_rcu(&root->root_list, &cgroup_roots); + cgroup_root_count++; + + /* +diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c +index 5ecd072a34fe72..eb86283901565b 100644 +--- a/kernel/irq/cpuhotplug.c ++++ b/kernel/irq/cpuhotplug.c +@@ -130,6 +130,22 @@ static bool migrate_one_irq(struct irq_desc *desc) + * CPU. + */ + err = irq_do_set_affinity(d, affinity, false); ++ ++ /* ++ * If there are online CPUs in the affinity mask, but they have no ++ * vectors left to make the migration work, try to break the ++ * affinity by migrating to any online CPU. ++ */ ++ if (err == -ENOSPC && !irqd_affinity_is_managed(d) && affinity != cpu_online_mask) { ++ pr_debug("IRQ%u: set affinity failed for %*pbl, re-try with online CPUs\n", ++ d->irq, cpumask_pr_args(affinity)); ++ ++ affinity = cpu_online_mask; ++ brokeaff = true; ++ ++ err = irq_do_set_affinity(d, affinity, false); ++ } ++ + if (err) { + pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n", + d->irq, err); +@@ -195,10 +211,15 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) + !irq_data_get_irq_chip(data) || !cpumask_test_cpu(cpu, affinity)) + return; + +- if (irqd_is_managed_and_shutdown(data)) { +- irq_startup(desc, IRQ_RESEND, IRQ_START_COND); ++ /* ++ * Don't restore suspended interrupts here when a system comes back ++ * from S3. They are reenabled via resume_device_irqs(). ++ */ ++ if (desc->istate & IRQS_SUSPENDED) + return; +- } ++ ++ if (irqd_is_managed_and_shutdown(data)) ++ irq_startup(desc, IRQ_RESEND, IRQ_START_COND); + + /* + * If the interrupt can only be directed to a single target +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index a054cd5ec08bce..8a936c1ffad390 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -796,10 +796,14 @@ void __enable_irq(struct irq_desc *desc) + irq_settings_set_noprobe(desc); + /* + * Call irq_startup() not irq_enable() here because the +- * interrupt might be marked NOAUTOEN. So irq_startup() +- * needs to be invoked when it gets enabled the first +- * time. If it was already started up, then irq_startup() +- * will invoke irq_enable() under the hood. ++ * interrupt might be marked NOAUTOEN so irq_startup() ++ * needs to be invoked when it gets enabled the first time. ++ * This is also required when __enable_irq() is invoked for ++ * a managed and shutdown interrupt from the S3 resume ++ * path. ++ * ++ * If it was already started up, then irq_startup() will ++ * invoke irq_enable() under the hood. + */ + irq_startup(desc, IRQ_RESEND, IRQ_START_FORCE); + break; +diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c +index 13f0d11927074a..68af76ca8bc992 100644 +--- a/mm/debug_vm_pgtable.c ++++ b/mm/debug_vm_pgtable.c +@@ -39,22 +39,7 @@ + * Please refer Documentation/mm/arch_pgtable_helpers.rst for the semantics + * expectations that are being validated here. All future changes in here + * or the documentation need to be in sync. +- * +- * On s390 platform, the lower 4 bits are used to identify given page table +- * entry type. But these bits might affect the ability to clear entries with +- * pxx_clear() because of how dynamic page table folding works on s390. So +- * while loading up the entries do not change the lower 4 bits. It does not +- * have affect any other platform. Also avoid the 62nd bit on ppc64 that is +- * used to mark a pte entry. + */ +-#define S390_SKIP_MASK GENMASK(3, 0) +-#if __BITS_PER_LONG == 64 +-#define PPC64_SKIP_MASK GENMASK(62, 62) +-#else +-#define PPC64_SKIP_MASK 0x0 +-#endif +-#define ARCH_SKIP_MASK (S390_SKIP_MASK | PPC64_SKIP_MASK) +-#define RANDOM_ORVALUE (GENMASK(BITS_PER_LONG - 1, 0) & ~ARCH_SKIP_MASK) + #define RANDOM_NZVALUE GENMASK(7, 0) + + struct pgtable_debug_args { +@@ -510,8 +495,7 @@ static void __init pud_clear_tests(struct pgtable_debug_args *args) + return; + + pr_debug("Validating PUD clear\n"); +- pud = __pud(pud_val(pud) | RANDOM_ORVALUE); +- WRITE_ONCE(*args->pudp, pud); ++ WARN_ON(pud_none(pud)); + pud_clear(args->pudp); + pud = READ_ONCE(*args->pudp); + WARN_ON(!pud_none(pud)); +@@ -547,8 +531,7 @@ static void __init p4d_clear_tests(struct pgtable_debug_args *args) + return; + + pr_debug("Validating P4D clear\n"); +- p4d = __p4d(p4d_val(p4d) | RANDOM_ORVALUE); +- WRITE_ONCE(*args->p4dp, p4d); ++ WARN_ON(p4d_none(p4d)); + p4d_clear(args->p4dp); + p4d = READ_ONCE(*args->p4dp); + WARN_ON(!p4d_none(p4d)); +@@ -581,8 +564,7 @@ static void __init pgd_clear_tests(struct pgtable_debug_args *args) + return; + + pr_debug("Validating PGD clear\n"); +- pgd = __pgd(pgd_val(pgd) | RANDOM_ORVALUE); +- WRITE_ONCE(*args->pgdp, pgd); ++ WARN_ON(pgd_none(pgd)); + pgd_clear(args->pgdp); + pgd = READ_ONCE(*args->pgdp); + WARN_ON(!pgd_none(pgd)); +@@ -633,10 +615,8 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args) + if (WARN_ON(!args->ptep)) + return; + +-#ifndef CONFIG_RISCV +- pte = __pte(pte_val(pte) | RANDOM_ORVALUE); +-#endif + set_pte_at(args->mm, args->vaddr, args->ptep, pte); ++ WARN_ON(pte_none(pte)); + flush_dcache_page(page); + barrier(); + ptep_clear(args->mm, args->vaddr, args->ptep); +@@ -649,8 +629,7 @@ static void __init pmd_clear_tests(struct pgtable_debug_args *args) + pmd_t pmd = READ_ONCE(*args->pmdp); + + pr_debug("Validating PMD clear\n"); +- pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE); +- WRITE_ONCE(*args->pmdp, pmd); ++ WARN_ON(pmd_none(pmd)); + pmd_clear(args->pmdp); + pmd = READ_ONCE(*args->pmdp); + WARN_ON(!pmd_none(pmd)); +diff --git a/mm/gup.c b/mm/gup.c +index f50fe2219a13b6..fdd75384160d8d 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -97,95 +97,6 @@ static inline struct folio *try_get_folio(struct page *page, int refs) + return folio; + } + +-/** +- * try_grab_folio() - Attempt to get or pin a folio. +- * @page: pointer to page to be grabbed +- * @refs: the value to (effectively) add to the folio's refcount +- * @flags: gup flags: these are the FOLL_* flag values. +- * +- * "grab" names in this file mean, "look at flags to decide whether to use +- * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount. +- * +- * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the +- * same time. (That's true throughout the get_user_pages*() and +- * pin_user_pages*() APIs.) Cases: +- * +- * FOLL_GET: folio's refcount will be incremented by @refs. +- * +- * FOLL_PIN on large folios: folio's refcount will be incremented by +- * @refs, and its pincount will be incremented by @refs. +- * +- * FOLL_PIN on single-page folios: folio's refcount will be incremented by +- * @refs * GUP_PIN_COUNTING_BIAS. +- * +- * Return: The folio containing @page (with refcount appropriately +- * incremented) for success, or NULL upon failure. If neither FOLL_GET +- * nor FOLL_PIN was set, that's considered failure, and furthermore, +- * a likely bug in the caller, so a warning is also emitted. +- */ +-struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags) +-{ +- struct folio *folio; +- +- if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0)) +- return NULL; +- +- if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page))) +- return NULL; +- +- if (flags & FOLL_GET) +- return try_get_folio(page, refs); +- +- /* FOLL_PIN is set */ +- +- /* +- * Don't take a pin on the zero page - it's not going anywhere +- * and it is used in a *lot* of places. +- */ +- if (is_zero_page(page)) +- return page_folio(page); +- +- folio = try_get_folio(page, refs); +- if (!folio) +- return NULL; +- +- /* +- * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a +- * right zone, so fail and let the caller fall back to the slow +- * path. +- */ +- if (unlikely((flags & FOLL_LONGTERM) && +- !folio_is_longterm_pinnable(folio))) { +- if (!put_devmap_managed_page_refs(&folio->page, refs)) +- folio_put_refs(folio, refs); +- return NULL; +- } +- +- /* +- * When pinning a large folio, use an exact count to track it. +- * +- * However, be sure to *also* increment the normal folio +- * refcount field at least once, so that the folio really +- * is pinned. That's why the refcount from the earlier +- * try_get_folio() is left intact. +- */ +- if (folio_test_large(folio)) +- atomic_add(refs, &folio->_pincount); +- else +- folio_ref_add(folio, +- refs * (GUP_PIN_COUNTING_BIAS - 1)); +- /* +- * Adjust the pincount before re-checking the PTE for changes. +- * This is essentially a smp_mb() and is paired with a memory +- * barrier in page_try_share_anon_rmap(). +- */ +- smp_mb__after_atomic(); +- +- node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs); +- +- return folio; +-} +- + static void gup_put_folio(struct folio *folio, int refs, unsigned int flags) + { + if (flags & FOLL_PIN) { +@@ -203,58 +114,59 @@ static void gup_put_folio(struct folio *folio, int refs, unsigned int flags) + } + + /** +- * try_grab_page() - elevate a page's refcount by a flag-dependent amount +- * @page: pointer to page to be grabbed +- * @flags: gup flags: these are the FOLL_* flag values. ++ * try_grab_folio() - add a folio's refcount by a flag-dependent amount ++ * @folio: pointer to folio to be grabbed ++ * @refs: the value to (effectively) add to the folio's refcount ++ * @flags: gup flags: these are the FOLL_* flag values + * + * This might not do anything at all, depending on the flags argument. + * + * "grab" names in this file mean, "look at flags to decide whether to use +- * FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount. ++ * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount. + * + * Either FOLL_PIN or FOLL_GET (or neither) may be set, but not both at the same +- * time. Cases: please see the try_grab_folio() documentation, with +- * "refs=1". ++ * time. + * + * Return: 0 for success, or if no action was required (if neither FOLL_PIN + * nor FOLL_GET was set, nothing is done). A negative error code for failure: + * +- * -ENOMEM FOLL_GET or FOLL_PIN was set, but the page could not ++ * -ENOMEM FOLL_GET or FOLL_PIN was set, but the folio could not + * be grabbed. ++ * ++ * It is called when we have a stable reference for the folio, typically in ++ * GUP slow path. + */ +-int __must_check try_grab_page(struct page *page, unsigned int flags) ++int __must_check try_grab_folio(struct folio *folio, int refs, ++ unsigned int flags) + { +- struct folio *folio = page_folio(page); +- + if (WARN_ON_ONCE(folio_ref_count(folio) <= 0)) + return -ENOMEM; + +- if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page))) ++ if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(&folio->page))) + return -EREMOTEIO; + + if (flags & FOLL_GET) +- folio_ref_inc(folio); ++ folio_ref_add(folio, refs); + else if (flags & FOLL_PIN) { + /* + * Don't take a pin on the zero page - it's not going anywhere + * and it is used in a *lot* of places. + */ +- if (is_zero_page(page)) ++ if (is_zero_folio(folio)) + return 0; + + /* +- * Similar to try_grab_folio(): be sure to *also* +- * increment the normal page refcount field at least once, ++ * Increment the normal page refcount field at least once, + * so that the page really is pinned. + */ + if (folio_test_large(folio)) { +- folio_ref_add(folio, 1); +- atomic_add(1, &folio->_pincount); ++ folio_ref_add(folio, refs); ++ atomic_add(refs, &folio->_pincount); + } else { +- folio_ref_add(folio, GUP_PIN_COUNTING_BIAS); ++ folio_ref_add(folio, refs * GUP_PIN_COUNTING_BIAS); + } + +- node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, 1); ++ node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs); + } + + return 0; +@@ -647,8 +559,8 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, + VM_BUG_ON_PAGE((flags & FOLL_PIN) && PageAnon(page) && + !PageAnonExclusive(page), page); + +- /* try_grab_page() does nothing unless FOLL_GET or FOLL_PIN is set. */ +- ret = try_grab_page(page, flags); ++ /* try_grab_folio() does nothing unless FOLL_GET or FOLL_PIN is set. */ ++ ret = try_grab_folio(page_folio(page), 1, flags); + if (unlikely(ret)) { + page = ERR_PTR(ret); + goto out; +@@ -899,7 +811,7 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address, + goto unmap; + *page = pte_page(entry); + } +- ret = try_grab_page(*page, gup_flags); ++ ret = try_grab_folio(page_folio(*page), 1, gup_flags); + if (unlikely(ret)) + goto unmap; + out: +@@ -1302,20 +1214,19 @@ static long __get_user_pages(struct mm_struct *mm, + * pages. + */ + if (page_increm > 1) { +- struct folio *folio; ++ struct folio *folio = page_folio(page); + + /* + * Since we already hold refcount on the + * large folio, this should never fail. + */ +- folio = try_grab_folio(page, page_increm - 1, +- foll_flags); +- if (WARN_ON_ONCE(!folio)) { ++ if (try_grab_folio(folio, page_increm - 1, ++ foll_flags)) { + /* + * Release the 1st page ref if the + * folio is problematic, fail hard. + */ +- gup_put_folio(page_folio(page), 1, ++ gup_put_folio(folio, 1, + foll_flags); + ret = -EFAULT; + goto out; +@@ -2541,6 +2452,102 @@ static void __maybe_unused undo_dev_pagemap(int *nr, int nr_start, + } + } + ++/** ++ * try_grab_folio_fast() - Attempt to get or pin a folio in fast path. ++ * @page: pointer to page to be grabbed ++ * @refs: the value to (effectively) add to the folio's refcount ++ * @flags: gup flags: these are the FOLL_* flag values. ++ * ++ * "grab" names in this file mean, "look at flags to decide whether to use ++ * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount. ++ * ++ * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the ++ * same time. (That's true throughout the get_user_pages*() and ++ * pin_user_pages*() APIs.) Cases: ++ * ++ * FOLL_GET: folio's refcount will be incremented by @refs. ++ * ++ * FOLL_PIN on large folios: folio's refcount will be incremented by ++ * @refs, and its pincount will be incremented by @refs. ++ * ++ * FOLL_PIN on single-page folios: folio's refcount will be incremented by ++ * @refs * GUP_PIN_COUNTING_BIAS. ++ * ++ * Return: The folio containing @page (with refcount appropriately ++ * incremented) for success, or NULL upon failure. If neither FOLL_GET ++ * nor FOLL_PIN was set, that's considered failure, and furthermore, ++ * a likely bug in the caller, so a warning is also emitted. ++ * ++ * It uses add ref unless zero to elevate the folio refcount and must be called ++ * in fast path only. ++ */ ++static struct folio *try_grab_folio_fast(struct page *page, int refs, ++ unsigned int flags) ++{ ++ struct folio *folio; ++ ++ /* Raise warn if it is not called in fast GUP */ ++ VM_WARN_ON_ONCE(!irqs_disabled()); ++ ++ if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0)) ++ return NULL; ++ ++ if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page))) ++ return NULL; ++ ++ if (flags & FOLL_GET) ++ return try_get_folio(page, refs); ++ ++ /* FOLL_PIN is set */ ++ ++ /* ++ * Don't take a pin on the zero page - it's not going anywhere ++ * and it is used in a *lot* of places. ++ */ ++ if (is_zero_page(page)) ++ return page_folio(page); ++ ++ folio = try_get_folio(page, refs); ++ if (!folio) ++ return NULL; ++ ++ /* ++ * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a ++ * right zone, so fail and let the caller fall back to the slow ++ * path. ++ */ ++ if (unlikely((flags & FOLL_LONGTERM) && ++ !folio_is_longterm_pinnable(folio))) { ++ if (!put_devmap_managed_page_refs(&folio->page, refs)) ++ folio_put_refs(folio, refs); ++ return NULL; ++ } ++ ++ /* ++ * When pinning a large folio, use an exact count to track it. ++ * ++ * However, be sure to *also* increment the normal folio ++ * refcount field at least once, so that the folio really ++ * is pinned. That's why the refcount from the earlier ++ * try_get_folio() is left intact. ++ */ ++ if (folio_test_large(folio)) ++ atomic_add(refs, &folio->_pincount); ++ else ++ folio_ref_add(folio, ++ refs * (GUP_PIN_COUNTING_BIAS - 1)); ++ /* ++ * Adjust the pincount before re-checking the PTE for changes. ++ * This is essentially a smp_mb() and is paired with a memory ++ * barrier in folio_try_share_anon_rmap_*(). ++ */ ++ smp_mb__after_atomic(); ++ ++ node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs); ++ ++ return folio; ++} ++ + #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL + /* + * Fast-gup relies on pte change detection to avoid concurrent pgtable +@@ -2605,7 +2612,7 @@ static int gup_pte_range(pmd_t pmd, pmd_t *pmdp, unsigned long addr, + VM_BUG_ON(!pfn_valid(pte_pfn(pte))); + page = pte_page(pte); + +- folio = try_grab_folio(page, 1, flags); ++ folio = try_grab_folio_fast(page, 1, flags); + if (!folio) + goto pte_unmap; + +@@ -2699,7 +2706,7 @@ static int __gup_device_huge(unsigned long pfn, unsigned long addr, + + SetPageReferenced(page); + pages[*nr] = page; +- if (unlikely(try_grab_page(page, flags))) { ++ if (unlikely(try_grab_folio(page_folio(page), 1, flags))) { + undo_dev_pagemap(nr, nr_start, flags, pages); + break; + } +@@ -2808,7 +2815,7 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, + page = nth_page(pte_page(pte), (addr & (sz - 1)) >> PAGE_SHIFT); + refs = record_subpages(page, addr, end, pages + *nr); + +- folio = try_grab_folio(page, refs, flags); ++ folio = try_grab_folio_fast(page, refs, flags); + if (!folio) + return 0; + +@@ -2879,7 +2886,7 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, + page = nth_page(pmd_page(orig), (addr & ~PMD_MASK) >> PAGE_SHIFT); + refs = record_subpages(page, addr, end, pages + *nr); + +- folio = try_grab_folio(page, refs, flags); ++ folio = try_grab_folio_fast(page, refs, flags); + if (!folio) + return 0; + +@@ -2923,7 +2930,7 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, + page = nth_page(pud_page(orig), (addr & ~PUD_MASK) >> PAGE_SHIFT); + refs = record_subpages(page, addr, end, pages + *nr); + +- folio = try_grab_folio(page, refs, flags); ++ folio = try_grab_folio_fast(page, refs, flags); + if (!folio) + return 0; + +@@ -2963,7 +2970,7 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, + page = nth_page(pgd_page(orig), (addr & ~PGDIR_MASK) >> PAGE_SHIFT); + refs = record_subpages(page, addr, end, pages + *nr); + +- folio = try_grab_folio(page, refs, flags); ++ folio = try_grab_folio_fast(page, refs, flags); + if (!folio) + return 0; + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 7ac2877e76629b..f2816c9a1f3ec8 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1056,7 +1056,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr, + if (!*pgmap) + return ERR_PTR(-EFAULT); + page = pfn_to_page(pfn); +- ret = try_grab_page(page, flags); ++ ret = try_grab_folio(page_folio(page), 1, flags); + if (ret) + page = ERR_PTR(ret); + +@@ -1214,7 +1214,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, + return ERR_PTR(-EFAULT); + page = pfn_to_page(pfn); + +- ret = try_grab_page(page, flags); ++ ret = try_grab_folio(page_folio(page), 1, flags); + if (ret) + page = ERR_PTR(ret); + +@@ -1475,7 +1475,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, + VM_BUG_ON_PAGE((flags & FOLL_PIN) && PageAnon(page) && + !PageAnonExclusive(page), page); + +- ret = try_grab_page(page, flags); ++ ret = try_grab_folio(page_folio(page), 1, flags); + if (ret) + return ERR_PTR(ret); + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index fb7a531fce7174..0acb04c3e95291 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -6532,7 +6532,7 @@ struct page *hugetlb_follow_page_mask(struct vm_area_struct *vma, + * try_grab_page() should always be able to get the page here, + * because we hold the ptl lock and have verified pte_present(). + */ +- ret = try_grab_page(page, flags); ++ ret = try_grab_folio(page_folio(page), 1, flags); + + if (WARN_ON_ONCE(ret)) { + page = ERR_PTR(ret); +diff --git a/mm/internal.h b/mm/internal.h +index abed947f784b7b..ef8d787a510c5c 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -938,8 +938,8 @@ int migrate_device_coherent_page(struct page *page); + /* + * mm/gup.c + */ +-struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags); +-int __must_check try_grab_page(struct page *page, unsigned int flags); ++int __must_check try_grab_folio(struct folio *folio, int refs, ++ unsigned int flags); + + /* + * mm/huge_memory.c +diff --git a/mm/page_table_check.c b/mm/page_table_check.c +index 6363f93a47c691..509c6ef8de400e 100644 +--- a/mm/page_table_check.c ++++ b/mm/page_table_check.c +@@ -7,6 +7,8 @@ + #include + #include + #include ++#include ++#include + + #undef pr_fmt + #define pr_fmt(fmt) "page_table_check: " fmt +@@ -191,6 +193,22 @@ void __page_table_check_pud_clear(struct mm_struct *mm, pud_t pud) + } + EXPORT_SYMBOL(__page_table_check_pud_clear); + ++/* Whether the swap entry cached writable information */ ++static inline bool swap_cached_writable(swp_entry_t entry) ++{ ++ return is_writable_device_exclusive_entry(entry) || ++ is_writable_device_private_entry(entry) || ++ is_writable_migration_entry(entry); ++} ++ ++static inline void page_table_check_pte_flags(pte_t pte) ++{ ++ if (pte_present(pte) && pte_uffd_wp(pte)) ++ WARN_ON_ONCE(pte_write(pte)); ++ else if (is_swap_pte(pte) && pte_swp_uffd_wp(pte)) ++ WARN_ON_ONCE(swap_cached_writable(pte_to_swp_entry(pte))); ++} ++ + void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte, + unsigned int nr) + { +@@ -199,6 +217,8 @@ void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte, + if (&init_mm == mm) + return; + ++ page_table_check_pte_flags(pte); ++ + for (i = 0; i < nr; i++) + __page_table_check_pte_clear(mm, ptep_get(ptep + i)); + if (pte_user_accessible_page(pte)) +@@ -206,11 +226,21 @@ void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte, + } + EXPORT_SYMBOL(__page_table_check_ptes_set); + ++static inline void page_table_check_pmd_flags(pmd_t pmd) ++{ ++ if (pmd_present(pmd) && pmd_uffd_wp(pmd)) ++ WARN_ON_ONCE(pmd_write(pmd)); ++ else if (is_swap_pmd(pmd) && pmd_swp_uffd_wp(pmd)) ++ WARN_ON_ONCE(swap_cached_writable(pmd_to_swp_entry(pmd))); ++} ++ + void __page_table_check_pmd_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd) + { + if (&init_mm == mm) + return; + ++ page_table_check_pmd_flags(pmd); ++ + __page_table_check_pmd_clear(mm, *pmdp); + if (pmd_user_accessible_page(pmd)) { + page_table_check_set(pmd_pfn(pmd), PMD_SIZE >> PAGE_SHIFT, +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index b54e8a530f55a1..29aa07e9db9d71 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, + + switch (optname) { + case RFCOMM_LM: +- if (copy_from_sockptr(&opt, optval, sizeof(u32))) { ++ if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) { + err = -EFAULT; + break; + } +@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, + struct sock *sk = sock->sk; + struct bt_security sec; + int err = 0; +- size_t len; + u32 opt; + + BT_DBG("sk %p", sk); +@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, + + sec.level = BT_SECURITY_LOW; + +- len = min_t(unsigned int, sizeof(sec), optlen); +- if (copy_from_sockptr(&sec, optval, len)) { +- err = -EFAULT; ++ err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen); ++ if (err) + break; +- } + + if (sec.level > BT_SECURITY_HIGH) { + err = -EINVAL; +@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- if (copy_from_sockptr(&opt, optval, sizeof(u32))) { +- err = -EFAULT; ++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); ++ if (err) + break; +- } + + if (opt) + set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); +diff --git a/net/core/filter.c b/net/core/filter.c +index 8cb44cd29967bb..be313928d272c6 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2271,12 +2271,12 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v6(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + out_xmit: + return ret; +@@ -2378,12 +2378,12 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v4(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + out_xmit: + return ret; +diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c +index 0c41076e31edad..b38b82ae903de0 100644 +--- a/net/ipv4/fou_core.c ++++ b/net/ipv4/fou_core.c +@@ -433,7 +433,7 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, + + offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; + ops = rcu_dereference(offloads[proto]); +- if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) ++ if (!ops || !ops->callbacks.gro_receive) + goto out; + + pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); +diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c +index b71f94a5932ac0..e0883ba709b0bf 100644 +--- a/net/ipv4/tcp_metrics.c ++++ b/net/ipv4/tcp_metrics.c +@@ -899,11 +899,13 @@ static void tcp_metrics_flush_all(struct net *net) + unsigned int row; + + for (row = 0; row < max_rows; row++, hb++) { +- struct tcp_metrics_block __rcu **pp; ++ struct tcp_metrics_block __rcu **pp = &hb->chain; + bool match; + ++ if (!rcu_access_pointer(*pp)) ++ continue; ++ + spin_lock_bh(&tcp_metrics_lock); +- pp = &hb->chain; + for (tm = deref_locked(*pp); tm; tm = deref_locked(*pp)) { + match = net ? net_eq(tm_net(tm), net) : + !refcount_read(&tm_net(tm)->ns.count); +@@ -915,6 +917,7 @@ static void tcp_metrics_flush_all(struct net *net) + } + } + spin_unlock_bh(&tcp_metrics_lock); ++ cond_resched(); + } + } + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 6e3bfb46af44d3..52b048807feae5 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -251,9 +251,9 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata + return ret; + } + +-static int ieee80211_change_mac(struct net_device *dev, void *addr) ++static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata, ++ void *addr) + { +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct sockaddr *sa = addr; + bool check_dup = true; +@@ -278,7 +278,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) + + if (live) + drv_remove_interface(local, sdata); +- ret = eth_mac_addr(dev, sa); ++ ret = eth_mac_addr(sdata->dev, sa); + + if (ret == 0) { + memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); +@@ -294,6 +294,27 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) + return ret; + } + ++static int ieee80211_change_mac(struct net_device *dev, void *addr) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ int ret; ++ ++ /* ++ * This happens during unregistration if there's a bond device ++ * active (maybe other cases?) and we must get removed from it. ++ * But we really don't care anymore if it's not registered now. ++ */ ++ if (!dev->ieee80211_ptr->registered) ++ return 0; ++ ++ wiphy_lock(local->hw.wiphy); ++ ret = _ieee80211_change_mac(sdata, addr); ++ wiphy_unlock(local->hw.wiphy); ++ ++ return ret; ++} ++ + static inline int identical_mac_addr_allowed(int type1, int type2) + { + return type1 == NL80211_IFTYPE_MONITOR || +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 819157bbb5a2c6..d5344563e525c9 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -252,10 +252,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- if (copy_from_sockptr(&opt, optval, sizeof(u32))) { +- err = -EFAULT; ++ err = copy_safe_from_sockptr(&opt, sizeof(opt), ++ optval, optlen); ++ if (err) + break; +- } + + if (opt > LLCP_MAX_RW) { + err = -EINVAL; +@@ -274,10 +274,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- if (copy_from_sockptr(&opt, optval, sizeof(u32))) { +- err = -EFAULT; ++ err = copy_safe_from_sockptr(&opt, sizeof(opt), ++ optval, optlen); ++ if (err) + break; +- } + + if (opt > LLCP_MAX_MIUX) { + err = -EINVAL; +diff --git a/net/rds/recv.c b/net/rds/recv.c +index c71b923764fd7c..5627f80013f8b1 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -425,6 +425,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, + struct sock *sk = rds_rs_to_sk(rs); + int ret = 0; + unsigned long flags; ++ struct rds_incoming *to_drop = NULL; + + write_lock_irqsave(&rs->rs_recv_lock, flags); + if (!list_empty(&inc->i_item)) { +@@ -435,11 +436,14 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, + -be32_to_cpu(inc->i_hdr.h_len), + inc->i_hdr.h_dport); + list_del_init(&inc->i_item); +- rds_inc_put(inc); ++ to_drop = inc; + } + } + write_unlock_irqrestore(&rs->rs_recv_lock, flags); + ++ if (to_drop) ++ rds_inc_put(to_drop); ++ + rdsdebug("inc %p rs %p still %d dropped %d\n", inc, rs, ret, drop); + return ret; + } +@@ -758,16 +762,21 @@ void rds_clear_recv_queue(struct rds_sock *rs) + struct sock *sk = rds_rs_to_sk(rs); + struct rds_incoming *inc, *tmp; + unsigned long flags; ++ LIST_HEAD(to_drop); + + write_lock_irqsave(&rs->rs_recv_lock, flags); + list_for_each_entry_safe(inc, tmp, &rs->rs_recv_queue, i_item) { + rds_recv_rcvbuf_delta(rs, sk, inc->i_conn->c_lcong, + -be32_to_cpu(inc->i_hdr.h_len), + inc->i_hdr.h_dport); ++ list_move(&inc->i_item, &to_drop); ++ } ++ write_unlock_irqrestore(&rs->rs_recv_lock, flags); ++ ++ list_for_each_entry_safe(inc, tmp, &to_drop, i_item) { + list_del_init(&inc->i_item); + rds_inc_put(inc); + } +- write_unlock_irqrestore(&rs->rs_recv_lock, flags); + } + + /* +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 4023c955036b12..6ab9359c1706f1 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -522,8 +522,9 @@ static void dev_watchdog(struct timer_list *t) + + if (unlikely(timedout_ms)) { + trace_net_dev_xmit_timeout(dev, i); +- WARN_ONCE(1, "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out %u ms\n", +- dev->name, netdev_drivername(dev), i, timedout_ms); ++ netdev_crit(dev, "NETDEV WATCHDOG: CPU: %d: transmit queue %u timed out %u ms\n", ++ raw_smp_processor_id(), ++ i, timedout_ms); + netif_freeze_queues(dev); + dev->netdev_ops->ndo_tx_timeout(dev, i); + netif_unfreeze_queues(dev); +diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c +index 7182c5a450fb5b..5c165218180588 100644 +--- a/net/sctp/inqueue.c ++++ b/net/sctp/inqueue.c +@@ -38,6 +38,14 @@ void sctp_inq_init(struct sctp_inq *queue) + INIT_WORK(&queue->immediate, NULL); + } + ++/* Properly release the chunk which is being worked on. */ ++static inline void sctp_inq_chunk_free(struct sctp_chunk *chunk) ++{ ++ if (chunk->head_skb) ++ chunk->skb = chunk->head_skb; ++ sctp_chunk_free(chunk); ++} ++ + /* Release the memory associated with an SCTP inqueue. */ + void sctp_inq_free(struct sctp_inq *queue) + { +@@ -53,7 +61,7 @@ void sctp_inq_free(struct sctp_inq *queue) + * free it as well. + */ + if (queue->in_progress) { +- sctp_chunk_free(queue->in_progress); ++ sctp_inq_chunk_free(queue->in_progress); + queue->in_progress = NULL; + } + } +@@ -130,9 +138,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + goto new_skb; + } + +- if (chunk->head_skb) +- chunk->skb = chunk->head_skb; +- sctp_chunk_free(chunk); ++ sctp_inq_chunk_free(chunk); + chunk = queue->in_progress = NULL; + } else { + /* Nothing to do. Next chunk in the packet, please. */ +diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c +index 65fc1297c6dfa4..383860cb1d5b0f 100644 +--- a/net/sunrpc/stats.c ++++ b/net/sunrpc/stats.c +@@ -314,7 +314,7 @@ EXPORT_SYMBOL_GPL(rpc_proc_unregister); + struct proc_dir_entry * + svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops) + { +- return do_register(net, statp->program->pg_name, statp, proc_ops); ++ return do_register(net, statp->program->pg_name, net, proc_ops); + } + EXPORT_SYMBOL_GPL(svc_proc_register); + +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index 691499d1d2315c..029c49065016ac 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -453,8 +453,8 @@ __svc_init_bc(struct svc_serv *serv) + * Create an RPC service + */ + static struct svc_serv * +-__svc_create(struct svc_program *prog, unsigned int bufsize, int npools, +- int (*threadfn)(void *data)) ++__svc_create(struct svc_program *prog, struct svc_stat *stats, ++ unsigned int bufsize, int npools, int (*threadfn)(void *data)) + { + struct svc_serv *serv; + unsigned int vers; +@@ -466,7 +466,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, + serv->sv_name = prog->pg_name; + serv->sv_program = prog; + kref_init(&serv->sv_refcnt); +- serv->sv_stats = prog->pg_stats; ++ serv->sv_stats = stats; + if (bufsize > RPCSVC_MAXPAYLOAD) + bufsize = RPCSVC_MAXPAYLOAD; + serv->sv_max_payload = bufsize? bufsize : 4096; +@@ -532,26 +532,28 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, + struct svc_serv *svc_create(struct svc_program *prog, unsigned int bufsize, + int (*threadfn)(void *data)) + { +- return __svc_create(prog, bufsize, 1, threadfn); ++ return __svc_create(prog, NULL, bufsize, 1, threadfn); + } + EXPORT_SYMBOL_GPL(svc_create); + + /** + * svc_create_pooled - Create an RPC service with pooled threads + * @prog: the RPC program the new service will handle ++ * @stats: the stats struct if desired + * @bufsize: maximum message size for @prog + * @threadfn: a function to service RPC requests for @prog + * + * Returns an instantiated struct svc_serv object or NULL. + */ + struct svc_serv *svc_create_pooled(struct svc_program *prog, ++ struct svc_stat *stats, + unsigned int bufsize, + int (*threadfn)(void *data)) + { + struct svc_serv *serv; + unsigned int npools = svc_pool_map_get(); + +- serv = __svc_create(prog, bufsize, npools, threadfn); ++ serv = __svc_create(prog, stats, bufsize, npools, threadfn); + if (!serv) + goto out_err; + return serv; +@@ -1377,7 +1379,8 @@ svc_process_common(struct svc_rqst *rqstp) + goto err_bad_proc; + + /* Syntactic check complete */ +- serv->sv_stats->rpccnt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpccnt++; + trace_svc_process(rqstp, progp->pg_name); + + aoffset = xdr_stream_pos(xdr); +@@ -1429,7 +1432,8 @@ svc_process_common(struct svc_rqst *rqstp) + goto close_xprt; + + err_bad_rpc: +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + xdr_stream_encode_u32(xdr, RPC_MSG_DENIED); + xdr_stream_encode_u32(xdr, RPC_MISMATCH); + /* Only RPCv2 supported */ +@@ -1440,7 +1444,8 @@ svc_process_common(struct svc_rqst *rqstp) + err_bad_auth: + dprintk("svc: authentication failed (%d)\n", + be32_to_cpu(rqstp->rq_auth_stat)); +- serv->sv_stats->rpcbadauth++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadauth++; + /* Restore write pointer to location of reply status: */ + xdr_truncate_encode(xdr, XDR_UNIT * 2); + xdr_stream_encode_u32(xdr, RPC_MSG_DENIED); +@@ -1450,7 +1455,8 @@ svc_process_common(struct svc_rqst *rqstp) + + err_bad_prog: + dprintk("svc: unknown program %d\n", rqstp->rq_prog); +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + *rqstp->rq_accept_statp = rpc_prog_unavail; + goto sendit; + +@@ -1458,7 +1464,8 @@ svc_process_common(struct svc_rqst *rqstp) + svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", + rqstp->rq_vers, rqstp->rq_prog, progp->pg_name); + +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + *rqstp->rq_accept_statp = rpc_prog_mismatch; + + /* +@@ -1472,19 +1479,22 @@ svc_process_common(struct svc_rqst *rqstp) + err_bad_proc: + svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc); + +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + *rqstp->rq_accept_statp = rpc_proc_unavail; + goto sendit; + + err_garbage_args: + svc_printk(rqstp, "failed to decode RPC header\n"); + +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + *rqstp->rq_accept_statp = rpc_garbage_args; + goto sendit; + + err_system_err: +- serv->sv_stats->rpcbadfmt++; ++ if (serv->sv_stats) ++ serv->sv_stats->rpcbadfmt++; + *rqstp->rq_accept_statp = rpc_system_err; + goto sendit; + } +@@ -1536,7 +1546,8 @@ void svc_process(struct svc_rqst *rqstp) + out_baddir: + svc_printk(rqstp, "bad direction 0x%08x, dropping request\n", + be32_to_cpu(*p)); +- rqstp->rq_server->sv_stats->rpcbadfmt++; ++ if (rqstp->rq_server->sv_stats) ++ rqstp->rq_server->sv_stats->rpcbadfmt++; + out_drop: + svc_drop(rqstp); + } +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index be5c42d6ffbeab..2b2dc46dc701f9 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -468,6 +468,10 @@ static struct netlink_range_validation nl80211_punct_bitmap_range = { + .max = 0xffff, + }; + ++static struct netlink_range_validation q_range = { ++ .max = INT_MAX, ++}; ++ + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -750,7 +754,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + + [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 }, + [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 }, +- [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, ++ [NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range), + [NL80211_ATTR_HE_CAPABILITY] = + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa, + NL80211_HE_MAX_CAPABILITY_LEN), +diff --git a/samples/bpf/map_perf_test_user.c b/samples/bpf/map_perf_test_user.c +index d2fbcf963cdf6d..07ff471ed6aee0 100644 +--- a/samples/bpf/map_perf_test_user.c ++++ b/samples/bpf/map_perf_test_user.c +@@ -370,7 +370,7 @@ static void run_perf_test(int tasks) + + static void fill_lpm_trie(void) + { +- struct bpf_lpm_trie_key *key; ++ struct bpf_lpm_trie_key_u8 *key; + unsigned long value = 0; + unsigned int i; + int r; +diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c +index 9d41db09c4800f..266fdd0b025dc6 100644 +--- a/samples/bpf/xdp_router_ipv4_user.c ++++ b/samples/bpf/xdp_router_ipv4_user.c +@@ -91,7 +91,7 @@ static int recv_msg(struct sockaddr_nl sock_addr, int sock) + static void read_route(struct nlmsghdr *nh, int nll) + { + char dsts[24], gws[24], ifs[16], dsts_len[24], metrics[24]; +- struct bpf_lpm_trie_key *prefix_key; ++ struct bpf_lpm_trie_key_u8 *prefix_key; + struct rtattr *rt_attr; + struct rtmsg *rt_msg; + int rtm_family; +diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c +index 8b58a7864703ee..7e8fca0b066280 100644 +--- a/sound/soc/soc-topology.c ++++ b/sound/soc/soc-topology.c +@@ -1021,6 +1021,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, + struct snd_soc_tplg_hdr *hdr) + { + struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; ++ const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN; + struct snd_soc_tplg_dapm_graph_elem *elem; + struct snd_soc_dapm_route *route; + int count, i; +@@ -1044,39 +1045,22 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, + tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); + + /* validate routes */ +- if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { +- ret = -EINVAL; +- break; +- } +- if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { +- ret = -EINVAL; +- break; +- } +- if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { ++ if ((strnlen(elem->source, maxlen) == maxlen) || ++ (strnlen(elem->sink, maxlen) == maxlen) || ++ (strnlen(elem->control, maxlen) == maxlen)) { + ret = -EINVAL; + break; + } + +- route->source = devm_kmemdup(tplg->dev, elem->source, +- min(strlen(elem->source), +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN), +- GFP_KERNEL); +- route->sink = devm_kmemdup(tplg->dev, elem->sink, +- min(strlen(elem->sink), SNDRV_CTL_ELEM_ID_NAME_MAXLEN), +- GFP_KERNEL); ++ route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL); ++ route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL); + if (!route->source || !route->sink) { + ret = -ENOMEM; + break; + } + +- if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) != 0) { +- route->control = devm_kmemdup(tplg->dev, elem->control, +- min(strlen(elem->control), +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN), +- GFP_KERNEL); ++ if (strnlen(elem->control, maxlen) != 0) { ++ route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL); + if (!route->control) { + ret = -ENOMEM; + break; +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index d1bdb0b93bda0c..8cc2d4937f3403 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -2021,6 +2021,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, + bmaControls = ftr->bmaControls; + } + ++ if (channels > 32) { ++ usb_audio_info(state->chip, ++ "usbmixer: too many channels (%d) in unit %d\n", ++ channels, unitid); ++ return -EINVAL; ++ } ++ + /* parse the source unit */ + err = parse_audio_unit(state, hdr->bSourceID); + if (err < 0) +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index fb09fd1767f289..ba6e346c8d669a 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -77,12 +77,29 @@ struct bpf_insn { + __s32 imm; /* signed immediate constant */ + }; + +-/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ ++/* Deprecated: use struct bpf_lpm_trie_key_u8 (when the "data" member is needed for ++ * byte access) or struct bpf_lpm_trie_key_hdr (when using an alternative type for ++ * the trailing flexible array member) instead. ++ */ + struct bpf_lpm_trie_key { + __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ + __u8 data[0]; /* Arbitrary size */ + }; + ++/* Header for bpf_lpm_trie_key structs */ ++struct bpf_lpm_trie_key_hdr { ++ __u32 prefixlen; ++}; ++ ++/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry, with trailing byte array. */ ++struct bpf_lpm_trie_key_u8 { ++ union { ++ struct bpf_lpm_trie_key_hdr hdr; ++ __u32 prefixlen; ++ }; ++ __u8 data[]; /* Arbitrary size */ ++}; ++ + struct bpf_cgroup_storage_key { + __u64 cgroup_inode_id; /* cgroup inode id */ + __u32 attach_type; /* program attach type (enum bpf_attach_type) */ +diff --git a/tools/testing/selftests/bpf/progs/map_ptr_kern.c b/tools/testing/selftests/bpf/progs/map_ptr_kern.c +index 3325da17ec81af..efaf622c28ddec 100644 +--- a/tools/testing/selftests/bpf/progs/map_ptr_kern.c ++++ b/tools/testing/selftests/bpf/progs/map_ptr_kern.c +@@ -316,7 +316,7 @@ struct lpm_trie { + } __attribute__((preserve_access_index)); + + struct lpm_key { +- struct bpf_lpm_trie_key trie_key; ++ struct bpf_lpm_trie_key_hdr trie_key; + __u32 data; + }; + +diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c +index c028d621c744da..d98c72dc563eaf 100644 +--- a/tools/testing/selftests/bpf/test_lpm_map.c ++++ b/tools/testing/selftests/bpf/test_lpm_map.c +@@ -211,7 +211,7 @@ static void test_lpm_map(int keysize) + volatile size_t n_matches, n_matches_after_delete; + size_t i, j, n_nodes, n_lookups; + struct tlpm_node *t, *list = NULL; +- struct bpf_lpm_trie_key *key; ++ struct bpf_lpm_trie_key_u8 *key; + uint8_t *data, *value; + int r, map; + +@@ -331,8 +331,8 @@ static void test_lpm_map(int keysize) + static void test_lpm_ipaddr(void) + { + LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); +- struct bpf_lpm_trie_key *key_ipv4; +- struct bpf_lpm_trie_key *key_ipv6; ++ struct bpf_lpm_trie_key_u8 *key_ipv4; ++ struct bpf_lpm_trie_key_u8 *key_ipv6; + size_t key_size_ipv4; + size_t key_size_ipv6; + int map_fd_ipv4; +@@ -423,7 +423,7 @@ static void test_lpm_ipaddr(void) + static void test_lpm_delete(void) + { + LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); +- struct bpf_lpm_trie_key *key; ++ struct bpf_lpm_trie_key_u8 *key; + size_t key_size; + int map_fd; + __u64 value; +@@ -532,7 +532,7 @@ static void test_lpm_delete(void) + static void test_lpm_get_next_key(void) + { + LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); +- struct bpf_lpm_trie_key *key_p, *next_key_p; ++ struct bpf_lpm_trie_key_u8 *key_p, *next_key_p; + size_t key_size; + __u32 value = 0; + int map_fd; +@@ -693,9 +693,9 @@ static void *lpm_test_command(void *arg) + { + int i, j, ret, iter, key_size; + struct lpm_mt_test_info *info = arg; +- struct bpf_lpm_trie_key *key_p; ++ struct bpf_lpm_trie_key_u8 *key_p; + +- key_size = sizeof(struct bpf_lpm_trie_key) + sizeof(__u32); ++ key_size = sizeof(*key_p) + sizeof(__u32); + key_p = alloca(key_size); + for (iter = 0; iter < info->iter; iter++) + for (i = 0; i < MAX_TEST_KEYS; i++) { +@@ -717,7 +717,7 @@ static void *lpm_test_command(void *arg) + ret = bpf_map_lookup_elem(info->map_fd, key_p, &value); + assert(ret == 0 || errno == ENOENT); + } else { +- struct bpf_lpm_trie_key *next_key_p = alloca(key_size); ++ struct bpf_lpm_trie_key_u8 *next_key_p = alloca(key_size); + ret = bpf_map_get_next_key(info->map_fd, key_p, next_key_p); + assert(ret == 0 || errno == ENOENT || errno == ENOMEM); + } +@@ -752,7 +752,7 @@ static void test_lpm_multi_thread(void) + + /* create a trie */ + value_size = sizeof(__u32); +- key_size = sizeof(struct bpf_lpm_trie_key) + value_size; ++ key_size = sizeof(struct bpf_lpm_trie_key_hdr) + value_size; + map_fd = bpf_map_create(BPF_MAP_TYPE_LPM_TRIE, NULL, key_size, value_size, 100, &opts); + + /* create 4 threads to test update, delete, lookup and get_next_key */ +diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c +index ad993ab3ac1819..bc36c91c4480f5 100644 +--- a/tools/testing/selftests/net/tls.c ++++ b/tools/testing/selftests/net/tls.c +@@ -707,6 +707,20 @@ TEST_F(tls, splice_from_pipe) + EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); + } + ++TEST_F(tls, splice_more) ++{ ++ unsigned int f = SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_GIFT; ++ int send_len = TLS_PAYLOAD_MAX_LEN; ++ char mem_send[TLS_PAYLOAD_MAX_LEN]; ++ int i, send_pipe = 1; ++ int p[2]; ++ ++ ASSERT_GE(pipe(p), 0); ++ EXPECT_GE(write(p[1], mem_send, send_len), 0); ++ for (i = 0; i < 32; i++) ++ EXPECT_EQ(splice(p[0], NULL, self->fd, NULL, send_pipe, f), 1); ++} ++ + TEST_F(tls, splice_from_pipe2) + { + int send_len = 16000;