mirror of
https://github.com/Fishwaldo/build.git
synced 2025-04-18 12:01:40 +00:00
4425 lines
148 KiB
Diff
4425 lines
148 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 6141df04fcb5..03bd927522f7 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 10
|
|
-SUBLEVEL = 55
|
|
+SUBLEVEL = 56
|
|
EXTRAVERSION =
|
|
NAME = TOSSUG Baby Fish
|
|
|
|
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
|
|
index 9ce8ba1a1433..adb9aa5c88c7 100644
|
|
--- a/arch/arm/configs/multi_v7_defconfig
|
|
+++ b/arch/arm/configs/multi_v7_defconfig
|
|
@@ -48,6 +48,8 @@ CONFIG_SERIAL_SIRFSOC=y
|
|
CONFIG_SERIAL_SIRFSOC_CONSOLE=y
|
|
CONFIG_SERIAL_VT8500=y
|
|
CONFIG_SERIAL_VT8500_CONSOLE=y
|
|
+CONFIG_SERIAL_XILINX_PS_UART=y
|
|
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
|
|
CONFIG_IPMI_HANDLER=y
|
|
CONFIG_IPMI_SI=y
|
|
CONFIG_I2C=y
|
|
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
|
|
index bc5bc0a97131..4bc816a74a2e 100644
|
|
--- a/arch/arm/kernel/entry-common.S
|
|
+++ b/arch/arm/kernel/entry-common.S
|
|
@@ -362,6 +362,16 @@ ENTRY(vector_swi)
|
|
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
|
|
zero_fp
|
|
|
|
+#ifdef CONFIG_ALIGNMENT_TRAP
|
|
+ ldr ip, __cr_alignment
|
|
+ ldr ip, [ip]
|
|
+ mcr p15, 0, ip, c1, c0 @ update control register
|
|
+#endif
|
|
+
|
|
+ enable_irq
|
|
+ ct_user_exit
|
|
+ get_thread_info tsk
|
|
+
|
|
/*
|
|
* Get the system call number.
|
|
*/
|
|
@@ -375,9 +385,9 @@ ENTRY(vector_swi)
|
|
#ifdef CONFIG_ARM_THUMB
|
|
tst r8, #PSR_T_BIT
|
|
movne r10, #0 @ no thumb OABI emulation
|
|
- ldreq r10, [lr, #-4] @ get SWI instruction
|
|
+ USER( ldreq r10, [lr, #-4] ) @ get SWI instruction
|
|
#else
|
|
- ldr r10, [lr, #-4] @ get SWI instruction
|
|
+ USER( ldr r10, [lr, #-4] ) @ get SWI instruction
|
|
#endif
|
|
#ifdef CONFIG_CPU_ENDIAN_BE8
|
|
rev r10, r10 @ little endian instruction
|
|
@@ -392,22 +402,13 @@ ENTRY(vector_swi)
|
|
/* Legacy ABI only, possibly thumb mode. */
|
|
tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
|
|
addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
|
|
- ldreq scno, [lr, #-4]
|
|
+ USER( ldreq scno, [lr, #-4] )
|
|
|
|
#else
|
|
/* Legacy ABI only. */
|
|
- ldr scno, [lr, #-4] @ get SWI instruction
|
|
+ USER( ldr scno, [lr, #-4] ) @ get SWI instruction
|
|
#endif
|
|
|
|
-#ifdef CONFIG_ALIGNMENT_TRAP
|
|
- ldr ip, __cr_alignment
|
|
- ldr ip, [ip]
|
|
- mcr p15, 0, ip, c1, c0 @ update control register
|
|
-#endif
|
|
- enable_irq
|
|
- ct_user_exit
|
|
-
|
|
- get_thread_info tsk
|
|
adr tbl, sys_call_table @ load syscall table pointer
|
|
|
|
#if defined(CONFIG_OABI_COMPAT)
|
|
@@ -442,6 +443,21 @@ local_restart:
|
|
eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
|
|
bcs arm_syscall
|
|
b sys_ni_syscall @ not private func
|
|
+
|
|
+#if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI)
|
|
+ /*
|
|
+ * We failed to handle a fault trying to access the page
|
|
+ * containing the swi instruction, but we're not really in a
|
|
+ * position to return -EFAULT. Instead, return back to the
|
|
+ * instruction and re-enter the user fault handling path trying
|
|
+ * to page it in. This will likely result in sending SEGV to the
|
|
+ * current task.
|
|
+ */
|
|
+9001:
|
|
+ sub lr, lr, #4
|
|
+ str lr, [sp, #S_PC]
|
|
+ b ret_fast_syscall
|
|
+#endif
|
|
ENDPROC(vector_swi)
|
|
|
|
/*
|
|
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
|
|
index 9723d17b8f38..1e782bdeee49 100644
|
|
--- a/arch/arm/kernel/irq.c
|
|
+++ b/arch/arm/kernel/irq.c
|
|
@@ -163,7 +163,7 @@ static bool migrate_one_irq(struct irq_desc *desc)
|
|
c = irq_data_get_irq_chip(d);
|
|
if (!c->irq_set_affinity)
|
|
pr_debug("IRQ%u: unable to set affinity\n", d->irq);
|
|
- else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
|
|
+ else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
|
|
cpumask_copy(d->affinity, affinity);
|
|
|
|
return ret;
|
|
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
|
|
index c3ef920823b6..70ae735dec53 100644
|
|
--- a/arch/arm/kernel/machine_kexec.c
|
|
+++ b/arch/arm/kernel/machine_kexec.c
|
|
@@ -14,10 +14,11 @@
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/mmu_context.h>
|
|
#include <asm/cacheflush.h>
|
|
+#include <asm/fncpy.h>
|
|
#include <asm/mach-types.h>
|
|
#include <asm/system_misc.h>
|
|
|
|
-extern const unsigned char relocate_new_kernel[];
|
|
+extern void relocate_new_kernel(void);
|
|
extern const unsigned int relocate_new_kernel_size;
|
|
|
|
extern unsigned long kexec_start_address;
|
|
@@ -133,6 +134,8 @@ void machine_kexec(struct kimage *image)
|
|
{
|
|
unsigned long page_list;
|
|
unsigned long reboot_code_buffer_phys;
|
|
+ unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
|
|
+ unsigned long reboot_entry_phys;
|
|
void *reboot_code_buffer;
|
|
|
|
if (num_online_cpus() > 1) {
|
|
@@ -156,18 +159,18 @@ void machine_kexec(struct kimage *image)
|
|
|
|
|
|
/* copy our kernel relocation code to the control code page */
|
|
- memcpy(reboot_code_buffer,
|
|
- relocate_new_kernel, relocate_new_kernel_size);
|
|
+ reboot_entry = fncpy(reboot_code_buffer,
|
|
+ reboot_entry,
|
|
+ relocate_new_kernel_size);
|
|
+ reboot_entry_phys = (unsigned long)reboot_entry +
|
|
+ (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
|
|
|
|
-
|
|
- flush_icache_range((unsigned long) reboot_code_buffer,
|
|
- (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
|
|
printk(KERN_INFO "Bye!\n");
|
|
|
|
if (kexec_reinit)
|
|
kexec_reinit();
|
|
|
|
- soft_restart(reboot_code_buffer_phys);
|
|
+ soft_restart(reboot_entry_phys);
|
|
}
|
|
|
|
void arch_crash_save_vmcoreinfo(void)
|
|
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
|
|
index d0cdedf4864d..95858966d84e 100644
|
|
--- a/arch/arm/kernel/relocate_kernel.S
|
|
+++ b/arch/arm/kernel/relocate_kernel.S
|
|
@@ -2,10 +2,12 @@
|
|
* relocate_kernel.S - put the kernel image in place to boot
|
|
*/
|
|
|
|
+#include <linux/linkage.h>
|
|
#include <asm/kexec.h>
|
|
|
|
- .globl relocate_new_kernel
|
|
-relocate_new_kernel:
|
|
+ .align 3 /* not needed for this code, but keeps fncpy() happy */
|
|
+
|
|
+ENTRY(relocate_new_kernel)
|
|
|
|
ldr r0,kexec_indirection_page
|
|
ldr r1,kexec_start_address
|
|
@@ -79,6 +81,8 @@ kexec_mach_type:
|
|
kexec_boot_atags:
|
|
.long 0x0
|
|
|
|
+ENDPROC(relocate_new_kernel)
|
|
+
|
|
relocate_new_kernel_end:
|
|
|
|
.globl relocate_new_kernel_size
|
|
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
|
|
index 80741992a9fc..5d777a567c35 100644
|
|
--- a/arch/arm/mm/abort-ev6.S
|
|
+++ b/arch/arm/mm/abort-ev6.S
|
|
@@ -17,12 +17,6 @@
|
|
*/
|
|
.align 5
|
|
ENTRY(v6_early_abort)
|
|
-#ifdef CONFIG_CPU_V6
|
|
- sub r1, sp, #4 @ Get unused stack location
|
|
- strex r0, r1, [r1] @ Clear the exclusive monitor
|
|
-#elif defined(CONFIG_CPU_32v6K)
|
|
- clrex
|
|
-#endif
|
|
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
|
/*
|
|
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
|
|
index 703375277ba6..4812ad054214 100644
|
|
--- a/arch/arm/mm/abort-ev7.S
|
|
+++ b/arch/arm/mm/abort-ev7.S
|
|
@@ -13,12 +13,6 @@
|
|
*/
|
|
.align 5
|
|
ENTRY(v7_early_abort)
|
|
- /*
|
|
- * The effect of data aborts on on the exclusive access monitor are
|
|
- * UNPREDICTABLE. Do a CLREX to clear the state
|
|
- */
|
|
- clrex
|
|
-
|
|
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
|
|
|
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
|
|
index 6f4585b89078..1fe0bf5c7375 100644
|
|
--- a/arch/arm/mm/alignment.c
|
|
+++ b/arch/arm/mm/alignment.c
|
|
@@ -39,6 +39,7 @@
|
|
* This code is not portable to processors with late data abort handling.
|
|
*/
|
|
#define CODING_BITS(i) (i & 0x0e000000)
|
|
+#define COND_BITS(i) (i & 0xf0000000)
|
|
|
|
#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
|
|
#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
|
|
@@ -812,6 +813,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|
break;
|
|
|
|
case 0x04000000: /* ldr or str immediate */
|
|
+ if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
|
|
+ goto bad;
|
|
offset.un = OFFSET_BITS(instr);
|
|
handler = do_alignment_ldrstr;
|
|
break;
|
|
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
|
|
index d064047612b1..52b484b6aa1a 100644
|
|
--- a/arch/arm64/include/asm/hw_breakpoint.h
|
|
+++ b/arch/arm64/include/asm/hw_breakpoint.h
|
|
@@ -79,7 +79,6 @@ static inline void decode_ctrl_reg(u32 reg,
|
|
*/
|
|
#define ARM_MAX_BRP 16
|
|
#define ARM_MAX_WRP 16
|
|
-#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP)
|
|
|
|
/* Virtual debug register bases. */
|
|
#define AARCH64_DBG_REG_BVR 0
|
|
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
|
|
index 46f02c3b5015..0860fc3077fc 100644
|
|
--- a/arch/arm64/kernel/process.c
|
|
+++ b/arch/arm64/kernel/process.c
|
|
@@ -172,9 +172,27 @@ void exit_thread(void)
|
|
{
|
|
}
|
|
|
|
+static void tls_thread_flush(void)
|
|
+{
|
|
+ asm ("msr tpidr_el0, xzr");
|
|
+
|
|
+ if (is_compat_task()) {
|
|
+ current->thread.tp_value = 0;
|
|
+
|
|
+ /*
|
|
+ * We need to ensure ordering between the shadow state and the
|
|
+ * hardware state, so that we don't corrupt the hardware state
|
|
+ * with a stale shadow state during context switch.
|
|
+ */
|
|
+ barrier();
|
|
+ asm ("msr tpidrro_el0, xzr");
|
|
+ }
|
|
+}
|
|
+
|
|
void flush_thread(void)
|
|
{
|
|
fpsimd_flush_thread();
|
|
+ tls_thread_flush();
|
|
flush_ptrace_hw_breakpoint(current);
|
|
}
|
|
|
|
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
|
|
index 85536688f753..33a74fc45959 100644
|
|
--- a/arch/arm64/kernel/ptrace.c
|
|
+++ b/arch/arm64/kernel/ptrace.c
|
|
@@ -103,7 +103,8 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|
break;
|
|
}
|
|
}
|
|
- for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
|
|
+
|
|
+ for (i = 0; i < ARM_MAX_WRP; ++i) {
|
|
if (current->thread.debug.hbp_watch[i] == bp) {
|
|
info.si_errno = -((i << 1) + 1);
|
|
break;
|
|
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
|
|
index 26e9c4eeaba8..78039927c807 100644
|
|
--- a/arch/arm64/kernel/sys_compat.c
|
|
+++ b/arch/arm64/kernel/sys_compat.c
|
|
@@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs)
|
|
|
|
case __ARM_NR_compat_set_tls:
|
|
current->thread.tp_value = regs->regs[0];
|
|
+
|
|
+ /*
|
|
+ * Protect against register corruption from context switch.
|
|
+ * See comment in tls_thread_flush.
|
|
+ */
|
|
+ barrier();
|
|
asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0]));
|
|
return 0;
|
|
|
|
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
|
|
index 2c9573098c0d..d498a1f9bccf 100644
|
|
--- a/arch/mips/boot/compressed/decompress.c
|
|
+++ b/arch/mips/boot/compressed/decompress.c
|
|
@@ -13,6 +13,7 @@
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
+#include <linux/string.h>
|
|
|
|
#include <asm/addrspace.h>
|
|
|
|
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
|
|
index 33d067148e61..3efbf0b29c1b 100644
|
|
--- a/arch/mips/kernel/mcount.S
|
|
+++ b/arch/mips/kernel/mcount.S
|
|
@@ -123,7 +123,11 @@ NESTED(_mcount, PT_SIZE, ra)
|
|
nop
|
|
#endif
|
|
b ftrace_stub
|
|
+#ifdef CONFIG_32BIT
|
|
+ addiu sp, sp, 8
|
|
+#else
|
|
nop
|
|
+#endif
|
|
|
|
static_trace:
|
|
MCOUNT_SAVE_REGS
|
|
@@ -133,6 +137,9 @@ static_trace:
|
|
move a1, AT /* arg2: parent's return address */
|
|
|
|
MCOUNT_RESTORE_REGS
|
|
+#ifdef CONFIG_32BIT
|
|
+ addiu sp, sp, 8
|
|
+#endif
|
|
.globl ftrace_stub
|
|
ftrace_stub:
|
|
RETURN_BACK
|
|
@@ -181,6 +188,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
|
|
jal prepare_ftrace_return
|
|
nop
|
|
MCOUNT_RESTORE_REGS
|
|
+#ifndef CONFIG_DYNAMIC_FTRACE
|
|
+#ifdef CONFIG_32BIT
|
|
+ addiu sp, sp, 8
|
|
+#endif
|
|
+#endif
|
|
RETURN_BACK
|
|
END(ftrace_graph_caller)
|
|
|
|
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
|
|
index 96ec3982be8d..94607bfa273d 100644
|
|
--- a/arch/parisc/Makefile
|
|
+++ b/arch/parisc/Makefile
|
|
@@ -46,7 +46,12 @@ cflags-y := -pipe
|
|
|
|
# These flags should be implied by an hppa-linux configuration, but they
|
|
# are not in gcc 3.2.
|
|
-cflags-y += -mno-space-regs -mfast-indirect-calls
|
|
+cflags-y += -mno-space-regs
|
|
+
|
|
+# -mfast-indirect-calls is only relevant for 32-bit kernels.
|
|
+ifndef CONFIG_64BIT
|
|
+cflags-y += -mfast-indirect-calls
|
|
+endif
|
|
|
|
# Currently we save and restore fpregs on all kernel entry/interruption paths.
|
|
# If that gets optimized, we might need to disable the use of fpregs in the
|
|
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
|
|
index becc08e6a65c..637c97fcbeb5 100644
|
|
--- a/arch/powerpc/include/asm/ptrace.h
|
|
+++ b/arch/powerpc/include/asm/ptrace.h
|
|
@@ -35,6 +35,12 @@
|
|
STACK_FRAME_OVERHEAD + 288)
|
|
#define STACK_FRAME_MARKER 12
|
|
|
|
+#if defined(_CALL_ELF) && _CALL_ELF == 2
|
|
+#define STACK_FRAME_MIN_SIZE 32
|
|
+#else
|
|
+#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD
|
|
+#endif
|
|
+
|
|
/* Size of dummy stack frame allocated when calling signal handler. */
|
|
#define __SIGNAL_FRAMESIZE 128
|
|
#define __SIGNAL_FRAMESIZE32 64
|
|
@@ -46,6 +52,7 @@
|
|
#define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773)
|
|
#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
|
|
#define STACK_FRAME_MARKER 2
|
|
+#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD
|
|
|
|
/* Size of stack frame allocated when calling signal handler. */
|
|
#define __SIGNAL_FRAMESIZE 64
|
|
diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c
|
|
index 74d1e780748b..2396dda282cd 100644
|
|
--- a/arch/powerpc/perf/callchain.c
|
|
+++ b/arch/powerpc/perf/callchain.c
|
|
@@ -35,7 +35,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp)
|
|
return 0; /* must be 16-byte aligned */
|
|
if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
|
|
return 0;
|
|
- if (sp >= prev_sp + STACK_FRAME_OVERHEAD)
|
|
+ if (sp >= prev_sp + STACK_FRAME_MIN_SIZE)
|
|
return 1;
|
|
/*
|
|
* sp could decrease when we jump off an interrupt stack
|
|
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
|
|
index 0dc7d9e21c34..9d7d36c82fc2 100644
|
|
--- a/arch/x86/include/asm/fixmap.h
|
|
+++ b/arch/x86/include/asm/fixmap.h
|
|
@@ -123,14 +123,14 @@ enum fixed_addresses {
|
|
__end_of_permanent_fixed_addresses,
|
|
|
|
/*
|
|
- * 256 temporary boot-time mappings, used by early_ioremap(),
|
|
+ * 512 temporary boot-time mappings, used by early_ioremap(),
|
|
* before ioremap() is functional.
|
|
*
|
|
- * If necessary we round it up to the next 256 pages boundary so
|
|
+ * If necessary we round it up to the next 512 pages boundary so
|
|
* that we can have a single pgd entry and a single pte table:
|
|
*/
|
|
#define NR_FIX_BTMAPS 64
|
|
-#define FIX_BTMAPS_SLOTS 4
|
|
+#define FIX_BTMAPS_SLOTS 8
|
|
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
|
FIX_BTMAP_END =
|
|
(__end_of_permanent_fixed_addresses ^
|
|
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
|
|
index fe862750583b..87084ab90d19 100644
|
|
--- a/arch/x86/kernel/smpboot.c
|
|
+++ b/arch/x86/kernel/smpboot.c
|
|
@@ -1284,6 +1284,9 @@ static void remove_siblinginfo(int cpu)
|
|
|
|
for_each_cpu(sibling, cpu_sibling_mask(cpu))
|
|
cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling));
|
|
+ for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
|
|
+ cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling));
|
|
+ cpumask_clear(cpu_llc_shared_mask(cpu));
|
|
cpumask_clear(cpu_sibling_mask(cpu));
|
|
cpumask_clear(cpu_core_mask(cpu));
|
|
c->phys_proc_id = 0;
|
|
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
index 1be0a9e75d1f..e8753555f144 100644
|
|
--- a/arch/x86/kvm/x86.c
|
|
+++ b/arch/x86/kvm/x86.c
|
|
@@ -1196,20 +1196,37 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|
elapsed = ns - kvm->arch.last_tsc_nsec;
|
|
|
|
if (vcpu->arch.virtual_tsc_khz) {
|
|
+ int faulted = 0;
|
|
+
|
|
/* n.b - signed multiplication and division required */
|
|
usdiff = data - kvm->arch.last_tsc_write;
|
|
#ifdef CONFIG_X86_64
|
|
usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz;
|
|
#else
|
|
/* do_div() only does unsigned */
|
|
- asm("idivl %2; xor %%edx, %%edx"
|
|
- : "=A"(usdiff)
|
|
- : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz));
|
|
+ asm("1: idivl %[divisor]\n"
|
|
+ "2: xor %%edx, %%edx\n"
|
|
+ " movl $0, %[faulted]\n"
|
|
+ "3:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ "4: movl $1, %[faulted]\n"
|
|
+ " jmp 3b\n"
|
|
+ ".previous\n"
|
|
+
|
|
+ _ASM_EXTABLE(1b, 4b)
|
|
+
|
|
+ : "=A"(usdiff), [faulted] "=r" (faulted)
|
|
+ : "A"(usdiff * 1000), [divisor] "rm"(vcpu->arch.virtual_tsc_khz));
|
|
+
|
|
#endif
|
|
do_div(elapsed, 1000);
|
|
usdiff -= elapsed;
|
|
if (usdiff < 0)
|
|
usdiff = -usdiff;
|
|
+
|
|
+ /* idivl overflow => difference is larger than USEC_PER_SEC */
|
|
+ if (faulted)
|
|
+ usdiff = USEC_PER_SEC;
|
|
} else
|
|
usdiff = USEC_PER_SEC; /* disable TSC match window below */
|
|
|
|
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
|
|
index d7546c94da52..385efb23ddce 100644
|
|
--- a/arch/xtensa/include/asm/pgtable.h
|
|
+++ b/arch/xtensa/include/asm/pgtable.h
|
|
@@ -68,7 +68,12 @@
|
|
#define VMALLOC_START 0xC0000000
|
|
#define VMALLOC_END 0xC7FEFFFF
|
|
#define TLBTEMP_BASE_1 0xC7FF0000
|
|
-#define TLBTEMP_BASE_2 0xC7FF8000
|
|
+#define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
|
|
+#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
|
|
+#define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE)
|
|
+#else
|
|
+#define TLBTEMP_SIZE ICACHE_WAY_SIZE
|
|
+#endif
|
|
|
|
/*
|
|
* Xtensa Linux config PTE layout (when present):
|
|
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
|
|
index fd686dc45d1a..c7211e7e182d 100644
|
|
--- a/arch/xtensa/include/asm/uaccess.h
|
|
+++ b/arch/xtensa/include/asm/uaccess.h
|
|
@@ -52,7 +52,12 @@
|
|
*/
|
|
.macro get_fs ad, sp
|
|
GET_CURRENT(\ad,\sp)
|
|
+#if THREAD_CURRENT_DS > 1020
|
|
+ addi \ad, \ad, TASK_THREAD
|
|
+ l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD
|
|
+#else
|
|
l32i \ad, \ad, THREAD_CURRENT_DS
|
|
+#endif
|
|
.endm
|
|
|
|
/*
|
|
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
|
|
index b4cb1100c0fb..a47909f0c34b 100644
|
|
--- a/arch/xtensa/include/uapi/asm/ioctls.h
|
|
+++ b/arch/xtensa/include/uapi/asm/ioctls.h
|
|
@@ -28,17 +28,17 @@
|
|
#define TCSETSW 0x5403
|
|
#define TCSETSF 0x5404
|
|
|
|
-#define TCGETA _IOR('t', 23, struct termio)
|
|
-#define TCSETA _IOW('t', 24, struct termio)
|
|
-#define TCSETAW _IOW('t', 25, struct termio)
|
|
-#define TCSETAF _IOW('t', 28, struct termio)
|
|
+#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */
|
|
+#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */
|
|
+#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */
|
|
+#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */
|
|
|
|
#define TCSBRK _IO('t', 29)
|
|
#define TCXONC _IO('t', 30)
|
|
#define TCFLSH _IO('t', 31)
|
|
|
|
-#define TIOCSWINSZ _IOW('t', 103, struct winsize)
|
|
-#define TIOCGWINSZ _IOR('t', 104, struct winsize)
|
|
+#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */
|
|
+#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */
|
|
#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
|
|
#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
|
|
#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
|
|
@@ -88,7 +88,6 @@
|
|
#define TIOCSETD _IOW('T', 35, int)
|
|
#define TIOCGETD _IOR('T', 36, int)
|
|
#define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/
|
|
-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
|
|
#define TIOCSBRK _IO('T', 39) /* BSD compatibility */
|
|
#define TIOCCBRK _IO('T', 40) /* BSD compatibility */
|
|
#define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/
|
|
@@ -114,8 +113,10 @@
|
|
#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */
|
|
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
|
# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */
|
|
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
|
|
+#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */
|
|
+ /* _IOR('T', 90, struct serial_multiport_struct) */
|
|
+#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */
|
|
+ /* _IOW('T', 91, struct serial_multiport_struct) */
|
|
|
|
#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
|
|
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
|
|
index aa7f9add7d77..6e53174f8556 100644
|
|
--- a/arch/xtensa/kernel/entry.S
|
|
+++ b/arch/xtensa/kernel/entry.S
|
|
@@ -1121,9 +1121,8 @@ ENTRY(fast_syscall_xtensa)
|
|
movi a7, 4 # sizeof(unsigned int)
|
|
access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
|
|
|
|
- addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1
|
|
- _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill
|
|
- _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
|
|
+ _bgeui a6, SYS_XTENSA_COUNT, .Lill
|
|
+ _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp
|
|
|
|
/* Fall through for ATOMIC_CMP_SWP. */
|
|
|
|
@@ -1135,27 +1134,26 @@ TRY s32i a5, a3, 0 # different, modify value
|
|
l32i a7, a2, PT_AREG7 # restore a7
|
|
l32i a0, a2, PT_AREG0 # restore a0
|
|
movi a2, 1 # and return 1
|
|
- addi a6, a6, 1 # restore a6 (really necessary?)
|
|
rfe
|
|
|
|
1: l32i a7, a2, PT_AREG7 # restore a7
|
|
l32i a0, a2, PT_AREG0 # restore a0
|
|
movi a2, 0 # return 0 (note that we cannot set
|
|
- addi a6, a6, 1 # restore a6 (really necessary?)
|
|
rfe
|
|
|
|
.Lnswp: /* Atomic set, add, and exg_add. */
|
|
|
|
TRY l32i a7, a3, 0 # orig
|
|
+ addi a6, a6, -SYS_XTENSA_ATOMIC_SET
|
|
add a0, a4, a7 # + arg
|
|
moveqz a0, a4, a6 # set
|
|
+ addi a6, a6, SYS_XTENSA_ATOMIC_SET
|
|
TRY s32i a0, a3, 0 # write new value
|
|
|
|
mov a0, a2
|
|
mov a2, a7
|
|
l32i a7, a0, PT_AREG7 # restore a7
|
|
l32i a0, a0, PT_AREG0 # restore a0
|
|
- addi a6, a6, 1 # restore a6 (really necessary?)
|
|
rfe
|
|
|
|
CATCH
|
|
@@ -1164,7 +1162,7 @@ CATCH
|
|
movi a2, -EFAULT
|
|
rfe
|
|
|
|
-.Lill: l32i a7, a2, PT_AREG0 # restore a7
|
|
+.Lill: l32i a7, a2, PT_AREG7 # restore a7
|
|
l32i a0, a2, PT_AREG0 # restore a0
|
|
movi a2, -EINVAL
|
|
rfe
|
|
@@ -1703,7 +1701,7 @@ ENTRY(fast_second_level_miss)
|
|
rsr a0, excvaddr
|
|
bltu a0, a3, 2f
|
|
|
|
- addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
|
|
+ addi a1, a0, -TLBTEMP_SIZE
|
|
bgeu a1, a3, 2f
|
|
|
|
/* Check if we have to restore an ITLB mapping. */
|
|
@@ -1961,7 +1959,6 @@ ENTRY(_switch_to)
|
|
|
|
entry a1, 16
|
|
|
|
- mov a10, a2 # preserve 'prev' (a2)
|
|
mov a11, a3 # and 'next' (a3)
|
|
|
|
l32i a4, a2, TASK_THREAD_INFO
|
|
@@ -1969,8 +1966,14 @@ ENTRY(_switch_to)
|
|
|
|
save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
|
|
|
|
- s32i a0, a10, THREAD_RA # save return address
|
|
- s32i a1, a10, THREAD_SP # save stack pointer
|
|
+#if THREAD_RA > 1020 || THREAD_SP > 1020
|
|
+ addi a10, a2, TASK_THREAD
|
|
+ s32i a0, a10, THREAD_RA - TASK_THREAD # save return address
|
|
+ s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer
|
|
+#else
|
|
+ s32i a0, a2, THREAD_RA # save return address
|
|
+ s32i a1, a2, THREAD_SP # save stack pointer
|
|
+#endif
|
|
|
|
/* Disable ints while we manipulate the stack pointer. */
|
|
|
|
@@ -2011,7 +2014,6 @@ ENTRY(_switch_to)
|
|
load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
|
|
|
|
wsr a14, ps
|
|
- mov a2, a10 # return 'prev'
|
|
rsync
|
|
|
|
retw
|
|
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
|
|
index 2d9cc6dbfd78..e8b76b8e4b29 100644
|
|
--- a/arch/xtensa/kernel/pci-dma.c
|
|
+++ b/arch/xtensa/kernel/pci-dma.c
|
|
@@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
|
|
|
|
/* We currently don't support coherent memory outside KSEG */
|
|
|
|
- if (ret < XCHAL_KSEG_CACHED_VADDR
|
|
- || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
|
|
- BUG();
|
|
+ BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
|
|
+ ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
|
|
|
|
|
|
if (ret != 0) {
|
|
@@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent);
|
|
void dma_free_coherent(struct device *hwdev, size_t size,
|
|
void *vaddr, dma_addr_t dma_handle)
|
|
{
|
|
- long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
|
|
+ unsigned long addr = (unsigned long)vaddr +
|
|
+ XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
|
|
|
|
- if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
|
|
- BUG();
|
|
+ BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR ||
|
|
+ addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
|
|
|
|
free_pages(addr, get_order(size));
|
|
}
|
|
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
|
|
index c410752c5c65..c981097dd634 100644
|
|
--- a/block/cfq-iosched.c
|
|
+++ b/block/cfq-iosched.c
|
|
@@ -1275,12 +1275,16 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|
static void
|
|
cfq_update_group_weight(struct cfq_group *cfqg)
|
|
{
|
|
- BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
|
-
|
|
if (cfqg->new_weight) {
|
|
cfqg->weight = cfqg->new_weight;
|
|
cfqg->new_weight = 0;
|
|
}
|
|
+}
|
|
+
|
|
+static void
|
|
+cfq_update_group_leaf_weight(struct cfq_group *cfqg)
|
|
+{
|
|
+ BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
|
|
|
if (cfqg->new_leaf_weight) {
|
|
cfqg->leaf_weight = cfqg->new_leaf_weight;
|
|
@@ -1299,7 +1303,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|
/* add to the service tree */
|
|
BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
|
|
|
- cfq_update_group_weight(cfqg);
|
|
+ cfq_update_group_leaf_weight(cfqg);
|
|
__cfq_group_service_tree_add(st, cfqg);
|
|
|
|
/*
|
|
@@ -1323,6 +1327,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|
*/
|
|
while ((parent = cfqg_parent(pos))) {
|
|
if (propagate) {
|
|
+ cfq_update_group_weight(pos);
|
|
propagate = !parent->nr_active++;
|
|
parent->children_weight += pos->weight;
|
|
}
|
|
diff --git a/block/genhd.c b/block/genhd.c
|
|
index cdeb5277dfd4..e670148c3773 100644
|
|
--- a/block/genhd.c
|
|
+++ b/block/genhd.c
|
|
@@ -28,10 +28,10 @@ struct kobject *block_depr;
|
|
/* for extended dynamic devt allocation, currently only one major is used */
|
|
#define NR_EXT_DEVT (1 << MINORBITS)
|
|
|
|
-/* For extended devt allocation. ext_devt_mutex prevents look up
|
|
+/* For extended devt allocation. ext_devt_lock prevents look up
|
|
* results from going away underneath its user.
|
|
*/
|
|
-static DEFINE_MUTEX(ext_devt_mutex);
|
|
+static DEFINE_SPINLOCK(ext_devt_lock);
|
|
static DEFINE_IDR(ext_devt_idr);
|
|
|
|
static struct device_type disk_type;
|
|
@@ -420,9 +420,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
|
|
}
|
|
|
|
/* allocate ext devt */
|
|
- mutex_lock(&ext_devt_mutex);
|
|
- idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL);
|
|
- mutex_unlock(&ext_devt_mutex);
|
|
+ idr_preload(GFP_KERNEL);
|
|
+
|
|
+ spin_lock(&ext_devt_lock);
|
|
+ idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT);
|
|
+ spin_unlock(&ext_devt_lock);
|
|
+
|
|
+ idr_preload_end();
|
|
if (idx < 0)
|
|
return idx == -ENOSPC ? -EBUSY : idx;
|
|
|
|
@@ -441,15 +445,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
|
|
*/
|
|
void blk_free_devt(dev_t devt)
|
|
{
|
|
- might_sleep();
|
|
-
|
|
if (devt == MKDEV(0, 0))
|
|
return;
|
|
|
|
if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
|
|
- mutex_lock(&ext_devt_mutex);
|
|
+ spin_lock(&ext_devt_lock);
|
|
idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
|
|
- mutex_unlock(&ext_devt_mutex);
|
|
+ spin_unlock(&ext_devt_lock);
|
|
}
|
|
}
|
|
|
|
@@ -665,7 +667,6 @@ void del_gendisk(struct gendisk *disk)
|
|
sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
|
|
pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
|
|
device_del(disk_to_dev(disk));
|
|
- blk_free_devt(disk_to_dev(disk)->devt);
|
|
}
|
|
EXPORT_SYMBOL(del_gendisk);
|
|
|
|
@@ -690,13 +691,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
|
|
} else {
|
|
struct hd_struct *part;
|
|
|
|
- mutex_lock(&ext_devt_mutex);
|
|
+ spin_lock(&ext_devt_lock);
|
|
part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
|
|
if (part && get_disk(part_to_disk(part))) {
|
|
*partno = part->partno;
|
|
disk = part_to_disk(part);
|
|
}
|
|
- mutex_unlock(&ext_devt_mutex);
|
|
+ spin_unlock(&ext_devt_lock);
|
|
}
|
|
|
|
return disk;
|
|
@@ -1098,6 +1099,7 @@ static void disk_release(struct device *dev)
|
|
{
|
|
struct gendisk *disk = dev_to_disk(dev);
|
|
|
|
+ blk_free_devt(dev->devt);
|
|
disk_release_events(disk);
|
|
kfree(disk->random);
|
|
disk_replace_part_tbl(disk, NULL);
|
|
diff --git a/block/partition-generic.c b/block/partition-generic.c
|
|
index 789cdea05893..0d9e5f97f0a8 100644
|
|
--- a/block/partition-generic.c
|
|
+++ b/block/partition-generic.c
|
|
@@ -211,6 +211,7 @@ static const struct attribute_group *part_attr_groups[] = {
|
|
static void part_release(struct device *dev)
|
|
{
|
|
struct hd_struct *p = dev_to_part(dev);
|
|
+ blk_free_devt(dev->devt);
|
|
free_part_stats(p);
|
|
free_part_info(p);
|
|
kfree(p);
|
|
@@ -253,7 +254,6 @@ void delete_partition(struct gendisk *disk, int partno)
|
|
rcu_assign_pointer(ptbl->last_lookup, NULL);
|
|
kobject_put(part->holder_dir);
|
|
device_del(part_to_dev(part));
|
|
- blk_free_devt(part_devt(part));
|
|
|
|
hd_struct_put(part);
|
|
}
|
|
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
|
|
index d5bfbd331bfd..95896886fc5a 100644
|
|
--- a/drivers/acpi/acpica/aclocal.h
|
|
+++ b/drivers/acpi/acpica/aclocal.h
|
|
@@ -254,6 +254,7 @@ struct acpi_create_field_info {
|
|
u32 field_bit_position;
|
|
u32 field_bit_length;
|
|
u16 resource_length;
|
|
+ u16 pin_number_index;
|
|
u8 field_flags;
|
|
u8 attribute;
|
|
u8 field_type;
|
|
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
|
|
index cc7ab6dd724e..a47cc78ffd4f 100644
|
|
--- a/drivers/acpi/acpica/acobject.h
|
|
+++ b/drivers/acpi/acpica/acobject.h
|
|
@@ -263,6 +263,7 @@ struct acpi_object_region_field {
|
|
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
|
|
union acpi_operand_object *region_obj; /* Containing op_region object */
|
|
u8 *resource_buffer; /* resource_template for serial regions/fields */
|
|
+ u16 pin_number_index; /* Index relative to previous Connection/Template */
|
|
};
|
|
|
|
struct acpi_object_bank_field {
|
|
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
|
|
index feadeed1012d..e651d4ec7c4c 100644
|
|
--- a/drivers/acpi/acpica/dsfield.c
|
|
+++ b/drivers/acpi/acpica/dsfield.c
|
|
@@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
|
|
*/
|
|
info->resource_buffer = NULL;
|
|
info->connection_node = NULL;
|
|
+ info->pin_number_index = 0;
|
|
|
|
/*
|
|
* A Connection() is either an actual resource descriptor (buffer)
|
|
@@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
|
|
}
|
|
|
|
info->field_bit_position += info->field_bit_length;
|
|
+ info->pin_number_index++; /* Index relative to previous Connection() */
|
|
break;
|
|
|
|
default:
|
|
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
|
|
index 6555e350fc1f..8fab9262d98a 100644
|
|
--- a/drivers/acpi/acpica/evregion.c
|
|
+++ b/drivers/acpi/acpica/evregion.c
|
|
@@ -141,6 +141,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|
union acpi_operand_object *region_obj2;
|
|
void *region_context = NULL;
|
|
struct acpi_connection_info *context;
|
|
+ acpi_physical_address address;
|
|
|
|
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
|
|
|
|
@@ -235,25 +236,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|
/* We have everything we need, we can invoke the address space handler */
|
|
|
|
handler = handler_desc->address_space.handler;
|
|
-
|
|
- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
|
|
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
|
|
- ®ion_obj->region.handler->address_space, handler,
|
|
- ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
|
|
- region_offset),
|
|
- acpi_ut_get_region_name(region_obj->region.
|
|
- space_id)));
|
|
+ address = (region_obj->region.address + region_offset);
|
|
|
|
/*
|
|
* Special handling for generic_serial_bus and general_purpose_io:
|
|
* There are three extra parameters that must be passed to the
|
|
* handler via the context:
|
|
- * 1) Connection buffer, a resource template from Connection() op.
|
|
- * 2) Length of the above buffer.
|
|
- * 3) Actual access length from the access_as() op.
|
|
+ * 1) Connection buffer, a resource template from Connection() op
|
|
+ * 2) Length of the above buffer
|
|
+ * 3) Actual access length from the access_as() op
|
|
+ *
|
|
+ * In addition, for general_purpose_io, the Address and bit_width fields
|
|
+ * are defined as follows:
|
|
+ * 1) Address is the pin number index of the field (bit offset from
|
|
+ * the previous Connection)
|
|
+ * 2) bit_width is the actual bit length of the field (number of pins)
|
|
*/
|
|
- if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
|
|
- (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
|
|
+ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
|
|
context && field_obj) {
|
|
|
|
/* Get the Connection (resource_template) buffer */
|
|
@@ -262,6 +261,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|
context->length = field_obj->field.resource_length;
|
|
context->access_length = field_obj->field.access_length;
|
|
}
|
|
+ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
|
|
+ context && field_obj) {
|
|
+
|
|
+ /* Get the Connection (resource_template) buffer */
|
|
+
|
|
+ context->connection = field_obj->field.resource_buffer;
|
|
+ context->length = field_obj->field.resource_length;
|
|
+ context->access_length = field_obj->field.access_length;
|
|
+ address = field_obj->field.pin_number_index;
|
|
+ bit_width = field_obj->field.bit_length;
|
|
+ }
|
|
+
|
|
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
|
|
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
|
|
+ ®ion_obj->region.handler->address_space, handler,
|
|
+ ACPI_FORMAT_NATIVE_UINT(address),
|
|
+ acpi_ut_get_region_name(region_obj->region.
|
|
+ space_id)));
|
|
|
|
if (!(handler_desc->address_space.handler_flags &
|
|
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
|
|
@@ -275,9 +292,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|
|
|
/* Call the handler */
|
|
|
|
- status = handler(function,
|
|
- (region_obj->region.address + region_offset),
|
|
- bit_width, value, context,
|
|
+ status = handler(function, address, bit_width, value, context,
|
|
region_obj2->extra.region_context);
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
|
|
index 7d4bae71e8c6..0108d59665ab 100644
|
|
--- a/drivers/acpi/acpica/exfield.c
|
|
+++ b/drivers/acpi/acpica/exfield.c
|
|
@@ -178,6 +178,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|
buffer = &buffer_desc->integer.value;
|
|
}
|
|
|
|
+ if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
|
+ (obj_desc->field.region_obj->region.space_id ==
|
|
+ ACPI_ADR_SPACE_GPIO)) {
|
|
+ /*
|
|
+ * For GPIO (general_purpose_io), the Address will be the bit offset
|
|
+ * from the previous Connection() operator, making it effectively a
|
|
+ * pin number index. The bit_length is the length of the field, which
|
|
+ * is thus the number of pins.
|
|
+ */
|
|
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
|
+ "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
|
|
+ obj_desc->field.pin_number_index,
|
|
+ obj_desc->field.bit_length));
|
|
+
|
|
+ /* Lock entire transaction if requested */
|
|
+
|
|
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
|
+
|
|
+ /* Perform the write */
|
|
+
|
|
+ status = acpi_ex_access_region(obj_desc, 0,
|
|
+ (u64 *)buffer, ACPI_READ);
|
|
+ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ acpi_ut_remove_reference(buffer_desc);
|
|
+ } else {
|
|
+ *ret_buffer_desc = buffer_desc;
|
|
+ }
|
|
+ return_ACPI_STATUS(status);
|
|
+ }
|
|
+
|
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
|
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
|
obj_desc, obj_desc->common.type, buffer,
|
|
@@ -325,6 +356,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|
|
|
*result_desc = buffer_desc;
|
|
return_ACPI_STATUS(status);
|
|
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
|
+ (obj_desc->field.region_obj->region.space_id ==
|
|
+ ACPI_ADR_SPACE_GPIO)) {
|
|
+ /*
|
|
+ * For GPIO (general_purpose_io), we will bypass the entire field
|
|
+ * mechanism and handoff the bit address and bit width directly to
|
|
+ * the handler. The Address will be the bit offset
|
|
+ * from the previous Connection() operator, making it effectively a
|
|
+ * pin number index. The bit_length is the length of the field, which
|
|
+ * is thus the number of pins.
|
|
+ */
|
|
+ if (source_desc->common.type != ACPI_TYPE_INTEGER) {
|
|
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
|
+ }
|
|
+
|
|
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
|
+ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
|
|
+ acpi_ut_get_type_name(source_desc->common.
|
|
+ type),
|
|
+ source_desc->common.type,
|
|
+ (u32)source_desc->integer.value,
|
|
+ obj_desc->field.pin_number_index,
|
|
+ obj_desc->field.bit_length));
|
|
+
|
|
+ buffer = &source_desc->integer.value;
|
|
+
|
|
+ /* Lock entire transaction if requested */
|
|
+
|
|
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
|
+
|
|
+ /* Perform the write */
|
|
+
|
|
+ status = acpi_ex_access_region(obj_desc, 0,
|
|
+ (u64 *)buffer, ACPI_WRITE);
|
|
+ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
+ return_ACPI_STATUS(status);
|
|
}
|
|
|
|
/* Get a pointer to the data to be written */
|
|
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
|
|
index 6b728aef2dca..df212fe4cf6c 100644
|
|
--- a/drivers/acpi/acpica/exprep.c
|
|
+++ b/drivers/acpi/acpica/exprep.c
|
|
@@ -479,6 +479,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
|
|
obj_desc->field.resource_length = info->resource_length;
|
|
}
|
|
|
|
+ obj_desc->field.pin_number_index = info->pin_number_index;
|
|
+
|
|
/* Allow full data read from EC address space */
|
|
|
|
if ((obj_desc->field.region_obj->region.space_id ==
|
|
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
|
|
index 3b39687c6336..c3f09505f795 100644
|
|
--- a/drivers/ata/ahci.c
|
|
+++ b/drivers/ata/ahci.c
|
|
@@ -304,6 +304,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|
{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
|
|
{ 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, 0x8c84), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
|
|
|
|
/* 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,
|
|
@@ -441,6 +449,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
|
|
.driver_data = board_ahci_yes_fbs }, /* 88se9172 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
|
|
+ .driver_data = board_ahci_yes_fbs }, /* 88se9182 */
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
|
|
.driver_data = board_ahci_yes_fbs }, /* 88se9172 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
|
|
.driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */
|
|
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
|
|
index b92913a528b6..82aa7b550ea5 100644
|
|
--- a/drivers/ata/ata_piix.c
|
|
+++ b/drivers/ata/ata_piix.c
|
|
@@ -340,6 +340,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
|
|
{ 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
|
|
/* SATA Controller IDE (Coleto Creek) */
|
|
{ 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
|
|
+ /* SATA Controller IDE (9 Series) */
|
|
+ { 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
|
|
+ /* SATA Controller IDE (9 Series) */
|
|
+ { 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
|
|
+ /* SATA Controller IDE (9 Series) */
|
|
+ { 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
|
|
+ /* SATA Controller IDE (9 Series) */
|
|
+ { 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
|
|
|
|
{ } /* terminate list */
|
|
};
|
|
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
|
|
index f35f15f4d83e..f7badaa39eb6 100644
|
|
--- a/drivers/ata/pata_scc.c
|
|
+++ b/drivers/ata/pata_scc.c
|
|
@@ -586,7 +586,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
|
|
* Note: Original code is ata_bus_softreset().
|
|
*/
|
|
|
|
-static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
|
+static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
|
unsigned long deadline)
|
|
{
|
|
struct ata_ioports *ioaddr = &ap->ioaddr;
|
|
@@ -600,9 +600,7 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
|
udelay(20);
|
|
out_be32(ioaddr->ctl_addr, ap->ctl);
|
|
|
|
- scc_wait_after_reset(&ap->link, devmask, deadline);
|
|
-
|
|
- return 0;
|
|
+ return scc_wait_after_reset(&ap->link, devmask, deadline);
|
|
}
|
|
|
|
/**
|
|
@@ -619,7 +617,8 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes,
|
|
{
|
|
struct ata_port *ap = link->ap;
|
|
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
|
|
- unsigned int devmask = 0, err_mask;
|
|
+ unsigned int devmask = 0;
|
|
+ int rc;
|
|
u8 err;
|
|
|
|
DPRINTK("ENTER\n");
|
|
@@ -635,9 +634,9 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes,
|
|
|
|
/* issue bus reset */
|
|
DPRINTK("about to softreset, devmask=%x\n", devmask);
|
|
- err_mask = scc_bus_softreset(ap, devmask, deadline);
|
|
- if (err_mask) {
|
|
- ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask);
|
|
+ rc = scc_bus_softreset(ap, devmask, deadline);
|
|
+ if (rc) {
|
|
+ ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc);
|
|
return -EIO;
|
|
}
|
|
|
|
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
|
|
index d0c81d1f409c..4b5cf2e34e9a 100644
|
|
--- a/drivers/base/regmap/regmap.c
|
|
+++ b/drivers/base/regmap/regmap.c
|
|
@@ -114,7 +114,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
|
|
|
|
bool regmap_volatile(struct regmap *map, unsigned int reg)
|
|
{
|
|
- if (!regmap_readable(map, reg))
|
|
+ if (!map->format.format_write && !regmap_readable(map, reg))
|
|
return false;
|
|
|
|
if (map->volatile_reg)
|
|
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
|
|
index f60fd7bd1183..96f874a508e2 100644
|
|
--- a/drivers/gpu/drm/ast/ast_main.c
|
|
+++ b/drivers/gpu/drm/ast/ast_main.c
|
|
@@ -100,7 +100,7 @@ static int ast_detect_chip(struct drm_device *dev)
|
|
}
|
|
ast->vga2_clone = false;
|
|
} else {
|
|
- ast->chip = 2000;
|
|
+ ast->chip = AST2000;
|
|
DRM_INFO("AST 2000 detected\n");
|
|
}
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
|
|
index 95070b2124c6..49acec155046 100644
|
|
--- a/drivers/gpu/drm/i915/intel_bios.c
|
|
+++ b/drivers/gpu/drm/i915/intel_bios.c
|
|
@@ -657,7 +657,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
|
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
|
|
}
|
|
|
|
-static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
|
|
+static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
|
|
{
|
|
DRM_DEBUG_KMS("Falling back to manually reading VBT from "
|
|
"VBIOS ROM for %s\n",
|
|
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
|
|
index 4a809969c5ac..53435a9d847e 100644
|
|
--- a/drivers/gpu/drm/i915/intel_crt.c
|
|
+++ b/drivers/gpu/drm/i915/intel_crt.c
|
|
@@ -702,7 +702,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
|
.destroy = intel_encoder_destroy,
|
|
};
|
|
|
|
-static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
|
|
+static int intel_no_crt_dmi_callback(const struct dmi_system_id *id)
|
|
{
|
|
DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
|
|
return 1;
|
|
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
|
|
index f77d42f74427..08e8e18b3f85 100644
|
|
--- a/drivers/gpu/drm/i915/intel_lvds.c
|
|
+++ b/drivers/gpu/drm/i915/intel_lvds.c
|
|
@@ -694,7 +694,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
|
|
.destroy = intel_encoder_destroy,
|
|
};
|
|
|
|
-static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
|
|
+static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
|
|
{
|
|
DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
|
|
return 1;
|
|
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
index 629527d205de..4605c3877c95 100644
|
|
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
@@ -396,6 +396,9 @@ static int init_ring_common(struct intel_ring_buffer *ring)
|
|
}
|
|
}
|
|
|
|
+ /* Enforce ordering by reading HEAD register back */
|
|
+ I915_READ_HEAD(ring);
|
|
+
|
|
/* Initialize the ring. This must happen _after_ we've cleared the ring
|
|
* registers with the above sequence (the readback of the HEAD registers
|
|
* also enforces ordering), otherwise the hw might lose the new ring
|
|
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
|
|
index a202d8d08c56..7c4e3126df27 100644
|
|
--- a/drivers/gpu/drm/i915/intel_tv.c
|
|
+++ b/drivers/gpu/drm/i915/intel_tv.c
|
|
@@ -856,6 +856,10 @@ intel_enable_tv(struct intel_encoder *encoder)
|
|
struct drm_device *dev = encoder->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ /* Prevents vblank waits from timing out in intel_tv_detect_type() */
|
|
+ intel_wait_for_vblank(encoder->base.dev,
|
|
+ to_intel_crtc(encoder->base.crtc)->pipe);
|
|
+
|
|
I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
index efb06e34aed7..ba2ab9a9b988 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
@@ -463,6 +463,13 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
|
|
}
|
|
}
|
|
|
|
+ /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */
|
|
+ if ((dev->pdev->device == 0x9805) &&
|
|
+ (dev->pdev->subsystem_vendor == 0x1734) &&
|
|
+ (dev->pdev->subsystem_device == 0x11bd)) {
|
|
+ if (*connector_type == DRM_MODE_CONNECTOR_VGA)
|
|
+ return false;
|
|
+ }
|
|
|
|
return true;
|
|
}
|
|
@@ -1908,7 +1915,7 @@ static const char *thermal_controller_names[] = {
|
|
"adm1032",
|
|
"adm1030",
|
|
"max6649",
|
|
- "lm64",
|
|
+ "lm63", /* lm64 */
|
|
"f75375",
|
|
"asc7xxx",
|
|
};
|
|
@@ -1919,7 +1926,7 @@ static const char *pp_lib_thermal_controller_names[] = {
|
|
"adm1032",
|
|
"adm1030",
|
|
"max6649",
|
|
- "lm64",
|
|
+ "lm63", /* lm64 */
|
|
"f75375",
|
|
"RV6xx",
|
|
"RV770",
|
|
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
|
|
index 2b5461bcd9fb..f060b7487c34 100644
|
|
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
|
|
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
|
|
@@ -116,6 +116,7 @@ static int tilcdc_unload(struct drm_device *dev)
|
|
struct tilcdc_drm_private *priv = dev->dev_private;
|
|
struct tilcdc_module *mod, *cur;
|
|
|
|
+ drm_fbdev_cma_fini(priv->fbdev);
|
|
drm_kms_helper_poll_fini(dev);
|
|
drm_mode_config_cleanup(dev);
|
|
drm_vblank_cleanup(dev);
|
|
@@ -596,10 +597,10 @@ static int __init tilcdc_drm_init(void)
|
|
static void __exit tilcdc_drm_fini(void)
|
|
{
|
|
DBG("fini");
|
|
- tilcdc_tfp410_fini();
|
|
- tilcdc_slave_fini();
|
|
- tilcdc_panel_fini();
|
|
platform_driver_unregister(&tilcdc_platform_driver);
|
|
+ tilcdc_panel_fini();
|
|
+ tilcdc_slave_fini();
|
|
+ tilcdc_tfp410_fini();
|
|
}
|
|
|
|
late_initcall(tilcdc_drm_init);
|
|
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
|
|
index 09176654fddb..779d508616d3 100644
|
|
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
|
|
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
|
|
@@ -151,6 +151,7 @@ struct panel_connector {
|
|
static void panel_connector_destroy(struct drm_connector *connector)
|
|
{
|
|
struct panel_connector *panel_connector = to_panel_connector(connector);
|
|
+ drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
kfree(panel_connector);
|
|
}
|
|
@@ -285,10 +286,8 @@ static void panel_destroy(struct tilcdc_module *mod)
|
|
{
|
|
struct panel_module *panel_mod = to_panel_module(mod);
|
|
|
|
- if (panel_mod->timings) {
|
|
+ if (panel_mod->timings)
|
|
display_timings_release(panel_mod->timings);
|
|
- kfree(panel_mod->timings);
|
|
- }
|
|
|
|
tilcdc_module_cleanup(mod);
|
|
kfree(panel_mod->info);
|
|
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
|
|
index db1d2fc9dfb5..5d6c597a5d69 100644
|
|
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
|
|
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
|
|
@@ -142,6 +142,7 @@ struct slave_connector {
|
|
static void slave_connector_destroy(struct drm_connector *connector)
|
|
{
|
|
struct slave_connector *slave_connector = to_slave_connector(connector);
|
|
+ drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
kfree(slave_connector);
|
|
}
|
|
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
|
|
index a36788fbcd98..986131dd9f47 100644
|
|
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
|
|
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
|
|
@@ -168,6 +168,7 @@ struct tfp410_connector {
|
|
static void tfp410_connector_destroy(struct drm_connector *connector)
|
|
{
|
|
struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
|
|
+ drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
kfree(tfp410_connector);
|
|
}
|
|
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
|
|
index b8b394319b45..de1a753b1d56 100644
|
|
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
|
|
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
|
|
@@ -1006,9 +1006,9 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
|
|
static int ttm_dma_pool_mm_shrink(struct shrinker *shrink,
|
|
struct shrink_control *sc)
|
|
{
|
|
- static atomic_t start_pool = ATOMIC_INIT(0);
|
|
+ static unsigned start_pool;
|
|
unsigned idx = 0;
|
|
- unsigned pool_offset = atomic_add_return(1, &start_pool);
|
|
+ unsigned pool_offset;
|
|
unsigned shrink_pages = sc->nr_to_scan;
|
|
struct device_pools *p;
|
|
|
|
@@ -1016,7 +1016,9 @@ static int ttm_dma_pool_mm_shrink(struct shrinker *shrink,
|
|
return 0;
|
|
|
|
mutex_lock(&_manager->lock);
|
|
- pool_offset = pool_offset % _manager->npools;
|
|
+ if (!_manager->npools)
|
|
+ goto out;
|
|
+ pool_offset = ++start_pool % _manager->npools;
|
|
list_for_each_entry(p, &_manager->pools, pools) {
|
|
unsigned nr_free;
|
|
|
|
@@ -1033,6 +1035,7 @@ static int ttm_dma_pool_mm_shrink(struct shrinker *shrink,
|
|
p->pool->dev_name, p->pool->name, current->pid,
|
|
nr_free, shrink_pages);
|
|
}
|
|
+out:
|
|
mutex_unlock(&_manager->lock);
|
|
/* return estimated number of unused pages in pool */
|
|
return ttm_dma_pool_get_num_unused_pages();
|
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
|
index 3eb148667d63..89664933861f 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
|
@@ -163,8 +163,9 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
|
|
|
mutex_lock(&dev_priv->hw_mutex);
|
|
|
|
+ vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
|
|
while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
|
|
- vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
|
|
+ ;
|
|
|
|
dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
|
|
|
|
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
|
|
index 51b1a5088c0d..d4c6d9f85ca5 100644
|
|
--- a/drivers/hid/hid-logitech-dj.c
|
|
+++ b/drivers/hid/hid-logitech-dj.c
|
|
@@ -679,7 +679,6 @@ static int logi_dj_raw_event(struct hid_device *hdev,
|
|
struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
|
|
struct dj_report *dj_report = (struct dj_report *) data;
|
|
unsigned long flags;
|
|
- bool report_processed = false;
|
|
|
|
dbg_hid("%s, size:%d\n", __func__, size);
|
|
|
|
@@ -706,34 +705,42 @@ static int logi_dj_raw_event(struct hid_device *hdev,
|
|
* device (via hid_input_report() ) and return 1 so hid-core does not do
|
|
* anything else with it.
|
|
*/
|
|
+
|
|
+ /* case 1) */
|
|
+ if (data[0] != REPORT_ID_DJ_SHORT)
|
|
+ return false;
|
|
+
|
|
if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
|
|
(dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
|
|
- dev_err(&hdev->dev, "%s: invalid device index:%d\n",
|
|
+ /*
|
|
+ * Device index is wrong, bail out.
|
|
+ * This driver can ignore safely the receiver notifications,
|
|
+ * so ignore those reports too.
|
|
+ */
|
|
+ if (dj_report->device_index != DJ_RECEIVER_INDEX)
|
|
+ dev_err(&hdev->dev, "%s: invalid device index:%d\n",
|
|
__func__, dj_report->device_index);
|
|
return false;
|
|
}
|
|
|
|
spin_lock_irqsave(&djrcv_dev->lock, flags);
|
|
- if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
|
|
- switch (dj_report->report_type) {
|
|
- case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
|
|
- case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
|
|
- logi_dj_recv_queue_notification(djrcv_dev, dj_report);
|
|
- break;
|
|
- case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
|
|
- if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
|
|
- STATUS_LINKLOSS) {
|
|
- logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
|
|
- }
|
|
- break;
|
|
- default:
|
|
- logi_dj_recv_forward_report(djrcv_dev, dj_report);
|
|
+ switch (dj_report->report_type) {
|
|
+ case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
|
|
+ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
|
|
+ logi_dj_recv_queue_notification(djrcv_dev, dj_report);
|
|
+ break;
|
|
+ case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
|
|
+ if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
|
|
+ STATUS_LINKLOSS) {
|
|
+ logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
|
|
}
|
|
- report_processed = true;
|
|
+ break;
|
|
+ default:
|
|
+ logi_dj_recv_forward_report(djrcv_dev, dj_report);
|
|
}
|
|
spin_unlock_irqrestore(&djrcv_dev->lock, flags);
|
|
|
|
- return report_processed;
|
|
+ return true;
|
|
}
|
|
|
|
static int logi_dj_probe(struct hid_device *hdev,
|
|
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
|
|
index 4a4000340ce1..daeb0aa4bee9 100644
|
|
--- a/drivers/hid/hid-logitech-dj.h
|
|
+++ b/drivers/hid/hid-logitech-dj.h
|
|
@@ -27,6 +27,7 @@
|
|
|
|
#define DJ_MAX_PAIRED_DEVICES 6
|
|
#define DJ_MAX_NUMBER_NOTIFICATIONS 8
|
|
+#define DJ_RECEIVER_INDEX 0
|
|
#define DJ_DEVICE_INDEX_MIN 1
|
|
#define DJ_DEVICE_INDEX_MAX 6
|
|
|
|
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
|
index 5bc37343eb22..c24f3dfd9367 100644
|
|
--- a/drivers/hid/hid-magicmouse.c
|
|
+++ b/drivers/hid/hid-magicmouse.c
|
|
@@ -290,6 +290,11 @@ static int magicmouse_raw_event(struct hid_device *hdev,
|
|
if (size < 4 || ((size - 4) % 9) != 0)
|
|
return 0;
|
|
npoints = (size - 4) / 9;
|
|
+ if (npoints > 15) {
|
|
+ hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n",
|
|
+ size);
|
|
+ return 0;
|
|
+ }
|
|
msc->ntouches = 0;
|
|
for (ii = 0; ii < npoints; ii++)
|
|
magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
|
|
@@ -307,6 +312,11 @@ static int magicmouse_raw_event(struct hid_device *hdev,
|
|
if (size < 6 || ((size - 6) % 8) != 0)
|
|
return 0;
|
|
npoints = (size - 6) / 8;
|
|
+ if (npoints > 15) {
|
|
+ hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n",
|
|
+ size);
|
|
+ return 0;
|
|
+ }
|
|
msc->ntouches = 0;
|
|
for (ii = 0; ii < npoints; ii++)
|
|
magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
|
|
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
|
|
index acbb021065ec..020df3c2e8b4 100644
|
|
--- a/drivers/hid/hid-picolcd_core.c
|
|
+++ b/drivers/hid/hid-picolcd_core.c
|
|
@@ -350,6 +350,12 @@ static int picolcd_raw_event(struct hid_device *hdev,
|
|
if (!data)
|
|
return 1;
|
|
|
|
+ if (size > 64) {
|
|
+ hid_warn(hdev, "invalid size value (%d) for picolcd raw event\n",
|
|
+ size);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (report->id == REPORT_KEY_STATE) {
|
|
if (data->input_keys)
|
|
ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
|
|
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
|
|
index f35ea236497b..b1240a250149 100644
|
|
--- a/drivers/i2c/busses/i2c-at91.c
|
|
+++ b/drivers/i2c/busses/i2c-at91.c
|
|
@@ -102,6 +102,7 @@ struct at91_twi_dev {
|
|
unsigned twi_cwgr_reg;
|
|
struct at91_twi_pdata *pdata;
|
|
bool use_dma;
|
|
+ bool recv_len_abort;
|
|
struct at91_twi_dma dma;
|
|
};
|
|
|
|
@@ -268,12 +269,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
|
|
*dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
|
|
--dev->buf_len;
|
|
|
|
+ /* return if aborting, we only needed to read RHR to clear RXRDY*/
|
|
+ if (dev->recv_len_abort)
|
|
+ return;
|
|
+
|
|
/* handle I2C_SMBUS_BLOCK_DATA */
|
|
if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
|
|
- dev->msg->flags &= ~I2C_M_RECV_LEN;
|
|
- dev->buf_len += *dev->buf;
|
|
- dev->msg->len = dev->buf_len + 1;
|
|
- dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
|
|
+ /* ensure length byte is a valid value */
|
|
+ if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
|
|
+ dev->msg->flags &= ~I2C_M_RECV_LEN;
|
|
+ dev->buf_len += *dev->buf;
|
|
+ dev->msg->len = dev->buf_len + 1;
|
|
+ dev_dbg(dev->dev, "received block length %d\n",
|
|
+ dev->buf_len);
|
|
+ } else {
|
|
+ /* abort and send the stop by reading one more byte */
|
|
+ dev->recv_len_abort = true;
|
|
+ dev->buf_len = 1;
|
|
+ }
|
|
}
|
|
|
|
/* send stop if second but last byte has been read */
|
|
@@ -422,8 +435,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
|
|
}
|
|
}
|
|
|
|
- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
|
|
- dev->adapter.timeout);
|
|
+ ret = wait_for_completion_io_timeout(&dev->cmd_complete,
|
|
+ dev->adapter.timeout);
|
|
if (ret == 0) {
|
|
dev_err(dev->dev, "controller timed out\n");
|
|
at91_init_twi_bus(dev);
|
|
@@ -445,6 +458,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
|
|
ret = -EIO;
|
|
goto error;
|
|
}
|
|
+ if (dev->recv_len_abort) {
|
|
+ dev_err(dev->dev, "invalid smbus block length recvd\n");
|
|
+ ret = -EPROTO;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
dev_dbg(dev->dev, "transfer complete\n");
|
|
|
|
return 0;
|
|
@@ -501,6 +520,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
|
|
dev->buf_len = m_start->len;
|
|
dev->buf = m_start->buf;
|
|
dev->msg = m_start;
|
|
+ dev->recv_len_abort = false;
|
|
|
|
ret = at91_do_twi_transfer(dev);
|
|
|
|
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
|
|
index f0d6335ae087..05d2733ef48c 100644
|
|
--- a/drivers/iio/adc/ad_sigma_delta.c
|
|
+++ b/drivers/iio/adc/ad_sigma_delta.c
|
|
@@ -477,7 +477,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
|
|
goto error_free_irq;
|
|
|
|
/* select default trigger */
|
|
- indio_dev->trig = sigma_delta->trig;
|
|
+ indio_dev->trig = iio_trigger_get(sigma_delta->trig);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
|
|
index 8fc3a97eb266..8d8ca6f1e16a 100644
|
|
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
|
|
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
|
|
@@ -49,7 +49,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
|
dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
|
|
goto iio_trigger_register_error;
|
|
}
|
|
- indio_dev->trig = sdata->trig;
|
|
+ indio_dev->trig = iio_trigger_get(sdata->trig);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c
|
|
index 6c43af9bb0a4..14917fae2d9d 100644
|
|
--- a/drivers/iio/gyro/itg3200_buffer.c
|
|
+++ b/drivers/iio/gyro/itg3200_buffer.c
|
|
@@ -135,7 +135,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev)
|
|
goto error_free_irq;
|
|
|
|
/* select default trigger */
|
|
- indio_dev->trig = st->trig;
|
|
+ indio_dev->trig = iio_trigger_get(st->trig);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
|
|
index 03b9372c1212..926fccea8de0 100644
|
|
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
|
|
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
|
|
@@ -135,7 +135,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
|
|
ret = iio_trigger_register(st->trig);
|
|
if (ret)
|
|
goto error_free_irq;
|
|
- indio_dev->trig = st->trig;
|
|
+ indio_dev->trig = iio_trigger_get(st->trig);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
|
|
index 1e8e94d4db7d..4fc88e617acf 100644
|
|
--- a/drivers/iio/inkern.c
|
|
+++ b/drivers/iio/inkern.c
|
|
@@ -178,7 +178,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
|
|
index = of_property_match_string(np, "io-channel-names",
|
|
name);
|
|
chan = of_iio_channel_get(np, index);
|
|
- if (!IS_ERR(chan))
|
|
+ if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
|
|
break;
|
|
else if (name && index >= 0) {
|
|
pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
|
|
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
|
|
index 16f0d6df239f..3ce3769c0823 100644
|
|
--- a/drivers/iio/magnetometer/st_magn_core.c
|
|
+++ b/drivers/iio/magnetometer/st_magn_core.c
|
|
@@ -40,7 +40,8 @@
|
|
#define ST_MAGN_FS_AVL_5600MG 5600
|
|
#define ST_MAGN_FS_AVL_8000MG 8000
|
|
#define ST_MAGN_FS_AVL_8100MG 8100
|
|
-#define ST_MAGN_FS_AVL_10000MG 10000
|
|
+#define ST_MAGN_FS_AVL_12000MG 12000
|
|
+#define ST_MAGN_FS_AVL_16000MG 16000
|
|
|
|
/* CUSTOM VALUES FOR SENSOR 1 */
|
|
#define ST_MAGN_1_WAI_EXP 0x3c
|
|
@@ -67,20 +68,20 @@
|
|
#define ST_MAGN_1_FS_AVL_4700_VAL 0x05
|
|
#define ST_MAGN_1_FS_AVL_5600_VAL 0x06
|
|
#define ST_MAGN_1_FS_AVL_8100_VAL 0x07
|
|
-#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 1100
|
|
-#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 855
|
|
-#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 670
|
|
-#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 450
|
|
-#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 400
|
|
-#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 330
|
|
-#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 230
|
|
-#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 980
|
|
-#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 760
|
|
-#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 600
|
|
-#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 400
|
|
-#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 355
|
|
-#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 295
|
|
-#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 205
|
|
+#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 909
|
|
+#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 1169
|
|
+#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 1492
|
|
+#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 2222
|
|
+#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 2500
|
|
+#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 3030
|
|
+#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 4347
|
|
+#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 1020
|
|
+#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 1315
|
|
+#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 1666
|
|
+#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 2500
|
|
+#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 2816
|
|
+#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 3389
|
|
+#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 4878
|
|
#define ST_MAGN_1_MULTIREAD_BIT false
|
|
|
|
/* CUSTOM VALUES FOR SENSOR 2 */
|
|
@@ -103,10 +104,12 @@
|
|
#define ST_MAGN_2_FS_MASK 0x60
|
|
#define ST_MAGN_2_FS_AVL_4000_VAL 0x00
|
|
#define ST_MAGN_2_FS_AVL_8000_VAL 0x01
|
|
-#define ST_MAGN_2_FS_AVL_10000_VAL 0x02
|
|
-#define ST_MAGN_2_FS_AVL_4000_GAIN 430
|
|
-#define ST_MAGN_2_FS_AVL_8000_GAIN 230
|
|
-#define ST_MAGN_2_FS_AVL_10000_GAIN 230
|
|
+#define ST_MAGN_2_FS_AVL_12000_VAL 0x02
|
|
+#define ST_MAGN_2_FS_AVL_16000_VAL 0x03
|
|
+#define ST_MAGN_2_FS_AVL_4000_GAIN 146
|
|
+#define ST_MAGN_2_FS_AVL_8000_GAIN 292
|
|
+#define ST_MAGN_2_FS_AVL_12000_GAIN 438
|
|
+#define ST_MAGN_2_FS_AVL_16000_GAIN 584
|
|
#define ST_MAGN_2_MULTIREAD_BIT false
|
|
#define ST_MAGN_2_OUT_X_L_ADDR 0x28
|
|
#define ST_MAGN_2_OUT_Y_L_ADDR 0x2a
|
|
@@ -252,9 +255,14 @@ static const struct st_sensors st_magn_sensors[] = {
|
|
.gain = ST_MAGN_2_FS_AVL_8000_GAIN,
|
|
},
|
|
[2] = {
|
|
- .num = ST_MAGN_FS_AVL_10000MG,
|
|
- .value = ST_MAGN_2_FS_AVL_10000_VAL,
|
|
- .gain = ST_MAGN_2_FS_AVL_10000_GAIN,
|
|
+ .num = ST_MAGN_FS_AVL_12000MG,
|
|
+ .value = ST_MAGN_2_FS_AVL_12000_VAL,
|
|
+ .gain = ST_MAGN_2_FS_AVL_12000_GAIN,
|
|
+ },
|
|
+ [3] = {
|
|
+ .num = ST_MAGN_FS_AVL_16000MG,
|
|
+ .value = ST_MAGN_2_FS_AVL_16000_VAL,
|
|
+ .gain = ST_MAGN_2_FS_AVL_16000_GAIN,
|
|
},
|
|
},
|
|
},
|
|
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
|
|
index 0e93152384f0..acb3865710c2 100644
|
|
--- a/drivers/infiniband/ulp/isert/ib_isert.c
|
|
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
|
|
@@ -404,7 +404,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
|
init_completion(&isert_conn->conn_wait);
|
|
init_completion(&isert_conn->conn_wait_comp_err);
|
|
kref_init(&isert_conn->conn_kref);
|
|
- kref_get(&isert_conn->conn_kref);
|
|
mutex_init(&isert_conn->conn_mutex);
|
|
|
|
cma_id->context = isert_conn;
|
|
@@ -530,7 +529,9 @@ isert_connect_release(struct isert_conn *isert_conn)
|
|
static void
|
|
isert_connected_handler(struct rdma_cm_id *cma_id)
|
|
{
|
|
- return;
|
|
+ struct isert_conn *isert_conn = cma_id->context;
|
|
+
|
|
+ kref_get(&isert_conn->conn_kref);
|
|
}
|
|
|
|
static void
|
|
@@ -582,7 +583,6 @@ isert_disconnect_work(struct work_struct *work)
|
|
|
|
wake_up:
|
|
complete(&isert_conn->conn_wait);
|
|
- isert_put_conn(isert_conn);
|
|
}
|
|
|
|
static void
|
|
@@ -2265,6 +2265,7 @@ static void isert_wait_conn(struct iscsi_conn *conn)
|
|
wait_for_completion(&isert_conn->conn_wait_comp_err);
|
|
|
|
wait_for_completion(&isert_conn->conn_wait);
|
|
+ isert_put_conn(isert_conn);
|
|
}
|
|
|
|
static void isert_free_conn(struct iscsi_conn *conn)
|
|
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
|
|
index 2dd1d0dd4f7d..6f5d79569136 100644
|
|
--- a/drivers/input/keyboard/atkbd.c
|
|
+++ b/drivers/input/keyboard/atkbd.c
|
|
@@ -1791,14 +1791,6 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
|
|
{
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"),
|
|
- },
|
|
- .callback = atkbd_deactivate_fixup,
|
|
- },
|
|
- {
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"),
|
|
},
|
|
.callback = atkbd_deactivate_fixup,
|
|
},
|
|
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
|
|
index 1913301df08f..85e75239c814 100644
|
|
--- a/drivers/input/mouse/elantech.c
|
|
+++ b/drivers/input/mouse/elantech.c
|
|
@@ -1223,6 +1223,13 @@ static bool elantech_is_signature_valid(const unsigned char *param)
|
|
if (param[1] == 0)
|
|
return true;
|
|
|
|
+ /*
|
|
+ * Some models have a revision higher then 20. Meaning param[2] may
|
|
+ * be 10 or 20, skip the rates check for these.
|
|
+ */
|
|
+ if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
|
|
+ return true;
|
|
+
|
|
for (i = 0; i < ARRAY_SIZE(rates); i++)
|
|
if (param[2] == rates[i])
|
|
return false;
|
|
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
|
|
index f36f7b88f260..d1c47d135c07 100644
|
|
--- a/drivers/input/mouse/synaptics.c
|
|
+++ b/drivers/input/mouse/synaptics.c
|
|
@@ -549,10 +549,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
|
|
((buf[0] & 0x04) >> 1) |
|
|
((buf[3] & 0x04) >> 2));
|
|
|
|
+ if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
|
|
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
|
|
+ hw->w == 2) {
|
|
+ synaptics_parse_agm(buf, priv, hw);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ hw->x = (((buf[3] & 0x10) << 8) |
|
|
+ ((buf[1] & 0x0f) << 8) |
|
|
+ buf[4]);
|
|
+ hw->y = (((buf[3] & 0x20) << 7) |
|
|
+ ((buf[1] & 0xf0) << 4) |
|
|
+ buf[5]);
|
|
+ hw->z = buf[2];
|
|
+
|
|
hw->left = (buf[0] & 0x01) ? 1 : 0;
|
|
hw->right = (buf[0] & 0x02) ? 1 : 0;
|
|
|
|
- if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
|
|
+ if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) {
|
|
+ /*
|
|
+ * ForcePads, like Clickpads, use middle button
|
|
+ * bits to report primary button clicks.
|
|
+ * Unfortunately they report primary button not
|
|
+ * only when user presses on the pad above certain
|
|
+ * threshold, but also when there are more than one
|
|
+ * finger on the touchpad, which interferes with
|
|
+ * out multi-finger gestures.
|
|
+ */
|
|
+ if (hw->z == 0) {
|
|
+ /* No contacts */
|
|
+ priv->press = priv->report_press = false;
|
|
+ } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
|
|
+ /*
|
|
+ * Single-finger touch with pressure above
|
|
+ * the threshold. If pressure stays long
|
|
+ * enough, we'll start reporting primary
|
|
+ * button. We rely on the device continuing
|
|
+ * sending data even if finger does not
|
|
+ * move.
|
|
+ */
|
|
+ if (!priv->press) {
|
|
+ priv->press_start = jiffies;
|
|
+ priv->press = true;
|
|
+ } else if (time_after(jiffies,
|
|
+ priv->press_start +
|
|
+ msecs_to_jiffies(50))) {
|
|
+ priv->report_press = true;
|
|
+ }
|
|
+ } else {
|
|
+ priv->press = false;
|
|
+ }
|
|
+
|
|
+ hw->left = priv->report_press;
|
|
+
|
|
+ } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
|
|
/*
|
|
* Clickpad's button is transmitted as middle button,
|
|
* however, since it is primary button, we will report
|
|
@@ -571,21 +622,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
|
|
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
|
|
}
|
|
|
|
- if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
|
|
- SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
|
|
- hw->w == 2) {
|
|
- synaptics_parse_agm(buf, priv, hw);
|
|
- return 1;
|
|
- }
|
|
-
|
|
- hw->x = (((buf[3] & 0x10) << 8) |
|
|
- ((buf[1] & 0x0f) << 8) |
|
|
- buf[4]);
|
|
- hw->y = (((buf[3] & 0x20) << 7) |
|
|
- ((buf[1] & 0xf0) << 4) |
|
|
- buf[5]);
|
|
- hw->z = buf[2];
|
|
-
|
|
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
|
|
((buf[0] ^ buf[3]) & 0x02)) {
|
|
switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
|
|
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
|
|
index e594af0b264b..fb2e076738ae 100644
|
|
--- a/drivers/input/mouse/synaptics.h
|
|
+++ b/drivers/input/mouse/synaptics.h
|
|
@@ -78,6 +78,11 @@
|
|
* 2 0x08 image sensor image sensor tracks 5 fingers, but only
|
|
* reports 2.
|
|
* 2 0x20 report min query 0x0f gives min coord reported
|
|
+ * 2 0x80 forcepad forcepad is a variant of clickpad that
|
|
+ * does not have physical buttons but rather
|
|
+ * uses pressure above certain threshold to
|
|
+ * report primary clicks. Forcepads also have
|
|
+ * clickpad bit set.
|
|
*/
|
|
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
|
|
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */
|
|
@@ -86,6 +91,7 @@
|
|
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
|
|
#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400)
|
|
#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800)
|
|
+#define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000)
|
|
|
|
/* synaptics modes query bits */
|
|
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
|
|
@@ -177,6 +183,11 @@ struct synaptics_data {
|
|
*/
|
|
struct synaptics_hw_state agm;
|
|
bool agm_pending; /* new AGM packet received */
|
|
+
|
|
+ /* ForcePad handling */
|
|
+ unsigned long press_start;
|
|
+ bool press;
|
|
+ bool report_press;
|
|
};
|
|
|
|
void synaptics_module_init(void);
|
|
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
|
|
index 0ec9abbe31fe..1291673bd57e 100644
|
|
--- a/drivers/input/serio/i8042-x86ia64io.h
|
|
+++ b/drivers/input/serio/i8042-x86ia64io.h
|
|
@@ -458,6 +458,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* Avatar AVIU-145A6 */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
|
|
+ },
|
|
+ },
|
|
{ }
|
|
};
|
|
|
|
@@ -601,6 +608,14 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* Fujitsu U574 laptop */
|
|
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
|
|
+ },
|
|
+ },
|
|
{ }
|
|
};
|
|
|
|
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
|
|
index 8755f5f3ad37..e4ecf3b64794 100644
|
|
--- a/drivers/input/serio/serport.c
|
|
+++ b/drivers/input/serio/serport.c
|
|
@@ -21,6 +21,7 @@
|
|
#include <linux/init.h>
|
|
#include <linux/serio.h>
|
|
#include <linux/tty.h>
|
|
+#include <linux/compat.h>
|
|
|
|
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
|
MODULE_DESCRIPTION("Input device TTY line discipline");
|
|
@@ -196,28 +197,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
|
|
return 0;
|
|
}
|
|
|
|
+static void serport_set_type(struct tty_struct *tty, unsigned long type)
|
|
+{
|
|
+ struct serport *serport = tty->disc_data;
|
|
+
|
|
+ serport->id.proto = type & 0x000000ff;
|
|
+ serport->id.id = (type & 0x0000ff00) >> 8;
|
|
+ serport->id.extra = (type & 0x00ff0000) >> 16;
|
|
+}
|
|
+
|
|
/*
|
|
* serport_ldisc_ioctl() allows to set the port protocol, and device ID
|
|
*/
|
|
|
|
-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
|
|
+static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
|
|
+ unsigned int cmd, unsigned long arg)
|
|
{
|
|
- struct serport *serport = (struct serport*) tty->disc_data;
|
|
- unsigned long type;
|
|
-
|
|
if (cmd == SPIOCSTYPE) {
|
|
+ unsigned long type;
|
|
+
|
|
if (get_user(type, (unsigned long __user *) arg))
|
|
return -EFAULT;
|
|
|
|
- serport->id.proto = type & 0x000000ff;
|
|
- serport->id.id = (type & 0x0000ff00) >> 8;
|
|
- serport->id.extra = (type & 0x00ff0000) >> 16;
|
|
+ serport_set_type(tty, type);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_COMPAT
|
|
+#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
|
|
+static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
|
|
+ struct file *file,
|
|
+ unsigned int cmd, unsigned long arg)
|
|
+{
|
|
+ if (cmd == COMPAT_SPIOCSTYPE) {
|
|
+ void __user *uarg = compat_ptr(arg);
|
|
+ compat_ulong_t compat_type;
|
|
+
|
|
+ if (get_user(compat_type, (compat_ulong_t __user *)uarg))
|
|
+ return -EFAULT;
|
|
|
|
+ serport_set_type(tty, compat_type);
|
|
return 0;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
+#endif
|
|
|
|
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
|
|
{
|
|
@@ -241,6 +269,9 @@ static struct tty_ldisc_ops serport_ldisc = {
|
|
.close = serport_ldisc_close,
|
|
.read = serport_ldisc_read,
|
|
.ioctl = serport_ldisc_ioctl,
|
|
+#ifdef CONFIG_COMPAT
|
|
+ .compat_ioctl = serport_ldisc_compat_ioctl,
|
|
+#endif
|
|
.receive_buf = serport_ldisc_receive,
|
|
.write_wakeup = serport_ldisc_write_wakeup
|
|
};
|
|
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
|
|
index 5177ba54559b..7409d79729ee 100644
|
|
--- a/drivers/md/dm-crypt.c
|
|
+++ b/drivers/md/dm-crypt.c
|
|
@@ -1506,6 +1506,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|
unsigned int key_size, opt_params;
|
|
unsigned long long tmpll;
|
|
int ret;
|
|
+ size_t iv_size_padding;
|
|
struct dm_arg_set as;
|
|
const char *opt_string;
|
|
char dummy;
|
|
@@ -1542,12 +1543,23 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|
|
|
cc->dmreq_start = sizeof(struct ablkcipher_request);
|
|
cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc));
|
|
- cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
|
|
- cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) &
|
|
- ~(crypto_tfm_ctx_alignment() - 1);
|
|
+ cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request));
|
|
+
|
|
+ if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) {
|
|
+ /* Allocate the padding exactly */
|
|
+ iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request))
|
|
+ & crypto_ablkcipher_alignmask(any_tfm(cc));
|
|
+ } else {
|
|
+ /*
|
|
+ * If the cipher requires greater alignment than kmalloc
|
|
+ * alignment, we don't know the exact position of the
|
|
+ * initialization vector. We must assume worst case.
|
|
+ */
|
|
+ iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc));
|
|
+ }
|
|
|
|
cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
|
|
- sizeof(struct dm_crypt_request) + cc->iv_size);
|
|
+ sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size);
|
|
if (!cc->req_pool) {
|
|
ti->error = "Cannot allocate crypt request mempool";
|
|
goto bad;
|
|
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
|
|
index a176791509f6..e885dbf08c40 100644
|
|
--- a/drivers/md/raid1.c
|
|
+++ b/drivers/md/raid1.c
|
|
@@ -2051,7 +2051,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
|
|
d--;
|
|
rdev = conf->mirrors[d].rdev;
|
|
if (rdev &&
|
|
- test_bit(In_sync, &rdev->flags))
|
|
+ !test_bit(Faulty, &rdev->flags))
|
|
r1_sync_page_io(rdev, sect, s,
|
|
conf->tmppage, WRITE);
|
|
}
|
|
@@ -2063,7 +2063,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
|
|
d--;
|
|
rdev = conf->mirrors[d].rdev;
|
|
if (rdev &&
|
|
- test_bit(In_sync, &rdev->flags)) {
|
|
+ !test_bit(Faulty, &rdev->flags)) {
|
|
if (r1_sync_page_io(rdev, sect, s,
|
|
conf->tmppage, READ)) {
|
|
atomic_add(s, &rdev->corrected_errors);
|
|
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
|
|
index 16e89f026bca..018cb9045330 100644
|
|
--- a/drivers/media/pci/cx18/cx18-driver.c
|
|
+++ b/drivers/media/pci/cx18/cx18-driver.c
|
|
@@ -1092,6 +1092,7 @@ static int cx18_probe(struct pci_dev *pci_dev,
|
|
setup.addr = ADDR_UNSET;
|
|
setup.type = cx->options.tuner;
|
|
setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
|
|
+ setup.config = NULL;
|
|
if (cx->options.radio > 0)
|
|
setup.mode_mask |= T_RADIO;
|
|
setup.tuner_callback = (setup.type == TUNER_XC2028) ?
|
|
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
|
|
index 70fd55968844..040ecf2027cd 100644
|
|
--- a/drivers/net/ethernet/ibm/ibmveth.c
|
|
+++ b/drivers/net/ethernet/ibm/ibmveth.c
|
|
@@ -293,6 +293,18 @@ failure:
|
|
atomic_add(buffers_added, &(pool->available));
|
|
}
|
|
|
|
+/*
|
|
+ * The final 8 bytes of the buffer list is a counter of frames dropped
|
|
+ * because there was not a buffer in the buffer list capable of holding
|
|
+ * the frame.
|
|
+ */
|
|
+static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter)
|
|
+{
|
|
+ __be64 *p = adapter->buffer_list_addr + 4096 - 8;
|
|
+
|
|
+ adapter->rx_no_buffer = be64_to_cpup(p);
|
|
+}
|
|
+
|
|
/* replenish routine */
|
|
static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
|
|
{
|
|
@@ -308,8 +320,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
|
|
ibmveth_replenish_buffer_pool(adapter, pool);
|
|
}
|
|
|
|
- adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) +
|
|
- 4096 - 8);
|
|
+ ibmveth_update_rx_no_buffer(adapter);
|
|
}
|
|
|
|
/* empty and free ana buffer pool - also used to do cleanup in error paths */
|
|
@@ -689,8 +700,7 @@ static int ibmveth_close(struct net_device *netdev)
|
|
|
|
free_irq(netdev->irq, netdev);
|
|
|
|
- adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) +
|
|
- 4096 - 8);
|
|
+ ibmveth_update_rx_no_buffer(adapter);
|
|
|
|
ibmveth_cleanup(adapter);
|
|
|
|
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
|
|
index 9dce106cd6d4..95a334f0719c 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
|
|
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
|
|
@@ -253,6 +253,7 @@ struct ar9170 {
|
|
atomic_t rx_work_urbs;
|
|
atomic_t rx_pool_urbs;
|
|
kernel_ulong_t features;
|
|
+ bool usb_ep_cmd_is_bulk;
|
|
|
|
/* firmware settings */
|
|
struct completion fw_load_wait;
|
|
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
|
|
index 307bc0ddff99..83d20c8b2ad7 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/usb.c
|
|
+++ b/drivers/net/wireless/ath/carl9170/usb.c
|
|
@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
|
|
goto err_free;
|
|
}
|
|
|
|
- usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
|
|
- AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
|
|
- carl9170_usb_cmd_complete, ar, 1);
|
|
+ if (ar->usb_ep_cmd_is_bulk)
|
|
+ usb_fill_bulk_urb(urb, ar->udev,
|
|
+ usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD),
|
|
+ cmd, cmd->hdr.len + 4,
|
|
+ carl9170_usb_cmd_complete, ar);
|
|
+ else
|
|
+ usb_fill_int_urb(urb, ar->udev,
|
|
+ usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD),
|
|
+ cmd, cmd->hdr.len + 4,
|
|
+ carl9170_usb_cmd_complete, ar, 1);
|
|
|
|
if (free_buf)
|
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
|
@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw,
|
|
static int carl9170_usb_probe(struct usb_interface *intf,
|
|
const struct usb_device_id *id)
|
|
{
|
|
+ struct usb_endpoint_descriptor *ep;
|
|
struct ar9170 *ar;
|
|
struct usb_device *udev;
|
|
- int err;
|
|
+ int i, err;
|
|
|
|
err = usb_reset_device(interface_to_usbdev(intf));
|
|
if (err)
|
|
@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf,
|
|
ar->intf = intf;
|
|
ar->features = id->driver_info;
|
|
|
|
+ /* We need to remember the type of endpoint 4 because it differs
|
|
+ * between high- and full-speed configuration. The high-speed
|
|
+ * configuration specifies it as interrupt and the full-speed
|
|
+ * configuration as bulk endpoint. This information is required
|
|
+ * later when sending urbs to that endpoint.
|
|
+ */
|
|
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) {
|
|
+ ep = &intf->cur_altsetting->endpoint[i].desc;
|
|
+
|
|
+ if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD &&
|
|
+ usb_endpoint_dir_out(ep) &&
|
|
+ usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK)
|
|
+ ar->usb_ep_cmd_is_bulk = true;
|
|
+ }
|
|
+
|
|
usb_set_intfdata(intf, ar);
|
|
SET_IEEE80211_DEV(ar->hw, &intf->dev);
|
|
|
|
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
|
|
index ca17e4c9eca2..cd1ad0019185 100644
|
|
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
|
|
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
|
|
@@ -1072,6 +1072,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|
/* recalculate basic rates */
|
|
iwl_calc_basic_rates(priv, ctx);
|
|
|
|
+ /*
|
|
+ * force CTS-to-self frames protection if RTS-CTS is not preferred
|
|
+ * one aggregation protection method
|
|
+ */
|
|
+ if (!priv->hw_params.use_rts_for_aggregation)
|
|
+ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
|
+
|
|
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
|
|
!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
|
|
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
|
@@ -1477,6 +1484,11 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
|
else
|
|
ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
|
|
|
|
+ if (bss_conf->use_cts_prot)
|
|
+ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
|
+ else
|
|
+ ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
|
|
+
|
|
memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
|
|
|
|
if (vif->type == NL80211_IFTYPE_AP ||
|
|
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
|
|
index 8188dcb512f0..e7a2af3ad05a 100644
|
|
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
|
|
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
|
|
@@ -316,6 +316,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
|
|
{RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
|
|
{RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
|
|
{RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
|
|
+ {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */
|
|
{RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/
|
|
{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
|
|
{RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/
|
|
diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c
|
|
index 3420d833db17..384ab8ca4b37 100644
|
|
--- a/drivers/nfc/microread/microread.c
|
|
+++ b/drivers/nfc/microread/microread.c
|
|
@@ -501,9 +501,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
|
|
targets->sens_res =
|
|
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]);
|
|
targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK];
|
|
- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID],
|
|
- skb->data[MICROREAD_EMCF_A_LEN]);
|
|
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN];
|
|
+ if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
|
|
+ r = -EINVAL;
|
|
+ goto exit_free;
|
|
+ }
|
|
+ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID],
|
|
+ targets->nfcid1_len);
|
|
break;
|
|
case MICROREAD_GATE_ID_MREAD_ISO_A_3:
|
|
targets->supported_protocols =
|
|
@@ -511,9 +515,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
|
|
targets->sens_res =
|
|
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]);
|
|
targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK];
|
|
- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID],
|
|
- skb->data[MICROREAD_EMCF_A3_LEN]);
|
|
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN];
|
|
+ if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
|
|
+ r = -EINVAL;
|
|
+ goto exit_free;
|
|
+ }
|
|
+ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID],
|
|
+ targets->nfcid1_len);
|
|
break;
|
|
case MICROREAD_GATE_ID_MREAD_ISO_B:
|
|
targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
|
|
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
|
|
index 5de946984500..f91d41788ce4 100644
|
|
--- a/drivers/scsi/libiscsi.c
|
|
+++ b/drivers/scsi/libiscsi.c
|
|
@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
|
return NULL;
|
|
}
|
|
|
|
+ if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) {
|
|
+ iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
task = conn->login_task;
|
|
} else {
|
|
if (session->state != ISCSI_STATE_LOGGED_IN)
|
|
return NULL;
|
|
|
|
+ if (data_size != 0) {
|
|
+ iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
|
|
BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
|
|
|
|
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
|
|
index 7a94ddd42f59..8c4f2896cd0d 100644
|
|
--- a/drivers/staging/iio/meter/ade7758_trigger.c
|
|
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
|
|
@@ -85,7 +85,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
|
|
ret = iio_trigger_register(st->trig);
|
|
|
|
/* select default trigger */
|
|
- indio_dev->trig = st->trig;
|
|
+ indio_dev->trig = iio_trigger_get(st->trig);
|
|
if (ret)
|
|
goto error_free_irq;
|
|
|
|
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
|
|
index 799f84e686b5..651b5768862f 100644
|
|
--- a/drivers/target/iscsi/iscsi_target.c
|
|
+++ b/drivers/target/iscsi/iscsi_target.c
|
|
@@ -4453,6 +4453,7 @@ static void iscsit_logout_post_handler_diffcid(
|
|
{
|
|
struct iscsi_conn *l_conn;
|
|
struct iscsi_session *sess = conn->sess;
|
|
+ bool conn_found = false;
|
|
|
|
if (!sess)
|
|
return;
|
|
@@ -4461,12 +4462,13 @@ static void iscsit_logout_post_handler_diffcid(
|
|
list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
|
|
if (l_conn->cid == cid) {
|
|
iscsit_inc_conn_usage_count(l_conn);
|
|
+ conn_found = true;
|
|
break;
|
|
}
|
|
}
|
|
spin_unlock_bh(&sess->conn_lock);
|
|
|
|
- if (!l_conn)
|
|
+ if (!conn_found)
|
|
return;
|
|
|
|
if (l_conn->sock)
|
|
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
|
|
index e38222191a33..30be6c9bdbc6 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_parameters.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
|
|
@@ -603,7 +603,7 @@ int iscsi_copy_param_list(
|
|
param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
|
|
if (!param_list) {
|
|
pr_err("Unable to allocate memory for struct iscsi_param_list.\n");
|
|
- goto err_out;
|
|
+ return -1;
|
|
}
|
|
INIT_LIST_HEAD(¶m_list->param_list);
|
|
INIT_LIST_HEAD(¶m_list->extra_response_list);
|
|
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
|
|
index ab9096dc3849..148ffe4c232f 100644
|
|
--- a/drivers/tty/serial/8250/8250_dma.c
|
|
+++ b/drivers/tty/serial/8250/8250_dma.c
|
|
@@ -192,21 +192,28 @@ int serial8250_request_dma(struct uart_8250_port *p)
|
|
|
|
dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size,
|
|
&dma->rx_addr, GFP_KERNEL);
|
|
- if (!dma->rx_buf) {
|
|
- dma_release_channel(dma->rxchan);
|
|
- dma_release_channel(dma->txchan);
|
|
- return -ENOMEM;
|
|
- }
|
|
+ if (!dma->rx_buf)
|
|
+ goto err;
|
|
|
|
/* TX buffer */
|
|
dma->tx_addr = dma_map_single(dma->txchan->device->dev,
|
|
p->port.state->xmit.buf,
|
|
UART_XMIT_SIZE,
|
|
DMA_TO_DEVICE);
|
|
+ if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) {
|
|
+ dma_free_coherent(dma->rxchan->device->dev, dma->rx_size,
|
|
+ dma->rx_buf, dma->rx_addr);
|
|
+ goto err;
|
|
+ }
|
|
|
|
dev_dbg_ratelimited(p->port.dev, "got both dma channels\n");
|
|
|
|
return 0;
|
|
+err:
|
|
+ dma_release_channel(dma->rxchan);
|
|
+ dma_release_channel(dma->txchan);
|
|
+
|
|
+ return -ENOMEM;
|
|
}
|
|
EXPORT_SYMBOL_GPL(serial8250_request_dma);
|
|
|
|
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
|
index a5631849017f..b5d42fee8a84 100644
|
|
--- a/drivers/usb/core/hub.c
|
|
+++ b/drivers/usb/core/hub.c
|
|
@@ -1165,7 +1165,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|
/* Tell khubd to disconnect the device or
|
|
* check for a new connection
|
|
*/
|
|
- if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
|
|
+ if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
|
|
+ (portstatus & USB_PORT_STAT_OVERCURRENT))
|
|
set_bit(port1, hub->change_bits);
|
|
|
|
} else if (portstatus & USB_PORT_STAT_ENABLE) {
|
|
@@ -4702,9 +4703,10 @@ static void hub_events(void)
|
|
|
|
hub = list_entry(tmp, struct usb_hub, event_list);
|
|
kref_get(&hub->kref);
|
|
+ hdev = hub->hdev;
|
|
+ usb_get_dev(hdev);
|
|
spin_unlock_irq(&hub_event_lock);
|
|
|
|
- hdev = hub->hdev;
|
|
hub_dev = hub->intfdev;
|
|
intf = to_usb_interface(hub_dev);
|
|
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
|
|
@@ -4919,6 +4921,7 @@ static void hub_events(void)
|
|
usb_autopm_put_interface(intf);
|
|
loop_disconnected:
|
|
usb_unlock_device(hdev);
|
|
+ usb_put_dev(hdev);
|
|
kref_put(&hub->kref, hub_release);
|
|
|
|
} /* end while (1) */
|
|
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
|
|
index 34638b92500d..cb5f8c44eb3a 100644
|
|
--- a/drivers/usb/dwc3/dwc3-omap.c
|
|
+++ b/drivers/usb/dwc3/dwc3-omap.c
|
|
@@ -395,9 +395,9 @@ static int dwc3_omap_remove(struct platform_device *pdev)
|
|
struct dwc3_omap *omap = platform_get_drvdata(pdev);
|
|
|
|
dwc3_omap_disable_irqs(omap);
|
|
+ device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
|
|
pm_runtime_put_sync(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
- device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
|
|
index 4518b8189a9e..5a160063176d 100644
|
|
--- a/drivers/usb/host/ehci-hcd.c
|
|
+++ b/drivers/usb/host/ehci-hcd.c
|
|
@@ -972,8 +972,6 @@ rescan:
|
|
}
|
|
|
|
qh->exception = 1;
|
|
- if (ehci->rh_state < EHCI_RH_RUNNING)
|
|
- qh->qh_state = QH_STATE_IDLE;
|
|
switch (qh->qh_state) {
|
|
case QH_STATE_LINKED:
|
|
case QH_STATE_COMPLETING:
|
|
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
|
|
index 7cdcfd024744..d939376c5dee 100644
|
|
--- a/drivers/usb/host/xhci-hub.c
|
|
+++ b/drivers/usb/host/xhci-hub.c
|
|
@@ -462,7 +462,8 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
|
|
}
|
|
|
|
/* Updates Link Status for super Speed port */
|
|
-static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
|
|
+static void xhci_hub_report_link_state(struct xhci_hcd *xhci,
|
|
+ u32 *status, u32 status_reg)
|
|
{
|
|
u32 pls = status_reg & PORT_PLS_MASK;
|
|
|
|
@@ -501,7 +502,8 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
|
|
* in which sometimes the port enters compliance mode
|
|
* caused by a delay on the host-device negotiation.
|
|
*/
|
|
- if (pls == USB_SS_PORT_LS_COMP_MOD)
|
|
+ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
|
|
+ (pls == USB_SS_PORT_LS_COMP_MOD))
|
|
pls |= USB_PORT_STAT_CONNECTION;
|
|
}
|
|
|
|
@@ -686,7 +688,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|
}
|
|
/* Update Port Link State for super speed ports*/
|
|
if (hcd->speed == HCD_USB3) {
|
|
- xhci_hub_report_link_state(&status, temp);
|
|
+ xhci_hub_report_link_state(xhci, &status, temp);
|
|
/*
|
|
* Verify if all USB3 Ports Have entered U0 already.
|
|
* Delete Compliance Mode Timer if so.
|
|
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
|
index d007f0920126..677f032482f7 100644
|
|
--- a/drivers/usb/host/xhci-mem.c
|
|
+++ b/drivers/usb/host/xhci-mem.c
|
|
@@ -1795,7 +1795,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|
}
|
|
|
|
num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
|
|
- for (i = 0; i < num_ports; i++) {
|
|
+ for (i = 0; i < num_ports && xhci->rh_bw; i++) {
|
|
struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
|
|
for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
|
|
struct list_head *ep = &bwt->interval_bw[j].endpoints;
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index 9a7088bc634d..10223f2b18d2 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -4407,13 +4407,21 @@ static int xhci_change_max_exit_latency(struct xhci_hcd *xhci,
|
|
int ret;
|
|
|
|
spin_lock_irqsave(&xhci->lock, flags);
|
|
- if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) {
|
|
+
|
|
+ virt_dev = xhci->devs[udev->slot_id];
|
|
+
|
|
+ /*
|
|
+ * virt_dev might not exists yet if xHC resumed from hibernate (S4) and
|
|
+ * xHC was re-initialized. Exit latency will be set later after
|
|
+ * hub_port_finish_reset() is done and xhci->devs[] are re-allocated
|
|
+ */
|
|
+
|
|
+ if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
|
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
/* Attempt to issue an Evaluate Context command to change the MEL. */
|
|
- virt_dev = xhci->devs[udev->slot_id];
|
|
command = xhci->lpm_command;
|
|
xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx);
|
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
|
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
|
|
index de98906f786d..0aef801edbc1 100644
|
|
--- a/drivers/usb/misc/sisusbvga/sisusb.c
|
|
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
|
|
@@ -3248,6 +3248,7 @@ static const struct usb_device_id sisusb_table[] = {
|
|
{ USB_DEVICE(0x0711, 0x0918) },
|
|
{ USB_DEVICE(0x0711, 0x0920) },
|
|
{ USB_DEVICE(0x0711, 0x0950) },
|
|
+ { USB_DEVICE(0x0711, 0x5200) },
|
|
{ USB_DEVICE(0x182d, 0x021c) },
|
|
{ USB_DEVICE(0x182d, 0x0269) },
|
|
{ }
|
|
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
|
|
index 120fff399c10..4235693ba2f7 100644
|
|
--- a/drivers/usb/serial/ftdi_sio.c
|
|
+++ b/drivers/usb/serial/ftdi_sio.c
|
|
@@ -744,6 +744,7 @@ static struct usb_device_id id_table_combined [] = {
|
|
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
|
|
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
|
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
|
|
+ { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) },
|
|
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
|
|
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
|
|
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
|
|
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
|
|
index 70b0b1d88ae9..8927a5c39b00 100644
|
|
--- a/drivers/usb/serial/ftdi_sio_ids.h
|
|
+++ b/drivers/usb/serial/ftdi_sio_ids.h
|
|
@@ -837,6 +837,12 @@
|
|
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
|
|
|
|
/*
|
|
+ * NOVITUS printers
|
|
+ */
|
|
+#define NOVITUS_VID 0x1a28
|
|
+#define NOVITUS_BONO_E_PID 0x6010
|
|
+
|
|
+/*
|
|
* RT Systems programming cables for various ham radios
|
|
*/
|
|
#define RTSYSTEMS_VID 0x2100 /* Vendor ID */
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
|
index 9da566a3f5c8..e47aabe0c760 100644
|
|
--- a/drivers/usb/serial/option.c
|
|
+++ b/drivers/usb/serial/option.c
|
|
@@ -275,8 +275,12 @@ static void option_instat_callback(struct urb *urb);
|
|
#define ZTE_PRODUCT_MF622 0x0001
|
|
#define ZTE_PRODUCT_MF628 0x0015
|
|
#define ZTE_PRODUCT_MF626 0x0031
|
|
-#define ZTE_PRODUCT_MC2718 0xffe8
|
|
#define ZTE_PRODUCT_AC2726 0xfff1
|
|
+#define ZTE_PRODUCT_CDMA_TECH 0xfffe
|
|
+#define ZTE_PRODUCT_AC8710T 0xffff
|
|
+#define ZTE_PRODUCT_MC2718 0xffe8
|
|
+#define ZTE_PRODUCT_AD3812 0xffeb
|
|
+#define ZTE_PRODUCT_MC2716 0xffed
|
|
|
|
#define BENQ_VENDOR_ID 0x04a5
|
|
#define BENQ_PRODUCT_H10 0x4068
|
|
@@ -494,6 +498,10 @@ static void option_instat_callback(struct urb *urb);
|
|
#define INOVIA_VENDOR_ID 0x20a6
|
|
#define INOVIA_SEW858 0x1105
|
|
|
|
+/* VIA Telecom */
|
|
+#define VIATELECOM_VENDOR_ID 0x15eb
|
|
+#define VIATELECOM_PRODUCT_CDS7 0x0001
|
|
+
|
|
/* some devices interfaces need special handling due to a number of reasons */
|
|
enum option_blacklist_reason {
|
|
OPTION_BLACKLIST_NONE = 0,
|
|
@@ -527,10 +535,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
|
|
.reserved = BIT(4),
|
|
};
|
|
|
|
+static const struct option_blacklist_info zte_ad3812_z_blacklist = {
|
|
+ .sendsetup = BIT(0) | BIT(1) | BIT(2),
|
|
+};
|
|
+
|
|
static const struct option_blacklist_info zte_mc2718_z_blacklist = {
|
|
.sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
|
|
};
|
|
|
|
+static const struct option_blacklist_info zte_mc2716_z_blacklist = {
|
|
+ .sendsetup = BIT(1) | BIT(2) | BIT(3),
|
|
+};
|
|
+
|
|
static const struct option_blacklist_info huawei_cdc12_blacklist = {
|
|
.reserved = BIT(1) | BIT(2),
|
|
};
|
|
@@ -1070,6 +1086,7 @@ static const struct usb_device_id option_ids[] = {
|
|
{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
|
|
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
|
|
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
|
|
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
|
|
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
|
|
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
|
|
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
|
|
@@ -1544,13 +1561,18 @@ static const struct usb_device_id option_ids[] = {
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) },
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) },
|
|
|
|
- /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
|
|
.driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
|
|
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
|
|
|
|
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
|
|
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
|
|
@@ -1724,6 +1746,7 @@ static const struct usb_device_id option_ids[] = {
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
|
|
{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
|
|
+ { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
|
|
{ } /* Terminating entry */
|
|
};
|
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
|
@@ -1917,6 +1940,8 @@ static void option_instat_callback(struct urb *urb)
|
|
dev_dbg(dev, "%s: type %x req %x\n", __func__,
|
|
req_pkt->bRequestType, req_pkt->bRequest);
|
|
}
|
|
+ } else if (status == -ENOENT || status == -ESHUTDOWN) {
|
|
+ dev_dbg(dev, "%s: urb stopped: %d\n", __func__, status);
|
|
} else
|
|
dev_err(dev, "%s: error %d\n", __func__, status);
|
|
|
|
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
|
|
index a0b58e252073..de3e15d8eb10 100644
|
|
--- a/drivers/usb/serial/pl2303.c
|
|
+++ b/drivers/usb/serial/pl2303.c
|
|
@@ -47,6 +47,7 @@ static const struct usb_device_id id_table[] = {
|
|
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
|
|
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
|
|
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
|
|
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
|
|
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
|
|
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
|
|
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
|
|
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
|
|
index 42bc082896ac..71fd9da1d6e7 100644
|
|
--- a/drivers/usb/serial/pl2303.h
|
|
+++ b/drivers/usb/serial/pl2303.h
|
|
@@ -22,6 +22,7 @@
|
|
#define PL2303_PRODUCT_ID_GPRS 0x0609
|
|
#define PL2303_PRODUCT_ID_HCR331 0x331a
|
|
#define PL2303_PRODUCT_ID_MOTOROLA 0x0307
|
|
+#define PL2303_PRODUCT_ID_ZTEK 0xe1f1
|
|
|
|
#define ATEN_VENDOR_ID 0x0557
|
|
#define ATEN_VENDOR_ID2 0x0547
|
|
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
|
|
index 4e4590854123..5aaa2b675116 100644
|
|
--- a/drivers/usb/serial/sierra.c
|
|
+++ b/drivers/usb/serial/sierra.c
|
|
@@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = {
|
|
/* Sierra Wireless HSPA Non-Composite Device */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
|
|
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
|
|
- { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
|
|
+ /* Sierra Wireless Direct IP modems */
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
|
|
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
|
|
+ },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
|
|
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
|
|
},
|
|
/* AT&T Direct IP LTE modems */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
|
|
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
|
|
},
|
|
- { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
|
|
+ /* Airprime/Sierra Wireless Direct IP modems */
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
|
|
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
|
|
},
|
|
|
|
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
|
|
index c1032d42b9d5..80d689f0fda9 100644
|
|
--- a/drivers/usb/serial/usb-serial.c
|
|
+++ b/drivers/usb/serial/usb-serial.c
|
|
@@ -778,29 +778,39 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
if (usb_endpoint_is_bulk_in(endpoint)) {
|
|
/* we found a bulk in endpoint */
|
|
dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
|
|
- bulk_in_endpoint[num_bulk_in] = endpoint;
|
|
- ++num_bulk_in;
|
|
+ if (num_bulk_in < MAX_NUM_PORTS) {
|
|
+ bulk_in_endpoint[num_bulk_in] = endpoint;
|
|
+ ++num_bulk_in;
|
|
+ }
|
|
}
|
|
|
|
if (usb_endpoint_is_bulk_out(endpoint)) {
|
|
/* we found a bulk out endpoint */
|
|
dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
|
|
- bulk_out_endpoint[num_bulk_out] = endpoint;
|
|
- ++num_bulk_out;
|
|
+ if (num_bulk_out < MAX_NUM_PORTS) {
|
|
+ bulk_out_endpoint[num_bulk_out] = endpoint;
|
|
+ ++num_bulk_out;
|
|
+ }
|
|
}
|
|
|
|
if (usb_endpoint_is_int_in(endpoint)) {
|
|
/* we found a interrupt in endpoint */
|
|
dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
|
|
- interrupt_in_endpoint[num_interrupt_in] = endpoint;
|
|
- ++num_interrupt_in;
|
|
+ if (num_interrupt_in < MAX_NUM_PORTS) {
|
|
+ interrupt_in_endpoint[num_interrupt_in] =
|
|
+ endpoint;
|
|
+ ++num_interrupt_in;
|
|
+ }
|
|
}
|
|
|
|
if (usb_endpoint_is_int_out(endpoint)) {
|
|
/* we found an interrupt out endpoint */
|
|
dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
|
|
- interrupt_out_endpoint[num_interrupt_out] = endpoint;
|
|
- ++num_interrupt_out;
|
|
+ if (num_interrupt_out < MAX_NUM_PORTS) {
|
|
+ interrupt_out_endpoint[num_interrupt_out] =
|
|
+ endpoint;
|
|
+ ++num_interrupt_out;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -823,8 +833,10 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
if (usb_endpoint_is_int_in(endpoint)) {
|
|
/* we found a interrupt in endpoint */
|
|
dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
|
|
- interrupt_in_endpoint[num_interrupt_in] = endpoint;
|
|
- ++num_interrupt_in;
|
|
+ if (num_interrupt_in < MAX_NUM_PORTS) {
|
|
+ interrupt_in_endpoint[num_interrupt_in] = endpoint;
|
|
+ ++num_interrupt_in;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -864,6 +876,11 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
num_ports = type->num_ports;
|
|
}
|
|
|
|
+ if (num_ports > MAX_NUM_PORTS) {
|
|
+ dev_warn(ddev, "too many ports requested: %d\n", num_ports);
|
|
+ num_ports = MAX_NUM_PORTS;
|
|
+ }
|
|
+
|
|
serial->num_ports = num_ports;
|
|
serial->num_bulk_in = num_bulk_in;
|
|
serial->num_bulk_out = num_bulk_out;
|
|
diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c
|
|
index eae2c873b39f..d6a3fbd029be 100644
|
|
--- a/drivers/usb/serial/zte_ev.c
|
|
+++ b/drivers/usb/serial/zte_ev.c
|
|
@@ -273,28 +273,16 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
|
|
}
|
|
|
|
static const struct usb_device_id id_table[] = {
|
|
- /* AC8710, AC8710T */
|
|
- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) },
|
|
- /* AC8700 */
|
|
- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) },
|
|
- /* MG880 */
|
|
- { USB_DEVICE(0x19d2, 0xfffd) },
|
|
- { USB_DEVICE(0x19d2, 0xfffc) },
|
|
- { USB_DEVICE(0x19d2, 0xfffb) },
|
|
- /* AC8710_V3 */
|
|
+ { USB_DEVICE(0x19d2, 0xffec) },
|
|
+ { USB_DEVICE(0x19d2, 0xffee) },
|
|
{ USB_DEVICE(0x19d2, 0xfff6) },
|
|
{ USB_DEVICE(0x19d2, 0xfff7) },
|
|
{ USB_DEVICE(0x19d2, 0xfff8) },
|
|
{ USB_DEVICE(0x19d2, 0xfff9) },
|
|
- { USB_DEVICE(0x19d2, 0xffee) },
|
|
- /* AC2716, MC2716 */
|
|
- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) },
|
|
- /* AD3812 */
|
|
- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) },
|
|
- { USB_DEVICE(0x19d2, 0xffec) },
|
|
- { USB_DEVICE(0x05C6, 0x3197) },
|
|
- { USB_DEVICE(0x05C6, 0x6000) },
|
|
- { USB_DEVICE(0x05C6, 0x9008) },
|
|
+ { USB_DEVICE(0x19d2, 0xfffb) },
|
|
+ { USB_DEVICE(0x19d2, 0xfffc) },
|
|
+ /* MG880 */
|
|
+ { USB_DEVICE(0x19d2, 0xfffd) },
|
|
{ },
|
|
};
|
|
MODULE_DEVICE_TABLE(usb, id_table);
|
|
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
|
|
index 042c83b01046..7f625306ea80 100644
|
|
--- a/drivers/usb/storage/unusual_devs.h
|
|
+++ b/drivers/usb/storage/unusual_devs.h
|
|
@@ -101,6 +101,12 @@ UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001,
|
|
"PhotoSmart R707",
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
|
|
|
|
+UNUSUAL_DEV( 0x03f3, 0x0001, 0x0000, 0x9999,
|
|
+ "Adaptec",
|
|
+ "USBConnect 2000",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
+
|
|
/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
|
|
* and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
|
|
* for USB floppies that need the SINGLE_LUN enforcement.
|
|
@@ -741,6 +747,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_SINGLE_LUN ),
|
|
|
|
+UNUSUAL_DEV( 0x059b, 0x0040, 0x0100, 0x0100,
|
|
+ "Iomega",
|
|
+ "Jaz USB Adapter",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
+ US_FL_SINGLE_LUN ),
|
|
+
|
|
/* Reported by <Hendryk.Pfeiffer@gmx.de> */
|
|
UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000,
|
|
"LaCie",
|
|
@@ -1113,6 +1125,18 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_NOT_LOCKABLE),
|
|
|
|
+UNUSUAL_DEV( 0x085a, 0x0026, 0x0100, 0x0133,
|
|
+ "Xircom",
|
|
+ "PortGear USB-SCSI (Mac USB Dock)",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
+
|
|
+UNUSUAL_DEV( 0x085a, 0x0028, 0x0100, 0x0133,
|
|
+ "Xircom",
|
|
+ "PortGear USB to SCSI Converter",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
+
|
|
/* Submitted by Jan De Luyck <lkml@kcore.org> */
|
|
UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
|
|
"CITIZEN",
|
|
@@ -1945,6 +1969,14 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
|
|
|
|
+/* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI)
|
|
+ * and Mac USB Dock USB-SCSI */
|
|
+UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133,
|
|
+ "Entrega Technologies",
|
|
+ "USB to SCSI Converter",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
+
|
|
/* Reported by Robert Schedel <r.schedel@yahoo.de>
|
|
* Note: this is a 'super top' device like the above 14cd/6600 device */
|
|
UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
|
|
@@ -1967,6 +1999,12 @@ UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
|
|
|
|
+UNUSUAL_DEV( 0x1822, 0x0001, 0x0000, 0x9999,
|
|
+ "Ariston Technologies",
|
|
+ "iConnect USB to SCSI adapter",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
+
|
|
/* Reported by Hans de Goede <hdegoede@redhat.com>
|
|
* These Appotech controllers are found in Picture Frames, they provide a
|
|
* (buggy) emulation of a cdrom drive which contains the windows software
|
|
diff --git a/fs/buffer.c b/fs/buffer.c
|
|
index 75964d734444..10fca21ee8aa 100644
|
|
--- a/fs/buffer.c
|
|
+++ b/fs/buffer.c
|
|
@@ -985,7 +985,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
|
|
bh = page_buffers(page);
|
|
if (bh->b_size == size) {
|
|
end_block = init_page_buffers(page, bdev,
|
|
- index << sizebits, size);
|
|
+ (sector_t)index << sizebits,
|
|
+ size);
|
|
goto done;
|
|
}
|
|
if (!try_to_free_buffers(page))
|
|
@@ -1006,7 +1007,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
|
|
*/
|
|
spin_lock(&inode->i_mapping->private_lock);
|
|
link_dev_buffers(page, bh);
|
|
- end_block = init_page_buffers(page, bdev, index << sizebits, size);
|
|
+ end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits,
|
|
+ size);
|
|
spin_unlock(&inode->i_mapping->private_lock);
|
|
done:
|
|
ret = (block < end_block) ? 1 : -ENXIO;
|
|
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
|
|
index 52480240168e..f74dfa89c4c4 100644
|
|
--- a/fs/cifs/cifsglob.h
|
|
+++ b/fs/cifs/cifsglob.h
|
|
@@ -375,6 +375,8 @@ struct smb_version_operations {
|
|
const char *, u32 *);
|
|
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
|
|
int);
|
|
+ /* check if we need to issue closedir */
|
|
+ bool (*dir_needs_close)(struct cifsFileInfo *);
|
|
};
|
|
|
|
struct smb_version_values {
|
|
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
|
|
index 97b03895ac8c..5fcc10fa62bd 100644
|
|
--- a/fs/cifs/file.c
|
|
+++ b/fs/cifs/file.c
|
|
@@ -735,7 +735,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|
|
|
cifs_dbg(FYI, "Freeing private data in close dir\n");
|
|
spin_lock(&cifs_file_list_lock);
|
|
- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
|
+ if (server->ops->dir_needs_close(cfile)) {
|
|
cfile->invalidHandle = true;
|
|
spin_unlock(&cifs_file_list_lock);
|
|
if (server->ops->close_dir)
|
|
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
|
|
index c9bce9b43855..0dee93706c98 100644
|
|
--- a/fs/cifs/inode.c
|
|
+++ b/fs/cifs/inode.c
|
|
@@ -1640,7 +1640,10 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
|
unlink_target:
|
|
/* Try unlinking the target dentry if it's not negative */
|
|
if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
|
|
- tmprc = cifs_unlink(target_dir, target_dentry);
|
|
+ if (S_ISDIR(target_dentry->d_inode->i_mode))
|
|
+ tmprc = cifs_rmdir(target_dir, target_dentry);
|
|
+ else
|
|
+ tmprc = cifs_unlink(target_dir, target_dentry);
|
|
if (tmprc)
|
|
goto cifs_rename_exit;
|
|
rc = cifs_do_rename(xid, source_dentry, from_name,
|
|
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
|
|
index 87d125f682cd..85ebdaa21015 100644
|
|
--- a/fs/cifs/readdir.c
|
|
+++ b/fs/cifs/readdir.c
|
|
@@ -582,7 +582,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
|
|
/* close and restart search */
|
|
cifs_dbg(FYI, "search backing up - close and restart search\n");
|
|
spin_lock(&cifs_file_list_lock);
|
|
- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
|
+ if (server->ops->dir_needs_close(cfile)) {
|
|
cfile->invalidHandle = true;
|
|
spin_unlock(&cifs_file_list_lock);
|
|
if (server->ops->close_dir)
|
|
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
|
|
index 4885a40f3210..610c6c24d41d 100644
|
|
--- a/fs/cifs/smb1ops.c
|
|
+++ b/fs/cifs/smb1ops.c
|
|
@@ -885,6 +885,12 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
|
|
(__u8)type, wait, 0);
|
|
}
|
|
|
|
+static bool
|
|
+cifs_dir_needs_close(struct cifsFileInfo *cfile)
|
|
+{
|
|
+ return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
|
|
+}
|
|
+
|
|
struct smb_version_operations smb1_operations = {
|
|
.send_cancel = send_nt_cancel,
|
|
.compare_fids = cifs_compare_fids,
|
|
@@ -948,6 +954,7 @@ struct smb_version_operations smb1_operations = {
|
|
.mand_lock = cifs_mand_lock,
|
|
.mand_unlock_range = cifs_unlock_range,
|
|
.push_mand_locks = cifs_push_mandatory_locks,
|
|
+ .dir_needs_close = cifs_dir_needs_close,
|
|
#ifdef CONFIG_CIFS_XATTR
|
|
.query_all_EAs = CIFSSMBQAllEAs,
|
|
.set_EA = CIFSSMBSetEA,
|
|
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
|
|
index 824696fb24db..4768cf8be6e2 100644
|
|
--- a/fs/cifs/smb2maperror.c
|
|
+++ b/fs/cifs/smb2maperror.c
|
|
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
|
|
{STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
|
|
{STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
|
|
{STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
|
|
- {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"},
|
|
+ {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
|
|
{STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
|
|
{STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
|
|
{STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
|
|
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
|
|
index fe7ac989c6c4..e12f258a5ffa 100644
|
|
--- a/fs/cifs/smb2ops.c
|
|
+++ b/fs/cifs/smb2ops.c
|
|
@@ -554,6 +554,12 @@ smb2_new_lease_key(struct cifs_fid *fid)
|
|
get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
|
|
}
|
|
|
|
+static bool
|
|
+smb2_dir_needs_close(struct cifsFileInfo *cfile)
|
|
+{
|
|
+ return !cfile->invalidHandle;
|
|
+}
|
|
+
|
|
struct smb_version_operations smb21_operations = {
|
|
.compare_fids = smb2_compare_fids,
|
|
.setup_request = smb2_setup_request,
|
|
@@ -618,6 +624,7 @@ struct smb_version_operations smb21_operations = {
|
|
.set_lease_key = smb2_set_lease_key,
|
|
.new_lease_key = smb2_new_lease_key,
|
|
.calc_signature = smb2_calc_signature,
|
|
+ .dir_needs_close = smb2_dir_needs_close,
|
|
};
|
|
|
|
|
|
@@ -685,6 +692,7 @@ struct smb_version_operations smb30_operations = {
|
|
.set_lease_key = smb2_set_lease_key,
|
|
.new_lease_key = smb2_new_lease_key,
|
|
.calc_signature = smb3_calc_signature,
|
|
+ .dir_needs_close = smb2_dir_needs_close,
|
|
};
|
|
|
|
struct smb_version_values smb20_values = {
|
|
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
|
|
index e37790841446..eb0de4c3ca76 100644
|
|
--- a/fs/cifs/smb2pdu.c
|
|
+++ b/fs/cifs/smb2pdu.c
|
|
@@ -1800,6 +1800,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
|
|
|
|
if (rc) {
|
|
+ if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
|
|
+ srch_inf->endOfSearch = true;
|
|
+ rc = 0;
|
|
+ }
|
|
cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
|
|
goto qdir_exit;
|
|
}
|
|
@@ -1837,11 +1841,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
else
|
|
cifs_dbg(VFS, "illegal search buffer type\n");
|
|
|
|
- if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
|
|
- srch_inf->endOfSearch = 1;
|
|
- else
|
|
- srch_inf->endOfSearch = 0;
|
|
-
|
|
return rc;
|
|
|
|
qdir_exit:
|
|
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
|
|
index 0a87bb10998d..99d84ce038b8 100644
|
|
--- a/fs/ext2/inode.c
|
|
+++ b/fs/ext2/inode.c
|
|
@@ -632,6 +632,8 @@ static int ext2_get_blocks(struct inode *inode,
|
|
int count = 0;
|
|
ext2_fsblk_t first_block = 0;
|
|
|
|
+ BUG_ON(maxblocks == 0);
|
|
+
|
|
depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
|
|
|
|
if (depth == 0)
|
|
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
|
|
index 1c3312858fcf..e98171a11cfe 100644
|
|
--- a/fs/ext2/xip.c
|
|
+++ b/fs/ext2/xip.c
|
|
@@ -35,6 +35,7 @@ __ext2_get_block(struct inode *inode, pgoff_t pgoff, int create,
|
|
int rc;
|
|
|
|
memset(&tmp, 0, sizeof(struct buffer_head));
|
|
+ tmp.b_size = 1 << inode->i_blkbits;
|
|
rc = ext2_get_block(inode, pgoff, &tmp, create);
|
|
*result = tmp.b_blocknr;
|
|
|
|
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
|
|
index d56a9904e52a..9c8a5a6d33df 100644
|
|
--- a/fs/lockd/svc.c
|
|
+++ b/fs/lockd/svc.c
|
|
@@ -253,13 +253,11 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
|
|
|
|
error = make_socks(serv, net);
|
|
if (error < 0)
|
|
- goto err_socks;
|
|
+ goto err_bind;
|
|
set_grace_period(net);
|
|
dprintk("lockd_up_net: per-net data created; net=%p\n", net);
|
|
return 0;
|
|
|
|
-err_socks:
|
|
- svc_rpcb_cleanup(serv, net);
|
|
err_bind:
|
|
ln->nlmsvc_users--;
|
|
return error;
|
|
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
|
|
index 02773aab43c5..cc143ee7a56e 100644
|
|
--- a/fs/nfs/nfs4client.c
|
|
+++ b/fs/nfs/nfs4client.c
|
|
@@ -311,6 +311,16 @@ int nfs40_walk_client_list(struct nfs_client *new,
|
|
|
|
spin_lock(&nn->nfs_client_lock);
|
|
list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
|
|
+
|
|
+ if (pos->rpc_ops != new->rpc_ops)
|
|
+ continue;
|
|
+
|
|
+ if (pos->cl_proto != new->cl_proto)
|
|
+ continue;
|
|
+
|
|
+ if (pos->cl_minorversion != new->cl_minorversion)
|
|
+ continue;
|
|
+
|
|
/* If "pos" isn't marked ready, we can't trust the
|
|
* remaining fields in "pos" */
|
|
if (pos->cl_cons_state > NFS_CS_READY) {
|
|
@@ -330,15 +340,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
|
|
if (pos->cl_cons_state != NFS_CS_READY)
|
|
continue;
|
|
|
|
- if (pos->rpc_ops != new->rpc_ops)
|
|
- continue;
|
|
-
|
|
- if (pos->cl_proto != new->cl_proto)
|
|
- continue;
|
|
-
|
|
- if (pos->cl_minorversion != new->cl_minorversion)
|
|
- continue;
|
|
-
|
|
if (pos->cl_clientid != new->cl_clientid)
|
|
continue;
|
|
|
|
@@ -444,6 +445,16 @@ int nfs41_walk_client_list(struct nfs_client *new,
|
|
|
|
spin_lock(&nn->nfs_client_lock);
|
|
list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
|
|
+
|
|
+ if (pos->rpc_ops != new->rpc_ops)
|
|
+ continue;
|
|
+
|
|
+ if (pos->cl_proto != new->cl_proto)
|
|
+ continue;
|
|
+
|
|
+ if (pos->cl_minorversion != new->cl_minorversion)
|
|
+ continue;
|
|
+
|
|
/* If "pos" isn't marked ready, we can't trust the
|
|
* remaining fields in "pos", especially the client
|
|
* ID and serverowner fields. Wait for CREATE_SESSION
|
|
@@ -469,15 +480,6 @@ int nfs41_walk_client_list(struct nfs_client *new,
|
|
if (pos->cl_cons_state != NFS_CS_READY)
|
|
continue;
|
|
|
|
- if (pos->rpc_ops != new->rpc_ops)
|
|
- continue;
|
|
-
|
|
- if (pos->cl_proto != new->cl_proto)
|
|
- continue;
|
|
-
|
|
- if (pos->cl_minorversion != new->cl_minorversion)
|
|
- continue;
|
|
-
|
|
if (!nfs4_match_clientids(pos, new))
|
|
continue;
|
|
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 25559821771b..3fc87b6f9def 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -2299,23 +2299,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
|
is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
|
|
is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
|
|
is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
|
|
- /* Calculate the current open share mode */
|
|
- calldata->arg.fmode = 0;
|
|
- if (is_rdonly || is_rdwr)
|
|
- calldata->arg.fmode |= FMODE_READ;
|
|
- if (is_wronly || is_rdwr)
|
|
- calldata->arg.fmode |= FMODE_WRITE;
|
|
/* Calculate the change in open mode */
|
|
+ calldata->arg.fmode = 0;
|
|
if (state->n_rdwr == 0) {
|
|
- if (state->n_rdonly == 0) {
|
|
- call_close |= is_rdonly || is_rdwr;
|
|
- calldata->arg.fmode &= ~FMODE_READ;
|
|
- }
|
|
- if (state->n_wronly == 0) {
|
|
- call_close |= is_wronly || is_rdwr;
|
|
- calldata->arg.fmode &= ~FMODE_WRITE;
|
|
- }
|
|
- }
|
|
+ if (state->n_rdonly == 0)
|
|
+ call_close |= is_rdonly;
|
|
+ else if (is_rdonly)
|
|
+ calldata->arg.fmode |= FMODE_READ;
|
|
+ if (state->n_wronly == 0)
|
|
+ call_close |= is_wronly;
|
|
+ else if (is_wronly)
|
|
+ calldata->arg.fmode |= FMODE_WRITE;
|
|
+ } else if (is_rdwr)
|
|
+ calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
|
|
+
|
|
+ if (calldata->arg.fmode == 0)
|
|
+ call_close |= is_rdwr;
|
|
+
|
|
if (!nfs4_valid_open_stateid(state))
|
|
call_close = 0;
|
|
spin_unlock(&state->owner->so_lock);
|
|
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
|
|
index bccfec8343c5..2e1372efbb00 100644
|
|
--- a/fs/nilfs2/inode.c
|
|
+++ b/fs/nilfs2/inode.c
|
|
@@ -24,6 +24,7 @@
|
|
#include <linux/buffer_head.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/mpage.h>
|
|
+#include <linux/pagemap.h>
|
|
#include <linux/writeback.h>
|
|
#include <linux/aio.h>
|
|
#include "nilfs.h"
|
|
@@ -219,10 +220,10 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc)
|
|
|
|
static int nilfs_set_page_dirty(struct page *page)
|
|
{
|
|
+ struct inode *inode = page->mapping->host;
|
|
int ret = __set_page_dirty_nobuffers(page);
|
|
|
|
if (page_has_buffers(page)) {
|
|
- struct inode *inode = page->mapping->host;
|
|
unsigned nr_dirty = 0;
|
|
struct buffer_head *bh, *head;
|
|
|
|
@@ -245,6 +246,10 @@ static int nilfs_set_page_dirty(struct page *page)
|
|
|
|
if (nr_dirty)
|
|
nilfs_set_file_dirty(inode, nr_dirty);
|
|
+ } else if (ret) {
|
|
+ unsigned nr_dirty = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
|
+
|
|
+ nilfs_set_file_dirty(inode, nr_dirty);
|
|
}
|
|
return ret;
|
|
}
|
|
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
|
|
index 238a5930cb3c..9d7e2b9659cb 100644
|
|
--- a/fs/notify/fdinfo.c
|
|
+++ b/fs/notify/fdinfo.c
|
|
@@ -42,7 +42,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
|
|
{
|
|
struct {
|
|
struct file_handle handle;
|
|
- u8 pad[64];
|
|
+ u8 pad[MAX_HANDLE_SZ];
|
|
} f;
|
|
int size, ret, i;
|
|
|
|
@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
|
|
size = f.handle.handle_bytes >> 2;
|
|
|
|
ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0);
|
|
- if ((ret == 255) || (ret == -ENOSPC)) {
|
|
+ if ((ret == FILEID_INVALID) || (ret < 0)) {
|
|
WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret);
|
|
return 0;
|
|
}
|
|
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
|
|
index 33ecbe0e6734..2b941113e423 100644
|
|
--- a/fs/ocfs2/dlm/dlmmaster.c
|
|
+++ b/fs/ocfs2/dlm/dlmmaster.c
|
|
@@ -653,12 +653,9 @@ void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
|
|
clear_bit(bit, res->refmap);
|
|
}
|
|
|
|
-
|
|
-void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
|
+static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
|
struct dlm_lock_resource *res)
|
|
{
|
|
- assert_spin_locked(&res->spinlock);
|
|
-
|
|
res->inflight_locks++;
|
|
|
|
mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name,
|
|
@@ -666,6 +663,13 @@ void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
|
__builtin_return_address(0));
|
|
}
|
|
|
|
+void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
|
+ struct dlm_lock_resource *res)
|
|
+{
|
|
+ assert_spin_locked(&res->spinlock);
|
|
+ __dlm_lockres_grab_inflight_ref(dlm, res);
|
|
+}
|
|
+
|
|
void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
|
|
struct dlm_lock_resource *res)
|
|
{
|
|
@@ -855,10 +859,8 @@ lookup:
|
|
/* finally add the lockres to its hash bucket */
|
|
__dlm_insert_lockres(dlm, res);
|
|
|
|
- /* Grab inflight ref to pin the resource */
|
|
- spin_lock(&res->spinlock);
|
|
- dlm_lockres_grab_inflight_ref(dlm, res);
|
|
- spin_unlock(&res->spinlock);
|
|
+ /* since this lockres is new it doesn't not require the spinlock */
|
|
+ __dlm_lockres_grab_inflight_ref(dlm, res);
|
|
|
|
/* get an extra ref on the mle in case this is a BLOCK
|
|
* if so, the creator of the BLOCK may try to put the last
|
|
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h
|
|
index 3869c525b052..545deb149655 100644
|
|
--- a/include/linux/iio/trigger.h
|
|
+++ b/include/linux/iio/trigger.h
|
|
@@ -83,10 +83,12 @@ static inline void iio_trigger_put(struct iio_trigger *trig)
|
|
put_device(&trig->dev);
|
|
}
|
|
|
|
-static inline void iio_trigger_get(struct iio_trigger *trig)
|
|
+static inline struct iio_trigger *iio_trigger_get(struct iio_trigger *trig)
|
|
{
|
|
get_device(&trig->dev);
|
|
__module_get(trig->ops->owner);
|
|
+
|
|
+ return trig;
|
|
}
|
|
|
|
/**
|
|
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
|
|
index 5cd0f0949927..998f4dfedecf 100644
|
|
--- a/include/linux/init_task.h
|
|
+++ b/include/linux/init_task.h
|
|
@@ -40,6 +40,7 @@ extern struct fs_struct init_fs;
|
|
|
|
#define INIT_SIGNALS(sig) { \
|
|
.nr_threads = 1, \
|
|
+ .thread_head = LIST_HEAD_INIT(init_task.thread_node), \
|
|
.wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
|
|
.shared_pending = { \
|
|
.list = LIST_HEAD_INIT(sig.shared_pending.list), \
|
|
@@ -213,6 +214,7 @@ extern struct task_group root_task_group;
|
|
[PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
|
|
}, \
|
|
.thread_group = LIST_HEAD_INIT(tsk.thread_group), \
|
|
+ .thread_node = LIST_HEAD_INIT(init_signals.thread_head), \
|
|
INIT_IDS \
|
|
INIT_PERF_EVENTS(tsk) \
|
|
INIT_TRACE_IRQFLAGS \
|
|
diff --git a/include/linux/sched.h b/include/linux/sched.h
|
|
index 597c8ab005a0..8293545ac9b7 100644
|
|
--- a/include/linux/sched.h
|
|
+++ b/include/linux/sched.h
|
|
@@ -480,6 +480,7 @@ struct signal_struct {
|
|
atomic_t sigcnt;
|
|
atomic_t live;
|
|
int nr_threads;
|
|
+ struct list_head thread_head;
|
|
|
|
wait_queue_head_t wait_chldexit; /* for wait4() */
|
|
|
|
@@ -1160,6 +1161,7 @@ struct task_struct {
|
|
/* PID/PID hash table linkage. */
|
|
struct pid_link pids[PIDTYPE_MAX];
|
|
struct list_head thread_group;
|
|
+ struct list_head thread_node;
|
|
|
|
struct completion *vfork_done; /* for vfork() */
|
|
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
|
|
@@ -2167,6 +2169,16 @@ extern bool current_is_single_threaded(void);
|
|
#define while_each_thread(g, t) \
|
|
while ((t = next_thread(t)) != g)
|
|
|
|
+#define __for_each_thread(signal, t) \
|
|
+ list_for_each_entry_rcu(t, &(signal)->thread_head, thread_node)
|
|
+
|
|
+#define for_each_thread(p, t) \
|
|
+ __for_each_thread((p)->signal, t)
|
|
+
|
|
+/* Careful: this is a double loop, 'break' won't work as expected. */
|
|
+#define for_each_process_thread(p, t) \
|
|
+ for_each_process(p) for_each_thread(p, t)
|
|
+
|
|
static inline int get_nr_threads(struct task_struct *tsk)
|
|
{
|
|
return tsk->signal->nr_threads;
|
|
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
|
|
index 623488fdc1f5..ff28cf578d01 100644
|
|
--- a/include/linux/workqueue.h
|
|
+++ b/include/linux/workqueue.h
|
|
@@ -414,7 +414,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
|
|
#define create_freezable_workqueue(name) \
|
|
alloc_workqueue((name), WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
|
|
#define create_singlethread_workqueue(name) \
|
|
- alloc_workqueue((name), WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
|
|
+ alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name)
|
|
|
|
extern void destroy_workqueue(struct workqueue_struct *wq);
|
|
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index 459b94c94721..6bf387a60399 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -1398,6 +1398,11 @@ retry:
|
|
*/
|
|
if (ctx->is_active) {
|
|
raw_spin_unlock_irq(&ctx->lock);
|
|
+ /*
|
|
+ * Reload the task pointer, it might have been changed by
|
|
+ * a concurrent perf_event_context_sched_out().
|
|
+ */
|
|
+ task = ctx->task;
|
|
goto retry;
|
|
}
|
|
|
|
@@ -1829,6 +1834,11 @@ retry:
|
|
*/
|
|
if (ctx->is_active) {
|
|
raw_spin_unlock_irq(&ctx->lock);
|
|
+ /*
|
|
+ * Reload the task pointer, it might have been changed by
|
|
+ * a concurrent perf_event_context_sched_out().
|
|
+ */
|
|
+ task = ctx->task;
|
|
goto retry;
|
|
}
|
|
|
|
diff --git a/kernel/exit.c b/kernel/exit.c
|
|
index 6682b2ea5b11..717efbd7cb72 100644
|
|
--- a/kernel/exit.c
|
|
+++ b/kernel/exit.c
|
|
@@ -74,6 +74,7 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
|
|
__this_cpu_dec(process_counts);
|
|
}
|
|
list_del_rcu(&p->thread_group);
|
|
+ list_del_rcu(&p->thread_node);
|
|
}
|
|
|
|
/*
|
|
diff --git a/kernel/fork.c b/kernel/fork.c
|
|
index 814363a69b80..2c76e11ba939 100644
|
|
--- a/kernel/fork.c
|
|
+++ b/kernel/fork.c
|
|
@@ -1045,6 +1045,11 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
|
|
sig->nr_threads = 1;
|
|
atomic_set(&sig->live, 1);
|
|
atomic_set(&sig->sigcnt, 1);
|
|
+
|
|
+ /* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
|
|
+ sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
|
|
+ tsk->thread_node = (struct list_head)LIST_HEAD_INIT(sig->thread_head);
|
|
+
|
|
init_waitqueue_head(&sig->wait_chldexit);
|
|
sig->curr_target = tsk;
|
|
init_sigpending(&sig->shared_pending);
|
|
@@ -1448,14 +1453,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|
goto bad_fork_free_pid;
|
|
}
|
|
|
|
- if (clone_flags & CLONE_THREAD) {
|
|
- current->signal->nr_threads++;
|
|
- atomic_inc(¤t->signal->live);
|
|
- atomic_inc(¤t->signal->sigcnt);
|
|
- p->group_leader = current->group_leader;
|
|
- list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
|
|
- }
|
|
-
|
|
if (likely(p->pid)) {
|
|
ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
|
|
|
|
@@ -1472,6 +1469,15 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|
list_add_tail(&p->sibling, &p->real_parent->children);
|
|
list_add_tail_rcu(&p->tasks, &init_task.tasks);
|
|
__this_cpu_inc(process_counts);
|
|
+ } else {
|
|
+ current->signal->nr_threads++;
|
|
+ atomic_inc(¤t->signal->live);
|
|
+ atomic_inc(¤t->signal->sigcnt);
|
|
+ p->group_leader = current->group_leader;
|
|
+ list_add_tail_rcu(&p->thread_group,
|
|
+ &p->group_leader->thread_group);
|
|
+ list_add_tail_rcu(&p->thread_node,
|
|
+ &p->signal->thread_head);
|
|
}
|
|
attach_pid(p, PIDTYPE_PID, pid);
|
|
nr_threads++;
|
|
diff --git a/kernel/kcmp.c b/kernel/kcmp.c
|
|
index e30ac0fe61c3..0aa69ea1d8fd 100644
|
|
--- a/kernel/kcmp.c
|
|
+++ b/kernel/kcmp.c
|
|
@@ -44,11 +44,12 @@ static long kptr_obfuscate(long v, int type)
|
|
*/
|
|
static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type)
|
|
{
|
|
- long ret;
|
|
+ long t1, t2;
|
|
|
|
- ret = kptr_obfuscate((long)v1, type) - kptr_obfuscate((long)v2, type);
|
|
+ t1 = kptr_obfuscate((long)v1, type);
|
|
+ t2 = kptr_obfuscate((long)v2, type);
|
|
|
|
- return (ret < 0) | ((ret > 0) << 1);
|
|
+ return (t1 < t2) | ((t1 > t2) << 1);
|
|
}
|
|
|
|
/* The caller must have pinned the task */
|
|
diff --git a/kernel/power/main.c b/kernel/power/main.c
|
|
index d77663bfedeb..312c1b2c725d 100644
|
|
--- a/kernel/power/main.c
|
|
+++ b/kernel/power/main.c
|
|
@@ -293,12 +293,12 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
{
|
|
char *s = buf;
|
|
#ifdef CONFIG_SUSPEND
|
|
- int i;
|
|
+ suspend_state_t i;
|
|
+
|
|
+ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
|
|
+ if (pm_states[i].state)
|
|
+ s += sprintf(s,"%s ", pm_states[i].label);
|
|
|
|
- for (i = 0; i < PM_SUSPEND_MAX; i++) {
|
|
- if (pm_states[i] && valid_state(i))
|
|
- s += sprintf(s,"%s ", pm_states[i]);
|
|
- }
|
|
#endif
|
|
#ifdef CONFIG_HIBERNATION
|
|
s += sprintf(s, "%s\n", "disk");
|
|
@@ -314,7 +314,7 @@ static suspend_state_t decode_state(const char *buf, size_t n)
|
|
{
|
|
#ifdef CONFIG_SUSPEND
|
|
suspend_state_t state = PM_SUSPEND_MIN;
|
|
- const char * const *s;
|
|
+ struct pm_sleep_state *s;
|
|
#endif
|
|
char *p;
|
|
int len;
|
|
@@ -328,8 +328,9 @@ static suspend_state_t decode_state(const char *buf, size_t n)
|
|
|
|
#ifdef CONFIG_SUSPEND
|
|
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++)
|
|
- if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
|
|
- return state;
|
|
+ if (s->state && len == strlen(s->label)
|
|
+ && !strncmp(buf, s->label, len))
|
|
+ return s->state;
|
|
#endif
|
|
|
|
return PM_SUSPEND_ON;
|
|
@@ -445,8 +446,8 @@ static ssize_t autosleep_show(struct kobject *kobj,
|
|
|
|
#ifdef CONFIG_SUSPEND
|
|
if (state < PM_SUSPEND_MAX)
|
|
- return sprintf(buf, "%s\n", valid_state(state) ?
|
|
- pm_states[state] : "error");
|
|
+ return sprintf(buf, "%s\n", pm_states[state].state ?
|
|
+ pm_states[state].label : "error");
|
|
#endif
|
|
#ifdef CONFIG_HIBERNATION
|
|
return sprintf(buf, "disk\n");
|
|
diff --git a/kernel/power/power.h b/kernel/power/power.h
|
|
index 7d4b7ffb3c1d..f770cad3666c 100644
|
|
--- a/kernel/power/power.h
|
|
+++ b/kernel/power/power.h
|
|
@@ -175,17 +175,20 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *,
|
|
unsigned int, char *);
|
|
|
|
#ifdef CONFIG_SUSPEND
|
|
+struct pm_sleep_state {
|
|
+ const char *label;
|
|
+ suspend_state_t state;
|
|
+};
|
|
+
|
|
/* kernel/power/suspend.c */
|
|
-extern const char *const pm_states[];
|
|
+extern struct pm_sleep_state pm_states[];
|
|
|
|
-extern bool valid_state(suspend_state_t state);
|
|
extern int suspend_devices_and_enter(suspend_state_t state);
|
|
#else /* !CONFIG_SUSPEND */
|
|
static inline int suspend_devices_and_enter(suspend_state_t state)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
-static inline bool valid_state(suspend_state_t state) { return false; }
|
|
#endif /* !CONFIG_SUSPEND */
|
|
|
|
#ifdef CONFIG_PM_TEST_SUSPEND
|
|
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
|
index bef86d121eb2..903c517b14da 100644
|
|
--- a/kernel/power/suspend.c
|
|
+++ b/kernel/power/suspend.c
|
|
@@ -29,10 +29,10 @@
|
|
|
|
#include "power.h"
|
|
|
|
-const char *const pm_states[PM_SUSPEND_MAX] = {
|
|
- [PM_SUSPEND_FREEZE] = "freeze",
|
|
- [PM_SUSPEND_STANDBY] = "standby",
|
|
- [PM_SUSPEND_MEM] = "mem",
|
|
+struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = {
|
|
+ [PM_SUSPEND_FREEZE] = { .label = "freeze", .state = PM_SUSPEND_FREEZE },
|
|
+ [PM_SUSPEND_STANDBY] = { .label = "standby", },
|
|
+ [PM_SUSPEND_MEM] = { .label = "mem", },
|
|
};
|
|
|
|
static const struct platform_suspend_ops *suspend_ops;
|
|
@@ -62,42 +62,34 @@ void freeze_wake(void)
|
|
}
|
|
EXPORT_SYMBOL_GPL(freeze_wake);
|
|
|
|
+static bool valid_state(suspend_state_t state)
|
|
+{
|
|
+ /*
|
|
+ * PM_SUSPEND_STANDBY and PM_SUSPEND_MEM states need low level
|
|
+ * support and need to be valid to the low level
|
|
+ * implementation, no valid callback implies that none are valid.
|
|
+ */
|
|
+ return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
|
|
+}
|
|
+
|
|
/**
|
|
* suspend_set_ops - Set the global suspend method table.
|
|
* @ops: Suspend operations to use.
|
|
*/
|
|
void suspend_set_ops(const struct platform_suspend_ops *ops)
|
|
{
|
|
+ suspend_state_t i;
|
|
+
|
|
lock_system_sleep();
|
|
+
|
|
suspend_ops = ops;
|
|
+ for (i = PM_SUSPEND_STANDBY; i <= PM_SUSPEND_MEM; i++)
|
|
+ pm_states[i].state = valid_state(i) ? i : 0;
|
|
+
|
|
unlock_system_sleep();
|
|
}
|
|
EXPORT_SYMBOL_GPL(suspend_set_ops);
|
|
|
|
-bool valid_state(suspend_state_t state)
|
|
-{
|
|
- if (state == PM_SUSPEND_FREEZE) {
|
|
-#ifdef CONFIG_PM_DEBUG
|
|
- if (pm_test_level != TEST_NONE &&
|
|
- pm_test_level != TEST_FREEZER &&
|
|
- pm_test_level != TEST_DEVICES &&
|
|
- pm_test_level != TEST_PLATFORM) {
|
|
- printk(KERN_WARNING "Unsupported pm_test mode for "
|
|
- "freeze state, please choose "
|
|
- "none/freezer/devices/platform.\n");
|
|
- return false;
|
|
- }
|
|
-#endif
|
|
- return true;
|
|
- }
|
|
- /*
|
|
- * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel
|
|
- * support and need to be valid to the lowlevel
|
|
- * implementation, no valid callback implies that none are valid.
|
|
- */
|
|
- return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
|
|
-}
|
|
-
|
|
/**
|
|
* suspend_valid_only_mem - Generic memory-only valid callback.
|
|
*
|
|
@@ -324,9 +316,17 @@ static int enter_state(suspend_state_t state)
|
|
{
|
|
int error;
|
|
|
|
- if (!valid_state(state))
|
|
- return -ENODEV;
|
|
-
|
|
+ if (state == PM_SUSPEND_FREEZE) {
|
|
+#ifdef CONFIG_PM_DEBUG
|
|
+ if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) {
|
|
+ pr_warning("PM: Unsupported test mode for freeze state,"
|
|
+ "please choose none/freezer/devices/platform.\n");
|
|
+ return -EAGAIN;
|
|
+ }
|
|
+#endif
|
|
+ } else if (!valid_state(state)) {
|
|
+ return -EINVAL;
|
|
+ }
|
|
if (!mutex_trylock(&pm_mutex))
|
|
return -EBUSY;
|
|
|
|
@@ -337,7 +337,7 @@ static int enter_state(suspend_state_t state)
|
|
sys_sync();
|
|
printk("done.\n");
|
|
|
|
- pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
|
|
+ pr_debug("PM: Preparing system for %s sleep\n", pm_states[state].label);
|
|
error = suspend_prepare(state);
|
|
if (error)
|
|
goto Unlock;
|
|
@@ -345,7 +345,7 @@ static int enter_state(suspend_state_t state)
|
|
if (suspend_test(TEST_FREEZER))
|
|
goto Finish;
|
|
|
|
- pr_debug("PM: Entering %s sleep\n", pm_states[state]);
|
|
+ pr_debug("PM: Entering %s sleep\n", pm_states[state].label);
|
|
pm_restrict_gfp_mask();
|
|
error = suspend_devices_and_enter(state);
|
|
pm_restore_gfp_mask();
|
|
diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c
|
|
index 9b2a1d58558d..269b097e78ea 100644
|
|
--- a/kernel/power/suspend_test.c
|
|
+++ b/kernel/power/suspend_test.c
|
|
@@ -92,13 +92,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
|
|
}
|
|
|
|
if (state == PM_SUSPEND_MEM) {
|
|
- printk(info_test, pm_states[state]);
|
|
+ printk(info_test, pm_states[state].label);
|
|
status = pm_suspend(state);
|
|
if (status == -ENODEV)
|
|
state = PM_SUSPEND_STANDBY;
|
|
}
|
|
if (state == PM_SUSPEND_STANDBY) {
|
|
- printk(info_test, pm_states[state]);
|
|
+ printk(info_test, pm_states[state].label);
|
|
status = pm_suspend(state);
|
|
}
|
|
if (status < 0)
|
|
@@ -136,18 +136,16 @@ static char warn_bad_state[] __initdata =
|
|
|
|
static int __init setup_test_suspend(char *value)
|
|
{
|
|
- unsigned i;
|
|
+ suspend_state_t i;
|
|
|
|
/* "=mem" ==> "mem" */
|
|
value++;
|
|
- for (i = 0; i < PM_SUSPEND_MAX; i++) {
|
|
- if (!pm_states[i])
|
|
- continue;
|
|
- if (strcmp(pm_states[i], value) != 0)
|
|
- continue;
|
|
- test_state = (__force suspend_state_t) i;
|
|
- return 0;
|
|
- }
|
|
+ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
|
|
+ if (!strcmp(pm_states[i].label, value)) {
|
|
+ test_state = pm_states[i].state;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
printk(warn_bad_state, value);
|
|
return 0;
|
|
}
|
|
@@ -164,8 +162,8 @@ static int __init test_suspend(void)
|
|
/* PM is initialized by now; is that state testable? */
|
|
if (test_state == PM_SUSPEND_ON)
|
|
goto done;
|
|
- if (!valid_state(test_state)) {
|
|
- printk(warn_bad_state, pm_states[test_state]);
|
|
+ if (!pm_states[test_state].state) {
|
|
+ printk(warn_bad_state, pm_states[test_state].label);
|
|
goto done;
|
|
}
|
|
|
|
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
|
|
index 294bf4ef1f47..7d19fca0617e 100644
|
|
--- a/kernel/time/alarmtimer.c
|
|
+++ b/kernel/time/alarmtimer.c
|
|
@@ -419,18 +419,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)
|
|
static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
|
|
ktime_t now)
|
|
{
|
|
+ unsigned long flags;
|
|
struct k_itimer *ptr = container_of(alarm, struct k_itimer,
|
|
it.alarm.alarmtimer);
|
|
- if (posix_timer_event(ptr, 0) != 0)
|
|
- ptr->it_overrun++;
|
|
+ enum alarmtimer_restart result = ALARMTIMER_NORESTART;
|
|
+
|
|
+ spin_lock_irqsave(&ptr->it_lock, flags);
|
|
+ if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
|
|
+ if (posix_timer_event(ptr, 0) != 0)
|
|
+ ptr->it_overrun++;
|
|
+ }
|
|
|
|
/* Re-add periodic timers */
|
|
if (ptr->it.alarm.interval.tv64) {
|
|
ptr->it_overrun += alarm_forward(alarm, now,
|
|
ptr->it.alarm.interval);
|
|
- return ALARMTIMER_RESTART;
|
|
+ result = ALARMTIMER_RESTART;
|
|
}
|
|
- return ALARMTIMER_NORESTART;
|
|
+ spin_unlock_irqrestore(&ptr->it_lock, flags);
|
|
+
|
|
+ return result;
|
|
}
|
|
|
|
/**
|
|
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
|
|
index 5efbc122e5ce..0bc181b0524c 100644
|
|
--- a/kernel/trace/ring_buffer.c
|
|
+++ b/kernel/trace/ring_buffer.c
|
|
@@ -626,8 +626,22 @@ int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
|
|
work = &cpu_buffer->irq_work;
|
|
}
|
|
|
|
- work->waiters_pending = true;
|
|
poll_wait(filp, &work->waiters, poll_table);
|
|
+ work->waiters_pending = true;
|
|
+ /*
|
|
+ * There's a tight race between setting the waiters_pending and
|
|
+ * checking if the ring buffer is empty. Once the waiters_pending bit
|
|
+ * is set, the next event will wake the task up, but we can get stuck
|
|
+ * if there's only a single event in.
|
|
+ *
|
|
+ * FIXME: Ideally, we need a memory barrier on the writer side as well,
|
|
+ * but adding a memory barrier to all events will cause too much of a
|
|
+ * performance hit in the fast path. We only need a memory barrier when
|
|
+ * the buffer goes from empty to having content. But as this race is
|
|
+ * extremely small, and it's not a problem if another event comes in, we
|
|
+ * will fix it later.
|
|
+ */
|
|
+ smp_mb();
|
|
|
|
if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) ||
|
|
(cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu)))
|
|
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
|
|
index dfa94ed3c7fa..8e40908e724a 100644
|
|
--- a/mm/oom_kill.c
|
|
+++ b/mm/oom_kill.c
|
|
@@ -47,19 +47,21 @@ static DEFINE_SPINLOCK(zone_scan_lock);
|
|
#ifdef CONFIG_NUMA
|
|
/**
|
|
* has_intersects_mems_allowed() - check task eligiblity for kill
|
|
- * @tsk: task struct of which task to consider
|
|
+ * @start: task struct of which task to consider
|
|
* @mask: nodemask passed to page allocator for mempolicy ooms
|
|
*
|
|
* Task eligibility is determined by whether or not a candidate task, @tsk,
|
|
* shares the same mempolicy nodes as current if it is bound by such a policy
|
|
* and whether or not it has the same set of allowed cpuset nodes.
|
|
*/
|
|
-static bool has_intersects_mems_allowed(struct task_struct *tsk,
|
|
+static bool has_intersects_mems_allowed(struct task_struct *start,
|
|
const nodemask_t *mask)
|
|
{
|
|
- struct task_struct *start = tsk;
|
|
+ struct task_struct *tsk;
|
|
+ bool ret = false;
|
|
|
|
- do {
|
|
+ rcu_read_lock();
|
|
+ for_each_thread(start, tsk) {
|
|
if (mask) {
|
|
/*
|
|
* If this is a mempolicy constrained oom, tsk's
|
|
@@ -67,19 +69,20 @@ static bool has_intersects_mems_allowed(struct task_struct *tsk,
|
|
* mempolicy intersects current, otherwise it may be
|
|
* needlessly killed.
|
|
*/
|
|
- if (mempolicy_nodemask_intersects(tsk, mask))
|
|
- return true;
|
|
+ ret = mempolicy_nodemask_intersects(tsk, mask);
|
|
} else {
|
|
/*
|
|
* This is not a mempolicy constrained oom, so only
|
|
* check the mems of tsk's cpuset.
|
|
*/
|
|
- if (cpuset_mems_allowed_intersects(current, tsk))
|
|
- return true;
|
|
+ ret = cpuset_mems_allowed_intersects(current, tsk);
|
|
}
|
|
- } while_each_thread(start, tsk);
|
|
+ if (ret)
|
|
+ break;
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
|
|
- return false;
|
|
+ return ret;
|
|
}
|
|
#else
|
|
static bool has_intersects_mems_allowed(struct task_struct *tsk,
|
|
@@ -97,16 +100,21 @@ static bool has_intersects_mems_allowed(struct task_struct *tsk,
|
|
*/
|
|
struct task_struct *find_lock_task_mm(struct task_struct *p)
|
|
{
|
|
- struct task_struct *t = p;
|
|
+ struct task_struct *t;
|
|
|
|
- do {
|
|
+ rcu_read_lock();
|
|
+
|
|
+ for_each_thread(p, t) {
|
|
task_lock(t);
|
|
if (likely(t->mm))
|
|
- return t;
|
|
+ goto found;
|
|
task_unlock(t);
|
|
- } while_each_thread(p, t);
|
|
+ }
|
|
+ t = NULL;
|
|
+found:
|
|
+ rcu_read_unlock();
|
|
|
|
- return NULL;
|
|
+ return t;
|
|
}
|
|
|
|
/* return true if the task is not adequate as candidate victim task. */
|
|
@@ -301,7 +309,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
|
|
unsigned long chosen_points = 0;
|
|
|
|
rcu_read_lock();
|
|
- do_each_thread(g, p) {
|
|
+ for_each_process_thread(g, p) {
|
|
unsigned int points;
|
|
|
|
switch (oom_scan_process_thread(p, totalpages, nodemask,
|
|
@@ -323,7 +331,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
|
|
chosen = p;
|
|
chosen_points = points;
|
|
}
|
|
- } while_each_thread(g, p);
|
|
+ }
|
|
if (chosen)
|
|
get_task_struct(chosen);
|
|
rcu_read_unlock();
|
|
@@ -406,7 +414,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
|
|
{
|
|
struct task_struct *victim = p;
|
|
struct task_struct *child;
|
|
- struct task_struct *t = p;
|
|
+ struct task_struct *t;
|
|
struct mm_struct *mm;
|
|
unsigned int victim_points = 0;
|
|
static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL,
|
|
@@ -437,7 +445,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
|
|
* still freeing memory.
|
|
*/
|
|
read_lock(&tasklist_lock);
|
|
- do {
|
|
+ for_each_thread(p, t) {
|
|
list_for_each_entry(child, &t->children, sibling) {
|
|
unsigned int child_points;
|
|
|
|
@@ -455,13 +463,11 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
|
|
get_task_struct(victim);
|
|
}
|
|
}
|
|
- } while_each_thread(p, t);
|
|
+ }
|
|
read_unlock(&tasklist_lock);
|
|
|
|
- rcu_read_lock();
|
|
p = find_lock_task_mm(victim);
|
|
if (!p) {
|
|
- rcu_read_unlock();
|
|
put_task_struct(victim);
|
|
return;
|
|
} else if (victim != p) {
|
|
@@ -487,6 +493,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
|
|
* That thread will now get access to memory reserves since it has a
|
|
* pending fatal signal.
|
|
*/
|
|
+ rcu_read_lock();
|
|
for_each_process(p)
|
|
if (p->mm == mm && !same_thread_group(p, victim) &&
|
|
!(p->flags & PF_KTHREAD)) {
|
|
diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c
|
|
index 3707c71ae4cd..51108165f829 100644
|
|
--- a/mm/percpu-vm.c
|
|
+++ b/mm/percpu-vm.c
|
|
@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
|
|
int page_start, int page_end)
|
|
{
|
|
const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
|
|
- unsigned int cpu;
|
|
+ unsigned int cpu, tcpu;
|
|
int i;
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
|
|
struct page **pagep = &pages[pcpu_page_idx(cpu, i)];
|
|
|
|
*pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0);
|
|
- if (!*pagep) {
|
|
- pcpu_free_pages(chunk, pages, populated,
|
|
- page_start, page_end);
|
|
- return -ENOMEM;
|
|
- }
|
|
+ if (!*pagep)
|
|
+ goto err;
|
|
}
|
|
}
|
|
return 0;
|
|
+
|
|
+err:
|
|
+ while (--i >= page_start)
|
|
+ __free_page(pages[pcpu_page_idx(cpu, i)]);
|
|
+
|
|
+ for_each_possible_cpu(tcpu) {
|
|
+ if (tcpu == cpu)
|
|
+ break;
|
|
+ for (i = page_start; i < page_end; i++)
|
|
+ __free_page(pages[pcpu_page_idx(tcpu, i)]);
|
|
+ }
|
|
+ return -ENOMEM;
|
|
}
|
|
|
|
/**
|
|
@@ -263,6 +272,7 @@ err:
|
|
__pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
|
|
page_end - page_start);
|
|
}
|
|
+ pcpu_post_unmap_tlb_flush(chunk, page_start, page_end);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/mm/percpu.c b/mm/percpu.c
|
|
index 25e2ea52db82..9bc1bf914cc8 100644
|
|
--- a/mm/percpu.c
|
|
+++ b/mm/percpu.c
|
|
@@ -1910,6 +1910,8 @@ void __init setup_per_cpu_areas(void)
|
|
|
|
if (pcpu_setup_first_chunk(ai, fc) < 0)
|
|
panic("Failed to initialize percpu areas.");
|
|
+
|
|
+ pcpu_free_alloc_info(ai);
|
|
}
|
|
|
|
#endif /* CONFIG_SMP */
|
|
diff --git a/mm/shmem.c b/mm/shmem.c
|
|
index 16cc1d77f70a..4e4a7349c5cd 100644
|
|
--- a/mm/shmem.c
|
|
+++ b/mm/shmem.c
|
|
@@ -2128,8 +2128,10 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
|
|
|
|
if (new_dentry->d_inode) {
|
|
(void) shmem_unlink(new_dir, new_dentry);
|
|
- if (they_are_dirs)
|
|
+ if (they_are_dirs) {
|
|
+ drop_nlink(new_dentry->d_inode);
|
|
drop_nlink(old_dir);
|
|
+ }
|
|
} else if (they_are_dirs) {
|
|
drop_nlink(old_dir);
|
|
inc_nlink(new_dir);
|
|
diff --git a/mm/util.c b/mm/util.c
|
|
index ab1424dbe2e6..0b1725254ff1 100644
|
|
--- a/mm/util.c
|
|
+++ b/mm/util.c
|
|
@@ -272,17 +272,14 @@ pid_t vm_is_stack(struct task_struct *task,
|
|
|
|
if (in_group) {
|
|
struct task_struct *t;
|
|
- rcu_read_lock();
|
|
- if (!pid_alive(task))
|
|
- goto done;
|
|
|
|
- t = task;
|
|
- do {
|
|
+ rcu_read_lock();
|
|
+ for_each_thread(task, t) {
|
|
if (vm_is_stack_for_task(t, vma)) {
|
|
ret = t->pid;
|
|
goto done;
|
|
}
|
|
- } while_each_thread(task, t);
|
|
+ }
|
|
done:
|
|
rcu_read_unlock();
|
|
}
|
|
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
|
|
index fc94937cd7b3..e606e4a113e1 100644
|
|
--- a/net/mac80211/mlme.c
|
|
+++ b/net/mac80211/mlme.c
|
|
@@ -4395,8 +4395,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
|
rcu_read_unlock();
|
|
|
|
if (bss->wmm_used && bss->uapsd_supported &&
|
|
- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
|
|
- sdata->wmm_acm != 0xff) {
|
|
+ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
|
|
assoc_data->uapsd = true;
|
|
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
|
|
} else {
|
|
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
|
|
index a083bda322b6..90e756cf6e52 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_conn.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_conn.c
|
|
@@ -797,7 +797,6 @@ static void ip_vs_conn_expire(unsigned long data)
|
|
ip_vs_control_del(cp);
|
|
|
|
if (cp->flags & IP_VS_CONN_F_NFCT) {
|
|
- ip_vs_conn_drop_conntrack(cp);
|
|
/* Do not access conntracks during subsys cleanup
|
|
* because nf_conntrack_find_get can not be used after
|
|
* conntrack cleanup for the net.
|
|
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
|
|
index 663042e84e81..26b9a986a87f 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_core.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_core.c
|
|
@@ -1898,7 +1898,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
|
|
{
|
|
.hook = ip_vs_local_reply6,
|
|
.owner = THIS_MODULE,
|
|
- .pf = NFPROTO_IPV4,
|
|
+ .pf = NFPROTO_IPV6,
|
|
.hooknum = NF_INET_LOCAL_OUT,
|
|
.priority = NF_IP6_PRI_NAT_DST + 1,
|
|
},
|
|
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
|
|
index 7f0e1cf2d7e8..1692e7534759 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_xmit.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
|
|
@@ -967,8 +967,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
iph->nexthdr = IPPROTO_IPV6;
|
|
iph->payload_len = old_iph->payload_len;
|
|
be16_add_cpu(&iph->payload_len, sizeof(*old_iph));
|
|
- iph->priority = old_iph->priority;
|
|
memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
|
|
+ ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph));
|
|
iph->daddr = cp->daddr.in6;
|
|
iph->saddr = saddr;
|
|
iph->hop_limit = old_iph->hop_limit;
|
|
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
|
|
index 4d4d8f1d01fc..7dcc376eea5f 100644
|
|
--- a/net/netfilter/nf_conntrack_proto_tcp.c
|
|
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
|
|
@@ -1043,6 +1043,12 @@ static int tcp_packet(struct nf_conn *ct,
|
|
nf_ct_kill_acct(ct, ctinfo, skb);
|
|
return NF_ACCEPT;
|
|
}
|
|
+ /* ESTABLISHED without SEEN_REPLY, i.e. mid-connection
|
|
+ * pickup with loose=1. Avoid large ESTABLISHED timeout.
|
|
+ */
|
|
+ if (new_state == TCP_CONNTRACK_ESTABLISHED &&
|
|
+ timeout > timeouts[TCP_CONNTRACK_UNACK])
|
|
+ timeout = timeouts[TCP_CONNTRACK_UNACK];
|
|
} else if (!test_bit(IPS_ASSURED_BIT, &ct->status)
|
|
&& (old_state == TCP_CONNTRACK_SYN_RECV
|
|
|| old_state == TCP_CONNTRACK_ESTABLISHED)
|
|
diff --git a/sound/core/info.c b/sound/core/info.c
|
|
index e79baa11b60e..08070e1eefeb 100644
|
|
--- a/sound/core/info.c
|
|
+++ b/sound/core/info.c
|
|
@@ -679,7 +679,7 @@ int snd_info_card_free(struct snd_card *card)
|
|
* snd_info_get_line - read one line from the procfs buffer
|
|
* @buffer: the procfs buffer
|
|
* @line: the buffer to store
|
|
- * @len: the max. buffer size - 1
|
|
+ * @len: the max. buffer size
|
|
*
|
|
* Reads one line from the buffer and stores the string.
|
|
*
|
|
@@ -699,7 +699,7 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
|
|
buffer->stop = 1;
|
|
if (c == '\n')
|
|
break;
|
|
- if (len) {
|
|
+ if (len > 1) {
|
|
len--;
|
|
*line++ = c;
|
|
}
|
|
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
|
|
index 3284940a4af2..8eddece217bb 100644
|
|
--- a/sound/core/pcm_lib.c
|
|
+++ b/sound/core/pcm_lib.c
|
|
@@ -1782,14 +1782,16 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
|
|
{
|
|
struct snd_pcm_hw_params *params = arg;
|
|
snd_pcm_format_t format;
|
|
- int channels, width;
|
|
+ int channels;
|
|
+ ssize_t frame_size;
|
|
|
|
params->fifo_size = substream->runtime->hw.fifo_size;
|
|
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) {
|
|
format = params_format(params);
|
|
channels = params_channels(params);
|
|
- width = snd_pcm_format_physical_width(format);
|
|
- params->fifo_size /= width * channels;
|
|
+ frame_size = snd_pcm_format_size(format, channels);
|
|
+ if (frame_size > 0)
|
|
+ params->fifo_size /= (unsigned)frame_size;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 593090e5bd77..4008034b6ebe 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -318,6 +318,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
|
|
case 0x10ec0885:
|
|
case 0x10ec0887:
|
|
/*case 0x10ec0889:*/ /* this causes an SPDIF problem */
|
|
+ case 0x10ec0900:
|
|
alc889_coef_init(codec);
|
|
break;
|
|
case 0x10ec0888:
|
|
@@ -2252,6 +2253,7 @@ static int patch_alc882(struct hda_codec *codec)
|
|
switch (codec->vendor_id) {
|
|
case 0x10ec0882:
|
|
case 0x10ec0885:
|
|
+ case 0x10ec0900:
|
|
break;
|
|
default:
|
|
/* ALC883 and variants */
|
|
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
|
|
index 132b4c802a47..5dd4c4af9c9f 100644
|
|
--- a/sound/pci/hda/patch_sigmatel.c
|
|
+++ b/sound/pci/hda/patch_sigmatel.c
|
|
@@ -539,8 +539,8 @@ static void stac_init_power_map(struct hda_codec *codec)
|
|
if (snd_hda_jack_tbl_get(codec, nid))
|
|
continue;
|
|
if (def_conf == AC_JACK_PORT_COMPLEX &&
|
|
- !(spec->vref_mute_led_nid == nid ||
|
|
- is_jack_detectable(codec, nid))) {
|
|
+ spec->vref_mute_led_nid != nid &&
|
|
+ is_jack_detectable(codec, nid)) {
|
|
snd_hda_jack_detect_enable_callback(codec, nid,
|
|
STAC_PWR_EVENT,
|
|
jack_update_power);
|
|
@@ -3647,11 +3647,18 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
|
return err;
|
|
}
|
|
|
|
- stac_init_power_map(codec);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
+static int stac_build_controls(struct hda_codec *codec)
|
|
+{
|
|
+ int err = snd_hda_gen_build_controls(codec);
|
|
+
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ stac_init_power_map(codec);
|
|
+ return 0;
|
|
+}
|
|
|
|
static int stac_init(struct hda_codec *codec)
|
|
{
|
|
@@ -3794,7 +3801,7 @@ static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
|
|
#endif /* CONFIG_PM */
|
|
|
|
static const struct hda_codec_ops stac_patch_ops = {
|
|
- .build_controls = snd_hda_gen_build_controls,
|
|
+ .build_controls = stac_build_controls,
|
|
.build_pcms = snd_hda_gen_build_pcms,
|
|
.init = stac_init,
|
|
.free = stac_free,
|
|
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
|
|
index 81490febac6d..ade9d6379c1b 100644
|
|
--- a/sound/soc/davinci/davinci-mcasp.c
|
|
+++ b/sound/soc/davinci/davinci-mcasp.c
|
|
@@ -632,8 +632,17 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
|
|
{
|
|
u32 fmt;
|
|
u32 tx_rotate = (word_length / 4) & 0x7;
|
|
- u32 rx_rotate = (32 - word_length) / 4;
|
|
u32 mask = (1ULL << word_length) - 1;
|
|
+ /*
|
|
+ * For captured data we should not rotate, inversion and masking is
|
|
+ * enoguh to get the data to the right position:
|
|
+ * Format data from bus after reverse (XRBUF)
|
|
+ * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB|
|
|
+ * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
|
|
+ * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
|
|
+ * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB|
|
|
+ */
|
|
+ u32 rx_rotate = 0;
|
|
|
|
/*
|
|
* if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
|
|
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
|
|
index 46878daca5cc..c9eac3edfe4d 100644
|
|
--- a/tools/perf/builtin-kmem.c
|
|
+++ b/tools/perf/builtin-kmem.c
|
|
@@ -101,7 +101,7 @@ static int setup_cpunode_map(void)
|
|
|
|
dir1 = opendir(PATH_SYS_NODE);
|
|
if (!dir1)
|
|
- return -1;
|
|
+ return 0;
|
|
|
|
while ((dent1 = readdir(dir1)) != NULL) {
|
|
if (dent1->d_type != DT_DIR ||
|