mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-22 21:08:49 +00:00
* Change DEV to EDGE * Renaming patches dev folder to edge * Move patches into subdir where they will be archived. * Relink patch directories properly
4855 lines
156 KiB
Diff
4855 lines
156 KiB
Diff
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index b5c933fa971f..94fa4a8de2ca 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -2741,7 +2741,7 @@
|
|
<name>,<region-number>[,<base>,<size>,<buswidth>,<altbuswidth>]
|
|
|
|
mtdparts= [MTD]
|
|
- See drivers/mtd/cmdlinepart.c.
|
|
+ See drivers/mtd/parsers/cmdlinepart.c
|
|
|
|
multitce=off [PPC] This parameter disables the use of the pSeries
|
|
firmware feature for updating multiple TCE entries
|
|
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
|
|
index b739f92da58e..1f90eb39870b 100644
|
|
--- a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
|
|
+++ b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
|
|
@@ -118,7 +118,7 @@ Tegra194:
|
|
--------
|
|
|
|
pcie@14180000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
|
|
reg = <0x00 0x14180000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x38000000 0x0 0x00040000 /* configuration space (256K) */
|
|
diff --git a/Makefile b/Makefile
|
|
index fdbc51db822a..6055a94aa4ce 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 34
|
|
+SUBLEVEL = 35
|
|
EXTRAVERSION =
|
|
NAME = Kleptomaniac Octopus
|
|
|
|
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
|
|
index e6b4b8525f98..bc488df31511 100644
|
|
--- a/arch/arm/boot/dts/imx6qdl.dtsi
|
|
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
|
|
@@ -1039,9 +1039,8 @@
|
|
compatible = "fsl,imx6q-fec";
|
|
reg = <0x02188000 0x4000>;
|
|
interrupt-names = "int0", "pps";
|
|
- interrupts-extended =
|
|
- <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
|
|
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
|
|
+ interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
|
|
+ <0 119 IRQ_TYPE_LEVEL_HIGH>;
|
|
clocks = <&clks IMX6QDL_CLK_ENET>,
|
|
<&clks IMX6QDL_CLK_ENET>,
|
|
<&clks IMX6QDL_CLK_ENET_REF>;
|
|
diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi
|
|
index 5f51f8e5c1fa..d91f92f944c5 100644
|
|
--- a/arch/arm/boot/dts/imx6qp.dtsi
|
|
+++ b/arch/arm/boot/dts/imx6qp.dtsi
|
|
@@ -77,7 +77,6 @@
|
|
};
|
|
|
|
&fec {
|
|
- /delete-property/interrupts-extended;
|
|
interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
|
|
<0 119 IRQ_TYPE_LEVEL_HIGH>;
|
|
};
|
|
diff --git a/arch/arm/boot/dts/rk3188-bqedison2qc.dts b/arch/arm/boot/dts/rk3188-bqedison2qc.dts
|
|
index ad1afd403052..66a0ff196eb1 100644
|
|
--- a/arch/arm/boot/dts/rk3188-bqedison2qc.dts
|
|
+++ b/arch/arm/boot/dts/rk3188-bqedison2qc.dts
|
|
@@ -58,20 +58,25 @@
|
|
|
|
lvds-encoder {
|
|
compatible = "ti,sn75lvds83", "lvds-encoder";
|
|
- #address-cells = <1>;
|
|
- #size-cells = <0>;
|
|
|
|
- port@0 {
|
|
- reg = <0>;
|
|
- lvds_in_vop0: endpoint {
|
|
- remote-endpoint = <&vop0_out_lvds>;
|
|
+ ports {
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
+
|
|
+ port@0 {
|
|
+ reg = <0>;
|
|
+
|
|
+ lvds_in_vop0: endpoint {
|
|
+ remote-endpoint = <&vop0_out_lvds>;
|
|
+ };
|
|
};
|
|
- };
|
|
|
|
- port@1 {
|
|
- reg = <1>;
|
|
- lvds_out_panel: endpoint {
|
|
- remote-endpoint = <&panel_in_lvds>;
|
|
+ port@1 {
|
|
+ reg = <1>;
|
|
+
|
|
+ lvds_out_panel: endpoint {
|
|
+ remote-endpoint = <&panel_in_lvds>;
|
|
+ };
|
|
};
|
|
};
|
|
};
|
|
@@ -465,7 +470,7 @@
|
|
non-removable;
|
|
pinctrl-names = "default";
|
|
pinctrl-0 = <&sd1_clk>, <&sd1_cmd>, <&sd1_bus4>;
|
|
- vmmcq-supply = <&vccio_wl>;
|
|
+ vqmmc-supply = <&vccio_wl>;
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
status = "okay";
|
|
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
|
|
index 74bb053cf23c..4e485e45fbc5 100644
|
|
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
|
|
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
|
|
@@ -313,7 +313,7 @@
|
|
|
|
display_clocks: clock@1000000 {
|
|
compatible = "allwinner,sun8i-a83t-de2-clk";
|
|
- reg = <0x01000000 0x100000>;
|
|
+ reg = <0x01000000 0x10000>;
|
|
clocks = <&ccu CLK_BUS_DE>,
|
|
<&ccu CLK_PLL_DE>;
|
|
clock-names = "bus",
|
|
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
|
|
index 80f4dc34df34..339402601990 100644
|
|
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
|
|
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
|
|
@@ -118,7 +118,7 @@
|
|
display_clocks: clock@1000000 {
|
|
compatible = "allwinner,sun8i-r40-de2-clk",
|
|
"allwinner,sun8i-h3-de2-clk";
|
|
- reg = <0x01000000 0x100000>;
|
|
+ reg = <0x01000000 0x10000>;
|
|
clocks = <&ccu CLK_BUS_DE>,
|
|
<&ccu CLK_DE>;
|
|
clock-names = "bus",
|
|
diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
|
|
index 23ba56df38f7..2abcba35d27e 100644
|
|
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
|
|
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
|
|
@@ -105,7 +105,7 @@
|
|
|
|
display_clocks: clock@1000000 {
|
|
compatible = "allwinner,sun8i-v3s-de2-clk";
|
|
- reg = <0x01000000 0x100000>;
|
|
+ reg = <0x01000000 0x10000>;
|
|
clocks = <&ccu CLK_BUS_DE>,
|
|
<&ccu CLK_DE>;
|
|
clock-names = "bus",
|
|
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
|
|
index 107eeafad20a..b3141c964c3a 100644
|
|
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
|
|
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
|
|
@@ -113,7 +113,7 @@
|
|
|
|
display_clocks: clock@1000000 {
|
|
/* compatible is in per SoC .dtsi file */
|
|
- reg = <0x01000000 0x100000>;
|
|
+ reg = <0x01000000 0x10000>;
|
|
clocks = <&ccu CLK_BUS_DE>,
|
|
<&ccu CLK_DE>;
|
|
clock-names = "bus",
|
|
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
|
|
index 97dc386e3cb8..7216653424fd 100644
|
|
--- a/arch/arm/net/bpf_jit_32.c
|
|
+++ b/arch/arm/net/bpf_jit_32.c
|
|
@@ -929,7 +929,11 @@ static inline void emit_a32_rsh_i64(const s8 dst[],
|
|
rd = arm_bpf_get_reg64(dst, tmp, ctx);
|
|
|
|
/* Do LSR operation */
|
|
- if (val < 32) {
|
|
+ if (val == 0) {
|
|
+ /* An immediate value of 0 encodes a shift amount of 32
|
|
+ * for LSR. To shift by 0, don't do anything.
|
|
+ */
|
|
+ } else if (val < 32) {
|
|
emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
|
|
emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
|
|
emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
|
|
@@ -955,7 +959,11 @@ static inline void emit_a32_arsh_i64(const s8 dst[],
|
|
rd = arm_bpf_get_reg64(dst, tmp, ctx);
|
|
|
|
/* Do ARSH operation */
|
|
- if (val < 32) {
|
|
+ if (val == 0) {
|
|
+ /* An immediate value of 0 encodes a shift amount of 32
|
|
+ * for ASR. To shift by 0, don't do anything.
|
|
+ */
|
|
+ } else if (val < 32) {
|
|
emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
|
|
emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
|
|
emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);
|
|
@@ -992,21 +1000,35 @@ static inline void emit_a32_mul_r64(const s8 dst[], const s8 src[],
|
|
arm_bpf_put_reg32(dst_hi, rd[0], ctx);
|
|
}
|
|
|
|
+static bool is_ldst_imm(s16 off, const u8 size)
|
|
+{
|
|
+ s16 off_max = 0;
|
|
+
|
|
+ switch (size) {
|
|
+ case BPF_B:
|
|
+ case BPF_W:
|
|
+ off_max = 0xfff;
|
|
+ break;
|
|
+ case BPF_H:
|
|
+ off_max = 0xff;
|
|
+ break;
|
|
+ case BPF_DW:
|
|
+ /* Need to make sure off+4 does not overflow. */
|
|
+ off_max = 0xfff - 4;
|
|
+ break;
|
|
+ }
|
|
+ return -off_max <= off && off <= off_max;
|
|
+}
|
|
+
|
|
/* *(size *)(dst + off) = src */
|
|
static inline void emit_str_r(const s8 dst, const s8 src[],
|
|
- s32 off, struct jit_ctx *ctx, const u8 sz){
|
|
+ s16 off, struct jit_ctx *ctx, const u8 sz){
|
|
const s8 *tmp = bpf2a32[TMP_REG_1];
|
|
- s32 off_max;
|
|
s8 rd;
|
|
|
|
rd = arm_bpf_get_reg32(dst, tmp[1], ctx);
|
|
|
|
- if (sz == BPF_H)
|
|
- off_max = 0xff;
|
|
- else
|
|
- off_max = 0xfff;
|
|
-
|
|
- if (off < 0 || off > off_max) {
|
|
+ if (!is_ldst_imm(off, sz)) {
|
|
emit_a32_mov_i(tmp[0], off, ctx);
|
|
emit(ARM_ADD_R(tmp[0], tmp[0], rd), ctx);
|
|
rd = tmp[0];
|
|
@@ -1035,18 +1057,12 @@ static inline void emit_str_r(const s8 dst, const s8 src[],
|
|
|
|
/* dst = *(size*)(src + off) */
|
|
static inline void emit_ldx_r(const s8 dst[], const s8 src,
|
|
- s32 off, struct jit_ctx *ctx, const u8 sz){
|
|
+ s16 off, struct jit_ctx *ctx, const u8 sz){
|
|
const s8 *tmp = bpf2a32[TMP_REG_1];
|
|
const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
|
|
s8 rm = src;
|
|
- s32 off_max;
|
|
-
|
|
- if (sz == BPF_H)
|
|
- off_max = 0xff;
|
|
- else
|
|
- off_max = 0xfff;
|
|
|
|
- if (off < 0 || off > off_max) {
|
|
+ if (!is_ldst_imm(off, sz)) {
|
|
emit_a32_mov_i(tmp[0], off, ctx);
|
|
emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
|
|
rm = tmp[0];
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
|
|
index ba41c1b85887..367699c8c902 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
|
|
@@ -227,7 +227,7 @@
|
|
|
|
display_clocks: clock@0 {
|
|
compatible = "allwinner,sun50i-a64-de2-clk";
|
|
- reg = <0x0 0x100000>;
|
|
+ reg = <0x0 0x10000>;
|
|
clocks = <&ccu CLK_BUS_DE>,
|
|
<&ccu CLK_DE>;
|
|
clock-names = "bus",
|
|
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
|
|
index a211a046b2f2..b90d78a5724b 100644
|
|
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
|
|
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
|
|
@@ -367,6 +367,7 @@
|
|
pinctrl-0 = <&cp0_copper_eth_phy_reset>;
|
|
reset-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>;
|
|
reset-assert-us = <10000>;
|
|
+ reset-deassert-us = <10000>;
|
|
};
|
|
|
|
switch0: switch0@4 {
|
|
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
|
|
index 3c0cf54f0aab..457b815d57f4 100644
|
|
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
|
|
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
|
|
@@ -1151,7 +1151,7 @@
|
|
};
|
|
|
|
pcie@14100000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
|
|
reg = <0x00 0x14100000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x30000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1197,7 +1197,7 @@
|
|
};
|
|
|
|
pcie@14120000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
|
|
reg = <0x00 0x14120000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x32000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1243,7 +1243,7 @@
|
|
};
|
|
|
|
pcie@14140000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
|
|
reg = <0x00 0x14140000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x34000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1289,7 +1289,7 @@
|
|
};
|
|
|
|
pcie@14160000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX4A>;
|
|
reg = <0x00 0x14160000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x36000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1335,7 +1335,7 @@
|
|
};
|
|
|
|
pcie@14180000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
|
|
reg = <0x00 0x14180000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x38000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1381,7 +1381,7 @@
|
|
};
|
|
|
|
pcie@141a0000 {
|
|
- compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
|
|
+ compatible = "nvidia,tegra194-pcie";
|
|
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>;
|
|
reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */
|
|
0x00 0x3a000000 0x0 0x00040000 /* configuration space (256K) */
|
|
@@ -1430,6 +1430,105 @@
|
|
0x82000000 0x0 0x40000000 0x1f 0x40000000 0x0 0xc0000000>; /* non-prefetchable memory (3GB) */
|
|
};
|
|
|
|
+ pcie_ep@14160000 {
|
|
+ compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
|
|
+ power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX4A>;
|
|
+ reg = <0x00 0x14160000 0x0 0x00020000 /* appl registers (128K) */
|
|
+ 0x00 0x36040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */
|
|
+ 0x00 0x36080000 0x0 0x00040000 /* DBI reg space (256K) */
|
|
+ 0x14 0x00000000 0x4 0x00000000>; /* Address Space (16G) */
|
|
+ reg-names = "appl", "atu_dma", "dbi", "addr_space";
|
|
+
|
|
+ status = "disabled";
|
|
+
|
|
+ num-lanes = <4>;
|
|
+ num-ib-windows = <2>;
|
|
+ num-ob-windows = <8>;
|
|
+
|
|
+ clocks = <&bpmp TEGRA194_CLK_PEX0_CORE_4>;
|
|
+ clock-names = "core";
|
|
+
|
|
+ resets = <&bpmp TEGRA194_RESET_PEX0_CORE_4_APB>,
|
|
+ <&bpmp TEGRA194_RESET_PEX0_CORE_4>;
|
|
+ reset-names = "apb", "core";
|
|
+
|
|
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
|
|
+ interrupt-names = "intr";
|
|
+
|
|
+ nvidia,bpmp = <&bpmp 4>;
|
|
+
|
|
+ nvidia,aspm-cmrt-us = <60>;
|
|
+ nvidia,aspm-pwr-on-t-us = <20>;
|
|
+ nvidia,aspm-l0s-entrance-latency-us = <3>;
|
|
+ };
|
|
+
|
|
+ pcie_ep@14180000 {
|
|
+ compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
|
|
+ power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
|
|
+ reg = <0x00 0x14180000 0x0 0x00020000 /* appl registers (128K) */
|
|
+ 0x00 0x38040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */
|
|
+ 0x00 0x38080000 0x0 0x00040000 /* DBI reg space (256K) */
|
|
+ 0x18 0x00000000 0x4 0x00000000>; /* Address Space (16G) */
|
|
+ reg-names = "appl", "atu_dma", "dbi", "addr_space";
|
|
+
|
|
+ status = "disabled";
|
|
+
|
|
+ num-lanes = <8>;
|
|
+ num-ib-windows = <2>;
|
|
+ num-ob-windows = <8>;
|
|
+
|
|
+ clocks = <&bpmp TEGRA194_CLK_PEX0_CORE_0>;
|
|
+ clock-names = "core";
|
|
+
|
|
+ resets = <&bpmp TEGRA194_RESET_PEX0_CORE_0_APB>,
|
|
+ <&bpmp TEGRA194_RESET_PEX0_CORE_0>;
|
|
+ reset-names = "apb", "core";
|
|
+
|
|
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
|
|
+ interrupt-names = "intr";
|
|
+
|
|
+ nvidia,bpmp = <&bpmp 0>;
|
|
+
|
|
+ nvidia,aspm-cmrt-us = <60>;
|
|
+ nvidia,aspm-pwr-on-t-us = <20>;
|
|
+ nvidia,aspm-l0s-entrance-latency-us = <3>;
|
|
+ };
|
|
+
|
|
+ pcie_ep@141a0000 {
|
|
+ compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
|
|
+ power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>;
|
|
+ reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */
|
|
+ 0x00 0x3a040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */
|
|
+ 0x00 0x3a080000 0x0 0x00040000 /* DBI reg space (256K) */
|
|
+ 0x1c 0x00000000 0x4 0x00000000>; /* Address Space (16G) */
|
|
+ reg-names = "appl", "atu_dma", "dbi", "addr_space";
|
|
+
|
|
+ status = "disabled";
|
|
+
|
|
+ num-lanes = <8>;
|
|
+ num-ib-windows = <2>;
|
|
+ num-ob-windows = <8>;
|
|
+
|
|
+ pinctrl-names = "default";
|
|
+ pinctrl-0 = <&clkreq_c5_bi_dir_state>;
|
|
+
|
|
+ clocks = <&bpmp TEGRA194_CLK_PEX1_CORE_5>;
|
|
+ clock-names = "core";
|
|
+
|
|
+ resets = <&bpmp TEGRA194_RESET_PEX1_CORE_5_APB>,
|
|
+ <&bpmp TEGRA194_RESET_PEX1_CORE_5>;
|
|
+ reset-names = "apb", "core";
|
|
+
|
|
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
|
|
+ interrupt-names = "intr";
|
|
+
|
|
+ nvidia,bpmp = <&bpmp 5>;
|
|
+
|
|
+ nvidia,aspm-cmrt-us = <60>;
|
|
+ nvidia,aspm-pwr-on-t-us = <20>;
|
|
+ nvidia,aspm-l0s-entrance-latency-us = <3>;
|
|
+ };
|
|
+
|
|
sysram@40000000 {
|
|
compatible = "nvidia,tegra194-sysram", "mmio-sram";
|
|
reg = <0x0 0x40000000 0x0 0x50000>;
|
|
diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h
|
|
index f35a9f3315ee..5056ebb902d1 100644
|
|
--- a/arch/csky/abiv1/inc/abi/entry.h
|
|
+++ b/arch/csky/abiv1/inc/abi/entry.h
|
|
@@ -172,10 +172,7 @@
|
|
addi r6, 0xe
|
|
cpwcr r6, cpcr30
|
|
|
|
- lsri r6, 28
|
|
- addi r6, 2
|
|
- lsli r6, 28
|
|
- addi r6, 0xe
|
|
+ movi r6, 0
|
|
cpwcr r6, cpcr31
|
|
.endm
|
|
|
|
diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c
|
|
index 86d187d4e5af..5acc5c2e544e 100644
|
|
--- a/arch/csky/abiv2/fpu.c
|
|
+++ b/arch/csky/abiv2/fpu.c
|
|
@@ -10,11 +10,6 @@
|
|
#define MTCR_DIST 0xC0006420
|
|
#define MFCR_DIST 0xC0006020
|
|
|
|
-void __init init_fpu(void)
|
|
-{
|
|
- mtcr("cr<1, 2>", 0);
|
|
-}
|
|
-
|
|
/*
|
|
* fpu_libc_helper() is to help libc to excute:
|
|
* - mfcr %a, cr<1, 2>
|
|
diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h
|
|
index 94a7a58765df..111973c6c713 100644
|
|
--- a/arch/csky/abiv2/inc/abi/entry.h
|
|
+++ b/arch/csky/abiv2/inc/abi/entry.h
|
|
@@ -230,11 +230,8 @@
|
|
addi r6, 0x1ce
|
|
mtcr r6, cr<30, 15> /* Set MSA0 */
|
|
|
|
- lsri r6, 28
|
|
- addi r6, 2
|
|
- lsli r6, 28
|
|
- addi r6, 0x1ce
|
|
- mtcr r6, cr<31, 15> /* Set MSA1 */
|
|
+ movi r6, 0
|
|
+ mtcr r6, cr<31, 15> /* Clr MSA1 */
|
|
|
|
/* enable MMU */
|
|
mfcr r6, cr18
|
|
diff --git a/arch/csky/abiv2/inc/abi/fpu.h b/arch/csky/abiv2/inc/abi/fpu.h
|
|
index 22ca3cf2794a..09e2700a3693 100644
|
|
--- a/arch/csky/abiv2/inc/abi/fpu.h
|
|
+++ b/arch/csky/abiv2/inc/abi/fpu.h
|
|
@@ -9,7 +9,8 @@
|
|
|
|
int fpu_libc_helper(struct pt_regs *regs);
|
|
void fpu_fpe(struct pt_regs *regs);
|
|
-void __init init_fpu(void);
|
|
+
|
|
+static inline void init_fpu(void) { mtcr("cr<1, 2>", 0); }
|
|
|
|
void save_to_user_fp(struct user_fp *user_fp);
|
|
void restore_from_user_fp(struct user_fp *user_fp);
|
|
diff --git a/arch/csky/include/asm/processor.h b/arch/csky/include/asm/processor.h
|
|
index 21e0bd5293dd..c6bcd7f7c720 100644
|
|
--- a/arch/csky/include/asm/processor.h
|
|
+++ b/arch/csky/include/asm/processor.h
|
|
@@ -43,6 +43,7 @@ extern struct cpuinfo_csky cpu_data[];
|
|
struct thread_struct {
|
|
unsigned long ksp; /* kernel stack pointer */
|
|
unsigned long sr; /* saved status register */
|
|
+ unsigned long trap_no; /* saved status register */
|
|
|
|
/* FPU regs */
|
|
struct user_fp __aligned(16) user_fp;
|
|
diff --git a/arch/csky/kernel/head.S b/arch/csky/kernel/head.S
|
|
index 61989f9241c0..17ed9d250480 100644
|
|
--- a/arch/csky/kernel/head.S
|
|
+++ b/arch/csky/kernel/head.S
|
|
@@ -21,6 +21,11 @@ END(_start)
|
|
ENTRY(_start_smp_secondary)
|
|
SETUP_MMU
|
|
|
|
+ /* copy msa1 from CPU0 */
|
|
+ lrw r6, secondary_msa1
|
|
+ ld.w r6, (r6, 0)
|
|
+ mtcr r6, cr<31, 15>
|
|
+
|
|
/* set stack point */
|
|
lrw r6, secondary_stack
|
|
ld.w r6, (r6, 0)
|
|
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
|
|
index 23ee604aafdb..2c1e253abb74 100644
|
|
--- a/arch/csky/kernel/setup.c
|
|
+++ b/arch/csky/kernel/setup.c
|
|
@@ -24,26 +24,9 @@ struct screen_info screen_info = {
|
|
};
|
|
#endif
|
|
|
|
-phys_addr_t __init_memblock memblock_end_of_REG0(void)
|
|
-{
|
|
- return (memblock.memory.regions[0].base +
|
|
- memblock.memory.regions[0].size);
|
|
-}
|
|
-
|
|
-phys_addr_t __init_memblock memblock_start_of_REG1(void)
|
|
-{
|
|
- return memblock.memory.regions[1].base;
|
|
-}
|
|
-
|
|
-size_t __init_memblock memblock_size_of_REG1(void)
|
|
-{
|
|
- return memblock.memory.regions[1].size;
|
|
-}
|
|
-
|
|
static void __init csky_memblock_init(void)
|
|
{
|
|
unsigned long zone_size[MAX_NR_ZONES];
|
|
- unsigned long zhole_size[MAX_NR_ZONES];
|
|
signed long size;
|
|
|
|
memblock_reserve(__pa(_stext), _end - _stext);
|
|
@@ -57,54 +40,36 @@ static void __init csky_memblock_init(void)
|
|
memblock_dump_all();
|
|
|
|
memset(zone_size, 0, sizeof(zone_size));
|
|
- memset(zhole_size, 0, sizeof(zhole_size));
|
|
|
|
min_low_pfn = PFN_UP(memblock_start_of_DRAM());
|
|
- max_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
|
-
|
|
- max_low_pfn = PFN_UP(memblock_end_of_REG0());
|
|
- if (max_low_pfn == 0)
|
|
- max_low_pfn = max_pfn;
|
|
+ max_low_pfn = max_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
|
|
|
size = max_pfn - min_low_pfn;
|
|
|
|
- if (memblock.memory.cnt > 1) {
|
|
- zone_size[ZONE_NORMAL] =
|
|
- PFN_DOWN(memblock_start_of_REG1()) - min_low_pfn;
|
|
- zhole_size[ZONE_NORMAL] =
|
|
- PFN_DOWN(memblock_start_of_REG1()) - max_low_pfn;
|
|
+ if (size <= PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET))
|
|
+ zone_size[ZONE_NORMAL] = size;
|
|
+ else if (size < PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET)) {
|
|
+ zone_size[ZONE_NORMAL] =
|
|
+ PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET);
|
|
+ max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
|
|
} else {
|
|
- if (size <= PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET))
|
|
- zone_size[ZONE_NORMAL] = max_pfn - min_low_pfn;
|
|
- else {
|
|
- zone_size[ZONE_NORMAL] =
|
|
+ zone_size[ZONE_NORMAL] =
|
|
PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
|
|
- max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
|
|
- }
|
|
+ max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
|
|
+ write_mmu_msa1(read_mmu_msa0() + SSEG_SIZE);
|
|
}
|
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
- size = 0;
|
|
- if (memblock.memory.cnt > 1) {
|
|
- size = PFN_DOWN(memblock_size_of_REG1());
|
|
- highstart_pfn = PFN_DOWN(memblock_start_of_REG1());
|
|
- } else {
|
|
- size = max_pfn - min_low_pfn -
|
|
- PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
|
|
- highstart_pfn = min_low_pfn +
|
|
- PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
|
|
- }
|
|
-
|
|
- if (size > 0)
|
|
- zone_size[ZONE_HIGHMEM] = size;
|
|
+ zone_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
|
|
|
|
- highend_pfn = max_pfn;
|
|
+ highstart_pfn = max_low_pfn;
|
|
+ highend_pfn = max_pfn;
|
|
#endif
|
|
memblock_set_current_limit(PFN_PHYS(max_low_pfn));
|
|
|
|
dma_contiguous_reserve(0);
|
|
|
|
- free_area_init_node(0, zone_size, min_low_pfn, zhole_size);
|
|
+ free_area_init_node(0, zone_size, min_low_pfn, NULL);
|
|
}
|
|
|
|
void __init setup_arch(char **cmdline_p)
|
|
diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c
|
|
index 0bb0954d5570..b5c5bc3afeb5 100644
|
|
--- a/arch/csky/kernel/smp.c
|
|
+++ b/arch/csky/kernel/smp.c
|
|
@@ -22,6 +22,9 @@
|
|
#include <asm/sections.h>
|
|
#include <asm/mmu_context.h>
|
|
#include <asm/pgalloc.h>
|
|
+#ifdef CONFIG_CPU_HAS_FPU
|
|
+#include <abi/fpu.h>
|
|
+#endif
|
|
|
|
struct ipi_data_struct {
|
|
unsigned long bits ____cacheline_aligned;
|
|
@@ -156,6 +159,8 @@ volatile unsigned int secondary_hint;
|
|
volatile unsigned int secondary_ccr;
|
|
volatile unsigned int secondary_stack;
|
|
|
|
+unsigned long secondary_msa1;
|
|
+
|
|
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
|
{
|
|
unsigned long mask = 1 << cpu;
|
|
@@ -164,6 +169,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
|
(unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
|
|
secondary_hint = mfcr("cr31");
|
|
secondary_ccr = mfcr("cr18");
|
|
+ secondary_msa1 = read_mmu_msa1();
|
|
|
|
/*
|
|
* Because other CPUs are in reset status, we must flush data
|
|
diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c
|
|
index b057480e7463..63715cb90ee9 100644
|
|
--- a/arch/csky/kernel/traps.c
|
|
+++ b/arch/csky/kernel/traps.c
|
|
@@ -115,8 +115,9 @@ asmlinkage void trap_c(struct pt_regs *regs)
|
|
int sig;
|
|
unsigned long vector;
|
|
siginfo_t info;
|
|
+ struct task_struct *tsk = current;
|
|
|
|
- vector = (mfcr("psr") >> 16) & 0xff;
|
|
+ vector = (regs->sr >> 16) & 0xff;
|
|
|
|
switch (vector) {
|
|
case VEC_ZERODIV:
|
|
@@ -129,6 +130,7 @@ asmlinkage void trap_c(struct pt_regs *regs)
|
|
sig = SIGTRAP;
|
|
break;
|
|
case VEC_ILLEGAL:
|
|
+ tsk->thread.trap_no = vector;
|
|
die_if_kernel("Kernel mode ILLEGAL", regs, vector);
|
|
#ifndef CONFIG_CPU_NO_USER_BKPT
|
|
if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT)
|
|
@@ -146,16 +148,20 @@ asmlinkage void trap_c(struct pt_regs *regs)
|
|
sig = SIGTRAP;
|
|
break;
|
|
case VEC_ACCESS:
|
|
+ tsk->thread.trap_no = vector;
|
|
return buserr(regs);
|
|
#ifdef CONFIG_CPU_NEED_SOFTALIGN
|
|
case VEC_ALIGN:
|
|
+ tsk->thread.trap_no = vector;
|
|
return csky_alignment(regs);
|
|
#endif
|
|
#ifdef CONFIG_CPU_HAS_FPU
|
|
case VEC_FPE:
|
|
+ tsk->thread.trap_no = vector;
|
|
die_if_kernel("Kernel mode FPE", regs, vector);
|
|
return fpu_fpe(regs);
|
|
case VEC_PRIV:
|
|
+ tsk->thread.trap_no = vector;
|
|
die_if_kernel("Kernel mode PRIV", regs, vector);
|
|
if (fpu_libc_helper(regs))
|
|
return;
|
|
@@ -164,5 +170,8 @@ asmlinkage void trap_c(struct pt_regs *regs)
|
|
sig = SIGSEGV;
|
|
break;
|
|
}
|
|
+
|
|
+ tsk->thread.trap_no = vector;
|
|
+
|
|
send_sig(sig, current, 0);
|
|
}
|
|
diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c
|
|
index f76618b630f9..562c7f708749 100644
|
|
--- a/arch/csky/mm/fault.c
|
|
+++ b/arch/csky/mm/fault.c
|
|
@@ -179,11 +179,14 @@ bad_area:
|
|
bad_area_nosemaphore:
|
|
/* User mode accesses just cause a SIGSEGV */
|
|
if (user_mode(regs)) {
|
|
+ tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
|
|
force_sig_fault(SIGSEGV, si_code, (void __user *)address);
|
|
return;
|
|
}
|
|
|
|
no_context:
|
|
+ tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
|
|
+
|
|
/* Are we prepared to handle this kernel fault? */
|
|
if (fixup_exception(regs))
|
|
return;
|
|
@@ -198,6 +201,8 @@ no_context:
|
|
die_if_kernel("Oops", regs, write);
|
|
|
|
out_of_memory:
|
|
+ tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
|
|
+
|
|
/*
|
|
* 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).
|
|
@@ -206,6 +211,8 @@ out_of_memory:
|
|
return;
|
|
|
|
do_sigbus:
|
|
+ tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
|
|
+
|
|
up_read(&mm->mmap_sem);
|
|
|
|
/* Kernel mode? Handle exceptions or die */
|
|
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
|
|
index eba9d4ee4baf..689664cd4e79 100644
|
|
--- a/arch/powerpc/kernel/prom_init.c
|
|
+++ b/arch/powerpc/kernel/prom_init.c
|
|
@@ -1761,6 +1761,9 @@ static void __init prom_rtas_os_term(char *str)
|
|
if (token == 0)
|
|
prom_panic("Could not get token for ibm,os-term\n");
|
|
os_term_args.token = cpu_to_be32(token);
|
|
+ os_term_args.nargs = cpu_to_be32(1);
|
|
+ os_term_args.nret = cpu_to_be32(1);
|
|
+ os_term_args.args[0] = cpu_to_be32(__pa(str));
|
|
prom_rtas_hcall((uint64_t)&os_term_args);
|
|
}
|
|
#endif /* CONFIG_PPC_SVM */
|
|
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
|
|
index 36abbe3c346d..e2183fed947d 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv.c
|
|
@@ -3623,6 +3623,7 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
|
|
if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested &&
|
|
kvmppc_get_gpr(vcpu, 3) == H_CEDE) {
|
|
kvmppc_nested_cede(vcpu);
|
|
+ kvmppc_set_gpr(vcpu, 3, 0);
|
|
trap = 0;
|
|
}
|
|
} else {
|
|
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
|
|
index 9cd6f3e1000b..09a0594350b6 100644
|
|
--- a/arch/powerpc/platforms/maple/setup.c
|
|
+++ b/arch/powerpc/platforms/maple/setup.c
|
|
@@ -294,23 +294,6 @@ static int __init maple_probe(void)
|
|
return 1;
|
|
}
|
|
|
|
-define_machine(maple) {
|
|
- .name = "Maple",
|
|
- .probe = maple_probe,
|
|
- .setup_arch = maple_setup_arch,
|
|
- .init_IRQ = maple_init_IRQ,
|
|
- .pci_irq_fixup = maple_pci_irq_fixup,
|
|
- .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
|
|
- .restart = maple_restart,
|
|
- .halt = maple_halt,
|
|
- .get_boot_time = maple_get_boot_time,
|
|
- .set_rtc_time = maple_set_rtc_time,
|
|
- .get_rtc_time = maple_get_rtc_time,
|
|
- .calibrate_decr = generic_calibrate_decr,
|
|
- .progress = maple_progress,
|
|
- .power_save = power4_idle,
|
|
-};
|
|
-
|
|
#ifdef CONFIG_EDAC
|
|
/*
|
|
* Register a platform device for CPC925 memory controller on
|
|
@@ -367,3 +350,20 @@ static int __init maple_cpc925_edac_setup(void)
|
|
}
|
|
machine_device_initcall(maple, maple_cpc925_edac_setup);
|
|
#endif
|
|
+
|
|
+define_machine(maple) {
|
|
+ .name = "Maple",
|
|
+ .probe = maple_probe,
|
|
+ .setup_arch = maple_setup_arch,
|
|
+ .init_IRQ = maple_init_IRQ,
|
|
+ .pci_irq_fixup = maple_pci_irq_fixup,
|
|
+ .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
|
|
+ .restart = maple_restart,
|
|
+ .halt = maple_halt,
|
|
+ .get_boot_time = maple_get_boot_time,
|
|
+ .set_rtc_time = maple_set_rtc_time,
|
|
+ .get_rtc_time = maple_get_rtc_time,
|
|
+ .calibrate_decr = generic_calibrate_decr,
|
|
+ .progress = maple_progress,
|
|
+ .power_save = power4_idle,
|
|
+};
|
|
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
|
|
index fdb8083e7870..229e1e2f8253 100644
|
|
--- a/arch/s390/kernel/perf_cpum_sf.c
|
|
+++ b/arch/s390/kernel/perf_cpum_sf.c
|
|
@@ -1589,6 +1589,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw)
|
|
perf_aux_output_end(handle, size);
|
|
num_sdb = aux->sfb.num_sdb;
|
|
|
|
+ num_sdb = aux->sfb.num_sdb;
|
|
while (!done) {
|
|
/* Get an output handle */
|
|
aux = perf_aux_output_begin(handle, cpuhw->event);
|
|
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
|
|
index 6ebc2117c66c..91b9b3f73de6 100644
|
|
--- a/arch/s390/kernel/processor.c
|
|
+++ b/arch/s390/kernel/processor.c
|
|
@@ -165,8 +165,9 @@ static void show_cpu_mhz(struct seq_file *m, unsigned long n)
|
|
static int show_cpuinfo(struct seq_file *m, void *v)
|
|
{
|
|
unsigned long n = (unsigned long) v - 1;
|
|
+ unsigned long first = cpumask_first(cpu_online_mask);
|
|
|
|
- if (!n)
|
|
+ if (n == first)
|
|
show_cpu_summary(m, v);
|
|
if (!machine_has_cpu_mhz)
|
|
return 0;
|
|
@@ -179,6 +180,8 @@ static inline void *c_update(loff_t *pos)
|
|
{
|
|
if (*pos)
|
|
*pos = cpumask_next(*pos - 1, cpu_online_mask);
|
|
+ else
|
|
+ *pos = cpumask_first(cpu_online_mask);
|
|
return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
|
|
}
|
|
|
|
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
|
|
index 9d9ab77d02dd..364e3a89c096 100644
|
|
--- a/arch/s390/mm/gmap.c
|
|
+++ b/arch/s390/mm/gmap.c
|
|
@@ -1844,6 +1844,7 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t,
|
|
goto out_free;
|
|
} else if (*table & _REGION_ENTRY_ORIGIN) {
|
|
rc = -EAGAIN; /* Race with shadow */
|
|
+ goto out_free;
|
|
}
|
|
crst_table_init(s_r3t, _REGION3_ENTRY_EMPTY);
|
|
/* mark as invalid as long as the parent table is not protected */
|
|
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
|
|
index 6627d7c30f37..0f5d0a699a49 100644
|
|
--- a/arch/um/drivers/ubd_kern.c
|
|
+++ b/arch/um/drivers/ubd_kern.c
|
|
@@ -1606,7 +1606,9 @@ int io_thread(void *arg)
|
|
written = 0;
|
|
|
|
do {
|
|
- res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n);
|
|
+ res = os_write_file(kernel_fd,
|
|
+ ((char *) io_req_buffer) + written,
|
|
+ n - written);
|
|
if (res >= 0) {
|
|
written += res;
|
|
}
|
|
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
|
|
index 5133e3afb96f..3996937e2c0d 100644
|
|
--- a/arch/um/os-Linux/file.c
|
|
+++ b/arch/um/os-Linux/file.c
|
|
@@ -8,6 +8,7 @@
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
+#include <linux/falloc.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/socket.h>
|
|
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
|
|
index 2db3972c0e0f..79583bac9ac4 100644
|
|
--- a/arch/x86/hyperv/hv_init.c
|
|
+++ b/arch/x86/hyperv/hv_init.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <linux/mm.h>
|
|
#include <linux/hyperv.h>
|
|
#include <linux/slab.h>
|
|
+#include <linux/kernel.h>
|
|
#include <linux/cpuhotplug.h>
|
|
#include <clocksource/hyperv_timer.h>
|
|
|
|
@@ -354,11 +355,14 @@ void hyperv_cleanup(void)
|
|
}
|
|
EXPORT_SYMBOL_GPL(hyperv_cleanup);
|
|
|
|
-void hyperv_report_panic(struct pt_regs *regs, long err)
|
|
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
|
|
{
|
|
static bool panic_reported;
|
|
u64 guest_id;
|
|
|
|
+ if (in_die && !panic_on_oops)
|
|
+ return;
|
|
+
|
|
/*
|
|
* We prefer to report panic on 'die' chain as we have proper
|
|
* registers to report, but if we miss it (e.g. on BUG()) we need
|
|
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
|
|
index caf2edccbad2..49ae4e1ac9cd 100644
|
|
--- a/arch/x86/kernel/acpi/cstate.c
|
|
+++ b/arch/x86/kernel/acpi/cstate.c
|
|
@@ -161,7 +161,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
|
|
|
|
/* Make sure we are running on right CPU */
|
|
|
|
- retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
|
|
+ retval = call_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx,
|
|
+ false);
|
|
if (retval == 0) {
|
|
/* Use the hint in CST */
|
|
percpu_entry->states[cx->index].eax = cx->address;
|
|
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
|
|
index c656d92cd708..fc8814faae62 100644
|
|
--- a/arch/x86/kernel/cpu/mshyperv.c
|
|
+++ b/arch/x86/kernel/cpu/mshyperv.c
|
|
@@ -263,6 +263,16 @@ static void __init ms_hyperv_init_platform(void)
|
|
cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
|
|
}
|
|
|
|
+ /*
|
|
+ * Hyper-V expects to get crash register data or kmsg when
|
|
+ * crash enlightment is available and system crashes. Set
|
|
+ * crash_kexec_post_notifiers to be true to make sure that
|
|
+ * calling crash enlightment interface before running kdump
|
|
+ * kernel.
|
|
+ */
|
|
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
|
|
+ crash_kexec_post_notifiers = true;
|
|
+
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
|
|
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
|
|
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
|
|
index 5611769e1569..12b707a4e52f 100644
|
|
--- a/block/bfq-cgroup.c
|
|
+++ b/block/bfq-cgroup.c
|
|
@@ -697,10 +697,7 @@ static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
|
|
|
|
if (entity->sched_data != &bfqg->sched_data) {
|
|
bic_set_bfqq(bic, NULL, 0);
|
|
- bfq_log_bfqq(bfqd, async_bfqq,
|
|
- "bic_change_group: %p %d",
|
|
- async_bfqq, async_bfqq->ref);
|
|
- bfq_put_queue(async_bfqq);
|
|
+ bfq_release_process_ref(bfqd, async_bfqq);
|
|
}
|
|
}
|
|
|
|
@@ -801,39 +798,53 @@ static void bfq_flush_idle_tree(struct bfq_service_tree *st)
|
|
/**
|
|
* bfq_reparent_leaf_entity - move leaf entity to the root_group.
|
|
* @bfqd: the device data structure with the root group.
|
|
- * @entity: the entity to move.
|
|
+ * @entity: the entity to move, if entity is a leaf; or the parent entity
|
|
+ * of an active leaf entity to move, if entity is not a leaf.
|
|
*/
|
|
static void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
|
|
- struct bfq_entity *entity)
|
|
+ struct bfq_entity *entity,
|
|
+ int ioprio_class)
|
|
{
|
|
- struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
|
|
+ struct bfq_queue *bfqq;
|
|
+ struct bfq_entity *child_entity = entity;
|
|
+
|
|
+ while (child_entity->my_sched_data) { /* leaf not reached yet */
|
|
+ struct bfq_sched_data *child_sd = child_entity->my_sched_data;
|
|
+ struct bfq_service_tree *child_st = child_sd->service_tree +
|
|
+ ioprio_class;
|
|
+ struct rb_root *child_active = &child_st->active;
|
|
+
|
|
+ child_entity = bfq_entity_of(rb_first(child_active));
|
|
+
|
|
+ if (!child_entity)
|
|
+ child_entity = child_sd->in_service_entity;
|
|
+ }
|
|
|
|
+ bfqq = bfq_entity_to_bfqq(child_entity);
|
|
bfq_bfqq_move(bfqd, bfqq, bfqd->root_group);
|
|
}
|
|
|
|
/**
|
|
- * bfq_reparent_active_entities - move to the root group all active
|
|
- * entities.
|
|
+ * bfq_reparent_active_queues - move to the root group all active queues.
|
|
* @bfqd: the device data structure with the root group.
|
|
* @bfqg: the group to move from.
|
|
- * @st: the service tree with the entities.
|
|
+ * @st: the service tree to start the search from.
|
|
*/
|
|
-static void bfq_reparent_active_entities(struct bfq_data *bfqd,
|
|
- struct bfq_group *bfqg,
|
|
- struct bfq_service_tree *st)
|
|
+static void bfq_reparent_active_queues(struct bfq_data *bfqd,
|
|
+ struct bfq_group *bfqg,
|
|
+ struct bfq_service_tree *st,
|
|
+ int ioprio_class)
|
|
{
|
|
struct rb_root *active = &st->active;
|
|
- struct bfq_entity *entity = NULL;
|
|
-
|
|
- if (!RB_EMPTY_ROOT(&st->active))
|
|
- entity = bfq_entity_of(rb_first(active));
|
|
+ struct bfq_entity *entity;
|
|
|
|
- for (; entity ; entity = bfq_entity_of(rb_first(active)))
|
|
- bfq_reparent_leaf_entity(bfqd, entity);
|
|
+ while ((entity = bfq_entity_of(rb_first(active))))
|
|
+ bfq_reparent_leaf_entity(bfqd, entity, ioprio_class);
|
|
|
|
if (bfqg->sched_data.in_service_entity)
|
|
bfq_reparent_leaf_entity(bfqd,
|
|
- bfqg->sched_data.in_service_entity);
|
|
+ bfqg->sched_data.in_service_entity,
|
|
+ ioprio_class);
|
|
}
|
|
|
|
/**
|
|
@@ -865,13 +876,6 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
|
for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
|
|
st = bfqg->sched_data.service_tree + i;
|
|
|
|
- /*
|
|
- * The idle tree may still contain bfq_queues belonging
|
|
- * to exited task because they never migrated to a different
|
|
- * cgroup from the one being destroyed now.
|
|
- */
|
|
- bfq_flush_idle_tree(st);
|
|
-
|
|
/*
|
|
* It may happen that some queues are still active
|
|
* (busy) upon group destruction (if the corresponding
|
|
@@ -884,7 +888,20 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
|
* There is no need to put the sync queues, as the
|
|
* scheduler has taken no reference.
|
|
*/
|
|
- bfq_reparent_active_entities(bfqd, bfqg, st);
|
|
+ bfq_reparent_active_queues(bfqd, bfqg, st, i);
|
|
+
|
|
+ /*
|
|
+ * The idle tree may still contain bfq_queues
|
|
+ * belonging to exited task because they never
|
|
+ * migrated to a different cgroup from the one being
|
|
+ * destroyed now. In addition, even
|
|
+ * bfq_reparent_active_queues() may happen to add some
|
|
+ * entities to the idle tree. It happens if, in some
|
|
+ * of the calls to bfq_bfqq_move() performed by
|
|
+ * bfq_reparent_active_queues(), the queue to move is
|
|
+ * empty and gets expired.
|
|
+ */
|
|
+ bfq_flush_idle_tree(st);
|
|
}
|
|
|
|
__bfq_deactivate_entity(entity, false);
|
|
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
|
index 5a825f9f1ea0..88497bff1135 100644
|
|
--- a/block/bfq-iosched.c
|
|
+++ b/block/bfq-iosched.c
|
|
@@ -2717,8 +2717,6 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
|
|
}
|
|
}
|
|
|
|
-
|
|
-static
|
|
void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
|
{
|
|
/*
|
|
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
|
|
index 1553a4e8f7ad..c0232975075d 100644
|
|
--- a/block/bfq-iosched.h
|
|
+++ b/block/bfq-iosched.h
|
|
@@ -950,6 +950,7 @@ void bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|
bool compensate, enum bfqq_expiration reason);
|
|
void bfq_put_queue(struct bfq_queue *bfqq);
|
|
void bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
|
|
+void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq);
|
|
void bfq_schedule_dispatch(struct bfq_data *bfqd);
|
|
void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
|
|
|
|
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
|
|
index 7da1864798a0..ecaa28733dc6 100644
|
|
--- a/drivers/acpi/acpica/acnamesp.h
|
|
+++ b/drivers/acpi/acpica/acnamesp.h
|
|
@@ -256,6 +256,8 @@ u32
|
|
acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
|
|
char *full_path, u32 path_size, u8 no_trailing);
|
|
|
|
+void acpi_ns_normalize_pathname(char *original_path);
|
|
+
|
|
char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
|
|
u8 no_trailing);
|
|
|
|
diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c
|
|
index 55a7e10998d8..1ef053585bbb 100644
|
|
--- a/drivers/acpi/acpica/dbinput.c
|
|
+++ b/drivers/acpi/acpica/dbinput.c
|
|
@@ -464,16 +464,14 @@ char *acpi_db_get_next_token(char *string,
|
|
return (NULL);
|
|
}
|
|
|
|
- /* Remove any spaces at the beginning */
|
|
+ /* Remove any spaces at the beginning, ignore blank lines */
|
|
|
|
- if (*string == ' ') {
|
|
- while (*string && (*string == ' ')) {
|
|
- string++;
|
|
- }
|
|
+ while (*string && isspace(*string)) {
|
|
+ string++;
|
|
+ }
|
|
|
|
- if (!(*string)) {
|
|
- return (NULL);
|
|
- }
|
|
+ if (!(*string)) {
|
|
+ return (NULL);
|
|
}
|
|
|
|
switch (*string) {
|
|
@@ -551,7 +549,7 @@ char *acpi_db_get_next_token(char *string,
|
|
|
|
/* Find end of token */
|
|
|
|
- while (*string && (*string != ' ')) {
|
|
+ while (*string && !isspace(*string)) {
|
|
string++;
|
|
}
|
|
break;
|
|
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
|
|
index d75aae304595..a68237b97c4c 100644
|
|
--- a/drivers/acpi/acpica/dswexec.c
|
|
+++ b/drivers/acpi/acpica/dswexec.c
|
|
@@ -16,6 +16,9 @@
|
|
#include "acinterp.h"
|
|
#include "acnamesp.h"
|
|
#include "acdebug.h"
|
|
+#ifdef ACPI_EXEC_APP
|
|
+#include "aecommon.h"
|
|
+#endif
|
|
|
|
#define _COMPONENT ACPI_DISPATCHER
|
|
ACPI_MODULE_NAME("dswexec")
|
|
@@ -329,6 +332,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
|
u32 op_class;
|
|
union acpi_parse_object *next_op;
|
|
union acpi_parse_object *first_arg;
|
|
+#ifdef ACPI_EXEC_APP
|
|
+ char *namepath;
|
|
+ union acpi_operand_object *obj_desc;
|
|
+#endif
|
|
|
|
ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
|
|
|
|
@@ -537,6 +544,32 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
|
|
|
status =
|
|
acpi_ds_eval_buffer_field_operands(walk_state, op);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ break;
|
|
+ }
|
|
+#ifdef ACPI_EXEC_APP
|
|
+ /*
|
|
+ * acpi_exec support for namespace initialization file (initialize
|
|
+ * buffer_fields in this code.)
|
|
+ */
|
|
+ namepath =
|
|
+ acpi_ns_get_external_pathname(op->common.node);
|
|
+ status = ae_lookup_init_file_entry(namepath, &obj_desc);
|
|
+ if (ACPI_SUCCESS(status)) {
|
|
+ status =
|
|
+ acpi_ex_write_data_to_field(obj_desc,
|
|
+ op->common.
|
|
+ node->object,
|
|
+ NULL);
|
|
+ if ACPI_FAILURE
|
|
+ (status) {
|
|
+ ACPI_EXCEPTION((AE_INFO, status,
|
|
+ "While writing to buffer field"));
|
|
+ }
|
|
+ }
|
|
+ ACPI_FREE(namepath);
|
|
+ status = AE_OK;
|
|
+#endif
|
|
break;
|
|
|
|
case AML_TYPE_CREATE_OBJECT:
|
|
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
|
|
index 4bcf15bf03de..6cf93fae4d07 100644
|
|
--- a/drivers/acpi/acpica/dswload.c
|
|
+++ b/drivers/acpi/acpica/dswload.c
|
|
@@ -14,7 +14,6 @@
|
|
#include "acdispat.h"
|
|
#include "acinterp.h"
|
|
#include "acnamesp.h"
|
|
-
|
|
#ifdef ACPI_ASL_COMPILER
|
|
#include "acdisasm.h"
|
|
#endif
|
|
@@ -399,7 +398,6 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
|
|
union acpi_parse_object *op;
|
|
acpi_object_type object_type;
|
|
acpi_status status = AE_OK;
|
|
-
|
|
#ifdef ACPI_ASL_COMPILER
|
|
u8 param_count;
|
|
#endif
|
|
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
|
|
index 935a8e2623e4..15d92bf15f0b 100644
|
|
--- a/drivers/acpi/acpica/dswload2.c
|
|
+++ b/drivers/acpi/acpica/dswload2.c
|
|
@@ -15,6 +15,9 @@
|
|
#include "acinterp.h"
|
|
#include "acnamesp.h"
|
|
#include "acevents.h"
|
|
+#ifdef ACPI_EXEC_APP
|
|
+#include "aecommon.h"
|
|
+#endif
|
|
|
|
#define _COMPONENT ACPI_DISPATCHER
|
|
ACPI_MODULE_NAME("dswload2")
|
|
@@ -373,6 +376,10 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
|
|
struct acpi_namespace_node *new_node;
|
|
u32 i;
|
|
u8 region_space;
|
|
+#ifdef ACPI_EXEC_APP
|
|
+ union acpi_operand_object *obj_desc;
|
|
+ char *namepath;
|
|
+#endif
|
|
|
|
ACPI_FUNCTION_TRACE(ds_load2_end_op);
|
|
|
|
@@ -466,6 +473,11 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
|
|
* be evaluated later during the execution phase
|
|
*/
|
|
status = acpi_ds_create_buffer_field(op, walk_state);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ ACPI_EXCEPTION((AE_INFO, status,
|
|
+ "CreateBufferField failure"));
|
|
+ goto cleanup;
|
|
+ }
|
|
break;
|
|
|
|
case AML_TYPE_NAMED_FIELD:
|
|
@@ -604,6 +616,29 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
|
|
case AML_NAME_OP:
|
|
|
|
status = acpi_ds_create_node(walk_state, node, op);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+#ifdef ACPI_EXEC_APP
|
|
+ /*
|
|
+ * acpi_exec support for namespace initialization file (initialize
|
|
+ * Name opcodes in this code.)
|
|
+ */
|
|
+ namepath = acpi_ns_get_external_pathname(node);
|
|
+ status = ae_lookup_init_file_entry(namepath, &obj_desc);
|
|
+ if (ACPI_SUCCESS(status)) {
|
|
+
|
|
+ /* Detach any existing object, attach new object */
|
|
+
|
|
+ if (node->object) {
|
|
+ acpi_ns_detach_object(node);
|
|
+ }
|
|
+ acpi_ns_attach_object(node, obj_desc,
|
|
+ obj_desc->common.type);
|
|
+ }
|
|
+ ACPI_FREE(namepath);
|
|
+ status = AE_OK;
|
|
+#endif
|
|
break;
|
|
|
|
case AML_METHOD_OP:
|
|
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
|
|
index 370bbc867745..c717fff7d9b5 100644
|
|
--- a/drivers/acpi/acpica/nsnames.c
|
|
+++ b/drivers/acpi/acpica/nsnames.c
|
|
@@ -13,9 +13,6 @@
|
|
#define _COMPONENT ACPI_NAMESPACE
|
|
ACPI_MODULE_NAME("nsnames")
|
|
|
|
-/* Local Prototypes */
|
|
-static void acpi_ns_normalize_pathname(char *original_path);
|
|
-
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_ns_get_external_pathname
|
|
@@ -30,7 +27,6 @@ static void acpi_ns_normalize_pathname(char *original_path);
|
|
* for error and debug statements.
|
|
*
|
|
******************************************************************************/
|
|
-
|
|
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
|
|
{
|
|
char *name_buffer;
|
|
@@ -411,7 +407,7 @@ cleanup:
|
|
*
|
|
******************************************************************************/
|
|
|
|
-static void acpi_ns_normalize_pathname(char *original_path)
|
|
+void acpi_ns_normalize_pathname(char *original_path)
|
|
{
|
|
char *input_path = original_path;
|
|
char *new_path_buffer;
|
|
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
|
|
index eee263cb7beb..c365faf4e6cd 100644
|
|
--- a/drivers/acpi/acpica/utdelete.c
|
|
+++ b/drivers/acpi/acpica/utdelete.c
|
|
@@ -452,13 +452,13 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
|
|
*
|
|
* FUNCTION: acpi_ut_update_object_reference
|
|
*
|
|
- * PARAMETERS: object - Increment ref count for this object
|
|
- * and all sub-objects
|
|
+ * PARAMETERS: object - Increment or decrement the ref count for
|
|
+ * this object and all sub-objects
|
|
* action - Either REF_INCREMENT or REF_DECREMENT
|
|
*
|
|
* RETURN: Status
|
|
*
|
|
- * DESCRIPTION: Increment the object reference count
|
|
+ * DESCRIPTION: Increment or decrement the object reference count
|
|
*
|
|
* Object references are incremented when:
|
|
* 1) An object is attached to a Node (namespace object)
|
|
@@ -492,7 +492,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
|
|
}
|
|
|
|
/*
|
|
- * All sub-objects must have their reference count incremented
|
|
+ * All sub-objects must have their reference count updated
|
|
* also. Different object types have different subobjects.
|
|
*/
|
|
switch (object->common.type) {
|
|
@@ -559,6 +559,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
|
|
break;
|
|
}
|
|
}
|
|
+
|
|
next_object = NULL;
|
|
break;
|
|
|
|
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
|
|
index 532a1ae3595a..a0bd56ece3ff 100644
|
|
--- a/drivers/acpi/processor_throttling.c
|
|
+++ b/drivers/acpi/processor_throttling.c
|
|
@@ -897,13 +897,6 @@ static long __acpi_processor_get_throttling(void *data)
|
|
return pr->throttling.acpi_processor_get_throttling(pr);
|
|
}
|
|
|
|
-static int call_on_cpu(int cpu, long (*fn)(void *), void *arg, bool direct)
|
|
-{
|
|
- if (direct || (is_percpu_thread() && cpu == smp_processor_id()))
|
|
- return fn(arg);
|
|
- return work_on_cpu(cpu, fn, arg);
|
|
-}
|
|
-
|
|
static int acpi_processor_get_throttling(struct acpi_processor *pr)
|
|
{
|
|
if (!pr)
|
|
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
|
|
index a67315786db4..274beda31c35 100644
|
|
--- a/drivers/block/rbd.c
|
|
+++ b/drivers/block/rbd.c
|
|
@@ -4636,6 +4636,10 @@ static void cancel_tasks_sync(struct rbd_device *rbd_dev)
|
|
cancel_work_sync(&rbd_dev->unlock_work);
|
|
}
|
|
|
|
+/*
|
|
+ * header_rwsem must not be held to avoid a deadlock with
|
|
+ * rbd_dev_refresh() when flushing notifies.
|
|
+ */
|
|
static void rbd_unregister_watch(struct rbd_device *rbd_dev)
|
|
{
|
|
cancel_tasks_sync(rbd_dev);
|
|
@@ -6929,9 +6933,10 @@ static int rbd_dev_header_name(struct rbd_device *rbd_dev)
|
|
|
|
static void rbd_dev_image_release(struct rbd_device *rbd_dev)
|
|
{
|
|
- rbd_dev_unprobe(rbd_dev);
|
|
if (rbd_dev->opts)
|
|
rbd_unregister_watch(rbd_dev);
|
|
+
|
|
+ rbd_dev_unprobe(rbd_dev);
|
|
rbd_dev->image_format = 0;
|
|
kfree(rbd_dev->spec->image_id);
|
|
rbd_dev->spec->image_id = NULL;
|
|
@@ -6942,6 +6947,9 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
|
|
* device. If this image is the one being mapped (i.e., not a
|
|
* parent), initiate a watch on its header object before using that
|
|
* object to get detailed information about the rbd image.
|
|
+ *
|
|
+ * On success, returns with header_rwsem held for write if called
|
|
+ * with @depth == 0.
|
|
*/
|
|
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
|
|
{
|
|
@@ -6974,9 +6982,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
|
|
}
|
|
}
|
|
|
|
+ if (!depth)
|
|
+ down_write(&rbd_dev->header_rwsem);
|
|
+
|
|
ret = rbd_dev_header_info(rbd_dev);
|
|
if (ret)
|
|
- goto err_out_watch;
|
|
+ goto err_out_probe;
|
|
|
|
/*
|
|
* If this image is the one being mapped, we have pool name and
|
|
@@ -7025,10 +7036,11 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
|
|
return 0;
|
|
|
|
err_out_probe:
|
|
- rbd_dev_unprobe(rbd_dev);
|
|
-err_out_watch:
|
|
+ if (!depth)
|
|
+ up_write(&rbd_dev->header_rwsem);
|
|
if (!depth)
|
|
rbd_unregister_watch(rbd_dev);
|
|
+ rbd_dev_unprobe(rbd_dev);
|
|
err_out_format:
|
|
rbd_dev->image_format = 0;
|
|
kfree(rbd_dev->spec->image_id);
|
|
@@ -7085,12 +7097,9 @@ static ssize_t do_rbd_add(struct bus_type *bus,
|
|
goto err_out_rbd_dev;
|
|
}
|
|
|
|
- down_write(&rbd_dev->header_rwsem);
|
|
rc = rbd_dev_image_probe(rbd_dev, 0);
|
|
- if (rc < 0) {
|
|
- up_write(&rbd_dev->header_rwsem);
|
|
+ if (rc < 0)
|
|
goto err_out_rbd_dev;
|
|
- }
|
|
|
|
/* If we are mapping a snapshot it must be marked read-only */
|
|
if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
|
|
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
|
|
index bda92980e015..c0895c993cce 100644
|
|
--- a/drivers/clk/at91/clk-usb.c
|
|
+++ b/drivers/clk/at91/clk-usb.c
|
|
@@ -75,6 +75,9 @@ static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
|
|
tmp_parent_rate = req->rate * div;
|
|
tmp_parent_rate = clk_hw_round_rate(parent,
|
|
tmp_parent_rate);
|
|
+ if (!tmp_parent_rate)
|
|
+ continue;
|
|
+
|
|
tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
|
|
if (tmp_rate < req->rate)
|
|
tmp_diff = req->rate - tmp_rate;
|
|
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
|
index 62d0fc486d3a..80b029713722 100644
|
|
--- a/drivers/clk/clk.c
|
|
+++ b/drivers/clk/clk.c
|
|
@@ -2642,12 +2642,14 @@ static int clk_core_get_phase(struct clk_core *core)
|
|
{
|
|
int ret;
|
|
|
|
- clk_prepare_lock();
|
|
+ lockdep_assert_held(&prepare_lock);
|
|
+ if (!core->ops->get_phase)
|
|
+ return 0;
|
|
+
|
|
/* Always try to update cached phase if possible */
|
|
- if (core->ops->get_phase)
|
|
- core->phase = core->ops->get_phase(core->hw);
|
|
- ret = core->phase;
|
|
- clk_prepare_unlock();
|
|
+ ret = core->ops->get_phase(core->hw);
|
|
+ if (ret >= 0)
|
|
+ core->phase = ret;
|
|
|
|
return ret;
|
|
}
|
|
@@ -2661,10 +2663,16 @@ static int clk_core_get_phase(struct clk_core *core)
|
|
*/
|
|
int clk_get_phase(struct clk *clk)
|
|
{
|
|
+ int ret;
|
|
+
|
|
if (!clk)
|
|
return 0;
|
|
|
|
- return clk_core_get_phase(clk->core);
|
|
+ clk_prepare_lock();
|
|
+ ret = clk_core_get_phase(clk->core);
|
|
+ clk_prepare_unlock();
|
|
+
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(clk_get_phase);
|
|
|
|
@@ -2878,13 +2886,21 @@ static struct hlist_head *orphan_list[] = {
|
|
static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
|
|
int level)
|
|
{
|
|
- seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
|
|
+ int phase;
|
|
+
|
|
+ seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
|
|
level * 3 + 1, "",
|
|
30 - level * 3, c->name,
|
|
c->enable_count, c->prepare_count, c->protect_count,
|
|
- clk_core_get_rate(c), clk_core_get_accuracy(c),
|
|
- clk_core_get_phase(c),
|
|
- clk_core_get_scaled_duty_cycle(c, 100000));
|
|
+ clk_core_get_rate(c), clk_core_get_accuracy(c));
|
|
+
|
|
+ phase = clk_core_get_phase(c);
|
|
+ if (phase >= 0)
|
|
+ seq_printf(s, "%5d", phase);
|
|
+ else
|
|
+ seq_puts(s, "-----");
|
|
+
|
|
+ seq_printf(s, " %6d\n", clk_core_get_scaled_duty_cycle(c, 100000));
|
|
}
|
|
|
|
static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
|
|
@@ -2921,6 +2937,7 @@ DEFINE_SHOW_ATTRIBUTE(clk_summary);
|
|
|
|
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
|
|
{
|
|
+ int phase;
|
|
unsigned long min_rate, max_rate;
|
|
|
|
clk_core_get_boundaries(c, &min_rate, &max_rate);
|
|
@@ -2934,7 +2951,9 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
|
|
seq_printf(s, "\"min_rate\": %lu,", min_rate);
|
|
seq_printf(s, "\"max_rate\": %lu,", max_rate);
|
|
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
|
|
- seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
|
|
+ phase = clk_core_get_phase(c);
|
|
+ if (phase >= 0)
|
|
+ seq_printf(s, "\"phase\": %d,", phase);
|
|
seq_printf(s, "\"duty_cycle\": %u",
|
|
clk_core_get_scaled_duty_cycle(c, 100000));
|
|
}
|
|
@@ -3375,14 +3394,11 @@ static int __clk_core_init(struct clk_core *core)
|
|
core->accuracy = 0;
|
|
|
|
/*
|
|
- * Set clk's phase.
|
|
+ * Set clk's phase by clk_core_get_phase() caching the phase.
|
|
* Since a phase is by definition relative to its parent, just
|
|
* query the current clock phase, or just assume it's in phase.
|
|
*/
|
|
- if (core->ops->get_phase)
|
|
- core->phase = core->ops->get_phase(core->hw);
|
|
- else
|
|
- core->phase = 0;
|
|
+ clk_core_get_phase(core);
|
|
|
|
/*
|
|
* Set clk's duty cycle.
|
|
diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c
|
|
index bec3e008335f..5e044ba1ae36 100644
|
|
--- a/drivers/clk/tegra/clk-tegra-pmc.c
|
|
+++ b/drivers/clk/tegra/clk-tegra-pmc.c
|
|
@@ -49,16 +49,16 @@ struct pmc_clk_init_data {
|
|
|
|
static DEFINE_SPINLOCK(clk_out_lock);
|
|
|
|
-static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
|
|
- "clk_m_div4", "extern1",
|
|
+static const char *clk_out1_parents[] = { "osc", "osc_div2",
|
|
+ "osc_div4", "extern1",
|
|
};
|
|
|
|
-static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
|
|
- "clk_m_div4", "extern2",
|
|
+static const char *clk_out2_parents[] = { "osc", "osc_div2",
|
|
+ "osc_div4", "extern2",
|
|
};
|
|
|
|
-static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
|
|
- "clk_m_div4", "extern3",
|
|
+static const char *clk_out3_parents[] = { "osc", "osc_div2",
|
|
+ "osc_div4", "extern3",
|
|
};
|
|
|
|
static struct pmc_clk_init_data pmc_clks[] = {
|
|
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
|
|
index 0dc1084b5e82..ad9483b9eea3 100644
|
|
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
|
|
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
|
|
@@ -1112,9 +1112,9 @@ kfd_gtt_out:
|
|
return 0;
|
|
|
|
kfd_gtt_no_free_chunk:
|
|
- pr_debug("Allocation failed with mem_obj = %p\n", mem_obj);
|
|
+ pr_debug("Allocation failed with mem_obj = %p\n", *mem_obj);
|
|
mutex_unlock(&kfd->gtt_sa_lock);
|
|
- kfree(mem_obj);
|
|
+ kfree(*mem_obj);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
index 2cd83849600f..b1beed40e746 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
@@ -618,6 +618,64 @@ nouveau_drm_device_fini(struct drm_device *dev)
|
|
kfree(drm);
|
|
}
|
|
|
|
+/*
|
|
+ * On some Intel PCIe bridge controllers doing a
|
|
+ * D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear.
|
|
+ * Skipping the intermediate D3hot step seems to make it work again. This is
|
|
+ * probably caused by not meeting the expectation the involved AML code has
|
|
+ * when the GPU is put into D3hot state before invoking it.
|
|
+ *
|
|
+ * This leads to various manifestations of this issue:
|
|
+ * - AML code execution to power on the GPU hits an infinite loop (as the
|
|
+ * code waits on device memory to change).
|
|
+ * - kernel crashes, as all PCI reads return -1, which most code isn't able
|
|
+ * to handle well enough.
|
|
+ *
|
|
+ * In all cases dmesg will contain at least one line like this:
|
|
+ * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3'
|
|
+ * followed by a lot of nouveau timeouts.
|
|
+ *
|
|
+ * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not
|
|
+ * documented PCI config space register 0x248 of the Intel PCIe bridge
|
|
+ * controller (0x1901) in order to change the state of the PCIe link between
|
|
+ * the PCIe port and the GPU. There are alternative code paths using other
|
|
+ * registers, which seem to work fine (executed pre Windows 8):
|
|
+ * - 0xbc bit 0x20 (publicly available documentation claims 'reserved')
|
|
+ * - 0xb0 bit 0x10 (link disable)
|
|
+ * Changing the conditions inside the firmware by poking into the relevant
|
|
+ * addresses does resolve the issue, but it seemed to be ACPI private memory
|
|
+ * and not any device accessible memory at all, so there is no portable way of
|
|
+ * changing the conditions.
|
|
+ * On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared.
|
|
+ *
|
|
+ * The only systems where this behavior can be seen are hybrid graphics laptops
|
|
+ * with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether
|
|
+ * this issue only occurs in combination with listed Intel PCIe bridge
|
|
+ * controllers and the mentioned GPUs or other devices as well.
|
|
+ *
|
|
+ * documentation on the PCIe bridge controller can be found in the
|
|
+ * "7th Generation Intel® Processor Families for H Platforms Datasheet Volume 2"
|
|
+ * Section "12 PCI Express* Controller (x16) Registers"
|
|
+ */
|
|
+
|
|
+static void quirk_broken_nv_runpm(struct pci_dev *pdev)
|
|
+{
|
|
+ struct drm_device *dev = pci_get_drvdata(pdev);
|
|
+ struct nouveau_drm *drm = nouveau_drm(dev);
|
|
+ struct pci_dev *bridge = pci_upstream_bridge(pdev);
|
|
+
|
|
+ if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL)
|
|
+ return;
|
|
+
|
|
+ switch (bridge->device) {
|
|
+ case 0x1901:
|
|
+ drm->old_pm_cap = pdev->pm_cap;
|
|
+ pdev->pm_cap = 0;
|
|
+ NV_INFO(drm, "Disabling PCI power management to avoid bug\n");
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
static int nouveau_drm_probe(struct pci_dev *pdev,
|
|
const struct pci_device_id *pent)
|
|
{
|
|
@@ -699,6 +757,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
|
|
if (ret)
|
|
goto fail_drm_dev_init;
|
|
|
|
+ quirk_broken_nv_runpm(pdev);
|
|
return 0;
|
|
|
|
fail_drm_dev_init:
|
|
@@ -736,7 +795,11 @@ static void
|
|
nouveau_drm_remove(struct pci_dev *pdev)
|
|
{
|
|
struct drm_device *dev = pci_get_drvdata(pdev);
|
|
+ struct nouveau_drm *drm = nouveau_drm(dev);
|
|
|
|
+ /* revert our workaround */
|
|
+ if (drm->old_pm_cap)
|
|
+ pdev->pm_cap = drm->old_pm_cap;
|
|
nouveau_drm_device_remove(dev);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
index 70f34cacc552..8104e3806499 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
@@ -138,6 +138,8 @@ struct nouveau_drm {
|
|
|
|
struct list_head clients;
|
|
|
|
+ u8 old_pm_cap;
|
|
+
|
|
struct {
|
|
struct agp_bridge_data *bridge;
|
|
u32 base;
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
|
|
index 668d4bd0c118..824654742a60 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
|
|
@@ -173,6 +173,11 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
|
|
mm = get_task_mm(current);
|
|
down_read(&mm->mmap_sem);
|
|
|
|
+ if (!cli->svm.svmm) {
|
|
+ up_read(&mm->mmap_sem);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
for (addr = args->va_start, end = args->va_start + size; addr < end;) {
|
|
struct vm_area_struct *vma;
|
|
unsigned long next;
|
|
@@ -181,6 +186,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
|
|
if (!vma)
|
|
break;
|
|
|
|
+ addr = max(addr, vma->vm_start);
|
|
next = min(vma->vm_end, end);
|
|
/* This is a best effort so we ignore errors */
|
|
nouveau_dmem_migrate_vma(cli->drm, vma, addr, next);
|
|
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
index c578deb5867a..c71606a45d1d 100644
|
|
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
@@ -1988,8 +1988,34 @@ gf100_gr_init_(struct nvkm_gr *base)
|
|
{
|
|
struct gf100_gr *gr = gf100_gr(base);
|
|
struct nvkm_subdev *subdev = &base->engine.subdev;
|
|
+ struct nvkm_device *device = subdev->device;
|
|
+ bool reset = device->chipset == 0x137 || device->chipset == 0x138;
|
|
u32 ret;
|
|
|
|
+ /* On certain GP107/GP108 boards, we trigger a weird issue where
|
|
+ * GR will stop responding to PRI accesses after we've asked the
|
|
+ * SEC2 RTOS to boot the GR falcons. This happens with far more
|
|
+ * frequency when cold-booting a board (ie. returning from D3).
|
|
+ *
|
|
+ * The root cause for this is not known and has proven difficult
|
|
+ * to isolate, with many avenues being dead-ends.
|
|
+ *
|
|
+ * A workaround was discovered by Karol, whereby putting GR into
|
|
+ * reset for an extended period right before initialisation
|
|
+ * prevents the problem from occuring.
|
|
+ *
|
|
+ * XXX: As RM does not require any such workaround, this is more
|
|
+ * of a hack than a true fix.
|
|
+ */
|
|
+ reset = nvkm_boolopt(device->cfgopt, "NvGrResetWar", reset);
|
|
+ if (reset) {
|
|
+ nvkm_mask(device, 0x000200, 0x00001000, 0x00000000);
|
|
+ nvkm_rd32(device, 0x000200);
|
|
+ msleep(50);
|
|
+ nvkm_mask(device, 0x000200, 0x00001000, 0x00001000);
|
|
+ nvkm_rd32(device, 0x000200);
|
|
+ }
|
|
+
|
|
nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
|
|
|
|
ret = nvkm_falcon_get(gr->fecs.falcon, subdev);
|
|
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
|
|
index f07803699809..abf165b2f64f 100644
|
|
--- a/drivers/gpu/drm/ttm/ttm_bo.c
|
|
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
|
|
@@ -517,8 +517,10 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
|
|
|
|
dma_resv_unlock(bo->base.resv);
|
|
}
|
|
- if (bo->base.resv != &bo->base._resv)
|
|
+ if (bo->base.resv != &bo->base._resv) {
|
|
+ ttm_bo_flush_all_fences(bo);
|
|
dma_resv_unlock(&bo->base._resv);
|
|
+ }
|
|
|
|
error:
|
|
kref_get(&bo->list_kref);
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
index 0853b980bcb3..d5f5ba410524 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
@@ -681,11 +681,23 @@ static enum drm_mode_status
|
|
vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
|
|
const struct drm_display_mode *mode)
|
|
{
|
|
- /* HSM clock must be 108% of the pixel clock. Additionally,
|
|
- * the AXI clock needs to be at least 25% of pixel clock, but
|
|
- * HSM ends up being the limiting factor.
|
|
+ /*
|
|
+ * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
|
|
+ * be faster than pixel clock, infinitesimally faster, tested in
|
|
+ * simulation. Otherwise, exact value is unimportant for HDMI
|
|
+ * operation." This conflicts with bcm2835's vc4 documentation, which
|
|
+ * states HSM's clock has to be at least 108% of the pixel clock.
|
|
+ *
|
|
+ * Real life tests reveal that vc4's firmware statement holds up, and
|
|
+ * users are able to use pixel clocks closer to HSM's, namely for
|
|
+ * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
|
|
+ * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
|
|
+ * 162MHz.
|
|
+ *
|
|
+ * Additionally, the AXI clock needs to be at least 25% of
|
|
+ * pixel clock, but HSM ends up being the limiting factor.
|
|
*/
|
|
- if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100))
|
|
+ if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
|
|
return MODE_CLOCK_HIGH;
|
|
|
|
return MODE_OK;
|
|
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
|
index 8eb167540b4f..c8296d5e74c3 100644
|
|
--- a/drivers/hv/channel_mgmt.c
|
|
+++ b/drivers/hv/channel_mgmt.c
|
|
@@ -839,6 +839,9 @@ void vmbus_initiate_unload(bool crash)
|
|
{
|
|
struct vmbus_channel_message_header hdr;
|
|
|
|
+ if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED)
|
|
+ return;
|
|
+
|
|
/* Pre-Win2012R2 hosts don't support reconnect */
|
|
if (vmbus_proto_version < VERSION_WIN8_1)
|
|
return;
|
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
|
index 05ead1735c6e..40f6b73dae94 100644
|
|
--- a/drivers/hv/vmbus_drv.c
|
|
+++ b/drivers/hv/vmbus_drv.c
|
|
@@ -31,6 +31,7 @@
|
|
#include <linux/kdebug.h>
|
|
#include <linux/efi.h>
|
|
#include <linux/random.h>
|
|
+#include <linux/kernel.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <clocksource/hyperv_timer.h>
|
|
#include "hyperv_vmbus.h"
|
|
@@ -48,14 +49,35 @@ static int hyperv_cpuhp_online;
|
|
|
|
static void *hv_panic_page;
|
|
|
|
+/*
|
|
+ * Boolean to control whether to report panic messages over Hyper-V.
|
|
+ *
|
|
+ * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
|
|
+ */
|
|
+static int sysctl_record_panic_msg = 1;
|
|
+
|
|
+static int hyperv_report_reg(void)
|
|
+{
|
|
+ return !sysctl_record_panic_msg || !hv_panic_page;
|
|
+}
|
|
+
|
|
static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
|
|
void *args)
|
|
{
|
|
struct pt_regs *regs;
|
|
|
|
- regs = current_pt_regs();
|
|
+ vmbus_initiate_unload(true);
|
|
|
|
- hyperv_report_panic(regs, val);
|
|
+ /*
|
|
+ * Hyper-V should be notified only once about a panic. If we will be
|
|
+ * doing hyperv_report_panic_msg() later with kmsg data, don't do
|
|
+ * the notification here.
|
|
+ */
|
|
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
|
|
+ && hyperv_report_reg()) {
|
|
+ regs = current_pt_regs();
|
|
+ hyperv_report_panic(regs, val, false);
|
|
+ }
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
@@ -65,7 +87,13 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
|
|
struct die_args *die = (struct die_args *)args;
|
|
struct pt_regs *regs = die->regs;
|
|
|
|
- hyperv_report_panic(regs, val);
|
|
+ /*
|
|
+ * Hyper-V should be notified only once about a panic. If we will be
|
|
+ * doing hyperv_report_panic_msg() later with kmsg data, don't do
|
|
+ * the notification here.
|
|
+ */
|
|
+ if (hyperv_report_reg())
|
|
+ hyperv_report_panic(regs, val, true);
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
@@ -1246,13 +1274,6 @@ static void vmbus_isr(void)
|
|
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
|
|
}
|
|
|
|
-/*
|
|
- * Boolean to control whether to report panic messages over Hyper-V.
|
|
- *
|
|
- * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
|
|
- */
|
|
-static int sysctl_record_panic_msg = 1;
|
|
-
|
|
/*
|
|
* Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
|
|
* buffer and call into Hyper-V to transfer the data.
|
|
@@ -1380,19 +1401,29 @@ static int vmbus_bus_init(void)
|
|
hv_panic_page = (void *)get_zeroed_page(GFP_KERNEL);
|
|
if (hv_panic_page) {
|
|
ret = kmsg_dump_register(&hv_kmsg_dumper);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
pr_err("Hyper-V: kmsg dump register "
|
|
"error 0x%x\n", ret);
|
|
+ hv_free_hyperv_page(
|
|
+ (unsigned long)hv_panic_page);
|
|
+ hv_panic_page = NULL;
|
|
+ }
|
|
} else
|
|
pr_err("Hyper-V: panic message page memory "
|
|
"allocation failed");
|
|
}
|
|
|
|
register_die_notifier(&hyperv_die_block);
|
|
- atomic_notifier_chain_register(&panic_notifier_list,
|
|
- &hyperv_panic_block);
|
|
}
|
|
|
|
+ /*
|
|
+ * Always register the panic notifier because we need to unload
|
|
+ * the VMbus channel connection to prevent any VMbus
|
|
+ * activity after the VM panics.
|
|
+ */
|
|
+ atomic_notifier_chain_register(&panic_notifier_list,
|
|
+ &hyperv_panic_block);
|
|
+
|
|
vmbus_request_offers();
|
|
|
|
return 0;
|
|
@@ -1406,7 +1437,6 @@ err_alloc:
|
|
hv_remove_vmbus_irq();
|
|
|
|
bus_unregister(&hv_bus);
|
|
- free_page((unsigned long)hv_panic_page);
|
|
unregister_sysctl_table(hv_ctl_table_hdr);
|
|
hv_ctl_table_hdr = NULL;
|
|
return ret;
|
|
@@ -2202,8 +2232,6 @@ static int vmbus_bus_suspend(struct device *dev)
|
|
|
|
vmbus_initiate_unload(false);
|
|
|
|
- vmbus_connection.conn_state = DISCONNECTED;
|
|
-
|
|
/* Reset the event for the next resume. */
|
|
reinit_completion(&vmbus_connection.ready_for_resume_event);
|
|
|
|
@@ -2288,7 +2316,6 @@ static void hv_kexec_handler(void)
|
|
{
|
|
hv_stimer_global_cleanup();
|
|
vmbus_initiate_unload(false);
|
|
- vmbus_connection.conn_state = DISCONNECTED;
|
|
/* Make sure conn_state is set as hv_synic_cleanup checks for it */
|
|
mb();
|
|
cpuhp_remove_state(hyperv_cpuhp_online);
|
|
@@ -2305,7 +2332,6 @@ static void hv_crash_handler(struct pt_regs *regs)
|
|
* doing the cleanup for current CPU only. This should be sufficient
|
|
* for kdump.
|
|
*/
|
|
- vmbus_connection.conn_state = DISCONNECTED;
|
|
cpu = smp_processor_id();
|
|
hv_stimer_cleanup(cpu);
|
|
hv_synic_disable_regs(cpu);
|
|
diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c
|
|
index 015a21f0c2ef..9174ab928880 100644
|
|
--- a/drivers/iio/light/si1133.c
|
|
+++ b/drivers/iio/light/si1133.c
|
|
@@ -102,6 +102,9 @@
|
|
#define SI1133_INPUT_FRACTION_LOW 15
|
|
#define SI1133_LUX_OUTPUT_FRACTION 12
|
|
#define SI1133_LUX_BUFFER_SIZE 9
|
|
+#define SI1133_MEASURE_BUFFER_SIZE 3
|
|
+
|
|
+#define SI1133_SIGN_BIT_INDEX 23
|
|
|
|
static const int si1133_scale_available[] = {
|
|
1, 2, 4, 8, 16, 32, 64, 128};
|
|
@@ -234,13 +237,13 @@ static const struct si1133_lux_coeff lux_coeff = {
|
|
}
|
|
};
|
|
|
|
-static int si1133_calculate_polynomial_inner(u32 input, u8 fraction, u16 mag,
|
|
+static int si1133_calculate_polynomial_inner(s32 input, u8 fraction, u16 mag,
|
|
s8 shift)
|
|
{
|
|
return ((input << fraction) / mag) << shift;
|
|
}
|
|
|
|
-static int si1133_calculate_output(u32 x, u32 y, u8 x_order, u8 y_order,
|
|
+static int si1133_calculate_output(s32 x, s32 y, u8 x_order, u8 y_order,
|
|
u8 input_fraction, s8 sign,
|
|
const struct si1133_coeff *coeffs)
|
|
{
|
|
@@ -276,7 +279,7 @@ static int si1133_calculate_output(u32 x, u32 y, u8 x_order, u8 y_order,
|
|
* The algorithm is from:
|
|
* https://siliconlabs.github.io/Gecko_SDK_Doc/efm32zg/html/si1133_8c_source.html#l00716
|
|
*/
|
|
-static int si1133_calc_polynomial(u32 x, u32 y, u8 input_fraction, u8 num_coeff,
|
|
+static int si1133_calc_polynomial(s32 x, s32 y, u8 input_fraction, u8 num_coeff,
|
|
const struct si1133_coeff *coeffs)
|
|
{
|
|
u8 x_order, y_order;
|
|
@@ -614,7 +617,7 @@ static int si1133_measure(struct si1133_data *data,
|
|
{
|
|
int err;
|
|
|
|
- __be16 resp;
|
|
+ u8 buffer[SI1133_MEASURE_BUFFER_SIZE];
|
|
|
|
err = si1133_set_adcmux(data, 0, chan->channel);
|
|
if (err)
|
|
@@ -625,12 +628,13 @@ static int si1133_measure(struct si1133_data *data,
|
|
if (err)
|
|
return err;
|
|
|
|
- err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(resp),
|
|
- (u8 *)&resp);
|
|
+ err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(buffer),
|
|
+ buffer);
|
|
if (err)
|
|
return err;
|
|
|
|
- *val = be16_to_cpu(resp);
|
|
+ *val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
|
|
+ SI1133_SIGN_BIT_INDEX);
|
|
|
|
return err;
|
|
}
|
|
@@ -704,9 +708,9 @@ static int si1133_get_lux(struct si1133_data *data, int *val)
|
|
{
|
|
int err;
|
|
int lux;
|
|
- u32 high_vis;
|
|
- u32 low_vis;
|
|
- u32 ir;
|
|
+ s32 high_vis;
|
|
+ s32 low_vis;
|
|
+ s32 ir;
|
|
u8 buffer[SI1133_LUX_BUFFER_SIZE];
|
|
|
|
/* Activate lux channels */
|
|
@@ -719,9 +723,16 @@ static int si1133_get_lux(struct si1133_data *data, int *val)
|
|
if (err)
|
|
return err;
|
|
|
|
- high_vis = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
|
- low_vis = (buffer[3] << 16) | (buffer[4] << 8) | buffer[5];
|
|
- ir = (buffer[6] << 16) | (buffer[7] << 8) | buffer[8];
|
|
+ high_vis =
|
|
+ sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
|
|
+ SI1133_SIGN_BIT_INDEX);
|
|
+
|
|
+ low_vis =
|
|
+ sign_extend32((buffer[3] << 16) | (buffer[4] << 8) | buffer[5],
|
|
+ SI1133_SIGN_BIT_INDEX);
|
|
+
|
|
+ ir = sign_extend32((buffer[6] << 16) | (buffer[7] << 8) | buffer[8],
|
|
+ SI1133_SIGN_BIT_INDEX);
|
|
|
|
if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD)
|
|
lux = si1133_calc_polynomial(high_vis, ir,
|
|
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
|
|
index daeabd98c60e..0679896b9e2e 100644
|
|
--- a/drivers/iommu/amd_iommu_types.h
|
|
+++ b/drivers/iommu/amd_iommu_types.h
|
|
@@ -348,7 +348,7 @@
|
|
|
|
#define DTE_GCR3_VAL_A(x) (((x) >> 12) & 0x00007ULL)
|
|
#define DTE_GCR3_VAL_B(x) (((x) >> 15) & 0x0ffffULL)
|
|
-#define DTE_GCR3_VAL_C(x) (((x) >> 31) & 0xfffffULL)
|
|
+#define DTE_GCR3_VAL_C(x) (((x) >> 31) & 0x1fffffULL)
|
|
|
|
#define DTE_GCR3_INDEX_A 0
|
|
#define DTE_GCR3_INDEX_B 1
|
|
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
|
|
index 0d922eeae357..773ac2b0d606 100644
|
|
--- a/drivers/iommu/intel-iommu.c
|
|
+++ b/drivers/iommu/intel-iommu.c
|
|
@@ -4335,7 +4335,8 @@ static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
|
|
struct dmar_atsr_unit *atsru;
|
|
struct acpi_dmar_atsr *tmp;
|
|
|
|
- list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
|
|
+ list_for_each_entry_rcu(atsru, &dmar_atsr_units, list,
|
|
+ dmar_rcu_check()) {
|
|
tmp = (struct acpi_dmar_atsr *)atsru->hdr;
|
|
if (atsr->segment != tmp->segment)
|
|
continue;
|
|
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
|
|
index 518d0b2d12af..1d3816cd65d5 100644
|
|
--- a/drivers/iommu/intel-svm.c
|
|
+++ b/drivers/iommu/intel-svm.c
|
|
@@ -502,7 +502,7 @@ struct page_req_dsc {
|
|
u64 priv_data[2];
|
|
};
|
|
|
|
-#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
|
|
+#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x20)
|
|
|
|
static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req)
|
|
{
|
|
@@ -583,14 +583,15 @@ static irqreturn_t prq_event_thread(int irq, void *d)
|
|
* any faults on kernel addresses. */
|
|
if (!svm->mm)
|
|
goto bad_req;
|
|
- /* If the mm is already defunct, don't handle faults. */
|
|
- if (!mmget_not_zero(svm->mm))
|
|
- goto bad_req;
|
|
|
|
/* If address is not canonical, return invalid response */
|
|
if (!is_canonical_address(address))
|
|
goto bad_req;
|
|
|
|
+ /* If the mm is already defunct, don't handle faults. */
|
|
+ if (!mmget_not_zero(svm->mm))
|
|
+ goto bad_req;
|
|
+
|
|
down_read(&svm->mm->mmap_sem);
|
|
vma = find_extend_vma(svm->mm, address);
|
|
if (!vma || address < vma->vm_start)
|
|
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
|
|
index 3ea9d7682999..6c340a4f4fd2 100644
|
|
--- a/drivers/iommu/virtio-iommu.c
|
|
+++ b/drivers/iommu/virtio-iommu.c
|
|
@@ -614,18 +614,20 @@ static int viommu_domain_finalise(struct viommu_dev *viommu,
|
|
int ret;
|
|
struct viommu_domain *vdomain = to_viommu_domain(domain);
|
|
|
|
- vdomain->viommu = viommu;
|
|
- vdomain->map_flags = viommu->map_flags;
|
|
+ ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
|
|
+ viommu->last_domain, GFP_KERNEL);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ vdomain->id = (unsigned int)ret;
|
|
|
|
domain->pgsize_bitmap = viommu->pgsize_bitmap;
|
|
domain->geometry = viommu->geometry;
|
|
|
|
- ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
|
|
- viommu->last_domain, GFP_KERNEL);
|
|
- if (ret >= 0)
|
|
- vdomain->id = (unsigned int)ret;
|
|
+ vdomain->map_flags = viommu->map_flags;
|
|
+ vdomain->viommu = viommu;
|
|
|
|
- return ret > 0 ? 0 : ret;
|
|
+ return 0;
|
|
}
|
|
|
|
static void viommu_domain_free(struct iommu_domain *domain)
|
|
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
|
|
index 6b566bba263b..ff7627b57772 100644
|
|
--- a/drivers/irqchip/irq-mbigen.c
|
|
+++ b/drivers/irqchip/irq-mbigen.c
|
|
@@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
|
|
return 0;
|
|
}
|
|
|
|
+static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
|
|
+ unsigned int nr_irqs)
|
|
+{
|
|
+ platform_msi_domain_free(domain, virq, nr_irqs);
|
|
+}
|
|
+
|
|
static const struct irq_domain_ops mbigen_domain_ops = {
|
|
.translate = mbigen_domain_translate,
|
|
.alloc = mbigen_irq_domain_alloc,
|
|
- .free = irq_domain_free_irqs_common,
|
|
+ .free = mbigen_irq_domain_free,
|
|
};
|
|
|
|
static int mbigen_of_create_domain(struct platform_device *pdev,
|
|
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
|
|
index 647b1263c579..d3e83c33783e 100644
|
|
--- a/drivers/leds/led-class.c
|
|
+++ b/drivers/leds/led-class.c
|
|
@@ -281,7 +281,7 @@ int led_classdev_register_ext(struct device *parent,
|
|
|
|
if (ret)
|
|
dev_warn(parent, "Led %s renamed to %s due to name collision",
|
|
- led_cdev->name, dev_name(led_cdev->dev));
|
|
+ proposed_name, dev_name(led_cdev->dev));
|
|
|
|
if (led_cdev->flags & LED_BRIGHT_HW_CHANGED) {
|
|
ret = led_add_brightness_hw_changed(led_cdev);
|
|
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
|
|
index 931e5c2481b5..b50ec7ecd10c 100644
|
|
--- a/drivers/mtd/devices/phram.c
|
|
+++ b/drivers/mtd/devices/phram.c
|
|
@@ -243,22 +243,25 @@ static int phram_setup(const char *val)
|
|
|
|
ret = parse_num64(&start, token[1]);
|
|
if (ret) {
|
|
- kfree(name);
|
|
parse_err("illegal start address\n");
|
|
+ goto error;
|
|
}
|
|
|
|
ret = parse_num64(&len, token[2]);
|
|
if (ret) {
|
|
- kfree(name);
|
|
parse_err("illegal device length\n");
|
|
+ goto error;
|
|
}
|
|
|
|
ret = register_device(name, start, len);
|
|
- if (!ret)
|
|
- pr_info("%s device: %#llx at %#llx\n", name, len, start);
|
|
- else
|
|
- kfree(name);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ pr_info("%s device: %#llx at %#llx\n", name, len, start);
|
|
+ return 0;
|
|
|
|
+error:
|
|
+ kfree(name);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
|
|
index 1efc643c9871..9341a8a592e8 100644
|
|
--- a/drivers/mtd/lpddr/lpddr_cmds.c
|
|
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
|
|
@@ -68,7 +68,6 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
|
|
shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared),
|
|
GFP_KERNEL);
|
|
if (!shared) {
|
|
- kfree(lpddr);
|
|
kfree(mtd);
|
|
return NULL;
|
|
}
|
|
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
|
|
index f64e3b6605c6..47c63968fa45 100644
|
|
--- a/drivers/mtd/nand/raw/nand_base.c
|
|
+++ b/drivers/mtd/nand/raw/nand_base.c
|
|
@@ -5907,6 +5907,8 @@ void nand_cleanup(struct nand_chip *chip)
|
|
chip->ecc.algo == NAND_ECC_BCH)
|
|
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
|
|
|
|
+ nanddev_cleanup(&chip->base);
|
|
+
|
|
/* Free bad block table memory */
|
|
kfree(chip->bbt);
|
|
kfree(chip->data_buf);
|
|
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
|
|
index 5750c45019d8..8dda51bbdd11 100644
|
|
--- a/drivers/mtd/nand/spi/core.c
|
|
+++ b/drivers/mtd/nand/spi/core.c
|
|
@@ -609,6 +609,7 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos)
|
|
.ooboffs = 0,
|
|
.ooblen = sizeof(marker),
|
|
.oobbuf.out = marker,
|
|
+ .mode = MTD_OPS_RAW,
|
|
};
|
|
int ret;
|
|
|
|
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
|
|
index 471837cf0b21..e15d18bb981e 100644
|
|
--- a/drivers/net/dsa/bcm_sf2_cfp.c
|
|
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
|
|
@@ -882,17 +882,14 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
|
|
fs->m_ext.data[1]))
|
|
return -EINVAL;
|
|
|
|
- if (fs->location != RX_CLS_LOC_ANY && fs->location >= CFP_NUM_RULES)
|
|
+ if (fs->location != RX_CLS_LOC_ANY &&
|
|
+ fs->location > bcm_sf2_cfp_rule_size(priv))
|
|
return -EINVAL;
|
|
|
|
if (fs->location != RX_CLS_LOC_ANY &&
|
|
test_bit(fs->location, priv->cfp.used))
|
|
return -EBUSY;
|
|
|
|
- if (fs->location != RX_CLS_LOC_ANY &&
|
|
- fs->location > bcm_sf2_cfp_rule_size(priv))
|
|
- return -EINVAL;
|
|
-
|
|
ret = bcm_sf2_cfp_rule_cmp(priv, port, fs);
|
|
if (ret == 0)
|
|
return -EEXIST;
|
|
@@ -973,7 +970,7 @@ static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port, u32 loc)
|
|
struct cfp_rule *rule;
|
|
int ret;
|
|
|
|
- if (loc >= CFP_NUM_RULES)
|
|
+ if (loc > bcm_sf2_cfp_rule_size(priv))
|
|
return -EINVAL;
|
|
|
|
/* Refuse deleting unused rules, and those that are not unique since
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
index 304ddce6b087..39ee32518b10 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
@@ -1548,6 +1548,10 @@ static int mlx5e_set_fecparam(struct net_device *netdev,
|
|
int mode;
|
|
int err;
|
|
|
|
+ if (bitmap_weight((unsigned long *)&fecparam->fec,
|
|
+ ETHTOOL_FEC_BASER_BIT + 1) > 1)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
|
|
if (!(pplm_fec_2_ethtool[mode] & fecparam->fec))
|
|
continue;
|
|
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
|
|
index d47412dcdf38..5e5c6aafc070 100644
|
|
--- a/drivers/nvdimm/bus.c
|
|
+++ b/drivers/nvdimm/bus.c
|
|
@@ -1010,8 +1010,10 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
|
|
return -EFAULT;
|
|
}
|
|
|
|
- if (!desc || (desc->out_num + desc->in_num == 0) ||
|
|
- !test_bit(cmd, &cmd_mask))
|
|
+ if (!desc ||
|
|
+ (desc->out_num + desc->in_num == 0) ||
|
|
+ cmd > ND_CMD_CALL ||
|
|
+ !test_bit(cmd, &cmd_mask))
|
|
return -ENOTTY;
|
|
|
|
/* fail write commands (when read-only) */
|
|
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
|
|
index 9617b7df7c4d..1688f576ee8a 100644
|
|
--- a/drivers/of/overlay.c
|
|
+++ b/drivers/of/overlay.c
|
|
@@ -261,6 +261,8 @@ static struct property *dup_and_fixup_symbol_prop(
|
|
|
|
of_property_set_flag(new_prop, OF_DYNAMIC);
|
|
|
|
+ kfree(target_path);
|
|
+
|
|
return new_prop;
|
|
|
|
err_free_new_prop:
|
|
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
|
|
index ca7823eef2b4..5707c309a754 100644
|
|
--- a/drivers/of/unittest.c
|
|
+++ b/drivers/of/unittest.c
|
|
@@ -776,6 +776,10 @@ static void __init of_unittest_changeset(void)
|
|
unittest(!of_changeset_revert(&chgset), "revert failed\n");
|
|
|
|
of_changeset_destroy(&chgset);
|
|
+
|
|
+ of_node_put(n1);
|
|
+ of_node_put(n2);
|
|
+ of_node_put(n21);
|
|
#endif
|
|
}
|
|
|
|
@@ -1061,10 +1065,13 @@ static void __init of_unittest_platform_populate(void)
|
|
|
|
of_platform_populate(np, match, NULL, &test_bus->dev);
|
|
for_each_child_of_node(np, child) {
|
|
- for_each_child_of_node(child, grandchild)
|
|
- unittest(of_find_device_by_node(grandchild),
|
|
+ for_each_child_of_node(child, grandchild) {
|
|
+ pdev = of_find_device_by_node(grandchild);
|
|
+ unittest(pdev,
|
|
"Could not create device for node '%pOFn'\n",
|
|
grandchild);
|
|
+ of_dev_put(pdev);
|
|
+ }
|
|
}
|
|
|
|
of_platform_depopulate(&test_bus->dev);
|
|
@@ -2474,8 +2481,11 @@ static __init void of_unittest_overlay_high_level(void)
|
|
goto err_unlock;
|
|
}
|
|
if (__of_add_property(of_symbols, new_prop)) {
|
|
+ kfree(new_prop->name);
|
|
+ kfree(new_prop->value);
|
|
+ kfree(new_prop);
|
|
/* "name" auto-generated by unflatten */
|
|
- if (!strcmp(new_prop->name, "name"))
|
|
+ if (!strcmp(prop->name, "name"))
|
|
continue;
|
|
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
|
|
prop->name);
|
|
diff --git a/drivers/phy/socionext/phy-uniphier-usb3ss.c b/drivers/phy/socionext/phy-uniphier-usb3ss.c
|
|
index ec231e40ef2a..a7577e316baf 100644
|
|
--- a/drivers/phy/socionext/phy-uniphier-usb3ss.c
|
|
+++ b/drivers/phy/socionext/phy-uniphier-usb3ss.c
|
|
@@ -314,6 +314,10 @@ static const struct of_device_id uniphier_u3ssphy_match[] = {
|
|
.compatible = "socionext,uniphier-pro4-usb3-ssphy",
|
|
.data = &uniphier_pro4_data,
|
|
},
|
|
+ {
|
|
+ .compatible = "socionext,uniphier-pro5-usb3-ssphy",
|
|
+ .data = &uniphier_pro4_data,
|
|
+ },
|
|
{
|
|
.compatible = "socionext,uniphier-pxs2-usb3-ssphy",
|
|
.data = &uniphier_pxs2_data,
|
|
diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
|
|
index e1bc4e6e6f30..f40fa0e63b6e 100644
|
|
--- a/drivers/power/supply/axp288_fuel_gauge.c
|
|
+++ b/drivers/power/supply/axp288_fuel_gauge.c
|
|
@@ -706,14 +706,14 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = {
|
|
{
|
|
/* Intel Cherry Trail Compute Stick, Windows version */
|
|
.matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"),
|
|
},
|
|
},
|
|
{
|
|
/* Intel Cherry Trail Compute Stick, version without an OS */
|
|
.matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"),
|
|
},
|
|
},
|
|
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
|
|
index 195c18c2f426..664e50103eaa 100644
|
|
--- a/drivers/power/supply/bq27xxx_battery.c
|
|
+++ b/drivers/power/supply/bq27xxx_battery.c
|
|
@@ -1885,7 +1885,10 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
|
|
|
|
di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
|
|
if (IS_ERR(di->bat)) {
|
|
- dev_err(di->dev, "failed to register battery\n");
|
|
+ if (PTR_ERR(di->bat) == -EPROBE_DEFER)
|
|
+ dev_dbg(di->dev, "failed to register battery, deferring probe\n");
|
|
+ else
|
|
+ dev_err(di->dev, "failed to register battery\n");
|
|
return PTR_ERR(di->bat);
|
|
}
|
|
|
|
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
|
|
index 4743b16a8d84..1526402e126b 100644
|
|
--- a/drivers/rtc/rtc-88pm860x.c
|
|
+++ b/drivers/rtc/rtc-88pm860x.c
|
|
@@ -336,6 +336,10 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
|
|
info->dev = &pdev->dev;
|
|
dev_set_drvdata(&pdev->dev, info);
|
|
|
|
+ info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
|
+ if (IS_ERR(info->rtc_dev))
|
|
+ return PTR_ERR(info->rtc_dev);
|
|
+
|
|
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
|
|
rtc_update_handler, IRQF_ONESHOT, "rtc",
|
|
info);
|
|
@@ -377,13 +381,11 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
|
|
}
|
|
}
|
|
|
|
- info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm860x-rtc",
|
|
- &pm860x_rtc_ops, THIS_MODULE);
|
|
- ret = PTR_ERR(info->rtc_dev);
|
|
- if (IS_ERR(info->rtc_dev)) {
|
|
- dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
|
+ info->rtc_dev->ops = &pm860x_rtc_ops;
|
|
+
|
|
+ ret = rtc_register_device(info->rtc_dev);
|
|
+ if (ret)
|
|
return ret;
|
|
- }
|
|
|
|
/*
|
|
* enable internal XO instead of internal 3.25MHz clock since it can
|
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
|
index cce757506383..94af30f768f7 100644
|
|
--- a/drivers/scsi/sg.c
|
|
+++ b/drivers/scsi/sg.c
|
|
@@ -803,8 +803,10 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
|
|
"sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n",
|
|
(int) cmnd[0], (int) hp->cmd_len));
|
|
|
|
- if (hp->dxfer_len >= SZ_256M)
|
|
+ if (hp->dxfer_len >= SZ_256M) {
|
|
+ sg_remove_request(sfp, srp);
|
|
return -EINVAL;
|
|
+ }
|
|
|
|
k = sg_start_req(srp, cmnd);
|
|
if (k) {
|
|
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
|
|
index 98b9d9a902ae..90a8b2c0676f 100644
|
|
--- a/drivers/soc/imx/gpc.c
|
|
+++ b/drivers/soc/imx/gpc.c
|
|
@@ -87,8 +87,8 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
|
|
static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
|
|
{
|
|
struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
|
|
- int i, ret, sw, sw2iso;
|
|
- u32 val;
|
|
+ int i, ret;
|
|
+ u32 val, req;
|
|
|
|
if (pd->supply) {
|
|
ret = regulator_enable(pd->supply);
|
|
@@ -107,17 +107,18 @@ static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
|
|
regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
|
|
0x1, 0x1);
|
|
|
|
- /* Read ISO and ISO2SW power up delays */
|
|
- regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
|
|
- sw = val & 0x3f;
|
|
- sw2iso = (val >> 8) & 0x3f;
|
|
-
|
|
/* Request GPC to power up domain */
|
|
- val = BIT(pd->cntr_pdn_bit + 1);
|
|
- regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
|
|
+ req = BIT(pd->cntr_pdn_bit + 1);
|
|
+ regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
|
|
|
|
- /* Wait ISO + ISO2SW IPG clock cycles */
|
|
- udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));
|
|
+ /* Wait for the PGC to handle the request */
|
|
+ ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
|
|
+ 1, 50);
|
|
+ if (ret)
|
|
+ pr_err("powerup request on domain %s timed out\n", genpd->name);
|
|
+
|
|
+ /* Wait for reset to propagate through peripherals */
|
|
+ usleep_range(5, 10);
|
|
|
|
/* Disable reset clocks for all devices in the domain */
|
|
for (i = 0; i < pd->num_clks; i++)
|
|
@@ -343,6 +344,7 @@ static const struct regmap_config imx_gpc_regmap_config = {
|
|
.rd_table = &access_table,
|
|
.wr_table = &access_table,
|
|
.max_register = 0x2ac,
|
|
+ .fast_io = true,
|
|
};
|
|
|
|
static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
|
|
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
|
|
index 769e0a5d1dfc..3c6dd06ec5fb 100644
|
|
--- a/drivers/tty/ehv_bytechan.c
|
|
+++ b/drivers/tty/ehv_bytechan.c
|
|
@@ -136,6 +136,21 @@ static int find_console_handle(void)
|
|
return 1;
|
|
}
|
|
|
|
+static unsigned int local_ev_byte_channel_send(unsigned int handle,
|
|
+ unsigned int *count,
|
|
+ const char *p)
|
|
+{
|
|
+ char buffer[EV_BYTE_CHANNEL_MAX_BYTES];
|
|
+ unsigned int c = *count;
|
|
+
|
|
+ if (c < sizeof(buffer)) {
|
|
+ memcpy(buffer, p, c);
|
|
+ memset(&buffer[c], 0, sizeof(buffer) - c);
|
|
+ p = buffer;
|
|
+ }
|
|
+ return ev_byte_channel_send(handle, count, p);
|
|
+}
|
|
+
|
|
/*************************** EARLY CONSOLE DRIVER ***************************/
|
|
|
|
#ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC
|
|
@@ -154,7 +169,7 @@ static void byte_channel_spin_send(const char data)
|
|
|
|
do {
|
|
count = 1;
|
|
- ret = ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE,
|
|
+ ret = local_ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE,
|
|
&count, &data);
|
|
} while (ret == EV_EAGAIN);
|
|
}
|
|
@@ -221,7 +236,7 @@ static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s,
|
|
while (count) {
|
|
len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES);
|
|
do {
|
|
- ret = ev_byte_channel_send(handle, &len, s);
|
|
+ ret = local_ev_byte_channel_send(handle, &len, s);
|
|
} while (ret == EV_EAGAIN);
|
|
count -= len;
|
|
s += len;
|
|
@@ -401,7 +416,7 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)
|
|
CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE),
|
|
EV_BYTE_CHANNEL_MAX_BYTES);
|
|
|
|
- ret = ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail);
|
|
+ ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail);
|
|
|
|
/* 'len' is valid only if the return code is 0 or EV_EAGAIN */
|
|
if (!ret || (ret == EV_EAGAIN))
|
|
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
|
|
index e6a1c805064f..e72738371ecb 100644
|
|
--- a/drivers/video/fbdev/core/fbmem.c
|
|
+++ b/drivers/video/fbdev/core/fbmem.c
|
|
@@ -662,20 +662,20 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
|
|
fb_logo.depth = 1;
|
|
|
|
|
|
- if (fb_logo.depth > 4 && depth > 4) {
|
|
- switch (info->fix.visual) {
|
|
- case FB_VISUAL_TRUECOLOR:
|
|
- fb_logo.needs_truepalette = 1;
|
|
- break;
|
|
- case FB_VISUAL_DIRECTCOLOR:
|
|
- fb_logo.needs_directpalette = 1;
|
|
- fb_logo.needs_cmapreset = 1;
|
|
- break;
|
|
- case FB_VISUAL_PSEUDOCOLOR:
|
|
- fb_logo.needs_cmapreset = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
+ if (fb_logo.depth > 4 && depth > 4) {
|
|
+ switch (info->fix.visual) {
|
|
+ case FB_VISUAL_TRUECOLOR:
|
|
+ fb_logo.needs_truepalette = 1;
|
|
+ break;
|
|
+ case FB_VISUAL_DIRECTCOLOR:
|
|
+ fb_logo.needs_directpalette = 1;
|
|
+ fb_logo.needs_cmapreset = 1;
|
|
+ break;
|
|
+ case FB_VISUAL_PSEUDOCOLOR:
|
|
+ fb_logo.needs_cmapreset = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
|
|
height = fb_logo.logo->height;
|
|
if (fb_center_logo)
|
|
@@ -1060,19 +1060,19 @@ fb_blank(struct fb_info *info, int blank)
|
|
struct fb_event event;
|
|
int ret = -EINVAL;
|
|
|
|
- if (blank > FB_BLANK_POWERDOWN)
|
|
- blank = FB_BLANK_POWERDOWN;
|
|
+ if (blank > FB_BLANK_POWERDOWN)
|
|
+ blank = FB_BLANK_POWERDOWN;
|
|
|
|
event.info = info;
|
|
event.data = ␣
|
|
|
|
if (info->fbops->fb_blank)
|
|
- ret = info->fbops->fb_blank(blank, info);
|
|
+ ret = info->fbops->fb_blank(blank, info);
|
|
|
|
if (!ret)
|
|
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
|
|
|
- return ret;
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL(fb_blank);
|
|
|
|
@@ -1110,7 +1110,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|
break;
|
|
case FBIOGET_FSCREENINFO:
|
|
lock_fb_info(info);
|
|
- fix = info->fix;
|
|
+ memcpy(&fix, &info->fix, sizeof(fix));
|
|
if (info->flags & FBINFO_HIDE_SMEM_START)
|
|
fix.smem_start = 0;
|
|
unlock_fb_info(info);
|
|
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
|
|
index 53e04926a7b2..190d26e2e75f 100644
|
|
--- a/drivers/watchdog/sp805_wdt.c
|
|
+++ b/drivers/watchdog/sp805_wdt.c
|
|
@@ -137,10 +137,14 @@ wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
|
|
{
|
|
struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
|
|
|
|
+ writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
|
|
writel_relaxed(0, wdt->base + WDTCONTROL);
|
|
writel_relaxed(0, wdt->base + WDTLOAD);
|
|
writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
|
|
|
|
+ /* Flush posted writes. */
|
|
+ readl_relaxed(wdt->base + WDTLOCK);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
|
|
index 5c794f4b051a..d1e1caa23c8b 100644
|
|
--- a/fs/afs/dir.c
|
|
+++ b/fs/afs/dir.c
|
|
@@ -1032,7 +1032,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|
struct dentry *parent;
|
|
struct inode *inode;
|
|
struct key *key;
|
|
- afs_dataversion_t dir_version;
|
|
+ afs_dataversion_t dir_version, invalid_before;
|
|
long de_version;
|
|
int ret;
|
|
|
|
@@ -1084,8 +1084,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|
if (de_version == (long)dir_version)
|
|
goto out_valid_noupdate;
|
|
|
|
- dir_version = dir->invalid_before;
|
|
- if (de_version - (long)dir_version >= 0)
|
|
+ invalid_before = dir->invalid_before;
|
|
+ if (de_version - (long)invalid_before >= 0)
|
|
goto out_valid;
|
|
|
|
_debug("dir modified");
|
|
@@ -1275,6 +1275,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
struct afs_fs_cursor fc;
|
|
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
|
struct key *key;
|
|
+ afs_dataversion_t data_version;
|
|
int ret;
|
|
|
|
mode |= S_IFDIR;
|
|
@@ -1295,7 +1296,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
|
+ data_version = dvnode->status.data_version + 1;
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
|
@@ -1316,10 +1317,14 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
goto error_key;
|
|
}
|
|
|
|
- if (ret == 0 &&
|
|
- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
- afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
|
- afs_edit_dir_for_create);
|
|
+ if (ret == 0) {
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
+ afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
|
+ afs_edit_dir_for_create);
|
|
+ up_write(&dvnode->validate_lock);
|
|
+ }
|
|
|
|
key_put(key);
|
|
kfree(scb);
|
|
@@ -1360,6 +1365,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|
struct afs_fs_cursor fc;
|
|
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
|
|
struct key *key;
|
|
+ afs_dataversion_t data_version;
|
|
int ret;
|
|
|
|
_enter("{%llx:%llu},{%pd}",
|
|
@@ -1391,7 +1397,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
|
+ data_version = dvnode->status.data_version + 1;
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
|
@@ -1404,9 +1410,12 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|
ret = afs_end_vnode_operation(&fc);
|
|
if (ret == 0) {
|
|
afs_dir_remove_subdir(dentry);
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
|
afs_edit_dir_for_rmdir);
|
|
+ up_write(&dvnode->validate_lock);
|
|
}
|
|
}
|
|
|
|
@@ -1544,10 +1553,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
|
|
ret = afs_end_vnode_operation(&fc);
|
|
if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
|
|
ret = afs_dir_remove_link(dvnode, dentry, key);
|
|
- if (ret == 0 &&
|
|
- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
- afs_edit_dir_remove(dvnode, &dentry->d_name,
|
|
- afs_edit_dir_for_unlink);
|
|
+
|
|
+ if (ret == 0) {
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
+ afs_edit_dir_remove(dvnode, &dentry->d_name,
|
|
+ afs_edit_dir_for_unlink);
|
|
+ up_write(&dvnode->validate_lock);
|
|
+ }
|
|
}
|
|
|
|
if (need_rehash && ret < 0 && ret != -ENOENT)
|
|
@@ -1573,6 +1587,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|
struct afs_status_cb *scb;
|
|
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
|
struct key *key;
|
|
+ afs_dataversion_t data_version;
|
|
int ret;
|
|
|
|
mode |= S_IFREG;
|
|
@@ -1597,7 +1612,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
|
+ data_version = dvnode->status.data_version + 1;
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
|
@@ -1618,9 +1633,12 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|
goto error_key;
|
|
}
|
|
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
|
afs_edit_dir_for_create);
|
|
+ up_write(&dvnode->validate_lock);
|
|
|
|
kfree(scb);
|
|
key_put(key);
|
|
@@ -1648,6 +1666,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
|
struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
|
|
struct key *key;
|
|
+ afs_dataversion_t data_version;
|
|
int ret;
|
|
|
|
_enter("{%llx:%llu},{%llx:%llu},{%pd}",
|
|
@@ -1672,7 +1691,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
|
+ data_version = dvnode->status.data_version + 1;
|
|
|
|
if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
|
|
afs_end_vnode_operation(&fc);
|
|
@@ -1702,9 +1721,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|
goto error_key;
|
|
}
|
|
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
|
|
afs_edit_dir_for_link);
|
|
+ up_write(&dvnode->validate_lock);
|
|
|
|
key_put(key);
|
|
kfree(scb);
|
|
@@ -1732,6 +1754,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|
struct afs_status_cb *scb;
|
|
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
|
struct key *key;
|
|
+ afs_dataversion_t data_version;
|
|
int ret;
|
|
|
|
_enter("{%llx:%llu},{%pd},%s",
|
|
@@ -1759,7 +1782,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
|
+ data_version = dvnode->status.data_version + 1;
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
|
@@ -1780,9 +1803,12 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|
goto error_key;
|
|
}
|
|
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == data_version)
|
|
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
|
afs_edit_dir_for_symlink);
|
|
+ up_write(&dvnode->validate_lock);
|
|
|
|
key_put(key);
|
|
kfree(scb);
|
|
@@ -1812,6 +1838,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
struct dentry *tmp = NULL, *rehash = NULL;
|
|
struct inode *new_inode;
|
|
struct key *key;
|
|
+ afs_dataversion_t orig_data_version;
|
|
+ afs_dataversion_t new_data_version;
|
|
bool new_negative = d_is_negative(new_dentry);
|
|
int ret;
|
|
|
|
@@ -1890,10 +1918,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
|
|
ret = -ERESTARTSYS;
|
|
if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
|
|
- afs_dataversion_t orig_data_version;
|
|
- afs_dataversion_t new_data_version;
|
|
- struct afs_status_cb *new_scb = &scb[1];
|
|
-
|
|
orig_data_version = orig_dvnode->status.data_version + 1;
|
|
|
|
if (orig_dvnode != new_dvnode) {
|
|
@@ -1904,7 +1928,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
new_data_version = new_dvnode->status.data_version + 1;
|
|
} else {
|
|
new_data_version = orig_data_version;
|
|
- new_scb = &scb[0];
|
|
}
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
@@ -1912,7 +1935,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
|
|
afs_fs_rename(&fc, old_dentry->d_name.name,
|
|
new_dvnode, new_dentry->d_name.name,
|
|
- &scb[0], new_scb);
|
|
+ &scb[0], &scb[1]);
|
|
}
|
|
|
|
afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
|
|
@@ -1930,18 +1953,25 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
if (ret == 0) {
|
|
if (rehash)
|
|
d_rehash(rehash);
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
|
|
- afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
|
|
- afs_edit_dir_for_rename_0);
|
|
+ down_write(&orig_dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
|
|
+ orig_dvnode->status.data_version == orig_data_version)
|
|
+ afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
|
|
+ afs_edit_dir_for_rename_0);
|
|
+ if (orig_dvnode != new_dvnode) {
|
|
+ up_write(&orig_dvnode->validate_lock);
|
|
|
|
- if (!new_negative &&
|
|
- test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
|
|
- afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
|
|
- afs_edit_dir_for_rename_1);
|
|
+ down_write(&new_dvnode->validate_lock);
|
|
+ }
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
|
|
+ orig_dvnode->status.data_version == new_data_version) {
|
|
+ if (!new_negative)
|
|
+ afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
|
|
+ afs_edit_dir_for_rename_1);
|
|
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
|
|
afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
|
|
&vnode->fid, afs_edit_dir_for_rename_2);
|
|
+ }
|
|
|
|
new_inode = d_inode(new_dentry);
|
|
if (new_inode) {
|
|
@@ -1957,14 +1987,10 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
* Note that if we ever implement RENAME_EXCHANGE, we'll have
|
|
* to update both dentries with opposing dir versions.
|
|
*/
|
|
- if (new_dvnode != orig_dvnode) {
|
|
- afs_update_dentry_version(&fc, old_dentry, &scb[1]);
|
|
- afs_update_dentry_version(&fc, new_dentry, &scb[1]);
|
|
- } else {
|
|
- afs_update_dentry_version(&fc, old_dentry, &scb[0]);
|
|
- afs_update_dentry_version(&fc, new_dentry, &scb[0]);
|
|
- }
|
|
+ afs_update_dentry_version(&fc, old_dentry, &scb[1]);
|
|
+ afs_update_dentry_version(&fc, new_dentry, &scb[1]);
|
|
d_move(old_dentry, new_dentry);
|
|
+ up_write(&new_dvnode->validate_lock);
|
|
goto error_tmp;
|
|
}
|
|
|
|
diff --git a/fs/afs/dir_silly.c b/fs/afs/dir_silly.c
|
|
index 361088a5edb9..d94e2b7cddff 100644
|
|
--- a/fs/afs/dir_silly.c
|
|
+++ b/fs/afs/dir_silly.c
|
|
@@ -21,6 +21,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|
{
|
|
struct afs_fs_cursor fc;
|
|
struct afs_status_cb *scb;
|
|
+ afs_dataversion_t dir_data_version;
|
|
int ret = -ERESTARTSYS;
|
|
|
|
_enter("%pd,%pd", old, new);
|
|
@@ -31,7 +32,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|
|
|
trace_afs_silly_rename(vnode, false);
|
|
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
|
- afs_dataversion_t dir_data_version = dvnode->status.data_version + 1;
|
|
+ dir_data_version = dvnode->status.data_version + 1;
|
|
|
|
while (afs_select_fileserver(&fc)) {
|
|
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
|
@@ -54,12 +55,15 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|
dvnode->silly_key = key_get(key);
|
|
}
|
|
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == dir_data_version) {
|
|
afs_edit_dir_remove(dvnode, &old->d_name,
|
|
afs_edit_dir_for_silly_0);
|
|
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
afs_edit_dir_add(dvnode, &new->d_name,
|
|
&vnode->fid, afs_edit_dir_for_silly_1);
|
|
+ }
|
|
+ up_write(&dvnode->validate_lock);
|
|
}
|
|
|
|
kfree(scb);
|
|
@@ -181,10 +185,14 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
|
}
|
|
}
|
|
- if (ret == 0 &&
|
|
- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
|
- afs_edit_dir_remove(dvnode, &dentry->d_name,
|
|
- afs_edit_dir_for_unlink);
|
|
+ if (ret == 0) {
|
|
+ down_write(&dvnode->validate_lock);
|
|
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
|
+ dvnode->status.data_version == dir_data_version)
|
|
+ afs_edit_dir_remove(dvnode, &dentry->d_name,
|
|
+ afs_edit_dir_for_unlink);
|
|
+ up_write(&dvnode->validate_lock);
|
|
+ }
|
|
}
|
|
|
|
kfree(scb);
|
|
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
|
|
index 6f84231f11a5..6805a469d13c 100644
|
|
--- a/fs/afs/fsclient.c
|
|
+++ b/fs/afs/fsclient.c
|
|
@@ -65,6 +65,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|
bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
|
|
u64 data_version, size;
|
|
u32 type, abort_code;
|
|
+ int ret;
|
|
|
|
abort_code = ntohl(xdr->abort_code);
|
|
|
|
@@ -78,7 +79,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|
*/
|
|
status->abort_code = abort_code;
|
|
scb->have_error = true;
|
|
- return 0;
|
|
+ goto good;
|
|
}
|
|
|
|
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
|
|
@@ -87,7 +88,8 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|
|
|
if (abort_code != 0 && inline_error) {
|
|
status->abort_code = abort_code;
|
|
- return 0;
|
|
+ scb->have_error = true;
|
|
+ goto good;
|
|
}
|
|
|
|
type = ntohl(xdr->type);
|
|
@@ -123,13 +125,16 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|
data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
|
|
status->data_version = data_version;
|
|
scb->have_status = true;
|
|
-
|
|
+good:
|
|
+ ret = 0;
|
|
+advance:
|
|
*_bp = (const void *)*_bp + sizeof(*xdr);
|
|
- return 0;
|
|
+ return ret;
|
|
|
|
bad:
|
|
xdr_dump_bad(*_bp);
|
|
- return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
|
+ ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
|
+ goto advance;
|
|
}
|
|
|
|
static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
|
|
@@ -983,16 +988,16 @@ static int afs_deliver_fs_rename(struct afs_call *call)
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- /* unmarshall the reply once we've received all of it */
|
|
+ /* If the two dirs are the same, we have two copies of the same status
|
|
+ * report, so we just decode it twice.
|
|
+ */
|
|
bp = call->buffer;
|
|
ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
|
|
if (ret < 0)
|
|
return ret;
|
|
- if (call->out_dir_scb != call->out_scb) {
|
|
- ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- }
|
|
+ ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
xdr_decode_AFSVolSync(&bp, call->out_volsync);
|
|
|
|
_leave(" = 0 [done]");
|
|
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
|
|
index 3ee7abf4b2d0..31b236c6b1f7 100644
|
|
--- a/fs/afs/yfsclient.c
|
|
+++ b/fs/afs/yfsclient.c
|
|
@@ -186,13 +186,14 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
|
|
const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
|
|
struct afs_file_status *status = &scb->status;
|
|
u32 type;
|
|
+ int ret;
|
|
|
|
status->abort_code = ntohl(xdr->abort_code);
|
|
if (status->abort_code != 0) {
|
|
if (status->abort_code == VNOVNODE)
|
|
status->nlink = 0;
|
|
scb->have_error = true;
|
|
- return 0;
|
|
+ goto good;
|
|
}
|
|
|
|
type = ntohl(xdr->type);
|
|
@@ -220,13 +221,16 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
|
|
status->size = xdr_to_u64(xdr->size);
|
|
status->data_version = xdr_to_u64(xdr->data_version);
|
|
scb->have_status = true;
|
|
-
|
|
+good:
|
|
+ ret = 0;
|
|
+advance:
|
|
*_bp += xdr_size(xdr);
|
|
- return 0;
|
|
+ return ret;
|
|
|
|
bad:
|
|
xdr_dump_bad(*_bp);
|
|
- return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
|
+ ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
|
+ goto advance;
|
|
}
|
|
|
|
/*
|
|
@@ -1154,11 +1158,9 @@ static int yfs_deliver_fs_rename(struct afs_call *call)
|
|
ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
|
|
if (ret < 0)
|
|
return ret;
|
|
- if (call->out_dir_scb != call->out_scb) {
|
|
- ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- }
|
|
+ ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
xdr_decode_YFSVolSync(&bp, call->out_volsync);
|
|
_leave(" = 0 [done]");
|
|
diff --git a/fs/block_dev.c b/fs/block_dev.c
|
|
index d612468ee66b..34644ce4b502 100644
|
|
--- a/fs/block_dev.c
|
|
+++ b/fs/block_dev.c
|
|
@@ -34,6 +34,7 @@
|
|
#include <linux/task_io_accounting_ops.h>
|
|
#include <linux/falloc.h>
|
|
#include <linux/uaccess.h>
|
|
+#include <linux/suspend.h>
|
|
#include "internal.h"
|
|
|
|
struct bdev_inode {
|
|
@@ -1975,7 +1976,8 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|
if (bdev_read_only(I_BDEV(bd_inode)))
|
|
return -EPERM;
|
|
|
|
- if (IS_SWAPFILE(bd_inode))
|
|
+ /* uswsusp needs write permission to the swap */
|
|
+ if (IS_SWAPFILE(bd_inode) && !hibernation_available())
|
|
return -ETXTBSY;
|
|
|
|
if (!iov_iter_count(from))
|
|
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
|
|
index 7dcfa7d7632a..95330f40f998 100644
|
|
--- a/fs/btrfs/block-group.c
|
|
+++ b/fs/btrfs/block-group.c
|
|
@@ -1829,6 +1829,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
|
|
}
|
|
}
|
|
|
|
+ rcu_read_lock();
|
|
list_for_each_entry_rcu(space_info, &info->space_info, list) {
|
|
if (!(btrfs_get_alloc_profile(info, space_info->flags) &
|
|
(BTRFS_BLOCK_GROUP_RAID10 |
|
|
@@ -1849,6 +1850,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
|
|
list)
|
|
inc_block_group_ro(cache, 1);
|
|
}
|
|
+ rcu_read_unlock();
|
|
|
|
btrfs_init_global_block_rsv(info);
|
|
ret = check_chunk_block_group_mappings(info);
|
|
diff --git a/fs/buffer.c b/fs/buffer.c
|
|
index 91ceca52d14f..79c9562434a8 100644
|
|
--- a/fs/buffer.c
|
|
+++ b/fs/buffer.c
|
|
@@ -1337,6 +1337,17 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
|
|
}
|
|
EXPORT_SYMBOL(__breadahead);
|
|
|
|
+void __breadahead_gfp(struct block_device *bdev, sector_t block, unsigned size,
|
|
+ gfp_t gfp)
|
|
+{
|
|
+ struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
|
|
+ if (likely(bh)) {
|
|
+ ll_rw_block(REQ_OP_READ, REQ_RAHEAD, 1, &bh);
|
|
+ brelse(bh);
|
|
+ }
|
|
+}
|
|
+EXPORT_SYMBOL(__breadahead_gfp);
|
|
+
|
|
/**
|
|
* __bread_gfp() - reads a specified block and returns the bh
|
|
* @bdev: the block_device to read from
|
|
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
|
|
index e67a43fd037c..fe1552cc8a0a 100644
|
|
--- a/fs/cifs/transport.c
|
|
+++ b/fs/cifs/transport.c
|
|
@@ -466,7 +466,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
|
struct smb_rqst *rqst, int flags)
|
|
{
|
|
struct kvec iov;
|
|
- struct smb2_transform_hdr tr_hdr;
|
|
+ struct smb2_transform_hdr *tr_hdr;
|
|
struct smb_rqst cur_rqst[MAX_COMPOUND];
|
|
int rc;
|
|
|
|
@@ -476,28 +476,34 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
|
if (num_rqst > MAX_COMPOUND - 1)
|
|
return -ENOMEM;
|
|
|
|
- memset(&cur_rqst[0], 0, sizeof(cur_rqst));
|
|
- memset(&iov, 0, sizeof(iov));
|
|
- memset(&tr_hdr, 0, sizeof(tr_hdr));
|
|
-
|
|
- iov.iov_base = &tr_hdr;
|
|
- iov.iov_len = sizeof(tr_hdr);
|
|
- cur_rqst[0].rq_iov = &iov;
|
|
- cur_rqst[0].rq_nvec = 1;
|
|
-
|
|
if (!server->ops->init_transform_rq) {
|
|
cifs_server_dbg(VFS, "Encryption requested but transform "
|
|
"callback is missing\n");
|
|
return -EIO;
|
|
}
|
|
|
|
+ tr_hdr = kmalloc(sizeof(*tr_hdr), GFP_NOFS);
|
|
+ if (!tr_hdr)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ memset(&cur_rqst[0], 0, sizeof(cur_rqst));
|
|
+ memset(&iov, 0, sizeof(iov));
|
|
+ memset(tr_hdr, 0, sizeof(*tr_hdr));
|
|
+
|
|
+ iov.iov_base = tr_hdr;
|
|
+ iov.iov_len = sizeof(*tr_hdr);
|
|
+ cur_rqst[0].rq_iov = &iov;
|
|
+ cur_rqst[0].rq_nvec = 1;
|
|
+
|
|
rc = server->ops->init_transform_rq(server, num_rqst + 1,
|
|
&cur_rqst[0], rqst);
|
|
if (rc)
|
|
- return rc;
|
|
+ goto out;
|
|
|
|
rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
|
|
smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
|
|
+out:
|
|
+ kfree(tr_hdr);
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
|
|
index 0456bc990b5e..62acbe27d8bf 100644
|
|
--- a/fs/ext2/xattr.c
|
|
+++ b/fs/ext2/xattr.c
|
|
@@ -56,6 +56,7 @@
|
|
|
|
#include <linux/buffer_head.h>
|
|
#include <linux/init.h>
|
|
+#include <linux/printk.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/mbcache.h>
|
|
#include <linux/quotaops.h>
|
|
@@ -84,8 +85,8 @@
|
|
printk("\n"); \
|
|
} while (0)
|
|
#else
|
|
-# define ea_idebug(f...)
|
|
-# define ea_bdebug(f...)
|
|
+# define ea_idebug(inode, f...) no_printk(f)
|
|
+# define ea_bdebug(bh, f...) no_printk(f)
|
|
#endif
|
|
|
|
static int ext2_xattr_set2(struct inode *, struct buffer_head *,
|
|
@@ -864,8 +865,7 @@ ext2_xattr_cache_insert(struct mb_cache *cache, struct buffer_head *bh)
|
|
true);
|
|
if (error) {
|
|
if (error == -EBUSY) {
|
|
- ea_bdebug(bh, "already in cache (%d cache entries)",
|
|
- atomic_read(&ext2_xattr_cache->c_entry_count));
|
|
+ ea_bdebug(bh, "already in cache");
|
|
error = 0;
|
|
}
|
|
} else
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index d2edd6e9072f..b9473fcc110f 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -4680,7 +4680,7 @@ make_io:
|
|
if (end > table)
|
|
end = table;
|
|
while (b <= end)
|
|
- sb_breadahead(sb, b++);
|
|
+ sb_breadahead_unmovable(sb, b++);
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index a1eca6d30643..53d4c67a20df 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -389,7 +389,8 @@ static void save_error_info(struct super_block *sb, const char *func,
|
|
unsigned int line)
|
|
{
|
|
__save_error_info(sb, func, line);
|
|
- ext4_commit_super(sb, 1);
|
|
+ if (!bdev_read_only(sb->s_bdev))
|
|
+ ext4_commit_super(sb, 1);
|
|
}
|
|
|
|
/*
|
|
@@ -4283,7 +4284,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
/* Pre-read the descriptors into the buffer cache */
|
|
for (i = 0; i < db_count; i++) {
|
|
block = descriptor_loc(sb, logical_sb_block, i);
|
|
- sb_breadahead(sb, block);
|
|
+ sb_breadahead_unmovable(sb, block);
|
|
}
|
|
|
|
for (i = 0; i < db_count; i++) {
|
|
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
|
|
index a0eef95b9e0e..a28ffecc0f95 100644
|
|
--- a/fs/f2fs/checkpoint.c
|
|
+++ b/fs/f2fs/checkpoint.c
|
|
@@ -1250,20 +1250,20 @@ static void unblock_operations(struct f2fs_sb_info *sbi)
|
|
f2fs_unlock_all(sbi);
|
|
}
|
|
|
|
-void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
|
|
+void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type)
|
|
{
|
|
DEFINE_WAIT(wait);
|
|
|
|
for (;;) {
|
|
prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
|
|
|
|
- if (!get_pages(sbi, F2FS_WB_CP_DATA))
|
|
+ if (!get_pages(sbi, type))
|
|
break;
|
|
|
|
if (unlikely(f2fs_cp_error(sbi)))
|
|
break;
|
|
|
|
- io_schedule_timeout(5*HZ);
|
|
+ io_schedule_timeout(HZ/50);
|
|
}
|
|
finish_wait(&sbi->cp_wait, &wait);
|
|
}
|
|
@@ -1301,10 +1301,14 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|
else
|
|
__clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
|
|
|
|
- if (is_sbi_flag_set(sbi, SBI_NEED_FSCK) ||
|
|
- is_sbi_flag_set(sbi, SBI_IS_RESIZEFS))
|
|
+ if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
|
|
__set_ckpt_flags(ckpt, CP_FSCK_FLAG);
|
|
|
|
+ if (is_sbi_flag_set(sbi, SBI_IS_RESIZEFS))
|
|
+ __set_ckpt_flags(ckpt, CP_RESIZEFS_FLAG);
|
|
+ else
|
|
+ __clear_ckpt_flags(ckpt, CP_RESIZEFS_FLAG);
|
|
+
|
|
if (is_sbi_flag_set(sbi, SBI_CP_DISABLED))
|
|
__set_ckpt_flags(ckpt, CP_DISABLED_FLAG);
|
|
else
|
|
@@ -1384,8 +1388,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|
|
|
/* Flush all the NAT/SIT pages */
|
|
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
|
|
- f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_META) &&
|
|
- !f2fs_cp_error(sbi));
|
|
|
|
/*
|
|
* modify checkpoint
|
|
@@ -1493,11 +1495,11 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|
|
|
/* Here, we have one bio having CP pack except cp pack 2 page */
|
|
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
|
|
- f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_META) &&
|
|
- !f2fs_cp_error(sbi));
|
|
+ /* Wait for all dirty meta pages to be submitted for IO */
|
|
+ f2fs_wait_on_all_pages(sbi, F2FS_DIRTY_META);
|
|
|
|
/* wait for previous submitted meta pages writeback */
|
|
- f2fs_wait_on_all_pages_writeback(sbi);
|
|
+ f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
|
|
|
|
/* flush all device cache */
|
|
err = f2fs_flush_device_cache(sbi);
|
|
@@ -1506,7 +1508,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|
|
|
/* barrier and flush checkpoint cp pack 2 page if it can */
|
|
commit_checkpoint(sbi, ckpt, start_blk);
|
|
- f2fs_wait_on_all_pages_writeback(sbi);
|
|
+ f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
|
|
|
|
/*
|
|
* invalidate intermediate page cache borrowed from meta inode
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 9046432b87c2..3edde3d6d089 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -100,6 +100,7 @@ extern const char *f2fs_fault_name[FAULT_MAX];
|
|
#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000
|
|
#define F2FS_MOUNT_RESERVE_ROOT 0x01000000
|
|
#define F2FS_MOUNT_DISABLE_CHECKPOINT 0x02000000
|
|
+#define F2FS_MOUNT_NORECOVERY 0x04000000
|
|
|
|
#define F2FS_OPTION(sbi) ((sbi)->mount_opt)
|
|
#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option)
|
|
@@ -3185,7 +3186,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi);
|
|
void f2fs_update_dirty_page(struct inode *inode, struct page *page);
|
|
void f2fs_remove_dirty_inode(struct inode *inode);
|
|
int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type);
|
|
-void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi);
|
|
+void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type);
|
|
int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc);
|
|
void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi);
|
|
int __init f2fs_create_checkpoint_caches(void);
|
|
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
|
|
index 5877bd729689..e611d768efde 100644
|
|
--- a/fs/f2fs/gc.c
|
|
+++ b/fs/f2fs/gc.c
|
|
@@ -1532,11 +1532,17 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)
|
|
goto out;
|
|
}
|
|
|
|
+ mutex_lock(&sbi->cp_mutex);
|
|
update_fs_metadata(sbi, -secs);
|
|
clear_sbi_flag(sbi, SBI_IS_RESIZEFS);
|
|
+ set_sbi_flag(sbi, SBI_IS_DIRTY);
|
|
+ mutex_unlock(&sbi->cp_mutex);
|
|
+
|
|
err = f2fs_sync_fs(sbi->sb, 1);
|
|
if (err) {
|
|
+ mutex_lock(&sbi->cp_mutex);
|
|
update_fs_metadata(sbi, secs);
|
|
+ mutex_unlock(&sbi->cp_mutex);
|
|
update_sb_metadata(sbi, secs);
|
|
f2fs_commit_super(sbi, false);
|
|
}
|
|
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
|
|
index 8b66bc4c004b..f14401a77d60 100644
|
|
--- a/fs/f2fs/node.c
|
|
+++ b/fs/f2fs/node.c
|
|
@@ -1562,15 +1562,16 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
|
|
if (atomic && !test_opt(sbi, NOBARRIER))
|
|
fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
|
|
|
|
- set_page_writeback(page);
|
|
- ClearPageError(page);
|
|
-
|
|
+ /* should add to global list before clearing PAGECACHE status */
|
|
if (f2fs_in_warm_node_list(sbi, page)) {
|
|
seq = f2fs_add_fsync_node_entry(sbi, page);
|
|
if (seq_id)
|
|
*seq_id = seq;
|
|
}
|
|
|
|
+ set_page_writeback(page);
|
|
+ ClearPageError(page);
|
|
+
|
|
fio.old_blkaddr = ni.blk_addr;
|
|
f2fs_do_write_node_page(nid, &fio);
|
|
set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
|
|
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
|
|
index ea8dbf1458c9..5e1d4d9243a9 100644
|
|
--- a/fs/f2fs/super.c
|
|
+++ b/fs/f2fs/super.c
|
|
@@ -439,7 +439,7 @@ static int parse_options(struct super_block *sb, char *options)
|
|
break;
|
|
case Opt_norecovery:
|
|
/* this option mounts f2fs with ro */
|
|
- set_opt(sbi, DISABLE_ROLL_FORWARD);
|
|
+ set_opt(sbi, NORECOVERY);
|
|
if (!f2fs_readonly(sb))
|
|
return -EINVAL;
|
|
break;
|
|
@@ -1105,7 +1105,7 @@ static void f2fs_put_super(struct super_block *sb)
|
|
/* our cp_error case, we can wait for any writeback page */
|
|
f2fs_flush_merged_writes(sbi);
|
|
|
|
- f2fs_wait_on_all_pages_writeback(sbi);
|
|
+ f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
|
|
|
|
f2fs_bug_on(sbi, sbi->fsync_node_num);
|
|
|
|
@@ -1348,6 +1348,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
|
}
|
|
if (test_opt(sbi, DISABLE_ROLL_FORWARD))
|
|
seq_puts(seq, ",disable_roll_forward");
|
|
+ if (test_opt(sbi, NORECOVERY))
|
|
+ seq_puts(seq, ",norecovery");
|
|
if (test_opt(sbi, DISCARD))
|
|
seq_puts(seq, ",discard");
|
|
else
|
|
@@ -1824,6 +1826,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
|
|
int offset = off & (sb->s_blocksize - 1);
|
|
size_t towrite = len;
|
|
struct page *page;
|
|
+ void *fsdata = NULL;
|
|
char *kaddr;
|
|
int err = 0;
|
|
int tocopy;
|
|
@@ -1833,7 +1836,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
|
|
towrite);
|
|
retry:
|
|
err = a_ops->write_begin(NULL, mapping, off, tocopy, 0,
|
|
- &page, NULL);
|
|
+ &page, &fsdata);
|
|
if (unlikely(err)) {
|
|
if (err == -ENOMEM) {
|
|
congestion_wait(BLK_RW_ASYNC, HZ/50);
|
|
@@ -1849,7 +1852,7 @@ retry:
|
|
flush_dcache_page(page);
|
|
|
|
a_ops->write_end(NULL, mapping, off, tocopy, tocopy,
|
|
- page, NULL);
|
|
+ page, fsdata);
|
|
offset = 0;
|
|
towrite -= tocopy;
|
|
off += tocopy;
|
|
@@ -3488,7 +3491,8 @@ try_onemore:
|
|
goto reset_checkpoint;
|
|
|
|
/* recover fsynced data */
|
|
- if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
|
|
+ if (!test_opt(sbi, DISABLE_ROLL_FORWARD) &&
|
|
+ !test_opt(sbi, NORECOVERY)) {
|
|
/*
|
|
* mount should be failed, when device has readonly mode, and
|
|
* previous checkpoint was not done by clean system shutdown.
|
|
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
|
|
index f39924ba050b..fc775b0b5194 100644
|
|
--- a/fs/nfs/callback_proc.c
|
|
+++ b/fs/nfs/callback_proc.c
|
|
@@ -130,6 +130,8 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
|
|
|
|
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
|
|
list_for_each_entry(lo, &server->layouts, plh_layouts) {
|
|
+ if (!pnfs_layout_is_valid(lo))
|
|
+ continue;
|
|
if (stateid != NULL &&
|
|
!nfs4_stateid_match_other(stateid, &lo->plh_stateid))
|
|
continue;
|
|
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
|
|
index 29f00da8a0b7..6b0bf4ebd812 100644
|
|
--- a/fs/nfs/direct.c
|
|
+++ b/fs/nfs/direct.c
|
|
@@ -571,6 +571,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
|
|
l_ctx = nfs_get_lock_context(dreq->ctx);
|
|
if (IS_ERR(l_ctx)) {
|
|
result = PTR_ERR(l_ctx);
|
|
+ nfs_direct_req_release(dreq);
|
|
goto out_release;
|
|
}
|
|
dreq->l_ctx = l_ctx;
|
|
@@ -989,6 +990,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
|
|
l_ctx = nfs_get_lock_context(dreq->ctx);
|
|
if (IS_ERR(l_ctx)) {
|
|
result = PTR_ERR(l_ctx);
|
|
+ nfs_direct_req_release(dreq);
|
|
goto out_release;
|
|
}
|
|
dreq->l_ctx = l_ctx;
|
|
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
|
|
index 2a03bfeec10a..3802c88e8372 100644
|
|
--- a/fs/nfs/inode.c
|
|
+++ b/fs/nfs/inode.c
|
|
@@ -959,16 +959,16 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
|
|
struct file *filp)
|
|
{
|
|
struct nfs_open_context *ctx;
|
|
- const struct cred *cred = get_current_cred();
|
|
|
|
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
|
- if (!ctx) {
|
|
- put_cred(cred);
|
|
+ if (!ctx)
|
|
return ERR_PTR(-ENOMEM);
|
|
- }
|
|
nfs_sb_active(dentry->d_sb);
|
|
ctx->dentry = dget(dentry);
|
|
- ctx->cred = cred;
|
|
+ if (filp)
|
|
+ ctx->cred = get_cred(filp->f_cred);
|
|
+ else
|
|
+ ctx->cred = get_current_cred();
|
|
ctx->ll_cred = NULL;
|
|
ctx->state = NULL;
|
|
ctx->mode = f_mode;
|
|
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
|
|
index 54f1c1f626fc..fb55c04cdc6b 100644
|
|
--- a/fs/nfs/nfs4file.c
|
|
+++ b/fs/nfs/nfs4file.c
|
|
@@ -210,6 +210,9 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
|
|
if (remap_flags & ~REMAP_FILE_ADVISORY)
|
|
return -EINVAL;
|
|
|
|
+ if (IS_SWAPFILE(dst_inode) || IS_SWAPFILE(src_inode))
|
|
+ return -ETXTBSY;
|
|
+
|
|
/* check alignment w.r.t. clone_blksize */
|
|
ret = -EINVAL;
|
|
if (bs) {
|
|
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
|
|
index 8b7c525dbbf7..b736912098ee 100644
|
|
--- a/fs/nfs/pagelist.c
|
|
+++ b/fs/nfs/pagelist.c
|
|
@@ -886,15 +886,6 @@ static void nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio,
|
|
pgio->pg_mirror_count = mirror_count;
|
|
}
|
|
|
|
-/*
|
|
- * nfs_pageio_stop_mirroring - stop using mirroring (set mirror count to 1)
|
|
- */
|
|
-void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio)
|
|
-{
|
|
- pgio->pg_mirror_count = 1;
|
|
- pgio->pg_mirror_idx = 0;
|
|
-}
|
|
-
|
|
static void nfs_pageio_cleanup_mirroring(struct nfs_pageio_descriptor *pgio)
|
|
{
|
|
pgio->pg_mirror_count = 1;
|
|
@@ -1320,6 +1311,14 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+ * nfs_pageio_stop_mirroring - stop using mirroring (set mirror count to 1)
|
|
+ */
|
|
+void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio)
|
|
+{
|
|
+ nfs_pageio_complete(pgio);
|
|
+}
|
|
+
|
|
int __init nfs_init_nfspagecache(void)
|
|
{
|
|
nfs_page_cachep = kmem_cache_create("nfs_page",
|
|
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
|
|
index 47805172e73d..683e124ad517 100644
|
|
--- a/include/acpi/processor.h
|
|
+++ b/include/acpi/processor.h
|
|
@@ -297,6 +297,14 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
|
|
}
|
|
#endif
|
|
|
|
+static inline int call_on_cpu(int cpu, long (*fn)(void *), void *arg,
|
|
+ bool direct)
|
|
+{
|
|
+ if (direct || (is_percpu_thread() && cpu == smp_processor_id()))
|
|
+ return fn(arg);
|
|
+ return work_on_cpu(cpu, fn, arg);
|
|
+}
|
|
+
|
|
/* in processor_perflib.c */
|
|
|
|
#ifdef CONFIG_CPU_FREQ
|
|
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
|
|
index 18d8e2d8210f..53759d2b9c26 100644
|
|
--- a/include/asm-generic/mshyperv.h
|
|
+++ b/include/asm-generic/mshyperv.h
|
|
@@ -163,7 +163,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
|
|
return nr_bank;
|
|
}
|
|
|
|
-void hyperv_report_panic(struct pt_regs *regs, long err);
|
|
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
|
|
void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
|
|
bool hv_is_hyperv_initialized(void);
|
|
void hyperv_cleanup(void);
|
|
diff --git a/include/keys/big_key-type.h b/include/keys/big_key-type.h
|
|
index f6a7ba4dccd4..3fee04f81439 100644
|
|
--- a/include/keys/big_key-type.h
|
|
+++ b/include/keys/big_key-type.h
|
|
@@ -17,6 +17,6 @@ extern void big_key_free_preparse(struct key_preparsed_payload *prep);
|
|
extern void big_key_revoke(struct key *key);
|
|
extern void big_key_destroy(struct key *key);
|
|
extern void big_key_describe(const struct key *big_key, struct seq_file *m);
|
|
-extern long big_key_read(const struct key *key, char __user *buffer, size_t buflen);
|
|
+extern long big_key_read(const struct key *key, char *buffer, size_t buflen);
|
|
|
|
#endif /* _KEYS_BIG_KEY_TYPE_H */
|
|
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
|
|
index d5e73266a81a..be61fcddc02a 100644
|
|
--- a/include/keys/user-type.h
|
|
+++ b/include/keys/user-type.h
|
|
@@ -41,8 +41,7 @@ extern int user_update(struct key *key, struct key_preparsed_payload *prep);
|
|
extern void user_revoke(struct key *key);
|
|
extern void user_destroy(struct key *key);
|
|
extern void user_describe(const struct key *user, struct seq_file *m);
|
|
-extern long user_read(const struct key *key,
|
|
- char __user *buffer, size_t buflen);
|
|
+extern long user_read(const struct key *key, char *buffer, size_t buflen);
|
|
|
|
static inline const struct user_key_payload *user_key_payload_rcu(const struct key *key)
|
|
{
|
|
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
|
|
index 7b73ef7f902d..b56cc825f64d 100644
|
|
--- a/include/linux/buffer_head.h
|
|
+++ b/include/linux/buffer_head.h
|
|
@@ -189,6 +189,8 @@ struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
|
|
void __brelse(struct buffer_head *);
|
|
void __bforget(struct buffer_head *);
|
|
void __breadahead(struct block_device *, sector_t block, unsigned int size);
|
|
+void __breadahead_gfp(struct block_device *, sector_t block, unsigned int size,
|
|
+ gfp_t gfp);
|
|
struct buffer_head *__bread_gfp(struct block_device *,
|
|
sector_t block, unsigned size, gfp_t gfp);
|
|
void invalidate_bh_lrus(void);
|
|
@@ -319,6 +321,12 @@ sb_breadahead(struct super_block *sb, sector_t block)
|
|
__breadahead(sb->s_bdev, block, sb->s_blocksize);
|
|
}
|
|
|
|
+static inline void
|
|
+sb_breadahead_unmovable(struct super_block *sb, sector_t block)
|
|
+{
|
|
+ __breadahead_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
|
|
+}
|
|
+
|
|
static inline struct buffer_head *
|
|
sb_getblk(struct super_block *sb, sector_t block)
|
|
{
|
|
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
|
|
index 5e88e7e33abe..034b0a644efc 100644
|
|
--- a/include/linux/compiler.h
|
|
+++ b/include/linux/compiler.h
|
|
@@ -347,7 +347,7 @@ static inline void *offset_to_ptr(const int *off)
|
|
* compiler has support to do so.
|
|
*/
|
|
#define compiletime_assert(condition, msg) \
|
|
- _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
|
|
+ _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
|
|
|
|
#define compiletime_assert_atomic_type(t) \
|
|
compiletime_assert(__native_word(t), \
|
|
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
|
|
index 284738996028..6bb6f718a102 100644
|
|
--- a/include/linux/f2fs_fs.h
|
|
+++ b/include/linux/f2fs_fs.h
|
|
@@ -124,6 +124,7 @@ struct f2fs_super_block {
|
|
/*
|
|
* For checkpoint
|
|
*/
|
|
+#define CP_RESIZEFS_FLAG 0x00004000
|
|
#define CP_DISABLED_QUICK_FLAG 0x00002000
|
|
#define CP_DISABLED_FLAG 0x00001000
|
|
#define CP_QUOTA_NEED_FSCK_FLAG 0x00000800
|
|
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
|
|
index 53fc34f930d0..8a03f392f368 100644
|
|
--- a/include/linux/hugetlb.h
|
|
+++ b/include/linux/hugetlb.h
|
|
@@ -298,7 +298,10 @@ static inline bool is_file_hugepages(struct file *file)
|
|
return is_file_shm_hugepages(file);
|
|
}
|
|
|
|
-
|
|
+static inline struct hstate *hstate_inode(struct inode *i)
|
|
+{
|
|
+ return HUGETLBFS_SB(i->i_sb)->hstate;
|
|
+}
|
|
#else /* !CONFIG_HUGETLBFS */
|
|
|
|
#define is_file_hugepages(file) false
|
|
@@ -310,6 +313,10 @@ hugetlb_file_setup(const char *name, size_t size, vm_flags_t acctflag,
|
|
return ERR_PTR(-ENOSYS);
|
|
}
|
|
|
|
+static inline struct hstate *hstate_inode(struct inode *i)
|
|
+{
|
|
+ return NULL;
|
|
+}
|
|
#endif /* !CONFIG_HUGETLBFS */
|
|
|
|
#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
|
@@ -379,11 +386,6 @@ extern unsigned int default_hstate_idx;
|
|
|
|
#define default_hstate (hstates[default_hstate_idx])
|
|
|
|
-static inline struct hstate *hstate_inode(struct inode *i)
|
|
-{
|
|
- return HUGETLBFS_SB(i->i_sb)->hstate;
|
|
-}
|
|
-
|
|
static inline struct hstate *hstate_file(struct file *f)
|
|
{
|
|
return hstate_inode(file_inode(f));
|
|
@@ -636,11 +638,6 @@ static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
|
|
return NULL;
|
|
}
|
|
|
|
-static inline struct hstate *hstate_inode(struct inode *i)
|
|
-{
|
|
- return NULL;
|
|
-}
|
|
-
|
|
static inline struct hstate *page_hstate(struct page *page)
|
|
{
|
|
return NULL;
|
|
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
|
|
index 4ded94bcf274..2ab2d6d6aeab 100644
|
|
--- a/include/linux/key-type.h
|
|
+++ b/include/linux/key-type.h
|
|
@@ -127,7 +127,7 @@ struct key_type {
|
|
* much is copied into the buffer
|
|
* - shouldn't do the copy if the buffer is NULL
|
|
*/
|
|
- long (*read)(const struct key *key, char __user *buffer, size_t buflen);
|
|
+ long (*read)(const struct key *key, char *buffer, size_t buflen);
|
|
|
|
/* handle request_key() for this type instead of invoking
|
|
* /sbin/request-key (optional)
|
|
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
|
|
index 4f052496cdfd..0a4f54dd4737 100644
|
|
--- a/include/linux/percpu_counter.h
|
|
+++ b/include/linux/percpu_counter.h
|
|
@@ -78,9 +78,9 @@ static inline s64 percpu_counter_read(struct percpu_counter *fbc)
|
|
*/
|
|
static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
|
|
{
|
|
- s64 ret = fbc->count;
|
|
+ /* Prevent reloads of fbc->count */
|
|
+ s64 ret = READ_ONCE(fbc->count);
|
|
|
|
- barrier(); /* Prevent reloads of fbc->count */
|
|
if (ret >= 0)
|
|
return ret;
|
|
return 0;
|
|
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
|
|
index 877fd239b6ff..3208a520d0be 100644
|
|
--- a/include/linux/swapops.h
|
|
+++ b/include/linux/swapops.h
|
|
@@ -348,7 +348,8 @@ static inline void num_poisoned_pages_inc(void)
|
|
}
|
|
#endif
|
|
|
|
-#if defined(CONFIG_MEMORY_FAILURE) || defined(CONFIG_MIGRATION)
|
|
+#if defined(CONFIG_MEMORY_FAILURE) || defined(CONFIG_MIGRATION) || \
|
|
+ defined(CONFIG_DEVICE_PRIVATE)
|
|
static inline int non_swap_entry(swp_entry_t entry)
|
|
{
|
|
return swp_type(entry) >= MAX_SWAPFILES;
|
|
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
index 013780ef0bd7..e1a65303cfd7 100644
|
|
--- a/kernel/bpf/verifier.c
|
|
+++ b/kernel/bpf/verifier.c
|
|
@@ -201,8 +201,7 @@ struct bpf_call_arg_meta {
|
|
bool pkt_access;
|
|
int regno;
|
|
int access_size;
|
|
- s64 msize_smax_value;
|
|
- u64 msize_umax_value;
|
|
+ u64 msize_max_value;
|
|
int ref_obj_id;
|
|
int func_id;
|
|
};
|
|
@@ -3377,8 +3376,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
|
|
/* remember the mem_size which may be used later
|
|
* to refine return values.
|
|
*/
|
|
- meta->msize_smax_value = reg->smax_value;
|
|
- meta->msize_umax_value = reg->umax_value;
|
|
+ meta->msize_max_value = reg->umax_value;
|
|
|
|
/* The register is SCALAR_VALUE; the access check
|
|
* happens using its boundaries.
|
|
@@ -3866,21 +3864,44 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
|
|
return 0;
|
|
}
|
|
|
|
-static void do_refine_retval_range(struct bpf_reg_state *regs, int ret_type,
|
|
- int func_id,
|
|
- struct bpf_call_arg_meta *meta)
|
|
+static int do_refine_retval_range(struct bpf_verifier_env *env,
|
|
+ struct bpf_reg_state *regs, int ret_type,
|
|
+ int func_id, struct bpf_call_arg_meta *meta)
|
|
{
|
|
struct bpf_reg_state *ret_reg = ®s[BPF_REG_0];
|
|
+ struct bpf_reg_state tmp_reg = *ret_reg;
|
|
+ bool ret;
|
|
|
|
if (ret_type != RET_INTEGER ||
|
|
(func_id != BPF_FUNC_get_stack &&
|
|
func_id != BPF_FUNC_probe_read_str))
|
|
- return;
|
|
+ return 0;
|
|
+
|
|
+ /* Error case where ret is in interval [S32MIN, -1]. */
|
|
+ ret_reg->smin_value = S32_MIN;
|
|
+ ret_reg->smax_value = -1;
|
|
+
|
|
+ __reg_deduce_bounds(ret_reg);
|
|
+ __reg_bound_offset(ret_reg);
|
|
+ __update_reg_bounds(ret_reg);
|
|
+
|
|
+ ret = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
|
|
+ if (!ret)
|
|
+ return -EFAULT;
|
|
+
|
|
+ *ret_reg = tmp_reg;
|
|
+
|
|
+ /* Success case where ret is in range [0, msize_max_value]. */
|
|
+ ret_reg->smin_value = 0;
|
|
+ ret_reg->smax_value = meta->msize_max_value;
|
|
+ ret_reg->umin_value = ret_reg->smin_value;
|
|
+ ret_reg->umax_value = ret_reg->smax_value;
|
|
|
|
- ret_reg->smax_value = meta->msize_smax_value;
|
|
- ret_reg->umax_value = meta->msize_umax_value;
|
|
__reg_deduce_bounds(ret_reg);
|
|
__reg_bound_offset(ret_reg);
|
|
+ __update_reg_bounds(ret_reg);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static int
|
|
@@ -4112,7 +4133,9 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
|
|
regs[BPF_REG_0].ref_obj_id = id;
|
|
}
|
|
|
|
- do_refine_retval_range(regs, fn->ret_type, func_id, &meta);
|
|
+ err = do_refine_retval_range(env, regs, fn->ret_type, func_id, &meta);
|
|
+ if (err)
|
|
+ return err;
|
|
|
|
err = check_map_func_compatibility(env, meta.map_ptr, func_id);
|
|
if (err)
|
|
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
|
|
index 551b0eb7028a..2a0c4985f38e 100644
|
|
--- a/kernel/dma/coherent.c
|
|
+++ b/kernel/dma/coherent.c
|
|
@@ -134,7 +134,7 @@ static void *__dma_alloc_from_coherent(struct device *dev,
|
|
|
|
spin_lock_irqsave(&mem->spinlock, flags);
|
|
|
|
- if (unlikely(size > (mem->size << PAGE_SHIFT)))
|
|
+ if (unlikely(size > ((dma_addr_t)mem->size << PAGE_SHIFT)))
|
|
goto err;
|
|
|
|
pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
|
|
@@ -144,8 +144,9 @@ static void *__dma_alloc_from_coherent(struct device *dev,
|
|
/*
|
|
* Memory was found in the coherent area.
|
|
*/
|
|
- *dma_handle = dma_get_device_base(dev, mem) + (pageno << PAGE_SHIFT);
|
|
- ret = mem->virt_base + (pageno << PAGE_SHIFT);
|
|
+ *dma_handle = dma_get_device_base(dev, mem) +
|
|
+ ((dma_addr_t)pageno << PAGE_SHIFT);
|
|
+ ret = mem->virt_base + ((dma_addr_t)pageno << PAGE_SHIFT);
|
|
spin_unlock_irqrestore(&mem->spinlock, flags);
|
|
memset(ret, 0, size);
|
|
return ret;
|
|
@@ -194,7 +195,7 @@ static int __dma_release_from_coherent(struct dma_coherent_mem *mem,
|
|
int order, void *vaddr)
|
|
{
|
|
if (mem && vaddr >= mem->virt_base && vaddr <
|
|
- (mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
|
+ (mem->virt_base + ((dma_addr_t)mem->size << PAGE_SHIFT))) {
|
|
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
|
|
unsigned long flags;
|
|
|
|
@@ -238,10 +239,10 @@ static int __dma_mmap_from_coherent(struct dma_coherent_mem *mem,
|
|
struct vm_area_struct *vma, void *vaddr, size_t size, int *ret)
|
|
{
|
|
if (mem && vaddr >= mem->virt_base && vaddr + size <=
|
|
- (mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
|
+ (mem->virt_base + ((dma_addr_t)mem->size << PAGE_SHIFT))) {
|
|
unsigned long off = vma->vm_pgoff;
|
|
int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
|
|
- int user_count = vma_pages(vma);
|
|
+ unsigned long user_count = vma_pages(vma);
|
|
int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
|
|
|
*ret = -ENXIO;
|
|
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
|
|
index 4ad74f5987ea..cb6425e52bf7 100644
|
|
--- a/kernel/dma/debug.c
|
|
+++ b/kernel/dma/debug.c
|
|
@@ -137,9 +137,12 @@ static const char *const maperr2str[] = {
|
|
[MAP_ERR_CHECKED] = "dma map error checked",
|
|
};
|
|
|
|
-static const char *type2name[5] = { "single", "page",
|
|
- "scather-gather", "coherent",
|
|
- "resource" };
|
|
+static const char *type2name[] = {
|
|
+ [dma_debug_single] = "single",
|
|
+ [dma_debug_sg] = "scather-gather",
|
|
+ [dma_debug_coherent] = "coherent",
|
|
+ [dma_debug_resource] = "resource",
|
|
+};
|
|
|
|
static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
|
|
"DMA_FROM_DEVICE", "DMA_NONE" };
|
|
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
|
|
index c513031cd7e3..e09562818bb7 100644
|
|
--- a/kernel/locking/locktorture.c
|
|
+++ b/kernel/locking/locktorture.c
|
|
@@ -697,10 +697,10 @@ static void __torture_print_stats(char *page,
|
|
if (statp[i].n_lock_fail)
|
|
fail = true;
|
|
sum += statp[i].n_lock_acquired;
|
|
- if (max < statp[i].n_lock_fail)
|
|
- max = statp[i].n_lock_fail;
|
|
- if (min > statp[i].n_lock_fail)
|
|
- min = statp[i].n_lock_fail;
|
|
+ if (max < statp[i].n_lock_acquired)
|
|
+ max = statp[i].n_lock_acquired;
|
|
+ if (min > statp[i].n_lock_acquired)
|
|
+ min = statp[i].n_lock_acquired;
|
|
}
|
|
page += sprintf(page,
|
|
"%s: Total: %lld Max/Min: %ld/%ld %s Fail: %d %s\n",
|
|
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
|
|
index f61d834e02fe..6118d99117da 100644
|
|
--- a/lib/Kconfig.debug
|
|
+++ b/lib/Kconfig.debug
|
|
@@ -223,6 +223,8 @@ config DEBUG_INFO_DWARF4
|
|
config DEBUG_INFO_BTF
|
|
bool "Generate BTF typeinfo"
|
|
depends on DEBUG_INFO
|
|
+ depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
|
|
+ depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
|
|
help
|
|
Generate deduplicated BTF type information from DWARF debug info.
|
|
Turning this on expects presence of pahole tool, which will convert
|
|
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
|
|
index 3e1a90669006..ad53eb31d40f 100644
|
|
--- a/net/dns_resolver/dns_key.c
|
|
+++ b/net/dns_resolver/dns_key.c
|
|
@@ -302,7 +302,7 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m)
|
|
* - the key's semaphore is read-locked
|
|
*/
|
|
static long dns_resolver_read(const struct key *key,
|
|
- char __user *buffer, size_t buflen)
|
|
+ char *buffer, size_t buflen)
|
|
{
|
|
int err = PTR_ERR(key->payload.data[dns_key_error]);
|
|
|
|
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
|
|
index 068daff41f6e..f7129232c825 100644
|
|
--- a/net/netfilter/nf_tables_api.c
|
|
+++ b/net/netfilter/nf_tables_api.c
|
|
@@ -3598,7 +3598,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
|
NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
|
|
NFT_SET_MAP | NFT_SET_EVAL |
|
|
NFT_SET_OBJECT))
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
/* Only one of these operations is supported */
|
|
if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
|
|
(NFT_SET_MAP | NFT_SET_OBJECT))
|
|
@@ -3636,7 +3636,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
|
objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
|
|
if (objtype == NFT_OBJECT_UNSPEC ||
|
|
objtype > NFT_OBJECT_MAX)
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
} else if (flags & NFT_SET_OBJECT)
|
|
return -EINVAL;
|
|
else
|
|
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
|
|
index 6c3f35fac42d..0c98313dd7a8 100644
|
|
--- a/net/rxrpc/key.c
|
|
+++ b/net/rxrpc/key.c
|
|
@@ -31,7 +31,7 @@ static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
|
|
static void rxrpc_destroy(struct key *);
|
|
static void rxrpc_destroy_s(struct key *);
|
|
static void rxrpc_describe(const struct key *, struct seq_file *);
|
|
-static long rxrpc_read(const struct key *, char __user *, size_t);
|
|
+static long rxrpc_read(const struct key *, char *, size_t);
|
|
|
|
/*
|
|
* rxrpc defined keys take an arbitrary string as the description and an
|
|
@@ -1042,12 +1042,12 @@ EXPORT_SYMBOL(rxrpc_get_null_key);
|
|
* - this returns the result in XDR form
|
|
*/
|
|
static long rxrpc_read(const struct key *key,
|
|
- char __user *buffer, size_t buflen)
|
|
+ char *buffer, size_t buflen)
|
|
{
|
|
const struct rxrpc_key_token *token;
|
|
const struct krb5_principal *princ;
|
|
size_t size;
|
|
- __be32 __user *xdr, *oldxdr;
|
|
+ __be32 *xdr, *oldxdr;
|
|
u32 cnlen, toksize, ntoks, tok, zero;
|
|
u16 toksizes[AFSTOKEN_MAX];
|
|
int loop;
|
|
@@ -1124,30 +1124,25 @@ static long rxrpc_read(const struct key *key,
|
|
if (!buffer || buflen < size)
|
|
return size;
|
|
|
|
- xdr = (__be32 __user *) buffer;
|
|
+ xdr = (__be32 *)buffer;
|
|
zero = 0;
|
|
#define ENCODE(x) \
|
|
do { \
|
|
- __be32 y = htonl(x); \
|
|
- if (put_user(y, xdr++) < 0) \
|
|
- goto fault; \
|
|
+ *xdr++ = htonl(x); \
|
|
} while(0)
|
|
#define ENCODE_DATA(l, s) \
|
|
do { \
|
|
u32 _l = (l); \
|
|
ENCODE(l); \
|
|
- if (copy_to_user(xdr, (s), _l) != 0) \
|
|
- goto fault; \
|
|
- if (_l & 3 && \
|
|
- copy_to_user((u8 __user *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \
|
|
- goto fault; \
|
|
+ memcpy(xdr, (s), _l); \
|
|
+ if (_l & 3) \
|
|
+ memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
|
|
xdr += (_l + 3) >> 2; \
|
|
} while(0)
|
|
#define ENCODE64(x) \
|
|
do { \
|
|
__be64 y = cpu_to_be64(x); \
|
|
- if (copy_to_user(xdr, &y, 8) != 0) \
|
|
- goto fault; \
|
|
+ memcpy(xdr, &y, 8); \
|
|
xdr += 8 >> 2; \
|
|
} while(0)
|
|
#define ENCODE_STR(s) \
|
|
@@ -1238,8 +1233,4 @@ static long rxrpc_read(const struct key *key,
|
|
ASSERTCMP((char __user *) xdr - buffer, ==, size);
|
|
_leave(" = %zu", size);
|
|
return size;
|
|
-
|
|
-fault:
|
|
- _leave(" = -EFAULT");
|
|
- return -EFAULT;
|
|
}
|
|
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
|
|
index d75fddca44c9..ff5fcb3e1208 100644
|
|
--- a/net/sunrpc/auth_gss/auth_gss.c
|
|
+++ b/net/sunrpc/auth_gss/auth_gss.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <linux/sunrpc/clnt.h>
|
|
#include <linux/sunrpc/auth.h>
|
|
#include <linux/sunrpc/auth_gss.h>
|
|
+#include <linux/sunrpc/gss_krb5.h>
|
|
#include <linux/sunrpc/svcauth_gss.h>
|
|
#include <linux/sunrpc/gss_err.h>
|
|
#include <linux/workqueue.h>
|
|
@@ -1050,7 +1051,7 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
|
|
goto err_put_mech;
|
|
auth = &gss_auth->rpc_auth;
|
|
auth->au_cslack = GSS_CRED_SLACK >> 2;
|
|
- auth->au_rslack = GSS_VERF_SLACK >> 2;
|
|
+ auth->au_rslack = GSS_KRB5_MAX_SLACK_NEEDED >> 2;
|
|
auth->au_verfsize = GSS_VERF_SLACK >> 2;
|
|
auth->au_ralign = GSS_VERF_SLACK >> 2;
|
|
auth->au_flags = 0;
|
|
@@ -1934,35 +1935,69 @@ gss_unwrap_resp_auth(struct rpc_cred *cred)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * RFC 2203, Section 5.3.2.2
|
|
+ *
|
|
+ * struct rpc_gss_integ_data {
|
|
+ * opaque databody_integ<>;
|
|
+ * opaque checksum<>;
|
|
+ * };
|
|
+ *
|
|
+ * struct rpc_gss_data_t {
|
|
+ * unsigned int seq_num;
|
|
+ * proc_req_arg_t arg;
|
|
+ * };
|
|
+ */
|
|
static int
|
|
gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
|
|
struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp,
|
|
struct xdr_stream *xdr)
|
|
{
|
|
- struct xdr_buf integ_buf, *rcv_buf = &rqstp->rq_rcv_buf;
|
|
- u32 data_offset, mic_offset, integ_len, maj_stat;
|
|
+ struct xdr_buf gss_data, *rcv_buf = &rqstp->rq_rcv_buf;
|
|
struct rpc_auth *auth = cred->cr_auth;
|
|
+ u32 len, offset, seqno, maj_stat;
|
|
struct xdr_netobj mic;
|
|
- __be32 *p;
|
|
+ int ret;
|
|
|
|
- p = xdr_inline_decode(xdr, 2 * sizeof(*p));
|
|
- if (unlikely(!p))
|
|
+ ret = -EIO;
|
|
+ mic.data = NULL;
|
|
+
|
|
+ /* opaque databody_integ<>; */
|
|
+ if (xdr_stream_decode_u32(xdr, &len))
|
|
goto unwrap_failed;
|
|
- integ_len = be32_to_cpup(p++);
|
|
- if (integ_len & 3)
|
|
+ if (len & 3)
|
|
goto unwrap_failed;
|
|
- data_offset = (u8 *)(p) - (u8 *)rcv_buf->head[0].iov_base;
|
|
- mic_offset = integ_len + data_offset;
|
|
- if (mic_offset > rcv_buf->len)
|
|
+ offset = rcv_buf->len - xdr_stream_remaining(xdr);
|
|
+ if (xdr_stream_decode_u32(xdr, &seqno))
|
|
goto unwrap_failed;
|
|
- if (be32_to_cpup(p) != rqstp->rq_seqno)
|
|
+ if (seqno != rqstp->rq_seqno)
|
|
goto bad_seqno;
|
|
+ if (xdr_buf_subsegment(rcv_buf, &gss_data, offset, len))
|
|
+ goto unwrap_failed;
|
|
|
|
- if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, integ_len))
|
|
+ /*
|
|
+ * The xdr_stream now points to the beginning of the
|
|
+ * upper layer payload, to be passed below to
|
|
+ * rpcauth_unwrap_resp_decode(). The checksum, which
|
|
+ * follows the upper layer payload in @rcv_buf, is
|
|
+ * located and parsed without updating the xdr_stream.
|
|
+ */
|
|
+
|
|
+ /* opaque checksum<>; */
|
|
+ offset += len;
|
|
+ if (xdr_decode_word(rcv_buf, offset, &len))
|
|
+ goto unwrap_failed;
|
|
+ offset += sizeof(__be32);
|
|
+ if (offset + len > rcv_buf->len)
|
|
goto unwrap_failed;
|
|
- if (xdr_buf_read_mic(rcv_buf, &mic, mic_offset))
|
|
+ mic.len = len;
|
|
+ mic.data = kmalloc(len, GFP_NOFS);
|
|
+ if (!mic.data)
|
|
+ goto unwrap_failed;
|
|
+ if (read_bytes_from_xdr_buf(rcv_buf, offset, mic.data, mic.len))
|
|
goto unwrap_failed;
|
|
- maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
|
|
+
|
|
+ maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &gss_data, &mic);
|
|
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
|
|
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
|
|
if (maj_stat != GSS_S_COMPLETE)
|
|
@@ -1970,16 +2005,21 @@ gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
|
|
|
|
auth->au_rslack = auth->au_verfsize + 2 + 1 + XDR_QUADLEN(mic.len);
|
|
auth->au_ralign = auth->au_verfsize + 2;
|
|
- return 0;
|
|
+ ret = 0;
|
|
+
|
|
+out:
|
|
+ kfree(mic.data);
|
|
+ return ret;
|
|
+
|
|
unwrap_failed:
|
|
trace_rpcgss_unwrap_failed(task);
|
|
- return -EIO;
|
|
+ goto out;
|
|
bad_seqno:
|
|
- trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, be32_to_cpup(p));
|
|
- return -EIO;
|
|
+ trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, seqno);
|
|
+ goto out;
|
|
bad_mic:
|
|
trace_rpcgss_verify_mic(task, maj_stat);
|
|
- return -EIO;
|
|
+ goto out;
|
|
}
|
|
|
|
static int
|
|
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
|
|
index 3049af269fbf..c5dba371a765 100644
|
|
--- a/net/xdp/xdp_umem.c
|
|
+++ b/net/xdp/xdp_umem.c
|
|
@@ -343,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
|
u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
|
|
unsigned int chunks, chunks_per_page;
|
|
u64 addr = mr->addr, size = mr->len;
|
|
- int size_chk, err;
|
|
+ int err;
|
|
|
|
if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
|
|
/* Strictly speaking we could support this, if:
|
|
@@ -382,8 +382,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- size_chk = chunk_size - headroom - XDP_PACKET_HEADROOM;
|
|
- if (size_chk < 0)
|
|
+ if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
|
|
return -EINVAL;
|
|
|
|
umem->address = (unsigned long)addr;
|
|
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
|
|
index d426fc01c529..7181a30666b4 100644
|
|
--- a/net/xdp/xsk.c
|
|
+++ b/net/xdp/xsk.c
|
|
@@ -129,8 +129,9 @@ static void __xsk_rcv_memcpy(struct xdp_umem *umem, u64 addr, void *from_buf,
|
|
u64 page_start = addr & ~(PAGE_SIZE - 1);
|
|
u64 first_len = PAGE_SIZE - (addr - page_start);
|
|
|
|
- memcpy(to_buf, from_buf, first_len + metalen);
|
|
- memcpy(next_pg_addr, from_buf + first_len, len - first_len);
|
|
+ memcpy(to_buf, from_buf, first_len);
|
|
+ memcpy(next_pg_addr, from_buf + first_len,
|
|
+ len + metalen - first_len);
|
|
|
|
return;
|
|
}
|
|
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
|
|
index 001abe530a0d..82008f900930 100644
|
|
--- a/security/keys/big_key.c
|
|
+++ b/security/keys/big_key.c
|
|
@@ -352,7 +352,7 @@ void big_key_describe(const struct key *key, struct seq_file *m)
|
|
* read the key data
|
|
* - the key's semaphore is read-locked
|
|
*/
|
|
-long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
|
|
+long big_key_read(const struct key *key, char *buffer, size_t buflen)
|
|
{
|
|
size_t datalen = (size_t)key->payload.data[big_key_len];
|
|
long ret;
|
|
@@ -391,9 +391,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
|
|
|
|
ret = datalen;
|
|
|
|
- /* copy decrypted data to user */
|
|
- if (copy_to_user(buffer, buf->virt, datalen) != 0)
|
|
- ret = -EFAULT;
|
|
+ /* copy out decrypted data */
|
|
+ memcpy(buffer, buf->virt, datalen);
|
|
|
|
err_fput:
|
|
fput(file);
|
|
@@ -401,9 +400,7 @@ error:
|
|
big_key_free_buffer(buf);
|
|
} else {
|
|
ret = datalen;
|
|
- if (copy_to_user(buffer, key->payload.data[big_key_data],
|
|
- datalen) != 0)
|
|
- ret = -EFAULT;
|
|
+ memcpy(buffer, key->payload.data[big_key_data], datalen);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
|
|
index 60720f58cbe0..f6797ba44bf7 100644
|
|
--- a/security/keys/encrypted-keys/encrypted.c
|
|
+++ b/security/keys/encrypted-keys/encrypted.c
|
|
@@ -902,14 +902,14 @@ out:
|
|
}
|
|
|
|
/*
|
|
- * encrypted_read - format and copy the encrypted data to userspace
|
|
+ * encrypted_read - format and copy out the encrypted data
|
|
*
|
|
* The resulting datablob format is:
|
|
* <master-key name> <decrypted data length> <encrypted iv> <encrypted data>
|
|
*
|
|
* On success, return to userspace the encrypted key datablob size.
|
|
*/
|
|
-static long encrypted_read(const struct key *key, char __user *buffer,
|
|
+static long encrypted_read(const struct key *key, char *buffer,
|
|
size_t buflen)
|
|
{
|
|
struct encrypted_key_payload *epayload;
|
|
@@ -957,8 +957,7 @@ static long encrypted_read(const struct key *key, char __user *buffer,
|
|
key_put(mkey);
|
|
memzero_explicit(derived_key, sizeof(derived_key));
|
|
|
|
- if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0)
|
|
- ret = -EFAULT;
|
|
+ memcpy(buffer, ascii_buf, asciiblob_len);
|
|
kzfree(ascii_buf);
|
|
|
|
return asciiblob_len;
|
|
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
|
|
index d1a3dea58dee..106e16f9006b 100644
|
|
--- a/security/keys/keyctl.c
|
|
+++ b/security/keys/keyctl.c
|
|
@@ -797,6 +797,21 @@ error:
|
|
return ret;
|
|
}
|
|
|
|
+/*
|
|
+ * Call the read method
|
|
+ */
|
|
+static long __keyctl_read_key(struct key *key, char *buffer, size_t buflen)
|
|
+{
|
|
+ long ret;
|
|
+
|
|
+ down_read(&key->sem);
|
|
+ ret = key_validate(key);
|
|
+ if (ret == 0)
|
|
+ ret = key->type->read(key, buffer, buflen);
|
|
+ up_read(&key->sem);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/*
|
|
* Read a key's payload.
|
|
*
|
|
@@ -812,26 +827,27 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
|
|
struct key *key;
|
|
key_ref_t key_ref;
|
|
long ret;
|
|
+ char *key_data;
|
|
|
|
/* find the key first */
|
|
key_ref = lookup_user_key(keyid, 0, 0);
|
|
if (IS_ERR(key_ref)) {
|
|
ret = -ENOKEY;
|
|
- goto error;
|
|
+ goto out;
|
|
}
|
|
|
|
key = key_ref_to_ptr(key_ref);
|
|
|
|
ret = key_read_state(key);
|
|
if (ret < 0)
|
|
- goto error2; /* Negatively instantiated */
|
|
+ goto key_put_out; /* Negatively instantiated */
|
|
|
|
/* see if we can read it directly */
|
|
ret = key_permission(key_ref, KEY_NEED_READ);
|
|
if (ret == 0)
|
|
goto can_read_key;
|
|
if (ret != -EACCES)
|
|
- goto error2;
|
|
+ goto key_put_out;
|
|
|
|
/* we can't; see if it's searchable from this process's keyrings
|
|
* - we automatically take account of the fact that it may be
|
|
@@ -839,26 +855,51 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
|
|
*/
|
|
if (!is_key_possessed(key_ref)) {
|
|
ret = -EACCES;
|
|
- goto error2;
|
|
+ goto key_put_out;
|
|
}
|
|
|
|
/* the key is probably readable - now try to read it */
|
|
can_read_key:
|
|
- ret = -EOPNOTSUPP;
|
|
- if (key->type->read) {
|
|
- /* Read the data with the semaphore held (since we might sleep)
|
|
- * to protect against the key being updated or revoked.
|
|
- */
|
|
- down_read(&key->sem);
|
|
- ret = key_validate(key);
|
|
- if (ret == 0)
|
|
- ret = key->type->read(key, buffer, buflen);
|
|
- up_read(&key->sem);
|
|
+ if (!key->type->read) {
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto key_put_out;
|
|
}
|
|
|
|
-error2:
|
|
+ if (!buffer || !buflen) {
|
|
+ /* Get the key length from the read method */
|
|
+ ret = __keyctl_read_key(key, NULL, 0);
|
|
+ goto key_put_out;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Read the data with the semaphore held (since we might sleep)
|
|
+ * to protect against the key being updated or revoked.
|
|
+ *
|
|
+ * Allocating a temporary buffer to hold the keys before
|
|
+ * transferring them to user buffer to avoid potential
|
|
+ * deadlock involving page fault and mmap_sem.
|
|
+ */
|
|
+ key_data = kmalloc(buflen, GFP_KERNEL);
|
|
+
|
|
+ if (!key_data) {
|
|
+ ret = -ENOMEM;
|
|
+ goto key_put_out;
|
|
+ }
|
|
+ ret = __keyctl_read_key(key, key_data, buflen);
|
|
+
|
|
+ /*
|
|
+ * Read methods will just return the required length without
|
|
+ * any copying if the provided length isn't large enough.
|
|
+ */
|
|
+ if (ret > 0 && ret <= buflen) {
|
|
+ if (copy_to_user(buffer, key_data, ret))
|
|
+ ret = -EFAULT;
|
|
+ }
|
|
+ kzfree(key_data);
|
|
+
|
|
+key_put_out:
|
|
key_put(key);
|
|
-error:
|
|
+out:
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
|
|
index febf36c6ddc5..5ca620d31cd3 100644
|
|
--- a/security/keys/keyring.c
|
|
+++ b/security/keys/keyring.c
|
|
@@ -459,7 +459,6 @@ static int keyring_read_iterator(const void *object, void *data)
|
|
{
|
|
struct keyring_read_iterator_context *ctx = data;
|
|
const struct key *key = keyring_ptr_to_key(object);
|
|
- int ret;
|
|
|
|
kenter("{%s,%d},,{%zu/%zu}",
|
|
key->type->name, key->serial, ctx->count, ctx->buflen);
|
|
@@ -467,10 +466,7 @@ static int keyring_read_iterator(const void *object, void *data)
|
|
if (ctx->count >= ctx->buflen)
|
|
return 1;
|
|
|
|
- ret = put_user(key->serial, ctx->buffer);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- ctx->buffer++;
|
|
+ *ctx->buffer++ = key->serial;
|
|
ctx->count += sizeof(key->serial);
|
|
return 0;
|
|
}
|
|
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
|
|
index ecba39c93fd9..41e9735006d0 100644
|
|
--- a/security/keys/request_key_auth.c
|
|
+++ b/security/keys/request_key_auth.c
|
|
@@ -22,7 +22,7 @@ static int request_key_auth_instantiate(struct key *,
|
|
static void request_key_auth_describe(const struct key *, struct seq_file *);
|
|
static void request_key_auth_revoke(struct key *);
|
|
static void request_key_auth_destroy(struct key *);
|
|
-static long request_key_auth_read(const struct key *, char __user *, size_t);
|
|
+static long request_key_auth_read(const struct key *, char *, size_t);
|
|
|
|
/*
|
|
* The request-key authorisation key type definition.
|
|
@@ -80,7 +80,7 @@ static void request_key_auth_describe(const struct key *key,
|
|
* - the key's semaphore is read-locked
|
|
*/
|
|
static long request_key_auth_read(const struct key *key,
|
|
- char __user *buffer, size_t buflen)
|
|
+ char *buffer, size_t buflen)
|
|
{
|
|
struct request_key_auth *rka = dereference_key_locked(key);
|
|
size_t datalen;
|
|
@@ -97,8 +97,7 @@ static long request_key_auth_read(const struct key *key,
|
|
if (buflen > datalen)
|
|
buflen = datalen;
|
|
|
|
- if (copy_to_user(buffer, rka->callout_info, buflen) != 0)
|
|
- ret = -EFAULT;
|
|
+ memcpy(buffer, rka->callout_info, buflen);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
|
|
index 1fbd77816610..36afc29aecc3 100644
|
|
--- a/security/keys/trusted.c
|
|
+++ b/security/keys/trusted.c
|
|
@@ -1144,11 +1144,10 @@ out:
|
|
* trusted_read - copy the sealed blob data to userspace in hex.
|
|
* On success, return to userspace the trusted key datablob size.
|
|
*/
|
|
-static long trusted_read(const struct key *key, char __user *buffer,
|
|
+static long trusted_read(const struct key *key, char *buffer,
|
|
size_t buflen)
|
|
{
|
|
const struct trusted_key_payload *p;
|
|
- char *ascii_buf;
|
|
char *bufp;
|
|
int i;
|
|
|
|
@@ -1157,18 +1156,9 @@ static long trusted_read(const struct key *key, char __user *buffer,
|
|
return -EINVAL;
|
|
|
|
if (buffer && buflen >= 2 * p->blob_len) {
|
|
- ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL);
|
|
- if (!ascii_buf)
|
|
- return -ENOMEM;
|
|
-
|
|
- bufp = ascii_buf;
|
|
+ bufp = buffer;
|
|
for (i = 0; i < p->blob_len; i++)
|
|
bufp = hex_byte_pack(bufp, p->blob[i]);
|
|
- if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
|
|
- kzfree(ascii_buf);
|
|
- return -EFAULT;
|
|
- }
|
|
- kzfree(ascii_buf);
|
|
}
|
|
return 2 * p->blob_len;
|
|
}
|
|
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
|
|
index 6f12de4ce549..07d4287e9084 100644
|
|
--- a/security/keys/user_defined.c
|
|
+++ b/security/keys/user_defined.c
|
|
@@ -168,7 +168,7 @@ EXPORT_SYMBOL_GPL(user_describe);
|
|
* read the key data
|
|
* - the key's semaphore is read-locked
|
|
*/
|
|
-long user_read(const struct key *key, char __user *buffer, size_t buflen)
|
|
+long user_read(const struct key *key, char *buffer, size_t buflen)
|
|
{
|
|
const struct user_key_payload *upayload;
|
|
long ret;
|
|
@@ -181,8 +181,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
|
|
if (buflen > upayload->datalen)
|
|
buflen = upayload->datalen;
|
|
|
|
- if (copy_to_user(buffer, upayload->data, buflen) != 0)
|
|
- ret = -EFAULT;
|
|
+ memcpy(buffer, upayload->data, buflen);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index 1db9d0579c72..72bbfeddea24 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -1068,6 +1068,8 @@ static int azx_freeze_noirq(struct device *dev)
|
|
struct azx *chip = card->private_data;
|
|
struct pci_dev *pci = to_pci_dev(dev);
|
|
|
|
+ if (!azx_is_pm_ready(card))
|
|
+ return 0;
|
|
if (chip->driver_type == AZX_DRIVER_SKL)
|
|
pci_set_power_state(pci, PCI_D3hot);
|
|
|
|
@@ -1080,6 +1082,8 @@ static int azx_thaw_noirq(struct device *dev)
|
|
struct azx *chip = card->private_data;
|
|
struct pci_dev *pci = to_pci_dev(dev);
|
|
|
|
+ if (!azx_is_pm_ready(card))
|
|
+ return 0;
|
|
if (chip->driver_type == AZX_DRIVER_SKL)
|
|
pci_set_power_state(pci, PCI_D0);
|
|
|
|
@@ -1976,24 +1980,15 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
|
|
{
|
|
struct snd_card *card = context;
|
|
struct azx *chip = card->private_data;
|
|
- struct pci_dev *pci = chip->pci;
|
|
|
|
- if (!fw) {
|
|
- dev_err(card->dev, "Cannot load firmware, aborting\n");
|
|
- goto error;
|
|
- }
|
|
-
|
|
- chip->fw = fw;
|
|
+ if (fw)
|
|
+ chip->fw = fw;
|
|
+ else
|
|
+ dev_err(card->dev, "Cannot load firmware, continue without patching\n");
|
|
if (!chip->disabled) {
|
|
/* continue probing */
|
|
- if (azx_probe_continue(chip))
|
|
- goto error;
|
|
+ azx_probe_continue(chip);
|
|
}
|
|
- return; /* OK */
|
|
-
|
|
- error:
|
|
- snd_card_free(card);
|
|
- pci_set_drvdata(pci, NULL);
|
|
}
|
|
#endif
|
|
|
|
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
|
|
index f53d3c515cdc..9fa4e1a46ca9 100644
|
|
--- a/tools/objtool/check.c
|
|
+++ b/tools/objtool/check.c
|
|
@@ -1010,10 +1010,7 @@ static struct rela *find_jump_table(struct objtool_file *file,
|
|
* it.
|
|
*/
|
|
for (;
|
|
- &insn->list != &file->insn_list &&
|
|
- insn->sec == func->sec &&
|
|
- insn->offset >= func->offset;
|
|
-
|
|
+ &insn->list != &file->insn_list && insn->func && insn->func->pfunc == func;
|
|
insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
|
|
|
|
if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
|
|
diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
|
|
index eba9a970703b..925722217edf 100644
|
|
--- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
|
|
+++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
|
|
@@ -82,6 +82,7 @@ static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size)
|
|
void test_get_stack_raw_tp(void)
|
|
{
|
|
const char *file = "./test_get_stack_rawtp.o";
|
|
+ const char *file_err = "./test_get_stack_rawtp_err.o";
|
|
const char *prog_name = "raw_tracepoint/sys_enter";
|
|
int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
|
|
struct perf_buffer_opts pb_opts = {};
|
|
@@ -93,6 +94,10 @@ void test_get_stack_raw_tp(void)
|
|
struct bpf_map *map;
|
|
cpu_set_t cpu_set;
|
|
|
|
+ err = bpf_prog_load(file_err, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
|
|
+ if (CHECK(err >= 0, "prog_load raw tp", "err %d errno %d\n", err, errno))
|
|
+ return;
|
|
+
|
|
err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
|
|
if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
|
|
return;
|
|
diff --git a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp_err.c b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp_err.c
|
|
new file mode 100644
|
|
index 000000000000..8941a41c2a55
|
|
--- /dev/null
|
|
+++ b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp_err.c
|
|
@@ -0,0 +1,26 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+
|
|
+#include <linux/bpf.h>
|
|
+#include <bpf/bpf_helpers.h>
|
|
+
|
|
+#define MAX_STACK_RAWTP 10
|
|
+
|
|
+SEC("raw_tracepoint/sys_enter")
|
|
+int bpf_prog2(void *ctx)
|
|
+{
|
|
+ __u64 stack[MAX_STACK_RAWTP];
|
|
+ int error;
|
|
+
|
|
+ /* set all the flags which should return -EINVAL */
|
|
+ error = bpf_get_stack(ctx, stack, 0, -1);
|
|
+ if (error < 0)
|
|
+ goto loop;
|
|
+
|
|
+ return error;
|
|
+loop:
|
|
+ while (1) {
|
|
+ error++;
|
|
+ }
|
|
+}
|
|
+
|
|
+char _license[] SEC("license") = "GPL";
|
|
diff --git a/tools/testing/selftests/bpf/verifier/bpf_get_stack.c b/tools/testing/selftests/bpf/verifier/bpf_get_stack.c
|
|
index f24d50f09dbe..371926771db5 100644
|
|
--- a/tools/testing/selftests/bpf/verifier/bpf_get_stack.c
|
|
+++ b/tools/testing/selftests/bpf/verifier/bpf_get_stack.c
|
|
@@ -9,17 +9,17 @@
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 28),
|
|
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
|
|
- BPF_MOV64_IMM(BPF_REG_9, sizeof(struct test_val)),
|
|
+ BPF_MOV64_IMM(BPF_REG_9, sizeof(struct test_val)/2),
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
|
|
- BPF_MOV64_IMM(BPF_REG_3, sizeof(struct test_val)),
|
|
+ BPF_MOV64_IMM(BPF_REG_3, sizeof(struct test_val)/2),
|
|
BPF_MOV64_IMM(BPF_REG_4, 256),
|
|
BPF_EMIT_CALL(BPF_FUNC_get_stack),
|
|
BPF_MOV64_IMM(BPF_REG_1, 0),
|
|
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_8, 32),
|
|
BPF_ALU64_IMM(BPF_ARSH, BPF_REG_8, 32),
|
|
- BPF_JMP_REG(BPF_JSLT, BPF_REG_1, BPF_REG_8, 16),
|
|
+ BPF_JMP_REG(BPF_JSLT, BPF_REG_8, BPF_REG_1, 16),
|
|
BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_8),
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_8),
|
|
@@ -29,7 +29,7 @@
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_1),
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
|
- BPF_MOV64_IMM(BPF_REG_5, sizeof(struct test_val)),
|
|
+ BPF_MOV64_IMM(BPF_REG_5, sizeof(struct test_val)/2),
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_5),
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 4),
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|