From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 505691382C5 for ; Sat, 17 Feb 2018 15:10:53 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 773DBE09F9; Sat, 17 Feb 2018 15:10:52 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 2821DE09F9 for ; Sat, 17 Feb 2018 15:10:52 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id B964F335C2C for ; Sat, 17 Feb 2018 15:10:50 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 03958215 for ; Sat, 17 Feb 2018 15:10:49 +0000 (UTC) From: "Alice Ferrazzi" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Alice Ferrazzi" Message-ID: <1518880228.4d7306a17d8280b24dacb30825968fca25bf1501.alicef@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.4 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1115_linux-4.4.116.patch X-VCS-Directories: / X-VCS-Committer: alicef X-VCS-Committer-Name: Alice Ferrazzi X-VCS-Revision: 4d7306a17d8280b24dacb30825968fca25bf1501 X-VCS-Branch: 4.4 Date: Sat, 17 Feb 2018 15:10:49 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 16c460b6-6f1f-4b92-8f6e-ae0898174685 X-Archives-Hash: ad28046542b7d393901aae024bfce8db commit: 4d7306a17d8280b24dacb30825968fca25bf1501 Author: Alice Ferrazzi gentoo org> AuthorDate: Sat Feb 17 15:10:28 2018 +0000 Commit: Alice Ferrazzi gentoo org> CommitDate: Sat Feb 17 15:10:28 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=4d7306a1 linux kernel 4.4.116 0000_README | 4 + 1115_linux-4.4.116.patch | 5357 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 5361 insertions(+) diff --git a/0000_README b/0000_README index 60d9f40..0996e2a 100644 --- a/0000_README +++ b/0000_README @@ -503,6 +503,10 @@ Patch: 1114_linux-4.4.115.patch From: http://www.kernel.org Desc: Linux 4.4.115 +Patch: 1115_linux-4.4.116.patch +From: http://www.kernel.org +Desc: Linux 4.4.116 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1115_linux-4.4.116.patch b/1115_linux-4.4.116.patch new file mode 100644 index 0000000..e3d5b51 --- /dev/null +++ b/1115_linux-4.4.116.patch @@ -0,0 +1,5357 @@ +diff --git a/Makefile b/Makefile +index 9c60120dd9fd..71acaecd7899 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 115 ++SUBLEVEL = 116 + EXTRAVERSION = + NAME = Blurry Fish Butt + +diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h +index 2b0ac429f5eb..412bb3c24f36 100644 +--- a/arch/alpha/kernel/pci_impl.h ++++ b/arch/alpha/kernel/pci_impl.h +@@ -143,7 +143,8 @@ struct pci_iommu_arena + }; + + #if defined(CONFIG_ALPHA_SRM) && \ +- (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA)) ++ (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \ ++ defined(CONFIG_ALPHA_AVANTI)) + # define NEED_SRM_SAVE_RESTORE + #else + # undef NEED_SRM_SAVE_RESTORE +diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c +index 84d13263ce46..8095fb2c5c94 100644 +--- a/arch/alpha/kernel/process.c ++++ b/arch/alpha/kernel/process.c +@@ -273,12 +273,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp, + application calling fork. */ + if (clone_flags & CLONE_SETTLS) + childti->pcb.unique = regs->r20; ++ else ++ regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */ + childti->pcb.usp = usp ?: rdusp(); + *childregs = *regs; + childregs->r0 = 0; + childregs->r19 = 0; + childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ +- regs->r20 = 0; + stack = ((struct switch_stack *) regs) - 1; + *childstack = *stack; + childstack->r26 = (unsigned long) ret_from_fork; +diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c +index f36b5b1acd1f..05b2f8294968 100644 +--- a/arch/arm/kvm/handle_exit.c ++++ b/arch/arm/kvm/handle_exit.c +@@ -45,7 +45,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + + ret = kvm_psci_call(vcpu); + if (ret < 0) { +- kvm_inject_undefined(vcpu); ++ vcpu_set_reg(vcpu, 0, ~0UL); + return 1; + } + +@@ -54,7 +54,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + + static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) + { +- kvm_inject_undefined(vcpu); ++ /* ++ * "If an SMC instruction executed at Non-secure EL1 is ++ * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a ++ * Trap exception, not a Secure Monitor Call exception [...]" ++ * ++ * We need to advance the PC after the trap, as it would ++ * otherwise return to the same address... ++ */ ++ vcpu_set_reg(vcpu, 0, ~0UL); ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; + } + +diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c +index b9920b1edd5a..70cef54dc40f 100644 +--- a/arch/mn10300/mm/misalignment.c ++++ b/arch/mn10300/mm/misalignment.c +@@ -437,7 +437,7 @@ transfer_failed: + + info.si_signo = SIGSEGV; + info.si_errno = 0; +- info.si_code = 0; ++ info.si_code = SEGV_MAPERR; + info.si_addr = (void *) regs->pc; + force_sig_info(SIGSEGV, &info, current); + return; +diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c +index 3d3f6062f49c..605a284922fb 100644 +--- a/arch/openrisc/kernel/traps.c ++++ b/arch/openrisc/kernel/traps.c +@@ -302,12 +302,12 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) + siginfo_t info; + + if (user_mode(regs)) { +- /* Send a SIGSEGV */ +- info.si_signo = SIGSEGV; ++ /* Send a SIGBUS */ ++ info.si_signo = SIGBUS; + info.si_errno = 0; +- /* info.si_code has been set above */ +- info.si_addr = (void *)address; +- force_sig_info(SIGSEGV, &info, current); ++ info.si_code = BUS_ADRALN; ++ info.si_addr = (void __user *)address; ++ force_sig_info(SIGBUS, &info, current); + } else { + printk("KERNEL: Unaligned Access 0x%.8lx\n", address); + show_registers(regs); +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index dfb1ee8c3e06..58a1fa979655 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -129,13 +129,14 @@ config PPC + select IRQ_FORCED_THREADING + select HAVE_RCU_TABLE_FREE if SMP + select HAVE_SYSCALL_TRACEPOINTS +- select HAVE_BPF_JIT ++ select HAVE_BPF_JIT if CPU_BIG_ENDIAN + select HAVE_ARCH_JUMP_LABEL + select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_HAS_GCOV_PROFILE_ALL + select GENERIC_SMP_IDLE_THREAD + select GENERIC_CMOS_UPDATE + select GENERIC_TIME_VSYSCALL_OLD ++ select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64 + select GENERIC_CLOCKEVENTS + select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST +diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h +index a703452d67b6..555e22d5e07f 100644 +--- a/arch/powerpc/include/asm/exception-64e.h ++++ b/arch/powerpc/include/asm/exception-64e.h +@@ -209,5 +209,11 @@ exc_##label##_book3e: + ori r3,r3,vector_offset@l; \ + mtspr SPRN_IVOR##vector_number,r3; + ++#define RFI_TO_KERNEL \ ++ rfi ++ ++#define RFI_TO_USER \ ++ rfi ++ + #endif /* _ASM_POWERPC_EXCEPTION_64E_H */ + +diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h +index 77f52b26dad6..9bddbec441b8 100644 +--- a/arch/powerpc/include/asm/exception-64s.h ++++ b/arch/powerpc/include/asm/exception-64s.h +@@ -50,6 +50,59 @@ + #define EX_PPR 88 /* SMT thread status register (priority) */ + #define EX_CTR 96 + ++/* ++ * Macros for annotating the expected destination of (h)rfid ++ * ++ * The nop instructions allow us to insert one or more instructions to flush the ++ * L1-D cache when returning to userspace or a guest. ++ */ ++#define RFI_FLUSH_SLOT \ ++ RFI_FLUSH_FIXUP_SECTION; \ ++ nop; \ ++ nop; \ ++ nop ++ ++#define RFI_TO_KERNEL \ ++ rfid ++ ++#define RFI_TO_USER \ ++ RFI_FLUSH_SLOT; \ ++ rfid; \ ++ b rfi_flush_fallback ++ ++#define RFI_TO_USER_OR_KERNEL \ ++ RFI_FLUSH_SLOT; \ ++ rfid; \ ++ b rfi_flush_fallback ++ ++#define RFI_TO_GUEST \ ++ RFI_FLUSH_SLOT; \ ++ rfid; \ ++ b rfi_flush_fallback ++ ++#define HRFI_TO_KERNEL \ ++ hrfid ++ ++#define HRFI_TO_USER \ ++ RFI_FLUSH_SLOT; \ ++ hrfid; \ ++ b hrfi_flush_fallback ++ ++#define HRFI_TO_USER_OR_KERNEL \ ++ RFI_FLUSH_SLOT; \ ++ hrfid; \ ++ b hrfi_flush_fallback ++ ++#define HRFI_TO_GUEST \ ++ RFI_FLUSH_SLOT; \ ++ hrfid; \ ++ b hrfi_flush_fallback ++ ++#define HRFI_TO_UNKNOWN \ ++ RFI_FLUSH_SLOT; \ ++ hrfid; \ ++ b hrfi_flush_fallback ++ + #ifdef CONFIG_RELOCATABLE + #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ + ld r12,PACAKBASE(r13); /* get high part of &label */ \ +@@ -191,7 +244,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) + mtspr SPRN_##h##SRR0,r12; \ + mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ + mtspr SPRN_##h##SRR1,r10; \ +- h##rfid; \ ++ h##RFI_TO_KERNEL; \ + b . /* prevent speculative execution */ + #define EXCEPTION_PROLOG_PSERIES_1(label, h) \ + __EXCEPTION_PROLOG_PSERIES_1(label, h) +diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h +index 9a67a38bf7b9..7068bafbb2d6 100644 +--- a/arch/powerpc/include/asm/feature-fixups.h ++++ b/arch/powerpc/include/asm/feature-fixups.h +@@ -184,4 +184,19 @@ label##3: \ + FTR_ENTRY_OFFSET label##1b-label##3b; \ + .popsection; + ++#define RFI_FLUSH_FIXUP_SECTION \ ++951: \ ++ .pushsection __rfi_flush_fixup,"a"; \ ++ .align 2; \ ++952: \ ++ FTR_ENTRY_OFFSET 951b-952b; \ ++ .popsection; ++ ++ ++#ifndef __ASSEMBLY__ ++ ++extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; ++ ++#endif ++ + #endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */ +diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index 85bc8c0d257b..449bbb87c257 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -239,6 +239,7 @@ + #define H_GET_HCA_INFO 0x1B8 + #define H_GET_PERF_COUNT 0x1BC + #define H_MANAGE_TRACE 0x1C0 ++#define H_GET_CPU_CHARACTERISTICS 0x1C8 + #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 + #define H_QUERY_INT_STATE 0x1E4 + #define H_POLL_PENDING 0x1D8 +@@ -285,7 +286,19 @@ + #define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3 + #define H_SET_MODE_RESOURCE_LE 4 + ++/* H_GET_CPU_CHARACTERISTICS return values */ ++#define H_CPU_CHAR_SPEC_BAR_ORI31 (1ull << 63) // IBM bit 0 ++#define H_CPU_CHAR_BCCTRL_SERIALISED (1ull << 62) // IBM bit 1 ++#define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2 ++#define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3 ++#define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4 ++ ++#define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0 ++#define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1 ++#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2 ++ + #ifndef __ASSEMBLY__ ++#include + + /** + * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments +@@ -423,6 +436,11 @@ extern long pseries_big_endian_exceptions(void); + + #endif /* CONFIG_PPC_PSERIES */ + ++struct h_cpu_char_result { ++ u64 character; ++ u64 behaviour; ++}; ++ + #endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ + #endif /* _ASM_POWERPC_HVCALL_H */ +diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h +index 70bd4381f8e6..45e2aefece16 100644 +--- a/arch/powerpc/include/asm/paca.h ++++ b/arch/powerpc/include/asm/paca.h +@@ -192,6 +192,16 @@ struct paca_struct { + #endif + struct kvmppc_host_state kvm_hstate; + #endif ++#ifdef CONFIG_PPC_BOOK3S_64 ++ /* ++ * rfi fallback flush must be in its own cacheline to prevent ++ * other paca data leaking into the L1d ++ */ ++ u64 exrfi[13] __aligned(0x80); ++ void *rfi_flush_fallback_area; ++ u64 l1d_flush_congruence; ++ u64 l1d_flush_sets; ++#endif + }; + + extern struct paca_struct *paca; +diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h +index 67859edbf8fd..6e05cb397a5c 100644 +--- a/arch/powerpc/include/asm/plpar_wrappers.h ++++ b/arch/powerpc/include/asm/plpar_wrappers.h +@@ -323,4 +323,18 @@ static inline long plapr_set_watchpoint0(unsigned long dawr0, unsigned long dawr + return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR, dawr0, dawrx0); + } + ++static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p) ++{ ++ unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; ++ long rc; ++ ++ rc = plpar_hcall(H_GET_CPU_CHARACTERISTICS, retbuf); ++ if (rc == H_SUCCESS) { ++ p->character = retbuf[0]; ++ p->behaviour = retbuf[1]; ++ } ++ ++ return rc; ++} ++ + #endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */ +diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h +index dd0fc18d8103..160bb2311bbb 100644 +--- a/arch/powerpc/include/asm/ppc_asm.h ++++ b/arch/powerpc/include/asm/ppc_asm.h +@@ -224,6 +224,16 @@ name: \ + .globl name; \ + name: + ++#define _KPROBE_TOC(name) \ ++ .section ".kprobes.text","a"; \ ++ .align 2 ; \ ++ .type name,@function; \ ++ .globl name; \ ++name: \ ++0: addis r2,r12,(.TOC.-0b)@ha; \ ++ addi r2,r2,(.TOC.-0b)@l; \ ++ .localentry name,.-name ++ + #define DOTSYM(a) a + + #else +@@ -261,6 +271,8 @@ name: \ + .type GLUE(.,name),@function; \ + GLUE(.,name): + ++#define _KPROBE_TOC(n) _KPROBE(n) ++ + #define DOTSYM(a) GLUE(.,a) + + #endif +diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h +index e9d384cbd021..7916b56f2e60 100644 +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -26,6 +26,19 @@ void initmem_init(void); + void setup_panic(void); + #define ARCH_PANIC_TIMEOUT 180 + ++void rfi_flush_enable(bool enable); ++ ++/* These are bit flags */ ++enum l1d_flush_type { ++ L1D_FLUSH_NONE = 0x1, ++ L1D_FLUSH_FALLBACK = 0x2, ++ L1D_FLUSH_ORI = 0x4, ++ L1D_FLUSH_MTTRIG = 0x8, ++}; ++ ++void __init setup_rfi_flush(enum l1d_flush_type, bool enable); ++void do_rfi_flush_fixups(enum l1d_flush_type types); ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* _ASM_POWERPC_SETUP_H */ +diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c +index 40da69163d51..d92705e3a0c1 100644 +--- a/arch/powerpc/kernel/asm-offsets.c ++++ b/arch/powerpc/kernel/asm-offsets.c +@@ -243,6 +243,10 @@ int main(void) + #ifdef CONFIG_PPC_BOOK3S_64 + DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp)); + DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce)); ++ DEFINE(PACA_RFI_FLUSH_FALLBACK_AREA, offsetof(struct paca_struct, rfi_flush_fallback_area)); ++ DEFINE(PACA_EXRFI, offsetof(struct paca_struct, exrfi)); ++ DEFINE(PACA_L1D_FLUSH_CONGRUENCE, offsetof(struct paca_struct, l1d_flush_congruence)); ++ DEFINE(PACA_L1D_FLUSH_SETS, offsetof(struct paca_struct, l1d_flush_sets)); + #endif + DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); + DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); +diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S +index f6fd0332c3a2..2837232bbffb 100644 +--- a/arch/powerpc/kernel/entry_64.S ++++ b/arch/powerpc/kernel/entry_64.S +@@ -36,6 +36,11 @@ + #include + #include + #include ++#ifdef CONFIG_PPC_BOOK3S ++#include ++#else ++#include ++#endif + + /* + * System calls. +@@ -225,13 +230,23 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) + ACCOUNT_CPU_USER_EXIT(r11, r12) + HMT_MEDIUM_LOW_HAS_PPR + ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ ++ ld r2,GPR2(r1) ++ ld r1,GPR1(r1) ++ mtlr r4 ++ mtcr r5 ++ mtspr SPRN_SRR0,r7 ++ mtspr SPRN_SRR1,r8 ++ RFI_TO_USER ++ b . /* prevent speculative execution */ ++ ++ /* exit to kernel */ + 1: ld r2,GPR2(r1) + ld r1,GPR1(r1) + mtlr r4 + mtcr r5 + mtspr SPRN_SRR0,r7 + mtspr SPRN_SRR1,r8 +- RFI ++ RFI_TO_KERNEL + b . /* prevent speculative execution */ + + syscall_error: +@@ -353,8 +368,7 @@ tabort_syscall: + mtmsrd r10, 1 + mtspr SPRN_SRR0, r11 + mtspr SPRN_SRR1, r12 +- +- rfid ++ RFI_TO_USER + b . /* prevent speculative execution */ + #endif + +@@ -887,7 +901,7 @@ BEGIN_FTR_SECTION + END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) + ACCOUNT_CPU_USER_EXIT(r2, r4) + REST_GPR(13, r1) +-1: ++ + mtspr SPRN_SRR1,r3 + + ld r2,_CCR(r1) +@@ -900,8 +914,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) + ld r3,GPR3(r1) + ld r4,GPR4(r1) + ld r1,GPR1(r1) ++ RFI_TO_USER ++ b . /* prevent speculative execution */ + +- rfid ++1: mtspr SPRN_SRR1,r3 ++ ++ ld r2,_CCR(r1) ++ mtcrf 0xFF,r2 ++ ld r2,_NIP(r1) ++ mtspr SPRN_SRR0,r2 ++ ++ ld r0,GPR0(r1) ++ ld r2,GPR2(r1) ++ ld r3,GPR3(r1) ++ ld r4,GPR4(r1) ++ ld r1,GPR1(r1) ++ RFI_TO_KERNEL + b . /* prevent speculative execution */ + + #endif /* CONFIG_PPC_BOOK3E */ +@@ -1077,7 +1105,7 @@ _GLOBAL(enter_rtas) + + mtspr SPRN_SRR0,r5 + mtspr SPRN_SRR1,r6 +- rfid ++ RFI_TO_KERNEL + b . /* prevent speculative execution */ + + rtas_return_loc: +@@ -1102,7 +1130,7 @@ rtas_return_loc: + + mtspr SPRN_SRR0,r3 + mtspr SPRN_SRR1,r4 +- rfid ++ RFI_TO_KERNEL + b . /* prevent speculative execution */ + + .align 3 +@@ -1173,7 +1201,7 @@ _GLOBAL(enter_prom) + LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE) + andc r11,r11,r12 + mtsrr1 r11 +- rfid ++ RFI_TO_KERNEL + #endif /* CONFIG_PPC_BOOK3E */ + + 1: /* Return from OF */ +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index b81ccc5fb32d..938a30fef031 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -46,7 +46,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ + mtspr SPRN_SRR0,r10 ; \ + ld r10,PACAKMSR(r13) ; \ + mtspr SPRN_SRR1,r10 ; \ +- rfid ; \ ++ RFI_TO_KERNEL ; \ + b . ; /* prevent speculative execution */ + + #define SYSCALL_PSERIES_3 \ +@@ -54,7 +54,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ + 1: mfspr r12,SPRN_SRR1 ; \ + xori r12,r12,MSR_LE ; \ + mtspr SPRN_SRR1,r12 ; \ +- rfid ; /* return to userspace */ \ ++ RFI_TO_USER ; /* return to userspace */ \ + b . ; /* prevent speculative execution */ + + #if defined(CONFIG_RELOCATABLE) +@@ -507,7 +507,7 @@ BEGIN_FTR_SECTION + LOAD_HANDLER(r12, machine_check_handle_early) + 1: mtspr SPRN_SRR0,r12 + mtspr SPRN_SRR1,r11 +- rfid ++ RFI_TO_KERNEL + b . /* prevent speculative execution */ + 2: + /* Stack overflow. Stay on emergency stack and panic. +@@ -601,7 +601,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) +- HRFID ++ HRFI_TO_UNKNOWN + b . + #endif + +@@ -666,7 +666,7 @@ masked_##_H##interrupt: \ + ld r10,PACA_EXGEN+EX_R10(r13); \ + ld r11,PACA_EXGEN+EX_R11(r13); \ + GET_SCRATCH0(r13); \ +- ##_H##rfid; \ ++ ##_H##RFI_TO_KERNEL; \ + b . + + MASKED_INTERRUPT() +@@ -756,7 +756,7 @@ kvmppc_skip_interrupt: + addi r13, r13, 4 + mtspr SPRN_SRR0, r13 + GET_SCRATCH0(r13) +- rfid ++ RFI_TO_KERNEL + b . + + kvmppc_skip_Hinterrupt: +@@ -768,7 +768,7 @@ kvmppc_skip_Hinterrupt: + addi r13, r13, 4 + mtspr SPRN_HSRR0, r13 + GET_SCRATCH0(r13) +- hrfid ++ HRFI_TO_KERNEL + b . + #endif + +@@ -1439,7 +1439,7 @@ machine_check_handle_early: + li r3,MSR_ME + andc r10,r10,r3 /* Turn off MSR_ME */ + mtspr SPRN_SRR1,r10 +- rfid ++ RFI_TO_KERNEL + b . + 2: + /* +@@ -1457,7 +1457,7 @@ machine_check_handle_early: + */ + bl machine_check_queue_event + MACHINE_CHECK_HANDLER_WINDUP +- rfid ++ RFI_TO_USER_OR_KERNEL + 9: + /* Deliver the machine check to host kernel in V mode. */ + MACHINE_CHECK_HANDLER_WINDUP +@@ -1503,6 +1503,8 @@ slb_miss_realmode: + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- 2f ++ andi. r10,r12,MSR_PR /* check for user mode (PR != 0) */ ++ bne 1f + + .machine push + .machine "power4" +@@ -1516,7 +1518,23 @@ slb_miss_realmode: + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) +- rfid ++ RFI_TO_KERNEL ++ b . /* prevent speculative execution */ ++ ++1: ++.machine push ++.machine "power4" ++ mtcrf 0x80,r9 ++ mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ ++.machine pop ++ ++ RESTORE_PPR_PACA(PACA_EXSLB, r9) ++ ld r9,PACA_EXSLB+EX_R9(r13) ++ ld r10,PACA_EXSLB+EX_R10(r13) ++ ld r11,PACA_EXSLB+EX_R11(r13) ++ ld r12,PACA_EXSLB+EX_R12(r13) ++ ld r13,PACA_EXSLB+EX_R13(r13) ++ RFI_TO_USER + b . /* prevent speculative execution */ + + 2: mfspr r11,SPRN_SRR0 +@@ -1525,7 +1543,7 @@ slb_miss_realmode: + mtspr SPRN_SRR0,r10 + ld r10,PACAKMSR(r13) + mtspr SPRN_SRR1,r10 +- rfid ++ RFI_TO_KERNEL + b . + + unrecov_slb: +@@ -1546,6 +1564,92 @@ power4_fixup_nap: + blr + #endif + ++ .globl rfi_flush_fallback ++rfi_flush_fallback: ++ SET_SCRATCH0(r13); ++ GET_PACA(r13); ++ std r9,PACA_EXRFI+EX_R9(r13) ++ std r10,PACA_EXRFI+EX_R10(r13) ++ std r11,PACA_EXRFI+EX_R11(r13) ++ std r12,PACA_EXRFI+EX_R12(r13) ++ std r8,PACA_EXRFI+EX_R13(r13) ++ mfctr r9 ++ ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) ++ ld r11,PACA_L1D_FLUSH_SETS(r13) ++ ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) ++ /* ++ * The load adresses are at staggered offsets within cachelines, ++ * which suits some pipelines better (on others it should not ++ * hurt). ++ */ ++ addi r12,r12,8 ++ mtctr r11 ++ DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ ++ ++ /* order ld/st prior to dcbt stop all streams with flushing */ ++ sync ++1: li r8,0 ++ .rept 8 /* 8-way set associative */ ++ ldx r11,r10,r8 ++ add r8,r8,r12 ++ xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not ++ add r8,r8,r11 // Add 0, this creates a dependency on the ldx ++ .endr ++ addi r10,r10,128 /* 128 byte cache line */ ++ bdnz 1b ++ ++ mtctr r9 ++ ld r9,PACA_EXRFI+EX_R9(r13) ++ ld r10,PACA_EXRFI+EX_R10(r13) ++ ld r11,PACA_EXRFI+EX_R11(r13) ++ ld r12,PACA_EXRFI+EX_R12(r13) ++ ld r8,PACA_EXRFI+EX_R13(r13) ++ GET_SCRATCH0(r13); ++ rfid ++ ++ .globl hrfi_flush_fallback ++hrfi_flush_fallback: ++ SET_SCRATCH0(r13); ++ GET_PACA(r13); ++ std r9,PACA_EXRFI+EX_R9(r13) ++ std r10,PACA_EXRFI+EX_R10(r13) ++ std r11,PACA_EXRFI+EX_R11(r13) ++ std r12,PACA_EXRFI+EX_R12(r13) ++ std r8,PACA_EXRFI+EX_R13(r13) ++ mfctr r9 ++ ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) ++ ld r11,PACA_L1D_FLUSH_SETS(r13) ++ ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) ++ /* ++ * The load adresses are at staggered offsets within cachelines, ++ * which suits some pipelines better (on others it should not ++ * hurt). ++ */ ++ addi r12,r12,8 ++ mtctr r11 ++ DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ ++ ++ /* order ld/st prior to dcbt stop all streams with flushing */ ++ sync ++1: li r8,0 ++ .rept 8 /* 8-way set associative */ ++ ldx r11,r10,r8 ++ add r8,r8,r12 ++ xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not ++ add r8,r8,r11 // Add 0, this creates a dependency on the ldx ++ .endr ++ addi r10,r10,128 /* 128 byte cache line */ ++ bdnz 1b ++ ++ mtctr r9 ++ ld r9,PACA_EXRFI+EX_R9(r13) ++ ld r10,PACA_EXRFI+EX_R10(r13) ++ ld r11,PACA_EXRFI+EX_R11(r13) ++ ld r12,PACA_EXRFI+EX_R12(r13) ++ ld r8,PACA_EXRFI+EX_R13(r13) ++ GET_SCRATCH0(r13); ++ hrfid ++ + /* + * Hash table stuff + */ +diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S +index db475d41b57a..107588295b39 100644 +--- a/arch/powerpc/kernel/misc_64.S ++++ b/arch/powerpc/kernel/misc_64.S +@@ -66,7 +66,7 @@ PPC64_CACHES: + * flush all bytes from start through stop-1 inclusive + */ + +-_KPROBE(flush_icache_range) ++_KPROBE_TOC(flush_icache_range) + BEGIN_FTR_SECTION + PURGE_PREFETCHED_INS + blr +@@ -117,7 +117,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) + * + * flush all bytes from start to stop-1 inclusive + */ +-_GLOBAL(flush_dcache_range) ++_GLOBAL_TOC(flush_dcache_range) + + /* + * Flush the data cache to memory +@@ -701,31 +701,3 @@ _GLOBAL(kexec_sequence) + li r5,0 + blr /* image->start(physid, image->start, 0); */ + #endif /* CONFIG_KEXEC */ +- +-#ifdef CONFIG_MODULES +-#if defined(_CALL_ELF) && _CALL_ELF == 2 +- +-#ifdef CONFIG_MODVERSIONS +-.weak __crc_TOC. +-.section "___kcrctab+TOC.","a" +-.globl __kcrctab_TOC. +-__kcrctab_TOC.: +- .llong __crc_TOC. +-#endif +- +-/* +- * Export a fake .TOC. since both modpost and depmod will complain otherwise. +- * Both modpost and depmod strip the leading . so we do the same here. +- */ +-.section "__ksymtab_strings","a" +-__kstrtab_TOC.: +- .asciz "TOC." +- +-.section "___ksymtab+TOC.","a" +-/* This symbol name is important: it's used by modpost to find exported syms */ +-.globl __ksymtab_TOC. +-__ksymtab_TOC.: +- .llong 0 /* .value */ +- .llong __kstrtab_TOC. +-#endif /* ELFv2 */ +-#endif /* MODULES */ +diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c +index e4f7d4eed20c..08b7a40de5f8 100644 +--- a/arch/powerpc/kernel/module_64.c ++++ b/arch/powerpc/kernel/module_64.c +@@ -326,7 +326,10 @@ static void dedotify_versions(struct modversion_info *vers, + } + } + +-/* Undefined symbols which refer to .funcname, hack to funcname (or .TOC.) */ ++/* ++ * Undefined symbols which refer to .funcname, hack to funcname. Make .TOC. ++ * seem to be defined (value set later). ++ */ + static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) + { + unsigned int i; +@@ -334,8 +337,11 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) + for (i = 1; i < numsyms; i++) { + if (syms[i].st_shndx == SHN_UNDEF) { + char *name = strtab + syms[i].st_name; +- if (name[0] == '.') ++ if (name[0] == '.') { ++ if (strcmp(name+1, "TOC.") == 0) ++ syms[i].st_shndx = SHN_ABS; + syms[i].st_name++; ++ } + } + } + } +@@ -351,7 +357,7 @@ static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs, + numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym); + + for (i = 1; i < numsyms; i++) { +- if (syms[i].st_shndx == SHN_UNDEF ++ if (syms[i].st_shndx == SHN_ABS + && strcmp(strtab + syms[i].st_name, "TOC.") == 0) + return &syms[i]; + } +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index cf788d7d7e56..a9b10812cbfd 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -209,7 +209,8 @@ void enable_kernel_vsx(void) + WARN_ON(preemptible()); + + #ifdef CONFIG_SMP +- if (current->thread.regs && (current->thread.regs->msr & MSR_VSX)) ++ if (current->thread.regs && ++ (current->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP))) + giveup_vsx(current); + else + giveup_vsx(NULL); /* just enable vsx for kernel - force */ +@@ -231,7 +232,7 @@ void flush_vsx_to_thread(struct task_struct *tsk) + { + if (tsk->thread.regs) { + preempt_disable(); +- if (tsk->thread.regs->msr & MSR_VSX) { ++ if (tsk->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP)) { + #ifdef CONFIG_SMP + BUG_ON(tsk != current); + #endif +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index a20823210ac0..df4a87eb8da4 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -834,4 +835,142 @@ static int __init disable_hardlockup_detector(void) + return 0; + } + early_initcall(disable_hardlockup_detector); ++ ++#ifdef CONFIG_PPC_BOOK3S_64 ++static enum l1d_flush_type enabled_flush_types; ++static void *l1d_flush_fallback_area; ++static bool no_rfi_flush; ++bool rfi_flush; ++ ++static int __init handle_no_rfi_flush(char *p) ++{ ++ pr_info("rfi-flush: disabled on command line."); ++ no_rfi_flush = true; ++ return 0; ++} ++early_param("no_rfi_flush", handle_no_rfi_flush); ++ ++/* ++ * The RFI flush is not KPTI, but because users will see doco that says to use ++ * nopti we hijack that option here to also disable the RFI flush. ++ */ ++static int __init handle_no_pti(char *p) ++{ ++ pr_info("rfi-flush: disabling due to 'nopti' on command line.\n"); ++ handle_no_rfi_flush(NULL); ++ return 0; ++} ++early_param("nopti", handle_no_pti); ++ ++static void do_nothing(void *unused) ++{ ++ /* ++ * We don't need to do the flush explicitly, just enter+exit kernel is ++ * sufficient, the RFI exit handlers will do the right thing. ++ */ ++} ++ ++void rfi_flush_enable(bool enable) ++{ ++ if (rfi_flush == enable) ++ return; ++ ++ if (enable) { ++ do_rfi_flush_fixups(enabled_flush_types); ++ on_each_cpu(do_nothing, NULL, 1); ++ } else ++ do_rfi_flush_fixups(L1D_FLUSH_NONE); ++ ++ rfi_flush = enable; ++} ++ ++static void init_fallback_flush(void) ++{ ++ u64 l1d_size, limit; ++ int cpu; ++ ++ l1d_size = ppc64_caches.dsize; ++ limit = min(safe_stack_limit(), ppc64_rma_size); ++ ++ /* ++ * Align to L1d size, and size it at 2x L1d size, to catch possible ++ * hardware prefetch runoff. We don't have a recipe for load patterns to ++ * reliably avoid the prefetcher. ++ */ ++ l1d_flush_fallback_area = __va(memblock_alloc_base(l1d_size * 2, l1d_size, limit)); ++ memset(l1d_flush_fallback_area, 0, l1d_size * 2); ++ ++ for_each_possible_cpu(cpu) { ++ /* ++ * The fallback flush is currently coded for 8-way ++ * associativity. Different associativity is possible, but it ++ * will be treated as 8-way and may not evict the lines as ++ * effectively. ++ * ++ * 128 byte lines are mandatory. ++ */ ++ u64 c = l1d_size / 8; ++ ++ paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area; ++ paca[cpu].l1d_flush_congruence = c; ++ paca[cpu].l1d_flush_sets = c / 128; ++ } ++} ++ ++void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) ++{ ++ if (types & L1D_FLUSH_FALLBACK) { ++ pr_info("rfi-flush: Using fallback displacement flush\n"); ++ init_fallback_flush(); ++ } ++ ++ if (types & L1D_FLUSH_ORI) ++ pr_info("rfi-flush: Using ori type flush\n"); ++ ++ if (types & L1D_FLUSH_MTTRIG) ++ pr_info("rfi-flush: Using mttrig type flush\n"); ++ ++ enabled_flush_types = types; ++ ++ if (!no_rfi_flush) ++ rfi_flush_enable(enable); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int rfi_flush_set(void *data, u64 val) ++{ ++ if (val == 1) ++ rfi_flush_enable(true); ++ else if (val == 0) ++ rfi_flush_enable(false); ++ else ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int rfi_flush_get(void *data, u64 *val) ++{ ++ *val = rfi_flush ? 1 : 0; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n"); ++ ++static __init int rfi_flush_debugfs_init(void) ++{ ++ debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush); ++ return 0; ++} ++device_initcall(rfi_flush_debugfs_init); ++#endif ++ ++ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (rfi_flush) ++ return sprintf(buf, "Mitigation: RFI Flush\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} ++#endif /* CONFIG_PPC_BOOK3S_64 */ + #endif +diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S +index d41fd0af8980..072a23a17350 100644 +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -72,6 +72,15 @@ SECTIONS + /* Read-only data */ + RODATA + ++#ifdef CONFIG_PPC64 ++ . = ALIGN(8); ++ __rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) { ++ __start___rfi_flush_fixup = .; ++ *(__rfi_flush_fixup) ++ __stop___rfi_flush_fixup = .; ++ } ++#endif ++ + EXCEPTION_TABLE(0) + + NOTES :kernel :notes +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index ffab9269bfe4..4463718ae614 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -64,7 +64,7 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline) + mtmsrd r0,1 /* clear RI in MSR */ + mtsrr0 r5 + mtsrr1 r6 +- RFI ++ RFI_TO_KERNEL + + kvmppc_call_hv_entry: + ld r4, HSTATE_KVM_VCPU(r13) +@@ -170,7 +170,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + mtsrr0 r8 + mtsrr1 r7 + beq cr1, 13f /* machine check */ +- RFI ++ RFI_TO_KERNEL + + /* On POWER7, we have external interrupts set to use HSRR0/1 */ + 11: mtspr SPRN_HSRR0, r8 +@@ -965,8 +965,7 @@ BEGIN_FTR_SECTION + END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) + ld r0, VCPU_GPR(R0)(r4) + ld r4, VCPU_GPR(R4)(r4) +- +- hrfid ++ HRFI_TO_GUEST + b . + + secondary_too_late: +diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S +index 16c4d88ba27d..a328f99a887c 100644 +--- a/arch/powerpc/kvm/book3s_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_rmhandlers.S +@@ -46,6 +46,9 @@ + + #define FUNC(name) name + ++#define RFI_TO_KERNEL RFI ++#define RFI_TO_GUEST RFI ++ + .macro INTERRUPT_TRAMPOLINE intno + + .global kvmppc_trampoline_\intno +@@ -141,7 +144,7 @@ kvmppc_handler_skip_ins: + GET_SCRATCH0(r13) + + /* And get back into the code */ +- RFI ++ RFI_TO_KERNEL + #endif + + /* +@@ -164,6 +167,6 @@ _GLOBAL_TOC(kvmppc_entry_trampoline) + ori r5, r5, MSR_EE + mtsrr0 r7 + mtsrr1 r6 +- RFI ++ RFI_TO_KERNEL + + #include "book3s_segment.S" +diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S +index ca8f174289bb..7c982956d709 100644 +--- a/arch/powerpc/kvm/book3s_segment.S ++++ b/arch/powerpc/kvm/book3s_segment.S +@@ -156,7 +156,7 @@ no_dcbz32_on: + PPC_LL r9, SVCPU_R9(r3) + PPC_LL r3, (SVCPU_R3)(r3) + +- RFI ++ RFI_TO_GUEST + kvmppc_handler_trampoline_enter_end: + + +@@ -389,5 +389,5 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) + cmpwi r12, BOOK3S_INTERRUPT_DOORBELL + beqa BOOK3S_INTERRUPT_DOORBELL + +- RFI ++ RFI_TO_KERNEL + kvmppc_handler_trampoline_exit_end: +diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c +index 7ce3870d7ddd..a18d648d31a6 100644 +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + + struct fixup_entry { +@@ -113,6 +114,47 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) + } + } + ++#ifdef CONFIG_PPC_BOOK3S_64 ++void do_rfi_flush_fixups(enum l1d_flush_type types) ++{ ++ unsigned int instrs[3], *dest; ++ long *start, *end; ++ int i; ++ ++ start = PTRRELOC(&__start___rfi_flush_fixup), ++ end = PTRRELOC(&__stop___rfi_flush_fixup); ++ ++ instrs[0] = 0x60000000; /* nop */ ++ instrs[1] = 0x60000000; /* nop */ ++ instrs[2] = 0x60000000; /* nop */ ++ ++ if (types & L1D_FLUSH_FALLBACK) ++ /* b .+16 to fallback flush */ ++ instrs[0] = 0x48000010; ++ ++ i = 0; ++ if (types & L1D_FLUSH_ORI) { ++ instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ ++ instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/ ++ } ++ ++ if (types & L1D_FLUSH_MTTRIG) ++ instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */ ++ ++ for (i = 0; start < end; start++, i++) { ++ dest = (void *)start + *start; ++ ++ pr_devel("patching dest %lx\n", (unsigned long)dest); ++ ++ patch_instruction(dest, instrs[0]); ++ patch_instruction(dest + 1, instrs[1]); ++ patch_instruction(dest + 2, instrs[2]); ++ } ++ ++ printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i); ++} ++#endif /* CONFIG_PPC_BOOK3S_64 */ ++ + void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) + { + long *start, *end; +diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c +index f48afc06ba14..30c6b3b7be90 100644 +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -35,13 +35,63 @@ + #include + #include + #include ++#include ++#include + + #include "powernv.h" + ++static void pnv_setup_rfi_flush(void) ++{ ++ struct device_node *np, *fw_features; ++ enum l1d_flush_type type; ++ int enable; ++ ++ /* Default to fallback in case fw-features are not available */ ++ type = L1D_FLUSH_FALLBACK; ++ enable = 1; ++ ++ np = of_find_node_by_name(NULL, "ibm,opal"); ++ fw_features = of_get_child_by_name(np, "fw-features"); ++ of_node_put(np); ++ ++ if (fw_features) { ++ np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2"); ++ if (np && of_property_read_bool(np, "enabled")) ++ type = L1D_FLUSH_MTTRIG; ++ ++ of_node_put(np); ++ ++ np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0"); ++ if (np && of_property_read_bool(np, "enabled")) ++ type = L1D_FLUSH_ORI; ++ ++ of_node_put(np); ++ ++ /* Enable unless firmware says NOT to */ ++ enable = 2; ++ np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0"); ++ if (np && of_property_read_bool(np, "disabled")) ++ enable--; ++ ++ of_node_put(np); ++ ++ np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1"); ++ if (np && of_property_read_bool(np, "disabled")) ++ enable--; ++ ++ of_node_put(np); ++ of_node_put(fw_features); ++ } ++ ++ setup_rfi_flush(type, enable > 0); ++} ++ + static void __init pnv_setup_arch(void) + { + set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); + ++ pnv_setup_rfi_flush(); ++ + /* Initialize SMP */ + pnv_smp_init(); + +diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c +index 36df46eaba24..dd2545fc9947 100644 +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -499,6 +499,39 @@ static void __init find_and_init_phbs(void) + of_pci_check_probe_only(); + } + ++static void pseries_setup_rfi_flush(void) ++{ ++ struct h_cpu_char_result result; ++ enum l1d_flush_type types; ++ bool enable; ++ long rc; ++ ++ /* Enable by default */ ++ enable = true; ++ ++ rc = plpar_get_cpu_characteristics(&result); ++ if (rc == H_SUCCESS) { ++ types = L1D_FLUSH_NONE; ++ ++ if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) ++ types |= L1D_FLUSH_MTTRIG; ++ if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) ++ types |= L1D_FLUSH_ORI; ++ ++ /* Use fallback if nothing set in hcall */ ++ if (types == L1D_FLUSH_NONE) ++ types = L1D_FLUSH_FALLBACK; ++ ++ if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) ++ enable = false; ++ } else { ++ /* Default to fallback if case hcall is not available */ ++ types = L1D_FLUSH_FALLBACK; ++ } ++ ++ setup_rfi_flush(types, enable); ++} ++ + static void __init pSeries_setup_arch(void) + { + set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); +@@ -515,7 +548,9 @@ static void __init pSeries_setup_arch(void) + + fwnmi_init(); + +- /* By default, only probe PCI (can be overriden by rtas_pci) */ ++ pseries_setup_rfi_flush(); ++ ++ /* By default, only probe PCI (can be overridden by rtas_pci) */ + pci_add_flags(PCI_PROBE_ONLY); + + /* Find and initialize PCI host bridges */ +diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c +index ff639342a8be..c5b997757988 100644 +--- a/arch/sh/kernel/traps_32.c ++++ b/arch/sh/kernel/traps_32.c +@@ -607,7 +607,8 @@ asmlinkage void do_divide_error(unsigned long r4) + break; + } + +- force_sig_info(SIGFPE, &info, current); ++ info.si_signo = SIGFPE; ++ force_sig_info(info.si_signo, &info, current); + } + #endif + +diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c +index 4264a3d59589..7c064887b783 100644 +--- a/arch/x86/crypto/poly1305_glue.c ++++ b/arch/x86/crypto/poly1305_glue.c +@@ -164,7 +164,6 @@ static struct shash_alg alg = { + .init = poly1305_simd_init, + .update = poly1305_simd_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_simd_desc_ctx), + .base = { + .cra_name = "poly1305", +diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h +index b9c6c7a6f5a6..1c79c8add0eb 100644 +--- a/arch/x86/include/asm/asm.h ++++ b/arch/x86/include/asm/asm.h +@@ -11,10 +11,12 @@ + # define __ASM_FORM_COMMA(x) " " #x "," + #endif + +-#ifdef CONFIG_X86_32 ++#ifndef __x86_64__ ++/* 32 bit */ + # define __ASM_SEL(a,b) __ASM_FORM(a) + # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a) + #else ++/* 64 bit */ + # define __ASM_SEL(a,b) __ASM_FORM(b) + # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b) + #endif +diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h +index 9ee85066f407..62210da19a92 100644 +--- a/arch/x86/include/asm/vsyscall.h ++++ b/arch/x86/include/asm/vsyscall.h +@@ -13,7 +13,6 @@ extern void map_vsyscall(void); + */ + extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address); + extern bool vsyscall_enabled(void); +-extern unsigned long vsyscall_pgprot; + #else + static inline void map_vsyscall(void) {} + static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) +@@ -22,5 +21,6 @@ static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) + } + static inline bool vsyscall_enabled(void) { return false; } + #endif ++extern unsigned long vsyscall_pgprot; + + #endif /* _ASM_X86_VSYSCALL_H */ +diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c +index b3e94ef461fd..ce5f8a2e7ae6 100644 +--- a/arch/x86/kernel/cpu/microcode/core.c ++++ b/arch/x86/kernel/cpu/microcode/core.c +@@ -44,7 +44,7 @@ + + static struct microcode_ops *microcode_ops; + +-static bool dis_ucode_ldr; ++static bool dis_ucode_ldr = true; + + static int __init disable_loader(char *str) + { +@@ -81,6 +81,7 @@ struct cpu_info_ctx { + + static bool __init check_loader_disabled_bsp(void) + { ++ u32 a, b, c, d; + #ifdef CONFIG_X86_32 + const char *cmdline = (const char *)__pa_nodebug(boot_command_line); + const char *opt = "dis_ucode_ldr"; +@@ -93,8 +94,20 @@ static bool __init check_loader_disabled_bsp(void) + bool *res = &dis_ucode_ldr; + #endif + +- if (cmdline_find_option_bool(cmdline, option)) +- *res = true; ++ a = 1; ++ c = 0; ++ native_cpuid(&a, &b, &c, &d); ++ ++ /* ++ * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not ++ * completely accurate as xen pv guests don't see that CPUID bit set but ++ * that's good enough as they don't land on the BSP path anyway. ++ */ ++ if (c & BIT(31)) ++ return *res; ++ ++ if (cmdline_find_option_bool(cmdline, option) <= 0) ++ *res = false; + + return *res; + } +@@ -122,9 +135,7 @@ void __init load_ucode_bsp(void) + { + int vendor; + unsigned int family; +- +- if (check_loader_disabled_bsp()) +- return; ++ bool intel = true; + + if (!have_cpuid_p()) + return; +@@ -134,16 +145,27 @@ void __init load_ucode_bsp(void) + + switch (vendor) { + case X86_VENDOR_INTEL: +- if (family >= 6) +- load_ucode_intel_bsp(); ++ if (family < 6) ++ return; + break; ++ + case X86_VENDOR_AMD: +- if (family >= 0x10) +- load_ucode_amd_bsp(family); ++ if (family < 0x10) ++ return; ++ intel = false; + break; ++ + default: +- break; ++ return; + } ++ ++ if (check_loader_disabled_bsp()) ++ return; ++ ++ if (intel) ++ load_ucode_intel_bsp(); ++ else ++ load_ucode_amd_bsp(family); + } + + static bool check_loader_disabled_ap(void) +@@ -162,9 +184,6 @@ void load_ucode_ap(void) + if (check_loader_disabled_ap()) + return; + +- if (!have_cpuid_p()) +- return; +- + vendor = x86_vendor(); + family = x86_family(); + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index f8d785aa2e96..2a1a8737015b 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -4595,14 +4595,15 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu, + + if (is_guest_mode(vcpu) && + vector == vmx->nested.posted_intr_nv) { +- /* the PIR and ON have been set by L1. */ +- kvm_vcpu_trigger_posted_interrupt(vcpu); + /* + * If a posted intr is not recognized by hardware, + * we will accomplish it in the next vmentry. + */ + vmx->nested.pi_pending = true; + kvm_make_request(KVM_REQ_EVENT, vcpu); ++ /* the PIR and ON have been set by L1. */ ++ if (!kvm_vcpu_trigger_posted_interrupt(vcpu)) ++ kvm_vcpu_kick(vcpu); + return 0; + } + return -1; +diff --git a/arch/x86/mm/kaiser.c b/arch/x86/mm/kaiser.c +index 2298434f7bdb..7a72e32e4806 100644 +--- a/arch/x86/mm/kaiser.c ++++ b/arch/x86/mm/kaiser.c +@@ -363,7 +363,7 @@ void __init kaiser_init(void) + kaiser_add_user_map_ptrs_early(__entry_text_start, __entry_text_end, + __PAGE_KERNEL_RX); + +-#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) ++#ifdef CONFIG_FUNCTION_GRAPH_TRACER + kaiser_add_user_map_ptrs_early(__irqentry_text_start, + __irqentry_text_end, + __PAGE_KERNEL_RX); +diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h +index b39531babec0..72bfc1cbc2b5 100644 +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -109,7 +109,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) + { + int ret = 0; +- u32 prev; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; +@@ -120,26 +119,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + + __asm__ __volatile__ ( + " # futex_atomic_cmpxchg_inatomic\n" +- "1: l32i %1, %3, 0\n" +- " mov %0, %5\n" +- " wsr %1, scompare1\n" +- "2: s32c1i %0, %3, 0\n" +- "3:\n" ++ " wsr %5, scompare1\n" ++ "1: s32c1i %1, %4, 0\n" ++ " s32i %1, %6, 0\n" ++ "2:\n" + " .section .fixup,\"ax\"\n" + " .align 4\n" +- "4: .long 3b\n" +- "5: l32r %1, 4b\n" +- " movi %0, %6\n" ++ "3: .long 2b\n" ++ "4: l32r %1, 3b\n" ++ " movi %0, %7\n" + " jx %1\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .long 1b,5b,2b,5b\n" ++ " .long 1b,4b\n" + " .previous\n" +- : "+r" (ret), "=&r" (prev), "+m" (*uaddr) +- : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT) ++ : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval) ++ : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT) + : "memory"); + +- *uval = prev; + return ret; + } + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index f9caf0f74199..7006dbfd39bd 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -637,5 +637,16 @@ struct hash_alg_common *ahash_attr_alg(struct rtattr *rta, u32 type, u32 mask) + } + EXPORT_SYMBOL_GPL(ahash_attr_alg); + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg) ++{ ++ struct crypto_alg *alg = &halg->base; ++ ++ if (alg->cra_type != &crypto_ahash_type) ++ return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg)); ++ ++ return __crypto_ahash_alg(alg)->setkey != NULL; ++} ++EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey); ++ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index 26a504db3f53..10a5a3eb675a 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -654,7 +654,8 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + inst->alg.finup = cryptd_hash_finup_enqueue; + inst->alg.export = cryptd_hash_export; + inst->alg.import = cryptd_hash_import; +- inst->alg.setkey = cryptd_hash_setkey; ++ if (crypto_shash_alg_has_setkey(salg)) ++ inst->alg.setkey = cryptd_hash_setkey; + inst->alg.digest = cryptd_hash_digest_enqueue; + + err = ahash_register_instance(tmpl, inst); +diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c +index 2df9835dfbc0..bca99238948f 100644 +--- a/crypto/poly1305_generic.c ++++ b/crypto/poly1305_generic.c +@@ -51,17 +51,6 @@ int crypto_poly1305_init(struct shash_desc *desc) + } + EXPORT_SYMBOL_GPL(crypto_poly1305_init); + +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen) +-{ +- /* Poly1305 requires a unique key for each tag, which implies that +- * we can't set it on the tfm that gets accessed by multiple users +- * simultaneously. Instead we expect the key as the first 32 bytes in +- * the update() call. */ +- return -ENOTSUPP; +-} +-EXPORT_SYMBOL_GPL(crypto_poly1305_setkey); +- + static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) + { + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ +@@ -80,6 +69,11 @@ static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key) + dctx->s[3] = le32_to_cpuvp(key + 12); + } + ++/* ++ * Poly1305 requires a unique key for each tag, which implies that we can't set ++ * it on the tfm that gets accessed by multiple users simultaneously. Instead we ++ * expect the key as the first 32 bytes in the update() call. ++ */ + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen) + { +@@ -285,7 +279,6 @@ static struct shash_alg poly1305_alg = { + .init = crypto_poly1305_init, + .update = crypto_poly1305_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_desc_ctx), + .base = { + .cra_name = "poly1305", +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index f522828d45c9..1d92b5d2d6bd 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -291,11 +291,13 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE], + } + + sg_init_table(sg, np + 1); +- np--; ++ if (rem) ++ np--; + for (k = 0; k < np; k++) + sg_set_buf(&sg[k + 1], xbuf[k], PAGE_SIZE); + +- sg_set_buf(&sg[k + 1], xbuf[k], rem); ++ if (rem) ++ sg_set_buf(&sg[k + 1], xbuf[k], rem); + } + + static void test_aead_speed(const char *algo, int enc, unsigned int secs, +diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c +index 2fa8304171e0..7a3431018e0a 100644 +--- a/drivers/acpi/sbshc.c ++++ b/drivers/acpi/sbshc.c +@@ -275,8 +275,8 @@ static int acpi_smbus_hc_add(struct acpi_device *device) + device->driver_data = hc; + + acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); +- printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", +- hc->ec, hc->offset, hc->query_bit); ++ dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n", ++ hc->offset, hc->query_bit); + + return 0; + } +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 60a15831c009..8ddf5d5c94fd 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -260,9 +260,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ +- { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ ++ { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH M AHCI */ + { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ +- { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ ++ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH M RAID */ + { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ +@@ -285,9 +285,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ +- { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ ++ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT M AHCI */ + { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ +- { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ ++ { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT M RAID */ + { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ +@@ -296,20 +296,20 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ + { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ +- { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ ++ { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point M AHCI */ + { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ +- { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point M RAID */ + { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ +- { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ +@@ -350,21 +350,21 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ +- { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ +- { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H M AHCI */ + { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ +- { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H M RAID */ + { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ +@@ -382,6 +382,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ ++ { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ ++ { PCI_VDEVICE(INTEL, 0x0f22), board_ahci }, /* Bay Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x0f23), board_ahci }, /* Bay Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci }, /* Cherry Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci }, /* Apollo Lake AHCI */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c +index d06c62eccdf0..156968a6655d 100644 +--- a/drivers/block/pktcdvd.c ++++ b/drivers/block/pktcdvd.c +@@ -2779,7 +2779,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) + pd->pkt_dev = MKDEV(pktdev_major, idx); + ret = pkt_new_dev(pd, dev); + if (ret) +- goto out_new_dev; ++ goto out_mem2; + + /* inherit events of the host device */ + disk->events = pd->bdev->bd_disk->events; +@@ -2797,8 +2797,6 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) + mutex_unlock(&ctl_mutex); + return 0; + +-out_new_dev: +- blk_cleanup_queue(disk->queue); + out_mem2: + put_disk(disk); + out_mem: +diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c +index 7b624423a7e8..89ccb604045c 100644 +--- a/drivers/bluetooth/btsdio.c ++++ b/drivers/bluetooth/btsdio.c +@@ -31,6 +31,7 @@ + #include + #include + ++#include + #include + #include + +@@ -291,6 +292,14 @@ static int btsdio_probe(struct sdio_func *func, + tuple = tuple->next; + } + ++ /* BCM43341 devices soldered onto the PCB (non-removable) use an ++ * uart connection for bluetooth, ignore the BT SDIO interface. ++ */ ++ if (func->vendor == SDIO_VENDOR_ID_BROADCOM && ++ func->device == SDIO_DEVICE_ID_BROADCOM_43341 && ++ !mmc_card_is_removable(func->card->host)) ++ return -ENODEV; ++ + data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 1ccad79ce77c..54cef3dc0beb 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -23,6 +23,7 @@ + + #include + #include ++#include + #include + #include + +@@ -360,8 +361,8 @@ static const struct usb_device_id blacklist_table[] = { + #define BTUSB_FIRMWARE_LOADED 7 + #define BTUSB_FIRMWARE_FAILED 8 + #define BTUSB_BOOTING 9 +-#define BTUSB_RESET_RESUME 10 +-#define BTUSB_DIAG_RUNNING 11 ++#define BTUSB_DIAG_RUNNING 10 ++#define BTUSB_OOB_WAKE_ENABLED 11 + + struct btusb_data { + struct hci_dev *hdev; +@@ -2972,9 +2973,9 @@ static int btusb_probe(struct usb_interface *intf, + + /* QCA Rome devices lose their updated firmware over suspend, + * but the USB hub doesn't notice any status change. +- * Explicitly request a device reset on resume. ++ * explicitly request a device reset on resume. + */ +- set_bit(BTUSB_RESET_RESUME, &data->flags); ++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + } + + #ifdef CONFIG_BT_HCIBTUSB_RTL +@@ -2985,7 +2986,7 @@ static int btusb_probe(struct usb_interface *intf, + * but the USB hub doesn't notice any status change. + * Explicitly request a device reset on resume. + */ +- set_bit(BTUSB_RESET_RESUME, &data->flags); ++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + } + #endif + +@@ -3142,14 +3143,6 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) + btusb_stop_traffic(data); + usb_kill_anchored_urbs(&data->tx_anchor); + +- /* Optionally request a device reset on resume, but only when +- * wakeups are disabled. If wakeups are enabled we assume the +- * device will stay powered up throughout suspend. +- */ +- if (test_bit(BTUSB_RESET_RESUME, &data->flags) && +- !device_may_wakeup(&data->udev->dev)) +- data->udev->reset_resume = 1; +- + return 0; + } + +diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c +index 53e61459c69f..ee87eb77095c 100644 +--- a/drivers/crypto/caam/ctrl.c ++++ b/drivers/crypto/caam/ctrl.c +@@ -224,12 +224,16 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask, + * without any error (HW optimizations for later + * CAAM eras), then try again. + */ ++ if (ret) ++ break; ++ + rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK; + if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) || +- !(rdsta_val & (1 << sh_idx))) ++ !(rdsta_val & (1 << sh_idx))) { + ret = -EAGAIN; +- if (ret) + break; ++ } ++ + dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx); + /* Clear the contents before recreating the descriptor */ + memset(desc, 0x00, CAAM_CMD_SZ * 7); +diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c +index 7254c20007f8..6796eb1a8a4c 100644 +--- a/drivers/dma/dmatest.c ++++ b/drivers/dma/dmatest.c +@@ -329,7 +329,7 @@ static void dmatest_callback(void *arg) + { + struct dmatest_done *done = arg; + struct dmatest_thread *thread = +- container_of(arg, struct dmatest_thread, done_wait); ++ container_of(done, struct dmatest_thread, test_done); + if (!thread->done) { + done->done = true; + wake_up_all(done->wait); +diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c +index cda6dab5067a..6b65a102b49d 100644 +--- a/drivers/edac/octeon_edac-lmc.c ++++ b/drivers/edac/octeon_edac-lmc.c +@@ -79,6 +79,7 @@ static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci) + if (!pvt->inject) + int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx)); + else { ++ int_reg.u64 = 0; + if (pvt->error_type == 1) + int_reg.s.sec_err = 1; + if (pvt->error_type == 2) +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +index 9befd624a5f0..6fab07935d16 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +@@ -371,6 +371,31 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) + rcrtc->started = true; + } + ++static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc) ++{ ++ struct rcar_du_device *rcdu = rcrtc->group->dev; ++ struct drm_crtc *crtc = &rcrtc->crtc; ++ u32 status; ++ /* Make sure vblank interrupts are enabled. */ ++ drm_crtc_vblank_get(crtc); ++ /* ++ * Disable planes and calculate how many vertical blanking interrupts we ++ * have to wait for. If a vertical blanking interrupt has been triggered ++ * but not processed yet, we don't know whether it occurred before or ++ * after the planes got disabled. We thus have to wait for two vblank ++ * interrupts in that case. ++ */ ++ spin_lock_irq(&rcrtc->vblank_lock); ++ rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); ++ status = rcar_du_crtc_read(rcrtc, DSSR); ++ rcrtc->vblank_count = status & DSSR_VBK ? 2 : 1; ++ spin_unlock_irq(&rcrtc->vblank_lock); ++ if (!wait_event_timeout(rcrtc->vblank_wait, rcrtc->vblank_count == 0, ++ msecs_to_jiffies(100))) ++ dev_warn(rcdu->dev, "vertical blanking timeout\n"); ++ drm_crtc_vblank_put(crtc); ++} ++ + static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) + { + struct drm_crtc *crtc = &rcrtc->crtc; +@@ -379,17 +404,16 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) + return; + + /* Disable all planes and wait for the change to take effect. This is +- * required as the DSnPR registers are updated on vblank, and no vblank +- * will occur once the CRTC is stopped. Disabling planes when starting +- * the CRTC thus wouldn't be enough as it would start scanning out +- * immediately from old frame buffers until the next vblank. ++ * required as the plane enable registers are updated on vblank, and no ++ * vblank will occur once the CRTC is stopped. Disabling planes when ++ * starting the CRTC thus wouldn't be enough as it would start scanning ++ * out immediately from old frame buffers until the next vblank. + * + * This increases the CRTC stop delay, especially when multiple CRTCs + * are stopped in one operation as we now wait for one vblank per CRTC. + * Whether this can be improved needs to be researched. + */ +- rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); +- drm_crtc_wait_one_vblank(crtc); ++ rcar_du_crtc_disable_planes(rcrtc); + + /* Disable vertical blanking interrupt reporting. We first need to wait + * for page flip completion before stopping the CRTC as userspace +@@ -528,10 +552,26 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) + irqreturn_t ret = IRQ_NONE; + u32 status; + ++ spin_lock(&rcrtc->vblank_lock); ++ + status = rcar_du_crtc_read(rcrtc, DSSR); + rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK); + +- if (status & DSSR_FRM) { ++ if (status & DSSR_VBK) { ++ /* ++ * Wake up the vblank wait if the counter reaches 0. This must ++ * be protected by the vblank_lock to avoid races in ++ * rcar_du_crtc_disable_planes(). ++ */ ++ if (rcrtc->vblank_count) { ++ if (--rcrtc->vblank_count == 0) ++ wake_up(&rcrtc->vblank_wait); ++ } ++ } ++ ++ spin_unlock(&rcrtc->vblank_lock); ++ ++ if (status & DSSR_VBK) { + drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index); + rcar_du_crtc_finish_page_flip(rcrtc); + ret = IRQ_HANDLED; +@@ -585,6 +625,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) + } + + init_waitqueue_head(&rcrtc->flip_wait); ++ init_waitqueue_head(&rcrtc->vblank_wait); ++ spin_lock_init(&rcrtc->vblank_lock); + + rcrtc->group = rgrp; + rcrtc->mmio_offset = mmio_offsets[index]; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +index 2bbe3f5aab65..be22ce33b70a 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +@@ -15,6 +15,7 @@ + #define __RCAR_DU_CRTC_H__ + + #include ++#include + #include + + #include +@@ -32,6 +33,9 @@ struct rcar_du_group; + * @started: whether the CRTC has been started and is running + * @event: event to post when the pending page flip completes + * @flip_wait: wait queue used to signal page flip completion ++ * @vblank_lock: protects vblank_wait and vblank_count ++ * @vblank_wait: wait queue used to signal vertical blanking ++ * @vblank_count: number of vertical blanking interrupts to wait for + * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC + * @enabled: whether the CRTC is enabled, used to control system resume + * @group: CRTC group this CRTC belongs to +@@ -48,6 +52,10 @@ struct rcar_du_crtc { + struct drm_pending_vblank_event *event; + wait_queue_head_t flip_wait; + ++ spinlock_t vblank_lock; ++ wait_queue_head_t vblank_wait; ++ unsigned int vblank_count; ++ + unsigned int outputs; + bool enabled; + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 3ba486d0ec6f..6861b74e2b61 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2308,7 +2308,6 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, +- { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, +@@ -2578,6 +2577,17 @@ bool hid_ignore(struct hid_device *hdev) + strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0) + return true; + break; ++ case USB_VENDOR_ID_ELAN: ++ /* ++ * Many Elan devices have a product id of 0x0401 and are handled ++ * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev ++ * is not (and cannot be) handled by that driver -> ++ * Ignore all 0x0401 devs except for the ELAN0800 dev. ++ */ ++ if (hdev->product == 0x0401 && ++ strncmp(hdev->name, "ELAN0800", 8) != 0) ++ return true; ++ break; + } + + if (hdev->type == HID_TYPE_USBMOUSE && +diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c +index 7979e5d6498b..7ca359391535 100644 +--- a/drivers/media/dvb-frontends/ts2020.c ++++ b/drivers/media/dvb-frontends/ts2020.c +@@ -369,7 +369,7 @@ static int ts2020_read_tuner_gain(struct dvb_frontend *fe, unsigned v_agc, + gain2 = clamp_t(long, gain2, 0, 13); + v_agc = clamp_t(long, v_agc, 400, 1100); + +- *_gain = -(gain1 * 2330 + ++ *_gain = -((__s64)gain1 * 2330 + + gain2 * 3500 + + v_agc * 24 / 10 * 10 + + 10000); +@@ -387,7 +387,7 @@ static int ts2020_read_tuner_gain(struct dvb_frontend *fe, unsigned v_agc, + gain3 = clamp_t(long, gain3, 0, 6); + v_agc = clamp_t(long, v_agc, 600, 1600); + +- *_gain = -(gain1 * 2650 + ++ *_gain = -((__s64)gain1 * 2650 + + gain2 * 3380 + + gain3 * 2850 + + v_agc * 176 / 100 * 10 - +diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c +index bda29bc1b933..2f74a5ac0147 100644 +--- a/drivers/media/platform/soc_camera/soc_scale_crop.c ++++ b/drivers/media/platform/soc_camera/soc_scale_crop.c +@@ -405,3 +405,7 @@ void soc_camera_calc_client_output(struct soc_camera_device *icd, + mf->height = soc_camera_shift_scale(rect->height, shift, scale_v); + } + EXPORT_SYMBOL(soc_camera_calc_client_output); ++ ++MODULE_DESCRIPTION("soc-camera scaling-cropping functions"); ++MODULE_AUTHOR("Guennadi Liakhovetski "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index 3721ee63b8fb..09c97847bf95 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -503,18 +503,23 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + + static int lme2510_return_status(struct dvb_usb_device *d) + { +- int ret = 0; ++ int ret; + u8 *data; + +- data = kzalloc(10, GFP_KERNEL); ++ data = kzalloc(6, GFP_KERNEL); + if (!data) + return -ENOMEM; + +- ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), +- 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); +- info("Firmware Status: %x (%x)", ret , data[2]); ++ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), ++ 0x06, 0x80, 0x0302, 0x00, ++ data, 0x6, 200); ++ if (ret != 6) ++ ret = -EINVAL; ++ else ++ ret = data[2]; ++ ++ info("Firmware Status: %6ph", data); + +- ret = (ret < 0) ? -ENODEV : data[2]; + kfree(data); + return ret; + } +@@ -1078,8 +1083,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) + + if (adap->fe[0]) { + info("FE Found M88RS2000"); +- dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config, +- &d->i2c_adap); + st->i2c_tuner_gate_w = 5; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0x60; +@@ -1145,17 +1148,18 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) + ret = st->tuner_config; + break; + case TUNER_RS2000: +- ret = st->tuner_config; ++ if (dvb_attach(ts2020_attach, adap->fe[0], ++ &ts2020_config, &d->i2c_adap)) ++ ret = st->tuner_config; + break; + default: + break; + } + +- if (ret) ++ if (ret) { + info("TUN Found %s tuner", tun_msg[ret]); +- else { +- info("TUN No tuner found --- resetting device"); +- lme_coldreset(d); ++ } else { ++ info("TUN No tuner found"); + return -ENODEV; + } + +@@ -1199,6 +1203,7 @@ static int lme2510_get_adapter_count(struct dvb_usb_device *d) + static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + { + struct lme2510_state *st = d->priv; ++ int status; + + usb_reset_configuration(d->udev); + +@@ -1207,12 +1212,16 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + + st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; + +- if (lme2510_return_status(d) == 0x44) { ++ status = lme2510_return_status(d); ++ if (status == 0x44) { + *name = lme_firmware_switch(d, 0); + return COLD; + } + +- return 0; ++ if (status != 0x47) ++ return -EINVAL; ++ ++ return WARM; + } + + static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, +diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c +index ab7151181728..d00b27ed73a6 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -818,6 +818,8 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int component, + case XC2028_RESET_CLK: + deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg); + break; ++ case XC2028_I2C_FLUSH: ++ break; + default: + deb_info("%s: unknown command %d, arg %d\n", __func__, + command, arg); +diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c +index 7df0707a0455..38c03283a441 100644 +--- a/drivers/media/usb/dvb-usb/dib0700_devices.c ++++ b/drivers/media/usb/dvb-usb/dib0700_devices.c +@@ -431,6 +431,7 @@ static int stk7700ph_xc3028_callback(void *ptr, int component, + state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); + break; + case XC2028_RESET_CLK: ++ case XC2028_I2C_FLUSH: + break; + default: + err("%s: unknown command %d, arg %d\n", __func__, +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index 4379b949bb93..943f90e392a7 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -18,8 +18,18 @@ + #include + #include + #include ++#include ++#include + #include + ++/* Use the same argument order as copy_in_user */ ++#define assign_in_user(to, from) \ ++({ \ ++ typeof(*from) __assign_tmp; \ ++ \ ++ get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \ ++}) ++ + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + long ret = -ENOIOCTLCMD; +@@ -33,131 +43,88 @@ static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + struct v4l2_clip32 { + struct v4l2_rect c; +- compat_caddr_t next; ++ compat_caddr_t next; + }; + + struct v4l2_window32 { + struct v4l2_rect w; +- __u32 field; /* enum v4l2_field */ ++ __u32 field; /* enum v4l2_field */ + __u32 chromakey; + compat_caddr_t clips; /* actually struct v4l2_clip32 * */ + __u32 clipcount; + compat_caddr_t bitmap; ++ __u8 global_alpha; + }; + +-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +-{ +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || +- copy_from_user(&kp->w, &up->w, sizeof(up->w)) || +- get_user(kp->field, &up->field) || +- get_user(kp->chromakey, &up->chromakey) || +- get_user(kp->clipcount, &up->clipcount)) +- return -EFAULT; +- if (kp->clipcount > 2048) +- return -EINVAL; +- if (kp->clipcount) { +- struct v4l2_clip32 __user *uclips; +- struct v4l2_clip __user *kclips; +- int n = kp->clipcount; +- compat_caddr_t p; +- +- if (get_user(p, &up->clips)) +- return -EFAULT; +- uclips = compat_ptr(p); +- kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); +- kp->clips = kclips; +- while (--n >= 0) { +- if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) +- return -EFAULT; +- if (put_user(n ? kclips + 1 : NULL, &kclips->next)) +- return -EFAULT; +- uclips += 1; +- kclips += 1; +- } +- } else +- kp->clips = NULL; +- return 0; +-} +- +-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +-{ +- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || +- put_user(kp->field, &up->field) || +- put_user(kp->chromakey, &up->chromakey) || +- put_user(kp->clipcount, &up->clipcount)) +- return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) +- return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, +- struct v4l2_pix_format_mplane __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) +- return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) +- return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, +- struct v4l2_pix_format_mplane __user *up) ++static int get_v4l2_window32(struct v4l2_window __user *kp, ++ struct v4l2_window32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { +- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) ++ struct v4l2_clip32 __user *uclips; ++ struct v4l2_clip __user *kclips; ++ compat_caddr_t p; ++ u32 clipcount; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ copy_in_user(&kp->w, &up->w, sizeof(up->w)) || ++ assign_in_user(&kp->field, &up->field) || ++ assign_in_user(&kp->chromakey, &up->chromakey) || ++ assign_in_user(&kp->global_alpha, &up->global_alpha) || ++ get_user(clipcount, &up->clipcount) || ++ put_user(clipcount, &kp->clipcount)) + return -EFAULT; +- return 0; +-} ++ if (clipcount > 2048) ++ return -EINVAL; ++ if (!clipcount) ++ return put_user(NULL, &kp->clips); + +-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) ++ if (get_user(p, &up->clips)) + return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) ++ uclips = compat_ptr(p); ++ if (aux_space < clipcount * sizeof(*kclips)) + return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) ++ kclips = aux_buf; ++ if (put_user(kclips, &kp->clips)) + return -EFAULT; +- return 0; +-} + +-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) +- return -EFAULT; ++ while (clipcount--) { ++ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) ++ return -EFAULT; ++ if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next)) ++ return -EFAULT; ++ uclips++; ++ kclips++; ++ } + return 0; + } + +-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) ++static int put_v4l2_window32(struct v4l2_window __user *kp, ++ struct v4l2_window32 __user *up) + { +- if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format))) ++ struct v4l2_clip __user *kclips = kp->clips; ++ struct v4l2_clip32 __user *uclips; ++ compat_caddr_t p; ++ u32 clipcount; ++ ++ if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) || ++ assign_in_user(&up->field, &kp->field) || ++ assign_in_user(&up->chromakey, &kp->chromakey) || ++ assign_in_user(&up->global_alpha, &kp->global_alpha) || ++ get_user(clipcount, &kp->clipcount) || ++ put_user(clipcount, &up->clipcount)) + return -EFAULT; +- return 0; +-} ++ if (!clipcount) ++ return 0; + +-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format))) ++ if (get_user(p, &up->clips)) + return -EFAULT; ++ uclips = compat_ptr(p); ++ while (clipcount--) { ++ if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c))) ++ return -EFAULT; ++ uclips++; ++ kclips++; ++ } + return 0; + } + +@@ -191,97 +158,158 @@ struct v4l2_create_buffers32 { + __u32 reserved[8]; + }; + +-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) ++{ ++ u32 type; ++ ++ if (get_user(type, &up->type)) ++ return -EFAULT; ++ ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { ++ u32 clipcount; ++ ++ if (get_user(clipcount, &up->fmt.win.clipcount)) ++ return -EFAULT; ++ if (clipcount > 2048) ++ return -EINVAL; ++ *size = clipcount * sizeof(struct v4l2_clip); ++ return 0; ++ } ++ default: ++ *size = 0; ++ return 0; ++ } ++} ++ ++static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) + { +- if (get_user(kp->type, &up->type)) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; ++ return __bufsize_v4l2_format(up, size); ++} + +- switch (kp->type) { ++static int __get_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up, ++ void __user *aux_buf, u32 aux_space) ++{ ++ u32 type; ++ ++ if (get_user(type, &up->type) || put_user(type, &kp->type)) ++ return -EFAULT; ++ ++ switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ++ return copy_in_user(&kp->fmt.pix, &up->fmt.pix, ++ sizeof(kp->fmt.pix)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, +- &up->fmt.pix_mp); ++ return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, ++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: +- return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); ++ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win, ++ aux_buf, aux_space); + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: +- return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); ++ return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi, ++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); ++ return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced, ++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: +- return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); ++ return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr, ++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0; + default: +- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", +- kp->type); + return -EINVAL; + } + } + +-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int get_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; +- return __get_v4l2_format32(kp, up); ++ return __get_v4l2_format32(kp, up, aux_buf, aux_space); + } + +-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) ++static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up, ++ u32 *size) + { +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || +- copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; +- return __get_v4l2_format32(&kp->format, &up->format); ++ return __bufsize_v4l2_format(&up->format, size); + } + +-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int get_v4l2_create32(struct v4l2_create_buffers __user *kp, ++ struct v4l2_create_buffers32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { +- if (put_user(kp->type, &up->type)) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ copy_in_user(kp, up, ++ offsetof(struct v4l2_create_buffers32, format))) + return -EFAULT; ++ return __get_v4l2_format32(&kp->format, &up->format, ++ aux_buf, aux_space); ++} ++ ++static int __put_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up) ++{ ++ u32 type; + +- switch (kp->type) { ++ if (get_user(type, &kp->type)) ++ return -EFAULT; ++ ++ switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ++ return copy_in_user(&up->fmt.pix, &kp->fmt.pix, ++ sizeof(kp->fmt.pix)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp, +- &up->fmt.pix_mp); ++ return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp, ++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: +- return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); ++ return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi, ++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); ++ return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced, ++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: +- return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); ++ return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr, ++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0; + default: +- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", +- kp->type); + return -EINVAL; + } + } + +-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int put_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32))) ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) + return -EFAULT; + return __put_v4l2_format32(kp, up); + } + +-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) ++static int put_v4l2_create32(struct v4l2_create_buffers __user *kp, ++ struct v4l2_create_buffers32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || +- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || +- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ copy_in_user(up, kp, ++ offsetof(struct v4l2_create_buffers32, format)) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + return -EFAULT; + return __put_v4l2_format32(&kp->format, &up->format); + } +@@ -295,25 +323,28 @@ struct v4l2_standard32 { + __u32 reserved[4]; + }; + +-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) ++static int get_v4l2_standard32(struct v4l2_standard __user *kp, ++ struct v4l2_standard32 __user *up) + { + /* other fields are not set by the user, nor used by the driver */ +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || +- get_user(kp->index, &up->index)) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->index, &up->index)) + return -EFAULT; + return 0; + } + +-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) ++static int put_v4l2_standard32(struct v4l2_standard __user *kp, ++ struct v4l2_standard32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || +- put_user(kp->index, &up->index) || +- put_user(kp->id, &up->id) || +- copy_to_user(up->name, kp->name, 24) || +- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || +- put_user(kp->framelines, &up->framelines) || +- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->index, &kp->index) || ++ assign_in_user(&up->id, &kp->id) || ++ copy_in_user(up->name, kp->name, sizeof(up->name)) || ++ copy_in_user(&up->frameperiod, &kp->frameperiod, ++ sizeof(up->frameperiod)) || ++ assign_in_user(&up->framelines, &kp->framelines) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -352,134 +383,186 @@ struct v4l2_buffer32 { + __u32 reserved; + }; + +-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +- enum v4l2_memory memory) ++static int get_v4l2_plane32(struct v4l2_plane __user *up, ++ struct v4l2_plane32 __user *up32, ++ enum v4l2_memory memory) + { +- void __user *up_pln; +- compat_long_t p; ++ compat_ulong_t p; + + if (copy_in_user(up, up32, 2 * sizeof(__u32)) || +- copy_in_user(&up->data_offset, &up32->data_offset, +- sizeof(__u32))) ++ copy_in_user(&up->data_offset, &up32->data_offset, ++ sizeof(up->data_offset))) + return -EFAULT; + +- if (memory == V4L2_MEMORY_USERPTR) { +- if (get_user(p, &up32->m.userptr)) +- return -EFAULT; +- up_pln = compat_ptr(p); +- if (put_user((unsigned long)up_pln, &up->m.userptr)) ++ switch (memory) { ++ case V4L2_MEMORY_MMAP: ++ case V4L2_MEMORY_OVERLAY: ++ if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, ++ sizeof(up32->m.mem_offset))) + return -EFAULT; +- } else if (memory == V4L2_MEMORY_DMABUF) { +- if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int))) ++ break; ++ case V4L2_MEMORY_USERPTR: ++ if (get_user(p, &up32->m.userptr) || ++ put_user((unsigned long)compat_ptr(p), &up->m.userptr)) + return -EFAULT; +- } else { +- if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, +- sizeof(__u32))) ++ break; ++ case V4L2_MEMORY_DMABUF: ++ if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd))) + return -EFAULT; ++ break; + } + + return 0; + } + +-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +- enum v4l2_memory memory) ++static int put_v4l2_plane32(struct v4l2_plane __user *up, ++ struct v4l2_plane32 __user *up32, ++ enum v4l2_memory memory) + { ++ unsigned long p; ++ + if (copy_in_user(up32, up, 2 * sizeof(__u32)) || +- copy_in_user(&up32->data_offset, &up->data_offset, +- sizeof(__u32))) ++ copy_in_user(&up32->data_offset, &up->data_offset, ++ sizeof(up->data_offset))) + return -EFAULT; + +- /* For MMAP, driver might've set up the offset, so copy it back. +- * USERPTR stays the same (was userspace-provided), so no copying. */ +- if (memory == V4L2_MEMORY_MMAP) ++ switch (memory) { ++ case V4L2_MEMORY_MMAP: ++ case V4L2_MEMORY_OVERLAY: + if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, +- sizeof(__u32))) ++ sizeof(up->m.mem_offset))) + return -EFAULT; +- /* For DMABUF, driver might've set up the fd, so copy it back. */ +- if (memory == V4L2_MEMORY_DMABUF) +- if (copy_in_user(&up32->m.fd, &up->m.fd, +- sizeof(int))) ++ break; ++ case V4L2_MEMORY_USERPTR: ++ if (get_user(p, &up->m.userptr) || ++ put_user((compat_ulong_t)ptr_to_compat((__force void *)p), ++ &up32->m.userptr)) ++ return -EFAULT; ++ break; ++ case V4L2_MEMORY_DMABUF: ++ if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd))) + return -EFAULT; ++ break; ++ } + + return 0; + } + +-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) ++static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size) + { ++ u32 type; ++ u32 length; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(type, &up->type) || ++ get_user(length, &up->length)) ++ return -EFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ if (length > VIDEO_MAX_PLANES) ++ return -EINVAL; ++ ++ /* ++ * We don't really care if userspace decides to kill itself ++ * by passing a very big length value ++ */ ++ *size = length * sizeof(struct v4l2_plane); ++ } else { ++ *size = 0; ++ } ++ return 0; ++} ++ ++static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, ++ struct v4l2_buffer32 __user *up, ++ void __user *aux_buf, u32 aux_space) ++{ ++ u32 type; ++ u32 length; ++ enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane __user *uplane; + compat_caddr_t p; +- int num_planes; + int ret; + +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || +- get_user(kp->index, &up->index) || +- get_user(kp->type, &up->type) || +- get_user(kp->flags, &up->flags) || +- get_user(kp->memory, &up->memory) || +- get_user(kp->length, &up->length)) +- return -EFAULT; ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->index, &up->index) || ++ get_user(type, &up->type) || ++ put_user(type, &kp->type) || ++ assign_in_user(&kp->flags, &up->flags) || ++ get_user(memory, &up->memory) || ++ put_user(memory, &kp->memory) || ++ get_user(length, &up->length) || ++ put_user(length, &kp->length)) ++ return -EFAULT; + +- if (V4L2_TYPE_IS_OUTPUT(kp->type)) +- if (get_user(kp->bytesused, &up->bytesused) || +- get_user(kp->field, &up->field) || +- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- get_user(kp->timestamp.tv_usec, +- &up->timestamp.tv_usec)) ++ if (V4L2_TYPE_IS_OUTPUT(type)) ++ if (assign_in_user(&kp->bytesused, &up->bytesused) || ++ assign_in_user(&kp->field, &up->field) || ++ assign_in_user(&kp->timestamp.tv_sec, ++ &up->timestamp.tv_sec) || ++ assign_in_user(&kp->timestamp.tv_usec, ++ &up->timestamp.tv_usec)) + return -EFAULT; + +- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +- num_planes = kp->length; ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ u32 num_planes = length; ++ + if (num_planes == 0) { +- kp->m.planes = NULL; +- /* num_planes == 0 is legal, e.g. when userspace doesn't +- * need planes array on DQBUF*/ +- return 0; ++ /* ++ * num_planes == 0 is legal, e.g. when userspace doesn't ++ * need planes array on DQBUF ++ */ ++ return put_user(NULL, &kp->m.planes); + } ++ if (num_planes > VIDEO_MAX_PLANES) ++ return -EINVAL; + + if (get_user(p, &up->m.planes)) + return -EFAULT; + + uplane32 = compat_ptr(p); + if (!access_ok(VERIFY_READ, uplane32, +- num_planes * sizeof(struct v4l2_plane32))) ++ num_planes * sizeof(*uplane32))) + return -EFAULT; + +- /* We don't really care if userspace decides to kill itself +- * by passing a very big num_planes value */ +- uplane = compat_alloc_user_space(num_planes * +- sizeof(struct v4l2_plane)); +- kp->m.planes = (__force struct v4l2_plane *)uplane; ++ /* ++ * We don't really care if userspace decides to kill itself ++ * by passing a very big num_planes value ++ */ ++ if (aux_space < num_planes * sizeof(*uplane)) ++ return -EFAULT; ++ ++ uplane = aux_buf; ++ if (put_user((__force struct v4l2_plane *)uplane, ++ &kp->m.planes)) ++ return -EFAULT; + +- while (--num_planes >= 0) { +- ret = get_v4l2_plane32(uplane, uplane32, kp->memory); ++ while (num_planes--) { ++ ret = get_v4l2_plane32(uplane, uplane32, memory); + if (ret) + return ret; +- ++uplane; +- ++uplane32; ++ uplane++; ++ uplane32++; + } + } else { +- switch (kp->memory) { ++ switch (memory) { + case V4L2_MEMORY_MMAP: +- if (get_user(kp->m.offset, &up->m.offset)) ++ case V4L2_MEMORY_OVERLAY: ++ if (assign_in_user(&kp->m.offset, &up->m.offset)) + return -EFAULT; + break; +- case V4L2_MEMORY_USERPTR: +- { +- compat_long_t tmp; ++ case V4L2_MEMORY_USERPTR: { ++ compat_ulong_t userptr; + +- if (get_user(tmp, &up->m.userptr)) +- return -EFAULT; +- +- kp->m.userptr = (unsigned long)compat_ptr(tmp); +- } +- break; +- case V4L2_MEMORY_OVERLAY: +- if (get_user(kp->m.offset, &up->m.offset)) ++ if (get_user(userptr, &up->m.userptr) || ++ put_user((unsigned long)compat_ptr(userptr), ++ &kp->m.userptr)) + return -EFAULT; + break; ++ } + case V4L2_MEMORY_DMABUF: +- if (get_user(kp->m.fd, &up->m.fd)) ++ if (assign_in_user(&kp->m.fd, &up->m.fd)) + return -EFAULT; + break; + } +@@ -488,65 +571,70 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user + return 0; + } + +-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) ++static int put_v4l2_buffer32(struct v4l2_buffer __user *kp, ++ struct v4l2_buffer32 __user *up) + { ++ u32 type; ++ u32 length; ++ enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane __user *uplane; + compat_caddr_t p; +- int num_planes; + int ret; + +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || +- put_user(kp->index, &up->index) || +- put_user(kp->type, &up->type) || +- put_user(kp->flags, &up->flags) || +- put_user(kp->memory, &up->memory)) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->index, &kp->index) || ++ get_user(type, &kp->type) || ++ put_user(type, &up->type) || ++ assign_in_user(&up->flags, &kp->flags) || ++ get_user(memory, &kp->memory) || ++ put_user(memory, &up->memory)) ++ return -EFAULT; + +- if (put_user(kp->bytesused, &up->bytesused) || +- put_user(kp->field, &up->field) || +- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || +- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || +- put_user(kp->sequence, &up->sequence) || +- put_user(kp->reserved2, &up->reserved2) || +- put_user(kp->reserved, &up->reserved) || +- put_user(kp->length, &up->length)) +- return -EFAULT; ++ if (assign_in_user(&up->bytesused, &kp->bytesused) || ++ assign_in_user(&up->field, &kp->field) || ++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || ++ assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) || ++ copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || ++ assign_in_user(&up->sequence, &kp->sequence) || ++ assign_in_user(&up->reserved2, &kp->reserved2) || ++ assign_in_user(&up->reserved, &kp->reserved) || ++ get_user(length, &kp->length) || ++ put_user(length, &up->length)) ++ return -EFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ u32 num_planes = length; + +- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +- num_planes = kp->length; + if (num_planes == 0) + return 0; + +- uplane = (__force struct v4l2_plane __user *)kp->m.planes; ++ if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes))) ++ return -EFAULT; + if (get_user(p, &up->m.planes)) + return -EFAULT; + uplane32 = compat_ptr(p); + +- while (--num_planes >= 0) { +- ret = put_v4l2_plane32(uplane, uplane32, kp->memory); ++ while (num_planes--) { ++ ret = put_v4l2_plane32(uplane, uplane32, memory); + if (ret) + return ret; + ++uplane; + ++uplane32; + } + } else { +- switch (kp->memory) { ++ switch (memory) { + case V4L2_MEMORY_MMAP: +- if (put_user(kp->m.offset, &up->m.offset)) ++ case V4L2_MEMORY_OVERLAY: ++ if (assign_in_user(&up->m.offset, &kp->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: +- if (put_user(kp->m.userptr, &up->m.userptr)) +- return -EFAULT; +- break; +- case V4L2_MEMORY_OVERLAY: +- if (put_user(kp->m.offset, &up->m.offset)) ++ if (assign_in_user(&up->m.userptr, &kp->m.userptr)) + return -EFAULT; + break; + case V4L2_MEMORY_DMABUF: +- if (put_user(kp->m.fd, &up->m.fd)) ++ if (assign_in_user(&up->m.fd, &kp->m.fd)) + return -EFAULT; + break; + } +@@ -558,7 +646,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user + struct v4l2_framebuffer32 { + __u32 capability; + __u32 flags; +- compat_caddr_t base; ++ compat_caddr_t base; + struct { + __u32 width; + __u32 height; +@@ -571,30 +659,33 @@ struct v4l2_framebuffer32 { + } fmt; + }; + +-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) ++static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, ++ struct v4l2_framebuffer32 __user *up) + { +- u32 tmp; +- +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || +- get_user(tmp, &up->base) || +- get_user(kp->capability, &up->capability) || +- get_user(kp->flags, &up->flags) || +- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) +- return -EFAULT; +- kp->base = (__force void *)compat_ptr(tmp); ++ compat_caddr_t tmp; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(tmp, &up->base) || ++ put_user((__force void *)compat_ptr(tmp), &kp->base) || ++ assign_in_user(&kp->capability, &up->capability) || ++ assign_in_user(&kp->flags, &up->flags) || ++ copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt))) ++ return -EFAULT; + return 0; + } + +-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) ++static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, ++ struct v4l2_framebuffer32 __user *up) + { +- u32 tmp = (u32)((unsigned long)kp->base); +- +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || +- put_user(tmp, &up->base) || +- put_user(kp->capability, &up->capability) || +- put_user(kp->flags, &up->flags) || +- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) +- return -EFAULT; ++ void *base; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ get_user(base, &kp->base) || ++ put_user(ptr_to_compat(base), &up->base) || ++ assign_in_user(&up->capability, &kp->capability) || ++ assign_in_user(&up->flags, &kp->flags) || ++ copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt))) ++ return -EFAULT; + return 0; + } + +@@ -606,21 +697,26 @@ struct v4l2_input32 { + __u32 tuner; /* Associated tuner */ + compat_u64 std; + __u32 status; +- __u32 reserved[4]; ++ __u32 capabilities; ++ __u32 reserved[3]; + }; + +-/* The 64-bit v4l2_input struct has extra padding at the end of the struct. +- Otherwise it is identical to the 32-bit version. */ +-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) ++/* ++ * The 64-bit v4l2_input struct has extra padding at the end of the struct. ++ * Otherwise it is identical to the 32-bit version. ++ */ ++static inline int get_v4l2_input32(struct v4l2_input __user *kp, ++ struct v4l2_input32 __user *up) + { +- if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) ++ if (copy_in_user(kp, up, sizeof(*up))) + return -EFAULT; + return 0; + } + +-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) ++static inline int put_v4l2_input32(struct v4l2_input __user *kp, ++ struct v4l2_input32 __user *up) + { +- if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) ++ if (copy_in_user(up, kp, sizeof(*up))) + return -EFAULT; + return 0; + } +@@ -644,58 +740,95 @@ struct v4l2_ext_control32 { + }; + } __attribute__ ((packed)); + +-/* The following function really belong in v4l2-common, but that causes +- a circular dependency between modules. We need to think about this, but +- for now this will do. */ +- +-/* Return non-zero if this control is a pointer type. Currently only +- type STRING is a pointer type. */ +-static inline int ctrl_is_pointer(u32 id) ++/* Return true if this control is a pointer type. */ ++static inline bool ctrl_is_pointer(struct file *file, u32 id) + { +- switch (id) { +- case V4L2_CID_RDS_TX_PS_NAME: +- case V4L2_CID_RDS_TX_RADIO_TEXT: +- return 1; +- default: +- return 0; ++ struct video_device *vdev = video_devdata(file); ++ struct v4l2_fh *fh = NULL; ++ struct v4l2_ctrl_handler *hdl = NULL; ++ struct v4l2_query_ext_ctrl qec = { id }; ++ const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) ++ fh = file->private_data; ++ ++ if (fh && fh->ctrl_handler) ++ hdl = fh->ctrl_handler; ++ else if (vdev->ctrl_handler) ++ hdl = vdev->ctrl_handler; ++ ++ if (hdl) { ++ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); ++ ++ return ctrl && ctrl->is_ptr; + } ++ ++ if (!ops || !ops->vidioc_query_ext_ctrl) ++ return false; ++ ++ return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && ++ (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); ++} ++ ++static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up, ++ u32 *size) ++{ ++ u32 count; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(count, &up->count)) ++ return -EFAULT; ++ if (count > V4L2_CID_MAX_CTRLS) ++ return -EINVAL; ++ *size = count * sizeof(struct v4l2_ext_control); ++ return 0; + } + +-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) ++static int get_v4l2_ext_controls32(struct file *file, ++ struct v4l2_ext_controls __user *kp, ++ struct v4l2_ext_controls32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { + struct v4l2_ext_control32 __user *ucontrols; + struct v4l2_ext_control __user *kcontrols; +- int n; ++ u32 count; ++ u32 n; + compat_caddr_t p; + +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || +- get_user(kp->ctrl_class, &up->ctrl_class) || +- get_user(kp->count, &up->count) || +- get_user(kp->error_idx, &up->error_idx) || +- copy_from_user(kp->reserved, up->reserved, +- sizeof(kp->reserved))) +- return -EFAULT; +- n = kp->count; +- if (n == 0) { +- kp->controls = NULL; +- return 0; +- } ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->ctrl_class, &up->ctrl_class) || ++ get_user(count, &up->count) || ++ put_user(count, &kp->count) || ++ assign_in_user(&kp->error_idx, &up->error_idx) || ++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) ++ return -EFAULT; ++ ++ if (count == 0) ++ return put_user(NULL, &kp->controls); ++ if (count > V4L2_CID_MAX_CTRLS) ++ return -EINVAL; + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(VERIFY_READ, ucontrols, +- n * sizeof(struct v4l2_ext_control32))) ++ if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols))) ++ return -EFAULT; ++ if (aux_space < count * sizeof(*kcontrols)) + return -EFAULT; +- kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); +- kp->controls = (__force struct v4l2_ext_control *)kcontrols; +- while (--n >= 0) { ++ kcontrols = aux_buf; ++ if (put_user((__force struct v4l2_ext_control *)kcontrols, ++ &kp->controls)) ++ return -EFAULT; ++ ++ for (n = 0; n < count; n++) { + u32 id; + + if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) + return -EFAULT; ++ + if (get_user(id, &kcontrols->id)) + return -EFAULT; +- if (ctrl_is_pointer(id)) { ++ ++ if (ctrl_is_pointer(file, id)) { + void __user *s; + + if (get_user(p, &ucontrols->string)) +@@ -710,43 +843,55 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext + return 0; + } + +-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) ++static int put_v4l2_ext_controls32(struct file *file, ++ struct v4l2_ext_controls __user *kp, ++ struct v4l2_ext_controls32 __user *up) + { + struct v4l2_ext_control32 __user *ucontrols; +- struct v4l2_ext_control __user *kcontrols = +- (__force struct v4l2_ext_control __user *)kp->controls; +- int n = kp->count; ++ struct v4l2_ext_control __user *kcontrols; ++ u32 count; ++ u32 n; + compat_caddr_t p; + +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || +- put_user(kp->ctrl_class, &up->ctrl_class) || +- put_user(kp->count, &up->count) || +- put_user(kp->error_idx, &up->error_idx) || +- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) +- return -EFAULT; +- if (!kp->count) +- return 0; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->ctrl_class, &kp->ctrl_class) || ++ get_user(count, &kp->count) || ++ put_user(count, &up->count) || ++ assign_in_user(&up->error_idx, &kp->error_idx) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) || ++ get_user(kcontrols, &kp->controls)) ++ return -EFAULT; + ++ if (!count) ++ return 0; + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(VERIFY_WRITE, ucontrols, +- n * sizeof(struct v4l2_ext_control32))) ++ if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; + +- while (--n >= 0) { +- unsigned size = sizeof(*ucontrols); ++ for (n = 0; n < count; n++) { ++ unsigned int size = sizeof(*ucontrols); + u32 id; + +- if (get_user(id, &kcontrols->id)) ++ if (get_user(id, &kcontrols->id) || ++ put_user(id, &ucontrols->id) || ++ assign_in_user(&ucontrols->size, &kcontrols->size) || ++ copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, ++ sizeof(ucontrols->reserved2))) + return -EFAULT; +- /* Do not modify the pointer when copying a pointer control. +- The contents of the pointer was changed, not the pointer +- itself. */ +- if (ctrl_is_pointer(id)) ++ ++ /* ++ * Do not modify the pointer when copying a pointer control. ++ * The contents of the pointer was changed, not the pointer ++ * itself. ++ */ ++ if (ctrl_is_pointer(file, id)) + size -= sizeof(ucontrols->value64); ++ + if (copy_in_user(ucontrols, kcontrols, size)) + return -EFAULT; ++ + ucontrols++; + kcontrols++; + } +@@ -766,18 +911,19 @@ struct v4l2_event32 { + __u32 reserved[8]; + }; + +-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) ++static int put_v4l2_event32(struct v4l2_event __user *kp, ++ struct v4l2_event32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || +- put_user(kp->type, &up->type) || +- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || +- put_user(kp->pending, &up->pending) || +- put_user(kp->sequence, &up->sequence) || +- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) || +- put_user(kp->id, &up->id) || +- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->type, &kp->type) || ++ copy_in_user(&up->u, &kp->u, sizeof(kp->u)) || ++ assign_in_user(&up->pending, &kp->pending) || ++ assign_in_user(&up->sequence, &kp->sequence) || ++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || ++ assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) || ++ assign_in_user(&up->id, &kp->id) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -789,32 +935,35 @@ struct v4l2_edid32 { + compat_caddr_t edid; + }; + +-static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) ++static int get_v4l2_edid32(struct v4l2_edid __user *kp, ++ struct v4l2_edid32 __user *up) + { +- u32 tmp; +- +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) || +- get_user(kp->pad, &up->pad) || +- get_user(kp->start_block, &up->start_block) || +- get_user(kp->blocks, &up->blocks) || +- get_user(tmp, &up->edid) || +- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) +- return -EFAULT; +- kp->edid = (__force u8 *)compat_ptr(tmp); ++ compat_uptr_t tmp; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->pad, &up->pad) || ++ assign_in_user(&kp->start_block, &up->start_block) || ++ assign_in_user(&kp->blocks, &up->blocks) || ++ get_user(tmp, &up->edid) || ++ put_user(compat_ptr(tmp), &kp->edid) || ++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) ++ return -EFAULT; + return 0; + } + +-static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) ++static int put_v4l2_edid32(struct v4l2_edid __user *kp, ++ struct v4l2_edid32 __user *up) + { +- u32 tmp = (u32)((unsigned long)kp->edid); +- +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) || +- put_user(kp->pad, &up->pad) || +- put_user(kp->start_block, &up->start_block) || +- put_user(kp->blocks, &up->blocks) || +- put_user(tmp, &up->edid) || +- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) +- return -EFAULT; ++ void *edid; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->pad, &kp->pad) || ++ assign_in_user(&up->start_block, &kp->start_block) || ++ assign_in_user(&up->blocks, &kp->blocks) || ++ get_user(edid, &kp->edid) || ++ put_user(ptr_to_compat(edid), &up->edid) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -830,7 +979,7 @@ static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) + #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) + #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) + #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) +-#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) ++#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) + #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) + #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) + #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) +@@ -846,22 +995,23 @@ static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) + #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) + #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) + ++static int alloc_userspace(unsigned int size, u32 aux_space, ++ void __user **up_native) ++{ ++ *up_native = compat_alloc_user_space(size + aux_space); ++ if (!*up_native) ++ return -ENOMEM; ++ if (clear_user(*up_native, size)) ++ return -EFAULT; ++ return 0; ++} ++ + static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- union { +- struct v4l2_format v2f; +- struct v4l2_buffer v2b; +- struct v4l2_framebuffer v2fb; +- struct v4l2_input v2i; +- struct v4l2_standard v2s; +- struct v4l2_ext_controls v2ecs; +- struct v4l2_event v2ev; +- struct v4l2_create_buffers v2crt; +- struct v4l2_edid v2edid; +- unsigned long vx; +- int vi; +- } karg; + void __user *up = compat_ptr(arg); ++ void __user *up_native = NULL; ++ void __user *aux_buf; ++ u32 aux_space; + int compatible_arg = 1; + long err = 0; + +@@ -900,30 +1050,52 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_STREAMOFF: + case VIDIOC_S_INPUT: + case VIDIOC_S_OUTPUT: +- err = get_user(karg.vi, (s32 __user *)up); ++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native); ++ if (!err && assign_in_user((unsigned int __user *)up_native, ++ (compat_uint_t __user *)up)) ++ err = -EFAULT; + compatible_arg = 0; + break; + + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: ++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native); + compatible_arg = 0; + break; + + case VIDIOC_G_EDID: + case VIDIOC_S_EDID: +- err = get_v4l2_edid32(&karg.v2edid, up); ++ err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native); ++ if (!err) ++ err = get_v4l2_edid32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: +- err = get_v4l2_format32(&karg.v2f, up); ++ err = bufsize_v4l2_format(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_format), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_format); ++ err = get_v4l2_format32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + + case VIDIOC_CREATE_BUFS: +- err = get_v4l2_create32(&karg.v2crt, up); ++ err = bufsize_v4l2_create(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_create_buffers), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_create_buffers); ++ err = get_v4l2_create32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + +@@ -931,36 +1103,63 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: +- err = get_v4l2_buffer32(&karg.v2b, up); ++ err = bufsize_v4l2_buffer(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_buffer), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_buffer); ++ err = get_v4l2_buffer32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + + case VIDIOC_S_FBUF: +- err = get_v4l2_framebuffer32(&karg.v2fb, up); ++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, ++ &up_native); ++ if (!err) ++ err = get_v4l2_framebuffer32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_FBUF: ++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, ++ &up_native); + compatible_arg = 0; + break; + + case VIDIOC_ENUMSTD: +- err = get_v4l2_standard32(&karg.v2s, up); ++ err = alloc_userspace(sizeof(struct v4l2_standard), 0, ++ &up_native); ++ if (!err) ++ err = get_v4l2_standard32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_ENUMINPUT: +- err = get_v4l2_input32(&karg.v2i, up); ++ err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native); ++ if (!err) ++ err = get_v4l2_input32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: +- err = get_v4l2_ext_controls32(&karg.v2ecs, up); ++ err = bufsize_v4l2_ext_controls(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_ext_controls), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_ext_controls); ++ err = get_v4l2_ext_controls32(file, up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + case VIDIOC_DQEVENT: ++ err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native); + compatible_arg = 0; + break; + } +@@ -969,22 +1168,26 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + + if (compatible_arg) + err = native_ioctl(file, cmd, (unsigned long)up); +- else { +- mm_segment_t old_fs = get_fs(); ++ else ++ err = native_ioctl(file, cmd, (unsigned long)up_native); + +- set_fs(KERNEL_DS); +- err = native_ioctl(file, cmd, (unsigned long)&karg); +- set_fs(old_fs); +- } ++ if (err == -ENOTTY) ++ return err; + +- /* Special case: even after an error we need to put the +- results back for these ioctls since the error_idx will +- contain information on which control failed. */ ++ /* ++ * Special case: even after an error we need to put the ++ * results back for these ioctls since the error_idx will ++ * contain information on which control failed. ++ */ + switch (cmd) { + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: +- if (put_v4l2_ext_controls32(&karg.v2ecs, up)) ++ if (put_v4l2_ext_controls32(file, up_native, up)) ++ err = -EFAULT; ++ break; ++ case VIDIOC_S_EDID: ++ if (put_v4l2_edid32(up_native, up)) + err = -EFAULT; + break; + } +@@ -996,44 +1199,46 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_S_OUTPUT: + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: +- err = put_user(((s32)karg.vi), (s32 __user *)up); ++ if (assign_in_user((compat_uint_t __user *)up, ++ ((unsigned int __user *)up_native))) ++ err = -EFAULT; + break; + + case VIDIOC_G_FBUF: +- err = put_v4l2_framebuffer32(&karg.v2fb, up); ++ err = put_v4l2_framebuffer32(up_native, up); + break; + + case VIDIOC_DQEVENT: +- err = put_v4l2_event32(&karg.v2ev, up); ++ err = put_v4l2_event32(up_native, up); + break; + + case VIDIOC_G_EDID: +- case VIDIOC_S_EDID: +- err = put_v4l2_edid32(&karg.v2edid, up); ++ err = put_v4l2_edid32(up_native, up); + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: +- err = put_v4l2_format32(&karg.v2f, up); ++ err = put_v4l2_format32(up_native, up); + break; + + case VIDIOC_CREATE_BUFS: +- err = put_v4l2_create32(&karg.v2crt, up); ++ err = put_v4l2_create32(up_native, up); + break; + ++ case VIDIOC_PREPARE_BUF: + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: +- err = put_v4l2_buffer32(&karg.v2b, up); ++ err = put_v4l2_buffer32(up_native, up); + break; + + case VIDIOC_ENUMSTD: +- err = put_v4l2_standard32(&karg.v2s, up); ++ err = put_v4l2_standard32(up_native, up); + break; + + case VIDIOC_ENUMINPUT: +- err = put_v4l2_input32(&karg.v2i, up); ++ err = put_v4l2_input32(up_native, up); + break; + } + return err; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 7486af2c8ae4..5e2a7e59f578 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -2783,8 +2783,11 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + + /* Handles IOCTL */ + err = func(file, cmd, parg); +- if (err == -ENOIOCTLCMD) ++ if (err == -ENOTTY || err == -ENOIOCTLCMD) { + err = -ENOTTY; ++ goto out; ++ } ++ + if (err == 0) { + if (cmd == VIDIOC_DQBUF) + trace_v4l2_dqbuf(video_devdata(file)->minor, parg); +diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c +index 6c441be8f893..bf23234d957e 100644 +--- a/drivers/media/v4l2-core/videobuf2-v4l2.c ++++ b/drivers/media/v4l2-core/videobuf2-v4l2.c +@@ -593,6 +593,12 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, + b->flags & V4L2_BUF_FLAG_LAST) + q->last_buffer_dequeued = true; + ++ /* ++ * After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be ++ * cleared. ++ */ ++ b->flags &= ~V4L2_BUF_FLAG_DONE; ++ + return ret; + } + +diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c +index 4a07ba1195b5..d125d19a35e4 100644 +--- a/drivers/mtd/nand/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/brcmnand/brcmnand.c +@@ -1922,16 +1922,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) + tmp &= ~ACC_CONTROL_PARTIAL_PAGE; + tmp &= ~ACC_CONTROL_RD_ERASED; + tmp &= ~ACC_CONTROL_FAST_PGM_RDIN; +- if (ctrl->features & BRCMNAND_HAS_PREFETCH) { +- /* +- * FIXME: Flash DMA + prefetch may see spurious erased-page ECC +- * errors +- */ +- if (has_flash_dma(ctrl)) +- tmp &= ~ACC_CONTROL_PREFETCH; +- else +- tmp |= ACC_CONTROL_PREFETCH; +- } ++ if (ctrl->features & BRCMNAND_HAS_PREFETCH) ++ tmp &= ~ACC_CONTROL_PREFETCH; ++ + nand_writereg(ctrl, offs, tmp); + + return 0; +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 7ba109e8cf88..27864c0863ef 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2023,6 +2023,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, + static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) + { ++ unsigned int max_bitflips = 0; + int page, realpage, chipnr; + struct nand_chip *chip = mtd->priv; + struct mtd_ecc_stats stats; +@@ -2083,6 +2084,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + nand_wait_ready(mtd); + } + ++ max_bitflips = max_t(unsigned int, max_bitflips, ret); ++ + readlen -= len; + if (!readlen) + break; +@@ -2108,7 +2111,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + if (mtd->ecc_stats.failed - stats.failed) + return -EBADMSG; + +- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; ++ return max_bitflips; + } + + /** +diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c +index 824711845c44..3bb9b34d9e77 100644 +--- a/drivers/mtd/nand/sunxi_nand.c ++++ b/drivers/mtd/nand/sunxi_nand.c +@@ -1046,8 +1046,14 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, + + /* Add ECC info retrieval from DT */ + for (i = 0; i < ARRAY_SIZE(strengths); i++) { +- if (ecc->strength <= strengths[i]) ++ if (ecc->strength <= strengths[i]) { ++ /* ++ * Update ecc->strength value with the actual strength ++ * that will be used by the ECC engine. ++ */ ++ ecc->strength = strengths[i]; + break; ++ } + } + + if (i >= ARRAY_SIZE(strengths)) { +diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c +index ebf46ad2d513..b2fb0528c092 100644 +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -99,6 +99,8 @@ struct ubiblock { + + /* Linked list of all ubiblock instances */ + static LIST_HEAD(ubiblock_devices); ++static DEFINE_IDR(ubiblock_minor_idr); ++/* Protects ubiblock_devices and ubiblock_minor_idr */ + static DEFINE_MUTEX(devices_mutex); + static int ubiblock_major; + +@@ -354,8 +356,6 @@ static struct blk_mq_ops ubiblock_mq_ops = { + .map_queue = blk_mq_map_queue, + }; + +-static DEFINE_IDR(ubiblock_minor_idr); +- + int ubiblock_create(struct ubi_volume_info *vi) + { + struct ubiblock *dev; +@@ -368,14 +368,15 @@ int ubiblock_create(struct ubi_volume_info *vi) + /* Check that the volume isn't already handled */ + mutex_lock(&devices_mutex); + if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { +- mutex_unlock(&devices_mutex); +- return -EEXIST; ++ ret = -EEXIST; ++ goto out_unlock; + } +- mutex_unlock(&devices_mutex); + + dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL); +- if (!dev) +- return -ENOMEM; ++ if (!dev) { ++ ret = -ENOMEM; ++ goto out_unlock; ++ } + + mutex_init(&dev->dev_mutex); + +@@ -440,14 +441,13 @@ int ubiblock_create(struct ubi_volume_info *vi) + goto out_free_queue; + } + +- mutex_lock(&devices_mutex); + list_add_tail(&dev->list, &ubiblock_devices); +- mutex_unlock(&devices_mutex); + + /* Must be the last step: anyone can call file ops from now on */ + add_disk(dev->gd); + dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", + dev->ubi_num, dev->vol_id, vi->name); ++ mutex_unlock(&devices_mutex); + return 0; + + out_free_queue: +@@ -460,6 +460,8 @@ out_put_disk: + put_disk(dev->gd); + out_free_dev: + kfree(dev); ++out_unlock: ++ mutex_unlock(&devices_mutex); + + return ret; + } +@@ -481,30 +483,36 @@ static void ubiblock_cleanup(struct ubiblock *dev) + int ubiblock_remove(struct ubi_volume_info *vi) + { + struct ubiblock *dev; ++ int ret; + + mutex_lock(&devices_mutex); + dev = find_dev_nolock(vi->ubi_num, vi->vol_id); + if (!dev) { +- mutex_unlock(&devices_mutex); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out_unlock; + } + + /* Found a device, let's lock it so we can check if it's busy */ + mutex_lock(&dev->dev_mutex); + if (dev->refcnt > 0) { +- mutex_unlock(&dev->dev_mutex); +- mutex_unlock(&devices_mutex); +- return -EBUSY; ++ ret = -EBUSY; ++ goto out_unlock_dev; + } + + /* Remove from device list */ + list_del(&dev->list); +- mutex_unlock(&devices_mutex); +- + ubiblock_cleanup(dev); + mutex_unlock(&dev->dev_mutex); ++ mutex_unlock(&devices_mutex); ++ + kfree(dev); + return 0; ++ ++out_unlock_dev: ++ mutex_unlock(&dev->dev_mutex); ++out_unlock: ++ mutex_unlock(&devices_mutex); ++ return ret; + } + + static int ubiblock_resize(struct ubi_volume_info *vi) +@@ -633,6 +641,7 @@ static void ubiblock_remove_all(void) + struct ubiblock *next; + struct ubiblock *dev; + ++ mutex_lock(&devices_mutex); + list_for_each_entry_safe(dev, next, &ubiblock_devices, list) { + /* The module is being forcefully removed */ + WARN_ON(dev->desc); +@@ -641,6 +650,7 @@ static void ubiblock_remove_all(void) + ubiblock_cleanup(dev); + kfree(dev); + } ++ mutex_unlock(&devices_mutex); + } + + int __init ubiblock_init(void) +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +index f9640d5ce6ba..b4f3cb55605e 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +@@ -3850,7 +3850,7 @@ static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) + struct list_head *head = &mbx->cmd_q; + struct qlcnic_cmd_args *cmd = NULL; + +- spin_lock(&mbx->queue_lock); ++ spin_lock_bh(&mbx->queue_lock); + + while (!list_empty(head)) { + cmd = list_entry(head->next, struct qlcnic_cmd_args, list); +@@ -3861,7 +3861,7 @@ static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) + qlcnic_83xx_notify_cmd_completion(adapter, cmd); + } + +- spin_unlock(&mbx->queue_lock); ++ spin_unlock_bh(&mbx->queue_lock); + } + + static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) +@@ -3897,12 +3897,12 @@ static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, + { + struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; + +- spin_lock(&mbx->queue_lock); ++ spin_lock_bh(&mbx->queue_lock); + + list_del(&cmd->list); + mbx->num_cmds--; + +- spin_unlock(&mbx->queue_lock); ++ spin_unlock_bh(&mbx->queue_lock); + + qlcnic_83xx_notify_cmd_completion(adapter, cmd); + } +@@ -3967,7 +3967,7 @@ static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, + init_completion(&cmd->completion); + cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_UNKNOWN; + +- spin_lock(&mbx->queue_lock); ++ spin_lock_bh(&mbx->queue_lock); + + list_add_tail(&cmd->list, &mbx->cmd_q); + mbx->num_cmds++; +@@ -3975,7 +3975,7 @@ static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, + *timeout = cmd->total_cmds * QLC_83XX_MBX_TIMEOUT; + queue_work(mbx->work_q, &mbx->work); + +- spin_unlock(&mbx->queue_lock); ++ spin_unlock_bh(&mbx->queue_lock); + + return 0; + } +@@ -4071,15 +4071,15 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) + mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT; + spin_unlock_irqrestore(&mbx->aen_lock, flags); + +- spin_lock(&mbx->queue_lock); ++ spin_lock_bh(&mbx->queue_lock); + + if (list_empty(head)) { +- spin_unlock(&mbx->queue_lock); ++ spin_unlock_bh(&mbx->queue_lock); + return; + } + cmd = list_entry(head->next, struct qlcnic_cmd_args, list); + +- spin_unlock(&mbx->queue_lock); ++ spin_unlock_bh(&mbx->queue_lock); + + mbx_ops->encode_cmd(adapter, cmd); + mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_REQUEST); +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index 24155380e43c..3783c40f568b 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -1387,7 +1387,7 @@ DECLARE_RTL_COND(rtl_ocp_tx_cond) + { + void __iomem *ioaddr = tp->mmio_addr; + +- return RTL_R8(IBISR0) & 0x02; ++ return RTL_R8(IBISR0) & 0x20; + } + + static void rtl8168ep_stop_cmac(struct rtl8169_private *tp) +@@ -1395,7 +1395,7 @@ static void rtl8168ep_stop_cmac(struct rtl8169_private *tp) + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W8(IBCR2, RTL_R8(IBCR2) & ~0x01); +- rtl_msleep_loop_wait_low(tp, &rtl_ocp_tx_cond, 50, 2000); ++ rtl_msleep_loop_wait_high(tp, &rtl_ocp_tx_cond, 50, 2000); + RTL_W8(IBISR0, RTL_R8(IBISR0) | 0x20); + RTL_W8(IBCR0, RTL_R8(IBCR0) & ~0x01); + } +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index 1228d0da4075..72cb30828a12 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -825,6 +825,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ + goto error2; + } + ++ /* Device-specific flags */ ++ ctx->drvflags = drvflags; ++ + /* + * Some Huawei devices have been observed to come out of reset in NDP32 mode. + * Let's check if this is the case, and set the device to NDP16 mode again if +@@ -873,9 +876,6 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ + /* finish setting up the device specific data */ + cdc_ncm_setup(dev); + +- /* Device-specific flags */ +- ctx->drvflags = drvflags; +- + /* Allocate the delayed NDP if needed. */ + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { + ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index d6ceb8b91cd6..1c8aedf21370 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2976,10 +2976,16 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) + mutex_unlock(&dev->shutdown_lock); + } + +-static void nvme_dev_remove(struct nvme_dev *dev) ++static void nvme_remove_namespaces(struct nvme_dev *dev) + { + struct nvme_ns *ns, *next; + ++ list_for_each_entry_safe(ns, next, &dev->namespaces, list) ++ nvme_ns_remove(ns); ++} ++ ++static void nvme_dev_remove(struct nvme_dev *dev) ++{ + if (nvme_io_incapable(dev)) { + /* + * If the device is not capable of IO (surprise hot-removal, +@@ -2989,8 +2995,7 @@ static void nvme_dev_remove(struct nvme_dev *dev) + */ + nvme_dev_shutdown(dev); + } +- list_for_each_entry_safe(ns, next, &dev->namespaces, list) +- nvme_ns_remove(ns); ++ nvme_remove_namespaces(dev); + } + + static int nvme_setup_prp_pools(struct nvme_dev *dev) +@@ -3174,7 +3179,7 @@ static void nvme_probe_work(struct work_struct *work) + */ + if (dev->online_queues < 2) { + dev_warn(dev->dev, "IO queues not created\n"); +- nvme_dev_remove(dev); ++ nvme_remove_namespaces(dev); + } else { + nvme_unfreeze_queues(dev); + nvme_dev_add(dev); +diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c +index ad8c9b05572d..01656f1c6d65 100644 +--- a/drivers/usb/gadget/function/uvc_configfs.c ++++ b/drivers/usb/gadget/function/uvc_configfs.c +@@ -2202,7 +2202,7 @@ static struct configfs_item_operations uvc_item_ops = { + .release = uvc_attr_release, + }; + +-#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \ ++#define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \ + static ssize_t f_uvc_opts_##cname##_show( \ + struct config_item *item, char *page) \ + { \ +@@ -2245,16 +2245,16 @@ end: \ + return ret; \ + } \ + \ +-UVC_ATTR(f_uvc_opts_, cname, aname) ++UVC_ATTR(f_uvc_opts_, cname, cname) + + #define identity_conv(x) (x) + +-UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv, +- 16); +-UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu, +- 3072); +-UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv, +- 15); ++UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv, ++ kstrtou8, u8, identity_conv, 16); ++UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu, ++ kstrtou16, u16, le16_to_cpu, 3072); ++UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv, ++ kstrtou8, u8, identity_conv, 15); + + #undef identity_conv + +diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c +index 00d68945548e..2d96bfd34138 100644 +--- a/drivers/usb/usbip/vhci_hcd.c ++++ b/drivers/usb/usbip/vhci_hcd.c +@@ -285,7 +285,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + case USB_PORT_FEAT_POWER: + usbip_dbg_vhci_rh( + " ClearPortFeature: USB_PORT_FEAT_POWER\n"); +- dum->port_status[rhport] = 0; ++ dum->port_status[rhport] &= ~USB_PORT_STAT_POWER; + dum->resuming = 0; + break; + case USB_PORT_FEAT_C_RESET: +diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c +index 1c7f41a65565..b9432fdec775 100644 +--- a/drivers/usb/usbip/vhci_sysfs.c ++++ b/drivers/usb/usbip/vhci_sysfs.c +@@ -53,7 +53,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, + * a security hole, the change is made to use sockfd instead. + */ + out += sprintf(out, +- "prt sta spd bus dev sockfd local_busid\n"); ++ "prt sta spd dev sockfd local_busid\n"); + + for (i = 0; i < VHCI_NPORTS; i++) { + struct vhci_device *vdev = port_to_vdev(i); +@@ -64,12 +64,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, + if (vdev->ud.status == VDEV_ST_USED) { + out += sprintf(out, "%03u %08x ", + vdev->speed, vdev->devid); +- out += sprintf(out, "%16p ", vdev->ud.tcp_socket); +- out += sprintf(out, "%06u", vdev->ud.sockfd); ++ out += sprintf(out, "%06u ", vdev->ud.sockfd); + out += sprintf(out, "%s", dev_name(&vdev->udev->dev)); + + } else +- out += sprintf(out, "000 000 000 000000 0-0"); ++ out += sprintf(out, "000 00000000 000000 0-0"); + + out += sprintf(out, "\n"); + spin_unlock(&vdev->ud.lock); +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index 9eda69e40678..44a5a8777053 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -981,6 +981,7 @@ static long vhost_net_reset_owner(struct vhost_net *n) + } + vhost_net_stop(n, &tx_sock, &rx_sock); + vhost_net_flush(n); ++ vhost_dev_stop(&n->dev); + vhost_dev_reset_owner(&n->dev, memory); + vhost_net_vq_reset(n); + done: +diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c +index 29ef719a6a3c..d69ab1e28d7d 100644 +--- a/drivers/watchdog/imx2_wdt.c ++++ b/drivers/watchdog/imx2_wdt.c +@@ -161,15 +161,21 @@ static void imx2_wdt_timer_ping(unsigned long arg) + mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2); + } + +-static int imx2_wdt_set_timeout(struct watchdog_device *wdog, +- unsigned int new_timeout) ++static void __imx2_wdt_set_timeout(struct watchdog_device *wdog, ++ unsigned int new_timeout) + { + struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); + +- wdog->timeout = new_timeout; +- + regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT, + WDOG_SEC_TO_COUNT(new_timeout)); ++} ++ ++static int imx2_wdt_set_timeout(struct watchdog_device *wdog, ++ unsigned int new_timeout) ++{ ++ __imx2_wdt_set_timeout(wdog, new_timeout); ++ ++ wdog->timeout = new_timeout; + return 0; + } + +@@ -353,7 +359,11 @@ static int imx2_wdt_suspend(struct device *dev) + + /* The watchdog IP block is running */ + if (imx2_wdt_is_running(wdev)) { +- imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); ++ /* ++ * Don't update wdog->timeout, we'll restore the current value ++ * during resume. ++ */ ++ __imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); + imx2_wdt_ping(wdog); + + /* The watchdog is not active */ +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index af1da85da509..86d209fc4992 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -2015,7 +2015,15 @@ again: + goto out; + } + +- btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state); ++ ret = btrfs_set_extent_delalloc(inode, page_start, page_end, ++ &cached_state); ++ if (ret) { ++ mapping_set_error(page->mapping, ret); ++ end_extent_writepage(page, ret, page_start, page_end); ++ ClearPageChecked(page); ++ goto out; ++ } ++ + ClearPageChecked(page); + set_page_dirty(page); + out: +diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c +index 4acbc390a7d6..1d707a67f8ac 100644 +--- a/fs/cifs/cifsencrypt.c ++++ b/fs/cifs/cifsencrypt.c +@@ -306,9 +306,8 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, + { + int i; + int rc; +- char password_with_pad[CIFS_ENCPWD_SIZE]; ++ char password_with_pad[CIFS_ENCPWD_SIZE] = {0}; + +- memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); + if (password) + strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 0a2bf9462637..077ad3a06c9a 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1695,7 +1695,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + tmp_end++; + if (!(tmp_end < end && tmp_end[1] == delim)) { + /* No it is not. Set the password to NULL */ +- kfree(vol->password); ++ kzfree(vol->password); + vol->password = NULL; + break; + } +@@ -1733,7 +1733,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + options = end; + } + +- kfree(vol->password); ++ kzfree(vol->password); + /* Now build new password string */ + temp_len = strlen(value); + vol->password = kzalloc(temp_len+1, GFP_KERNEL); +@@ -4148,7 +4148,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) + reset_cifs_unix_caps(0, tcon, NULL, vol_info); + out: + kfree(vol_info->username); +- kfree(vol_info->password); ++ kzfree(vol_info->password); + kfree(vol_info); + + return tcon; +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index ec2d07bb9beb..744be3c146f5 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -3241,20 +3241,18 @@ static const struct vm_operations_struct cifs_file_vm_ops = { + + int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) + { +- int rc, xid; ++ int xid, rc = 0; + struct inode *inode = file_inode(file); + + xid = get_xid(); + +- if (!CIFS_CACHE_READ(CIFS_I(inode))) { ++ if (!CIFS_CACHE_READ(CIFS_I(inode))) + rc = cifs_zap_mapping(inode); +- if (rc) +- return rc; +- } +- +- rc = generic_file_mmap(file, vma); +- if (rc == 0) ++ if (!rc) ++ rc = generic_file_mmap(file, vma); ++ if (!rc) + vma->vm_ops = &cifs_file_vm_ops; ++ + free_xid(xid); + return rc; + } +@@ -3264,16 +3262,16 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) + int rc, xid; + + xid = get_xid(); ++ + rc = cifs_revalidate_file(file); +- if (rc) { ++ if (rc) + cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n", + rc); +- free_xid(xid); +- return rc; +- } +- rc = generic_file_mmap(file, vma); +- if (rc == 0) ++ if (!rc) ++ rc = generic_file_mmap(file, vma); ++ if (!rc) + vma->vm_ops = &cifs_file_vm_ops; ++ + free_xid(xid); + return rc; + } +diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c +index 2396ab099849..0cc699d9b932 100644 +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -99,14 +99,11 @@ sesInfoFree(struct cifs_ses *buf_to_free) + kfree(buf_to_free->serverOS); + kfree(buf_to_free->serverDomain); + kfree(buf_to_free->serverNOS); +- if (buf_to_free->password) { +- memset(buf_to_free->password, 0, strlen(buf_to_free->password)); +- kfree(buf_to_free->password); +- } ++ kzfree(buf_to_free->password); + kfree(buf_to_free->user_name); + kfree(buf_to_free->domainName); +- kfree(buf_to_free->auth_key.response); +- kfree(buf_to_free); ++ kzfree(buf_to_free->auth_key.response); ++ kzfree(buf_to_free); + } + + struct cifs_tcon * +@@ -137,10 +134,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) + } + atomic_dec(&tconInfoAllocCount); + kfree(buf_to_free->nativeFileSystem); +- if (buf_to_free->password) { +- memset(buf_to_free->password, 0, strlen(buf_to_free->password)); +- kfree(buf_to_free->password); +- } ++ kzfree(buf_to_free->password); + kfree(buf_to_free); + } + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index f2ff60e58ec8..84614a5edb87 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -580,8 +580,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } + + /* check validate negotiate info response matches what we got earlier */ +- if (pneg_rsp->Dialect != +- cpu_to_le16(tcon->ses->server->vals->protocol_id)) ++ if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) + goto vneg_out; + + if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 4df1cb19a243..f0cabc8c96cb 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4417,6 +4417,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) + inode->i_op = &ext4_symlink_inode_operations; + ext4_set_aops(inode); + } ++ inode_nohighmem(inode); + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + inode->i_op = &ext4_special_inode_operations; +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 4c36dca486cc..32960b3ecd4f 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3151,6 +3151,7 @@ static int ext4_symlink(struct inode *dir, + if ((disk_link.len > EXT4_N_BLOCKS * 4)) { + if (!encryption_required) + inode->i_op = &ext4_symlink_inode_operations; ++ inode_nohighmem(inode); + ext4_set_aops(inode); + /* + * We cannot call page_symlink() with transaction started +diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c +index e8e7af62ac95..287c3980fa0b 100644 +--- a/fs/ext4/symlink.c ++++ b/fs/ext4/symlink.c +@@ -45,7 +45,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook + cpage = read_mapping_page(inode->i_mapping, 0, NULL); + if (IS_ERR(cpage)) + return ERR_CAST(cpage); +- caddr = kmap(cpage); ++ caddr = page_address(cpage); + caddr[size] = 0; + } + +@@ -75,16 +75,12 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook + /* Null-terminate the name */ + if (res <= plen) + paddr[res] = '\0'; +- if (cpage) { +- kunmap(cpage); ++ if (cpage) + page_cache_release(cpage); +- } + return *cookie = paddr; + errout: +- if (cpage) { +- kunmap(cpage); ++ if (cpage) + page_cache_release(cpage); +- } + kfree(paddr); + return ERR_PTR(res); + } +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 97e20decacb4..5528801a5baf 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -202,6 +202,7 @@ make_now: + inode->i_op = &f2fs_encrypted_symlink_inode_operations; + else + inode->i_op = &f2fs_symlink_inode_operations; ++ inode_nohighmem(inode); + inode->i_mapping->a_ops = &f2fs_dblock_aops; + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index 2c32110f9fc0..484df6850747 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -351,6 +351,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, + inode->i_op = &f2fs_encrypted_symlink_inode_operations; + else + inode->i_op = &f2fs_symlink_inode_operations; ++ inode_nohighmem(inode); + inode->i_mapping->a_ops = &f2fs_dblock_aops; + + f2fs_lock_op(sbi); +@@ -942,7 +943,7 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook + cpage = read_mapping_page(inode->i_mapping, 0, NULL); + if (IS_ERR(cpage)) + return ERR_CAST(cpage); +- caddr = kmap(cpage); ++ caddr = page_address(cpage); + caddr[size] = 0; + + /* Symlink is encrypted */ +@@ -982,13 +983,11 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook + /* Null-terminate the name */ + paddr[res] = '\0'; + +- kunmap(cpage); + page_cache_release(cpage); + return *cookie = paddr; + errout: + kfree(cstr.name); + f2fs_fname_crypto_free_buffer(&pstr); +- kunmap(cpage); + page_cache_release(cpage); + return ERR_PTR(res); + } +diff --git a/fs/inode.c b/fs/inode.c +index b0edef500590..b95615f3fc50 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -2028,3 +2028,9 @@ void inode_set_flags(struct inode *inode, unsigned int flags, + new_flags) != old_flags)); + } + EXPORT_SYMBOL(inode_set_flags); ++ ++void inode_nohighmem(struct inode *inode) ++{ ++ mapping_set_gfp_mask(inode->i_mapping, GFP_USER); ++} ++EXPORT_SYMBOL(inode_nohighmem); +diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c +index 6e9a912d394c..6875bd5d35f6 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -272,7 +272,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, + { + struct kernfs_open_file *of = kernfs_of(file); + const struct kernfs_ops *ops; +- size_t len; ++ ssize_t len; + char *buf; + + if (of->atomic_write_len) { +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 4b1d08f56aba..5fd3cf54b2b3 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -787,10 +787,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) + + spin_lock(&dreq->lock); + +- if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { +- dreq->flags = 0; ++ if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) + dreq->error = hdr->error; +- } + if (dreq->error == 0) { + nfs_direct_good_bytes(dreq, hdr); + if (nfs_write_need_commit(hdr)) { +diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c +index 5ba22c6b0ffa..1ee62e62ea76 100644 +--- a/fs/nfs/nfs4idmap.c ++++ b/fs/nfs/nfs4idmap.c +@@ -567,9 +567,13 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, + struct idmap_msg *im; + struct idmap *idmap = (struct idmap *)aux; + struct key *key = cons->key; +- int ret = -ENOMEM; ++ int ret = -ENOKEY; ++ ++ if (!aux) ++ goto out1; + + /* msg and im are freed in idmap_pipe_destroy_msg */ ++ ret = -ENOMEM; + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto out1; +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index 7af7bedd7c02..c8e75e5e6a67 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -1943,7 +1943,7 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, + nfs_pageio_reset_write_mds(desc); + mirror->pg_recoalesce = 1; + } +- hdr->release(hdr); ++ hdr->completion_ops->completion(hdr); + } + + static enum pnfs_try_status +@@ -2058,7 +2058,7 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, + nfs_pageio_reset_read_mds(desc); + mirror->pg_recoalesce = 1; + } +- hdr->release(hdr); ++ hdr->completion_ops->completion(hdr); + } + + /* +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index 7a9b6e347249..6e81a5b5858e 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -1746,6 +1746,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) + set_bit(NFS_CONTEXT_RESEND_WRITES, &req->wb_context->flags); + next: + nfs_unlock_and_release_request(req); ++ /* Latency breaker */ ++ cond_resched(); + } + nfss = NFS_SERVER(data->inode); + if (atomic_long_read(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) +diff --git a/fs/nsfs.c b/fs/nsfs.c +index 8f20d6016e20..914ca6b2794d 100644 +--- a/fs/nsfs.c ++++ b/fs/nsfs.c +@@ -95,6 +95,7 @@ slow: + return ERR_PTR(-ENOMEM); + } + d_instantiate(dentry, inode); ++ dentry->d_flags |= DCACHE_RCUACCESS; + dentry->d_fsdata = (void *)ns_ops; + d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); + if (d) { +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index adcb1398c481..299a6e1d6b77 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -441,10 +441,14 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, + struct dentry *dentry = file->f_path.dentry; + struct file *realfile = od->realfile; + ++ /* Nothing to sync for lower */ ++ if (!OVL_TYPE_UPPER(ovl_path_type(dentry))) ++ return 0; ++ + /* + * Need to check if we started out being a lower dir, but got copied up + */ +- if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) { ++ if (!od->is_upper) { + struct inode *inode = file_inode(file); + + realfile = lockless_dereference(od->upperfile); +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index 9779c35f8454..dab9569f22bf 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -91,6 +91,8 @@ static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) + return alg->setkey != shash_no_setkey; + } + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg); ++ + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, + struct hash_alg_common *alg, + struct crypto_instance *inst); +diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h +index 894df59b74e4..d586f741cab5 100644 +--- a/include/crypto/poly1305.h ++++ b/include/crypto/poly1305.h +@@ -30,8 +30,6 @@ struct poly1305_desc_ctx { + }; + + int crypto_poly1305_init(struct shash_desc *desc); +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen); + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen); + int crypto_poly1305_update(struct shash_desc *desc, +diff --git a/include/linux/fs.h b/include/linux/fs.h +index c8decb7075d6..f746a59fcc88 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3066,5 +3066,6 @@ static inline bool dir_relax(struct inode *inode) + } + + extern bool path_noexec(const struct path *path); ++extern void inode_nohighmem(struct inode *inode); + + #endif /* _LINUX_FS_H */ +diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h +index 806d0ab845e0..676d3d2a1a0a 100644 +--- a/include/linux/mtd/map.h ++++ b/include/linux/mtd/map.h +@@ -265,75 +265,67 @@ void map_destroy(struct mtd_info *mtd); + #define INVALIDATE_CACHED_RANGE(map, from, size) \ + do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0) + +- +-static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if (val1.x[i] != val2.x[i]) +- return 0; +- } +- +- return 1; +-} +- +-static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] & val2.x[i]; +- +- return r; +-} +- +-static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] & ~val2.x[i]; +- +- return r; +-} +- +-static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] | val2.x[i]; +- +- return r; +-} +- +-static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if ((val1.x[i] & val2.x[i]) != val3.x[i]) +- return 0; +- } +- +- return 1; +-} +- +-static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if (val1.x[i] & val2.x[i]) +- return 1; +- } +- +- return 0; +-} ++#define map_word_equal(map, val1, val2) \ ++({ \ ++ int i, ret = 1; \ ++ for (i = 0; i < map_words(map); i++) \ ++ if ((val1).x[i] != (val2).x[i]) { \ ++ ret = 0; \ ++ break; \ ++ } \ ++ ret; \ ++}) ++ ++#define map_word_and(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] & (val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_clr(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] & ~(val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_or(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] | (val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_andequal(map, val1, val2, val3) \ ++({ \ ++ int i, ret = 1; \ ++ for (i = 0; i < map_words(map); i++) { \ ++ if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) { \ ++ ret = 0; \ ++ break; \ ++ } \ ++ } \ ++ ret; \ ++}) ++ ++#define map_word_bitsset(map, val1, val2) \ ++({ \ ++ int i, ret = 0; \ ++ for (i = 0; i < map_words(map); i++) { \ ++ if ((val1).x[i] & (val2).x[i]) { \ ++ ret = 1; \ ++ break; \ ++ } \ ++ } \ ++ ret; \ ++}) + + static inline map_word map_word_load(struct map_info *map, const void *ptr) + { +diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h +index 9c5638ad872e..0dbce55437f2 100644 +--- a/include/net/netfilter/nf_queue.h ++++ b/include/net/netfilter/nf_queue.h +@@ -28,8 +28,8 @@ struct nf_queue_handler { + struct nf_hook_ops *ops); + }; + +-void nf_register_queue_handler(const struct nf_queue_handler *qh); +-void nf_unregister_queue_handler(void); ++void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh); ++void nf_unregister_queue_handler(struct net *net); + void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); + + void nf_queue_entry_get_refs(struct nf_queue_entry *entry); +diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h +index 38aa4983e2a9..36d723579af2 100644 +--- a/include/net/netns/netfilter.h ++++ b/include/net/netns/netfilter.h +@@ -5,11 +5,13 @@ + + struct proc_dir_entry; + struct nf_logger; ++struct nf_queue_handler; + + struct netns_nf { + #if defined CONFIG_PROC_FS + struct proc_dir_entry *proc_netfilter; + #endif ++ const struct nf_queue_handler __rcu *queue_handler; + const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; + #ifdef CONFIG_SYSCTL + struct ctl_table_header *nf_log_dir_header; +diff --git a/kernel/async.c b/kernel/async.c +index 4c3773c0bf63..f1fd155abff6 100644 +--- a/kernel/async.c ++++ b/kernel/async.c +@@ -84,20 +84,24 @@ static atomic_t entry_count; + + static async_cookie_t lowest_in_progress(struct async_domain *domain) + { +- struct list_head *pending; ++ struct async_entry *first = NULL; + async_cookie_t ret = ASYNC_COOKIE_MAX; + unsigned long flags; + + spin_lock_irqsave(&async_lock, flags); + +- if (domain) +- pending = &domain->pending; +- else +- pending = &async_global_pending; ++ if (domain) { ++ if (!list_empty(&domain->pending)) ++ first = list_first_entry(&domain->pending, ++ struct async_entry, domain_list); ++ } else { ++ if (!list_empty(&async_global_pending)) ++ first = list_first_entry(&async_global_pending, ++ struct async_entry, global_list); ++ } + +- if (!list_empty(pending)) +- ret = list_first_entry(pending, struct async_entry, +- domain_list)->cookie; ++ if (first) ++ ret = first->cookie; + + spin_unlock_irqrestore(&async_lock, flags); + return ret; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index e6d1173a2046..c5b1c62623cf 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -5896,6 +5896,19 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd) + call_rcu_sched(&old_rd->rcu, free_rootdomain); + } + ++void sched_get_rd(struct root_domain *rd) ++{ ++ atomic_inc(&rd->refcount); ++} ++ ++void sched_put_rd(struct root_domain *rd) ++{ ++ if (!atomic_dec_and_test(&rd->refcount)) ++ return; ++ ++ call_rcu_sched(&rd->rcu, free_rootdomain); ++} ++ + static int init_rootdomain(struct root_domain *rd) + { + memset(rd, 0, sizeof(*rd)); +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 95fefb364dab..e0b5169aeac4 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1833,9 +1833,8 @@ static void push_rt_tasks(struct rq *rq) + * the rt_loop_next will cause the iterator to perform another scan. + * + */ +-static int rto_next_cpu(struct rq *rq) ++static int rto_next_cpu(struct root_domain *rd) + { +- struct root_domain *rd = rq->rd; + int next; + int cpu; + +@@ -1911,19 +1910,24 @@ static void tell_cpu_to_push(struct rq *rq) + * Otherwise it is finishing up and an ipi needs to be sent. + */ + if (rq->rd->rto_cpu < 0) +- cpu = rto_next_cpu(rq); ++ cpu = rto_next_cpu(rq->rd); + + raw_spin_unlock(&rq->rd->rto_lock); + + rto_start_unlock(&rq->rd->rto_loop_start); + +- if (cpu >= 0) ++ if (cpu >= 0) { ++ /* Make sure the rd does not get freed while pushing */ ++ sched_get_rd(rq->rd); + irq_work_queue_on(&rq->rd->rto_push_work, cpu); ++ } + } + + /* Called from hardirq context */ + void rto_push_irq_work_func(struct irq_work *work) + { ++ struct root_domain *rd = ++ container_of(work, struct root_domain, rto_push_work); + struct rq *rq; + int cpu; + +@@ -1939,18 +1943,20 @@ void rto_push_irq_work_func(struct irq_work *work) + raw_spin_unlock(&rq->lock); + } + +- raw_spin_lock(&rq->rd->rto_lock); ++ raw_spin_lock(&rd->rto_lock); + + /* Pass the IPI to the next rt overloaded queue */ +- cpu = rto_next_cpu(rq); ++ cpu = rto_next_cpu(rd); + +- raw_spin_unlock(&rq->rd->rto_lock); ++ raw_spin_unlock(&rd->rto_lock); + +- if (cpu < 0) ++ if (cpu < 0) { ++ sched_put_rd(rd); + return; ++ } + + /* Try the next RT overloaded CPU */ +- irq_work_queue_on(&rq->rd->rto_push_work, cpu); ++ irq_work_queue_on(&rd->rto_push_work, cpu); + } + #endif /* HAVE_RT_PUSH_IPI */ + +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 448a8266ceea..0c9ebd82a684 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -553,6 +553,8 @@ struct root_domain { + }; + + extern struct root_domain def_root_domain; ++extern void sched_get_rd(struct root_domain *rd); ++extern void sched_put_rd(struct root_domain *rd); + + #ifdef HAVE_RT_PUSH_IPI + extern void rto_push_irq_work_func(struct irq_work *work); +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index f2826c35e918..fc7c37ad90a0 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -507,17 +507,22 @@ static struct pid *good_sigevent(sigevent_t * event) + { + struct task_struct *rtn = current->group_leader; + +- if ((event->sigev_notify & SIGEV_THREAD_ID ) && +- (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) || +- !same_thread_group(rtn, current) || +- (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) ++ switch (event->sigev_notify) { ++ case SIGEV_SIGNAL | SIGEV_THREAD_ID: ++ rtn = find_task_by_vpid(event->sigev_notify_thread_id); ++ if (!rtn || !same_thread_group(rtn, current)) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_SIGNAL: ++ case SIGEV_THREAD: ++ if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_NONE: ++ return task_pid(rtn); ++ default: + return NULL; +- +- if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) && +- ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) +- return NULL; +- +- return task_pid(rtn); ++ } + } + + void posix_timers_register_clock(const clockid_t clock_id, +@@ -745,8 +750,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + /* interval timer ? */ + if (iv.tv64) + cur_setting->it_interval = ktime_to_timespec(iv); +- else if (!hrtimer_active(timer) && +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE) + return; + + now = timer->base->get_time(); +@@ -757,7 +761,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + * expiry is > now. + */ + if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) ++ timr->it_sigev_notify == SIGEV_NONE)) + timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); + + remaining = __hrtimer_expires_remaining_adjusted(timer, now); +@@ -767,7 +771,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + * A single shot SIGEV_NONE timer must return 0, when + * it is expired ! + */ +- if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ if (timr->it_sigev_notify != SIGEV_NONE) + cur_setting->it_value.tv_nsec = 1; + } else + cur_setting->it_value = ktime_to_timespec(remaining); +@@ -865,7 +869,7 @@ common_timer_set(struct k_itimer *timr, int flags, + timr->it.real.interval = timespec_to_ktime(new_setting->it_interval); + + /* SIGEV_NONE timers are not queued ! See common_timer_get */ +- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { ++ if (timr->it_sigev_notify == SIGEV_NONE) { + /* Setup correct expiry time for relative timers */ + if (mode == HRTIMER_MODE_REL) { + hrtimer_add_expires(timer, timer->base->get_time()); +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index fc0051fd672d..ac758a53fcea 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -3845,7 +3845,6 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, + func_g.type = filter_parse_regex(glob, strlen(glob), + &func_g.search, ¬); + func_g.len = strlen(func_g.search); +- func_g.search = glob; + + /* we do not support '!' for function probes */ + if (WARN_ON(not)) +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index b68168fcc06a..9d43c1f40274 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -259,6 +259,7 @@ int dccp_disconnect(struct sock *sk, int flags) + { + struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_sock *inet = inet_sk(sk); ++ struct dccp_sock *dp = dccp_sk(sk); + int err = 0; + const int old_state = sk->sk_state; + +@@ -278,6 +279,10 @@ int dccp_disconnect(struct sock *sk, int flags) + sk->sk_err = ECONNRESET; + + dccp_clear_xmit_timers(sk); ++ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); ++ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); ++ dp->dccps_hc_rx_ccid = NULL; ++ dp->dccps_hc_tx_ccid = NULL; + + __skb_queue_purge(&sk->sk_receive_queue); + __skb_queue_purge(&sk->sk_write_queue); +diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c +index 8212ed80da48..c67efa3e79dd 100644 +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -392,7 +392,11 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) + pip->frag_off = htons(IP_DF); + pip->ttl = 1; + pip->daddr = fl4.daddr; ++ ++ rcu_read_lock(); + pip->saddr = igmpv3_get_srcaddr(dev, &fl4); ++ rcu_read_unlock(); ++ + pip->protocol = IPPROTO_IGMP; + pip->tot_len = 0; /* filled in later */ + ip_select_ident(net, skb, NULL); +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 37e8966a457b..23d77ff1da59 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2276,6 +2276,12 @@ int tcp_disconnect(struct sock *sk, int flags) + + WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); + ++ if (sk->sk_frag.page) { ++ put_page(sk->sk_frag.page); ++ sk->sk_frag.page = NULL; ++ sk->sk_frag.offset = 0; ++ } ++ + sk->sk_error_report(sk); + return err; + } +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index 8361d73ab653..e5846d1f9b55 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -495,6 +495,7 @@ static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) + return ERR_PTR(-ENOENT); + + it->mrt = mrt; ++ it->cache = NULL; + return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) + : SEQ_START_TOKEN; + } +diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c +index 5baa8e24e6ac..b19ad20a705c 100644 +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -26,23 +26,21 @@ + * Once the queue is registered it must reinject all packets it + * receives, no matter what. + */ +-static const struct nf_queue_handler __rcu *queue_handler __read_mostly; + + /* return EBUSY when somebody else is registered, return EEXIST if the + * same handler is registered, return 0 in case of success. */ +-void nf_register_queue_handler(const struct nf_queue_handler *qh) ++void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh) + { + /* should never happen, we only have one queueing backend in kernel */ +- WARN_ON(rcu_access_pointer(queue_handler)); +- rcu_assign_pointer(queue_handler, qh); ++ WARN_ON(rcu_access_pointer(net->nf.queue_handler)); ++ rcu_assign_pointer(net->nf.queue_handler, qh); + } + EXPORT_SYMBOL(nf_register_queue_handler); + + /* The caller must flush their queue before this */ +-void nf_unregister_queue_handler(void) ++void nf_unregister_queue_handler(struct net *net) + { +- RCU_INIT_POINTER(queue_handler, NULL); +- synchronize_rcu(); ++ RCU_INIT_POINTER(net->nf.queue_handler, NULL); + } + EXPORT_SYMBOL(nf_unregister_queue_handler); + +@@ -103,7 +101,7 @@ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops) + const struct nf_queue_handler *qh; + + rcu_read_lock(); +- qh = rcu_dereference(queue_handler); ++ qh = rcu_dereference(net->nf.queue_handler); + if (qh) + qh->nf_hook_drop(net, ops); + rcu_read_unlock(); +@@ -122,9 +120,10 @@ int nf_queue(struct sk_buff *skb, + struct nf_queue_entry *entry = NULL; + const struct nf_afinfo *afinfo; + const struct nf_queue_handler *qh; ++ struct net *net = state->net; + + /* QUEUE == DROP if no one is waiting, to be safe. */ +- qh = rcu_dereference(queue_handler); ++ qh = rcu_dereference(net->nf.queue_handler); + if (!qh) { + status = -ESRCH; + goto err; +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index c14d2e8eaec3..f853b55bf877 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -1382,21 +1382,29 @@ static int __net_init nfnl_queue_net_init(struct net *net) + net->nf.proc_netfilter, &nfqnl_file_ops)) + return -ENOMEM; + #endif ++ nf_register_queue_handler(net, &nfqh); + return 0; + } + + static void __net_exit nfnl_queue_net_exit(struct net *net) + { ++ nf_unregister_queue_handler(net); + #ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); + #endif + } + ++static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list) ++{ ++ synchronize_rcu(); ++} ++ + static struct pernet_operations nfnl_queue_net_ops = { +- .init = nfnl_queue_net_init, +- .exit = nfnl_queue_net_exit, +- .id = &nfnl_queue_net_id, +- .size = sizeof(struct nfnl_queue_net), ++ .init = nfnl_queue_net_init, ++ .exit = nfnl_queue_net_exit, ++ .exit_batch = nfnl_queue_net_exit_batch, ++ .id = &nfnl_queue_net_id, ++ .size = sizeof(struct nfnl_queue_net), + }; + + static int __init nfnetlink_queue_init(void) +@@ -1417,7 +1425,6 @@ static int __init nfnetlink_queue_init(void) + } + + register_netdevice_notifier(&nfqnl_dev_notifier); +- nf_register_queue_handler(&nfqh); + return status; + + cleanup_netlink_notifier: +@@ -1429,7 +1436,6 @@ out: + + static void __exit nfnetlink_queue_fini(void) + { +- nf_unregister_queue_handler(); + unregister_netdevice_notifier(&nfqnl_dev_notifier); + nfnetlink_subsys_unregister(&nfqnl_subsys); + netlink_unregister_notifier(&nfqnl_rtnl_notifier); +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index e080746e1a6b..48958d3cec9e 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -594,7 +594,8 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) + if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || + strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 || + strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || +- strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0) ++ strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0 || ++ strcmp(symname, ".TOC.") == 0) + return 1; + /* Do not ignore this symbol */ + return 0; +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index ce295c0c1da0..e44e844c8ec4 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc) + */ + static int valid_master_desc(const char *new_desc, const char *orig_desc) + { +- if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { +- if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) +- goto out; +- if (orig_desc) +- if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) +- goto out; +- } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { +- if (strlen(new_desc) == KEY_USER_PREFIX_LEN) +- goto out; +- if (orig_desc) +- if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) +- goto out; +- } else +- goto out; ++ int prefix_len; ++ ++ if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) ++ prefix_len = KEY_TRUSTED_PREFIX_LEN; ++ else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) ++ prefix_len = KEY_USER_PREFIX_LEN; ++ else ++ return -EINVAL; ++ ++ if (!new_desc[prefix_len]) ++ return -EINVAL; ++ ++ if (orig_desc && strncmp(new_desc, orig_desc, prefix_len)) ++ return -EINVAL; ++ + return 0; +-out: +- return -EINVAL; + } + + /* +diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c +index 712ed6598c48..ebdf9bd5a64c 100644 +--- a/sound/soc/codecs/pcm512x-spi.c ++++ b/sound/soc/codecs/pcm512x-spi.c +@@ -70,3 +70,7 @@ static struct spi_driver pcm512x_spi_driver = { + }; + + module_spi_driver(pcm512x_spi_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM512x codec driver - SPI"); ++MODULE_AUTHOR("Mark Brown "); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c +index ff6fcd9f92f7..0b1b6fcb7500 100644 +--- a/sound/soc/generic/simple-card.c ++++ b/sound/soc/generic/simple-card.c +@@ -343,13 +343,19 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, + snprintf(prop, sizeof(prop), "%scpu", prefix); + cpu = of_get_child_by_name(node, prop); + ++ if (!cpu) { ++ ret = -EINVAL; ++ dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); ++ goto dai_link_of_err; ++ } ++ + snprintf(prop, sizeof(prop), "%splat", prefix); + plat = of_get_child_by_name(node, prop); + + snprintf(prop, sizeof(prop), "%scodec", prefix); + codec = of_get_child_by_name(node, prop); + +- if (!cpu || !codec) { ++ if (!codec) { + ret = -EINVAL; + dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); + goto dai_link_of_err; +diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h +index 085329878525..5976e3992dd1 100644 +--- a/sound/soc/sh/rcar/rsnd.h ++++ b/sound/soc/sh/rcar/rsnd.h +@@ -235,6 +235,7 @@ enum rsnd_mod_type { + RSND_MOD_MIX, + RSND_MOD_CTU, + RSND_MOD_SRC, ++ RSND_MOD_SSIP, /* SSI parent */ + RSND_MOD_SSI, + RSND_MOD_MAX, + }; +@@ -365,6 +366,7 @@ struct rsnd_dai_stream { + }; + #define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL) + #define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI) ++#define rsnd_io_to_mod_ssip(io) rsnd_io_to_mod((io), RSND_MOD_SSIP) + #define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC) + #define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU) + #define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX) +diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c +index c62a2947ac14..38aae96267c9 100644 +--- a/sound/soc/sh/rcar/ssi.c ++++ b/sound/soc/sh/rcar/ssi.c +@@ -550,11 +550,16 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_priv *priv) + { + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); ++ struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io); + struct device *dev = rsnd_priv_to_dev(priv); + int irq = ssi->info->irq; + + rsnd_dma_quit(io, rsnd_mod_to_dma(mod)); + ++ /* Do nothing if non SSI (= SSI parent, multi SSI) mod */ ++ if (pure_ssi_mod != mod) ++ return 0; ++ + /* PIO will request IRQ again */ + devm_free_irq(dev, irq, mod); +