summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--0000_README4
-rw-r--r--1081_linux-4.9.82.patch4130
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, &not);
+ 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;
+ }