diff options
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1081_linux-4.9.82.patch | 4130 |
2 files changed, 4134 insertions, 0 deletions
diff --git a/0000_README b/0000_README index a2405f2c..363e368e 100644 --- a/0000_README +++ b/0000_README @@ -367,6 +367,10 @@ Patch: 1080_linux-4.9.81.patch From: http://www.kernel.org Desc: Linux 4.9.81 +Patch: 1081_linux-4.9.82.patch +From: http://www.kernel.org +Desc: Linux 4.9.82 + 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/1081_linux-4.9.82.patch b/1081_linux-4.9.82.patch new file mode 100644 index 00000000..a60b06b5 --- /dev/null +++ b/1081_linux-4.9.82.patch @@ -0,0 +1,4130 @@ +diff --git a/Makefile b/Makefile +index 4d5753f1c37b..d338530540e0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 81 ++SUBLEVEL = 82 + EXTRAVERSION = + NAME = Roaring Lionus + +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 b483156698d5..60c17b9bf04d 100644 +--- a/arch/alpha/kernel/process.c ++++ b/arch/alpha/kernel/process.c +@@ -265,12 +265,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/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c +index 74aceead06e9..32ba92cdf5f6 100644 +--- a/arch/alpha/kernel/traps.c ++++ b/arch/alpha/kernel/traps.c +@@ -158,11 +158,16 @@ void show_stack(struct task_struct *task, unsigned long *sp) + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & (THREAD_SIZE-1)) == 0) + break; +- if (i && ((i % 4) == 0)) +- printk("\n "); +- printk("%016lx ", *stack++); ++ if ((i % 4) == 0) { ++ if (i) ++ pr_cont("\n"); ++ printk(" "); ++ } else { ++ pr_cont(" "); ++ } ++ pr_cont("%016lx", *stack++); + } +- printk("\n"); ++ pr_cont("\n"); + dik_show_trace(sp); + } + +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index 19b5f5c1c0ff..c38bfbeec306 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -1165,6 +1165,7 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, + cpu_hyp_reset(); + + return NOTIFY_OK; ++ case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + if (__this_cpu_read(kvm_arm_hardware_enabled)) + /* The hardware was enabled before suspend. */ +diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c +index 42f5daf715d0..4e57ebca6e69 100644 +--- a/arch/arm/kvm/handle_exit.c ++++ b/arch/arm/kvm/handle_exit.c +@@ -38,7 +38,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; + } + +@@ -47,7 +47,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 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code) + + 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/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index 0e12cb2437d1..dc0996b9d75d 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -319,6 +319,7 @@ + #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2 + + #ifndef __ASSEMBLY__ ++#include <linux/types.h> + + /** + * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments +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 e32142bc071d..28c372003e44 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/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c +index 36870b26067a..d08805032f01 100644 +--- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c ++++ b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c +@@ -57,10 +57,12 @@ void sha512_mb_mgr_init_avx2(struct sha512_mb_mgr *state) + { + unsigned int j; + +- state->lens[0] = 0; +- state->lens[1] = 1; +- state->lens[2] = 2; +- state->lens[3] = 3; ++ /* initially all lanes are unused */ ++ state->lens[0] = 0xFFFFFFFF00000000; ++ state->lens[1] = 0xFFFFFFFF00000001; ++ state->lens[2] = 0xFFFFFFFF00000002; ++ state->lens[3] = 0xFFFFFFFF00000003; ++ + state->unused_lanes = 0xFF03020100; + for (j = 0; j < 4; j++) + state->ldata[j].job_in_lane = NULL; +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/kvm/vmx.c b/arch/x86/kvm/vmx.c +index d49da86e3099..d66224e695cf 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -4967,14 +4967,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/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 cce0268a13fe..f3fa104de479 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -625,5 +625,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 0c654e59f215..af9ad45d1909 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -691,7 +691,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/mcryptd.c b/crypto/mcryptd.c +index a14100e74754..6e9389c8bfbd 100644 +--- a/crypto/mcryptd.c ++++ b/crypto/mcryptd.c +@@ -534,7 +534,8 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + inst->alg.finup = mcryptd_hash_finup_enqueue; + inst->alg.export = mcryptd_hash_export; + inst->alg.import = mcryptd_hash_import; +- inst->alg.setkey = mcryptd_hash_setkey; ++ if (crypto_hash_alg_has_setkey(halg)) ++ inst->alg.setkey = mcryptd_hash_setkey; + inst->alg.digest = mcryptd_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/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c +index fe03d00de22b..b1815b20a99c 100644 +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -1535,6 +1535,9 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) + struct kernfs_node *nfit_kernfs; + + nvdimm = nfit_mem->nvdimm; ++ if (!nvdimm) ++ continue; ++ + nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit"); + if (nfit_kernfs) + nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs, +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 c94038206c3a..9b46ef4c851e 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -265,9 +265,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 */ +@@ -290,9 +290,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 */ +@@ -301,20 +301,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 */ +@@ -355,21 +355,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*/ +@@ -383,6 +383,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0xa206), 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 90fa4ac149db..7e4ef0502796 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 1cb958e199eb..94e914a33a99 100644 +--- a/drivers/bluetooth/btsdio.c ++++ b/drivers/bluetooth/btsdio.c +@@ -31,6 +31,7 @@ + #include <linux/errno.h> + #include <linux/skbuff.h> + ++#include <linux/mmc/host.h> + #include <linux/mmc/sdio_ids.h> + #include <linux/mmc/sdio_func.h> + +@@ -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 693028659ccc..3257647d4f74 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -23,6 +23,7 @@ + + #include <linux/module.h> + #include <linux/usb.h> ++#include <linux/usb/quirks.h> + #include <linux/firmware.h> + #include <asm/unaligned.h> + +@@ -369,8 +370,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; +@@ -2928,9 +2929,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 +@@ -2941,7 +2942,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 + +@@ -3098,14 +3099,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/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c +index 1b2574c4fb97..b167cc634fae 100644 +--- a/drivers/clocksource/timer-stm32.c ++++ b/drivers/clocksource/timer-stm32.c +@@ -16,6 +16,7 @@ + #include <linux/of_irq.h> + #include <linux/clk.h> + #include <linux/reset.h> ++#include <linux/slab.h> + + #define TIM_CR1 0x00 + #define TIM_DIER 0x0c +@@ -106,6 +107,10 @@ static int __init stm32_clockevent_init(struct device_node *np) + unsigned long rate, max_delta; + int irq, ret, bits, prescaler = 1; + ++ data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); +@@ -156,8 +161,8 @@ static int __init stm32_clockevent_init(struct device_node *np) + + writel_relaxed(prescaler - 1, data->base + TIM_PSC); + writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR); +- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER); + writel_relaxed(0, data->base + TIM_SR); ++ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER); + + data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ); + +@@ -184,6 +189,7 @@ static int __init stm32_clockevent_init(struct device_node *np) + err_clk_enable: + clk_put(clk); + err_clk_get: ++ kfree(data); + return ret; + } + +diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c +index 98468b96c32f..2ca101ac0c17 100644 +--- a/drivers/crypto/caam/ctrl.c ++++ b/drivers/crypto/caam/ctrl.c +@@ -228,12 +228,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 e0bd578a253a..ebe72a466587 100644 +--- a/drivers/dma/dmatest.c ++++ b/drivers/dma/dmatest.c +@@ -339,7 +339,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/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 7fdc42e5aac8..74163a928cba 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -5063,6 +5063,12 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, + */ + final->t8 = 1; + final->t9 = 1; ++ ++ /* ++ * HW has only a 100msec granularity for t11_t12 so round it up ++ * accordingly. ++ */ ++ final->t11_t12 = roundup(final->t11_t12, 100 * 10); + } + + static void +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index e32862ca5223..03cac5731afc 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2365,7 +2365,6 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, + { 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) }, +@@ -2635,6 +2634,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/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c +index ad304eed656d..c61227cfff25 100644 +--- a/drivers/media/dvb-frontends/ascot2e.c ++++ b/drivers/media/dvb-frontends/ascot2e.c +@@ -155,7 +155,9 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv, + + static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val) + { +- return ascot2e_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return ascot2e_write_regs(priv, reg, &tmp, 1); + } + + static int ascot2e_read_regs(struct ascot2e_priv *priv, +diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c +index fd0f25ee251f..b97647cd7dc6 100644 +--- a/drivers/media/dvb-frontends/cxd2841er.c ++++ b/drivers/media/dvb-frontends/cxd2841er.c +@@ -261,7 +261,9 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv, + static int cxd2841er_write_reg(struct cxd2841er_priv *priv, + u8 addr, u8 reg, u8 val) + { +- return cxd2841er_write_regs(priv, addr, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return cxd2841er_write_regs(priv, addr, reg, &tmp, 1); + } + + static int cxd2841er_read_regs(struct cxd2841er_priv *priv, +diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c +index dc43c5f6d0ea..e06bcd4b3ddc 100644 +--- a/drivers/media/dvb-frontends/helene.c ++++ b/drivers/media/dvb-frontends/helene.c +@@ -331,7 +331,9 @@ static int helene_write_regs(struct helene_priv *priv, + + static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) + { +- return helene_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return helene_write_regs(priv, reg, &tmp, 1); + } + + static int helene_read_regs(struct helene_priv *priv, +diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c +index 0c089b5986a1..4ebddc895137 100644 +--- a/drivers/media/dvb-frontends/horus3a.c ++++ b/drivers/media/dvb-frontends/horus3a.c +@@ -89,7 +89,9 @@ static int horus3a_write_regs(struct horus3a_priv *priv, + + static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val) + { +- return horus3a_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return horus3a_write_regs(priv, reg, &tmp, 1); + } + + static int horus3a_enter_power_save(struct horus3a_priv *priv) +diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c +index cadcae4cff89..ac9d2591bb6f 100644 +--- a/drivers/media/dvb-frontends/itd1000.c ++++ b/drivers/media/dvb-frontends/itd1000.c +@@ -99,8 +99,9 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg) + + static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v) + { +- int ret = itd1000_write_regs(state, r, &v, 1); +- state->shadow[r] = v; ++ u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ int ret = itd1000_write_regs(state, r, &tmp, 1); ++ state->shadow[r] = tmp; + return ret; + } + +diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c +index fc08429c99b7..7824926a3744 100644 +--- a/drivers/media/dvb-frontends/mt312.c ++++ b/drivers/media/dvb-frontends/mt312.c +@@ -142,7 +142,10 @@ static inline int mt312_readreg(struct mt312_state *state, + static inline int mt312_writereg(struct mt312_state *state, + const enum mt312_reg_addr reg, const u8 val) + { +- return mt312_write(state, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ ++ return mt312_write(state, reg, &tmp, 1); + } + + static inline u32 mt312_div(u32 a, u32 b) +diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c +index 3d171b0e00c2..3deddbcaa8b7 100644 +--- a/drivers/media/dvb-frontends/stb0899_drv.c ++++ b/drivers/media/dvb-frontends/stb0899_drv.c +@@ -552,7 +552,8 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, + + int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data) + { +- return stb0899_write_regs(state, reg, &data, 1); ++ u8 tmp = data; ++ return stb0899_write_regs(state, reg, &tmp, 1); + } + + /* +diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c +index 5add1182c3ca..4746b1e0d637 100644 +--- a/drivers/media/dvb-frontends/stb6100.c ++++ b/drivers/media/dvb-frontends/stb6100.c +@@ -226,12 +226,14 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st + + static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) + { ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ + if (unlikely(reg >= STB6100_NUMREGS)) { + dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg); + return -EREMOTEIO; + } +- data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set; +- return stb6100_write_reg_range(state, &data, reg, 1); ++ tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set; ++ return stb6100_write_reg_range(state, &tmp, reg, 1); + } + + +diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c +index abc379aea713..94cec81d0a5c 100644 +--- a/drivers/media/dvb-frontends/stv0367.c ++++ b/drivers/media/dvb-frontends/stv0367.c +@@ -804,7 +804,9 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len) + + static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data) + { +- return stv0367_writeregs(state, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv0367_writeregs(state, reg, &tmp, 1); + } + + static u8 stv0367_readreg(struct stv0367_state *state, u16 reg) +diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c +index 25bdf6e0f963..f0377e2b341b 100644 +--- a/drivers/media/dvb-frontends/stv090x.c ++++ b/drivers/media/dvb-frontends/stv090x.c +@@ -761,7 +761,9 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 + + static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) + { +- return stv090x_write_regs(state, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv090x_write_regs(state, reg, &tmp, 1); + } + + static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) +diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c +index c611ad210b5c..924f16fee1fb 100644 +--- a/drivers/media/dvb-frontends/stv6110x.c ++++ b/drivers/media/dvb-frontends/stv6110x.c +@@ -97,7 +97,9 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da + + static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) + { +- return stv6110x_write_regs(stv6110x, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv6110x_write_regs(stv6110x, reg, &tmp, 1); + } + + static int stv6110x_init(struct dvb_frontend *fe) +diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c +index a9f6bbea6df3..103b9c824f1f 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/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c +index f8c271be196c..0d2bef62ff05 100644 +--- a/drivers/media/dvb-frontends/zl10039.c ++++ b/drivers/media/dvb-frontends/zl10039.c +@@ -138,7 +138,9 @@ static inline int zl10039_writereg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, + const u8 val) + { +- return zl10039_write(state, reg, &val, 1); ++ const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return zl10039_write(state, reg, &tmp, 1); + } + + static int zl10039_init(struct dvb_frontend *fe) +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index 0e8fb89896c4..5c4aa247d650 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -504,18 +504,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; + } +@@ -1079,8 +1084,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; +@@ -1146,17 +1149,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; + } + +@@ -1200,6 +1204,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); + +@@ -1208,12 +1213,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 9fd43a37154c..b20f03d86e00 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -820,6 +820,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 caa55402052e..2868766893c8 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/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c +index a61d8fd63c12..a20b60ac66ca 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-core.c ++++ b/drivers/media/usb/hdpvr/hdpvr-core.c +@@ -295,7 +295,7 @@ static int hdpvr_probe(struct usb_interface *interface, + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + dev_err(&interface->dev, "v4l2_device_register failed\n"); +- goto error; ++ goto error_free_dev; + } + + mutex_init(&dev->io_mutex); +@@ -304,7 +304,7 @@ static int hdpvr_probe(struct usb_interface *interface, + dev->usbc_buf = kmalloc(64, GFP_KERNEL); + if (!dev->usbc_buf) { + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); +- goto error; ++ goto error_v4l2_unregister; + } + + init_waitqueue_head(&dev->wait_buffer); +@@ -342,13 +342,13 @@ static int hdpvr_probe(struct usb_interface *interface, + } + if (!dev->bulk_in_endpointAddr) { + v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); +- goto error; ++ goto error_put_usb; + } + + /* init the device */ + if (hdpvr_device_init(dev)) { + v4l2_err(&dev->v4l2_dev, "device init failed\n"); +- goto error; ++ goto error_put_usb; + } + + mutex_lock(&dev->io_mutex); +@@ -356,7 +356,7 @@ static int hdpvr_probe(struct usb_interface *interface, + mutex_unlock(&dev->io_mutex); + v4l2_err(&dev->v4l2_dev, + "allocating transfer buffers failed\n"); +- goto error; ++ goto error_put_usb; + } + mutex_unlock(&dev->io_mutex); + +@@ -364,7 +364,7 @@ static int hdpvr_probe(struct usb_interface *interface, + retval = hdpvr_register_i2c_adapter(dev); + if (retval < 0) { + v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); +- goto error; ++ goto error_free_buffers; + } + + client = hdpvr_register_ir_rx_i2c(dev); +@@ -397,13 +397,17 @@ static int hdpvr_probe(struct usb_interface *interface, + reg_fail: + #if IS_ENABLED(CONFIG_I2C) + i2c_del_adapter(&dev->i2c_adapter); ++error_free_buffers: + #endif ++ hdpvr_free_buffers(dev); ++error_put_usb: ++ usb_put_dev(dev->udev); ++ kfree(dev->usbc_buf); ++error_v4l2_unregister: ++ v4l2_device_unregister(&dev->v4l2_dev); ++error_free_dev: ++ kfree(dev); + error: +- if (dev) { +- flush_work(&dev->worker); +- /* this frees allocated memory */ +- hdpvr_delete(dev); +- } + return retval; + } + +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index dc51dd86377d..48a39222fdf9 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -18,8 +18,18 @@ + #include <linux/videodev2.h> + #include <linux/v4l2-subdev.h> + #include <media/v4l2-dev.h> ++#include <media/v4l2-fh.h> ++#include <media/v4l2-ctrls.h> + #include <media/v4l2-ioctl.h> + ++/* 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->which, &up->which) || +- 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->which, &up->which) || ++ 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->which, &up->which) || +- 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->which, &kp->which) || ++ 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 c52d94c018bb..4510e8a37244 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -2862,8 +2862,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/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c +index d9fab2222eb3..1a4a790054e4 100644 +--- a/drivers/mtd/nand/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/brcmnand/brcmnand.c +@@ -2193,16 +2193,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) + if (ctrl->nand_version >= 0x0702) + 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 a77cfd74a92e..21c03086bb7f 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2320,6 +2320,7 @@ EXPORT_SYMBOL(nand_write_oob_syndrome); + 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_to_nand(mtd); + struct mtd_ecc_stats stats; +@@ -2377,6 +2378,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; +@@ -2402,7 +2405,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 f9b2a771096b..e26c4f880df6 100644 +--- a/drivers/mtd/nand/sunxi_nand.c ++++ b/drivers/mtd/nand/sunxi_nand.c +@@ -1835,8 +1835,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 d1e6931c132f..46913ef25bc0 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; + +@@ -353,8 +355,6 @@ static struct blk_mq_ops ubiblock_mq_ops = { + .init_request = ubiblock_init_request, + }; + +-static DEFINE_IDR(ubiblock_minor_idr); +- + int ubiblock_create(struct ubi_volume_info *vi) + { + struct ubiblock *dev; +@@ -367,14 +367,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); + +@@ -439,14 +440,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: +@@ -459,6 +459,8 @@ int ubiblock_create(struct ubi_volume_info *vi) + put_disk(dev->gd); + out_free_dev: + kfree(dev); ++out_unlock: ++ mutex_unlock(&devices_mutex); + + return ret; + } +@@ -480,30 +482,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) +@@ -632,6 +640,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); +@@ -640,6 +649,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/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index b5b8cd6f481c..668b46202507 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -1528,6 +1528,46 @@ static void shutdown_work(struct ubi_device *ubi) + } + } + ++/** ++ * erase_aeb - erase a PEB given in UBI attach info PEB ++ * @ubi: UBI device description object ++ * @aeb: UBI attach info PEB ++ * @sync: If true, erase synchronously. Otherwise schedule for erasure ++ */ ++static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync) ++{ ++ struct ubi_wl_entry *e; ++ int err; ++ ++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); ++ if (!e) ++ return -ENOMEM; ++ ++ e->pnum = aeb->pnum; ++ e->ec = aeb->ec; ++ ubi->lookuptbl[e->pnum] = e; ++ ++ if (sync) { ++ err = sync_erase(ubi, e, false); ++ if (err) ++ goto out_free; ++ ++ wl_tree_add(e, &ubi->free); ++ ubi->free_count++; ++ } else { ++ err = schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false); ++ if (err) ++ goto out_free; ++ } ++ ++ return 0; ++ ++out_free: ++ wl_entry_destroy(ubi, e); ++ ++ return err; ++} ++ + /** + * ubi_wl_init - initialize the WL sub-system using attaching information. + * @ubi: UBI device description object +@@ -1566,18 +1606,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) { + cond_resched(); + +- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); +- if (!e) ++ err = erase_aeb(ubi, aeb, false); ++ if (err) + goto out_free; + +- e->pnum = aeb->pnum; +- e->ec = aeb->ec; +- ubi->lookuptbl[e->pnum] = e; +- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) { +- wl_entry_destroy(ubi, e); +- goto out_free; +- } +- + found_pebs++; + } + +@@ -1635,6 +1667,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + ubi_assert(!ubi->lookuptbl[e->pnum]); + ubi->lookuptbl[e->pnum] = e; + } else { ++ bool sync = false; ++ + /* + * Usually old Fastmap PEBs are scheduled for erasure + * and we don't have to care about them but if we face +@@ -1644,18 +1678,21 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + if (ubi->lookuptbl[aeb->pnum]) + continue; + +- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); +- if (!e) +- goto out_free; ++ /* ++ * The fastmap update code might not find a free PEB for ++ * writing the fastmap anchor to and then reuses the ++ * current fastmap anchor PEB. When this PEB gets erased ++ * and a power cut happens before it is written again we ++ * must make sure that the fastmap attach code doesn't ++ * find any outdated fastmap anchors, hence we erase the ++ * outdated fastmap anchor PEBs synchronously here. ++ */ ++ if (aeb->vol_id == UBI_FM_SB_VOLUME_ID) ++ sync = true; + +- e->pnum = aeb->pnum; +- e->ec = aeb->ec; +- ubi_assert(!ubi->lookuptbl[e->pnum]); +- ubi->lookuptbl[e->pnum] = e; +- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) { +- wl_entry_destroy(ubi, e); ++ err = erase_aeb(ubi, aeb, sync); ++ if (err) + goto out_free; +- } + } + + found_pebs++; +diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c +index b40a074822cf..df63b7d997e8 100644 +--- a/drivers/pinctrl/intel/pinctrl-intel.c ++++ b/drivers/pinctrl/intel/pinctrl-intel.c +@@ -368,6 +368,18 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input) + writel(value, padcfg0); + } + ++static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) ++{ ++ u32 value; ++ ++ /* Put the pad into GPIO mode */ ++ value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; ++ /* Disable SCI/SMI/NMI generation */ ++ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); ++ value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); ++ writel(value, padcfg0); ++} ++ + static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned pin) +@@ -375,7 +387,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + void __iomem *padcfg0; + unsigned long flags; +- u32 value; + + raw_spin_lock_irqsave(&pctrl->lock, flags); + +@@ -385,13 +396,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + } + + padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); +- /* Put the pad into GPIO mode */ +- value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; +- /* Disable SCI/SMI/NMI generation */ +- value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); +- value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); +- writel(value, padcfg0); +- ++ intel_gpio_set_gpio_mode(padcfg0); + /* Disable TX buffer and enable RX (this will be input) */ + __intel_gpio_set_direction(padcfg0, true); + +@@ -770,6 +775,8 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type) + + raw_spin_lock_irqsave(&pctrl->lock, flags); + ++ intel_gpio_set_gpio_mode(reg); ++ + value = readl(reg); + + value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); +diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c +index 31125a4a2658..d7dcd39fe12c 100644 +--- a/drivers/usb/gadget/function/uvc_configfs.c ++++ b/drivers/usb/gadget/function/uvc_configfs.c +@@ -2140,7 +2140,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) \ + { \ +@@ -2183,16 +2183,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/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c +index 4874b0f18650..518dfa1047cb 100644 +--- a/drivers/watchdog/imx2_wdt.c ++++ b/drivers/watchdog/imx2_wdt.c +@@ -169,15 +169,21 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) + return 0; + } + +-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; + } + +@@ -371,7 +377,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); + } + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 894d56361ea9..a8a1fb40e258 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -2063,8 +2063,15 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) + goto out; + } + +- btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state, +- 0); ++ ret = btrfs_set_extent_delalloc(inode, page_start, page_end, ++ &cached_state, 0); ++ 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 5eb04129f938..73360df52ce9 100644 +--- a/fs/cifs/cifsencrypt.c ++++ b/fs/cifs/cifsencrypt.c +@@ -318,9 +318,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 580b3a4ca53a..441d434a48c1 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1667,7 +1667,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; + } +@@ -1705,7 +1705,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); +@@ -4159,7 +4159,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 cf192f9ce254..02e403af9518 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -3285,20 +3285,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; + } +@@ -3308,16 +3306,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 5419afea0a36..323d8e34abde 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 69b610ad3fdc..94c4c1901222 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -585,8 +585,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/kernfs/file.c b/fs/kernfs/file.c +index 78219d5644e9..d6512cd9ba02 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -275,7 +275,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 bd81bcf3ffcf..1ac1593aded3 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/io.c b/fs/nfs/io.c +index 1fc5d1ce327e..d18ccc1ce0b5 100644 +--- a/fs/nfs/io.c ++++ b/fs/nfs/io.c +@@ -98,7 +98,7 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode) + { + if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) { + set_bit(NFS_INO_ODIRECT, &nfsi->flags); +- nfs_wb_all(inode); ++ nfs_sync_mapping(inode->i_mapping); + } + } + +diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c +index c444285bb1b1..f1160cdd4682 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 b7a07ba8783a..b8e44746f761 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -2145,7 +2145,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 +@@ -2256,7 +2256,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 9905735463a4..9a3b3820306d 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -1806,6 +1806,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 8718af895eab..80fdfad7c215 100644 +--- a/fs/nsfs.c ++++ b/fs/nsfs.c +@@ -90,6 +90,7 @@ static void *__ns_get_path(struct path *path, struct ns_common *ns) + 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 f241b4ee3d8a..a1be6baabca3 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -434,10 +434,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/fs/pipe.c b/fs/pipe.c +index 9faecf1b4a27..34345535f63d 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -609,12 +609,17 @@ static unsigned long account_pipe_buffers(struct user_struct *user, + + static bool too_many_pipe_buffers_soft(unsigned long user_bufs) + { +- return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft; ++ return pipe_user_pages_soft && user_bufs > pipe_user_pages_soft; + } + + static bool too_many_pipe_buffers_hard(unsigned long user_bufs) + { +- return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard; ++ return pipe_user_pages_hard && user_bufs > pipe_user_pages_hard; ++} ++ ++static bool is_unprivileged_user(void) ++{ ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); + } + + struct pipe_inode_info *alloc_pipe_info(void) +@@ -633,12 +638,12 @@ struct pipe_inode_info *alloc_pipe_info(void) + + user_bufs = account_pipe_buffers(user, 0, pipe_bufs); + +- if (too_many_pipe_buffers_soft(user_bufs)) { ++ if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) { + user_bufs = account_pipe_buffers(user, pipe_bufs, 1); + pipe_bufs = 1; + } + +- if (too_many_pipe_buffers_hard(user_bufs)) ++ if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user()) + goto out_revert_acct; + + pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), +@@ -1069,7 +1074,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) + if (nr_pages > pipe->buffers && + (too_many_pipe_buffers_hard(user_bufs) || + too_many_pipe_buffers_soft(user_bufs)) && +- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { ++ is_unprivileged_user()) { + ret = -EPERM; + goto out_revert_acct; + } +diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c +index 5c89a07e3d7f..df7e07986ead 100644 +--- a/fs/proc/kcore.c ++++ b/fs/proc/kcore.c +@@ -507,23 +507,15 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) + return -EFAULT; + } else { + if (kern_addr_valid(start)) { +- unsigned long n; +- + /* + * Using bounce buffer to bypass the + * hardened user copy kernel text checks. + */ +- memcpy(buf, (char *) start, tsz); +- n = copy_to_user(buffer, buf, tsz); +- /* +- * We cannot distinguish between fault on source +- * and fault on destination. When this happens +- * we clear too and hope it will trigger the +- * EFAULT again. +- */ +- if (n) { +- if (clear_user(buffer + tsz - n, +- n)) ++ if (probe_kernel_read(buf, (void *) start, tsz)) { ++ if (clear_user(buffer, tsz)) ++ return -EFAULT; ++ } else { ++ if (copy_to_user(buffer, buf, tsz)) + return -EFAULT; + } + } else { +diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c +index d9f9615bfd71..3979d767a0cb 100644 +--- a/fs/ubifs/xattr.c ++++ b/fs/ubifs/xattr.c +@@ -270,7 +270,8 @@ static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) + } + + static int __ubifs_setxattr(struct inode *host, const char *name, +- const void *value, size_t size, int flags) ++ const void *value, size_t size, int flags, ++ bool check_lock) + { + struct inode *inode; + struct ubifs_info *c = host->i_sb->s_fs_info; +@@ -279,7 +280,8 @@ static int __ubifs_setxattr(struct inode *host, const char *name, + union ubifs_key key; + int err; + +- ubifs_assert(inode_is_locked(host)); ++ if (check_lock) ++ ubifs_assert(inode_is_locked(host)); + + if (size > UBIFS_MAX_INO_DATA) + return -ERANGE; +@@ -548,7 +550,8 @@ static int init_xattrs(struct inode *inode, const struct xattr *xattr_array, + } + strcpy(name, XATTR_SECURITY_PREFIX); + strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); +- err = __ubifs_setxattr(inode, name, xattr->value, xattr->value_len, 0); ++ err = __ubifs_setxattr(inode, name, xattr->value, ++ xattr->value_len, 0, false); + kfree(name); + if (err < 0) + break; +@@ -594,7 +597,8 @@ static int ubifs_xattr_set(const struct xattr_handler *handler, + name = xattr_full_name(handler, name); + + if (value) +- return __ubifs_setxattr(inode, name, value, size, flags); ++ return __ubifs_setxattr(inode, name, value, size, flags, ++ true); + else + return __ubifs_removexattr(inode, name); + } +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index cac57358f7af..5203560f992e 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -88,6 +88,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/mtd/map.h b/include/linux/mtd/map.h +index 3aa56e3104bb..b5b43f94f311 100644 +--- a/include/linux/mtd/map.h ++++ b/include/linux/mtd/map.h +@@ -270,75 +270,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/kernel/async.c b/kernel/async.c +index d2edd6efec56..d84d4860992e 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/relay.c b/kernel/relay.c +index 8f18d314a96a..2603e04f55f9 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -611,7 +611,6 @@ struct rchan *relay_open(const char *base_filename, + + kref_put(&chan->kref, relay_destroy_channel); + mutex_unlock(&relay_channels_mutex); +- kfree(chan); + return NULL; + } + EXPORT_SYMBOL_GPL(relay_open); +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index e5066955cc3a..bce3a7ad4253 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -5864,6 +5864,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 7a360d6f6798..f6d68ddfa2f3 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1895,9 +1895,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; + +@@ -1973,19 +1972,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; + +@@ -2001,18 +2005,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 cff985feb6e7..f564a1d2c9d5 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -590,6 +590,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 5b8d7189e147..2884fe01cb54 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -3911,7 +3911,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/lib/ubsan.c b/lib/ubsan.c +index fb0409df1bcf..50d1d5c25deb 100644 +--- a/lib/ubsan.c ++++ b/lib/ubsan.c +@@ -265,14 +265,14 @@ void __ubsan_handle_divrem_overflow(struct overflow_data *data, + } + EXPORT_SYMBOL(__ubsan_handle_divrem_overflow); + +-static void handle_null_ptr_deref(struct type_mismatch_data *data) ++static void handle_null_ptr_deref(struct type_mismatch_data_common *data) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + + pr_err("%s null pointer of type %s\n", + type_check_kinds[data->type_check_kind], +@@ -281,15 +281,15 @@ static void handle_null_ptr_deref(struct type_mismatch_data *data) + ubsan_epilogue(&flags); + } + +-static void handle_missaligned_access(struct type_mismatch_data *data, ++static void handle_misaligned_access(struct type_mismatch_data_common *data, + unsigned long ptr) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + + pr_err("%s misaligned address %p for type %s\n", + type_check_kinds[data->type_check_kind], +@@ -299,15 +299,15 @@ static void handle_missaligned_access(struct type_mismatch_data *data, + ubsan_epilogue(&flags); + } + +-static void handle_object_size_mismatch(struct type_mismatch_data *data, ++static void handle_object_size_mismatch(struct type_mismatch_data_common *data, + unsigned long ptr) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + pr_err("%s address %p with insufficient space\n", + type_check_kinds[data->type_check_kind], + (void *) ptr); +@@ -315,19 +315,47 @@ static void handle_object_size_mismatch(struct type_mismatch_data *data, + ubsan_epilogue(&flags); + } + +-void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, ++static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data, + unsigned long ptr) + { + + if (!ptr) + handle_null_ptr_deref(data); + else if (data->alignment && !IS_ALIGNED(ptr, data->alignment)) +- handle_missaligned_access(data, ptr); ++ handle_misaligned_access(data, ptr); + else + handle_object_size_mismatch(data, ptr); + } ++ ++void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, ++ unsigned long ptr) ++{ ++ struct type_mismatch_data_common common_data = { ++ .location = &data->location, ++ .type = data->type, ++ .alignment = data->alignment, ++ .type_check_kind = data->type_check_kind ++ }; ++ ++ ubsan_type_mismatch_common(&common_data, ptr); ++} + EXPORT_SYMBOL(__ubsan_handle_type_mismatch); + ++void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, ++ unsigned long ptr) ++{ ++ ++ struct type_mismatch_data_common common_data = { ++ .location = &data->location, ++ .type = data->type, ++ .alignment = 1UL << data->log_alignment, ++ .type_check_kind = data->type_check_kind ++ }; ++ ++ ubsan_type_mismatch_common(&common_data, ptr); ++} ++EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1); ++ + void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) + { + unsigned long flags; +diff --git a/lib/ubsan.h b/lib/ubsan.h +index b2d18d4a53f5..d8b8085e5dac 100644 +--- a/lib/ubsan.h ++++ b/lib/ubsan.h +@@ -36,6 +36,20 @@ struct type_mismatch_data { + unsigned char type_check_kind; + }; + ++struct type_mismatch_data_v1 { ++ struct source_location location; ++ struct type_descriptor *type; ++ unsigned char log_alignment; ++ unsigned char type_check_kind; ++}; ++ ++struct type_mismatch_data_common { ++ struct source_location *location; ++ struct type_descriptor *type; ++ unsigned long alignment; ++ unsigned char type_check_kind; ++}; ++ + struct nonnull_arg_data { + struct source_location location; + struct source_location attr_location; +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/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c +index 3f8e6f0b7eb5..dcf03691ebc8 100644 +--- a/sound/soc/intel/skylake/skl-nhlt.c ++++ b/sound/soc/intel/skylake/skl-nhlt.c +@@ -41,7 +41,8 @@ struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) + obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL); + if (obj && obj->type == ACPI_TYPE_BUFFER) { + nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; +- nhlt_table = (struct nhlt_acpi_table *) ++ if (nhlt_ptr->length) ++ nhlt_table = (struct nhlt_acpi_table *) + memremap(nhlt_ptr->min_addr, nhlt_ptr->length, + MEMREMAP_WB); + ACPI_FREE(obj); +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 974915cb4c4f..08bfee447a36 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -476,6 +476,7 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) + case I2S_INTCR: + case I2S_XFER: + case I2S_CLR: ++ case I2S_TXDR: + case I2S_RXDR: + case I2S_FIFOLR: + case I2S_INTSR: +@@ -490,6 +491,9 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + switch (reg) { + case I2S_INTSR: + case I2S_CLR: ++ case I2S_FIFOLR: ++ case I2S_TXDR: ++ case I2S_RXDR: + return true; + default: + return false; +@@ -499,6 +503,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case I2S_RXDR: ++ return true; + default: + return false; + } |