From a6383ddcf48aac166b64e6008cbceb4476975279 Mon Sep 17 00:00:00 2001 From: "Anthony G. Basile" Date: Sat, 22 Apr 2017 12:08:04 -0400 Subject: grsecurity-3.1-4.9.24-201704220732 --- 4.9.24/0000_README | 56 + 4.9.24/1023_linux-4.9.24.patch | 3261 + .../4420_grsecurity-3.1-4.9.24-201704220732.patch | 225996 ++++++++++++++++++ 4.9.24/4425_grsec_remove_EI_PAX.patch | 19 + 4.9.24/4426_default_XATTR_PAX_FLAGS.patch | 36 + 4.9.24/4427_force_XATTR_PAX_tmpfs.patch | 48 + 4.9.24/4430_grsec-remove-localversion-grsec.patch | 9 + 4.9.24/4435_grsec-mute-warnings.patch | 43 + 4.9.24/4440_grsec-remove-protected-paths.patch | 20 + 4.9.24/4450_grsec-kconfig-default-gids.patch | 111 + 4.9.24/4465_selinux-avc_audit-log-curr_ip.patch | 73 + 4.9.24/4470_disable-compat_vdso.patch | 58 + 4.9.24/4475_emutramp_default_on.patch | 34 + 13 files changed, 229764 insertions(+) create mode 100644 4.9.24/0000_README create mode 100644 4.9.24/1023_linux-4.9.24.patch create mode 100644 4.9.24/4420_grsecurity-3.1-4.9.24-201704220732.patch create mode 100644 4.9.24/4425_grsec_remove_EI_PAX.patch create mode 100644 4.9.24/4426_default_XATTR_PAX_FLAGS.patch create mode 100644 4.9.24/4427_force_XATTR_PAX_tmpfs.patch create mode 100644 4.9.24/4430_grsec-remove-localversion-grsec.patch create mode 100644 4.9.24/4435_grsec-mute-warnings.patch create mode 100644 4.9.24/4440_grsec-remove-protected-paths.patch create mode 100644 4.9.24/4450_grsec-kconfig-default-gids.patch create mode 100644 4.9.24/4465_selinux-avc_audit-log-curr_ip.patch create mode 100644 4.9.24/4470_disable-compat_vdso.patch create mode 100644 4.9.24/4475_emutramp_default_on.patch (limited to '4.9.24') diff --git a/4.9.24/0000_README b/4.9.24/0000_README new file mode 100644 index 0000000..89862a9 --- /dev/null +++ b/4.9.24/0000_README @@ -0,0 +1,56 @@ +README +----------------------------------------------------------------------------- +Individual Patch Descriptions: +----------------------------------------------------------------------------- +Patch: 1023_linux-4.9.24.patch +From: http://www.kernel.org +Desc: Linux 4.9.24 + +Patch: 4420_grsecurity-3.1-4.9.24-201704220732.patch +From: http://www.grsecurity.net +Desc: hardened-sources base patch from upstream grsecurity + +Patch: 4425_grsec_remove_EI_PAX.patch +From: Anthony G. Basile +Desc: Remove EI_PAX option and force off + +Patch: 4426_default_XATTR_PAX_FLAGS.patch +From: Anthony G. Basile +Desc: Defalut PT_PAX_FLAGS off and XATTR_PAX_FLAGS on + +Patch: 4427_force_XATTR_PAX_tmpfs.patch +From: Anthony G. Basile +Desc: Force XATTR_PAX on tmpfs + +Patch: 4430_grsec-remove-localversion-grsec.patch +From: Kerin Millar +Desc: Removes grsecurity's localversion-grsec file + +Patch: 4435_grsec-mute-warnings.patch +From: Alexander Gabert + Gordon Malm +Desc: Removes verbose compile warning settings from grsecurity, restores + mainline Linux kernel behavior + +Patch: 4440_grsec-remove-protected-paths.patch +From: Anthony G. Basile +Desc: Removes chmod statements from grsecurity/Makefile + +Patch: 4450_grsec-kconfig-default-gids.patch +From: Kerin Millar +Desc: Sets sane(r) default GIDs on various grsecurity group-dependent + features + +Patch: 4465_selinux-avc_audit-log-curr_ip.patch +From: Gordon Malm + Anthony G. Basile +Desc: Configurable option to add src IP address to SELinux log messages + +Patch: 4470_disable-compat_vdso.patch +From: Gordon Malm + Kerin Millar +Desc: Disables VDSO_COMPAT operation completely + +Patch: 4475_emutramp_default_on.patch +From: Anthony G. Basile +Desc: Set PAX_EMUTRAMP default on for libffi, bugs #329499 and #457194 diff --git a/4.9.24/1023_linux-4.9.24.patch b/4.9.24/1023_linux-4.9.24.patch new file mode 100644 index 0000000..0ffd31b --- /dev/null +++ b/4.9.24/1023_linux-4.9.24.patch @@ -0,0 +1,3261 @@ +diff --git a/Makefile b/Makefile +index 0de7597..50436f5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 23 ++SUBLEVEL = 24 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c +index 0ddf369..8ac0e59 100644 +--- a/arch/mips/lantiq/irq.c ++++ b/arch/mips/lantiq/irq.c +@@ -269,11 +269,6 @@ static void ltq_hw5_irqdispatch(void) + DEFINE_HWx_IRQDISPATCH(5) + #endif + +-static void ltq_hw_irq_handler(struct irq_desc *desc) +-{ +- ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2); +-} +- + #ifdef CONFIG_MIPS_MT_SMP + void __init arch_init_ipiirq(int irq, struct irqaction *action) + { +@@ -318,19 +313,23 @@ static struct irqaction irq_call = { + asmlinkage void plat_irq_dispatch(void) + { + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; +- int irq; +- +- if (!pending) { +- spurious_interrupt(); +- return; ++ unsigned int i; ++ ++ if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) { ++ do_IRQ(MIPS_CPU_TIMER_IRQ); ++ goto out; ++ } else { ++ for (i = 0; i < MAX_IM; i++) { ++ if (pending & (CAUSEF_IP2 << i)) { ++ ltq_hw_irqdispatch(i); ++ goto out; ++ } ++ } + } ++ pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status()); + +- pending >>= CAUSEB_IP; +- while (pending) { +- irq = fls(pending) - 1; +- do_IRQ(MIPS_CPU_IRQ_BASE + irq); +- pending &= ~BIT(irq); +- } ++out: ++ return; + } + + static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +@@ -355,6 +354,11 @@ static const struct irq_domain_ops irq_domain_ops = { + .map = icu_map, + }; + ++static struct irqaction cascade = { ++ .handler = no_action, ++ .name = "cascade", ++}; ++ + int __init icu_of_init(struct device_node *node, struct device_node *parent) + { + struct device_node *eiu_node; +@@ -386,7 +390,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) + mips_cpu_irq_init(); + + for (i = 0; i < MAX_IM; i++) +- irq_set_chained_handler(i + 2, ltq_hw_irq_handler); ++ setup_irq(i + 2, &cascade); + + if (cpu_has_vint) { + pr_info("Setting up vectored interrupts\n"); +diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h +index 7fcf512..0497cec 100644 +--- a/arch/parisc/include/asm/uaccess.h ++++ b/arch/parisc/include/asm/uaccess.h +@@ -42,10 +42,10 @@ static inline long access_ok(int type, const void __user * addr, + #define get_user __get_user + + #if !defined(CONFIG_64BIT) +-#define LDD_USER(ptr) __get_user_asm64(ptr) ++#define LDD_USER(val, ptr) __get_user_asm64(val, ptr) + #define STD_USER(x, ptr) __put_user_asm64(x, ptr) + #else +-#define LDD_USER(ptr) __get_user_asm("ldd", ptr) ++#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr) + #define STD_USER(x, ptr) __put_user_asm("std", x, ptr) + #endif + +@@ -100,63 +100,87 @@ struct exception_data { + " mtsp %0,%%sr2\n\t" \ + : : "r"(get_fs()) : ) + +-#define __get_user(x, ptr) \ +-({ \ +- register long __gu_err __asm__ ("r8") = 0; \ +- register long __gu_val; \ +- \ +- load_sr2(); \ +- switch (sizeof(*(ptr))) { \ +- case 1: __get_user_asm("ldb", ptr); break; \ +- case 2: __get_user_asm("ldh", ptr); break; \ +- case 4: __get_user_asm("ldw", ptr); break; \ +- case 8: LDD_USER(ptr); break; \ +- default: BUILD_BUG(); break; \ +- } \ +- \ +- (x) = (__force __typeof__(*(ptr))) __gu_val; \ +- __gu_err; \ ++#define __get_user_internal(val, ptr) \ ++({ \ ++ register long __gu_err __asm__ ("r8") = 0; \ ++ \ ++ switch (sizeof(*(ptr))) { \ ++ case 1: __get_user_asm(val, "ldb", ptr); break; \ ++ case 2: __get_user_asm(val, "ldh", ptr); break; \ ++ case 4: __get_user_asm(val, "ldw", ptr); break; \ ++ case 8: LDD_USER(val, ptr); break; \ ++ default: BUILD_BUG(); \ ++ } \ ++ \ ++ __gu_err; \ + }) + +-#define __get_user_asm(ldx, ptr) \ ++#define __get_user(val, ptr) \ ++({ \ ++ load_sr2(); \ ++ __get_user_internal(val, ptr); \ ++}) ++ ++#define __get_user_asm(val, ldx, ptr) \ ++{ \ ++ register long __gu_val; \ ++ \ + __asm__("1: " ldx " 0(%%sr2,%2),%0\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ + : "=r"(__gu_val), "=r"(__gu_err) \ +- : "r"(ptr), "1"(__gu_err)); ++ : "r"(ptr), "1"(__gu_err)); \ ++ \ ++ (val) = (__force __typeof__(*(ptr))) __gu_val; \ ++} + + #if !defined(CONFIG_64BIT) + +-#define __get_user_asm64(ptr) \ ++#define __get_user_asm64(val, ptr) \ ++{ \ ++ union { \ ++ unsigned long long l; \ ++ __typeof__(*(ptr)) t; \ ++ } __gu_tmp; \ ++ \ + __asm__(" copy %%r0,%R0\n" \ + "1: ldw 0(%%sr2,%2),%0\n" \ + "2: ldw 4(%%sr2,%2),%R0\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \ +- : "=r"(__gu_val), "=r"(__gu_err) \ +- : "r"(ptr), "1"(__gu_err)); ++ : "=&r"(__gu_tmp.l), "=r"(__gu_err) \ ++ : "r"(ptr), "1"(__gu_err)); \ ++ \ ++ (val) = __gu_tmp.t; \ ++} + + #endif /* !defined(CONFIG_64BIT) */ + + +-#define __put_user(x, ptr) \ ++#define __put_user_internal(x, ptr) \ + ({ \ + register long __pu_err __asm__ ("r8") = 0; \ + __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ + \ +- load_sr2(); \ + switch (sizeof(*(ptr))) { \ +- case 1: __put_user_asm("stb", __x, ptr); break; \ +- case 2: __put_user_asm("sth", __x, ptr); break; \ +- case 4: __put_user_asm("stw", __x, ptr); break; \ +- case 8: STD_USER(__x, ptr); break; \ +- default: BUILD_BUG(); break; \ +- } \ ++ case 1: __put_user_asm("stb", __x, ptr); break; \ ++ case 2: __put_user_asm("sth", __x, ptr); break; \ ++ case 4: __put_user_asm("stw", __x, ptr); break; \ ++ case 8: STD_USER(__x, ptr); break; \ ++ default: BUILD_BUG(); \ ++ } \ + \ + __pu_err; \ + }) + ++#define __put_user(x, ptr) \ ++({ \ ++ load_sr2(); \ ++ __put_user_internal(x, ptr); \ ++}) ++ ++ + /* + * The "__put_user/kernel_asm()" macros tell gcc they read from memory + * instead of writing. This is because they do not write to any memory +diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S +index f01188c..85c28bb 100644 +--- a/arch/parisc/lib/lusercopy.S ++++ b/arch/parisc/lib/lusercopy.S +@@ -201,7 +201,7 @@ ENTRY_CFI(pa_memcpy) + add dst,len,end + + /* short copy with less than 16 bytes? */ +- cmpib,>>=,n 15,len,.Lbyte_loop ++ cmpib,COND(>>=),n 15,len,.Lbyte_loop + + /* same alignment? */ + xor src,dst,t0 +@@ -216,7 +216,7 @@ ENTRY_CFI(pa_memcpy) + /* loop until we are 64-bit aligned */ + .Lalign_loop64: + extru dst,31,3,t1 +- cmpib,=,n 0,t1,.Lcopy_loop_16 ++ cmpib,=,n 0,t1,.Lcopy_loop_16_start + 20: ldb,ma 1(srcspc,src),t1 + 21: stb,ma t1,1(dstspc,dst) + b .Lalign_loop64 +@@ -225,6 +225,7 @@ ENTRY_CFI(pa_memcpy) + ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + ++.Lcopy_loop_16_start: + ldi 31,t0 + .Lcopy_loop_16: + cmpb,COND(>>=),n t0,len,.Lword_loop +@@ -267,7 +268,7 @@ ENTRY_CFI(pa_memcpy) + /* loop until we are 32-bit aligned */ + .Lalign_loop32: + extru dst,31,2,t1 +- cmpib,=,n 0,t1,.Lcopy_loop_4 ++ cmpib,=,n 0,t1,.Lcopy_loop_8 + 20: ldb,ma 1(srcspc,src),t1 + 21: stb,ma t1,1(dstspc,dst) + b .Lalign_loop32 +@@ -277,7 +278,7 @@ ENTRY_CFI(pa_memcpy) + ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done) + + +-.Lcopy_loop_4: ++.Lcopy_loop_8: + cmpib,COND(>>=),n 15,len,.Lbyte_loop + + 10: ldw 0(srcspc,src),t1 +@@ -299,7 +300,7 @@ ENTRY_CFI(pa_memcpy) + ASM_EXCEPTIONTABLE_ENTRY(16b,.Lcopy_done) + ASM_EXCEPTIONTABLE_ENTRY(17b,.Lcopy_done) + +- b .Lcopy_loop_4 ++ b .Lcopy_loop_8 + ldo -16(len),len + + .Lbyte_loop: +@@ -324,7 +325,7 @@ ENTRY_CFI(pa_memcpy) + .Lunaligned_copy: + /* align until dst is 32bit-word-aligned */ + extru dst,31,2,t1 +- cmpib,COND(=),n 0,t1,.Lcopy_dstaligned ++ cmpib,=,n 0,t1,.Lcopy_dstaligned + 20: ldb 0(srcspc,src),t1 + ldo 1(src),src + 21: stb,ma t1,1(dstspc,dst) +@@ -362,7 +363,7 @@ ENTRY_CFI(pa_memcpy) + cmpiclr,<> 1,t0,%r0 + b,n .Lcase1 + .Lcase0: +- cmpb,= %r0,len,.Lcda_finish ++ cmpb,COND(=) %r0,len,.Lcda_finish + nop + + 1: ldw,ma 4(srcspc,src), a3 +@@ -376,7 +377,7 @@ ENTRY_CFI(pa_memcpy) + 1: ldw,ma 4(srcspc,src), a3 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) + ldo -1(len),len +- cmpb,=,n %r0,len,.Ldo0 ++ cmpb,COND(=),n %r0,len,.Ldo0 + .Ldo4: + 1: ldw,ma 4(srcspc,src), a0 + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault) +@@ -402,7 +403,7 @@ ENTRY_CFI(pa_memcpy) + 1: stw,ma t0, 4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done) + ldo -4(len),len +- cmpb,<> %r0,len,.Ldo4 ++ cmpb,COND(<>) %r0,len,.Ldo4 + nop + .Ldo0: + shrpw a2, a3, %sar, t0 +@@ -436,14 +437,14 @@ ENTRY_CFI(pa_memcpy) + /* fault exception fixup handlers: */ + #ifdef CONFIG_64BIT + .Lcopy16_fault: +-10: b .Lcopy_done +- std,ma t1,8(dstspc,dst) ++ b .Lcopy_done ++10: std,ma t1,8(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) + #endif + + .Lcopy8_fault: +-10: b .Lcopy_done +- stw,ma t1,4(dstspc,dst) ++ b .Lcopy_done ++10: stw,ma t1,4(dstspc,dst) + ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done) + + .exit +diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c +index 7853b53..3f9d1a8 100644 +--- a/arch/x86/entry/vdso/vdso32-setup.c ++++ b/arch/x86/entry/vdso/vdso32-setup.c +@@ -30,8 +30,10 @@ static int __init vdso32_setup(char *s) + { + vdso32_enabled = simple_strtoul(s, NULL, 0); + +- if (vdso32_enabled > 1) ++ if (vdso32_enabled > 1) { + pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n"); ++ vdso32_enabled = 0; ++ } + + return 1; + } +@@ -62,13 +64,18 @@ subsys_initcall(sysenter_setup); + /* Register vsyscall32 into the ABI table */ + #include + ++static const int zero; ++static const int one = 1; ++ + static struct ctl_table abi_table2[] = { + { + .procname = "vsyscall32", + .data = &vdso32_enabled, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = (int *)&zero, ++ .extra2 = (int *)&one, + }, + {} + }; +diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c +index 81b321a..f924629 100644 +--- a/arch/x86/events/intel/lbr.c ++++ b/arch/x86/events/intel/lbr.c +@@ -507,6 +507,9 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) + cpuc->lbr_entries[i].to = msr_lastbranch.to; + cpuc->lbr_entries[i].mispred = 0; + cpuc->lbr_entries[i].predicted = 0; ++ cpuc->lbr_entries[i].in_tx = 0; ++ cpuc->lbr_entries[i].abort = 0; ++ cpuc->lbr_entries[i].cycles = 0; + cpuc->lbr_entries[i].reserved = 0; + } + cpuc->lbr_stack.nr = i; +diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h +index e7f155c..94aad63 100644 +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -278,7 +278,7 @@ struct task_struct; + + #define ARCH_DLINFO_IA32 \ + do { \ +- if (vdso32_enabled) { \ ++ if (VDSO_CURRENT_BASE) { \ + NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \ + } \ +diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h +index 2c1ebeb..529bb4a 100644 +--- a/arch/x86/include/asm/pmem.h ++++ b/arch/x86/include/asm/pmem.h +@@ -55,7 +55,8 @@ static inline int arch_memcpy_from_pmem(void *dst, const void *src, size_t n) + * @size: number of bytes to write back + * + * Write back a cache range using the CLWB (cache line write back) +- * instruction. ++ * instruction. Note that @size is internally rounded up to be cache ++ * line size aligned. + */ + static inline void arch_wb_cache_pmem(void *addr, size_t size) + { +@@ -69,15 +70,6 @@ static inline void arch_wb_cache_pmem(void *addr, size_t size) + clwb(p); + } + +-/* +- * copy_from_iter_nocache() on x86 only uses non-temporal stores for iovec +- * iterators, so for other types (bvec & kvec) we must do a cache write-back. +- */ +-static inline bool __iter_needs_pmem_wb(struct iov_iter *i) +-{ +- return iter_is_iovec(i) == false; +-} +- + /** + * arch_copy_from_iter_pmem - copy data from an iterator to PMEM + * @addr: PMEM destination address +@@ -94,7 +86,35 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes, + /* TODO: skip the write-back by always using non-temporal stores */ + len = copy_from_iter_nocache(addr, bytes, i); + +- if (__iter_needs_pmem_wb(i)) ++ /* ++ * In the iovec case on x86_64 copy_from_iter_nocache() uses ++ * non-temporal stores for the bulk of the transfer, but we need ++ * to manually flush if the transfer is unaligned. A cached ++ * memory copy is used when destination or size is not naturally ++ * aligned. That is: ++ * - Require 8-byte alignment when size is 8 bytes or larger. ++ * - Require 4-byte alignment when size is 4 bytes. ++ * ++ * In the non-iovec case the entire destination needs to be ++ * flushed. ++ */ ++ if (iter_is_iovec(i)) { ++ unsigned long flushed, dest = (unsigned long) addr; ++ ++ if (bytes < 8) { ++ if (!IS_ALIGNED(dest, 4) || (bytes != 4)) ++ arch_wb_cache_pmem(addr, 1); ++ } else { ++ if (!IS_ALIGNED(dest, 8)) { ++ dest = ALIGN(dest, boot_cpu_data.x86_clflush_size); ++ arch_wb_cache_pmem(addr, 1); ++ } ++ ++ flushed = dest - (unsigned long) addr; ++ if (bytes > flushed && !IS_ALIGNED(bytes - flushed, 8)) ++ arch_wb_cache_pmem(addr + bytes - 1, 1); ++ } ++ } else + arch_wb_cache_pmem(addr, bytes); + + return len; +diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c +index ec1f756..71beb28 100644 +--- a/arch/x86/kernel/signal_compat.c ++++ b/arch/x86/kernel/signal_compat.c +@@ -151,8 +151,8 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, + + if (from->si_signo == SIGSEGV) { + if (from->si_code == SEGV_BNDERR) { +- compat_uptr_t lower = (unsigned long)&to->si_lower; +- compat_uptr_t upper = (unsigned long)&to->si_upper; ++ compat_uptr_t lower = (unsigned long)from->si_lower; ++ compat_uptr_t upper = (unsigned long)from->si_upper; + put_user_ex(lower, &to->si_lower); + put_user_ex(upper, &to->si_upper); + } +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 69b8f8a..43b55ef 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -6925,14 +6925,20 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason, + } + + page = nested_get_page(vcpu, vmptr); +- if (page == NULL || +- *(u32 *)kmap(page) != VMCS12_REVISION) { ++ if (page == NULL) { + nested_vmx_failInvalid(vcpu); ++ skip_emulated_instruction(vcpu); ++ return 1; ++ } ++ if (*(u32 *)kmap(page) != VMCS12_REVISION) { + kunmap(page); ++ nested_release_page_clean(page); ++ nested_vmx_failInvalid(vcpu); + skip_emulated_instruction(vcpu); + return 1; + } + kunmap(page); ++ nested_release_page_clean(page); + vmx->nested.vmxon_ptr = vmptr; + break; + case EXIT_REASON_VMCLEAR: +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index 22af912..889e761 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -643,21 +643,40 @@ void __init init_mem_mapping(void) + * devmem_is_allowed() checks to see if /dev/mem access to a certain address + * is valid. The argument is a physical page number. + * +- * +- * On x86, access has to be given to the first megabyte of ram because that area +- * contains BIOS code and data regions used by X and dosemu and similar apps. +- * Access has to be given to non-kernel-ram areas as well, these contain the PCI +- * mmio resources as well as potential bios/acpi data regions. ++ * On x86, access has to be given to the first megabyte of RAM because that ++ * area traditionally contains BIOS code and data regions used by X, dosemu, ++ * and similar apps. Since they map the entire memory range, the whole range ++ * must be allowed (for mapping), but any areas that would otherwise be ++ * disallowed are flagged as being "zero filled" instead of rejected. ++ * Access has to be given to non-kernel-ram areas as well, these contain the ++ * PCI mmio resources as well as potential bios/acpi data regions. + */ + int devmem_is_allowed(unsigned long pagenr) + { +- if (pagenr < 256) +- return 1; +- if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) ++ if (page_is_ram(pagenr)) { ++ /* ++ * For disallowed memory regions in the low 1MB range, ++ * request that the page be shown as all zeros. ++ */ ++ if (pagenr < 256) ++ return 2; ++ ++ return 0; ++ } ++ ++ /* ++ * This must follow RAM test, since System RAM is considered a ++ * restricted resource under CONFIG_STRICT_IOMEM. ++ */ ++ if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) { ++ /* Low 1MB bypasses iomem restrictions. */ ++ if (pagenr < 256) ++ return 1; ++ + return 0; +- if (!page_is_ram(pagenr)) +- return 1; +- return 0; ++ } ++ ++ return 1; + } + + void free_init_pages(char *what, unsigned long begin, unsigned long end) +diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c +index 30031d5..cdfe8c6 100644 +--- a/arch/x86/platform/efi/quirks.c ++++ b/arch/x86/platform/efi/quirks.c +@@ -201,6 +201,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) + return; + } + ++ /* No need to reserve regions that will never be freed. */ ++ if (md.attribute & EFI_MEMORY_RUNTIME) ++ return; ++ + size += addr % EFI_PAGE_SIZE; + size = round_up(size, EFI_PAGE_SIZE); + addr = round_down(addr, EFI_PAGE_SIZE); +diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c +index 44c88ad..bcea81f 100644 +--- a/arch/x86/xen/apic.c ++++ b/arch/x86/xen/apic.c +@@ -145,7 +145,7 @@ static void xen_silent_inquire(int apicid) + static int xen_cpu_present_to_apicid(int cpu) + { + if (cpu_present(cpu)) +- return xen_get_apic_id(xen_apic_read(APIC_ID)); ++ return cpu_data(cpu).apicid; + else + return BAD_APICID; + } +diff --git a/crypto/ahash.c b/crypto/ahash.c +index 2ce8bcb..cce0268 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -31,6 +31,7 @@ struct ahash_request_priv { + crypto_completion_t complete; + void *data; + u8 *result; ++ u32 flags; + void *ubuf[] CRYPTO_MINALIGN_ATTR; + }; + +@@ -252,6 +253,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + priv->result = req->result; + priv->complete = req->base.complete; + priv->data = req->base.data; ++ priv->flags = req->base.flags; ++ + /* + * WARNING: We do not backup req->priv here! The req->priv + * is for internal use of the Crypto API and the +@@ -266,38 +269,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + return 0; + } + +-static void ahash_restore_req(struct ahash_request *req) ++static void ahash_restore_req(struct ahash_request *req, int err) + { + struct ahash_request_priv *priv = req->priv; + ++ if (!err) ++ memcpy(priv->result, req->result, ++ crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ + /* Restore the original crypto request. */ + req->result = priv->result; +- req->base.complete = priv->complete; +- req->base.data = priv->data; ++ ++ ahash_request_set_callback(req, priv->flags, ++ priv->complete, priv->data); + req->priv = NULL; + + /* Free the req->priv.priv from the ADJUSTED request. */ + kzfree(priv); + } + +-static void ahash_op_unaligned_finish(struct ahash_request *req, int err) ++static void ahash_notify_einprogress(struct ahash_request *req) + { + struct ahash_request_priv *priv = req->priv; ++ struct crypto_async_request oreq; + +- if (err == -EINPROGRESS) +- return; +- +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ oreq.data = priv->data; + +- ahash_restore_req(req); ++ priv->complete(&oreq, -EINPROGRESS); + } + + static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ + /* + * Restore the original request, see ahash_op_unaligned() for what + * goes where. +@@ -308,7 +317,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + */ + + /* First copy req->result into req->priv.result */ +- ahash_op_unaligned_finish(areq, err); ++ ahash_restore_req(areq, err); + + /* Complete the ORIGINAL request. */ + areq->base.complete(&areq->base, err); +@@ -324,7 +333,12 @@ static int ahash_op_unaligned(struct ahash_request *req, + return err; + + err = op(req); +- ahash_op_unaligned_finish(req, err); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ ++ ahash_restore_req(req, err); + + return err; + } +@@ -359,25 +373,14 @@ int crypto_ahash_digest(struct ahash_request *req) + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +-static void ahash_def_finup_finish2(struct ahash_request *req, int err) ++static void ahash_def_finup_done2(struct crypto_async_request *req, int err) + { +- struct ahash_request_priv *priv = req->priv; ++ struct ahash_request *areq = req->data; + + if (err == -EINPROGRESS) + return; + +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); +- +- ahash_restore_req(req); +-} +- +-static void ahash_def_finup_done2(struct crypto_async_request *req, int err) +-{ +- struct ahash_request *areq = req->data; +- +- ahash_def_finup_finish2(areq, err); ++ ahash_restore_req(areq, err); + + areq->base.complete(&areq->base, err); + } +@@ -388,11 +391,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err) + goto out; + + req->base.complete = ahash_def_finup_done2; +- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = crypto_ahash_reqtfm(req)->final(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; + + out: +- ahash_def_finup_finish2(req, err); ++ ahash_restore_req(req, err); + return err; + } + +@@ -400,7 +407,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ ++ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = ahash_def_finup_finish1(areq, err); ++ if (areq->priv) ++ return; + + areq->base.complete(&areq->base, err); + } +@@ -415,6 +431,11 @@ static int ahash_def_finup(struct ahash_request *req) + return err; + + err = tfm->update(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ + return ahash_def_finup_finish1(req, err); + } + +diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c +index e8817e2..fde8d88 100644 +--- a/crypto/algif_aead.c ++++ b/crypto/algif_aead.c +@@ -39,6 +39,7 @@ struct aead_async_req { + struct aead_async_rsgl first_rsgl; + struct list_head list; + struct kiocb *iocb; ++ struct sock *sk; + unsigned int tsgls; + char iv[]; + }; +@@ -379,12 +380,10 @@ static ssize_t aead_sendpage(struct socket *sock, struct page *page, + + static void aead_async_cb(struct crypto_async_request *_req, int err) + { +- struct sock *sk = _req->data; +- struct alg_sock *ask = alg_sk(sk); +- struct aead_ctx *ctx = ask->private; +- struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req); +- struct aead_request *req = aead_request_cast(_req); ++ struct aead_request *req = _req->data; ++ struct crypto_aead *tfm = crypto_aead_reqtfm(req); + struct aead_async_req *areq = GET_ASYM_REQ(req, tfm); ++ struct sock *sk = areq->sk; + struct scatterlist *sg = areq->tsgl; + struct aead_async_rsgl *rsgl; + struct kiocb *iocb = areq->iocb; +@@ -447,11 +446,12 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg, + memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl)); + INIT_LIST_HEAD(&areq->list); + areq->iocb = msg->msg_iocb; ++ areq->sk = sk; + memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm)); + aead_request_set_tfm(req, tfm); + aead_request_set_ad(req, ctx->aead_assoclen); + aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, +- aead_async_cb, sk); ++ aead_async_cb, req); + used -= ctx->aead_assoclen; + + /* take over all tx sgls from ctx */ +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 48e19d0..22ca892 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -729,12 +729,12 @@ static void start_transaction(struct acpi_ec *ec) + + static int ec_guard(struct acpi_ec *ec) + { +- unsigned long guard = usecs_to_jiffies(ec_polling_guard); ++ unsigned long guard = usecs_to_jiffies(ec->polling_guard); + unsigned long timeout = ec->timestamp + guard; + + /* Ensure guarding period before polling EC status */ + do { +- if (ec_busy_polling) { ++ if (ec->busy_polling) { + /* Perform busy polling */ + if (ec_transaction_completed(ec)) + return 0; +@@ -998,6 +998,28 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) + spin_unlock_irqrestore(&ec->lock, flags); + } + ++static void acpi_ec_enter_noirq(struct acpi_ec *ec) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ec->lock, flags); ++ ec->busy_polling = true; ++ ec->polling_guard = 0; ++ ec_log_drv("interrupt blocked"); ++ spin_unlock_irqrestore(&ec->lock, flags); ++} ++ ++static void acpi_ec_leave_noirq(struct acpi_ec *ec) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ec->lock, flags); ++ ec->busy_polling = ec_busy_polling; ++ ec->polling_guard = ec_polling_guard; ++ ec_log_drv("interrupt unblocked"); ++ spin_unlock_irqrestore(&ec->lock, flags); ++} ++ + void acpi_ec_block_transactions(void) + { + struct acpi_ec *ec = first_ec; +@@ -1278,7 +1300,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, + if (function != ACPI_READ && function != ACPI_WRITE) + return AE_BAD_PARAMETER; + +- if (ec_busy_polling || bits > 8) ++ if (ec->busy_polling || bits > 8) + acpi_ec_burst_enable(ec); + + for (i = 0; i < bytes; ++i, ++address, ++value) +@@ -1286,7 +1308,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, + acpi_ec_read(ec, address, value) : + acpi_ec_write(ec, address, *value); + +- if (ec_busy_polling || bits > 8) ++ if (ec->busy_polling || bits > 8) + acpi_ec_burst_disable(ec); + + switch (result) { +@@ -1329,6 +1351,8 @@ static struct acpi_ec *acpi_ec_alloc(void) + spin_lock_init(&ec->lock); + INIT_WORK(&ec->work, acpi_ec_event_handler); + ec->timestamp = jiffies; ++ ec->busy_polling = true; ++ ec->polling_guard = 0; + return ec; + } + +@@ -1390,6 +1414,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events) + acpi_ec_start(ec, false); + + if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { ++ acpi_ec_enter_noirq(ec); + status = acpi_install_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler, +@@ -1429,6 +1454,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events) + /* This is not fatal as we can poll EC events */ + if (ACPI_SUCCESS(status)) { + set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); ++ acpi_ec_leave_noirq(ec); + if (test_bit(EC_FLAGS_STARTED, &ec->flags) && + ec->reference_count >= 1) + acpi_ec_enable_gpe(ec, true); +@@ -1839,34 +1865,6 @@ int __init acpi_ec_ecdt_probe(void) + } + + #ifdef CONFIG_PM_SLEEP +-static void acpi_ec_enter_noirq(struct acpi_ec *ec) +-{ +- unsigned long flags; +- +- if (ec == first_ec) { +- spin_lock_irqsave(&ec->lock, flags); +- ec->saved_busy_polling = ec_busy_polling; +- ec->saved_polling_guard = ec_polling_guard; +- ec_busy_polling = true; +- ec_polling_guard = 0; +- ec_log_drv("interrupt blocked"); +- spin_unlock_irqrestore(&ec->lock, flags); +- } +-} +- +-static void acpi_ec_leave_noirq(struct acpi_ec *ec) +-{ +- unsigned long flags; +- +- if (ec == first_ec) { +- spin_lock_irqsave(&ec->lock, flags); +- ec_busy_polling = ec->saved_busy_polling; +- ec_polling_guard = ec->saved_polling_guard; +- ec_log_drv("interrupt unblocked"); +- spin_unlock_irqrestore(&ec->lock, flags); +- } +-} +- + static int acpi_ec_suspend_noirq(struct device *dev) + { + struct acpi_ec *ec = +diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h +index 0c45226..219b90b 100644 +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -172,8 +172,8 @@ struct acpi_ec { + struct work_struct work; + unsigned long timestamp; + unsigned long nr_pending_queries; +- bool saved_busy_polling; +- unsigned int saved_polling_guard; ++ bool busy_polling; ++ unsigned int polling_guard; + }; + + extern struct acpi_ec *first_ec; +diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c +index d1664df..9ef3941 100644 +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -1617,7 +1617,11 @@ static int cmp_map(const void *m0, const void *m1) + const struct nfit_set_info_map *map0 = m0; + const struct nfit_set_info_map *map1 = m1; + +- return map0->region_offset - map1->region_offset; ++ if (map0->region_offset < map1->region_offset) ++ return -1; ++ else if (map0->region_offset > map1->region_offset) ++ return 1; ++ return 0; + } + + /* Retrieve the nth entry referencing this spa */ +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 5a2fdf1..dd3786a 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -1827,15 +1827,20 @@ static void acpi_bus_attach(struct acpi_device *device) + return; + + device->flags.match_driver = true; +- if (!ret) { +- ret = device_attach(&device->dev); +- if (ret < 0) +- return; +- +- if (!ret && device->pnp.type.platform_id) +- acpi_default_enumeration(device); ++ if (ret > 0) { ++ acpi_device_set_enumerated(device); ++ goto ok; + } + ++ ret = device_attach(&device->dev); ++ if (ret < 0) ++ return; ++ ++ if (ret > 0 || !device->pnp.type.platform_id) ++ acpi_device_set_enumerated(device); ++ else ++ acpi_default_enumeration(device); ++ + ok: + list_for_each_entry(child, &device->children, node) + acpi_bus_attach(child); +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 7a10487..c9441f9 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -54,7 +54,7 @@ struct nbd_device { + + struct mutex tx_lock; + struct gendisk *disk; +- int blksize; ++ loff_t blksize; + loff_t bytesize; + + /* protects initialization and shutdown of the socket */ +@@ -126,7 +126,7 @@ static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev) + } + + static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, +- int blocksize, int nr_blocks) ++ loff_t blocksize, loff_t nr_blocks) + { + int ret; + +@@ -135,7 +135,7 @@ static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, + return ret; + + nbd->blksize = blocksize; +- nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks; ++ nbd->bytesize = blocksize * nr_blocks; + + nbd_size_update(nbd, bdev); + +@@ -648,7 +648,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, + + case NBD_SET_SIZE: + return nbd_size_set(nbd, bdev, nbd->blksize, +- arg / nbd->blksize); ++ div_s64(arg, nbd->blksize)); + + case NBD_SET_SIZE_BLOCKS: + return nbd_size_set(nbd, bdev, nbd->blksize, arg); +@@ -817,7 +817,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd) + debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); + debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); + debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout); +- debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); ++ debugfs_create_u64("blocksize", 0444, dir, &nbd->blksize); + debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops); + + return 0; +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index d2ef51c..c9914d6 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -582,13 +582,13 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) + + if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { + bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); +- clear_page(mem); ++ memset(mem, 0, PAGE_SIZE); + return 0; + } + + cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); + if (size == PAGE_SIZE) { +- copy_page(mem, cmem); ++ memcpy(mem, cmem, PAGE_SIZE); + } else { + struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); + +@@ -780,7 +780,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + + if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) { + src = kmap_atomic(page); +- copy_page(cmem, src); ++ memcpy(cmem, src, PAGE_SIZE); + kunmap_atomic(src); + } else { + memcpy(cmem, src, clen); +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index dcc0973..8453a49 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -571,9 +571,12 @@ config TELCLOCK + controlling the behavior of this hardware. + + config DEVPORT +- bool ++ bool "/dev/port character device" + depends on ISA || PCI + default y ++ help ++ Say Y here if you want to support the /dev/port device. The /dev/port ++ device is similar to /dev/mem, but for I/O ports. + + source "drivers/s390/char/Kconfig" + +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 6d9cc2d..7e4a9d1 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -60,6 +60,10 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) + #endif + + #ifdef CONFIG_STRICT_DEVMEM ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return devmem_is_allowed(pfn); ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + u64 from = ((u64)pfn) << PAGE_SHIFT; +@@ -75,6 +79,10 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) + return 1; + } + #else ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return 1; ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + return 1; +@@ -122,23 +130,31 @@ static ssize_t read_mem(struct file *file, char __user *buf, + + while (count > 0) { + unsigned long remaining; ++ int allowed; + + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, count)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; ++ if (allowed == 2) { ++ /* Show zeros for restricted memory. */ ++ remaining = clear_user(buf, sz); ++ } else { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) ++ return -EFAULT; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) +- return -EFAULT; ++ remaining = copy_to_user(buf, ptr, sz); ++ ++ unxlate_dev_mem_ptr(p, ptr); ++ } + +- remaining = copy_to_user(buf, ptr, sz); +- unxlate_dev_mem_ptr(p, ptr); + if (remaining) + return -EFAULT; + +@@ -181,30 +197,36 @@ static ssize_t write_mem(struct file *file, const char __user *buf, + #endif + + while (count > 0) { ++ int allowed; ++ + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, sz)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) { +- if (written) +- break; +- return -EFAULT; +- } ++ /* Skip actual writing when a page is marked as restricted. */ ++ if (allowed == 1) { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) { ++ if (written) ++ break; ++ return -EFAULT; ++ } + +- copied = copy_from_user(ptr, buf, sz); +- unxlate_dev_mem_ptr(p, ptr); +- if (copied) { +- written += sz - copied; +- if (written) +- break; +- return -EFAULT; ++ copied = copy_from_user(ptr, buf, sz); ++ unxlate_dev_mem_ptr(p, ptr); ++ if (copied) { ++ written += sz - copied; ++ if (written) ++ break; ++ return -EFAULT; ++ } + } + + buf += sz; +diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c +index 5649234..471a301 100644 +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1136,6 +1136,8 @@ static int put_chars(u32 vtermno, const char *buf, int count) + { + struct port *port; + struct scatterlist sg[1]; ++ void *data; ++ int ret; + + if (unlikely(early_put_chars)) + return early_put_chars(vtermno, buf, count); +@@ -1144,8 +1146,14 @@ static int put_chars(u32 vtermno, const char *buf, int count) + if (!port) + return -EPIPE; + +- sg_init_one(sg, buf, count); +- return __send_to_port(port, sg, 1, count, (void *)buf, false); ++ data = kmemdup(buf, count, GFP_ATOMIC); ++ if (!data) ++ return -ENOMEM; ++ ++ sg_init_one(sg, data, count); ++ ret = __send_to_port(port, sg, 1, count, data, false); ++ kfree(data); ++ return ret; + } + + /* +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index cac4a92..6153b66 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -2404,6 +2404,20 @@ EXPORT_SYMBOL_GPL(cpufreq_boost_enabled); + *********************************************************************/ + static enum cpuhp_state hp_online; + ++static int cpuhp_cpufreq_online(unsigned int cpu) ++{ ++ cpufreq_online(cpu); ++ ++ return 0; ++} ++ ++static int cpuhp_cpufreq_offline(unsigned int cpu) ++{ ++ cpufreq_offline(cpu); ++ ++ return 0; ++} ++ + /** + * cpufreq_register_driver - register a CPU Frequency driver + * @driver_data: A struct cpufreq_driver containing the values# +@@ -2466,8 +2480,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) + } + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "cpufreq:online", +- cpufreq_online, +- cpufreq_offline); ++ cpuhp_cpufreq_online, ++ cpuhp_cpufreq_offline); + if (ret < 0) + goto err_if_unreg; + hp_online = ret; +diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c +index 932742e..24c461d 100644 +--- a/drivers/firmware/efi/libstub/gop.c ++++ b/drivers/firmware/efi/libstub/gop.c +@@ -149,7 +149,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, + + status = __gop_query32(sys_table_arg, gop32, &info, &size, + ¤t_fb_base); +- if (status == EFI_SUCCESS && (!first_gop || conout_found)) { ++ if (status == EFI_SUCCESS && (!first_gop || conout_found) && ++ info->pixel_format != PIXEL_BLT_ONLY) { + /* + * Systems that use the UEFI Console Splitter may + * provide multiple GOP devices, not all of which are +@@ -266,7 +267,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, + + status = __gop_query64(sys_table_arg, gop64, &info, &size, + ¤t_fb_base); +- if (status == EFI_SUCCESS && (!first_gop || conout_found)) { ++ if (status == EFI_SUCCESS && (!first_gop || conout_found) && ++ info->pixel_format != PIXEL_BLT_ONLY) { + /* + * Systems that use the UEFI Console Splitter may + * provide multiple GOP devices, not all of which are +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +index b87d278..a336754 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -1305,7 +1305,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, + if (!fence) { + event_free(gpu, event); + ret = -ENOMEM; +- goto out_pm_put; ++ goto out_unlock; + } + + gpu->event[event].fence = fence; +@@ -1345,6 +1345,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, + hangcheck_timer_reset(gpu); + ret = 0; + ++out_unlock: + mutex_unlock(&gpu->lock); + + out_pm_put: +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +index e0d7f84..d741ff8 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +@@ -714,7 +714,7 @@ nv4a_chipset = { + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, +- .mmu = nv44_mmu_new, ++ .mmu = nv04_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +index fbb8c7d..0d65e7f 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +@@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device *device) + case 0x94: + case 0x96: + case 0x98: +- case 0xaa: +- case 0xac: + return true; + default: + break; +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +index 003ac91..8a88952 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +@@ -198,7 +198,7 @@ nv31_mpeg_intr(struct nvkm_engine *engine) + } + + if (type == 0x00000010) { +- if (!nv31_mpeg_mthd(mpeg, mthd, data)) ++ if (nv31_mpeg_mthd(mpeg, mthd, data)) + show &= ~0x01000000; + } + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +index e536f37..c3cf02e 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +@@ -172,7 +172,7 @@ nv44_mpeg_intr(struct nvkm_engine *engine) + } + + if (type == 0x00000010) { +- if (!nv44_mpeg_mthd(subdev->device, mthd, data)) ++ if (nv44_mpeg_mthd(subdev->device, mthd, data)) + show &= ~0x01000000; + } + } +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index bbe1524..f397a5b 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -201,6 +201,7 @@ static const struct xpad_device { + { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, + { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 }, ++ { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE }, + { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 }, + { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, + { 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 }, +@@ -329,6 +330,7 @@ static struct usb_device_id xpad_table[] = { + XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ ++ XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */ + XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ + { } +diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c +index 15af9a9..2d203b4 100644 +--- a/drivers/irqchip/irq-imx-gpcv2.c ++++ b/drivers/irqchip/irq-imx-gpcv2.c +@@ -230,6 +230,8 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node, + return -ENOMEM; + } + ++ raw_spin_lock_init(&cd->rlock); ++ + cd->gpc_base = of_iomap(node, 0); + if (!cd->gpc_base) { + pr_err("fsl-gpcv2: unable to map gpc registers\n"); +diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +index a8e6624..a9bb2dd 100644 +--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c ++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +@@ -1013,8 +1013,8 @@ EXPORT_SYMBOL(dvb_usbv2_probe); + void dvb_usbv2_disconnect(struct usb_interface *intf) + { + struct dvb_usb_device *d = usb_get_intfdata(intf); +- const char *name = d->name; +- struct device dev = d->udev->dev; ++ const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL); ++ const char *drvname = d->name; + + dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); +@@ -1024,8 +1024,9 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) + + dvb_usbv2_exit(d); + +- dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", +- KBUILD_MODNAME, name); ++ pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n", ++ KBUILD_MODNAME, drvname, devname); ++ kfree(devname); + } + EXPORT_SYMBOL(dvb_usbv2_disconnect); + +diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c +index 2434030..9fd43a3 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -59,23 +59,24 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, + u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) + { + struct cxusb_state *st = d->priv; +- int ret, wo; ++ int ret; + + if (1 + wlen > MAX_XFER_SIZE) { + warn("i2c wr: len=%d is too big!\n", wlen); + return -EOPNOTSUPP; + } + +- wo = (rbuf == NULL || rlen == 0); /* write-only */ ++ if (rlen > MAX_XFER_SIZE) { ++ warn("i2c rd: len=%d is too big!\n", rlen); ++ return -EOPNOTSUPP; ++ } + + mutex_lock(&d->data_mutex); + st->data[0] = cmd; + memcpy(&st->data[1], wbuf, wlen); +- if (wo) +- ret = dvb_usb_generic_write(d, st->data, 1 + wlen); +- else +- ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, +- rbuf, rlen, 0); ++ ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, st->data, rlen, 0); ++ if (!ret && rbuf && rlen) ++ memcpy(rbuf, st->data, rlen); + + mutex_unlock(&d->data_mutex); + return ret; +diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +index dd048a7..b8d2ac5 100644 +--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +@@ -35,42 +35,51 @@ static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 le + + int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) + { +- struct hexline hx; +- u8 reset; +- int ret,pos=0; ++ struct hexline *hx; ++ u8 *buf; ++ int ret, pos = 0; ++ u16 cpu_cs_register = cypress[type].cpu_cs_register; ++ ++ buf = kmalloc(sizeof(*hx), GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ hx = (struct hexline *)buf; + + /* stop the CPU */ +- reset = 1; +- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) ++ buf[0] = 1; ++ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) + err("could not stop the USB controller CPU."); + +- while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) { +- deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk); +- ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len); ++ while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) { ++ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n", hx->addr, hx->len, hx->chk); ++ ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len); + +- if (ret != hx.len) { ++ if (ret != hx->len) { + err("error while transferring firmware " + "(transferred size: %d, block size: %d)", +- ret,hx.len); ++ ret, hx->len); + ret = -EINVAL; + break; + } + } + if (ret < 0) { + err("firmware download failed at %d with %d",pos,ret); ++ kfree(buf); + return ret; + } + + if (ret == 0) { + /* restart the CPU */ +- reset = 0; +- if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { ++ buf[0] = 0; ++ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) { + err("could not restart the USB controller CPU."); + ret = -EINVAL; + } + } else + ret = -EIO; + ++ kfree(buf); ++ + return ret; + } + EXPORT_SYMBOL(usb_cypress_load_firmware); +diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c +index 368bb07..481895b 100644 +--- a/drivers/net/can/ifi_canfd/ifi_canfd.c ++++ b/drivers/net/can/ifi_canfd/ifi_canfd.c +@@ -557,7 +557,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota) + int work_done = 0; + + u32 stcmd = readl(priv->base + IFI_CANFD_STCMD); +- u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD); ++ u32 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD); + u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR); + + /* Handle bus state changes */ +diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c +index e2512d5..eedf86b 100644 +--- a/drivers/net/wireless/ath/ath9k/common-spectral.c ++++ b/drivers/net/wireless/ath/ath9k/common-spectral.c +@@ -528,6 +528,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h + if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) + return 0; + ++ if (!spec_priv->rfs_chan_spec_scan) ++ return 1; ++ + /* Output buffers are full, no need to process anything + * since there is no space to put the result anyway + */ +@@ -1072,7 +1075,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { + + void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) + { +- if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS)) { ++ if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + relay_close(spec_priv->rfs_chan_spec_scan); + spec_priv->rfs_chan_spec_scan = NULL; + } +@@ -1086,6 +1089,9 @@ void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, + debugfs_phy, + 1024, 256, &rfs_spec_scan_cb, + NULL); ++ if (!spec_priv->rfs_chan_spec_scan) ++ return; ++ + debugfs_create_file("spectral_scan_ctl", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, +diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c +index 23d4a17..351bac8 100644 +--- a/drivers/nvdimm/bus.c ++++ b/drivers/nvdimm/bus.c +@@ -934,8 +934,14 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, + rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, NULL); + if (rc < 0) + goto out_unlock; ++ nvdimm_bus_unlock(&nvdimm_bus->dev); ++ + if (copy_to_user(p, buf, buf_len)) + rc = -EFAULT; ++ ++ vfree(buf); ++ return rc; ++ + out_unlock: + nvdimm_bus_unlock(&nvdimm_bus->dev); + out: +diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c +index d614493..dcb32f3 100644 +--- a/drivers/nvdimm/dimm_devs.c ++++ b/drivers/nvdimm/dimm_devs.c +@@ -388,7 +388,7 @@ EXPORT_SYMBOL_GPL(nvdimm_create); + + int alias_dpa_busy(struct device *dev, void *data) + { +- resource_size_t map_end, blk_start, new, busy; ++ resource_size_t map_end, blk_start, new; + struct blk_alloc_info *info = data; + struct nd_mapping *nd_mapping; + struct nd_region *nd_region; +@@ -429,29 +429,19 @@ int alias_dpa_busy(struct device *dev, void *data) + retry: + /* + * Find the free dpa from the end of the last pmem allocation to +- * the end of the interleave-set mapping that is not already +- * covered by a blk allocation. ++ * the end of the interleave-set mapping. + */ +- busy = 0; + for_each_dpa_resource(ndd, res) { ++ if (strncmp(res->name, "pmem", 4) != 0) ++ continue; + if ((res->start >= blk_start && res->start < map_end) + || (res->end >= blk_start + && res->end <= map_end)) { +- if (strncmp(res->name, "pmem", 4) == 0) { +- new = max(blk_start, min(map_end + 1, +- res->end + 1)); +- if (new != blk_start) { +- blk_start = new; +- goto retry; +- } +- } else +- busy += min(map_end, res->end) +- - max(nd_mapping->start, res->start) + 1; +- } else if (nd_mapping->start > res->start +- && map_end < res->end) { +- /* total eclipse of the PMEM region mapping */ +- busy += nd_mapping->size; +- break; ++ new = max(blk_start, min(map_end + 1, res->end + 1)); ++ if (new != blk_start) { ++ blk_start = new; ++ goto retry; ++ } + } + } + +@@ -463,52 +453,11 @@ int alias_dpa_busy(struct device *dev, void *data) + return 1; + } + +- info->available -= blk_start - nd_mapping->start + busy; ++ info->available -= blk_start - nd_mapping->start; + + return 0; + } + +-static int blk_dpa_busy(struct device *dev, void *data) +-{ +- struct blk_alloc_info *info = data; +- struct nd_mapping *nd_mapping; +- struct nd_region *nd_region; +- resource_size_t map_end; +- int i; +- +- if (!is_nd_pmem(dev)) +- return 0; +- +- nd_region = to_nd_region(dev); +- for (i = 0; i < nd_region->ndr_mappings; i++) { +- nd_mapping = &nd_region->mapping[i]; +- if (nd_mapping->nvdimm == info->nd_mapping->nvdimm) +- break; +- } +- +- if (i >= nd_region->ndr_mappings) +- return 0; +- +- map_end = nd_mapping->start + nd_mapping->size - 1; +- if (info->res->start >= nd_mapping->start +- && info->res->start < map_end) { +- if (info->res->end <= map_end) { +- info->busy = 0; +- return 1; +- } else { +- info->busy -= info->res->end - map_end; +- return 0; +- } +- } else if (info->res->end >= nd_mapping->start +- && info->res->end <= map_end) { +- info->busy -= nd_mapping->start - info->res->start; +- return 0; +- } else { +- info->busy -= nd_mapping->size; +- return 0; +- } +-} +- + /** + * nd_blk_available_dpa - account the unused dpa of BLK region + * @nd_mapping: container of dpa-resource-root + labels +@@ -538,11 +487,7 @@ resource_size_t nd_blk_available_dpa(struct nd_region *nd_region) + for_each_dpa_resource(ndd, res) { + if (strncmp(res->name, "blk", 3) != 0) + continue; +- +- info.res = res; +- info.busy = resource_size(res); +- device_for_each_child(&nvdimm_bus->dev, &info, blk_dpa_busy); +- info.available -= info.busy; ++ info.available -= resource_size(res); + } + + return info.available; +diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c +index a66192f..c29b9b6 100644 +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -1846,11 +1846,24 @@ static int __init acer_wmi_enable_lm(void) + return status; + } + ++#define ACER_WMID_ACCEL_HID "BST0001" ++ + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, + void *ctx, void **retval) + { ++ struct acpi_device *dev; ++ ++ if (!strcmp(ctx, "SENR")) { ++ if (acpi_bus_get_device(ah, &dev)) ++ return AE_OK; ++ if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) ++ return AE_OK; ++ } else ++ return AE_OK; ++ + *(acpi_handle *)retval = ah; +- return AE_OK; ++ ++ return AE_CTRL_TERMINATE; + } + + static int __init acer_wmi_get_handle(const char *name, const char *prop, +@@ -1877,7 +1890,7 @@ static int __init acer_wmi_accel_setup(void) + { + int err; + +- err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); ++ err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle); + if (err) + return err; + +@@ -2233,10 +2246,11 @@ static int __init acer_wmi_init(void) + err = acer_wmi_input_setup(); + if (err) + return err; ++ err = acer_wmi_accel_setup(); ++ if (err) ++ return err; + } + +- acer_wmi_accel_setup(); +- + err = platform_driver_register(&acer_platform_driver); + if (err) { + pr_err("Unable to register platform driver\n"); +diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c +index ef89df1..744d561 100644 +--- a/drivers/pwm/pwm-rockchip.c ++++ b/drivers/pwm/pwm-rockchip.c +@@ -191,6 +191,28 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + ++static int rockchip_pwm_enable(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ bool enable, ++ enum pwm_polarity polarity) ++{ ++ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); ++ int ret; ++ ++ if (enable) { ++ ret = clk_enable(pc->clk); ++ if (ret) ++ return ret; ++ } ++ ++ pc->data->set_enable(chip, pwm, enable, polarity); ++ ++ if (!enable) ++ clk_disable(pc->clk); ++ ++ return 0; ++} ++ + static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) + { +@@ -207,22 +229,26 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + + if (state->polarity != curstate.polarity && enabled) { +- pc->data->set_enable(chip, pwm, false, state->polarity); ++ ret = rockchip_pwm_enable(chip, pwm, false, state->polarity); ++ if (ret) ++ goto out; + enabled = false; + } + + ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (ret) { + if (enabled != curstate.enabled) +- pc->data->set_enable(chip, pwm, !enabled, +- state->polarity); +- ++ rockchip_pwm_enable(chip, pwm, !enabled, ++ state->polarity); + goto out; + } + +- if (state->enabled != enabled) +- pc->data->set_enable(chip, pwm, state->enabled, +- state->polarity); ++ if (state->enabled != enabled) { ++ ret = rockchip_pwm_enable(chip, pwm, state->enabled, ++ state->polarity); ++ if (ret) ++ goto out; ++ } + + /* + * Update the state with the real hardware, which can differ a bit +diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c +index 3853ba9..19e03d0 100644 +--- a/drivers/rtc/rtc-tegra.c ++++ b/drivers/rtc/rtc-tegra.c +@@ -18,6 +18,7 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + #include ++#include + #include + #include + #include +@@ -59,6 +60,7 @@ struct tegra_rtc_info { + struct platform_device *pdev; + struct rtc_device *rtc_dev; + void __iomem *rtc_base; /* NULL if not initialized. */ ++ struct clk *clk; + int tegra_rtc_irq; /* alarm and periodic irq */ + spinlock_t tegra_rtc_lock; + }; +@@ -326,6 +328,14 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) + if (info->tegra_rtc_irq <= 0) + return -EBUSY; + ++ info->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(info->clk)) ++ return PTR_ERR(info->clk); ++ ++ ret = clk_prepare_enable(info->clk); ++ if (ret < 0) ++ return ret; ++ + /* set context info. */ + info->pdev = pdev; + spin_lock_init(&info->tegra_rtc_lock); +@@ -346,7 +356,7 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) + ret = PTR_ERR(info->rtc_dev); + dev_err(&pdev->dev, "Unable to register device (err=%d).\n", + ret); +- return ret; ++ goto disable_clk; + } + + ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, +@@ -356,12 +366,25 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) + dev_err(&pdev->dev, + "Unable to request interrupt for device (err=%d).\n", + ret); +- return ret; ++ goto disable_clk; + } + + dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); + + return 0; ++ ++disable_clk: ++ clk_disable_unprepare(info->clk); ++ return ret; ++} ++ ++static int tegra_rtc_remove(struct platform_device *pdev) ++{ ++ struct tegra_rtc_info *info = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(info->clk); ++ ++ return 0; + } + + #ifdef CONFIG_PM_SLEEP +@@ -413,6 +436,7 @@ static void tegra_rtc_shutdown(struct platform_device *pdev) + + MODULE_ALIAS("platform:tegra_rtc"); + static struct platform_driver tegra_rtc_driver = { ++ .remove = tegra_rtc_remove, + .shutdown = tegra_rtc_shutdown, + .driver = { + .name = "tegra_rtc", +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 4f361d8..734e592 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -968,8 +968,13 @@ static inline + uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha) + { + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; ++ struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; + +- return ((RD_REG_DWORD(®->host_status)) == ISP_REG_DISCONNECT); ++ if (IS_P3P_TYPE(ha)) ++ return ((RD_REG_DWORD(®82->host_int)) == ISP_REG_DISCONNECT); ++ else ++ return ((RD_REG_DWORD(®->host_status)) == ++ ISP_REG_DISCONNECT); + } + + /************************************************************************** +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 51e5629..931af07 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2057,6 +2057,22 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, + + #define READ_CAPACITY_RETRIES_ON_RESET 10 + ++/* ++ * Ensure that we don't overflow sector_t when CONFIG_LBDAF is not set ++ * and the reported logical block size is bigger than 512 bytes. Note ++ * that last_sector is a u64 and therefore logical_to_sectors() is not ++ * applicable. ++ */ ++static bool sd_addressable_capacity(u64 lba, unsigned int sector_size) ++{ ++ u64 last_sector = (lba + 1ULL) << (ilog2(sector_size) - 9); ++ ++ if (sizeof(sector_t) == 4 && last_sector > U32_MAX) ++ return false; ++ ++ return true; ++} ++ + static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, + unsigned char *buffer) + { +@@ -2122,7 +2138,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, + return -ENODEV; + } + +- if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) { ++ if (!sd_addressable_capacity(lba, sector_size)) { + sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " + "kernel compiled with support for large block " + "devices.\n"); +@@ -2208,7 +2224,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, + return sector_size; + } + +- if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { ++ if (!sd_addressable_capacity(lba, sector_size)) { + sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " + "kernel compiled with support for large block " + "devices.\n"); +@@ -2877,7 +2893,8 @@ static int sd_revalidate_disk(struct gendisk *disk) + q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); + rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); + } else +- rw_max = BLK_DEF_MAX_SECTORS; ++ rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), ++ (sector_t)BLK_DEF_MAX_SECTORS); + + /* Combine with controller limits */ + q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q)); +diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c +index bed2bbd..e635973 100644 +--- a/drivers/scsi/sr.c ++++ b/drivers/scsi/sr.c +@@ -833,6 +833,7 @@ static void get_capabilities(struct scsi_cd *cd) + unsigned char *buffer; + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; ++ unsigned int ms_len = 128; + int rc, n; + + static const char *loadmech[] = +@@ -859,10 +860,11 @@ static void get_capabilities(struct scsi_cd *cd) + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); + + /* ask for mode page 0x2a */ +- rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, ++ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, + SR_TIMEOUT, 3, &data, NULL); + +- if (!scsi_status_is_good(rc)) { ++ if (!scsi_status_is_good(rc) || data.length > ms_len || ++ data.header_length + data.block_descriptor_length > data.length) { + /* failed, drive doesn't have capabilities mode page */ + cd->cdi.speed = 1; + cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | +diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c +index 0efa80b..4a073339a 100644 +--- a/drivers/target/iscsi/iscsi_target_parameters.c ++++ b/drivers/target/iscsi/iscsi_target_parameters.c +@@ -782,22 +782,6 @@ static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) + if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) + SET_PSTATE_REPLY_OPTIONAL(param); + /* +- * The GlobalSAN iSCSI Initiator for MacOSX does +- * not respond to MaxBurstLength, FirstBurstLength, +- * DefaultTime2Wait or DefaultTime2Retain parameter keys. +- * So, we set them to 'reply optional' here, and assume the +- * the defaults from iscsi_parameters.h if the initiator +- * is not RFC compliant and the keys are not negotiated. +- */ +- if (!strcmp(param->name, MAXBURSTLENGTH)) +- SET_PSTATE_REPLY_OPTIONAL(param); +- if (!strcmp(param->name, FIRSTBURSTLENGTH)) +- SET_PSTATE_REPLY_OPTIONAL(param); +- if (!strcmp(param->name, DEFAULTTIME2WAIT)) +- SET_PSTATE_REPLY_OPTIONAL(param); +- if (!strcmp(param->name, DEFAULTTIME2RETAIN)) +- SET_PSTATE_REPLY_OPTIONAL(param); +- /* + * Required for gPXE iSCSI boot client + */ + if (!strcmp(param->name, MAXCONNECTIONS)) +diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c +index 1f38177..da5a5fc 100644 +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -735,21 +735,23 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) + { + struct se_cmd *se_cmd = NULL; + int rc; ++ bool op_scsi = false; + /* + * Determine if a struct se_cmd is associated with + * this struct iscsi_cmd. + */ + switch (cmd->iscsi_opcode) { + case ISCSI_OP_SCSI_CMD: +- se_cmd = &cmd->se_cmd; +- __iscsit_free_cmd(cmd, true, shutdown); ++ op_scsi = true; + /* + * Fallthrough + */ + case ISCSI_OP_SCSI_TMFUNC: +- rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); +- if (!rc && shutdown && se_cmd && se_cmd->se_sess) { +- __iscsit_free_cmd(cmd, true, shutdown); ++ se_cmd = &cmd->se_cmd; ++ __iscsit_free_cmd(cmd, op_scsi, shutdown); ++ rc = transport_generic_free_cmd(se_cmd, shutdown); ++ if (!rc && shutdown && se_cmd->se_sess) { ++ __iscsit_free_cmd(cmd, op_scsi, shutdown); + target_put_sess_cmd(se_cmd); + } + break; +diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c +index 31a096a..6e456de 100644 +--- a/drivers/target/target_core_fabric_configfs.c ++++ b/drivers/target/target_core_fabric_configfs.c +@@ -92,6 +92,11 @@ static int target_fabric_mappedlun_link( + pr_err("Source se_lun->lun_se_dev does not exist\n"); + return -EINVAL; + } ++ if (lun->lun_shutdown) { ++ pr_err("Unable to create mappedlun symlink because" ++ " lun->lun_shutdown=true\n"); ++ return -EINVAL; ++ } + se_tpg = lun->lun_tpg; + + nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; +diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c +index 2744251..1949f50 100644 +--- a/drivers/target/target_core_tpg.c ++++ b/drivers/target/target_core_tpg.c +@@ -640,6 +640,8 @@ void core_tpg_remove_lun( + */ + struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev); + ++ lun->lun_shutdown = true; ++ + core_clear_lun_from_tpg(lun, tpg); + /* + * Wait for any active I/O references to percpu se_lun->lun_ref to +@@ -661,6 +663,8 @@ void core_tpg_remove_lun( + } + if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) + hlist_del_rcu(&lun->link); ++ ++ lun->lun_shutdown = false; + mutex_unlock(&tpg->tpg_lun_mutex); + + percpu_ref_exit(&lun->lun_ref); +diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c +index 70c143a..1a83456 100644 +--- a/drivers/target/target_core_user.c ++++ b/drivers/target/target_core_user.c +@@ -306,24 +306,50 @@ static void free_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd) + DATA_BLOCK_BITS); + } + +-static void gather_data_area(struct tcmu_dev *udev, unsigned long *cmd_bitmap, +- struct scatterlist *data_sg, unsigned int data_nents) ++static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, ++ bool bidi) + { ++ struct se_cmd *se_cmd = cmd->se_cmd; + int i, block; + int block_remaining = 0; + void *from, *to; + size_t copy_bytes, from_offset; +- struct scatterlist *sg; ++ struct scatterlist *sg, *data_sg; ++ unsigned int data_nents; ++ DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS); ++ ++ bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS); ++ ++ if (!bidi) { ++ data_sg = se_cmd->t_data_sg; ++ data_nents = se_cmd->t_data_nents; ++ } else { ++ uint32_t count; ++ ++ /* ++ * For bidi case, the first count blocks are for Data-Out ++ * buffer blocks, and before gathering the Data-In buffer ++ * the Data-Out buffer blocks should be discarded. ++ */ ++ count = DIV_ROUND_UP(se_cmd->data_length, DATA_BLOCK_SIZE); ++ while (count--) { ++ block = find_first_bit(bitmap, DATA_BLOCK_BITS); ++ clear_bit(block, bitmap); ++ } ++ ++ data_sg = se_cmd->t_bidi_data_sg; ++ data_nents = se_cmd->t_bidi_data_nents; ++ } + + for_each_sg(data_sg, sg, data_nents, i) { + int sg_remaining = sg->length; + to = kmap_atomic(sg_page(sg)) + sg->offset; + while (sg_remaining > 0) { + if (block_remaining == 0) { +- block = find_first_bit(cmd_bitmap, ++ block = find_first_bit(bitmap, + DATA_BLOCK_BITS); + block_remaining = DATA_BLOCK_SIZE; +- clear_bit(block, cmd_bitmap); ++ clear_bit(block, bitmap); + } + copy_bytes = min_t(size_t, sg_remaining, + block_remaining); +@@ -389,6 +415,27 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d + return true; + } + ++static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd) ++{ ++ struct se_cmd *se_cmd = tcmu_cmd->se_cmd; ++ size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE); ++ ++ if (se_cmd->se_cmd_flags & SCF_BIDI) { ++ BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); ++ data_length += round_up(se_cmd->t_bidi_data_sg->length, ++ DATA_BLOCK_SIZE); ++ } ++ ++ return data_length; ++} ++ ++static inline uint32_t tcmu_cmd_get_block_cnt(struct tcmu_cmd *tcmu_cmd) ++{ ++ size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd); ++ ++ return data_length / DATA_BLOCK_SIZE; ++} ++ + static sense_reason_t + tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) + { +@@ -402,7 +449,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) + uint32_t cmd_head; + uint64_t cdb_off; + bool copy_to_data_area; +- size_t data_length; ++ size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd); + DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); + + if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) +@@ -416,8 +463,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) + * expensive to tell how many regions are freed in the bitmap + */ + base_command_size = max(offsetof(struct tcmu_cmd_entry, +- req.iov[se_cmd->t_bidi_data_nents + +- se_cmd->t_data_nents]), ++ req.iov[tcmu_cmd_get_block_cnt(tcmu_cmd)]), + sizeof(struct tcmu_cmd_entry)); + command_size = base_command_size + + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE); +@@ -428,11 +474,6 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) + + mb = udev->mb_addr; + cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ +- data_length = se_cmd->data_length; +- if (se_cmd->se_cmd_flags & SCF_BIDI) { +- BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); +- data_length += se_cmd->t_bidi_data_sg->length; +- } + if ((command_size > (udev->cmdr_size / 2)) || + data_length > udev->data_size) { + pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " +@@ -502,11 +543,14 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) + entry->req.iov_dif_cnt = 0; + + /* Handle BIDI commands */ +- iov_cnt = 0; +- alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg, +- se_cmd->t_bidi_data_nents, &iov, &iov_cnt, false); +- entry->req.iov_bidi_cnt = iov_cnt; +- ++ if (se_cmd->se_cmd_flags & SCF_BIDI) { ++ iov_cnt = 0; ++ iov++; ++ alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg, ++ se_cmd->t_bidi_data_nents, &iov, &iov_cnt, ++ false); ++ entry->req.iov_bidi_cnt = iov_cnt; ++ } + /* cmd's data_bitmap is what changed in process */ + bitmap_xor(tcmu_cmd->data_bitmap, old_bitmap, udev->data_bitmap, + DATA_BLOCK_BITS); +@@ -582,19 +626,11 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry * + se_cmd->scsi_sense_length); + free_data_area(udev, cmd); + } else if (se_cmd->se_cmd_flags & SCF_BIDI) { +- DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS); +- + /* Get Data-In buffer before clean up */ +- bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS); +- gather_data_area(udev, bitmap, +- se_cmd->t_bidi_data_sg, se_cmd->t_bidi_data_nents); ++ gather_data_area(udev, cmd, true); + free_data_area(udev, cmd); + } else if (se_cmd->data_direction == DMA_FROM_DEVICE) { +- DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS); +- +- bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS); +- gather_data_area(udev, bitmap, +- se_cmd->t_data_sg, se_cmd->t_data_nents); ++ gather_data_area(udev, cmd, false); + free_data_area(udev, cmd); + } else if (se_cmd->data_direction == DMA_TO_DEVICE) { + free_data_area(udev, cmd); +diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c +index 37a37c4..6f2e729 100644 +--- a/drivers/video/fbdev/efifb.c ++++ b/drivers/video/fbdev/efifb.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include