diff --git a/config/kernel/linux-rk3328-default.config b/config/kernel/linux-rk3328-default.config index 6c263000e..2d1f08f77 100644 --- a/config/kernel/linux-rk3328-default.config +++ b/config/kernel/linux-rk3328-default.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.132 Kernel Configuration +# Linux/arm64 4.4.133 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -2145,6 +2145,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_FT6236 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GSLX680A is not set # CONFIG_TOUCHSCREEN_GSLX680_D708 is not set # CONFIG_TOUCHSCREEN_GSLX680_PAD is not set CONFIG_TOUCHSCREEN_GSLX680_VR=y @@ -3634,6 +3635,7 @@ CONFIG_DRM_BRIDGE=y # CONFIG_DRM_PARADE_PS8622 is not set # CONFIG_DRM_RK1000 is not set # CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LONTIUM_LT8912 is not set CONFIG_DRM_ANALOGIX_DP=y CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set @@ -3659,6 +3661,7 @@ CONFIG_MALI_MIDGARD=y # CONFIG_MALI_MIDGARD_ENABLE_TRACE is not set # CONFIG_MALI_DMA_FENCE is not set CONFIG_MALI_EXPERT=y +# CONFIG_MALI_CORESTACK is not set # CONFIG_MALI_PRFCNT_SET_SECONDARY is not set # CONFIG_MALI_PLATFORM_FAKE is not set # CONFIG_MALI_PLATFORM_DEVICETREE is not set @@ -3669,7 +3672,9 @@ CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk" # CONFIG_MALI_TRACE_TIMELINE is not set # CONFIG_MALI_SYSTEM_TRACE is not set # CONFIG_MALI_GPU_MMU_AARCH64 is not set -# CONFIG_MALI_BIFROST_FOR_ANDROID is not set +# CONFIG_MALI_PWRSOFT_765 is not set +# CONFIG_MALI_KUTF is not set +CONFIG_MALI_BIFROST_FOR_ANDROID=y # CONFIG_MALI_BIFROST_FOR_LINUX is not set # CONFIG_MALI_BIFROST is not set @@ -3890,6 +3895,7 @@ CONFIG_SND_SOC_ROCKCHIP_I2S=y CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m # CONFIG_SND_SOC_ROCKCHIP_PDM is not set CONFIG_SND_SOC_ROCKCHIP_SPDIF=y +# CONFIG_SND_SOC_ROCKCHIP_VAD is not set # CONFIG_SND_SOC_ROCKCHIP_DA7219 is not set # CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG is not set # CONFIG_SND_SOC_ROCKCHIP_HDMI_DP is not set @@ -3948,7 +3954,7 @@ CONFIG_SND_SOC_MAX98090=y # CONFIG_SND_SOC_PCM512x_SPI is not set # CONFIG_SND_SOC_RK312X is not set # CONFIG_SND_SOC_RK3228 is not set -CONFIG_SND_SOC_RK3308=m +# CONFIG_SND_SOC_RK3308 is not set CONFIG_SND_SOC_RK3328=y # CONFIG_SND_SOC_RK817 is not set CONFIG_SND_SOC_RL6231=y @@ -4878,6 +4884,7 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # # DEVFREQ Drivers # +# CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ is not set CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y CONFIG_PM_DEVFREQ_EVENT=y CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y diff --git a/patch/kernel/rk3328-default/04-patch-4.4.132-133.patch b/patch/kernel/rk3328-default/04-patch-4.4.132-133.patch new file mode 100644 index 000000000..503171837 --- /dev/null +++ b/patch/kernel/rk3328-default/04-patch-4.4.132-133.patch @@ -0,0 +1,5004 @@ +diff --git a/Makefile b/Makefile +index ace4a655548a..ac52ee65685b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 132 ++SUBLEVEL = 133 + EXTRAVERSION = + NAME = Blurry Fish Butt + +diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h +index f939794363ac..56474690e685 100644 +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "memory") + +-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/arc/include/asm/futex.h b/arch/arc/include/asm/futex.h +index 11e1b1f3acda..eb887dd13e74 100644 +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #endif + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; +- + #ifndef CONFIG_ARC_HAS_LLSC + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +index 7a032dd84bb2..9e096d811bed 100644 +--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +@@ -88,7 +88,6 @@ + clocks = <&clks 201>; + VDDA-supply = <®_2p5v>; + VDDIO-supply = <®_3p3v>; +- lrclk-strength = <3>; + }; + }; + +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index 2c16d9e7c03c..4a275fba6059 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -530,4 +530,14 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) + #endif + .endm + ++#ifdef CONFIG_KPROBES ++#define _ASM_NOKPROBE(entry) \ ++ .pushsection "_kprobe_blacklist", "aw" ; \ ++ .balign 4 ; \ ++ .long entry; \ ++ .popsection ++#else ++#define _ASM_NOKPROBE(entry) ++#endif ++ + #endif /* __ASM_ASSEMBLER_H__ */ +diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h +index 6795368ad023..cc414382dab4 100644 +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + #endif /* !SMP */ + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index c92b535150a0..306a2a581785 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -395,7 +396,8 @@ void unregister_undef_hook(struct undef_hook *hook) + raw_spin_unlock_irqrestore(&undef_lock, flags); + } + +-static int call_undef_hook(struct pt_regs *regs, unsigned int instr) ++static nokprobe_inline ++int call_undef_hook(struct pt_regs *regs, unsigned int instr) + { + struct undef_hook *hook; + unsigned long flags; +@@ -468,6 +470,7 @@ die_sig: + + arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); + } ++NOKPROBE_SYMBOL(do_undefinstr) + + /* + * Handle FIQ similarly to NMI on x86 systems. +diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S +index df73914e81c8..746e7801dcdf 100644 +--- a/arch/arm/lib/getuser.S ++++ b/arch/arm/lib/getuser.S +@@ -38,6 +38,7 @@ ENTRY(__get_user_1) + mov r0, #0 + ret lr + ENDPROC(__get_user_1) ++_ASM_NOKPROBE(__get_user_1) + + ENTRY(__get_user_2) + check_uaccess r0, 2, r1, r2, __get_user_bad +@@ -58,6 +59,7 @@ rb .req r0 + mov r0, #0 + ret lr + ENDPROC(__get_user_2) ++_ASM_NOKPROBE(__get_user_2) + + ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad +@@ -65,6 +67,7 @@ ENTRY(__get_user_4) + mov r0, #0 + ret lr + ENDPROC(__get_user_4) ++_ASM_NOKPROBE(__get_user_4) + + ENTRY(__get_user_8) + check_uaccess r0, 8, r1, r2, __get_user_bad8 +@@ -78,6 +81,7 @@ ENTRY(__get_user_8) + mov r0, #0 + ret lr + ENDPROC(__get_user_8) ++_ASM_NOKPROBE(__get_user_8) + + #ifdef __ARMEB__ + ENTRY(__get_user_32t_8) +@@ -91,6 +95,7 @@ ENTRY(__get_user_32t_8) + mov r0, #0 + ret lr + ENDPROC(__get_user_32t_8) ++_ASM_NOKPROBE(__get_user_32t_8) + + ENTRY(__get_user_64t_1) + check_uaccess r0, 1, r1, r2, __get_user_bad8 +@@ -98,6 +103,7 @@ ENTRY(__get_user_64t_1) + mov r0, #0 + ret lr + ENDPROC(__get_user_64t_1) ++_ASM_NOKPROBE(__get_user_64t_1) + + ENTRY(__get_user_64t_2) + check_uaccess r0, 2, r1, r2, __get_user_bad8 +@@ -114,6 +120,7 @@ rb .req r0 + mov r0, #0 + ret lr + ENDPROC(__get_user_64t_2) ++_ASM_NOKPROBE(__get_user_64t_2) + + ENTRY(__get_user_64t_4) + check_uaccess r0, 4, r1, r2, __get_user_bad8 +@@ -121,6 +128,7 @@ ENTRY(__get_user_64t_4) + mov r0, #0 + ret lr + ENDPROC(__get_user_64t_4) ++_ASM_NOKPROBE(__get_user_64t_4) + #endif + + __get_user_bad8: +@@ -131,6 +139,8 @@ __get_user_bad: + ret lr + ENDPROC(__get_user_bad) + ENDPROC(__get_user_bad8) ++_ASM_NOKPROBE(__get_user_bad) ++_ASM_NOKPROBE(__get_user_bad8) + + .pushsection __ex_table, "a" + .long 1b, __get_user_bad +diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c +index bcdecc25461b..b2aa9b32bff2 100644 +--- a/arch/arm/probes/kprobes/opt-arm.c ++++ b/arch/arm/probes/kprobes/opt-arm.c +@@ -165,13 +165,14 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) + { + unsigned long flags; + struct kprobe *p = &op->kp; +- struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); ++ struct kprobe_ctlblk *kcb; + + /* Save skipped registers */ + regs->ARM_pc = (unsigned long)op->kp.addr; + regs->ARM_ORIG_r0 = ~0UL; + + local_irq_save(flags); ++ kcb = get_kprobe_ctlblk(); + + if (kprobe_running()) { + kprobes_inc_nmissed_count(&op->kp); +@@ -191,6 +192,7 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) + + local_irq_restore(flags); + } ++NOKPROBE_SYMBOL(optimized_callback) + + int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig) + { +diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h +index f50753573989..195fd56b2377 100644 +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -53,20 +53,10 @@ + : "memory") + + static inline int +-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (int)(encoded_op << 8) >> 20; +- int cmparg = (int)(encoded_op << 20) >> 20; + int oldval = 0, ret, tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h +index 4bea27f50a7a..2702bd802d44 100644 +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include + #include + +-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr); ++extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr); + + static inline int + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c +index d155ca9e5098..37f7b2bf7f73 100644 +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_o + /* + * do the futex operations + */ +-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; break; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h +index 7e597f8434da..c607b77c8215 100644 +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + static inline int +-futex_atomic_op_inuser(int encoded_op, int __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h +index 76acbcd5c060..6d67dc1eaf2b 100644 +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h +index 01848f056f43..a9dad9e5e132 100644 +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h +index 1de190bdfb9c..a9e61ea54ca9 100644 +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h +index 49df14805a9b..ae5b64981d72 100644 +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags) + } + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { + unsigned long int flags; + u32 val; +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; + + pagefault_disable(); + +@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h +index e05808a328db..b0629249778b 100644 +--- a/arch/powerpc/include/asm/firmware.h ++++ b/arch/powerpc/include/asm/firmware.h +@@ -47,12 +47,10 @@ + #define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000) + #define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000) + #define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000) +-#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000) + #define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000) + #define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000) + #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000) + #define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000) +-#define FW_FEATURE_OPALv3 ASM_CONST(0x0000000400000000) + + #ifndef __ASSEMBLY__ + +@@ -70,8 +68,7 @@ enum { + FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY | + FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN, + FW_FEATURE_PSERIES_ALWAYS = 0, +- FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2 | +- FW_FEATURE_OPALv3, ++ FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL, + FW_FEATURE_POWERNV_ALWAYS = 0, + FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, + FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, +diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h +index 2a9cf845473b..f4c7467f7465 100644 +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "cr0", "memory") + +-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c +index 44c8d03558ac..318224784114 100644 +--- a/arch/powerpc/kernel/setup-common.c ++++ b/arch/powerpc/kernel/setup-common.c +@@ -217,14 +217,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) + unsigned short maj; + unsigned short min; + +- /* We only show online cpus: disable preempt (overzealous, I +- * knew) to prevent cpu going down. */ +- preempt_disable(); +- if (!cpu_online(cpu_id)) { +- preempt_enable(); +- return 0; +- } +- + #ifdef CONFIG_SMP + pvr = per_cpu(cpu_pvr, cpu_id); + #else +@@ -329,9 +321,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) + #ifdef CONFIG_SMP + seq_printf(m, "\n"); + #endif +- +- preempt_enable(); +- + /* If this is the last cpu, print the summary */ + if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids) + show_cpuinfo_summary(m); +diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c +index 92736851c795..3f653f5201e7 100644 +--- a/arch/powerpc/platforms/powernv/eeh-powernv.c ++++ b/arch/powerpc/platforms/powernv/eeh-powernv.c +@@ -48,8 +48,8 @@ static int pnv_eeh_init(void) + struct pci_controller *hose; + struct pnv_phb *phb; + +- if (!firmware_has_feature(FW_FEATURE_OPALv3)) { +- pr_warn("%s: OPALv3 is required !\n", ++ if (!firmware_has_feature(FW_FEATURE_OPAL)) { ++ pr_warn("%s: OPAL is required !\n", + __func__); + return -EINVAL; + } +diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c +index 59d735d2e5c0..15bfbcd5debc 100644 +--- a/arch/powerpc/platforms/powernv/idle.c ++++ b/arch/powerpc/platforms/powernv/idle.c +@@ -242,7 +242,7 @@ static int __init pnv_init_idle_states(void) + if (cpuidle_disable != IDLE_NO_OVERRIDE) + goto out; + +- if (!firmware_has_feature(FW_FEATURE_OPALv3)) ++ if (!firmware_has_feature(FW_FEATURE_OPAL)) + goto out; + + power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); +diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c +index 1bceb95f422d..5584247f5029 100644 +--- a/arch/powerpc/platforms/powernv/opal-nvram.c ++++ b/arch/powerpc/platforms/powernv/opal-nvram.c +@@ -44,6 +44,10 @@ static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index) + return count; + } + ++/* ++ * This can be called in the panic path with interrupts off, so use ++ * mdelay in that case. ++ */ + static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) + { + s64 rc = OPAL_BUSY; +@@ -58,10 +62,16 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) + while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { + rc = opal_write_nvram(__pa(buf), count, off); + if (rc == OPAL_BUSY_EVENT) { +- msleep(OPAL_BUSY_DELAY_MS); ++ if (in_interrupt() || irqs_disabled()) ++ mdelay(OPAL_BUSY_DELAY_MS); ++ else ++ msleep(OPAL_BUSY_DELAY_MS); + opal_poll_events(NULL); + } else if (rc == OPAL_BUSY) { +- msleep(OPAL_BUSY_DELAY_MS); ++ if (in_interrupt() || irqs_disabled()) ++ mdelay(OPAL_BUSY_DELAY_MS); ++ else ++ msleep(OPAL_BUSY_DELAY_MS); + } + } + +diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c +index 7634d1c62299..d0ac535cf5d7 100644 +--- a/arch/powerpc/platforms/powernv/opal-xscom.c ++++ b/arch/powerpc/platforms/powernv/opal-xscom.c +@@ -126,7 +126,7 @@ static const struct scom_controller opal_scom_controller = { + + static int opal_xscom_init(void) + { +- if (firmware_has_feature(FW_FEATURE_OPALv3)) ++ if (firmware_has_feature(FW_FEATURE_OPAL)) + scom_init(&opal_scom_controller); + return 0; + } +diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c +index ae29eaf85e9e..e48826aa314c 100644 +--- a/arch/powerpc/platforms/powernv/opal.c ++++ b/arch/powerpc/platforms/powernv/opal.c +@@ -98,16 +98,11 @@ int __init early_init_dt_scan_opal(unsigned long node, + pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n", + opal.size, sizep, runtimesz); + +- powerpc_firmware_features |= FW_FEATURE_OPAL; + if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { +- powerpc_firmware_features |= FW_FEATURE_OPALv2; +- powerpc_firmware_features |= FW_FEATURE_OPALv3; +- pr_info("OPAL V3 detected !\n"); +- } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { +- powerpc_firmware_features |= FW_FEATURE_OPALv2; +- pr_info("OPAL V2 detected !\n"); ++ powerpc_firmware_features |= FW_FEATURE_OPAL; ++ pr_info("OPAL detected !\n"); + } else { +- pr_info("OPAL V1 detected !\n"); ++ panic("OPAL != V3 detected, no longer supported.\n"); + } + + /* Reinit all cores with the right endian */ +@@ -352,17 +347,15 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) + * enough room and be done with it + */ + spin_lock_irqsave(&opal_write_lock, flags); +- if (firmware_has_feature(FW_FEATURE_OPALv2)) { +- rc = opal_console_write_buffer_space(vtermno, &olen); +- len = be64_to_cpu(olen); +- if (rc || len < total_len) { +- spin_unlock_irqrestore(&opal_write_lock, flags); +- /* Closed -> drop characters */ +- if (rc) +- return total_len; +- opal_poll_events(NULL); +- return -EAGAIN; +- } ++ rc = opal_console_write_buffer_space(vtermno, &olen); ++ len = be64_to_cpu(olen); ++ if (rc || len < total_len) { ++ spin_unlock_irqrestore(&opal_write_lock, flags); ++ /* Closed -> drop characters */ ++ if (rc) ++ return total_len; ++ opal_poll_events(NULL); ++ return -EAGAIN; + } + + /* We still try to handle partial completions, though they +@@ -696,10 +689,7 @@ static int __init opal_init(void) + } + + /* Register OPAL consoles if any ports */ +- if (firmware_has_feature(FW_FEATURE_OPALv2)) +- consoles = of_find_node_by_path("/ibm,opal/consoles"); +- else +- consoles = of_node_get(opal_node); ++ consoles = of_find_node_by_path("/ibm,opal/consoles"); + if (consoles) { + for_each_child_of_node(consoles, np) { + if (strcmp(np->name, "serial")) +diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c +index ecb7f3220355..eac3b7cc78c6 100644 +--- a/arch/powerpc/platforms/powernv/pci-ioda.c ++++ b/arch/powerpc/platforms/powernv/pci-ioda.c +@@ -344,7 +344,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) + return; + } + +- if (!firmware_has_feature(FW_FEATURE_OPALv3)) { ++ if (!firmware_has_feature(FW_FEATURE_OPAL)) { + pr_info(" Firmware too old to support M64 window\n"); + return; + } +diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c +index 30c6b3b7be90..c57afc619b20 100644 +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -140,12 +140,8 @@ static void pnv_show_cpuinfo(struct seq_file *m) + if (root) + model = of_get_property(root, "model", NULL); + seq_printf(m, "machine\t\t: PowerNV %s\n", model); +- if (firmware_has_feature(FW_FEATURE_OPALv3)) +- seq_printf(m, "firmware\t: OPAL v3\n"); +- else if (firmware_has_feature(FW_FEATURE_OPALv2)) +- seq_printf(m, "firmware\t: OPAL v2\n"); +- else if (firmware_has_feature(FW_FEATURE_OPAL)) +- seq_printf(m, "firmware\t: OPAL v1\n"); ++ if (firmware_has_feature(FW_FEATURE_OPAL)) ++ seq_printf(m, "firmware\t: OPAL\n"); + else + seq_printf(m, "firmware\t: BML\n"); + of_node_put(root); +@@ -274,9 +270,9 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) + { + xics_kexec_teardown_cpu(secondary); + +- /* On OPAL v3, we return all CPUs to firmware */ ++ /* On OPAL, we return all CPUs to firmware */ + +- if (!firmware_has_feature(FW_FEATURE_OPALv3)) ++ if (!firmware_has_feature(FW_FEATURE_OPAL)) + return; + + if (secondary) { +diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c +index ca264833ee64..ad7b1a3dbed0 100644 +--- a/arch/powerpc/platforms/powernv/smp.c ++++ b/arch/powerpc/platforms/powernv/smp.c +@@ -61,14 +61,15 @@ static int pnv_smp_kick_cpu(int nr) + unsigned long start_here = + __pa(ppc_function_entry(generic_secondary_smp_init)); + long rc; ++ uint8_t status; + + BUG_ON(nr < 0 || nr >= NR_CPUS); + + /* +- * If we already started or OPALv2 is not supported, we just ++ * If we already started or OPAL is not supported, we just + * kick the CPU via the PACA + */ +- if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2)) ++ if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPAL)) + goto kick; + + /* +@@ -77,55 +78,42 @@ static int pnv_smp_kick_cpu(int nr) + * first time. OPAL v3 allows us to query OPAL to know if it + * has the CPUs, so we do that + */ +- if (firmware_has_feature(FW_FEATURE_OPALv3)) { +- uint8_t status; +- +- rc = opal_query_cpu_status(pcpu, &status); +- if (rc != OPAL_SUCCESS) { +- pr_warn("OPAL Error %ld querying CPU %d state\n", +- rc, nr); +- return -ENODEV; +- } ++ rc = opal_query_cpu_status(pcpu, &status); ++ if (rc != OPAL_SUCCESS) { ++ pr_warn("OPAL Error %ld querying CPU %d state\n", rc, nr); ++ return -ENODEV; ++ } + +- /* +- * Already started, just kick it, probably coming from +- * kexec and spinning +- */ +- if (status == OPAL_THREAD_STARTED) +- goto kick; ++ /* ++ * Already started, just kick it, probably coming from ++ * kexec and spinning ++ */ ++ if (status == OPAL_THREAD_STARTED) ++ goto kick; + +- /* +- * Available/inactive, let's kick it +- */ +- if (status == OPAL_THREAD_INACTIVE) { +- pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", +- nr, pcpu); +- rc = opal_start_cpu(pcpu, start_here); +- if (rc != OPAL_SUCCESS) { +- pr_warn("OPAL Error %ld starting CPU %d\n", +- rc, nr); +- return -ENODEV; +- } +- } else { +- /* +- * An unavailable CPU (or any other unknown status) +- * shouldn't be started. It should also +- * not be in the possible map but currently it can +- * happen +- */ +- pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable" +- " (status %d)...\n", nr, pcpu, status); ++ /* ++ * Available/inactive, let's kick it ++ */ ++ if (status == OPAL_THREAD_INACTIVE) { ++ pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); ++ rc = opal_start_cpu(pcpu, start_here); ++ if (rc != OPAL_SUCCESS) { ++ pr_warn("OPAL Error %ld starting CPU %d\n", rc, nr); + return -ENODEV; + } + } else { + /* +- * On OPAL v2, we just kick it and hope for the best, +- * we must not test the error from opal_start_cpu() or +- * we would fail to get CPUs from kexec. ++ * An unavailable CPU (or any other unknown status) ++ * shouldn't be started. It should also ++ * not be in the possible map but currently it can ++ * happen + */ +- opal_start_cpu(pcpu, start_here); ++ pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable" ++ " (status %d)...\n", nr, pcpu, status); ++ return -ENODEV; + } +- kick: ++ ++kick: + return smp_generic_kick_cpu(nr); + } + +diff --git a/arch/s390/include/asm/alternative-asm.h b/arch/s390/include/asm/alternative-asm.h +new file mode 100644 +index 000000000000..955d620db23e +--- /dev/null ++++ b/arch/s390/include/asm/alternative-asm.h +@@ -0,0 +1,108 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _ASM_S390_ALTERNATIVE_ASM_H ++#define _ASM_S390_ALTERNATIVE_ASM_H ++ ++#ifdef __ASSEMBLY__ ++ ++/* ++ * Check the length of an instruction sequence. The length may not be larger ++ * than 254 bytes and it has to be divisible by 2. ++ */ ++.macro alt_len_check start,end ++ .if ( \end - \start ) > 254 ++ .error "cpu alternatives does not support instructions blocks > 254 bytes\n" ++ .endif ++ .if ( \end - \start ) % 2 ++ .error "cpu alternatives instructions length is odd\n" ++ .endif ++.endm ++ ++/* ++ * Issue one struct alt_instr descriptor entry (need to put it into ++ * the section .altinstructions, see below). This entry contains ++ * enough information for the alternatives patching code to patch an ++ * instruction. See apply_alternatives(). ++ */ ++.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature ++ .long \orig_start - . ++ .long \alt_start - . ++ .word \feature ++ .byte \orig_end - \orig_start ++ .byte \alt_end - \alt_start ++.endm ++ ++/* ++ * Fill up @bytes with nops. The macro emits 6-byte nop instructions ++ * for the bulk of the area, possibly followed by a 4-byte and/or ++ * a 2-byte nop if the size of the area is not divisible by 6. ++ */ ++.macro alt_pad_fill bytes ++ .fill ( \bytes ) / 6, 6, 0xc0040000 ++ .fill ( \bytes ) % 6 / 4, 4, 0x47000000 ++ .fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700 ++.endm ++ ++/* ++ * Fill up @bytes with nops. If the number of bytes is larger ++ * than 6, emit a jg instruction to branch over all nops, then ++ * fill an area of size (@bytes - 6) with nop instructions. ++ */ ++.macro alt_pad bytes ++ .if ( \bytes > 0 ) ++ .if ( \bytes > 6 ) ++ jg . + \bytes ++ alt_pad_fill \bytes - 6 ++ .else ++ alt_pad_fill \bytes ++ .endif ++ .endif ++.endm ++ ++/* ++ * Define an alternative between two instructions. If @feature is ++ * present, early code in apply_alternatives() replaces @oldinstr with ++ * @newinstr. ".skip" directive takes care of proper instruction padding ++ * in case @newinstr is longer than @oldinstr. ++ */ ++.macro ALTERNATIVE oldinstr, newinstr, feature ++ .pushsection .altinstr_replacement,"ax" ++770: \newinstr ++771: .popsection ++772: \oldinstr ++773: alt_len_check 770b, 771b ++ alt_len_check 772b, 773b ++ alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) ) ++774: .pushsection .altinstructions,"a" ++ alt_entry 772b, 774b, 770b, 771b, \feature ++ .popsection ++.endm ++ ++/* ++ * Define an alternative between two instructions. If @feature is ++ * present, early code in apply_alternatives() replaces @oldinstr with ++ * @newinstr. ".skip" directive takes care of proper instruction padding ++ * in case @newinstr is longer than @oldinstr. ++ */ ++.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 ++ .pushsection .altinstr_replacement,"ax" ++770: \newinstr1 ++771: \newinstr2 ++772: .popsection ++773: \oldinstr ++774: alt_len_check 770b, 771b ++ alt_len_check 771b, 772b ++ alt_len_check 773b, 774b ++ .if ( 771b - 770b > 772b - 771b ) ++ alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) ) ++ .else ++ alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) ) ++ .endif ++775: .pushsection .altinstructions,"a" ++ alt_entry 773b, 775b, 770b, 771b,\feature1 ++ alt_entry 773b, 775b, 771b, 772b,\feature2 ++ .popsection ++.endm ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* _ASM_S390_ALTERNATIVE_ASM_H */ +diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h +index a4811aa0304d..8f8eec9e1198 100644 +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "m" (*uaddr) : "cc"); + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, newval, ret; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/s390/include/asm/nospec-insn.h b/arch/s390/include/asm/nospec-insn.h +new file mode 100644 +index 000000000000..087fc9b972c5 +--- /dev/null ++++ b/arch/s390/include/asm/nospec-insn.h +@@ -0,0 +1,182 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _ASM_S390_NOSPEC_ASM_H ++#define _ASM_S390_NOSPEC_ASM_H ++ ++#ifdef __ASSEMBLY__ ++ ++#ifdef CONFIG_EXPOLINE ++ ++/* ++ * The expoline macros are used to create thunks in the same format ++ * as gcc generates them. The 'comdat' section flag makes sure that ++ * the various thunks are merged into a single copy. ++ */ ++ .macro __THUNK_PROLOG_NAME name ++ .pushsection .text.\name,"axG",@progbits,\name,comdat ++ .globl \name ++ .hidden \name ++ .type \name,@function ++\name: ++ .cfi_startproc ++ .endm ++ ++ .macro __THUNK_EPILOG ++ .cfi_endproc ++ .popsection ++ .endm ++ ++ .macro __THUNK_PROLOG_BR r1,r2 ++ __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1 ++ .endm ++ ++ .macro __THUNK_PROLOG_BC d0,r1,r2 ++ __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1 ++ .endm ++ ++ .macro __THUNK_BR r1,r2 ++ jg __s390x_indirect_jump_r\r2\()use_r\r1 ++ .endm ++ ++ .macro __THUNK_BC d0,r1,r2 ++ jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1 ++ .endm ++ ++ .macro __THUNK_BRASL r1,r2,r3 ++ brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2 ++ .endm ++ ++ .macro __DECODE_RR expand,reg,ruse ++ .set __decode_fail,1 ++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \reg,%r\r1 ++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \ruse,%r\r2 ++ \expand \r1,\r2 ++ .set __decode_fail,0 ++ .endif ++ .endr ++ .endif ++ .endr ++ .if __decode_fail == 1 ++ .error "__DECODE_RR failed" ++ .endif ++ .endm ++ ++ .macro __DECODE_RRR expand,rsave,rtarget,ruse ++ .set __decode_fail,1 ++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \rsave,%r\r1 ++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \rtarget,%r\r2 ++ .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \ruse,%r\r3 ++ \expand \r1,\r2,\r3 ++ .set __decode_fail,0 ++ .endif ++ .endr ++ .endif ++ .endr ++ .endif ++ .endr ++ .if __decode_fail == 1 ++ .error "__DECODE_RRR failed" ++ .endif ++ .endm ++ ++ .macro __DECODE_DRR expand,disp,reg,ruse ++ .set __decode_fail,1 ++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \reg,%r\r1 ++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ++ .ifc \ruse,%r\r2 ++ \expand \disp,\r1,\r2 ++ .set __decode_fail,0 ++ .endif ++ .endr ++ .endif ++ .endr ++ .if __decode_fail == 1 ++ .error "__DECODE_DRR failed" ++ .endif ++ .endm ++ ++ .macro __THUNK_EX_BR reg,ruse ++#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES ++ exrl 0,555f ++ j . ++#else ++ larl \ruse,555f ++ ex 0,0(\ruse) ++ j . ++#endif ++555: br \reg ++ .endm ++ ++ .macro __THUNK_EX_BC disp,reg,ruse ++#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES ++ exrl 0,556f ++ j . ++#else ++ larl \ruse,556f ++ ex 0,0(\ruse) ++ j . ++#endif ++556: b \disp(\reg) ++ .endm ++ ++ .macro GEN_BR_THUNK reg,ruse=%r1 ++ __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse ++ __THUNK_EX_BR \reg,\ruse ++ __THUNK_EPILOG ++ .endm ++ ++ .macro GEN_B_THUNK disp,reg,ruse=%r1 ++ __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse ++ __THUNK_EX_BC \disp,\reg,\ruse ++ __THUNK_EPILOG ++ .endm ++ ++ .macro BR_EX reg,ruse=%r1 ++557: __DECODE_RR __THUNK_BR,\reg,\ruse ++ .pushsection .s390_indirect_branches,"a",@progbits ++ .long 557b-. ++ .popsection ++ .endm ++ ++ .macro B_EX disp,reg,ruse=%r1 ++558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse ++ .pushsection .s390_indirect_branches,"a",@progbits ++ .long 558b-. ++ .popsection ++ .endm ++ ++ .macro BASR_EX rsave,rtarget,ruse=%r1 ++559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse ++ .pushsection .s390_indirect_branches,"a",@progbits ++ .long 559b-. ++ .popsection ++ .endm ++ ++#else ++ .macro GEN_BR_THUNK reg,ruse=%r1 ++ .endm ++ ++ .macro GEN_B_THUNK disp,reg,ruse=%r1 ++ .endm ++ ++ .macro BR_EX reg,ruse=%r1 ++ br \reg ++ .endm ++ ++ .macro B_EX disp,reg,ruse=%r1 ++ b \disp(\reg) ++ .endm ++ ++ .macro BASR_EX rsave,rtarget,ruse=%r1 ++ basr \rsave,\rtarget ++ .endm ++#endif ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* _ASM_S390_NOSPEC_ASM_H */ +diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile +index 8ccfbf22ecbb..c4d4d4ef5e58 100644 +--- a/arch/s390/kernel/Makefile ++++ b/arch/s390/kernel/Makefile +@@ -49,6 +49,7 @@ obj-y += nospec-branch.o + + extra-y += head.o head64.o vmlinux.lds + ++obj-$(CONFIG_SYSFS) += nospec-sysfs.o + CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE) + + obj-$(CONFIG_MODULES) += s390_ksyms.o module.o +diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S +index 326f717df587..61fca549a93b 100644 +--- a/arch/s390/kernel/base.S ++++ b/arch/s390/kernel/base.S +@@ -8,18 +8,22 @@ + + #include + #include ++#include + #include + #include + ++ GEN_BR_THUNK %r9 ++ GEN_BR_THUNK %r14 ++ + ENTRY(s390_base_mcck_handler) + basr %r13,0 + 0: lg %r15,__LC_PANIC_STACK # load panic stack + aghi %r15,-STACK_FRAME_OVERHEAD + larl %r1,s390_base_mcck_handler_fn +- lg %r1,0(%r1) +- ltgr %r1,%r1 ++ lg %r9,0(%r1) ++ ltgr %r9,%r9 + jz 1f +- basr %r14,%r1 ++ BASR_EX %r14,%r9 + 1: la %r1,4095 + lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) + lpswe __LC_MCK_OLD_PSW +@@ -36,10 +40,10 @@ ENTRY(s390_base_ext_handler) + basr %r13,0 + 0: aghi %r15,-STACK_FRAME_OVERHEAD + larl %r1,s390_base_ext_handler_fn +- lg %r1,0(%r1) +- ltgr %r1,%r1 ++ lg %r9,0(%r1) ++ ltgr %r9,%r9 + jz 1f +- basr %r14,%r1 ++ BASR_EX %r14,%r9 + 1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC + ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit + lpswe __LC_EXT_OLD_PSW +@@ -56,10 +60,10 @@ ENTRY(s390_base_pgm_handler) + basr %r13,0 + 0: aghi %r15,-STACK_FRAME_OVERHEAD + larl %r1,s390_base_pgm_handler_fn +- lg %r1,0(%r1) +- ltgr %r1,%r1 ++ lg %r9,0(%r1) ++ ltgr %r9,%r9 + jz 1f +- basr %r14,%r1 ++ BASR_EX %r14,%r9 + lmg %r0,%r15,__LC_SAVE_AREA_SYNC + lpswe __LC_PGM_OLD_PSW + 1: lpswe disabled_wait_psw-0b(%r13) +@@ -116,7 +120,7 @@ ENTRY(diag308_reset) + larl %r4,.Lcontinue_psw # Restore PSW flags + lpswe 0(%r4) + .Lcontinue: +- br %r14 ++ BR_EX %r14 + .align 16 + .Lrestart_psw: + .long 0x00080000,0x80000000 + .Lrestart_part2 +diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S +index c63730326215..5416d5d68308 100644 +--- a/arch/s390/kernel/entry.S ++++ b/arch/s390/kernel/entry.S +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + __PT_R0 = __PT_GPRS + __PT_R1 = __PT_GPRS + 8 +@@ -225,74 +226,16 @@ _PIF_WORK = (_PIF_PER_TRAP) + .popsection + .endm + +-#ifdef CONFIG_EXPOLINE +- +- .macro GEN_BR_THUNK name,reg,tmp +- .section .text.\name,"axG",@progbits,\name,comdat +- .globl \name +- .hidden \name +- .type \name,@function +-\name: +- .cfi_startproc +-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES +- exrl 0,0f +-#else +- larl \tmp,0f +- ex 0,0(\tmp) +-#endif +- j . +-0: br \reg +- .cfi_endproc +- .endm +- +- GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1 +- GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1 +- GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11 +- +- .macro BASR_R14_R9 +-0: brasl %r14,__s390x_indirect_jump_r1use_r9 +- .pushsection .s390_indirect_branches,"a",@progbits +- .long 0b-. +- .popsection +- .endm +- +- .macro BR_R1USE_R14 +-0: jg __s390x_indirect_jump_r1use_r14 +- .pushsection .s390_indirect_branches,"a",@progbits +- .long 0b-. +- .popsection +- .endm +- +- .macro BR_R11USE_R14 +-0: jg __s390x_indirect_jump_r11use_r14 +- .pushsection .s390_indirect_branches,"a",@progbits +- .long 0b-. +- .popsection +- .endm +- +-#else /* CONFIG_EXPOLINE */ +- +- .macro BASR_R14_R9 +- basr %r14,%r9 +- .endm +- +- .macro BR_R1USE_R14 +- br %r14 +- .endm +- +- .macro BR_R11USE_R14 +- br %r14 +- .endm +- +-#endif /* CONFIG_EXPOLINE */ +- ++ GEN_BR_THUNK %r9 ++ GEN_BR_THUNK %r14 ++ GEN_BR_THUNK %r14,%r11 + + .section .kprobes.text, "ax" + + ENTRY(__bpon) + .globl __bpon + BPON +- BR_R1USE_R14 ++ BR_EX %r14 + + /* + * Scheduler resume function, called by switch_to +@@ -322,7 +265,7 @@ ENTRY(__switch_to) + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP + jz 0f + .insn s,0xb2800000,__LC_LPP # set program parameter +-0: BR_R1USE_R14 ++0: BR_EX %r14 + + .L__critical_start: + +@@ -388,7 +331,7 @@ sie_exit: + xgr %r5,%r5 + lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers + lg %r2,__SF_EMPTY+16(%r15) # return exit reason code +- BR_R1USE_R14 ++ BR_EX %r14 + .Lsie_fault: + lghi %r14,-EFAULT + stg %r14,__SF_EMPTY+16(%r15) # set exit reason code +@@ -445,7 +388,7 @@ ENTRY(system_call) + lgf %r9,0(%r8,%r10) # get system call add. + TSTMSK __TI_flags(%r12),_TIF_TRACE + jnz .Lsysc_tracesys +- BASR_R14_R9 # call sys_xxxx ++ BASR_EX %r14,%r9 # call sys_xxxx + stg %r2,__PT_R2(%r11) # store return value + + .Lsysc_return: +@@ -585,7 +528,7 @@ ENTRY(system_call) + lmg %r3,%r7,__PT_R3(%r11) + stg %r7,STACK_FRAME_OVERHEAD(%r15) + lg %r2,__PT_ORIG_GPR2(%r11) +- BASR_R14_R9 # call sys_xxx ++ BASR_EX %r14,%r9 # call sys_xxx + stg %r2,__PT_R2(%r11) # store return value + .Lsysc_tracenogo: + TSTMSK __TI_flags(%r12),_TIF_TRACE +@@ -609,7 +552,7 @@ ENTRY(ret_from_fork) + lmg %r9,%r10,__PT_R9(%r11) # load gprs + ENTRY(kernel_thread_starter) + la %r2,0(%r10) +- BASR_R14_R9 ++ BASR_EX %r14,%r9 + j .Lsysc_tracenogo + + /* +@@ -685,7 +628,7 @@ ENTRY(pgm_check_handler) + je .Lpgm_return + lgf %r9,0(%r10,%r1) # load address of handler routine + lgr %r2,%r11 # pass pointer to pt_regs +- BASR_R14_R9 # branch to interrupt-handler ++ BASR_EX %r14,%r9 # branch to interrupt-handler + .Lpgm_return: + LOCKDEP_SYS_EXIT + tm __PT_PSW+1(%r11),0x01 # returning to user ? +@@ -962,7 +905,7 @@ ENTRY(psw_idle) + stpt __TIMER_IDLE_ENTER(%r2) + .Lpsw_idle_lpsw: + lpswe __SF_EMPTY(%r15) +- BR_R1USE_R14 ++ BR_EX %r14 + .Lpsw_idle_end: + + /* +@@ -1007,7 +950,7 @@ ENTRY(save_fpu_regs) + .Lsave_fpu_regs_done: + oi __LC_CPU_FLAGS+7,_CIF_FPU + .Lsave_fpu_regs_exit: +- BR_R1USE_R14 ++ BR_EX %r14 + .Lsave_fpu_regs_end: + + /* +@@ -1054,7 +997,7 @@ load_fpu_regs: + .Lload_fpu_regs_done: + ni __LC_CPU_FLAGS+7,255-_CIF_FPU + .Lload_fpu_regs_exit: +- BR_R1USE_R14 ++ BR_EX %r14 + .Lload_fpu_regs_end: + + .L__critical_end: +@@ -1227,7 +1170,7 @@ cleanup_critical: + jl 0f + clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end + jl .Lcleanup_load_fpu_regs +-0: BR_R11USE_R14 ++0: BR_EX %r14 + + .align 8 + .Lcleanup_table: +@@ -1257,7 +1200,7 @@ cleanup_critical: + ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE + lctlg %c1,%c1,__LC_USER_ASCE # load primary asce + larl %r9,sie_exit # skip forward to sie_exit +- BR_R11USE_R14 ++ BR_EX %r14 + #endif + + .Lcleanup_system_call: +@@ -1315,7 +1258,7 @@ cleanup_critical: + stg %r15,56(%r11) # r15 stack pointer + # set new psw address and exit + larl %r9,.Lsysc_do_svc +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + .Lcleanup_system_call_insn: + .quad system_call + .quad .Lsysc_stmg +@@ -1325,7 +1268,7 @@ cleanup_critical: + + .Lcleanup_sysc_tif: + larl %r9,.Lsysc_tif +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + + .Lcleanup_sysc_restore: + # check if stpt has been executed +@@ -1342,14 +1285,14 @@ cleanup_critical: + mvc 0(64,%r11),__PT_R8(%r9) + lmg %r0,%r7,__PT_R0(%r9) + 1: lmg %r8,%r9,__LC_RETURN_PSW +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + .Lcleanup_sysc_restore_insn: + .quad .Lsysc_exit_timer + .quad .Lsysc_done - 4 + + .Lcleanup_io_tif: + larl %r9,.Lio_tif +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + + .Lcleanup_io_restore: + # check if stpt has been executed +@@ -1363,7 +1306,7 @@ cleanup_critical: + mvc 0(64,%r11),__PT_R8(%r9) + lmg %r0,%r7,__PT_R0(%r9) + 1: lmg %r8,%r9,__LC_RETURN_PSW +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + .Lcleanup_io_restore_insn: + .quad .Lio_exit_timer + .quad .Lio_done - 4 +@@ -1415,17 +1358,17 @@ cleanup_critical: + # prepare return psw + nihh %r8,0xfcfd # clear irq & wait state bits + lg %r9,48(%r11) # return from psw_idle +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + .Lcleanup_idle_insn: + .quad .Lpsw_idle_lpsw + + .Lcleanup_save_fpu_regs: + larl %r9,save_fpu_regs +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + + .Lcleanup_load_fpu_regs: + larl %r9,load_fpu_regs +- BR_R11USE_R14 ++ BR_EX %r14,%r11 + + /* + * Integer constants +diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c +index f41d5208aaf7..590e9394b4dd 100644 +--- a/arch/s390/kernel/irq.c ++++ b/arch/s390/kernel/irq.c +@@ -173,10 +173,9 @@ void do_softirq_own_stack(void) + new -= STACK_FRAME_OVERHEAD; + ((struct stack_frame *) new)->back_chain = old; + asm volatile(" la 15,0(%0)\n" +- " basr 14,%2\n" ++ " brasl 14,__do_softirq\n" + " la 15,0(%1)\n" +- : : "a" (new), "a" (old), +- "a" (__do_softirq) ++ : : "a" (new), "a" (old) + : "0", "1", "2", "3", "4", "5", "14", + "cc", "memory" ); + } else { +diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c +index 9f3b5b382743..d5eed651b5ab 100644 +--- a/arch/s390/kernel/nospec-branch.c ++++ b/arch/s390/kernel/nospec-branch.c +@@ -44,24 +44,6 @@ static int __init nospec_report(void) + } + arch_initcall(nospec_report); + +-#ifdef CONFIG_SYSFS +-ssize_t cpu_show_spectre_v1(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- return sprintf(buf, "Mitigation: __user pointer sanitization\n"); +-} +- +-ssize_t cpu_show_spectre_v2(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) +- return sprintf(buf, "Mitigation: execute trampolines\n"); +- if (__test_facility(82, S390_lowcore.alt_stfle_fac_list)) +- return sprintf(buf, "Mitigation: limited branch prediction.\n"); +- return sprintf(buf, "Vulnerable\n"); +-} +-#endif +- + #ifdef CONFIG_EXPOLINE + + int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF); +@@ -112,7 +94,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) + s32 *epo; + + /* Second part of the instruction replace is always a nop */ +- memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4); + for (epo = start; epo < end; epo++) { + instr = (u8 *) epo + *epo; + if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04) +@@ -133,18 +114,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) + br = thunk + (*(int *)(thunk + 2)) * 2; + else + continue; +- if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0) ++ /* Check for unconditional branch 0x07f? or 0x47f???? */ ++ if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0) + continue; ++ ++ memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4); + switch (type) { + case BRCL_EXPOLINE: +- /* brcl to thunk, replace with br + nop */ + insnbuf[0] = br[0]; + insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); ++ if (br[0] == 0x47) { ++ /* brcl to b, replace with bc + nopr */ ++ insnbuf[2] = br[2]; ++ insnbuf[3] = br[3]; ++ } else { ++ /* brcl to br, replace with bcr + nop */ ++ } + break; + case BRASL_EXPOLINE: +- /* brasl to thunk, replace with basr + nop */ +- insnbuf[0] = 0x0d; + insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); ++ if (br[0] == 0x47) { ++ /* brasl to b, replace with bas + nopr */ ++ insnbuf[0] = 0x4d; ++ insnbuf[2] = br[2]; ++ insnbuf[3] = br[3]; ++ } else { ++ /* brasl to br, replace with basr + nop */ ++ insnbuf[0] = 0x0d; ++ } + break; + } + +diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c +new file mode 100644 +index 000000000000..8affad5f18cb +--- /dev/null ++++ b/arch/s390/kernel/nospec-sysfs.c +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++#include ++#include ++ ++ssize_t cpu_show_spectre_v1(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Mitigation: __user pointer sanitization\n"); ++} ++ ++ssize_t cpu_show_spectre_v2(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) ++ return sprintf(buf, "Mitigation: execute trampolines\n"); ++ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list)) ++ return sprintf(buf, "Mitigation: limited branch prediction\n"); ++ return sprintf(buf, "Vulnerable\n"); ++} +diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c +index 3d8da1e742c2..b79d51459cf2 100644 +--- a/arch/s390/kernel/perf_cpum_sf.c ++++ b/arch/s390/kernel/perf_cpum_sf.c +@@ -744,6 +744,10 @@ static int __hw_perf_event_init(struct perf_event *event) + */ + rate = 0; + if (attr->freq) { ++ if (!attr->sample_freq) { ++ err = -EINVAL; ++ goto out; ++ } + rate = freq_to_sample_rate(&si, attr->sample_freq); + rate = hw_limit_rate(&si, rate); + attr->freq = 0; +diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S +index 52aab0bd84f8..6b1b91c17b40 100644 +--- a/arch/s390/kernel/reipl.S ++++ b/arch/s390/kernel/reipl.S +@@ -6,8 +6,11 @@ + + #include + #include ++#include + #include + ++ GEN_BR_THUNK %r14 ++ + # + # store_status + # +@@ -62,7 +65,7 @@ ENTRY(store_status) + st %r3,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 4(%r1) + larl %r2,store_status + stg %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1) +- br %r14 ++ BR_EX %r14 + + .section .bss + .align 8 +diff --git a/arch/s390/kernel/swsusp.S b/arch/s390/kernel/swsusp.S +index 2d6b6e81f812..60a829c77378 100644 +--- a/arch/s390/kernel/swsusp.S ++++ b/arch/s390/kernel/swsusp.S +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -23,6 +24,8 @@ + * (see below) in the resume process. + * This function runs with disabled interrupts. + */ ++ GEN_BR_THUNK %r14 ++ + .section .text + ENTRY(swsusp_arch_suspend) + stmg %r6,%r15,__SF_GPRS(%r15) +@@ -102,7 +105,7 @@ ENTRY(swsusp_arch_suspend) + spx 0x318(%r1) + lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) + lghi %r2,0 +- br %r14 ++ BR_EX %r14 + + /* + * Restore saved memory image to correct place and restore register context. +@@ -196,11 +199,10 @@ pgm_check_entry: + larl %r15,init_thread_union + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) + larl %r2,.Lpanic_string +- larl %r3,_sclp_print_early + lghi %r1,0 + sam31 + sigp %r1,%r0,SIGP_SET_ARCHITECTURE +- basr %r14,%r3 ++ brasl %r14,_sclp_print_early + larl %r3,.Ldisabled_wait_31 + lpsw 0(%r3) + 4: +@@ -266,7 +268,7 @@ restore_registers: + /* Return 0 */ + lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) + lghi %r2,0 +- br %r14 ++ BR_EX %r14 + + .section .data..nosave,"aw",@progbits + .align 8 +diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S +index c6d553e85ab1..16c5998b9792 100644 +--- a/arch/s390/lib/mem.S ++++ b/arch/s390/lib/mem.S +@@ -5,6 +5,9 @@ + */ + + #include ++#include ++ ++ GEN_BR_THUNK %r14 + + /* + * memset implementation +@@ -38,7 +41,7 @@ ENTRY(memset) + .Lmemset_clear_rest: + larl %r3,.Lmemset_xc + ex %r4,0(%r3) +- br %r14 ++ BR_EX %r14 + .Lmemset_fill: + stc %r3,0(%r2) + cghi %r4,1 +@@ -55,7 +58,7 @@ ENTRY(memset) + .Lmemset_fill_rest: + larl %r3,.Lmemset_mvc + ex %r4,0(%r3) +- br %r14 ++ BR_EX %r14 + .Lmemset_xc: + xc 0(1,%r1),0(%r1) + .Lmemset_mvc: +@@ -77,7 +80,7 @@ ENTRY(memcpy) + .Lmemcpy_rest: + larl %r5,.Lmemcpy_mvc + ex %r4,0(%r5) +- br %r14 ++ BR_EX %r14 + .Lmemcpy_loop: + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) +diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S +index a1c917d881ec..fa716f2a95a7 100644 +--- a/arch/s390/net/bpf_jit.S ++++ b/arch/s390/net/bpf_jit.S +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include "bpf_jit.h" + + /* +@@ -53,7 +54,7 @@ ENTRY(sk_load_##NAME##_pos); \ + clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \ + jh sk_load_##NAME##_slow; \ + LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \ +- b OFF_OK(%r6); /* Return */ \ ++ B_EX OFF_OK,%r6; /* Return */ \ + \ + sk_load_##NAME##_slow:; \ + lgr %r2,%r7; /* Arg1 = skb pointer */ \ +@@ -63,11 +64,14 @@ sk_load_##NAME##_slow:; \ + brasl %r14,skb_copy_bits; /* Get data from skb */ \ + LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \ + ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \ +- br %r6; /* Return */ ++ BR_EX %r6; /* Return */ + + sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ + sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ + ++ GEN_BR_THUNK %r6 ++ GEN_B_THUNK OFF_OK,%r6 ++ + /* + * Load 1 byte from SKB (optimized version) + */ +@@ -79,7 +83,7 @@ ENTRY(sk_load_byte_pos) + clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen? + jnl sk_load_byte_slow + llgc %r14,0(%r3,%r12) # Get byte from skb +- b OFF_OK(%r6) # Return OK ++ B_EX OFF_OK,%r6 # Return OK + + sk_load_byte_slow: + lgr %r2,%r7 # Arg1 = skb pointer +@@ -89,7 +93,7 @@ sk_load_byte_slow: + brasl %r14,skb_copy_bits # Get data from skb + llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer + ltgr %r2,%r2 # Set cc to (%r2 != 0) +- br %r6 # Return cc ++ BR_EX %r6 # Return cc + + #define sk_negative_common(NAME, SIZE, LOAD) \ + sk_load_##NAME##_slow_neg:; \ +@@ -103,7 +107,7 @@ sk_load_##NAME##_slow_neg:; \ + jz bpf_error; \ + LOAD %r14,0(%r2); /* Get data from pointer */ \ + xr %r3,%r3; /* Set cc to zero */ \ +- br %r6; /* Return cc */ ++ BR_EX %r6; /* Return cc */ + + sk_negative_common(word, 4, llgf) + sk_negative_common(half, 2, llgh) +@@ -112,4 +116,4 @@ sk_negative_common(byte, 1, llgc) + bpf_error: + # force a return 0 from jit handler + ltgr %r15,%r15 # Set condition code +- br %r6 ++ BR_EX %r6 +diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c +index 1395eeb6005f..a26528afceb2 100644 +--- a/arch/s390/net/bpf_jit_comp.c ++++ b/arch/s390/net/bpf_jit_comp.c +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + #include "bpf_jit.h" + + int bpf_jit_enable __read_mostly; +@@ -41,6 +43,8 @@ struct bpf_jit { + int base_ip; /* Base address for literal pool */ + int ret0_ip; /* Address of return 0 */ + int exit_ip; /* Address of exit */ ++ int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ ++ int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ + int tail_call_start; /* Tail call start offset */ + int labels[1]; /* Labels for local jumps */ + }; +@@ -248,6 +252,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1) + REG_SET_SEEN(b2); \ + }) + ++#define EMIT6_PCREL_RILB(op, b, target) \ ++({ \ ++ int rel = (target - jit->prg) / 2; \ ++ _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \ ++ REG_SET_SEEN(b); \ ++}) ++ ++#define EMIT6_PCREL_RIL(op, target) \ ++({ \ ++ int rel = (target - jit->prg) / 2; \ ++ _EMIT6(op | rel >> 16, rel & 0xffff); \ ++}) ++ + #define _EMIT6_IMM(op, imm) \ + ({ \ + unsigned int __imm = (imm); \ +@@ -475,8 +492,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit) + EMIT4(0xb9040000, REG_2, BPF_REG_0); + /* Restore registers */ + save_restore_regs(jit, REGS_RESTORE); ++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { ++ jit->r14_thunk_ip = jit->prg; ++ /* Generate __s390_indirect_jump_r14 thunk */ ++ if (test_facility(35)) { ++ /* exrl %r0,.+10 */ ++ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10); ++ } else { ++ /* larl %r1,.+14 */ ++ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14); ++ /* ex 0,0(%r1) */ ++ EMIT4_DISP(0x44000000, REG_0, REG_1, 0); ++ } ++ /* j . */ ++ EMIT4_PCREL(0xa7f40000, 0); ++ } + /* br %r14 */ + _EMIT2(0x07fe); ++ ++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable && ++ (jit->seen & SEEN_FUNC)) { ++ jit->r1_thunk_ip = jit->prg; ++ /* Generate __s390_indirect_jump_r1 thunk */ ++ if (test_facility(35)) { ++ /* exrl %r0,.+10 */ ++ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10); ++ /* j . */ ++ EMIT4_PCREL(0xa7f40000, 0); ++ /* br %r1 */ ++ _EMIT2(0x07f1); ++ } else { ++ /* larl %r1,.+14 */ ++ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14); ++ /* ex 0,S390_lowcore.br_r1_tampoline */ ++ EMIT4_DISP(0x44000000, REG_0, REG_0, ++ offsetof(struct _lowcore, br_r1_trampoline)); ++ /* j . */ ++ EMIT4_PCREL(0xa7f40000, 0); ++ } ++ } + } + + /* +@@ -980,8 +1034,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i + /* lg %w1,(%l) */ + EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L, + EMIT_CONST_U64(func)); +- /* basr %r14,%w1 */ +- EMIT2(0x0d00, REG_14, REG_W1); ++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { ++ /* brasl %r14,__s390_indirect_jump_r1 */ ++ EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip); ++ } else { ++ /* basr %r14,%w1 */ ++ EMIT2(0x0d00, REG_14, REG_W1); ++ } + /* lgr %b0,%r2: load return value into %b0 */ + EMIT4(0xb9040000, BPF_REG_0, REG_2); + if (bpf_helper_changes_skb_data((void *)func)) { +diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h +index 7be39a646fbd..e05187d26d76 100644 +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -10,20 +10,11 @@ + /* XXX: UP variants, fix for SH-4A and SMP.. */ + #include + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h +index 4e899b0dabf7..1cfd89d92208 100644 +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "memory") + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tem; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h +index 1a6ef1b69cb1..d96d9dab5c0b 100644 +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #endif + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int uninitialized_var(val), ret; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + /* The 32-bit futex code makes this assumption, so validate it here. */ + BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int)); + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (val == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (val != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (val < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (val >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (val <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (val > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 583d539a4197..2bc6651791cc 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -364,7 +364,8 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom) + if (status != EFI_SUCCESS) + goto free_struct; + +- memcpy(rom->romdata, pci->romimage, pci->romsize); ++ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage, ++ pci->romsize); + return status; + + free_struct: +@@ -470,7 +471,8 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom) + if (status != EFI_SUCCESS) + goto free_struct; + +- memcpy(rom->romdata, pci->romimage, pci->romsize); ++ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage, ++ pci->romsize); + return status; + + free_struct: +diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h +index b4c1f5453436..f4dc9b63bdda 100644 +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "r" (oparg), "i" (-EFAULT), "1" (0)) + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tem; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c +index 469b23d6acc2..fd7e9937ddd6 100644 +--- a/arch/x86/kernel/machine_kexec_32.c ++++ b/arch/x86/kernel/machine_kexec_32.c +@@ -71,12 +71,17 @@ static void load_segments(void) + static void machine_kexec_free_page_tables(struct kimage *image) + { + free_page((unsigned long)image->arch.pgd); ++ image->arch.pgd = NULL; + #ifdef CONFIG_X86_PAE + free_page((unsigned long)image->arch.pmd0); ++ image->arch.pmd0 = NULL; + free_page((unsigned long)image->arch.pmd1); ++ image->arch.pmd1 = NULL; + #endif + free_page((unsigned long)image->arch.pte0); ++ image->arch.pte0 = NULL; + free_page((unsigned long)image->arch.pte1); ++ image->arch.pte1 = NULL; + } + + static int machine_kexec_alloc_page_tables(struct kimage *image) +@@ -93,7 +98,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image) + !image->arch.pmd0 || !image->arch.pmd1 || + #endif + !image->arch.pte0 || !image->arch.pte1) { +- machine_kexec_free_page_tables(image); + return -ENOMEM; + } + return 0; +diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c +index ca6e65250b1a..13d6b8ac0b0b 100644 +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -37,8 +37,11 @@ static struct kexec_file_ops *kexec_file_loaders[] = { + static void free_transition_pgtable(struct kimage *image) + { + free_page((unsigned long)image->arch.pud); ++ image->arch.pud = NULL; + free_page((unsigned long)image->arch.pmd); ++ image->arch.pmd = NULL; + free_page((unsigned long)image->arch.pte); ++ image->arch.pte = NULL; + } + + static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) +@@ -79,7 +82,6 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) + set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); + return 0; + err: +- free_transition_pgtable(image); + return result; + } + +diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c +index 63146c378f1e..2b05f681a1fd 100644 +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1316,8 +1316,6 @@ void xen_flush_tlb_all(void) + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb_all(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +@@ -1335,8 +1333,6 @@ static void xen_flush_tlb(void) + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h +index 72bfc1cbc2b5..5bfbc1c401d4 100644 +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "memory") + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + #if !XCHAL_HAVE_S32C1I + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (ret) +- return ret; ++ if (!ret) ++ *oval = oldval; + +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: return (oldval == cmparg); +- case FUTEX_OP_CMP_NE: return (oldval != cmparg); +- case FUTEX_OP_CMP_LT: return (oldval < cmparg); +- case FUTEX_OP_CMP_GE: return (oldval >= cmparg); +- case FUTEX_OP_CMP_LE: return (oldval <= cmparg); +- case FUTEX_OP_CMP_GT: return (oldval > cmparg); +- } +- +- return -ENOSYS; ++ return ret; + } + + static inline int +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index 7ff8b15a3422..88728d997088 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -1361,6 +1361,11 @@ static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; } + static inline bool intel_pstate_has_acpi_ppc(void) { return false; } + #endif /* CONFIG_ACPI */ + ++static const struct x86_cpu_id hwp_support_ids[] __initconst = { ++ { X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP }, ++ {} ++}; ++ + static int __init intel_pstate_init(void) + { + int cpu, rc = 0; +@@ -1370,17 +1375,16 @@ static int __init intel_pstate_init(void) + if (no_load) + return -ENODEV; + ++ if (x86_match_cpu(hwp_support_ids) && !no_hwp) { ++ copy_cpu_funcs(&core_params.funcs); ++ hwp_active++; ++ goto hwp_cpu_matched; ++ } ++ + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + +- /* +- * The Intel pstate driver will be ignored if the platform +- * firmware has its own power management modes. +- */ +- if (intel_pstate_platform_pwr_mgmt_exists()) +- return -ENODEV; +- + cpu_def = (struct cpu_defaults *)id->driver_data; + + copy_pid_params(&cpu_def->pid_policy); +@@ -1389,17 +1393,20 @@ static int __init intel_pstate_init(void) + if (intel_pstate_msrs_not_valid()) + return -ENODEV; + ++hwp_cpu_matched: ++ /* ++ * The Intel pstate driver will be ignored if the platform ++ * firmware has its own power management modes. ++ */ ++ if (intel_pstate_platform_pwr_mgmt_exists()) ++ return -ENODEV; ++ + pr_info("Intel P-state driver initializing.\n"); + + all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); + if (!all_cpu_data) + return -ENOMEM; + +- if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) { +- pr_info("intel_pstate: HWP enabled\n"); +- hwp_active++; +- } +- + if (!hwp_active && hwp_only) + goto out; + +@@ -1410,6 +1417,9 @@ static int __init intel_pstate_init(void) + intel_pstate_debug_expose_params(); + intel_pstate_sysfs_expose_params(); + ++ if (hwp_active) ++ pr_info("intel_pstate: HWP enabled\n"); ++ + return rc; + out: + get_online_cpus(); +diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c +index c4b0ef65988c..57e6c45724e7 100644 +--- a/drivers/cpufreq/powernv-cpufreq.c ++++ b/drivers/cpufreq/powernv-cpufreq.c +@@ -592,7 +592,7 @@ static int __init powernv_cpufreq_init(void) + int rc = 0; + + /* Don't probe on pseries (guest) platforms */ +- if (!firmware_has_feature(FW_FEATURE_OPALv3)) ++ if (!firmware_has_feature(FW_FEATURE_OPAL)) + return -ENODEV; + + /* Discover pstates from device tree and init */ +diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c +index 344058f8501a..d5657d50ac40 100644 +--- a/drivers/cpuidle/coupled.c ++++ b/drivers/cpuidle/coupled.c +@@ -119,7 +119,6 @@ struct cpuidle_coupled { + + #define CPUIDLE_COUPLED_NOT_IDLE (-1) + +-static DEFINE_MUTEX(cpuidle_coupled_lock); + static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb); + + /* +diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c +index d5c5a476360f..c44a843cb405 100644 +--- a/drivers/cpuidle/cpuidle-powernv.c ++++ b/drivers/cpuidle/cpuidle-powernv.c +@@ -282,7 +282,7 @@ static int powernv_idle_probe(void) + if (cpuidle_disable != IDLE_NO_OVERRIDE) + return -ENODEV; + +- if (firmware_has_feature(FW_FEATURE_OPALv3)) { ++ if (firmware_has_feature(FW_FEATURE_OPAL)) { + cpuidle_state_table = powernv_states; + /* Device tree can indicate more idle states */ + max_idle_state = powernv_add_idle_states(); +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index 2a8122444614..9ba4aaa9f755 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -200,6 +200,48 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on) + return 0; + } + ++static void gpio_rcar_irq_bus_lock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, ++ gpio_chip); ++ ++ pm_runtime_get_sync(&p->pdev->dev); ++} ++ ++static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, ++ gpio_chip); ++ ++ pm_runtime_put(&p->pdev->dev); ++} ++ ++ ++static int gpio_rcar_irq_request_resources(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, ++ gpio_chip); ++ int error; ++ ++ error = pm_runtime_get_sync(&p->pdev->dev); ++ if (error < 0) ++ return error; ++ ++ return 0; ++} ++ ++static void gpio_rcar_irq_release_resources(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, ++ gpio_chip); ++ ++ pm_runtime_put(&p->pdev->dev); ++} ++ + static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) + { + struct gpio_rcar_priv *p = dev_id; +@@ -460,6 +502,10 @@ static int gpio_rcar_probe(struct platform_device *pdev) + irq_chip->irq_unmask = gpio_rcar_irq_enable; + irq_chip->irq_set_type = gpio_rcar_irq_set_type; + irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; ++ irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock; ++ irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock; ++ irq_chip->irq_request_resources = gpio_rcar_irq_request_resources; ++ irq_chip->irq_release_resources = gpio_rcar_irq_release_resources; + irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; + + ret = gpiochip_add(gpio_chip); +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index bb9e9fc45e1b..82d23bd3a742 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -453,7 +453,7 @@ static void rlb_update_client(struct rlb_client_info *client_info) + { + int i; + +- if (!client_info->slave) ++ if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst)) + return; + + for (i = 0; i < RLB_ARP_BURST_SIZE; i++) { +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 3bba92fc9c1a..1325825d5225 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -8722,14 +8722,15 @@ static void tg3_free_consistent(struct tg3 *tp) + tg3_mem_rx_release(tp); + tg3_mem_tx_release(tp); + +- /* Protect tg3_get_stats64() from reading freed tp->hw_stats. */ +- tg3_full_lock(tp, 0); ++ /* tp->hw_stats can be referenced safely: ++ * 1. under rtnl_lock ++ * 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set. ++ */ + if (tp->hw_stats) { + dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), + tp->hw_stats, tp->stats_mapping); + tp->hw_stats = NULL; + } +- tg3_full_unlock(tp); + } + + /* +@@ -14163,7 +14164,7 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, + struct tg3 *tp = netdev_priv(dev); + + spin_lock_bh(&tp->lock); +- if (!tp->hw_stats) { ++ if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) { + *stats = tp->net_stats_prev; + spin_unlock_bh(&tp->lock); + return stats; +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +index ddb5541882f5..bcfac000199e 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +@@ -967,6 +967,22 @@ static int mlx4_en_set_coalesce(struct net_device *dev, + if (!coal->tx_max_coalesced_frames_irq) + return -EINVAL; + ++ if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) { ++ netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n", ++ __func__, MLX4_EN_MAX_COAL_TIME); ++ return -ERANGE; ++ } ++ ++ if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS || ++ coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) { ++ netdev_info(dev, "%s: maximum coalesced frames supported is %d\n", ++ __func__, MLX4_EN_MAX_COAL_PKTS); ++ return -ERANGE; ++ } ++ + priv->rx_frames = (coal->rx_max_coalesced_frames == + MLX4_EN_AUTO_CONF) ? + MLX4_EN_RX_COAL_TARGET : +diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +index 10aa6544cf4d..607daaffae98 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h ++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +@@ -140,6 +140,9 @@ enum { + #define MLX4_EN_TX_COAL_PKTS 16 + #define MLX4_EN_TX_COAL_TIME 0x10 + ++#define MLX4_EN_MAX_COAL_PKTS U16_MAX ++#define MLX4_EN_MAX_COAL_TIME U16_MAX ++ + #define MLX4_EN_RX_RATE_LOW 400000 + #define MLX4_EN_RX_COAL_TIME_LOW 0 + #define MLX4_EN_RX_RATE_HIGH 450000 +@@ -518,8 +521,8 @@ struct mlx4_en_priv { + u16 rx_usecs_low; + u32 pkt_rate_high; + u16 rx_usecs_high; +- u16 sample_interval; +- u16 adaptive_rx_coal; ++ u32 sample_interval; ++ u32 adaptive_rx_coal; + u32 msg_enable; + u32 loopback_ok; + u32 validate_loopback; +diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c +index ef668d300800..d987d571fdd6 100644 +--- a/drivers/net/ethernet/realtek/8139too.c ++++ b/drivers/net/ethernet/realtek/8139too.c +@@ -2229,7 +2229,7 @@ static void rtl8139_poll_controller(struct net_device *dev) + struct rtl8139_private *tp = netdev_priv(dev); + const int irq = tp->pci_dev->irq; + +- disable_irq(irq); ++ disable_irq_nosync(irq); + rtl8139_interrupt(irq, dev); + enable_irq(irq); + } +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index a82c89af7124..8b4069ea52ce 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -4832,6 +4832,9 @@ static void rtl_pll_power_down(struct rtl8169_private *tp) + static void rtl_pll_power_up(struct rtl8169_private *tp) + { + rtl_generic_op(tp, tp->pll_power_ops.up); ++ ++ /* give MAC/PHY some time to resume */ ++ msleep(20); + } + + static void rtl_init_pll_power_ops(struct rtl8169_private *tp) +diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c +index ab6051a43134..ccebf89aa1e4 100644 +--- a/drivers/net/ethernet/sun/niu.c ++++ b/drivers/net/ethernet/sun/niu.c +@@ -3442,7 +3442,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, + + len = (val & RCR_ENTRY_L2_LEN) >> + RCR_ENTRY_L2_LEN_SHIFT; +- len -= ETH_FCS_LEN; ++ append_size = len + ETH_HLEN + ETH_FCS_LEN; + + addr = (val & RCR_ENTRY_PKT_BUF_ADDR) << + RCR_ENTRY_PKT_BUF_ADDR_SHIFT; +@@ -3452,7 +3452,6 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, + RCR_ENTRY_PKTBUFSZ_SHIFT]; + + off = addr & ~PAGE_MASK; +- append_size = rcr_size; + if (num_rcr == 1) { + int ptype; + +@@ -3465,7 +3464,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, + else + skb_checksum_none_assert(skb); + } else if (!(val & RCR_ENTRY_MULTI)) +- append_size = len - skb->len; ++ append_size = append_size - skb->len; + + niu_rx_skb_append(skb, page, off, append_size, rcr_size); + if ((page->index + rp->rbr_block_size) - rcr_size == addr) { +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index a6f0a8f516d6..8aaa09b3c753 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -855,6 +855,18 @@ static int qmi_wwan_probe(struct usb_interface *intf, + id->driver_info = (unsigned long)&qmi_wwan_info; + } + ++ /* There are devices where the same interface number can be ++ * configured as different functions. We should only bind to ++ * vendor specific functions when matching on interface number ++ */ ++ if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER && ++ desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) { ++ dev_dbg(&intf->dev, ++ "Rejecting interface number match for class %02x\n", ++ desc->bInterfaceClass); ++ return -ENODEV; ++ } ++ + /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */ + if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) { + dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n"); +diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c +index 48b3866a9ded..35286907c636 100644 +--- a/drivers/s390/cio/qdio_setup.c ++++ b/drivers/s390/cio/qdio_setup.c +@@ -140,7 +140,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) + int i; + + for (i = 0; i < nr_queues; i++) { +- q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); ++ q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); + if (!q) + return -ENOMEM; + +@@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) + { + struct ciw *ciw; + struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; +- int rc; + + memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); + memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); +@@ -493,16 +492,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data) + ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); + if (!ciw) { + DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); +- rc = -EINVAL; +- goto out_err; ++ return -EINVAL; + } + irq_ptr->equeue = *ciw; + + ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); + if (!ciw) { + DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); +- rc = -EINVAL; +- goto out_err; ++ return -EINVAL; + } + irq_ptr->aqueue = *ciw; + +@@ -510,9 +507,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) + irq_ptr->orig_handler = init_data->cdev->handler; + init_data->cdev->handler = qdio_int_handler; + return 0; +-out_err: +- qdio_release_memory(irq_ptr); +- return rc; + } + + void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, +diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c +index 34367d172961..4534a7ce77b8 100644 +--- a/drivers/s390/scsi/zfcp_dbf.c ++++ b/drivers/s390/scsi/zfcp_dbf.c +@@ -3,7 +3,7 @@ + * + * Debug traces for zfcp. + * +- * Copyright IBM Corp. 2002, 2017 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #define KMSG_COMPONENT "zfcp" +@@ -287,6 +287,27 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, + spin_unlock_irqrestore(&dbf->rec_lock, flags); + } + ++/** ++ * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock ++ * @tag: identifier for event ++ * @adapter: adapter on which the erp_action should run ++ * @port: remote port involved in the erp_action ++ * @sdev: scsi device involved in the erp_action ++ * @want: wanted erp_action ++ * @need: required erp_action ++ * ++ * The adapter->erp_lock must not be held. ++ */ ++void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, ++ struct zfcp_port *port, struct scsi_device *sdev, ++ u8 want, u8 need) ++{ ++ unsigned long flags; ++ ++ read_lock_irqsave(&adapter->erp_lock, flags); ++ zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need); ++ read_unlock_irqrestore(&adapter->erp_lock, flags); ++} + + /** + * zfcp_dbf_rec_run_lvl - trace event related to running recovery +diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h +index 21c8c689b02b..7a7984a50683 100644 +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -3,7 +3,7 @@ + * + * External function declarations. + * +- * Copyright IBM Corp. 2002, 2016 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #ifndef ZFCP_EXT_H +@@ -34,6 +34,9 @@ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); + extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); + extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, + struct zfcp_port *, struct scsi_device *, u8, u8); ++extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, ++ struct zfcp_port *port, ++ struct scsi_device *sdev, u8 want, u8 need); + extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); + extern void zfcp_dbf_rec_run_lvl(int level, char *tag, + struct zfcp_erp_action *erp); +diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c +index a9b8104b982e..bb99db2948ab 100644 +--- a/drivers/s390/scsi/zfcp_scsi.c ++++ b/drivers/s390/scsi/zfcp_scsi.c +@@ -3,7 +3,7 @@ + * + * Interface to Linux SCSI midlayer. + * +- * Copyright IBM Corp. 2002, 2017 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #define KMSG_COMPONENT "zfcp" +@@ -616,9 +616,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) + ids.port_id = port->d_id; + ids.roles = FC_RPORT_ROLE_FCP_TARGET; + +- zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); ++ zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); + rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); + if (!rport) { + dev_err(&port->adapter->ccw_device->dev, +@@ -640,9 +640,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) + struct fc_rport *rport = port->rport; + + if (rport) { +- zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); ++ zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); + fc_remote_port_delete(rport); + port->rport = NULL; + } +diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c +index 519dac4e341e..9a8c2f97ed70 100644 +--- a/drivers/scsi/libsas/sas_scsi_host.c ++++ b/drivers/scsi/libsas/sas_scsi_host.c +@@ -222,6 +222,7 @@ out_done: + static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + { + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); ++ struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_task *task = TO_SAS_TASK(cmd); + + /* At this point, we only get called following an actual abort +@@ -230,6 +231,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + */ + sas_end_task(cmd, task); + ++ if (dev_is_sata(dev)) { ++ /* defer commands to libata so that libata EH can ++ * handle ata qcs correctly ++ */ ++ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); ++ return; ++ } ++ + /* now finish the command and move it on to the error + * handler done list, this also takes it off the + * error handler pending list. +@@ -237,22 +246,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); + } + +-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) +-{ +- struct domain_device *dev = cmd_to_domain_dev(cmd); +- struct sas_ha_struct *ha = dev->port->ha; +- struct sas_task *task = TO_SAS_TASK(cmd); +- +- if (!dev_is_sata(dev)) { +- sas_eh_finish_cmd(cmd); +- return; +- } +- +- /* report the timeout to libata */ +- sas_end_task(cmd, task); +- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); +-} +- + static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) + { + struct scsi_cmnd *cmd, *n; +@@ -260,7 +253,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd + list_for_each_entry_safe(cmd, n, error_q, eh_entry) { + if (cmd->device->sdev_target == my_cmd->device->sdev_target && + cmd->device->lun == my_cmd->device->lun) +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + } + } + +@@ -622,12 +615,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * + case TASK_IS_DONE: + SAS_DPRINTK("%s: task 0x%p is done\n", __func__, + task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_ABORTED: + SAS_DPRINTK("%s: task 0x%p is aborted\n", + __func__, task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_AT_LU: + SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); +@@ -638,7 +631,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * + "recovered\n", + SAS_ADDR(task->dev), + cmd->device->lun); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + sas_scsi_clear_queue_lu(work_q, cmd); + goto Again; + } +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index cb19c9ad1b57..841f3fbec77c 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1903,7 +1903,7 @@ retry: + num = (rem_sz > scatter_elem_sz_prev) ? + scatter_elem_sz_prev : rem_sz; + +- schp->pages[k] = alloc_pages(gfp_mask, order); ++ schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order); + if (!schp->pages[k]) + goto out; + +diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h +index 58efa98313aa..24c07fea9de2 100644 +--- a/drivers/spi/spi-pxa2xx.h ++++ b/drivers/spi/spi-pxa2xx.h +@@ -38,7 +38,7 @@ struct driver_data { + + /* SSP register addresses */ + void __iomem *ioaddr; +- u32 ssdr_physical; ++ phys_addr_t ssdr_physical; + + /* SSP masks*/ + u32 dma_cr1; +diff --git a/drivers/usb/usbip/stub.h b/drivers/usb/usbip/stub.h +index 266e2b0ce9a8..47ccd73a74f0 100644 +--- a/drivers/usb/usbip/stub.h ++++ b/drivers/usb/usbip/stub.h +@@ -88,6 +88,7 @@ struct bus_id_priv { + struct stub_device *sdev; + struct usb_device *udev; + char shutdown_busid; ++ spinlock_t busid_lock; + }; + + /* stub_priv is allocated from stub_priv_cache */ +@@ -98,6 +99,7 @@ extern struct usb_device_driver stub_driver; + + /* stub_main.c */ + struct bus_id_priv *get_busid_priv(const char *busid); ++void put_busid_priv(struct bus_id_priv *bid); + int del_match_busid(char *busid); + void stub_device_cleanup_urbs(struct stub_device *sdev); + +diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c +index 0931f3271119..4aad99a59958 100644 +--- a/drivers/usb/usbip/stub_dev.c ++++ b/drivers/usb/usbip/stub_dev.c +@@ -314,9 +314,9 @@ static int stub_probe(struct usb_device *udev) + struct stub_device *sdev = NULL; + const char *udev_busid = dev_name(&udev->dev); + struct bus_id_priv *busid_priv; +- int rc; ++ int rc = 0; + +- dev_dbg(&udev->dev, "Enter\n"); ++ dev_dbg(&udev->dev, "Enter probe\n"); + + /* check we should claim or not by busid_table */ + busid_priv = get_busid_priv(udev_busid); +@@ -331,13 +331,15 @@ static int stub_probe(struct usb_device *udev) + * other matched drivers by the driver core. + * See driver_probe_device() in driver/base/dd.c + */ +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { + dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n", + udev_busid); +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { +@@ -345,13 +347,16 @@ static int stub_probe(struct usb_device *udev) + "%s is attached on vhci_hcd... skip!\n", + udev_busid); + +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + /* ok, this is my device */ + sdev = stub_device_alloc(udev); +- if (!sdev) +- return -ENOMEM; ++ if (!sdev) { ++ rc = -ENOMEM; ++ goto call_put_busid_priv; ++ } + + dev_info(&udev->dev, + "usbip-host: register new device (bus %u dev %u)\n", +@@ -383,7 +388,9 @@ static int stub_probe(struct usb_device *udev) + } + busid_priv->status = STUB_BUSID_ALLOC; + +- return 0; ++ rc = 0; ++ goto call_put_busid_priv; ++ + err_files: + usb_hub_release_port(udev->parent, udev->portnum, + (struct usb_dev_state *) udev); +@@ -394,6 +401,9 @@ err_port: + + busid_priv->sdev = NULL; + stub_device_free(sdev); ++ ++call_put_busid_priv: ++ put_busid_priv(busid_priv); + return rc; + } + +@@ -419,7 +429,7 @@ static void stub_disconnect(struct usb_device *udev) + struct bus_id_priv *busid_priv; + int rc; + +- dev_dbg(&udev->dev, "Enter\n"); ++ dev_dbg(&udev->dev, "Enter disconnect\n"); + + busid_priv = get_busid_priv(udev_busid); + if (!busid_priv) { +@@ -432,7 +442,7 @@ static void stub_disconnect(struct usb_device *udev) + /* get stub_device */ + if (!sdev) { + dev_err(&udev->dev, "could not get device"); +- return; ++ goto call_put_busid_priv; + } + + dev_set_drvdata(&udev->dev, NULL); +@@ -447,12 +457,12 @@ static void stub_disconnect(struct usb_device *udev) + (struct usb_dev_state *) udev); + if (rc) { + dev_dbg(&udev->dev, "unable to release port\n"); +- return; ++ goto call_put_busid_priv; + } + + /* If usb reset is called from event handler */ + if (busid_priv->sdev->ud.eh == current) +- return; ++ goto call_put_busid_priv; + + /* shutdown the current connection */ + shutdown_busid(busid_priv); +@@ -463,12 +473,11 @@ static void stub_disconnect(struct usb_device *udev) + busid_priv->sdev = NULL; + stub_device_free(sdev); + +- if (busid_priv->status == STUB_BUSID_ALLOC) { ++ if (busid_priv->status == STUB_BUSID_ALLOC) + busid_priv->status = STUB_BUSID_ADDED; +- } else { +- busid_priv->status = STUB_BUSID_OTHER; +- del_match_busid((char *)udev_busid); +- } ++ ++call_put_busid_priv: ++ put_busid_priv(busid_priv); + } + + #ifdef CONFIG_PM +diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c +index f761e02e75c9..fa90496ca7a8 100644 +--- a/drivers/usb/usbip/stub_main.c ++++ b/drivers/usb/usbip/stub_main.c +@@ -28,6 +28,7 @@ + #define DRIVER_DESC "USB/IP Host Driver" + + struct kmem_cache *stub_priv_cache; ++ + /* + * busid_tables defines matching busids that usbip can grab. A user can change + * dynamically what device is locally used and what device is exported to a +@@ -39,6 +40,8 @@ static spinlock_t busid_table_lock; + + static void init_busid_table(void) + { ++ int i; ++ + /* + * This also sets the bus_table[i].status to + * STUB_BUSID_OTHER, which is 0. +@@ -46,6 +49,9 @@ static void init_busid_table(void) + memset(busid_table, 0, sizeof(busid_table)); + + spin_lock_init(&busid_table_lock); ++ ++ for (i = 0; i < MAX_BUSID; i++) ++ spin_lock_init(&busid_table[i].busid_lock); + } + + /* +@@ -57,15 +63,20 @@ static int get_busid_idx(const char *busid) + int i; + int idx = -1; + +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (busid_table[i].name[0]) + if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { + idx = i; ++ spin_unlock(&busid_table[i].busid_lock); + break; + } ++ spin_unlock(&busid_table[i].busid_lock); ++ } + return idx; + } + ++/* Returns holding busid_lock. Should call put_busid_priv() to unlock */ + struct bus_id_priv *get_busid_priv(const char *busid) + { + int idx; +@@ -73,13 +84,22 @@ struct bus_id_priv *get_busid_priv(const char *busid) + + spin_lock(&busid_table_lock); + idx = get_busid_idx(busid); +- if (idx >= 0) ++ if (idx >= 0) { + bid = &(busid_table[idx]); ++ /* get busid_lock before returning */ ++ spin_lock(&bid->busid_lock); ++ } + spin_unlock(&busid_table_lock); + + return bid; + } + ++void put_busid_priv(struct bus_id_priv *bid) ++{ ++ if (bid) ++ spin_unlock(&bid->busid_lock); ++} ++ + static int add_match_busid(char *busid) + { + int i; +@@ -92,15 +112,19 @@ static int add_match_busid(char *busid) + goto out; + } + +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (!busid_table[i].name[0]) { + strlcpy(busid_table[i].name, busid, BUSID_SIZE); + if ((busid_table[i].status != STUB_BUSID_ALLOC) && + (busid_table[i].status != STUB_BUSID_REMOV)) + busid_table[i].status = STUB_BUSID_ADDED; + ret = 0; ++ spin_unlock(&busid_table[i].busid_lock); + break; + } ++ spin_unlock(&busid_table[i].busid_lock); ++ } + + out: + spin_unlock(&busid_table_lock); +@@ -121,6 +145,8 @@ int del_match_busid(char *busid) + /* found */ + ret = 0; + ++ spin_lock(&busid_table[idx].busid_lock); ++ + if (busid_table[idx].status == STUB_BUSID_OTHER) + memset(busid_table[idx].name, 0, BUSID_SIZE); + +@@ -128,6 +154,7 @@ int del_match_busid(char *busid) + (busid_table[idx].status != STUB_BUSID_ADDED)) + busid_table[idx].status = STUB_BUSID_REMOV; + ++ spin_unlock(&busid_table[idx].busid_lock); + out: + spin_unlock(&busid_table_lock); + +@@ -140,9 +167,12 @@ static ssize_t show_match_busid(struct device_driver *drv, char *buf) + char *out = buf; + + spin_lock(&busid_table_lock); +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (busid_table[i].name[0]) + out += sprintf(out, "%s ", busid_table[i].name); ++ spin_unlock(&busid_table[i].busid_lock); ++ } + spin_unlock(&busid_table_lock); + out += sprintf(out, "\n"); + +@@ -184,6 +214,51 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf, + static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid, + store_match_busid); + ++static int do_rebind(char *busid, struct bus_id_priv *busid_priv) ++{ ++ int ret; ++ ++ /* device_attach() callers should hold parent lock for USB */ ++ if (busid_priv->udev->dev.parent) ++ device_lock(busid_priv->udev->dev.parent); ++ ret = device_attach(&busid_priv->udev->dev); ++ if (busid_priv->udev->dev.parent) ++ device_unlock(busid_priv->udev->dev.parent); ++ if (ret < 0) { ++ dev_err(&busid_priv->udev->dev, "rebind failed\n"); ++ return ret; ++ } ++ return 0; ++} ++ ++static void stub_device_rebind(void) ++{ ++#if IS_MODULE(CONFIG_USBIP_HOST) ++ struct bus_id_priv *busid_priv; ++ int i; ++ ++ /* update status to STUB_BUSID_OTHER so probe ignores the device */ ++ spin_lock(&busid_table_lock); ++ for (i = 0; i < MAX_BUSID; i++) { ++ if (busid_table[i].name[0] && ++ busid_table[i].shutdown_busid) { ++ busid_priv = &(busid_table[i]); ++ busid_priv->status = STUB_BUSID_OTHER; ++ } ++ } ++ spin_unlock(&busid_table_lock); ++ ++ /* now run rebind - no need to hold locks. driver files are removed */ ++ for (i = 0; i < MAX_BUSID; i++) { ++ if (busid_table[i].name[0] && ++ busid_table[i].shutdown_busid) { ++ busid_priv = &(busid_table[i]); ++ do_rebind(busid_table[i].name, busid_priv); ++ } ++ } ++#endif ++} ++ + static ssize_t rebind_store(struct device_driver *dev, const char *buf, + size_t count) + { +@@ -201,16 +276,17 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf, + if (!bid) + return -ENODEV; + +- /* device_attach() callers should hold parent lock for USB */ +- if (bid->udev->dev.parent) +- device_lock(bid->udev->dev.parent); +- ret = device_attach(&bid->udev->dev); +- if (bid->udev->dev.parent) +- device_unlock(bid->udev->dev.parent); +- if (ret < 0) { +- dev_err(&bid->udev->dev, "rebind failed\n"); ++ /* mark the device for deletion so probe ignores it during rescan */ ++ bid->status = STUB_BUSID_OTHER; ++ /* release the busid lock */ ++ put_busid_priv(bid); ++ ++ ret = do_rebind((char *) buf, bid); ++ if (ret < 0) + return ret; +- } ++ ++ /* delete device from busid_table */ ++ del_match_busid((char *) buf); + + return count; + } +@@ -333,6 +409,9 @@ static void __exit usbip_host_exit(void) + */ + usb_deregister_device_driver(&stub_driver); + ++ /* initiate scan to attach devices */ ++ stub_device_rebind(); ++ + kmem_cache_destroy(stub_priv_cache); + } + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 0f2b7c622ce3..e2f5be261532 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -2497,10 +2497,8 @@ read_block_for_search(struct btrfs_trans_handle *trans, + if (p->reada) + reada_for_search(root, p, level, slot, key->objectid); + +- btrfs_release_path(p); +- + ret = -EAGAIN; +- tmp = read_tree_block(root, blocknr, 0); ++ tmp = read_tree_block(root, blocknr, gen); + if (!IS_ERR(tmp)) { + /* + * If the read above didn't mark this buffer up to date, +@@ -2512,6 +2510,8 @@ read_block_for_search(struct btrfs_trans_handle *trans, + ret = -EIO; + free_extent_buffer(tmp); + } ++ ++ btrfs_release_path(p); + return ret; + } + +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index d6359af9789d..6ba022ed4a52 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -4568,6 +4568,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, + struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; + u64 logged_isize = 0; + bool need_log_inode_item = true; ++ bool xattrs_logged = false; + + path = btrfs_alloc_path(); + if (!path) +@@ -4808,6 +4809,7 @@ next_slot: + err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path); + if (err) + goto out_unlock; ++ xattrs_logged = true; + if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) { + btrfs_release_path(path); + btrfs_release_path(dst_path); +@@ -4820,6 +4822,11 @@ log_extents: + btrfs_release_path(dst_path); + if (need_log_inode_item) { + err = log_inode_item(trans, log, dst_path, inode); ++ if (!err && !xattrs_logged) { ++ err = btrfs_log_all_xattrs(trans, root, inode, path, ++ dst_path); ++ btrfs_release_path(path); ++ } + if (err) + goto out_unlock; + } +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 6d874b1cd53c..ed75d70b4bc2 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -3850,6 +3850,15 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) + return 0; + } + ++ /* ++ * A ro->rw remount sequence should continue with the paused balance ++ * regardless of who pauses it, system or the user as of now, so set ++ * the resume flag. ++ */ ++ spin_lock(&fs_info->balance_lock); ++ fs_info->balance_ctl->flags |= BTRFS_BALANCE_RESUME; ++ spin_unlock(&fs_info->balance_lock); ++ + tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); + return PTR_ERR_OR_ZERO(tsk); + } +diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c +index 0aa9bf6e6e53..f600c43f0047 100644 +--- a/fs/ext2/inode.c ++++ b/fs/ext2/inode.c +@@ -1175,21 +1175,11 @@ do_indirects: + + static void ext2_truncate_blocks(struct inode *inode, loff_t offset) + { +- /* +- * XXX: it seems like a bug here that we don't allow +- * IS_APPEND inode to have blocks-past-i_size trimmed off. +- * review and fix this. +- * +- * Also would be nice to be able to handle IO errors and such, +- * but that's probably too much to ask. +- */ + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + if (ext2_inode_is_fast_symlink(inode)) + return; +- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) +- return; + + dax_sem_down_write(EXT2_I(inode)); + __ext2_truncate_blocks(inode, offset); +diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c +index 7302d96ae8bf..fa40e756c501 100644 +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -585,6 +585,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) + return 0; + + out_put_hidden_dir: ++ cancel_delayed_work_sync(&sbi->sync_work); + iput(sbi->hidden_dir); + out_put_root: + dput(sb->s_root); +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index a2edb0049eb5..f038d4ac9aec 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -271,6 +271,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) + if (ln->nlmsvc_users) { + if (--ln->nlmsvc_users == 0) { + nlm_shutdown_hosts_net(net); ++ cancel_delayed_work_sync(&ln->grace_period_end); ++ locks_end_grace(&ln->lockd_manager); + svc_shutdown_net(serv, net); + dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); + } +diff --git a/fs/pipe.c b/fs/pipe.c +index 39eff9a67253..1e7263bb837a 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -616,6 +616,9 @@ struct pipe_inode_info *alloc_pipe_info(void) + unsigned long pipe_bufs = PIPE_DEF_BUFFERS; + struct user_struct *user = get_current_user(); + ++ if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE)) ++ pipe_bufs = pipe_max_size >> PAGE_SHIFT; ++ + if (!too_many_pipe_buffers_hard(user)) { + if (too_many_pipe_buffers_soft(user)) + pipe_bufs = 1; +diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c +index 9155a5a0d3b9..df4661abadc4 100644 +--- a/fs/proc/meminfo.c ++++ b/fs/proc/meminfo.c +@@ -57,11 +57,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v) + /* + * Estimate the amount of memory available for userspace allocations, + * without causing swapping. +- * +- * Free memory cannot be taken below the low watermark, before the +- * system starts swapping. + */ +- available = i.freeram - wmark_low; ++ available = i.freeram - totalreserve_pages; + + /* + * Not all the page cache can be freed, otherwise the system will +diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h +index bf2d34c9d804..f0d8b1c51343 100644 +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -13,7 +13,7 @@ + */ + + /** +- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant ++ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant + * argument and comparison of the previous + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval, ret; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + + #else + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index c47c68e535e8..a16d1851cfb1 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -767,6 +767,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; + ++ if (!chan || !chan->device || !chan->device->device_prep_slave_sg) ++ return NULL; ++ + return chan->device->device_prep_slave_sg(chan, &sg, 1, + dir, flags, NULL); + } +@@ -775,6 +778,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction dir, unsigned long flags) + { ++ if (!chan || !chan->device || !chan->device->device_prep_slave_sg) ++ return NULL; ++ + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, NULL); + } +@@ -786,6 +792,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( + enum dma_transfer_direction dir, unsigned long flags, + struct rio_dma_ext *rio_ext) + { ++ if (!chan || !chan->device || !chan->device->device_prep_slave_sg) ++ return NULL; ++ + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, rio_ext); + } +@@ -796,6 +805,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( + size_t period_len, enum dma_transfer_direction dir, + unsigned long flags) + { ++ if (!chan || !chan->device || !chan->device->device_prep_dma_cyclic) ++ return NULL; ++ + return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, + period_len, dir, flags); + } +@@ -804,6 +816,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) + { ++ if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) ++ return NULL; ++ + return chan->device->device_prep_interleaved_dma(chan, xt, flags); + } + +@@ -811,7 +826,7 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memset( + struct dma_chan *chan, dma_addr_t dest, int value, size_t len, + unsigned long flags) + { +- if (!chan || !chan->device) ++ if (!chan || !chan->device || !chan->device->device_prep_dma_memset) + return NULL; + + return chan->device->device_prep_dma_memset(chan, dest, value, +@@ -824,6 +839,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_sg( + struct scatterlist *src_sg, unsigned int src_nents, + unsigned long flags) + { ++ if (!chan || !chan->device || !chan->device->device_prep_dma_sg) ++ return NULL; ++ + return chan->device->device_prep_dma_sg(chan, dst_sg, dst_nents, + src_sg, src_nents, flags); + } +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 47be3ad7d3e5..7af95b58ebf3 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -364,8 +364,8 @@ typedef struct { + u32 attributes; + u32 get_bar_attributes; + u32 set_bar_attributes; +- uint64_t romsize; +- void *romimage; ++ u64 romsize; ++ u32 romimage; + } efi_pci_io_protocol_32; + + typedef struct { +@@ -384,8 +384,8 @@ typedef struct { + u64 attributes; + u64 get_bar_attributes; + u64 set_bar_attributes; +- uint64_t romsize; +- void *romimage; ++ u64 romsize; ++ u64 romimage; + } efi_pci_io_protocol_64; + + typedef struct { +diff --git a/include/linux/signal.h b/include/linux/signal.h +index d80259afb9e5..bcc094cb697c 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -97,6 +97,23 @@ static inline int sigisemptyset(sigset_t *set) + } + } + ++static inline int sigequalsets(const sigset_t *set1, const sigset_t *set2) ++{ ++ switch (_NSIG_WORDS) { ++ case 4: ++ return (set1->sig[3] == set2->sig[3]) && ++ (set1->sig[2] == set2->sig[2]) && ++ (set1->sig[1] == set2->sig[1]) && ++ (set1->sig[0] == set2->sig[0]); ++ case 2: ++ return (set1->sig[1] == set2->sig[1]) && ++ (set1->sig[0] == set2->sig[0]); ++ case 1: ++ return set1->sig[0] == set2->sig[0]; ++ } ++ return 0; ++} ++ + #define sigmask(sig) (1UL << ((sig) - 1)) + + #ifndef __HAVE_ARCH_SIG_SETOPS +diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h +index bce990f5a35d..d6be935caa50 100644 +--- a/include/trace/events/xen.h ++++ b/include/trace/events/xen.h +@@ -377,22 +377,6 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); + +-TRACE_EVENT(xen_mmu_flush_tlb_all, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- +-TRACE_EVENT(xen_mmu_flush_tlb, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- + TRACE_EVENT(xen_mmu_flush_tlb_single, + TP_PROTO(unsigned long addr), + TP_ARGS(addr), +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index 1f0b4cf5dd03..f4227173b5d8 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2195,6 +2195,8 @@ enum nl80211_attrs { + #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS + #define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + ++#define NL80211_WIPHY_NAME_MAXLEN 128 ++ + #define NL80211_MAX_SUPP_RATES 32 + #define NL80211_MAX_SUPP_HT_RATES 77 + #define NL80211_MAX_SUPP_REG_RULES 64 +diff --git a/kernel/auditsc.c b/kernel/auditsc.c +index 4bdea31cf6ce..7444f95f3ee9 100644 +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -1981,14 +1981,15 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, + if (!audit_enabled) + return; + ++ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); ++ if (!ab) ++ return; ++ + uid = from_kuid(&init_user_ns, task_uid(current)); + oldloginuid = from_kuid(&init_user_ns, koldloginuid); + loginuid = from_kuid(&init_user_ns, kloginuid), + tty = audit_get_tty(current); +- +- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); +- if (!ab) +- return; ++ + audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); + audit_log_task_context(ab); + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", +diff --git a/kernel/exit.c b/kernel/exit.c +index ffba5df4abd5..f20e6339761b 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -1608,6 +1608,10 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, + __WNOTHREAD|__WCLONE|__WALL)) + return -EINVAL; + ++ /* -INT_MIN is not defined */ ++ if (upid == INT_MIN) ++ return -ESRCH; ++ + if (upid == -1) + type = PIDTYPE_MAX; + else if (upid < 0) { +diff --git a/kernel/futex.c b/kernel/futex.c +index a12aa6785361..a26d217c99fe 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -666,13 +666,14 @@ again: + * this reference was taken by ihold under the page lock + * pinning the inode in place so i_lock was unnecessary. The + * only way for this check to fail is if the inode was +- * truncated in parallel so warn for now if this happens. ++ * truncated in parallel which is almost certainly an ++ * application bug. In such a case, just retry. + * + * We are not calling into get_futex_key_refs() in file-backed + * cases, therefore a successful atomic_inc return below will + * guarantee that get_futex_key() will still imply smp_mb(); (B). + */ +- if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) { ++ if (!atomic_inc_not_zero(&inode->i_count)) { + rcu_read_unlock(); + put_page(page_head); + +@@ -1452,6 +1453,45 @@ out: + return ret; + } + ++static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr) ++{ ++ unsigned int op = (encoded_op & 0x70000000) >> 28; ++ unsigned int cmp = (encoded_op & 0x0f000000) >> 24; ++ int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11); ++ int cmparg = sign_extend32(encoded_op & 0x00000fff, 11); ++ int oldval, ret; ++ ++ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) { ++ if (oparg < 0 || oparg > 31) ++ return -EINVAL; ++ oparg = 1 << oparg; ++ } ++ ++ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) ++ return -EFAULT; ++ ++ ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr); ++ if (ret) ++ return ret; ++ ++ switch (cmp) { ++ case FUTEX_OP_CMP_EQ: ++ return oldval == cmparg; ++ case FUTEX_OP_CMP_NE: ++ return oldval != cmparg; ++ case FUTEX_OP_CMP_LT: ++ return oldval < cmparg; ++ case FUTEX_OP_CMP_GE: ++ return oldval >= cmparg; ++ case FUTEX_OP_CMP_LE: ++ return oldval <= cmparg; ++ case FUTEX_OP_CMP_GT: ++ return oldval > cmparg; ++ default: ++ return -ENOSYS; ++ } ++} ++ + /* + * Wake up all waiters hashed on the physical page that is mapped + * to this virtual address: +diff --git a/kernel/signal.c b/kernel/signal.c +index 4a548c6a4118..7d75bc2d042f 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2495,6 +2495,13 @@ void __set_current_blocked(const sigset_t *newset) + { + struct task_struct *tsk = current; + ++ /* ++ * In case the signal mask hasn't changed, there is nothing we need ++ * to do. The current->blocked shouldn't be modified by other task. ++ */ ++ if (sigequalsets(&tsk->blocked, newset)) ++ return; ++ + spin_lock_irq(&tsk->sighand->siglock); + __set_task_blocked(tsk, newset); + spin_unlock_irq(&tsk->sighand->siglock); +diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c +index d2a20e83ebae..22d7454b387b 100644 +--- a/kernel/time/tick-broadcast.c ++++ b/kernel/time/tick-broadcast.c +@@ -610,6 +610,14 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) + now = ktime_get(); + /* Find all expired events */ + for_each_cpu(cpu, tick_broadcast_oneshot_mask) { ++ /* ++ * Required for !SMP because for_each_cpu() reports ++ * unconditionally CPU0 as set on UP kernels. ++ */ ++ if (!IS_ENABLED(CONFIG_SMP) && ++ cpumask_empty(tick_broadcast_oneshot_mask)) ++ break; ++ + td = &per_cpu(tick_cpu_device, cpu); + if (td->evtdev->next_event.tv64 <= now.tv64) { + cpumask_set_cpu(cpu, tmpmask); +diff --git a/mm/Kconfig b/mm/Kconfig +index 97a4e06b15c0..5753f69b23f4 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -628,6 +628,7 @@ config DEFERRED_STRUCT_PAGE_INIT + default n + depends on ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT + depends on MEMORY_HOTPLUG ++ depends on !NEED_PER_CPU_KM + help + Ordinarily all struct pages are initialised during early boot in a + single thread. On very large machines this can take a considerable +diff --git a/mm/filemap.c b/mm/filemap.c +index b15f1d8bba43..21e750b6e810 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -1581,6 +1581,15 @@ find_page: + index, last_index - index); + } + if (!PageUptodate(page)) { ++ /* ++ * See comment in do_read_cache_page on why ++ * wait_on_page_locked is used to avoid unnecessarily ++ * serialisations and why it's safe. ++ */ ++ wait_on_page_locked_killable(page); ++ if (PageUptodate(page)) ++ goto page_ok; ++ + if (inode->i_blkbits == PAGE_CACHE_SHIFT || + !mapping->a_ops->is_partially_uptodate) + goto page_not_up_to_date; +@@ -2215,7 +2224,7 @@ static struct page *wait_on_page_read(struct page *page) + return page; + } + +-static struct page *__read_cache_page(struct address_space *mapping, ++static struct page *do_read_cache_page(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *, struct page *), + void *data, +@@ -2237,53 +2246,74 @@ repeat: + /* Presumably ENOMEM for radix tree node */ + return ERR_PTR(err); + } ++ ++filler: + err = filler(data, page); + if (err < 0) { + page_cache_release(page); +- page = ERR_PTR(err); +- } else { +- page = wait_on_page_read(page); ++ return ERR_PTR(err); + } +- } +- return page; +-} + +-static struct page *do_read_cache_page(struct address_space *mapping, +- pgoff_t index, +- int (*filler)(void *, struct page *), +- void *data, +- gfp_t gfp) +- +-{ +- struct page *page; +- int err; ++ page = wait_on_page_read(page); ++ if (IS_ERR(page)) ++ return page; ++ goto out; ++ } ++ if (PageUptodate(page)) ++ goto out; + +-retry: +- page = __read_cache_page(mapping, index, filler, data, gfp); +- if (IS_ERR(page)) +- return page; ++ /* ++ * Page is not up to date and may be locked due one of the following ++ * case a: Page is being filled and the page lock is held ++ * case b: Read/write error clearing the page uptodate status ++ * case c: Truncation in progress (page locked) ++ * case d: Reclaim in progress ++ * ++ * Case a, the page will be up to date when the page is unlocked. ++ * There is no need to serialise on the page lock here as the page ++ * is pinned so the lock gives no additional protection. Even if the ++ * the page is truncated, the data is still valid if PageUptodate as ++ * it's a race vs truncate race. ++ * Case b, the page will not be up to date ++ * Case c, the page may be truncated but in itself, the data may still ++ * be valid after IO completes as it's a read vs truncate race. The ++ * operation must restart if the page is not uptodate on unlock but ++ * otherwise serialising on page lock to stabilise the mapping gives ++ * no additional guarantees to the caller as the page lock is ++ * released before return. ++ * Case d, similar to truncation. If reclaim holds the page lock, it ++ * will be a race with remove_mapping that determines if the mapping ++ * is valid on unlock but otherwise the data is valid and there is ++ * no need to serialise with page lock. ++ * ++ * As the page lock gives no additional guarantee, we optimistically ++ * wait on the page to be unlocked and check if it's up to date and ++ * use the page if it is. Otherwise, the page lock is required to ++ * distinguish between the different cases. The motivation is that we ++ * avoid spurious serialisations and wakeups when multiple processes ++ * wait on the same page for IO to complete. ++ */ ++ wait_on_page_locked(page); + if (PageUptodate(page)) + goto out; + ++ /* Distinguish between all the cases under the safety of the lock */ + lock_page(page); ++ ++ /* Case c or d, restart the operation */ + if (!page->mapping) { + unlock_page(page); + page_cache_release(page); +- goto retry; ++ goto repeat; + } ++ ++ /* Someone else locked and filled the page in a very small window */ + if (PageUptodate(page)) { + unlock_page(page); + goto out; + } +- err = filler(data, page); +- if (err < 0) { +- page_cache_release(page); +- return ERR_PTR(err); +- } else { +- page = wait_on_page_read(page); +- if (IS_ERR(page)) +- return page; +- } ++ goto filler; ++ + out: + mark_page_accessed(page); + return page; +diff --git a/mm/util.c b/mm/util.c +index 818bbae84721..5fae5b9c2885 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -428,17 +428,25 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen) + int res = 0; + unsigned int len; + struct mm_struct *mm = get_task_mm(task); ++ unsigned long arg_start, arg_end, env_start, env_end; + if (!mm) + goto out; + if (!mm->arg_end) + goto out_mm; /* Shh! No looking before we're done */ + +- len = mm->arg_end - mm->arg_start; ++ down_read(&mm->mmap_sem); ++ arg_start = mm->arg_start; ++ arg_end = mm->arg_end; ++ env_start = mm->env_start; ++ env_end = mm->env_end; ++ up_read(&mm->mmap_sem); ++ ++ len = arg_end - arg_start; + + if (len > buflen) + len = buflen; + +- res = access_process_vm(task, mm->arg_start, buffer, len, 0); ++ res = access_process_vm(task, arg_start, buffer, len, 0); + + /* + * If the nul at the end of args has been overwritten, then +@@ -449,10 +457,10 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen) + if (len < res) { + res = len; + } else { +- len = mm->env_end - mm->env_start; ++ len = env_end - env_start; + if (len > buflen - res) + len = buflen - res; +- res += access_process_vm(task, mm->env_start, ++ res += access_process_vm(task, env_start, + buffer+res, len, 0); + res = strnlen(buffer, res); + } +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 930f7c67a9c1..12a69e6c10ba 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2057,10 +2057,16 @@ static void get_scan_count(struct lruvec *lruvec, int swappiness, + } + + /* +- * There is enough inactive page cache, do not reclaim +- * anything from the anonymous working set right now. ++ * If there is enough inactive page cache, i.e. if the size of the ++ * inactive list is greater than that of the active list *and* the ++ * inactive list actually has some pages to scan on this priority, we ++ * do not reclaim anything from the anonymous working set right now. ++ * Without the second condition we could end up never scanning an ++ * lruvec even if it has plenty of old anonymous pages unless the ++ * system is under heavy pressure. + */ +- if (!inactive_file_is_low(lruvec)) { ++ if (!inactive_file_is_low(lruvec) && ++ get_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) { + scan_balance = SCAN_FILE; + goto out; + } +diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c +index ec02f5869a78..3400b1e47668 100644 +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -456,8 +456,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) + if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) + return -ELOOP; + +- /* Device is already being bridged */ +- if (br_port_exists(dev)) ++ /* Device has master upper dev */ ++ if (netdev_master_upper_dev_get(dev)) + return -EBUSY; + + /* No bridging devices that dislike that (e.g. wireless) */ +diff --git a/net/compat.c b/net/compat.c +index 0ccf3ecf6bbb..17e97b106458 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -358,7 +358,8 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname, + if (optname == SO_ATTACH_FILTER) + return do_set_attach_filter(sock, level, optname, + optval, optlen); +- if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) ++ if (!COMPAT_USE_64BIT_TIME && ++ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + return do_set_sock_timeout(sock, level, optname, optval, optlen); + + return sock_setsockopt(sock, level, optname, optval, optlen); +@@ -423,7 +424,8 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname, + static int compat_sock_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) + { +- if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) ++ if (!COMPAT_USE_64BIT_TIME && ++ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + return do_get_sock_timeout(sock, level, optname, optval, optlen); + return sock_getsockopt(sock, level, optname, optval, optlen); + } +diff --git a/net/core/sock.c b/net/core/sock.c +index cd12cb6fe366..4238835a0e4e 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1474,7 +1474,7 @@ void sk_destruct(struct sock *sk) + + static void __sk_free(struct sock *sk) + { +- if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt)) ++ if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk))) + sock_diag_broadcast_destroy(sk); + else + sk_destruct(sk); +diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c +index 7753681195c1..86a2ed0fb219 100644 +--- a/net/dccp/ccids/ccid2.c ++++ b/net/dccp/ccids/ccid2.c +@@ -126,6 +126,16 @@ static void ccid2_change_l_seq_window(struct sock *sk, u64 val) + DCCPF_SEQ_WMAX)); + } + ++static void dccp_tasklet_schedule(struct sock *sk) ++{ ++ struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet; ++ ++ if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { ++ sock_hold(sk); ++ __tasklet_schedule(t); ++ } ++} ++ + static void ccid2_hc_tx_rto_expire(unsigned long data) + { + struct sock *sk = (struct sock *)data; +@@ -166,7 +176,7 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) + + /* if we were blocked before, we may now send cwnd=1 packet */ + if (sender_was_blocked) +- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); ++ dccp_tasklet_schedule(sk); + /* restart backed-off timer */ + sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); + out: +@@ -706,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) + done: + /* check if incoming Acks allow pending packets to be sent */ + if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) +- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); ++ dccp_tasklet_schedule(sk); + dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); + } + +diff --git a/net/dccp/timer.c b/net/dccp/timer.c +index 3ef7acef3ce8..aa7c7dad7f96 100644 +--- a/net/dccp/timer.c ++++ b/net/dccp/timer.c +@@ -230,12 +230,12 @@ static void dccp_write_xmitlet(unsigned long data) + else + dccp_write_xmit(sk); + bh_unlock_sock(sk); ++ sock_put(sk); + } + + static void dccp_write_xmit_timer(unsigned long data) + { + dccp_write_xmitlet(data); +- sock_put((struct sock *)data); + } + + void dccp_init_xmit_timers(struct sock *sk) +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 09c73dd541c5..10286432f684 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1062,7 +1062,8 @@ alloc_new_skb: + if (copy > length) + copy = length; + +- if (!(rt->dst.dev->features&NETIF_F_SG)) { ++ if (!(rt->dst.dev->features&NETIF_F_SG) && ++ skb_tailroom(skb) >= copy) { + unsigned int off; + + off = skb->len; +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 37a3b05d175c..82c878224bfc 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -777,8 +777,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + ipc.addr = faddr = daddr; + + if (ipc.opt && ipc.opt->opt.srr) { +- if (!daddr) +- return -EINVAL; ++ if (!daddr) { ++ err = -EINVAL; ++ goto out_free; ++ } + faddr = ipc.opt->opt.faddr; + } + tos = get_rttos(&ipc, inet); +@@ -843,6 +845,7 @@ back_from_confirm: + + out: + ip_rt_put(rt); ++out_free: + if (free) + kfree(ipc.opt); + if (!err) { +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index b531a0997664..a0f0a7db946b 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1108,7 +1108,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + lock_sock(sk); + + flags = msg->msg_flags; +- if (flags & MSG_FASTOPEN) { ++ if ((flags & MSG_FASTOPEN) && !tp->repair) { + err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); + if (err == -EINPROGRESS && copied_syn > 0) + goto out; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 39c2919fe0d3..2854db094864 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2587,8 +2587,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) + return -EBUSY; + + if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { +- if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) +- BUG(); ++ if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) { ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } + if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) + return -ENOMEM; + } +@@ -3117,6 +3119,7 @@ static void tcp_connect_init(struct sock *sk) + sock_reset_flag(sk, SOCK_DONE); + tp->snd_wnd = 0; + tcp_init_wl(tp, 0); ++ tcp_write_queue_purge(sk); + tp->snd_una = tp->write_seq; + tp->snd_sml = tp->write_seq; + tp->snd_up = tp->write_seq; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index a98ae890adb9..6f929689fd03 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -991,8 +991,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + ipc.addr = faddr = daddr; + + if (ipc.opt && ipc.opt->opt.srr) { +- if (!daddr) +- return -EINVAL; ++ if (!daddr) { ++ err = -EINVAL; ++ goto out_free; ++ } + faddr = ipc.opt->opt.faddr; + connected = 0; + } +@@ -1105,6 +1107,7 @@ do_append_data: + + out: + ip_rt_put(rt); ++out_free: + if (free) + kfree(ipc.opt); + if (!err) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index bfa710e8b615..74786783834b 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1529,7 +1529,8 @@ alloc_new_skb: + if (copy > length) + copy = length; + +- if (!(rt->dst.dev->features&NETIF_F_SG)) { ++ if (!(rt->dst.dev->features&NETIF_F_SG) && ++ skb_tailroom(skb) >= copy) { + unsigned int off; + + off = skb->len; +diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c +index ae3438685caa..fb3248ff8b48 100644 +--- a/net/l2tp/l2tp_netlink.c ++++ b/net/l2tp/l2tp_netlink.c +@@ -732,8 +732,6 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl + + if ((session->ifname[0] && + nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) || +- (session->offset && +- nla_put_u16(skb, L2TP_ATTR_OFFSET, session->offset)) || + (session->cookie_len && + nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len, + &session->cookie[0])) || +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 09f2f3471ad6..83e8a295c806 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -926,6 +926,9 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + if (size > llc->dev->mtu) + size = llc->dev->mtu; + copied = size - hdrlen; ++ rc = -EINVAL; ++ if (copied < 0) ++ goto release; + release_sock(sk); + skb = sock_alloc_send_skb(sk, size, noblock, &rc); + lock_sock(sk); +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 21e4d339217e..624c4719e404 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -1141,13 +1141,10 @@ static void nlattr_set(struct nlattr *attr, u8 val, + + /* The nlattr stream should already have been validated */ + nla_for_each_nested(nla, attr, rem) { +- if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) { +- if (tbl[nla_type(nla)].next) +- tbl = tbl[nla_type(nla)].next; +- nlattr_set(nla, val, tbl); +- } else { ++ if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) ++ nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl); ++ else + memset(nla_data(nla), val, nla_len(nla)); +- } + + if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE) + *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index f165514a4db5..392d4e2c0a24 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2771,13 +2771,15 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) + if (skb == NULL) + goto out_unlock; + +- skb_set_network_header(skb, reserve); ++ skb_reset_network_header(skb); + + err = -EINVAL; + if (sock->type == SOCK_DGRAM) { + offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len); + if (unlikely(offset < 0)) + goto out_free; ++ } else if (reserve) { ++ skb_push(skb, reserve); + } + + /* Returns -EFAULT on error */ +diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c +index 3c6a47d66a04..117ed90c5f21 100644 +--- a/net/sched/sch_fq.c ++++ b/net/sched/sch_fq.c +@@ -126,6 +126,28 @@ static bool fq_flow_is_detached(const struct fq_flow *f) + return f->next == &detached; + } + ++static bool fq_flow_is_throttled(const struct fq_flow *f) ++{ ++ return f->next == &throttled; ++} ++ ++static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) ++{ ++ if (head->first) ++ head->last->next = flow; ++ else ++ head->first = flow; ++ head->last = flow; ++ flow->next = NULL; ++} ++ ++static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f) ++{ ++ rb_erase(&f->rate_node, &q->delayed); ++ q->throttled_flows--; ++ fq_flow_add_tail(&q->old_flows, f); ++} ++ + static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) + { + struct rb_node **p = &q->delayed.rb_node, *parent = NULL; +@@ -153,15 +175,6 @@ static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) + + static struct kmem_cache *fq_flow_cachep __read_mostly; + +-static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) +-{ +- if (head->first) +- head->last->next = flow; +- else +- head->first = flow; +- head->last = flow; +- flow->next = NULL; +-} + + /* limit number of collected flows per round */ + #define FQ_GC_MAX 8 +@@ -265,6 +278,8 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q) + f->socket_hash != sk->sk_hash)) { + f->credit = q->initial_quantum; + f->socket_hash = sk->sk_hash; ++ if (fq_flow_is_throttled(f)) ++ fq_flow_unset_throttled(q, f); + f->time_next_packet = 0ULL; + } + return f; +@@ -419,9 +434,7 @@ static void fq_check_throttled(struct fq_sched_data *q, u64 now) + q->time_next_delayed_flow = f->time_next_packet; + break; + } +- rb_erase(p, &q->delayed); +- q->throttled_flows--; +- fq_flow_add_tail(&q->old_flows, f); ++ fq_flow_unset_throttled(q, f); + } + } + +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index 559afd0ee7de..a40b8b0ef0d5 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1000,9 +1000,10 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) + struct sctp_endpoint *ep; + struct sctp_chunk *chunk; + struct sctp_inq *inqueue; +- int state; + sctp_subtype_t subtype; ++ int first_time = 1; /* is this the first time through the loop */ + int error = 0; ++ int state; + + /* The association should be held so we should be safe. */ + ep = asoc->ep; +@@ -1013,6 +1014,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) + state = asoc->state; + subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); + ++ /* If the first chunk in the packet is AUTH, do special ++ * processing specified in Section 6.3 of SCTP-AUTH spec ++ */ ++ if (first_time && subtype.chunk == SCTP_CID_AUTH) { ++ struct sctp_chunkhdr *next_hdr; ++ ++ next_hdr = sctp_inq_peek(inqueue); ++ if (!next_hdr) ++ goto normal; ++ ++ /* If the next chunk is COOKIE-ECHO, skip the AUTH ++ * chunk while saving a pointer to it so we can do ++ * Authentication later (during cookie-echo ++ * processing). ++ */ ++ if (next_hdr->type == SCTP_CID_COOKIE_ECHO) { ++ chunk->auth_chunk = skb_clone(chunk->skb, ++ GFP_ATOMIC); ++ chunk->auth = 1; ++ continue; ++ } ++ } ++ ++normal: + /* SCTP-AUTH, Section 6.3: + * The receiver has a list of chunk types which it expects + * to be received only after an AUTH-chunk. This list has +@@ -1051,6 +1076,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) + /* If there is an error on chunk, discard this packet. */ + if (error && chunk) + chunk->pdiscard = 1; ++ ++ if (first_time) ++ first_time = 0; + } + sctp_association_put(asoc); + } +diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c +index 7e8a16c77039..8d9b7ad25b65 100644 +--- a/net/sctp/inqueue.c ++++ b/net/sctp/inqueue.c +@@ -178,7 +178,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); + chunk->subh.v = NULL; /* Subheader is no longer valid. */ + +- if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < ++ if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) <= + skb_tail_pointer(chunk->skb)) { + /* This is not a singleton */ + chunk->singleton = 0; +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 1cd7b7e33fa3..5ca8309ea7b1 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -863,6 +863,9 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, + if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) + return 1; + ++ if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET) ++ return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr; ++ + return __sctp_v6_cmp_addr(addr1, addr2); + } + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 29c7c43de108..df9ac3746c1b 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -144,10 +144,8 @@ static sctp_disposition_t sctp_sf_violation_chunk( + void *arg, + sctp_cmd_seq_t *commands); + +-static sctp_ierror_t sctp_sf_authenticate(struct net *net, +- const struct sctp_endpoint *ep, ++static sctp_ierror_t sctp_sf_authenticate( + const struct sctp_association *asoc, +- const sctp_subtype_t type, + struct sctp_chunk *chunk); + + static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, +@@ -615,6 +613,38 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, + return SCTP_DISPOSITION_CONSUME; + } + ++static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, ++ const struct sctp_association *asoc) ++{ ++ struct sctp_chunk auth; ++ ++ if (!chunk->auth_chunk) ++ return true; ++ ++ /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo ++ * is supposed to be authenticated and we have to do delayed ++ * authentication. We've just recreated the association using ++ * the information in the cookie and now it's much easier to ++ * do the authentication. ++ */ ++ ++ /* Make sure that we and the peer are AUTH capable */ ++ if (!net->sctp.auth_enable || !asoc->peer.auth_capable) ++ return false; ++ ++ /* set-up our fake chunk so that we can process it */ ++ auth.skb = chunk->auth_chunk; ++ auth.asoc = chunk->asoc; ++ auth.sctp_hdr = chunk->sctp_hdr; ++ auth.chunk_hdr = (struct sctp_chunkhdr *) ++ skb_push(chunk->auth_chunk, ++ sizeof(struct sctp_chunkhdr)); ++ skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr)); ++ auth.transport = chunk->transport; ++ ++ return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR; ++} ++ + /* + * Respond to a normal COOKIE ECHO chunk. + * We are the side that is being asked for an association. +@@ -751,36 +781,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, + if (error) + goto nomem_init; + +- /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo +- * is supposed to be authenticated and we have to do delayed +- * authentication. We've just recreated the association using +- * the information in the cookie and now it's much easier to +- * do the authentication. +- */ +- if (chunk->auth_chunk) { +- struct sctp_chunk auth; +- sctp_ierror_t ret; +- +- /* Make sure that we and the peer are AUTH capable */ +- if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { +- sctp_association_free(new_asoc); +- return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); +- } +- +- /* set-up our fake chunk so that we can process it */ +- auth.skb = chunk->auth_chunk; +- auth.asoc = chunk->asoc; +- auth.sctp_hdr = chunk->sctp_hdr; +- auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk, +- sizeof(sctp_chunkhdr_t)); +- skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t)); +- auth.transport = chunk->transport; +- +- ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); +- if (ret != SCTP_IERROR_NO_ERROR) { +- sctp_association_free(new_asoc); +- return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); +- } ++ if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) { ++ sctp_association_free(new_asoc); ++ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } + + repl = sctp_make_cookie_ack(new_asoc, chunk); +@@ -1717,13 +1720,15 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, + GFP_ATOMIC)) + goto nomem; + ++ if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) ++ return SCTP_DISPOSITION_DISCARD; ++ + /* Make sure no new addresses are being added during the + * restart. Though this is a pretty complicated attack + * since you'd have to get inside the cookie. + */ +- if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { ++ if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) + return SCTP_DISPOSITION_CONSUME; +- } + + /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes + * the peer has restarted (Action A), it MUST NOT setup a new +@@ -1828,6 +1833,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net, + GFP_ATOMIC)) + goto nomem; + ++ if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) ++ return SCTP_DISPOSITION_DISCARD; ++ + /* Update the content of current association. */ + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, +@@ -1920,6 +1928,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net, + * a COOKIE ACK. + */ + ++ if (!sctp_auth_chunk_verify(net, chunk, asoc)) ++ return SCTP_DISPOSITION_DISCARD; ++ + /* Don't accidentally move back into established state. */ + if (asoc->state < SCTP_STATE_ESTABLISHED) { + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, +@@ -1959,7 +1970,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net, + } + } + +- repl = sctp_make_cookie_ack(new_asoc, chunk); ++ repl = sctp_make_cookie_ack(asoc, chunk); + if (!repl) + goto nomem; + +@@ -3985,10 +3996,8 @@ gen_shutdown: + * + * The return value is the disposition of the chunk. + */ +-static sctp_ierror_t sctp_sf_authenticate(struct net *net, +- const struct sctp_endpoint *ep, ++static sctp_ierror_t sctp_sf_authenticate( + const struct sctp_association *asoc, +- const sctp_subtype_t type, + struct sctp_chunk *chunk) + { + struct sctp_authhdr *auth_hdr; +@@ -4087,7 +4096,7 @@ sctp_disposition_t sctp_sf_eat_auth(struct net *net, + commands); + + auth_hdr = (struct sctp_authhdr *)chunk->skb->data; +- error = sctp_sf_authenticate(net, ep, asoc, type, chunk); ++ error = sctp_sf_authenticate(asoc, chunk); + switch (error) { + case SCTP_IERROR_AUTH_BAD_HMAC: + /* Generate the ERROR chunk and discard the rest +diff --git a/net/wireless/core.c b/net/wireless/core.c +index eeaf83acba1b..a1e909ae0f78 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -94,6 +94,9 @@ static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev, + + ASSERT_RTNL(); + ++ if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN) ++ return -EINVAL; ++ + /* prohibit calling the thing phy%d when %d is not its number */ + sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); + if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 62d87f859566..d6a11af0bab1 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -1159,6 +1159,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) + + if (orig->aead) { + x->aead = xfrm_algo_aead_clone(orig->aead); ++ x->geniv = orig->geniv; + if (!x->aead) + goto error; + } +diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c +index 0608f216f359..ac0a40b9ba1e 100644 +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -400,8 +400,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, + if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || + copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + goto error; +- if (get_user(data->owner, &data32->owner) || +- get_user(data->type, &data32->type)) ++ if (get_user(data->owner, &data32->owner)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 3be91696ac35..d0b55c866370 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -2072,6 +2072,8 @@ static struct snd_pci_quirk power_save_blacklist[] = { + SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0), + /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ + SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */ ++ SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0), + /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ + SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0), + {} +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index c5447ff078b3..97d6a18e6956 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -904,6 +904,14 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, + } + break; + ++ case USB_ID(0x0d8c, 0x0103): ++ if (!strcmp(kctl->id.name, "PCM Playback Volume")) { ++ usb_audio_info(chip, ++ "set volume quirk for CM102-A+/102S+\n"); ++ cval->min = -256; ++ } ++ break; ++ + case USB_ID(0x0471, 0x0101): + case USB_ID(0x0471, 0x0104): + case USB_ID(0x0471, 0x0105):