diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/m32r/kernel/setup.c linux-libre-3.2.77-gnu1/arch/m32r/kernel/setup.c
--- linux-libre-3.2.76-gnu1/arch/m32r/kernel/setup.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/m32r/kernel/setup.c	2016-02-13 05:34:14.000000000 -0500
@@ -81,7 +81,10 @@ static struct resource code_resource = {
 };
 
 unsigned long memory_start;
+EXPORT_SYMBOL(memory_start);
+
 unsigned long memory_end;
+EXPORT_SYMBOL(memory_end);
 
 void __init setup_arch(char **);
 int get_cpuinfo(char *);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/parisc/include/asm/siginfo.h linux-libre-3.2.77-gnu1/arch/parisc/include/asm/siginfo.h
--- linux-libre-3.2.76-gnu1/arch/parisc/include/asm/siginfo.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/parisc/include/asm/siginfo.h	2016-02-13 05:34:14.000000000 -0500
@@ -1,6 +1,10 @@
 #ifndef _PARISC_SIGINFO_H
 #define _PARISC_SIGINFO_H
 
+#if defined(__LP64__)
+#define __ARCH_SI_PREAMBLE_SIZE   (4 * sizeof(int))
+#endif
+
 #include <asm-generic/siginfo.h>
 
 #undef NSIGTRAP
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/powerpc/include/asm/synch.h linux-libre-3.2.77-gnu1/arch/powerpc/include/asm/synch.h
--- linux-libre-3.2.76-gnu1/arch/powerpc/include/asm/synch.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/powerpc/include/asm/synch.h	2016-02-13 05:34:14.000000000 -0500
@@ -44,7 +44,7 @@ static inline void isync(void)
 	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
 #define PPC_ACQUIRE_BARRIER	 "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
 #define PPC_RELEASE_BARRIER	 stringify_in_c(LWSYNC) "\n"
-#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(sync) "\n"
 #define PPC_ATOMIC_EXIT_BARRIER	 "\n" stringify_in_c(sync) "\n"
 #else
 #define PPC_ACQUIRE_BARRIER
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/powerpc/include/asm/system.h linux-libre-3.2.77-gnu1/arch/powerpc/include/asm/system.h
--- linux-libre-3.2.76-gnu1/arch/powerpc/include/asm/system.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/powerpc/include/asm/system.h	2016-02-13 05:34:14.000000000 -0500
@@ -234,12 +234,12 @@ __xchg_u32(volatile void *p, unsigned lo
 	unsigned long prev;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2 \n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%3,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (prev), "+m" (*(volatile unsigned int *)p)
 	: "r" (p), "r" (val)
 	: "cc", "memory");
@@ -277,12 +277,12 @@ __xchg_u64(volatile void *p, unsigned lo
 	unsigned long prev;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2 \n"
 	PPC405_ERR77(0,%2)
 "	stdcx.	%3,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (prev), "+m" (*(volatile unsigned long *)p)
 	: "r" (p), "r" (val)
 	: "cc", "memory");
@@ -368,14 +368,14 @@ __cmpxchg_u32(volatile unsigned int *p,
 	unsigned int prev;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2		# __cmpxchg_u32\n\
 	cmpw	0,%0,%3\n\
 	bne-	2f\n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%4,0,%2\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"
 	: "=&r" (prev), "+m" (*p)
@@ -414,13 +414,13 @@ __cmpxchg_u64(volatile unsigned long *p,
 	unsigned long prev;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2		# __cmpxchg_u64\n\
 	cmpd	0,%0,%3\n\
 	bne-	2f\n\
 	stdcx.	%4,0,%2\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"
 	: "=&r" (prev), "+m" (*p)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/sparc/kernel/sys_sparc_64.c linux-libre-3.2.77-gnu1/arch/sparc/kernel/sys_sparc_64.c
--- linux-libre-3.2.76-gnu1/arch/sparc/kernel/sys_sparc_64.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/sparc/kernel/sys_sparc_64.c	2016-02-13 05:34:14.000000000 -0500
@@ -517,7 +517,7 @@ out:
 
 SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
 {
-	int ret;
+	long ret;
 
 	if (personality(current->personality) == PER_LINUX32 &&
 	    personality(personality) == PER_LINUX)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/um/os-Linux/start_up.c linux-libre-3.2.77-gnu1/arch/um/os-Linux/start_up.c
--- linux-libre-3.2.76-gnu1/arch/um/os-Linux/start_up.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/um/os-Linux/start_up.c	2016-02-13 05:34:14.000000000 -0500
@@ -95,6 +95,8 @@ static int start_ptraced_child(void)
 {
 	int pid, n, status;
 
+	fflush(stdout);
+
 	pid = fork();
 	if (pid == 0)
 		ptrace_child();
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/include/asm/boot.h linux-libre-3.2.77-gnu1/arch/x86/include/asm/boot.h
--- linux-libre-3.2.76-gnu1/arch/x86/include/asm/boot.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/include/asm/boot.h	2016-02-13 05:34:14.000000000 -0500
@@ -32,7 +32,7 @@
 #define BOOT_HEAP_SIZE             0x400000
 #else /* !CONFIG_KERNEL_BZIP2 */
 
-#define BOOT_HEAP_SIZE	0x8000
+#define BOOT_HEAP_SIZE	0x10000
 
 #endif /* !CONFIG_KERNEL_BZIP2 */
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/include/asm/mmu_context.h linux-libre-3.2.77-gnu1/arch/x86/include/asm/mmu_context.h
--- linux-libre-3.2.76-gnu1/arch/x86/include/asm/mmu_context.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/include/asm/mmu_context.h	2016-02-13 05:34:14.000000000 -0500
@@ -87,7 +87,34 @@ static inline void switch_mm(struct mm_s
 #endif
 		cpumask_set_cpu(cpu, mm_cpumask(next));
 
-		/* Re-load page tables */
+		/*
+		 * Re-load page tables.
+		 *
+		 * This logic has an ordering constraint:
+		 *
+		 *  CPU 0: Write to a PTE for 'next'
+		 *  CPU 0: load bit 1 in mm_cpumask.  if nonzero, send IPI.
+		 *  CPU 1: set bit 1 in next's mm_cpumask
+		 *  CPU 1: load from the PTE that CPU 0 writes (implicit)
+		 *
+		 * We need to prevent an outcome in which CPU 1 observes
+		 * the new PTE value and CPU 0 observes bit 1 clear in
+		 * mm_cpumask.  (If that occurs, then the IPI will never
+		 * be sent, and CPU 0's TLB will contain a stale entry.)
+		 *
+		 * The bad outcome can occur if either CPU's load is
+		 * reordered before that CPU's store, so both CPUs must
+		 * execute full barriers to prevent this from happening.
+		 *
+		 * Thus, switch_mm needs a full barrier between the
+		 * store to mm_cpumask and any operation that could load
+		 * from next->pgd.  TLB fills are special and can happen
+		 * due to instruction fetches or for no reason at all,
+		 * and neither LOCK nor MFENCE orders them.
+		 * Fortunately, load_cr3() is serializing and gives the
+		 * ordering guarantee we need.
+		 *
+		 */
 		load_cr3(next->pgd);
 
 		/* stop flush ipis for the previous mm */
@@ -108,6 +135,9 @@ static inline void switch_mm(struct mm_s
 			/* We were in lazy tlb mode and leave_mm disabled
 			 * tlb flush IPI delivery. We must reload CR3
 			 * to make sure to use no freed page tables.
+			 *
+			 * As above, load_cr3() is serializing and orders TLB
+			 * fills with respect to the mm_cpumask write.
 			 */
 			load_cr3(next->pgd);
 			load_mm_ldt(next);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/kernel/process_64.c linux-libre-3.2.77-gnu1/arch/x86/kernel/process_64.c
--- linux-libre-3.2.76-gnu1/arch/x86/kernel/process_64.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/kernel/process_64.c	2016-02-13 05:34:14.000000000 -0500
@@ -221,7 +221,7 @@ void release_thread(struct task_struct *
 		if (dead_task->mm->context.ldt) {
 			printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
 					dead_task->comm,
-					dead_task->mm->context.ldt,
+					dead_task->mm->context.ldt->entries,
 					dead_task->mm->context.ldt->size);
 			BUG();
 		}
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/kernel/reboot.c linux-libre-3.2.77-gnu1/arch/x86/kernel/reboot.c
--- linux-libre-3.2.76-gnu1/arch/x86/kernel/reboot.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/kernel/reboot.c	2016-02-13 05:34:14.000000000 -0500
@@ -412,6 +412,14 @@ static struct dmi_system_id __initdata p
 			DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
 		},
 	},
+	{	/* Handle problems with rebooting on the iMac10,1. */
+		.callback = set_pci_reboot,
+		.ident = "Apple iMac10,1",
+		.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "iMac10,1"),
+		},
+	},
 	/* ASRock */
 	{	/* Handle problems with rebooting on ASRock Q1900DC-ITX */
 		.callback = set_pci_reboot,
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/kvm/trace.h linux-libre-3.2.77-gnu1/arch/x86/kvm/trace.h
--- linux-libre-3.2.76-gnu1/arch/x86/kvm/trace.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/kvm/trace.h	2016-02-13 05:34:14.000000000 -0500
@@ -326,7 +326,7 @@ TRACE_EVENT(kvm_inj_virq,
 #define kvm_trace_sym_exc						\
 	EXS(DE), EXS(DB), EXS(BP), EXS(OF), EXS(BR), EXS(UD), EXS(NM),	\
 	EXS(DF), EXS(TS), EXS(NP), EXS(SS), EXS(GP), EXS(PF),		\
-	EXS(MF), EXS(MC)
+	EXS(MF), EXS(AC), EXS(MC)
 
 /*
  * Tracepoint for kvm interrupt injection:
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/kvm/x86.c linux-libre-3.2.77-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.2.76-gnu1/arch/x86/kvm/x86.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/kvm/x86.c	2016-02-13 05:34:14.000000000 -0500
@@ -834,7 +834,8 @@ static u32 msrs_to_save[] = {
 #ifdef CONFIG_X86_64
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
-	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA
+	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
+	MSR_TSC_AUX,
 };
 
 static unsigned num_msrs_to_save;
@@ -3867,6 +3868,20 @@ static void kvm_init_msr_list(void)
 	for (i = j = KVM_SAVE_MSRS_BEGIN; i < ARRAY_SIZE(msrs_to_save); i++) {
 		if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
 			continue;
+
+		/*
+		 * Even MSRs that are valid in the host may not be exposed
+		 * to the guests in some cases.
+		 */
+		switch (msrs_to_save[i]) {
+		case MSR_TSC_AUX:
+			if (!kvm_x86_ops->rdtscp_supported())
+				continue;
+			break;
+		default:
+			break;
+		}
+
 		if (j < i)
 			msrs_to_save[j] = msrs_to_save[i];
 		j++;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/mm/tlb.c linux-libre-3.2.77-gnu1/arch/x86/mm/tlb.c
--- linux-libre-3.2.76-gnu1/arch/x86/mm/tlb.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/mm/tlb.c	2016-02-13 05:34:14.000000000 -0500
@@ -278,7 +278,9 @@ void flush_tlb_current_task(void)
 
 	preempt_disable();
 
+	/* This is an implicit full barrier that synchronizes with switch_mm. */
 	local_flush_tlb();
+
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
 	preempt_enable();
@@ -289,10 +291,20 @@ void flush_tlb_mm(struct mm_struct *mm)
 	preempt_disable();
 
 	if (current->active_mm == mm) {
-		if (current->mm)
+		if (current->mm) {
+			/*
+			 * This is an implicit full barrier (MOV to CR) that
+			 * synchronizes with switch_mm.
+			 */
 			local_flush_tlb();
-		else
+		} else {
 			leave_mm(smp_processor_id());
+			/* Synchronize with switch_mm. */
+			smp_mb();
+		}
+	} else {
+		/* Synchronize with switch_mm. */
+		smp_mb();
 	}
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
@@ -307,10 +319,18 @@ void flush_tlb_page(struct vm_area_struc
 	preempt_disable();
 
 	if (current->active_mm == mm) {
-		if (current->mm)
+		if (current->mm) {
+			/*
+			 * Implicit full barrier (INVLPG) that synchronizes
+			 * with switch_mm.
+			 */
 			__flush_tlb_one(va);
-		else
+		} else {
 			leave_mm(smp_processor_id());
+
+			/* Synchronize with switch_mm. */
+			smp_mb();
+		}
 	}
 
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/arch/x86/xen/suspend.c linux-libre-3.2.77-gnu1/arch/x86/xen/suspend.c
--- linux-libre-3.2.76-gnu1/arch/x86/xen/suspend.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/arch/x86/xen/suspend.c	2016-02-13 05:34:14.000000000 -0500
@@ -30,7 +30,8 @@ void xen_arch_hvm_post_suspend(int suspe
 {
 #ifdef CONFIG_XEN_PVHVM
 	int cpu;
-	xen_hvm_init_shared_info();
+	if (!suspend_cancelled)
+	    xen_hvm_init_shared_info();
 	xen_callback_vector();
 	xen_unplug_emulated_devices();
 	if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/ablkcipher.c linux-libre-3.2.77-gnu1/crypto/ablkcipher.c
--- linux-libre-3.2.76-gnu1/crypto/ablkcipher.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/ablkcipher.c	2016-02-13 05:34:14.000000000 -0500
@@ -379,6 +379,7 @@ static int crypto_init_ablkcipher_ops(st
 	}
 	crt->base = __crypto_ablkcipher_cast(tfm);
 	crt->ivsize = alg->ivsize;
+	crt->has_setkey = alg->max_keysize;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/af_alg.c linux-libre-3.2.77-gnu1/crypto/af_alg.c
--- linux-libre-3.2.76-gnu1/crypto/af_alg.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/af_alg.c	2016-02-13 05:34:14.000000000 -0500
@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af
 		goto unlock;
 
 	type->ops->owner = THIS_MODULE;
+	if (type->ops_nokey)
+		type->ops_nokey->owner = THIS_MODULE;
 	node->type = type;
 	list_add(&node->list, &alg_types);
 	err = 0;
@@ -125,6 +127,26 @@ int af_alg_release(struct socket *sock)
 }
 EXPORT_SYMBOL_GPL(af_alg_release);
 
+void af_alg_release_parent(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	unsigned int nokey = ask->nokey_refcnt;
+	bool last = nokey && !ask->refcnt;
+
+	sk = ask->parent;
+	ask = alg_sk(sk);
+
+	lock_sock(sk);
+	ask->nokey_refcnt -= nokey;
+	if (!last)
+		last = !--ask->refcnt;
+	release_sock(sk);
+
+	if (last)
+		sock_put(sk);
+}
+EXPORT_SYMBOL_GPL(af_alg_release_parent);
+
 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk = sock->sk;
@@ -132,6 +154,7 @@ static int alg_bind(struct socket *sock,
 	struct sockaddr_alg *sa = (void *)uaddr;
 	const struct af_alg_type *type;
 	void *private;
+	int err;
 
 	if (sock->state == SS_CONNECTED)
 		return -EINVAL;
@@ -157,16 +180,22 @@ static int alg_bind(struct socket *sock,
 		return PTR_ERR(private);
 	}
 
+	err = -EBUSY;
 	lock_sock(sk);
+	if (ask->refcnt | ask->nokey_refcnt)
+		goto unlock;
 
 	swap(ask->type, type);
 	swap(ask->private, private);
 
+	err = 0;
+
+unlock:
 	release_sock(sk);
 
 	alg_do_release(type, private);
 
-	return 0;
+	return err;
 }
 
 static int alg_setkey(struct sock *sk, char __user *ukey,
@@ -199,11 +228,15 @@ static int alg_setsockopt(struct socket
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
 	const struct af_alg_type *type;
-	int err = -ENOPROTOOPT;
+	int err = -EBUSY;
 
 	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock;
+
 	type = ask->type;
 
+	err = -ENOPROTOOPT;
 	if (level != SOL_ALG || !type)
 		goto unlock;
 
@@ -228,6 +261,7 @@ int af_alg_accept(struct sock *sk, struc
 	struct alg_sock *ask = alg_sk(sk);
 	const struct af_alg_type *type;
 	struct sock *sk2;
+	unsigned int nokey;
 	int err;
 
 	lock_sock(sk);
@@ -247,20 +281,29 @@ int af_alg_accept(struct sock *sk, struc
 	security_sk_clone(sk, sk2);
 
 	err = type->accept(ask->private, sk2);
-	if (err) {
-		sk_free(sk2);
+
+	nokey = err == -ENOKEY;
+	if (nokey && type->accept_nokey)
+		err = type->accept_nokey(ask->private, sk2);
+
+	if (err)
 		goto unlock;
-	}
 
 	sk2->sk_family = PF_ALG;
 
-	sock_hold(sk);
+	if (nokey || !ask->refcnt++)
+		sock_hold(sk);
+	ask->nokey_refcnt += nokey;
 	alg_sk(sk2)->parent = sk;
 	alg_sk(sk2)->type = type;
+	alg_sk(sk2)->nokey_refcnt = nokey;
 
 	newsock->ops = type->ops;
 	newsock->state = SS_CONNECTED;
 
+	if (nokey)
+		newsock->ops = type->ops_nokey;
+
 	err = 0;
 
 unlock:
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/ahash.c linux-libre-3.2.77-gnu1/crypto/ahash.c
--- linux-libre-3.2.76-gnu1/crypto/ahash.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/ahash.c	2016-02-13 05:34:14.000000000 -0500
@@ -369,6 +369,7 @@ static int crypto_ahash_init_tfm(struct
 	struct ahash_alg *alg = crypto_ahash_alg(hash);
 
 	hash->setkey = ahash_nosetkey;
+	hash->has_setkey = false;
 	hash->export = ahash_no_export;
 	hash->import = ahash_no_import;
 
@@ -381,8 +382,10 @@ static int crypto_ahash_init_tfm(struct
 	hash->finup = alg->finup ?: ahash_def_finup;
 	hash->digest = alg->digest;
 
-	if (alg->setkey)
+	if (alg->setkey) {
 		hash->setkey = alg->setkey;
+		hash->has_setkey = true;
+	}
 	if (alg->export)
 		hash->export = alg->export;
 	if (alg->import)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/algif_hash.c linux-libre-3.2.77-gnu1/crypto/algif_hash.c
--- linux-libre-3.2.76-gnu1/crypto/algif_hash.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/algif_hash.c	2016-02-13 05:34:14.000000000 -0500
@@ -34,6 +34,11 @@ struct hash_ctx {
 	struct ahash_request req;
 };
 
+struct algif_hash_tfm {
+	struct crypto_ahash *hash;
+	bool has_key;
+};
+
 static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
 			struct msghdr *msg, size_t ignored)
 {
@@ -246,19 +251,151 @@ static struct proto_ops algif_hash_ops =
 	.accept		=	hash_accept,
 };
 
+static int hash_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct algif_hash_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int hash_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
+			      struct msghdr *msg, size_t size)
+{
+	int err;
+
+	err = hash_check_key(sock);
+	if (err)
+		return err;
+
+	return hash_sendmsg(unused, sock, msg, size);
+}
+
+static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
+				   int offset, size_t size, int flags)
+{
+	int err;
+
+	err = hash_check_key(sock);
+	if (err)
+		return err;
+
+	return hash_sendpage(sock, page, offset, size, flags);
+}
+
+static int hash_recvmsg_nokey(struct kiocb *unused, struct socket *sock,
+			      struct msghdr *msg, size_t ignored, int flags)
+{
+	int err;
+
+	err = hash_check_key(sock);
+	if (err)
+		return err;
+
+	return hash_recvmsg(unused, sock, msg, ignored, flags);
+}
+
+static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
+			     int flags)
+{
+	int err;
+
+	err = hash_check_key(sock);
+	if (err)
+		return err;
+
+	return hash_accept(sock, newsock, flags);
+}
+
+static struct proto_ops algif_hash_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.setsockopt	=	sock_no_setsockopt,
+	.poll		=	sock_no_poll,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	hash_sendmsg_nokey,
+	.sendpage	=	hash_sendpage_nokey,
+	.recvmsg	=	hash_recvmsg_nokey,
+	.accept		=	hash_accept_nokey,
+};
+
 static void *hash_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_ahash(name, type, mask);
+	struct algif_hash_tfm *tfm;
+	struct crypto_ahash *hash;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	hash = crypto_alloc_ahash(name, type, mask);
+	if (IS_ERR(hash)) {
+		kfree(tfm);
+		return ERR_CAST(hash);
+	}
+
+	tfm->hash = hash;
+
+	return tfm;
 }
 
 static void hash_release(void *private)
 {
-	crypto_free_ahash(private);
+	struct algif_hash_tfm *tfm = private;
+
+	crypto_free_ahash(tfm->hash);
+	kfree(tfm);
 }
 
 static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_ahash_setkey(private, key, keylen);
+	struct algif_hash_tfm *tfm = private;
+	int err;
+
+	err = crypto_ahash_setkey(tfm->hash, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void hash_sock_destruct(struct sock *sk)
@@ -272,12 +409,14 @@ static void hash_sock_destruct(struct so
 	af_alg_release_parent(sk);
 }
 
-static int hash_accept_parent(void *private, struct sock *sk)
+static int hash_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct hash_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
-	unsigned ds = crypto_ahash_digestsize(private);
+	struct algif_hash_tfm *tfm = private;
+	struct crypto_ahash *hash = tfm->hash;
+	unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
+	unsigned ds = crypto_ahash_digestsize(hash);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -297,7 +436,7 @@ static int hash_accept_parent(void *priv
 
 	ask->private = ctx;
 
-	ahash_request_set_tfm(&ctx->req, private);
+	ahash_request_set_tfm(&ctx->req, hash);
 	ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				   af_alg_complete, &ctx->completion);
 
@@ -306,12 +445,24 @@ static int hash_accept_parent(void *priv
 	return 0;
 }
 
+static int hash_accept_parent(void *private, struct sock *sk)
+{
+	struct algif_hash_tfm *tfm = private;
+
+	if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
+		return -ENOKEY;
+
+	return hash_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_hash = {
 	.bind		=	hash_bind,
 	.release	=	hash_release,
 	.setkey		=	hash_setkey,
 	.accept		=	hash_accept_parent,
+	.accept_nokey	=	hash_accept_parent_nokey,
 	.ops		=	&algif_hash_ops,
+	.ops_nokey	=	&algif_hash_ops_nokey,
 	.name		=	"hash",
 	.owner		=	THIS_MODULE
 };
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/algif_skcipher.c linux-libre-3.2.77-gnu1/crypto/algif_skcipher.c
--- linux-libre-3.2.76-gnu1/crypto/algif_skcipher.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/algif_skcipher.c	2016-02-13 05:34:14.000000000 -0500
@@ -31,6 +31,11 @@ struct skcipher_sg_list {
 	struct scatterlist sg[0];
 };
 
+struct skcipher_tfm {
+	struct crypto_ablkcipher *skcipher;
+	bool has_key;
+};
+
 struct skcipher_ctx {
 	struct list_head tsgl;
 	struct af_alg_sgl rsgl;
@@ -441,13 +446,6 @@ static int skcipher_recvmsg(struct kiocb
 		char __user *from = iov->iov_base;
 
 		while (seglen) {
-			sgl = list_first_entry(&ctx->tsgl,
-					       struct skcipher_sg_list, list);
-			sg = sgl->sg;
-
-			while (!sg->length)
-				sg++;
-
 			used = ctx->used;
 			if (!used) {
 				err = skcipher_wait_for_data(sk, flags);
@@ -469,6 +467,13 @@ static int skcipher_recvmsg(struct kiocb
 			if (!used)
 				goto free;
 
+			sgl = list_first_entry(&ctx->tsgl,
+					       struct skcipher_sg_list, list);
+			sg = sgl->sg;
+
+			while (!sg->length)
+				sg++;
+
 			ablkcipher_request_set_crypt(&ctx->req, sg,
 						     ctx->rsgl.sg, used,
 						     ctx->iv);
@@ -544,19 +549,139 @@ static struct proto_ops algif_skcipher_o
 	.poll		=	skcipher_poll,
 };
 
+static int skcipher_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct skcipher_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int skcipher_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
+				  struct msghdr *msg, size_t size)
+{
+	int err;
+
+	err = skcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return skcipher_sendmsg(unused, sock, msg, size);
+}
+
+static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = skcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return skcipher_sendpage(sock, page, offset, size, flags);
+}
+
+static int skcipher_recvmsg_nokey(struct kiocb *unused, struct socket *sock,
+				  struct msghdr *msg, size_t ignored, int flags)
+{
+	int err;
+
+	err = skcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return skcipher_recvmsg(unused, sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_skcipher_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	skcipher_sendmsg_nokey,
+	.sendpage	=	skcipher_sendpage_nokey,
+	.recvmsg	=	skcipher_recvmsg_nokey,
+	.poll		=	skcipher_poll,
+};
+
 static void *skcipher_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_ablkcipher(name, type, mask);
+	struct skcipher_tfm *tfm;
+	struct crypto_ablkcipher *skcipher;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	skcipher = crypto_alloc_ablkcipher(name, type, mask);
+	if (IS_ERR(skcipher)) {
+		kfree(tfm);
+		return ERR_CAST(skcipher);
+	}
+
+	tfm->skcipher = skcipher;
+
+	return tfm;
 }
 
 static void skcipher_release(void *private)
 {
-	crypto_free_ablkcipher(private);
+	struct skcipher_tfm *tfm = private;
+
+	crypto_free_ablkcipher(tfm->skcipher);
+	kfree(tfm);
 }
 
 static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_ablkcipher_setkey(private, key, keylen);
+	struct skcipher_tfm *tfm = private;
+	int err;
+
+	err = crypto_ablkcipher_setkey(tfm->skcipher, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void skcipher_sock_destruct(struct sock *sk)
@@ -571,24 +696,26 @@ static void skcipher_sock_destruct(struc
 	af_alg_release_parent(sk);
 }
 
-static int skcipher_accept_parent(void *private, struct sock *sk)
+static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct skcipher_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
+	struct skcipher_tfm *tfm = private;
+	struct crypto_ablkcipher *skcipher = tfm->skcipher;
+	unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(skcipher);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
 
-	ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
+	ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(skcipher),
 			       GFP_KERNEL);
 	if (!ctx->iv) {
 		sock_kfree_s(sk, ctx, len);
 		return -ENOMEM;
 	}
 
-	memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
+	memset(ctx->iv, 0, crypto_ablkcipher_ivsize(skcipher));
 
 	INIT_LIST_HEAD(&ctx->tsgl);
 	ctx->len = len;
@@ -600,7 +727,7 @@ static int skcipher_accept_parent(void *
 
 	ask->private = ctx;
 
-	ablkcipher_request_set_tfm(&ctx->req, private);
+	ablkcipher_request_set_tfm(&ctx->req, skcipher);
 	ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 					af_alg_complete, &ctx->completion);
 
@@ -609,12 +736,24 @@ static int skcipher_accept_parent(void *
 	return 0;
 }
 
+static int skcipher_accept_parent(void *private, struct sock *sk)
+{
+	struct skcipher_tfm *tfm = private;
+
+	if (!tfm->has_key && crypto_ablkcipher_has_setkey(tfm->skcipher))
+		return -ENOKEY;
+
+	return skcipher_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_skcipher = {
 	.bind		=	skcipher_bind,
 	.release	=	skcipher_release,
 	.setkey		=	skcipher_setkey,
 	.accept		=	skcipher_accept_parent,
+	.accept_nokey	=	skcipher_accept_parent_nokey,
 	.ops		=	&algif_skcipher_ops,
+	.ops_nokey	=	&algif_skcipher_ops_nokey,
 	.name		=	"skcipher",
 	.owner		=	THIS_MODULE
 };
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/crypto/shash.c linux-libre-3.2.77-gnu1/crypto/shash.c
--- linux-libre-3.2.76-gnu1/crypto/shash.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/crypto/shash.c	2016-02-13 05:34:14.000000000 -0500
@@ -354,8 +354,10 @@ int crypto_init_shash_ops_async(struct c
 	crt->finup = shash_async_finup;
 	crt->digest = shash_async_digest;
 
-	if (alg->setkey)
+	if (alg->setkey) {
 		crt->setkey = shash_async_setkey;
+		crt->has_setkey = true;
+	}
 	if (alg->export)
 		crt->export = shash_async_export;
 	if (alg->import)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/edac/edac_device.c linux-libre-3.2.77-gnu1/drivers/edac/edac_device.c
--- linux-libre-3.2.76-gnu1/drivers/edac/edac_device.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/edac/edac_device.c	2016-02-13 05:34:14.000000000 -0500
@@ -444,13 +444,10 @@ void edac_device_workq_setup(struct edac
  */
 void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
 {
-	int status;
+	edac_dev->op_state = OP_OFFLINE;
 
-	status = cancel_delayed_work(&edac_dev->work);
-	if (status == 0) {
-		/* workq instance might be running, wait for it */
-		flush_workqueue(edac_workqueue);
-	}
+	cancel_delayed_work_sync(&edac_dev->work);
+	flush_workqueue(edac_workqueue);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/edac/edac_mc.c linux-libre-3.2.77-gnu1/drivers/edac/edac_mc.c
--- linux-libre-3.2.76-gnu1/drivers/edac/edac_mc.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/edac/edac_mc.c	2016-02-13 05:34:14.000000000 -0500
@@ -348,19 +348,10 @@ static void edac_mc_workq_setup(struct m
  */
 static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
 {
-	int status;
-
-	if (mci->op_state != OP_RUNNING_POLL)
-		return;
-
-	status = cancel_delayed_work(&mci->work);
-	if (status == 0) {
-		debugf0("%s() not canceled, flush the queue\n",
-			__func__);
+	mci->op_state = OP_OFFLINE;
 
-		/* workq instance might be running, wait for it */
-		flush_workqueue(edac_workqueue);
-	}
+	cancel_delayed_work_sync(&mci->work);
+	flush_workqueue(edac_workqueue);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/edac/edac_pci.c linux-libre-3.2.77-gnu1/drivers/edac/edac_pci.c
--- linux-libre-3.2.76-gnu1/drivers/edac/edac_pci.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/edac/edac_pci.c	2016-02-13 05:34:14.000000000 -0500
@@ -275,13 +275,12 @@ static void edac_pci_workq_setup(struct
  */
 static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
 {
-	int status;
-
 	debugf0("%s()\n", __func__);
 
-	status = cancel_delayed_work(&pci->work);
-	if (status == 0)
-		flush_workqueue(edac_workqueue);
+	pci->op_state = OP_OFFLINE;
+
+	cancel_delayed_work_sync(&pci->work);
+	flush_workqueue(edac_workqueue);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.2.77-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.2.76-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2016-02-13 05:34:14.000000000 -0500
@@ -446,7 +446,9 @@ static bool radeon_atom_apply_quirks(str
 	}
 
 	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
-	if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&
+	if (((dev->pdev->device == 0x9802) ||
+	     (dev->pdev->device == 0x9805) ||
+	     (dev->pdev->device == 0x9806)) &&
 	    (dev->pdev->subsystem_vendor == 0x1734) &&
 	    (dev->pdev->subsystem_device == 0x11bd)) {
 		if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
@@ -457,14 +459,6 @@ static bool radeon_atom_apply_quirks(str
 		}
 	}
 
-	/* 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;
 }
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/gpu/drm/radeon/radeon_device.c linux-libre-3.2.77-gnu1/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-3.2.76-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2016-02-13 05:34:14.000000000 -0500
@@ -960,6 +960,7 @@ int radeon_resume_kms(struct drm_device
 	}
 
 	drm_kms_helper_poll_enable(dev);
+	drm_helper_hpd_irq_event(dev);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/infiniband/hw/mlx4/ah.c linux-libre-3.2.77-gnu1/drivers/infiniband/hw/mlx4/ah.c
--- linux-libre-3.2.76-gnu1/drivers/infiniband/hw/mlx4/ah.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/infiniband/hw/mlx4/ah.c	2016-02-13 05:34:14.000000000 -0500
@@ -112,6 +112,7 @@ static struct ib_ah *create_iboe_ah(stru
 	ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
 	ah->av.eth.gid_index = ah_attr->grh.sgid_index;
 	ah->av.eth.vlan = cpu_to_be16(vlan_tag);
+	ah->av.eth.hop_limit = ah_attr->grh.hop_limit;
 	if (ah_attr->static_rate) {
 		ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
 		while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/infiniband/hw/qib/qib_verbs_mcast.c linux-libre-3.2.77-gnu1/drivers/infiniband/hw/qib/qib_verbs_mcast.c
--- linux-libre-3.2.76-gnu1/drivers/infiniband/hw/qib/qib_verbs_mcast.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/infiniband/hw/qib/qib_verbs_mcast.c	2016-02-13 05:34:14.000000000 -0500
@@ -286,15 +286,13 @@ int qib_multicast_detach(struct ib_qp *i
 	struct qib_ibdev *dev = to_idev(ibqp->device);
 	struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num);
 	struct qib_mcast *mcast = NULL;
-	struct qib_mcast_qp *p, *tmp;
+	struct qib_mcast_qp *p, *tmp, *delp = NULL;
 	struct rb_node *n;
 	int last = 0;
 	int ret;
 
-	if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) {
-		ret = -EINVAL;
-		goto bail;
-	}
+	if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
+		return -EINVAL;
 
 	spin_lock_irq(&ibp->lock);
 
@@ -303,8 +301,7 @@ int qib_multicast_detach(struct ib_qp *i
 	while (1) {
 		if (n == NULL) {
 			spin_unlock_irq(&ibp->lock);
-			ret = -EINVAL;
-			goto bail;
+			return -EINVAL;
 		}
 
 		mcast = rb_entry(n, struct qib_mcast, rb_node);
@@ -328,6 +325,7 @@ int qib_multicast_detach(struct ib_qp *i
 		 */
 		list_del_rcu(&p->list);
 		mcast->n_attached--;
+		delp = p;
 
 		/* If this was the last attached QP, remove the GID too. */
 		if (list_empty(&mcast->qp_list)) {
@@ -338,15 +336,16 @@ int qib_multicast_detach(struct ib_qp *i
 	}
 
 	spin_unlock_irq(&ibp->lock);
+	/* QP not attached */
+	if (!delp)
+		return -EINVAL;
+	/*
+	 * Wait for any list walkers to finish before freeing the
+	 * list element.
+	 */
+	wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+	qib_mcast_qp_free(delp);
 
-	if (p) {
-		/*
-		 * Wait for any list walkers to finish before freeing the
-		 * list element.
-		 */
-		wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
-		qib_mcast_qp_free(p);
-	}
 	if (last) {
 		atomic_dec(&mcast->refcount);
 		wait_event(mcast->wait, !atomic_read(&mcast->refcount));
@@ -355,11 +354,7 @@ int qib_multicast_detach(struct ib_qp *i
 		dev->n_mcast_grps_allocated--;
 		spin_unlock_irq(&dev->n_mcast_grps_lock);
 	}
-
-	ret = 0;
-
-bail:
-	return ret;
+	return 0;
 }
 
 int qib_mcast_tree_empty(struct qib_ibport *ibp)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.2.77-gnu1/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.2.76-gnu1/drivers/input/serio/i8042-x86ia64io.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/input/serio/i8042-x86ia64io.h	2016-02-13 05:34:14.000000000 -0500
@@ -258,6 +258,13 @@ static const struct dmi_system_id __init
 		},
 	},
 	{
+		/* Fujitsu Lifebook U745 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
+		},
+	},
+	{
 		/* Fujitsu T70H */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/md/dm-exception-store.h linux-libre-3.2.77-gnu1/drivers/md/dm-exception-store.h
--- linux-libre-3.2.76-gnu1/drivers/md/dm-exception-store.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/md/dm-exception-store.h	2016-02-13 05:34:14.000000000 -0500
@@ -70,7 +70,7 @@ struct dm_exception_store_type {
 	 * Update the metadata with this exception.
 	 */
 	void (*commit_exception) (struct dm_exception_store *store,
-				  struct dm_exception *e,
+				  struct dm_exception *e, int valid,
 				  void (*callback) (void *, int success),
 				  void *callback_context);
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/md/dm-snap.c linux-libre-3.2.77-gnu1/drivers/md/dm-snap.c
--- linux-libre-3.2.76-gnu1/drivers/md/dm-snap.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/md/dm-snap.c	2016-02-13 05:34:14.000000000 -0500
@@ -1393,8 +1393,9 @@ static void __invalidate_snapshot(struct
 	dm_table_event(s->ti->table);
 }
 
-static void pending_complete(struct dm_snap_pending_exception *pe, int success)
+static void pending_complete(void *context, int success)
 {
+	struct dm_snap_pending_exception *pe = context;
 	struct dm_exception *e;
 	struct dm_snapshot *s = pe->snap;
 	struct bio *origin_bios = NULL;
@@ -1464,24 +1465,13 @@ out:
 	free_pending_exception(pe);
 }
 
-static void commit_callback(void *context, int success)
-{
-	struct dm_snap_pending_exception *pe = context;
-
-	pending_complete(pe, success);
-}
-
 static void complete_exception(struct dm_snap_pending_exception *pe)
 {
 	struct dm_snapshot *s = pe->snap;
 
-	if (unlikely(pe->copy_error))
-		pending_complete(pe, 0);
-
-	else
-		/* Update the metadata if we are persistent */
-		s->store->type->commit_exception(s->store, &pe->e,
-						 commit_callback, pe);
+	/* Update the metadata if we are persistent */
+	s->store->type->commit_exception(s->store, &pe->e, !pe->copy_error,
+					 pending_complete, pe);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/md/dm-snap-persistent.c linux-libre-3.2.77-gnu1/drivers/md/dm-snap-persistent.c
--- linux-libre-3.2.76-gnu1/drivers/md/dm-snap-persistent.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/md/dm-snap-persistent.c	2016-02-13 05:34:14.000000000 -0500
@@ -646,7 +646,7 @@ static int persistent_prepare_exception(
 }
 
 static void persistent_commit_exception(struct dm_exception_store *store,
-					struct dm_exception *e,
+					struct dm_exception *e, int valid,
 					void (*callback) (void *, int success),
 					void *callback_context)
 {
@@ -655,6 +655,9 @@ static void persistent_commit_exception(
 	struct core_exception ce;
 	struct commit_callback *cb;
 
+	if (!valid)
+		ps->valid = 0;
+
 	ce.old_chunk = e->old_chunk;
 	ce.new_chunk = e->new_chunk;
 	write_exception(ps, ps->current_committed++, &ce);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/md/dm-snap-transient.c linux-libre-3.2.77-gnu1/drivers/md/dm-snap-transient.c
--- linux-libre-3.2.76-gnu1/drivers/md/dm-snap-transient.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/md/dm-snap-transient.c	2016-02-13 05:34:14.000000000 -0500
@@ -52,12 +52,12 @@ static int transient_prepare_exception(s
 }
 
 static void transient_commit_exception(struct dm_exception_store *store,
-				       struct dm_exception *e,
+				       struct dm_exception *e, int valid,
 				       void (*callback) (void *, int success),
 				       void *callback_context)
 {
 	/* Just succeed */
-	callback(callback_context, 1);
+	callback(callback_context, valid);
 }
 
 static void transient_usage(struct dm_exception_store *store,
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-3.2.77-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-3.2.76-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/media/dvb/dvb-core/dvb_frontend.c	2016-02-13 05:34:14.000000000 -0500
@@ -1661,9 +1661,9 @@ static int dvb_frontend_ioctl_legacy(str
 		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
 		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
 
-		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
-		 * do it, it is done for it. */
-		info->caps |= FE_CAN_INVERSION_AUTO;
+		/* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */
+		if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT))
+			info->caps |= FE_CAN_INVERSION_AUTO;
 		err = 0;
 		break;
 	}
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/media/rc/rc-main.c linux-libre-3.2.77-gnu1/drivers/media/rc/rc-main.c
--- linux-libre-3.2.76-gnu1/drivers/media/rc/rc-main.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/media/rc/rc-main.c	2016-02-13 05:34:14.000000000 -0500
@@ -54,7 +54,7 @@ struct rc_map *rc_map_get(const char *na
 	struct rc_map_list *map;
 
 	map = seek_rc_map(name);
-#ifdef MODULE
+#ifdef CONFIG_MODULES
 	if (!map) {
 		int rc = request_module(name);
 		if (rc < 0) {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/media/video/gspca/ov534.c linux-libre-3.2.77-gnu1/drivers/media/video/gspca/ov534.c
--- linux-libre-3.2.76-gnu1/drivers/media/video/gspca/ov534.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/media/video/gspca/ov534.c	2016-02-13 05:34:14.000000000 -0500
@@ -1481,8 +1481,13 @@ static void sd_set_streamparm(struct gsp
 	struct v4l2_fract *tpf = &cp->timeperframe;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	/* Set requested framerate */
-	sd->frame_rate = tpf->denominator / tpf->numerator;
+	if (tpf->numerator == 0 || tpf->denominator == 0)
+		/* Set default framerate */
+		sd->frame_rate = 30;
+	else
+		/* Set requested framerate */
+		sd->frame_rate = tpf->denominator / tpf->numerator;
+
 	if (gspca_dev->streaming)
 		set_frame_rate(gspca_dev);
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/media/video/gspca/topro.c linux-libre-3.2.77-gnu1/drivers/media/video/gspca/topro.c
--- linux-libre-3.2.76-gnu1/drivers/media/video/gspca/topro.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/media/video/gspca/topro.c	2016-02-13 05:34:14.000000000 -0500
@@ -4789,7 +4789,11 @@ static void sd_set_streamparm(struct gsp
 	struct v4l2_fract *tpf = &cp->timeperframe;
 	int fr, i;
 
-	sd->framerate = tpf->denominator / tpf->numerator;
+	if (tpf->numerator == 0 || tpf->denominator == 0)
+		sd->framerate = 30;
+	else
+		sd->framerate = tpf->denominator / tpf->numerator;
+
 	if (gspca_dev->streaming)
 		setframerate(gspca_dev);
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/media/video/usbvision/usbvision-video.c linux-libre-3.2.77-gnu1/drivers/media/video/usbvision/usbvision-video.c
--- linux-libre-3.2.76-gnu1/drivers/media/video/usbvision/usbvision-video.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/media/video/usbvision/usbvision-video.c	2016-02-13 05:34:14.000000000 -0500
@@ -1425,6 +1425,7 @@ static void usbvision_release(struct usb
 
 	usbvision_remove_sysfs(usbvision->vdev);
 	usbvision_unregister_video(usbvision);
+	kfree(usbvision->alt_max_pkt_size);
 
 	usb_free_urb(usbvision->ctrl_urb);
 
@@ -1486,7 +1487,7 @@ static int __devinit usbvision_probe(str
 	const struct usb_host_interface *interface;
 	struct usb_usbvision *usbvision = NULL;
 	const struct usb_endpoint_descriptor *endpoint;
-	int model, i;
+	int model, i, ret;
 
 	PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
 				dev->descriptor.idVendor,
@@ -1495,33 +1496,58 @@ static int __devinit usbvision_probe(str
 	model = devid->driver_info;
 	if (model < 0 || model >= usbvision_device_data_size) {
 		PDEBUG(DBG_PROBE, "model out of bounds %d", model);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_usb;
 	}
 	printk(KERN_INFO "%s: %s found\n", __func__,
 				usbvision_device_data[model].model_string);
 
+	/*
+	 * this is a security check.
+	 * an exploit using an incorrect bInterfaceNumber is known
+	 */
+	if (ifnum >= USB_MAXINTERFACES || !dev->actconfig->interface[ifnum])
+		return -ENODEV;
+
 	if (usbvision_device_data[model].interface >= 0)
 		interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
-	else
+	else if (ifnum < dev->actconfig->desc.bNumInterfaces)
 		interface = &dev->actconfig->interface[ifnum]->altsetting[0];
+	else {
+		dev_err(&intf->dev, "interface %d is invalid, max is %d\n",
+		    ifnum, dev->actconfig->desc.bNumInterfaces - 1);
+		ret = -ENODEV;
+		goto err_usb;
+	}
+
+	if (interface->desc.bNumEndpoints < 2) {
+		dev_err(&intf->dev, "interface %d has %d endpoints, but must"
+		    " have minimum 2\n", ifnum, interface->desc.bNumEndpoints);
+		ret = -ENODEV;
+		goto err_usb;
+	}
 	endpoint = &interface->endpoint[1].desc;
+
 	if (!usb_endpoint_xfer_isoc(endpoint)) {
 		dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
 		    __func__, ifnum);
 		dev_err(&intf->dev, "%s: Endpoint attributes %d",
 		    __func__, endpoint->bmAttributes);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_usb;
 	}
 	if (usb_endpoint_dir_out(endpoint)) {
 		dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n",
 		    __func__, ifnum);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_usb;
 	}
 
 	usbvision = usbvision_alloc(dev, intf);
 	if (usbvision == NULL) {
 		dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_usb;
 	}
 
 	if (dev->descriptor.bNumConfigurations > 1)
@@ -1540,7 +1566,8 @@ static int __devinit usbvision_probe(str
 	usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
 	if (usbvision->alt_max_pkt_size == NULL) {
 		dev_err(&intf->dev, "usbvision: out of memory!\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_pkt;
 	}
 
 	for (i = 0; i < usbvision->num_alt; i++) {
@@ -1575,6 +1602,12 @@ static int __devinit usbvision_probe(str
 
 	PDEBUG(DBG_PROBE, "success");
 	return 0;
+
+err_pkt:
+	usbvision_release(usbvision);
+err_usb:
+	usb_put_dev(dev);
+	return ret;
 }
 
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/usb/asix.c linux-libre-3.2.77-gnu1/drivers/net/usb/asix.c
--- linux-libre-3.2.76-gnu1/drivers/net/usb/asix.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/usb/asix.c	2016-02-13 05:34:14.000000000 -0500
@@ -361,7 +361,7 @@ static int asix_rx_fixup_internal(struct
 		}
 
 		if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
-			netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
+			netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
 				   rx->size);
 			kfree_skb(rx->ax_skb);
 			return 0;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c linux-libre-3.2.77-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c	2016-02-13 05:34:14.000000000 -0500
@@ -377,7 +377,7 @@ void ath9k_htc_rx_msg(struct htc_target
 	htc_hdr = (struct htc_frame_hdr *) skb->data;
 	epid = htc_hdr->endpoint_id;
 
-	if (epid >= ENDPOINT_MAX) {
+	if (epid < 0 || epid >= ENDPOINT_MAX) {
 		if (pipe_id != USB_REG_IN_PIPE)
 			dev_kfree_skb_any(skb);
 		else
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2016-01-23 22:46:14.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2016-02-13 23:25:53.000000000 -0500
@@ -138,6 +138,8 @@ int rtl92c_init_sw_vars(struct ieee80211
 	rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
 	rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
 	rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+	rtlpriv->cfg->mod_params->sw_crypto =
+		rtlpriv->cfg->mod_params->sw_crypto;
 	if (!rtlpriv->psc.inactiveps)
 		pr_info("rtl8192ce: Power Save off (module option)\n");
 	if (!rtlpriv->psc.fwctrl_lps)
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2016-01-23 22:46:16.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2016-02-13 23:25:55.000000000 -0500
@@ -62,6 +62,8 @@ static int rtl92cu_init_sw_vars(struct i
 	rtlpriv->dm.disable_framebursting = 0;
 	rtlpriv->dm.thermalvalue = 0;
 	rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
+	rtlpriv->cfg->mod_params->sw_crypto =
+		rtlpriv->cfg->mod_params->sw_crypto;
 	rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
 	if (!rtlpriv->rtlhal.pfirmware) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c	2016-01-23 22:46:20.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c	2016-02-13 23:25:57.000000000 -0500
@@ -387,8 +387,8 @@ module_param_named(swlps, rtl92de_mod_pa
 module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
-MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
 
 static const struct dev_pm_ops rtlwifi_pm_ops = {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c	2016-01-23 22:46:22.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c	2016-02-13 23:25:59.000000000 -0500
@@ -167,6 +167,8 @@ static int rtl92s_init_sw_vars(struct ie
 	rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
 	rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
 	rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+	rtlpriv->cfg->mod_params->sw_crypto =
+		rtlpriv->cfg->mod_params->sw_crypto;
 	if (!rtlpriv->psc.inactiveps)
 		pr_info("rtl8192ce: Power Save off (module option)\n");
 	if (!rtlpriv->psc.fwctrl_lps)
@@ -399,8 +401,8 @@ module_param_named(swlps, rtl92se_mod_pa
 module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
-MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
 
 static const struct dev_pm_ops rtlwifi_pm_ops = {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/usb.c linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/usb.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/rtlwifi/usb.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/rtlwifi/usb.c	2016-02-13 05:34:14.000000000 -0500
@@ -500,6 +500,8 @@ static void _rtl_usb_rx_process_noagg(st
 		} else {
 			dev_kfree_skb_any(skb);
 		}
+	} else {
+		dev_kfree_skb_any(skb);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/net/wireless/wl12xx/spi.c linux-libre-3.2.77-gnu1/drivers/net/wireless/wl12xx/spi.c
--- linux-libre-3.2.76-gnu1/drivers/net/wireless/wl12xx/spi.c	2016-01-23 22:46:42.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/net/wireless/wl12xx/spi.c	2016-02-13 23:26:16.000000000 -0500
@@ -67,7 +67,10 @@
 /* HW limitation: maximum possible chunk size is 4095 bytes */
 #define WSPI_MAX_CHUNK_SIZE    4092
 
-#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
+/* Maximum number of SPI write chunks */
+#define WSPI_MAX_NUM_OF_CHUNKS \
+	((WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
+
 
 static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
 {
@@ -274,9 +277,10 @@ static void wl1271_spi_raw_read(struct w
 static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
 			  size_t len, bool fixed)
 {
+	/* SPI write buffers - 2 for each chunk */
 	struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
 	struct spi_message m;
-	u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
+	u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
 	u32 *cmd;
 	u32 chunk_len;
 	int i;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/power/test_power.c linux-libre-3.2.77-gnu1/drivers/power/test_power.c
--- linux-libre-3.2.76-gnu1/drivers/power/test_power.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/power/test_power.c	2016-02-13 05:34:14.000000000 -0500
@@ -237,6 +237,8 @@ static int map_get_value(struct battery_
 	buf[MAX_KEYLENGTH-1] = '\0';
 
 	cr = strnlen(buf, MAX_KEYLENGTH) - 1;
+	if (cr < 0)
+		return def_val;
 	if (buf[cr] == '\n')
 		buf[cr] = '\0';
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/scsi/initio.c linux-libre-3.2.77-gnu1/drivers/scsi/initio.c
--- linux-libre-3.2.76-gnu1/drivers/scsi/initio.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/scsi/initio.c	2016-02-13 05:34:14.000000000 -0500
@@ -110,11 +110,6 @@
 #define i91u_MAXQUEUE		2
 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"
 
-#define I950_DEVICE_ID	0x9500	/* Initio's inic-950 product ID   */
-#define I940_DEVICE_ID	0x9400	/* Initio's inic-940 product ID   */
-#define I935_DEVICE_ID	0x9401	/* Initio's inic-935 product ID   */
-#define I920_DEVICE_ID	0x0002	/* Initio's other product ID      */
-
 #ifdef DEBUG_i91u
 static unsigned int i91u_debug = DEBUG_DEFAULT;
 #endif
@@ -127,17 +122,6 @@ static int setup_debug = 0;
 
 static void i91uSCBPost(u8 * pHcb, u8 * pScb);
 
-/* PCI Devices supported by this driver */
-static struct pci_device_id i91u_pci_devices[] = {
-	{ PCI_VENDOR_ID_INIT,  I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_INIT,  I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_INIT,  I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_INIT,  I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_DOMEX, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, i91u_pci_devices);
-
 #define DEBUG_INTERRUPT 0
 #define DEBUG_QUEUE     0
 #define DEBUG_STATE     0
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/usb/host/xhci.c linux-libre-3.2.77-gnu1/drivers/usb/host/xhci.c
--- linux-libre-3.2.76-gnu1/drivers/usb/host/xhci.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/usb/host/xhci.c	2016-02-13 05:34:14.000000000 -0500
@@ -4300,6 +4300,9 @@ static int __init xhci_hcd_init(void)
 {
 	int retval;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	retval = xhci_register_pci();
 	if (retval < 0) {
 		printk(KERN_DEBUG "Problem registering PCI driver.");
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/drivers/usb/serial/cp210x.c linux-libre-3.2.77-gnu1/drivers/usb/serial/cp210x.c
--- linux-libre-3.2.76-gnu1/drivers/usb/serial/cp210x.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/drivers/usb/serial/cp210x.c	2016-02-13 05:34:14.000000000 -0500
@@ -166,6 +166,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
 	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+	{ USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
 	{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
 	{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
 	{ USB_DEVICE(0x1BA4, 0x0002) },	/* Silicon Labs 358x factory default */
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/cifs/cifs_debug.h linux-libre-3.2.77-gnu1/fs/cifs/cifs_debug.h
--- linux-libre-3.2.76-gnu1/fs/cifs/cifs_debug.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/cifs/cifs_debug.h	2016-02-13 05:34:14.000000000 -0500
@@ -23,6 +23,8 @@
 #ifndef _H_CIFS_DEBUG
 #define _H_CIFS_DEBUG
 
+#include <linux/ratelimit.h>
+
 void cifs_dump_mem(char *label, void *data, int length);
 #ifdef CONFIG_CIFS_DEBUG2
 #define DBG2 2
@@ -48,7 +50,7 @@ extern int cifsFYI;
 #define cifsfyi(fmt, arg...)						\
 do {									\
 	if (cifsFYI & CIFS_INFO)					\
-		printk(KERN_DEBUG "%s: " fmt "\n", __FILE__, ##arg);	\
+		pr_debug_ratelimited("%s: " fmt "\n", __FILE__, ##arg); \
 } while (0)
 
 #define cFYI(set, fmt, arg...)			\
@@ -58,7 +60,7 @@ do {						\
 } while (0)
 
 #define cifswarn(fmt, arg...)			\
-	printk(KERN_WARNING fmt "\n", ##arg)
+	pr_warn_ratelimited(fmt "\n", ##arg)
 
 /* debug event message: */
 extern int cifsERROR;
@@ -73,7 +75,7 @@ do {									\
 #define cifserror(fmt, arg...)					\
 do {								\
 	if (cifsERROR)						\
-		printk(KERN_ERR "CIFS VFS: " fmt "\n", ##arg);	\
+		pr_err_ratelimited("CIFS VFS: " fmt "\n", ##arg);	\
 } while (0)
 
 #define cERROR(set, fmt, arg...)		\
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/cifs/connect.c linux-libre-3.2.77-gnu1/fs/cifs/connect.c
--- linux-libre-3.2.76-gnu1/fs/cifs/connect.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/cifs/connect.c	2016-02-13 05:34:14.000000000 -0500
@@ -134,7 +134,6 @@ cifs_reconnect(struct TCP_Server_Info *s
 	server->session_key.response = NULL;
 	server->session_key.len = 0;
 	server->lstrp = jiffies;
-	mutex_unlock(&server->srv_mutex);
 
 	/* mark submitted MIDs for retry and issue callback */
 	INIT_LIST_HEAD(&retry_list);
@@ -147,6 +146,7 @@ cifs_reconnect(struct TCP_Server_Info *s
 		list_move(&mid_entry->qhead, &retry_list);
 	}
 	spin_unlock(&GlobalMid_Lock);
+	mutex_unlock(&server->srv_mutex);
 
 	cFYI(1, "%s: issuing mid callbacks", __func__);
 	list_for_each_safe(tmp, tmp2, &retry_list) {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/cifs/readdir.c linux-libre-3.2.77-gnu1/fs/cifs/readdir.c
--- linux-libre-3.2.76-gnu1/fs/cifs/readdir.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/cifs/readdir.c	2016-02-13 05:34:14.000000000 -0500
@@ -823,6 +823,7 @@ int cifs_readdir(struct file *file, void
 			}
 			/* if buggy server returns . and .. late do
 			we want to check for that here? */
+			*tmp_buf = 0;
 			rc = cifs_filldir(current_entry, file,
 					filldir, direntry, tmp_buf, max_len);
 			if (rc == -EOVERFLOW) {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/cifs/transport.c linux-libre-3.2.77-gnu1/fs/cifs/transport.c
--- linux-libre-3.2.76-gnu1/fs/cifs/transport.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/cifs/transport.c	2016-02-13 05:34:14.000000000 -0500
@@ -370,10 +370,8 @@ cifs_call_async(struct TCP_Server_Info *
 	spin_unlock(&GlobalMid_Lock);
 
 	rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
-	if (rc) {
-		mutex_unlock(&server->srv_mutex);
-		goto out_err;
-	}
+	if (rc)
+		goto out;
 
 	mid->receive = receive;
 	mid->callback = callback;
@@ -384,14 +382,15 @@ cifs_call_async(struct TCP_Server_Info *
 	rc = smb_sendv(server, iov, nvec);
 	cifs_in_send_dec(server);
 	cifs_save_when_sent(mid);
+out:
+	if (rc < 0)
+		delete_mid(mid);
+
 	mutex_unlock(&server->srv_mutex);
 
-	if (rc)
-		goto out_err;
+	if (rc == 0)
+		return 0;
 
-	return rc;
-out_err:
-	delete_mid(mid);
 	atomic_dec(&server->inFlight);
 	wake_up(&server->request_q);
 	return rc;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/hostfs/hostfs_kern.c linux-libre-3.2.77-gnu1/fs/hostfs/hostfs_kern.c
--- linux-libre-3.2.76-gnu1/fs/hostfs/hostfs_kern.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/hostfs/hostfs_kern.c	2016-02-13 05:34:14.000000000 -0500
@@ -720,15 +720,13 @@ int hostfs_mknod(struct inode *dir, stru
 
 	init_special_inode(inode, mode, dev);
 	err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
-	if (!err)
+	if (err)
 		goto out_free;
 
 	err = read_name(inode, name);
 	__putname(name);
 	if (err)
 		goto out_put;
-	if (err)
-		goto out_put;
 
 	d_instantiate(dentry, inode);
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/locks.c linux-libre-3.2.77-gnu1/fs/locks.c
--- linux-libre-3.2.76-gnu1/fs/locks.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/locks.c	2016-02-13 05:34:14.000000000 -0500
@@ -1863,7 +1863,6 @@ int fcntl_setlk(unsigned int fd, struct
 		goto out;
 	}
 
-again:
 	error = flock_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
@@ -1894,19 +1893,22 @@ again:
 	 * Attempt to detect a close/fcntl race and recover by
 	 * releasing the lock that was just acquired.
 	 */
-	/*
-	 * we need that spin_lock here - it prevents reordering between
-	 * update of inode->i_flock and check for it done in close().
-	 * rcu_read_lock() wouldn't do.
-	 */
-	spin_lock(&current->files->file_lock);
-	f = fcheck(fd);
-	spin_unlock(&current->files->file_lock);
-	if (!error && f != filp && flock.l_type != F_UNLCK) {
-		flock.l_type = F_UNLCK;
-		goto again;
+	if (!error && file_lock->fl_type != F_UNLCK) {
+		/*
+		 * We need that spin_lock here - it prevents reordering between
+		 * update of inode->i_flock and check for it done in
+		 * close(). rcu_read_lock() wouldn't do.
+		 */
+		spin_lock(&current->files->file_lock);
+		f = fcheck(fd);
+		spin_unlock(&current->files->file_lock);
+		if (f != filp) {
+			file_lock->fl_type = F_UNLCK;
+			error = do_lock_file_wait(filp, cmd, file_lock);
+			WARN_ON_ONCE(error);
+			error = -EBADF;
+		}
 	}
-
 out:
 	locks_free_lock(file_lock);
 	return error;
@@ -1981,7 +1983,6 @@ int fcntl_setlk64(unsigned int fd, struc
 		goto out;
 	}
 
-again:
 	error = flock64_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
@@ -2012,14 +2013,22 @@ again:
 	 * Attempt to detect a close/fcntl race and recover by
 	 * releasing the lock that was just acquired.
 	 */
-	spin_lock(&current->files->file_lock);
-	f = fcheck(fd);
-	spin_unlock(&current->files->file_lock);
-	if (!error && f != filp && flock.l_type != F_UNLCK) {
-		flock.l_type = F_UNLCK;
-		goto again;
+	if (!error && file_lock->fl_type != F_UNLCK) {
+		/*
+		 * We need that spin_lock here - it prevents reordering between
+		 * update of inode->i_flock and check for it done in
+		 * close(). rcu_read_lock() wouldn't do.
+		 */
+		spin_lock(&current->files->file_lock);
+		f = fcheck(fd);
+		spin_unlock(&current->files->file_lock);
+		if (f != filp) {
+			file_lock->fl_type = F_UNLCK;
+			error = do_lock_file_wait(filp, cmd, file_lock);
+			WARN_ON_ONCE(error);
+			error = -EBADF;
+		}
 	}
-
 out:
 	locks_free_lock(file_lock);
 	return error;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/nfs/inode.c linux-libre-3.2.77-gnu1/fs/nfs/inode.c
--- linux-libre-3.2.76-gnu1/fs/nfs/inode.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/nfs/inode.c	2016-02-13 05:34:14.000000000 -0500
@@ -1207,6 +1207,7 @@ static int nfs_update_inode(struct inode
 	unsigned long invalid = 0;
 	unsigned long now = jiffies;
 	unsigned long save_cache_validity;
+	bool cache_revalidated = true;
 
 	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
 			__func__, inode->i_sb->s_id, inode->i_ino,
@@ -1252,8 +1253,10 @@ static int nfs_update_inode(struct inode
 				nfs_force_lookup_revalidate(inode);
 			inode->i_version = fattr->change_attr;
 		}
-	} else if (server->caps & NFS_CAP_CHANGE_ATTR)
+	} else if (server->caps & NFS_CAP_CHANGE_ATTR) {
 		invalid |= save_cache_validity;
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
 		/* NFSv2/v3: Check if the mtime agrees */
@@ -1265,11 +1268,13 @@ static int nfs_update_inode(struct inode
 				nfs_force_lookup_revalidate(inode);
 			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
 		}
-	} else if (server->caps & NFS_CAP_MTIME)
+	} else if (server->caps & NFS_CAP_MTIME) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_DATA
 				| NFS_INO_REVAL_PAGECACHE
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
 		/* If ctime has changed we should definitely clear access+acl caches */
@@ -1284,11 +1289,13 @@ static int nfs_update_inode(struct inode
 			}
 			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
 		}
-	} else if (server->caps & NFS_CAP_CTIME)
+	} else if (server->caps & NFS_CAP_CTIME) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	/* Check if our cached file size is stale */
 	if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
@@ -1309,17 +1316,21 @@ static int nfs_update_inode(struct inode
 					(long long)cur_isize,
 					(long long)new_isize);
 		}
-	} else
+	} else {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_PAGECACHE
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 
 	if (fattr->valid & NFS_ATTR_FATTR_ATIME)
 		memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
-	else if (server->caps & NFS_CAP_ATIME)
+	else if (server->caps & NFS_CAP_ATIME) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATIME
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_MODE) {
 		if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
@@ -1328,33 +1339,39 @@ static int nfs_update_inode(struct inode
 			inode->i_mode = newmode;
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 		}
-	} else if (server->caps & NFS_CAP_MODE)
+	} else if (server->caps & NFS_CAP_MODE) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
 		if (inode->i_uid != fattr->uid) {
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 			inode->i_uid = fattr->uid;
 		}
-	} else if (server->caps & NFS_CAP_OWNER)
+	} else if (server->caps & NFS_CAP_OWNER) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
 		if (inode->i_gid != fattr->gid) {
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 			inode->i_gid = fattr->gid;
 		}
-	} else if (server->caps & NFS_CAP_OWNER_GROUP)
+	} else if (server->caps & NFS_CAP_OWNER_GROUP) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
 		if (inode->i_nlink != fattr->nlink) {
@@ -1363,18 +1380,21 @@ static int nfs_update_inode(struct inode
 				invalid |= NFS_INO_INVALID_DATA;
 			set_nlink(inode, fattr->nlink);
 		}
-	} else if (server->caps & NFS_CAP_NLINK)
+	} else if (server->caps & NFS_CAP_NLINK) {
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_FORCED);
+		cache_revalidated = false;
+	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
 		/*
 		 * report the blocks in 512byte units
 		 */
 		inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
- 	}
-	if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
+	} else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
 		inode->i_blocks = fattr->du.nfs2.blocks;
+	else
+		cache_revalidated = false;
 
 	/* Update attrtimeo value if we're out of the unstable period */
 	if (invalid & NFS_INO_INVALID_ATTR) {
@@ -1383,15 +1403,19 @@ static int nfs_update_inode(struct inode
 		nfsi->attrtimeo_timestamp = now;
 		nfsi->attr_gencount = nfs_inc_attr_generation_counter();
 	} else {
-		if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
-			if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
-				nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
+		if (cache_revalidated) {
+			if (!time_in_range_open(now, nfsi->attrtimeo_timestamp,
+				nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
+				nfsi->attrtimeo <<= 1;
+				if (nfsi->attrtimeo > NFS_MAXATTRTIMEO(inode))
+					nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
+			}
 			nfsi->attrtimeo_timestamp = now;
 		}
 	}
 
 	/* Don't declare attrcache up to date if there were no attrs! */
-	if (fattr->valid != 0)
+	if (cache_revalidated)
 		invalid &= ~NFS_INO_INVALID_ATTR;
 
 	/* Don't invalidate the data if we were to blame */
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/ocfs2/dlm/dlmmaster.c linux-libre-3.2.77-gnu1/fs/ocfs2/dlm/dlmmaster.c
--- linux-libre-3.2.76-gnu1/fs/ocfs2/dlm/dlmmaster.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/ocfs2/dlm/dlmmaster.c	2016-02-13 05:34:14.000000000 -0500
@@ -2459,6 +2459,11 @@ static int dlm_migrate_lockres(struct dl
 	spin_lock(&dlm->master_lock);
 	ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
 				    namelen, target, dlm->node_num);
+	/* get an extra reference on the mle.
+	 * otherwise the assert_master from the new
+	 * master will destroy this.
+	 */
+	dlm_get_mle_inuse(mle);
 	spin_unlock(&dlm->master_lock);
 	spin_unlock(&dlm->spinlock);
 
@@ -2494,6 +2499,7 @@ fail:
 		if (mle_added) {
 			dlm_mle_detach_hb_events(dlm, mle);
 			dlm_put_mle(mle);
+			dlm_put_mle_inuse(mle);
 		} else if (mle) {
 			kmem_cache_free(dlm_mle_cache, mle);
 			mle = NULL;
@@ -2511,17 +2517,6 @@ fail:
 	 * ensure that all assert_master work is flushed. */
 	flush_workqueue(dlm->dlm_worker);
 
-	/* get an extra reference on the mle.
-	 * otherwise the assert_master from the new
-	 * master will destroy this.
-	 * also, make sure that all callers of dlm_get_mle
-	 * take both dlm->spinlock and dlm->master_lock */
-	spin_lock(&dlm->spinlock);
-	spin_lock(&dlm->master_lock);
-	dlm_get_mle_inuse(mle);
-	spin_unlock(&dlm->master_lock);
-	spin_unlock(&dlm->spinlock);
-
 	/* notify new node and send all lock state */
 	/* call send_one_lockres with migration flag.
 	 * this serves as notice to the target node that a
@@ -3249,6 +3244,15 @@ top:
 			    mle->new_master != dead_node)
 				continue;
 
+			if (mle->new_master == dead_node && mle->inuse) {
+				mlog(ML_NOTICE, "%s: target %u died during "
+						"migration from %u, the MLE is "
+						"still keep used, ignore it!\n",
+						dlm->name, dead_node,
+						mle->master);
+				continue;
+			}
+
 			/* If we have reached this point, this mle needs to be
 			 * removed from the list and freed. */
 			dlm_clean_migration_mle(dlm, mle);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/ocfs2/dlmglue.c linux-libre-3.2.77-gnu1/fs/ocfs2/dlmglue.c
--- linux-libre-3.2.76-gnu1/fs/ocfs2/dlmglue.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/ocfs2/dlmglue.c	2016-02-13 05:34:14.000000000 -0500
@@ -1373,6 +1373,7 @@ static int __ocfs2_cluster_lock(struct o
 	unsigned long flags;
 	unsigned int gen;
 	int noqueue_attempted = 0;
+	int kick_dc = 0;
 
 	ocfs2_init_mask_waiter(&mw);
 
@@ -1501,7 +1502,12 @@ update_holders:
 unlock:
 	lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
 
+	/* ocfs2_unblock_lock reques on seeing OCFS2_LOCK_UPCONVERT_FINISHING */
+	kick_dc = (lockres->l_flags & OCFS2_LOCK_BLOCKED);
+
 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+	if (kick_dc)
+		ocfs2_wake_downconvert_thread(osb);
 out:
 	/*
 	 * This is helping work around a lock inversion between the page lock
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/udf/inode.c linux-libre-3.2.77-gnu1/fs/udf/inode.c
--- linux-libre-3.2.76-gnu1/fs/udf/inode.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/udf/inode.c	2016-02-13 05:34:14.000000000 -0500
@@ -1975,14 +1975,29 @@ void udf_write_aext(struct inode *inode,
 		epos->offset += adsize;
 }
 
+/*
+ * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
+ * someone does some weird stuff.
+ */
+#define UDF_MAX_INDIR_EXTS 16
+
 int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
 		     struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
 	int8_t etype;
+	unsigned int indirections = 0;
 
 	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
 	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
 		int block;
+
+		if (++indirections > UDF_MAX_INDIR_EXTS) {
+			udf_err(inode->i_sb,
+				"too many indirect extents in inode %lu\n",
+				inode->i_ino);
+			return -1;
+		}
+
 		epos->block = *eloc;
 		epos->offset = sizeof(struct allocExtDesc);
 		brelse(epos->bh);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/fs/udf/unicode.c linux-libre-3.2.77-gnu1/fs/udf/unicode.c
--- linux-libre-3.2.76-gnu1/fs/udf/unicode.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/fs/udf/unicode.c	2016-02-13 05:34:14.000000000 -0500
@@ -133,11 +133,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
 		if (c < 0x80U)
 			utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
 		else if (c < 0x800U) {
+			if (utf_o->u_len > (UDF_NAME_LEN - 4))
+				break;
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0xc0 | (c >> 6));
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0x80 | (c & 0x3f));
 		} else {
+			if (utf_o->u_len > (UDF_NAME_LEN - 5))
+				break;
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0xe0 | (c >> 12));
 			utf_o->u_name[utf_o->u_len++] =
@@ -178,17 +182,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
 static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
 {
 	unsigned c, i, max_val, utf_char;
-	int utf_cnt, u_len;
+	int utf_cnt, u_len, u_ch;
 
 	memset(ocu, 0, sizeof(dstring) * length);
 	ocu[0] = 8;
 	max_val = 0xffU;
+	u_ch = 1;
 
 try_again:
 	u_len = 0U;
 	utf_char = 0U;
 	utf_cnt = 0U;
 	for (i = 0U; i < utf->u_len; i++) {
+		/* Name didn't fit? */
+		if (u_len + 1 + u_ch >= length)
+			return 0;
+
 		c = (uint8_t)utf->u_name[i];
 
 		/* Complete a multi-byte UTF-8 character */
@@ -230,6 +239,7 @@ try_again:
 			if (max_val == 0xffU) {
 				max_val = 0xffffU;
 				ocu[0] = (uint8_t)0x10U;
+				u_ch = 2;
 				goto try_again;
 			}
 			goto error_out;
@@ -282,7 +292,7 @@ static int udf_CS0toNLS(struct nls_table
 			c = (c << 8) | ocu[i++];
 
 		len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
-				    UDF_NAME_LEN - utf_o->u_len);
+				    UDF_NAME_LEN - 2 - utf_o->u_len);
 		/* Valid character? */
 		if (len >= 0)
 			utf_o->u_len += len;
@@ -300,15 +310,19 @@ static int udf_NLStoCS0(struct nls_table
 	int len;
 	unsigned i, max_val;
 	uint16_t uni_char;
-	int u_len;
+	int u_len, u_ch;
 
 	memset(ocu, 0, sizeof(dstring) * length);
 	ocu[0] = 8;
 	max_val = 0xffU;
+	u_ch = 1;
 
 try_again:
 	u_len = 0U;
 	for (i = 0U; i < uni->u_len; i++) {
+		/* Name didn't fit? */
+		if (u_len + 1 + u_ch >= length)
+			return 0;
 		len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char);
 		if (!len)
 			continue;
@@ -321,6 +335,7 @@ try_again:
 		if (uni_char > max_val) {
 			max_val = 0xffffU;
 			ocu[0] = (uint8_t)0x10U;
+			u_ch = 2;
 			goto try_again;
 		}
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/include/crypto/hash.h linux-libre-3.2.77-gnu1/include/crypto/hash.h
--- linux-libre-3.2.76-gnu1/include/crypto/hash.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/include/crypto/hash.h	2016-02-13 05:34:14.000000000 -0500
@@ -94,6 +94,7 @@ struct crypto_ahash {
 		      unsigned int keylen);
 
 	unsigned int reqsize;
+	bool has_setkey;
 	struct crypto_tfm base;
 };
 
@@ -181,6 +182,11 @@ static inline void *ahash_request_ctx(st
 
 int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
 			unsigned int keylen);
+static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm)
+{
+	return tfm->has_setkey;
+}
+
 int crypto_ahash_finup(struct ahash_request *req);
 int crypto_ahash_final(struct ahash_request *req);
 int crypto_ahash_digest(struct ahash_request *req);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/include/crypto/if_alg.h linux-libre-3.2.77-gnu1/include/crypto/if_alg.h
--- linux-libre-3.2.76-gnu1/include/crypto/if_alg.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/include/crypto/if_alg.h	2016-02-13 05:34:14.000000000 -0500
@@ -30,6 +30,9 @@ struct alg_sock {
 
 	struct sock *parent;
 
+	unsigned int refcnt;
+	unsigned int nokey_refcnt;
+
 	const struct af_alg_type *type;
 	void *private;
 };
@@ -49,8 +52,10 @@ struct af_alg_type {
 	void (*release)(void *private);
 	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
 	int (*accept)(void *private, struct sock *sk);
+	int (*accept_nokey)(void *private, struct sock *sk);
 
 	struct proto_ops *ops;
+	struct proto_ops *ops_nokey;
 	struct module *owner;
 	char name[14];
 };
@@ -64,6 +69,7 @@ int af_alg_register_type(const struct af
 int af_alg_unregister_type(const struct af_alg_type *type);
 
 int af_alg_release(struct socket *sock);
+void af_alg_release_parent(struct sock *sk);
 int af_alg_accept(struct sock *sk, struct socket *newsock);
 
 int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
@@ -80,11 +86,6 @@ static inline struct alg_sock *alg_sk(st
 	return (struct alg_sock *)sk;
 }
 
-static inline void af_alg_release_parent(struct sock *sk)
-{
-	sock_put(alg_sk(sk)->parent);
-}
-
 static inline void af_alg_init_completion(struct af_alg_completion *completion)
 {
 	init_completion(&completion->completion);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/include/linux/crypto.h linux-libre-3.2.77-gnu1/include/linux/crypto.h
--- linux-libre-3.2.76-gnu1/include/linux/crypto.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/include/linux/crypto.h	2016-02-13 05:34:14.000000000 -0500
@@ -346,6 +346,7 @@ struct ablkcipher_tfm {
 
 	unsigned int ivsize;
 	unsigned int reqsize;
+	bool has_setkey;
 };
 
 struct aead_tfm {
@@ -656,6 +657,13 @@ static inline int crypto_ablkcipher_setk
 	return crt->setkey(crt->base, key, keylen);
 }
 
+static inline bool crypto_ablkcipher_has_setkey(struct crypto_ablkcipher *tfm)
+{
+	struct ablkcipher_tfm *crt = crypto_ablkcipher_crt(tfm);
+
+	return crt->has_setkey;
+}
+
 static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
 	struct ablkcipher_request *req)
 {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/include/linux/mtd/nand.h linux-libre-3.2.77-gnu1/include/linux/mtd/nand.h
--- linux-libre-3.2.76-gnu1/include/linux/mtd/nand.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/include/linux/mtd/nand.h	2016-02-13 05:34:14.000000000 -0500
@@ -283,7 +283,7 @@ struct nand_onfi_params {
 	__le16 t_r;
 	__le16 t_ccs;
 	__le16 src_sync_timing_mode;
-	__le16 src_ssync_features;
+	u8 src_ssync_features;
 	__le16 clk_pin_capacitance_typ;
 	__le16 io_pin_capacitance_typ;
 	__le16 input_pin_capacitance_typ;
@@ -291,7 +291,7 @@ struct nand_onfi_params {
 	u8 driver_strenght_support;
 	__le16 t_int_r;
 	__le16 t_ald;
-	u8 reserved4[7];
+	u8 reserved4[8];
 
 	/* vendor */
 	u8 reserved5[90];
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/include/linux/printk.h linux-libre-3.2.77-gnu1/include/linux/printk.h
--- linux-libre-3.2.76-gnu1/include/linux/printk.h	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/include/linux/printk.h	2016-02-13 05:34:14.000000000 -0500
@@ -80,13 +80,13 @@ struct va_format {
 
 /*
  * Dummy printk for disabled debugging statements to use whilst maintaining
- * gcc's format and side-effect checking.
+ * gcc's format checking.
  */
-static inline __printf(1, 2)
-int no_printk(const char *fmt, ...)
-{
-	return 0;
-}
+#define no_printk(fmt, ...)			\
+do {						\
+	if (0)					\
+		printk(fmt, ##__VA_ARGS__);	\
+} while (0)
 
 extern asmlinkage __printf(1, 2)
 void early_printk(const char *fmt, ...);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/kernel/futex.c linux-libre-3.2.77-gnu1/kernel/futex.c
--- linux-libre-3.2.76-gnu1/kernel/futex.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/kernel/futex.c	2016-02-13 05:34:14.000000000 -0500
@@ -2492,6 +2492,11 @@ static int futex_wait_requeue_pi(u32 __u
 		if (q.pi_state && (q.pi_state->owner != current)) {
 			spin_lock(q.lock_ptr);
 			ret = fixup_pi_state_owner(uaddr2, &q, current);
+			/*
+			 * Drop the reference to the pi state which
+			 * the requeue_pi() code acquired for us.
+			 */
+			free_pi_state(q.pi_state);
 			spin_unlock(q.lock_ptr);
 		}
 	} else {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/kernel/time/posix-clock.c linux-libre-3.2.77-gnu1/kernel/time/posix-clock.c
--- linux-libre-3.2.76-gnu1/kernel/time/posix-clock.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/kernel/time/posix-clock.c	2016-02-13 05:34:14.000000000 -0500
@@ -69,10 +69,10 @@ static ssize_t posix_clock_read(struct f
 static unsigned int posix_clock_poll(struct file *fp, poll_table *wait)
 {
 	struct posix_clock *clk = get_posix_clock(fp);
-	int result = 0;
+	unsigned int result = 0;
 
 	if (!clk)
-		return -ENODEV;
+		return POLLERR;
 
 	if (clk->ops.poll)
 		result = clk->ops.poll(clk, fp, wait);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/lib/dma-debug.c linux-libre-3.2.77-gnu1/lib/dma-debug.c
--- linux-libre-3.2.76-gnu1/lib/dma-debug.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/lib/dma-debug.c	2016-02-13 05:34:14.000000000 -0500
@@ -942,7 +942,7 @@ static inline bool overlap(void *addr, u
 
 static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
 {
-	if (overlap(addr, len, _text, _etext) ||
+	if (overlap(addr, len, _stext, _etext) ||
 	    overlap(addr, len, __start_rodata, __end_rodata))
 		err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);
 }
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/Makefile linux-libre-3.2.77-gnu1/Makefile
--- linux-libre-3.2.76-gnu1/Makefile	2016-01-23 22:35:58.000000000 -0500
+++ linux-libre-3.2.77-gnu1/Makefile	2016-02-13 23:16:39.000000000 -0500
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 76
+SUBLEVEL = 77
 EXTRAVERSION =-gnu1
 NAME = Saber-toothed Squirrel
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/mm/memcontrol.c linux-libre-3.2.77-gnu1/mm/memcontrol.c
--- linux-libre-3.2.76-gnu1/mm/memcontrol.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/mm/memcontrol.c	2016-02-13 05:34:14.000000000 -0500
@@ -4564,16 +4564,17 @@ static void mem_cgroup_usage_unregister_
 swap_buffers:
 	/* Swap primary and spare array */
 	thresholds->spare = thresholds->primary;
-	/* If all events are unregistered, free the spare array */
-	if (!new) {
-		kfree(thresholds->spare);
-		thresholds->spare = NULL;
-	}
 
 	rcu_assign_pointer(thresholds->primary, new);
 
 	/* To be sure that nobody uses thresholds */
 	synchronize_rcu();
+
+	/* If all events are unregistered, free the spare array */
+	if (!new) {
+		kfree(thresholds->spare);
+		thresholds->spare = NULL;
+	}
 unlock:
 	mutex_unlock(&memcg->thresholds_lock);
 }
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/net/ipv6/tcp_ipv6.c linux-libre-3.2.77-gnu1/net/ipv6/tcp_ipv6.c
--- linux-libre-3.2.76-gnu1/net/ipv6/tcp_ipv6.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/net/ipv6/tcp_ipv6.c	2016-02-13 05:34:14.000000000 -0500
@@ -513,8 +513,10 @@ static int tcp_v6_send_synack(struct soc
 		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 
 		ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
+		rcu_read_lock();
 		err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
 			       np->tclass);
+		rcu_read_unlock();
 		err = net_xmit_eval(err);
 	}
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/net/sctp/sm_sideeffect.c linux-libre-3.2.77-gnu1/net/sctp/sm_sideeffect.c
--- linux-libre-3.2.76-gnu1/net/sctp/sm_sideeffect.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/net/sctp/sm_sideeffect.c	2016-02-13 05:34:14.000000000 -0500
@@ -249,11 +249,12 @@ void sctp_generate_t3_rtx_event(unsigned
 	int error;
 	struct sctp_transport *transport = (struct sctp_transport *) peer;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 
 	/* Check whether a task is in the sock.  */
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -276,10 +277,10 @@ void sctp_generate_t3_rtx_event(unsigned
 			   transport, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_transport_put(transport);
 }
 
@@ -289,10 +290,11 @@ out_unlock:
 static void sctp_generate_timeout_event(struct sctp_association *asoc,
 					sctp_event_timeout_t timeout_type)
 {
+	struct sock *sk = asoc->base.sk;
 	int error = 0;
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy: timer %d\n",
 				  __func__,
 				  timeout_type);
@@ -316,10 +318,10 @@ static void sctp_generate_timeout_event(
 			   (void *)timeout_type, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_association_put(asoc);
 }
 
@@ -369,9 +371,10 @@ void sctp_generate_heartbeat_event(unsig
 	int error = 0;
 	struct sctp_transport *transport = (struct sctp_transport *) data;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -392,10 +395,10 @@ void sctp_generate_heartbeat_event(unsig
 			   transport, GFP_ATOMIC);
 
 	 if (error)
-		 asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_transport_put(transport);
 }
 
@@ -406,9 +409,10 @@ void sctp_generate_proto_unreach_event(u
 {
 	struct sctp_transport *transport = (struct sctp_transport *) data;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 	
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -429,7 +433,7 @@ void sctp_generate_proto_unreach_event(u
 		   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_association_put(asoc);
 }
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/scripts/bloat-o-meter linux-libre-3.2.77-gnu1/scripts/bloat-o-meter
--- linux-libre-3.2.76-gnu1/scripts/bloat-o-meter	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/scripts/bloat-o-meter	2016-02-13 05:34:14.000000000 -0500
@@ -55,8 +55,8 @@ for name in common:
 delta.sort()
 delta.reverse()
 
-print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
-      (add, remove, grow, shrink, up, -down, up-down)
-print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")
+print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
+      (add, remove, grow, shrink, up, -down, up-down))
+print("%-40s %7s %7s %+7s" % ("function", "old", "new", "delta"))
 for d, n in delta:
-    if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
+    if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/control.c linux-libre-3.2.77-gnu1/sound/core/control.c
--- linux-libre-3.2.76-gnu1/sound/core/control.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/control.c	2016-02-13 05:34:14.000000000 -0500
@@ -1321,6 +1321,8 @@ static int snd_ctl_tlv_ioctl(struct snd_
 		return -EFAULT;
 	if (tlv.length < sizeof(unsigned int) * 2)
 		return -EINVAL;
+	if (!tlv.numid)
+		return -EINVAL;
 	down_read(&card->controls_rwsem);
 	kctl = snd_ctl_find_numid(card, tlv.numid);
 	if (kctl == NULL) {
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/hrtimer.c linux-libre-3.2.77-gnu1/sound/core/hrtimer.c
--- linux-libre-3.2.76-gnu1/sound/core/hrtimer.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/hrtimer.c	2016-02-13 05:34:14.000000000 -0500
@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_
 	struct snd_hrtimer *stime = t->private_data;
 
 	atomic_set(&stime->running, 0);
-	hrtimer_cancel(&stime->hrt);
+	hrtimer_try_to_cancel(&stime->hrt);
 	hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
 		      HRTIMER_MODE_REL);
 	atomic_set(&stime->running, 1);
@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_t
 {
 	struct snd_hrtimer *stime = t->private_data;
 	atomic_set(&stime->running, 0);
+	hrtimer_try_to_cancel(&stime->hrt);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/pcm_compat.c linux-libre-3.2.77-gnu1/sound/core/pcm_compat.c
--- linux-libre-3.2.76-gnu1/sound/core/pcm_compat.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/pcm_compat.c	2016-02-13 05:34:14.000000000 -0500
@@ -235,10 +235,15 @@ static int snd_pcm_ioctl_hw_params_compa
 	if (! (runtime = substream->runtime))
 		return -ENOTTY;
 
-	/* only fifo_size is different, so just copy all */
-	data = memdup_user(data32, sizeof(*data32));
-	if (IS_ERR(data))
-		return PTR_ERR(data);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* only fifo_size (RO from userspace) is different, so just copy all */
+	if (copy_from_user(data, data32, sizeof(*data32))) {
+		err = -EFAULT;
+		goto error;
+	}
 
 	if (refine)
 		err = snd_pcm_hw_refine(substream, data);
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/seq/seq_clientmgr.c linux-libre-3.2.77-gnu1/sound/core/seq/seq_clientmgr.c
--- linux-libre-3.2.76-gnu1/sound/core/seq/seq_clientmgr.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/seq/seq_clientmgr.c	2016-02-13 05:34:14.000000000 -0500
@@ -1950,7 +1950,7 @@ static int snd_seq_ioctl_remove_events(s
 		 * No restrictions so for a user client we can clear
 		 * the whole fifo
 		 */
-		if (client->type == USER_CLIENT)
+		if (client->type == USER_CLIENT && client->data.user.fifo)
 			snd_seq_fifo_clear(client->data.user.fifo);
 	}
 
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/seq/seq_compat.c linux-libre-3.2.77-gnu1/sound/core/seq/seq_compat.c
--- linux-libre-3.2.76-gnu1/sound/core/seq/seq_compat.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/seq/seq_compat.c	2016-02-13 05:34:14.000000000 -0500
@@ -49,11 +49,12 @@ static int snd_seq_call_port_info_ioctl(
 	struct snd_seq_port_info *data;
 	mm_segment_t fs;
 
-	data = memdup_user(data32, sizeof(*data32));
-	if (IS_ERR(data))
-		return PTR_ERR(data);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	if (get_user(data->flags, &data32->flags) ||
+	if (copy_from_user(data, data32, sizeof(*data32)) ||
+	    get_user(data->flags, &data32->flags) ||
 	    get_user(data->time_queue, &data32->time_queue))
 		goto error;
 	data->kernel = NULL;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/seq/seq_queue.c linux-libre-3.2.77-gnu1/sound/core/seq/seq_queue.c
--- linux-libre-3.2.76-gnu1/sound/core/seq/seq_queue.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/seq/seq_queue.c	2016-02-13 05:34:14.000000000 -0500
@@ -144,8 +144,10 @@ static struct snd_seq_queue *queue_new(i
 static void queue_delete(struct snd_seq_queue *q)
 {
 	/* stop and release the timer */
+	mutex_lock(&q->timer_mutex);
 	snd_seq_timer_stop(q->timer);
 	snd_seq_timer_close(q);
+	mutex_unlock(&q->timer_mutex);
 	/* wait until access free */
 	snd_use_lock_sync(&q->use_lock);
 	/* release resources... */
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/core/timer.c linux-libre-3.2.77-gnu1/sound/core/timer.c
--- linux-libre-3.2.76-gnu1/sound/core/timer.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/core/timer.c	2016-02-13 05:34:14.000000000 -0500
@@ -72,7 +72,7 @@ struct snd_timer_user {
 	struct timespec tstamp;		/* trigger tstamp */
 	wait_queue_head_t qchange_sleep;
 	struct fasync_struct *fasync;
-	struct mutex tread_sem;
+	struct mutex ioctl_lock;
 };
 
 /* list of timers */
@@ -214,11 +214,13 @@ static void snd_timer_check_master(struc
 		    slave->slave_id == master->slave_id) {
 			list_move_tail(&slave->open_list, &master->slave_list_head);
 			spin_lock_irq(&slave_active_lock);
+			spin_lock(&master->timer->lock);
 			slave->master = master;
 			slave->timer = master->timer;
 			if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
 				list_add_tail(&slave->active_list,
 					      &master->slave_active_head);
+			spin_unlock(&master->timer->lock);
 			spin_unlock_irq(&slave_active_lock);
 		}
 	}
@@ -344,15 +346,18 @@ int snd_timer_close(struct snd_timer_ins
 		    timer->hw.close)
 			timer->hw.close(timer);
 		/* remove slave links */
+		spin_lock_irq(&slave_active_lock);
+		spin_lock(&timer->lock);
 		list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
 					 open_list) {
-			spin_lock_irq(&slave_active_lock);
-			_snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
 			list_move_tail(&slave->open_list, &snd_timer_slave_list);
 			slave->master = NULL;
 			slave->timer = NULL;
-			spin_unlock_irq(&slave_active_lock);
+			list_del_init(&slave->ack_list);
+			list_del_init(&slave->active_list);
 		}
+		spin_unlock(&timer->lock);
+		spin_unlock_irq(&slave_active_lock);
 		mutex_unlock(&register_mutex);
 	}
  out:
@@ -439,9 +444,12 @@ static int snd_timer_start_slave(struct
 
 	spin_lock_irqsave(&slave_active_lock, flags);
 	timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
-	if (timeri->master)
+	if (timeri->master && timeri->timer) {
+		spin_lock(&timeri->timer->lock);
 		list_add_tail(&timeri->active_list,
 			      &timeri->master->slave_active_head);
+		spin_unlock(&timeri->timer->lock);
+	}
 	spin_unlock_irqrestore(&slave_active_lock, flags);
 	return 1; /* delayed start */
 }
@@ -487,6 +495,8 @@ static int _snd_timer_stop(struct snd_ti
 		if (!keep_flag) {
 			spin_lock_irqsave(&slave_active_lock, flags);
 			timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+			list_del_init(&timeri->ack_list);
+			list_del_init(&timeri->active_list);
 			spin_unlock_irqrestore(&slave_active_lock, flags);
 		}
 		goto __end;
@@ -692,7 +702,7 @@ void snd_timer_interrupt(struct snd_time
 		} else {
 			ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
 			if (--timer->running)
-				list_del(&ti->active_list);
+				list_del_init(&ti->active_list);
 		}
 		if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
 		    (ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1255,7 +1265,7 @@ static int snd_timer_user_open(struct in
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
 	init_waitqueue_head(&tu->qchange_sleep);
-	mutex_init(&tu->tread_sem);
+	mutex_init(&tu->ioctl_lock);
 	tu->ticks = 1;
 	tu->queue_size = 128;
 	tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
@@ -1275,8 +1285,10 @@ static int snd_timer_user_release(struct
 	if (file->private_data) {
 		tu = file->private_data;
 		file->private_data = NULL;
+		mutex_lock(&tu->ioctl_lock);
 		if (tu->timeri)
 			snd_timer_close(tu->timeri);
+		mutex_unlock(&tu->ioctl_lock);
 		kfree(tu->queue);
 		kfree(tu->tqueue);
 		kfree(tu);
@@ -1514,7 +1526,6 @@ static int snd_timer_user_tselect(struct
 	int err = 0;
 
 	tu = file->private_data;
-	mutex_lock(&tu->tread_sem);
 	if (tu->timeri) {
 		snd_timer_close(tu->timeri);
 		tu->timeri = NULL;
@@ -1558,7 +1569,6 @@ static int snd_timer_user_tselect(struct
 	}
 
       __err:
-      	mutex_unlock(&tu->tread_sem);
 	return err;
 }
 
@@ -1771,7 +1781,7 @@ enum {
 	SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
 };
 
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long arg)
 {
 	struct snd_timer_user *tu;
@@ -1788,17 +1798,11 @@ static long snd_timer_user_ioctl(struct
 	{
 		int xarg;
 
-		mutex_lock(&tu->tread_sem);
-		if (tu->timeri)	{	/* too late */
-			mutex_unlock(&tu->tread_sem);
+		if (tu->timeri)	/* too late */
 			return -EBUSY;
-		}
-		if (get_user(xarg, p)) {
-			mutex_unlock(&tu->tread_sem);
+		if (get_user(xarg, p))
 			return -EFAULT;
-		}
 		tu->tread = xarg ? 1 : 0;
-		mutex_unlock(&tu->tread_sem);
 		return 0;
 	}
 	case SNDRV_TIMER_IOCTL_GINFO:
@@ -1831,6 +1835,18 @@ static long snd_timer_user_ioctl(struct
 	return -ENOTTY;
 }
 
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct snd_timer_user *tu = file->private_data;
+	long ret;
+
+	mutex_lock(&tu->ioctl_lock);
+	ret = __snd_timer_user_ioctl(file, cmd, arg);
+	mutex_unlock(&tu->ioctl_lock);
+	return ret;
+}
+
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
 {
 	struct snd_timer_user *tu;
diff -druNp --no-dereference linux-libre-3.2.76-gnu1/sound/pci/fm801.c linux-libre-3.2.77-gnu1/sound/pci/fm801.c
--- linux-libre-3.2.76-gnu1/sound/pci/fm801.c	2016-01-22 16:40:13.000000000 -0500
+++ linux-libre-3.2.77-gnu1/sound/pci/fm801.c	2016-02-13 05:34:14.000000000 -0500
@@ -1244,6 +1244,8 @@ static int __devinit snd_fm801_create(st
 			return -ENODEV;
 		}
 	} else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
+		unsigned int tuner_only = tea575x_tuner & TUNER_ONLY;
+
 		/* autodetect tuner connection */
 		for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {
 			chip->tea575x_tuner = tea575x_tuner;
@@ -1257,6 +1259,8 @@ static int __devinit snd_fm801_create(st
 			snd_printk(KERN_ERR "TEA575x radio not found\n");
 			chip->tea575x_tuner = TUNER_DISABLED;
 		}
+
+		chip->tea575x_tuner |= tuner_only;
 	}
 	if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
 		strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
