diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/Makefile linux-libre-2.6.38.8-gnu/arch/arm/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/boot/compressed/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -59,7 +59,7 @@
 ZBSSADDR	:= $(CONFIG_ZBOOT_ROM_BSS)
 else
 ZTEXTADDR	:= 0
-ZBSSADDR	:= ALIGN(4)
+ZBSSADDR	:= ALIGN(8)
 endif
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/vmlinux.lds.in linux-libre-2.6.38.8-gnu/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2011-06-02 21:35:11.000000000 -0400
@@ -57,6 +57,7 @@
   .bss			: { *(.bss) }
   _end = .;
 
+  . = ALIGN(8);		/* the stack must be 64-bit aligned */
   .stack		: { *(.stack) }
 
   .stab 0		: { *(.stab) }
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/hw_breakpoint.c linux-libre-2.6.38.8-gnu/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/hw_breakpoint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/kernel/hw_breakpoint.c	2011-06-02 21:35:11.000000000 -0400
@@ -868,6 +868,13 @@
 		 */
 		asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
 		isb();
+
+		/*
+		 * Clear any configured vector-catch events before
+		 * enabling monitor mode.
+		 */
+		asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+		isb();
 	}
 
 	if (enable_monitor_mode())
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/sys_oabi-compat.c linux-libre-2.6.38.8-gnu/arch/arm/kernel/sys_oabi-compat.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/sys_oabi-compat.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/kernel/sys_oabi-compat.c	2011-06-02 21:35:11.000000000 -0400
@@ -311,7 +311,7 @@
 	long err;
 	int i;
 
-	if (nsops < 1)
+	if (nsops < 1 || nsops > SEMOPM)
 		return -EINVAL;
 	sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
 	if (!sops)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-dm644x-evm.c linux-libre-2.6.38.8-gnu/arch/arm/mach-davinci/board-dm644x-evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2011-06-02 21:35:11.000000000 -0400
@@ -440,11 +440,6 @@
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_direction_output(gpio + 7, 1);
 
-	/* irlml6401 switches over 1A, in under 8 msec;
-	 * now it can be managed by nDRV_VBUS ...
-	 */
-	davinci_setup_usb(1000, 8);
-
 	return 0;
 }
 
@@ -705,6 +700,9 @@
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
+	/* irlml6401 switches over 1A, in under 8 msec */
+	davinci_setup_usb(1000, 8);
+
 	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-mini2440.c linux-libre-2.6.38.8-gnu/arch/arm/mach-s3c2440/mach-mini2440.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2011-06-02 21:35:11.000000000 -0400
@@ -506,6 +506,11 @@
 	},
 };
 
+static struct platform_device uda1340_codec = {
+		.name = "uda134x-codec",
+		.id = -1,
+};
+
 static struct platform_device *mini2440_devices[] __initdata = {
 	&s3c_device_ohci,
 	&s3c_device_wdt,
@@ -521,7 +526,9 @@
 	&s3c_device_nand,
 	&s3c_device_sdi,
 	&s3c_device_iis,
+	&uda1340_codec,
 	&mini2440_audio,
+	&samsung_asoc_dma,
 };
 
 static void __init mini2440_map_io(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-v6.S linux-libre-2.6.38.8-gnu/arch/arm/mm/cache-v6.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-v6.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/mm/cache-v6.S	2011-06-02 21:35:11.000000000 -0400
@@ -176,6 +176,7 @@
  */
 ENTRY(v6_flush_kern_dcache_area)
 	add	r1, r0, r1
+	bic	r0, r0, #D_CACHE_LINE_SIZE - 1
 1:
 #ifdef HARVARD_CACHE
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-v7.S linux-libre-2.6.38.8-gnu/arch/arm/mm/cache-v7.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-v7.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/arm/mm/cache-v7.S	2011-06-02 21:35:11.000000000 -0400
@@ -221,6 +221,8 @@
 ENTRY(v7_flush_kern_dcache_area)
 	dcache_line_size r2, r3
 	add	r1, r0, r1
+	sub	r3, r2, #1
+	bic	r0, r0, r3
 1:
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
 	add	r0, r0, r2
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/mca.c linux-libre-2.6.38.8-gnu/arch/ia64/kernel/mca.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/mca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/ia64/kernel/mca.c	2011-06-02 21:35:11.000000000 -0400
@@ -1859,7 +1859,8 @@
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = __get_free_pages(GFP_KERNEL, get_order(sz));
+			data = (void *)__get_free_pages(GFP_KERNEL,
+							get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
 					cpu);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/pci/tioca_provider.c linux-libre-2.6.38.8-gnu/arch/ia64/sn/pci/tioca_provider.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/pci/tioca_provider.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/ia64/sn/pci/tioca_provider.c	2011-06-02 21:35:11.000000000 -0400
@@ -509,7 +509,7 @@
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/motorola.c linux-libre-2.6.38.8-gnu/arch/m68k/mm/motorola.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/motorola.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/m68k/mm/motorola.c	2011-06-02 21:35:11.000000000 -0400
@@ -300,6 +300,8 @@
 		zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
 		free_area_init_node(i, zones_size,
 				    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+		if (node_present_pages(i))
+			node_set_state(i, N_NORMAL_MEMORY);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/uaccess.h linux-libre-2.6.38.8-gnu/arch/microblaze/include/asm/uaccess.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/microblaze/include/asm/uaccess.h	2011-06-02 21:35:11.000000000 -0400
@@ -120,16 +120,16 @@
 {
 	/* normal memset with two words to __ex_table */
 	__asm__ __volatile__ (				\
-			"1:	sb	r0, %2, r0;"	\
+			"1:	sb	r0, %1, r0;"	\
 			"	addik	%0, %0, -1;"	\
 			"	bneid	%0, 1b;"	\
-			"	addik	%2, %2, 1;"	\
+			"	addik	%1, %1, 1;"	\
 			"2:			"	\
 			__EX_TABLE_SECTION		\
 			".word	1b,2b;"			\
 			".previous;"			\
-		: "=r"(n)				\
-		: "0"(n), "r"(to)
+		: "=r"(n), "=r"(to)			\
+		: "0"(n), "1"(to)
 	);
 	return n;
 }
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/unistd.h linux-libre-2.6.38.8-gnu/arch/parisc/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/parisc/include/asm/unistd.h	2011-06-02 21:35:11.000000000 -0400
@@ -814,8 +814,11 @@
 #define __NR_recvmmsg		(__NR_Linux + 319)
 #define __NR_accept4		(__NR_Linux + 320)
 #define __NR_prlimit64		(__NR_Linux + 321)
+#define __NR_fanotify_init	(__NR_Linux + 322)
+#define __NR_fanotify_mark	(__NR_Linux + 323)
+#define __NR_clock_adjtime	(__NR_Linux + 324)
 
-#define __NR_Linux_syscalls	(__NR_prlimit64 + 1)
+#define __NR_Linux_syscalls	(__NR_clock_adjtime + 1)
 
 
 #define __IGNORE_select		/* newselect */
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/irq.c linux-libre-2.6.38.8-gnu/arch/parisc/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/parisc/kernel/irq.c	2011-06-02 21:35:11.000000000 -0400
@@ -108,7 +108,7 @@
 	int cpu_dest;
 
 	/* timer and ipi have to always be received on all CPUs */
-	if (CHECK_IRQ_PER_CPU(irq)) {
+	if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
 		cpumask_setall(irq_desc[irq].affinity);
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall_table.S linux-libre-2.6.38.8-gnu/arch/parisc/kernel/syscall_table.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall_table.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/parisc/kernel/syscall_table.S	2011-06-02 21:35:11.000000000 -0400
@@ -420,6 +420,9 @@
 	ENTRY_COMP(recvmmsg)
 	ENTRY_SAME(accept4)		/* 320 */
 	ENTRY_SAME(prlimit64)
+	ENTRY_SAME(fanotify_init)
+	ENTRY_COMP(fanotify_mark)
+	ENTRY_COMP(clock_adjtime)
 
 	/* Nothing yet */
 
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/sys_parisc32.c linux-libre-2.6.38.8-gnu/arch/parisc/kernel/sys_parisc32.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/sys_parisc32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/parisc/kernel/sys_parisc32.c	2011-06-02 21:35:11.000000000 -0400
@@ -228,3 +228,11 @@
         return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
                              ((loff_t)lenhi << 32) | lenlo);
 }
+
+asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi,
+					 u32 mask_lo, int fd,
+					 const char __user *pathname)
+{
+	return sys_fanotify_mark(fan_fd, flags, ((u64)mask_hi << 32) | mask_lo,
+				 fd, pathname);
+}
diff -druN linux-libre-2.6.38-gnu/arch/parisc/mm/init.c linux-libre-2.6.38.8-gnu/arch/parisc/mm/init.c
--- linux-libre-2.6.38-gnu/arch/parisc/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/parisc/mm/init.c	2011-06-02 21:35:11.000000000 -0400
@@ -266,8 +266,10 @@
 	}
 	memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
-	for (i = 0; i < npmem_ranges; i++)
+	for (i = 0; i < npmem_ranges; i++) {
+		node_set_state(i, N_NORMAL_MEMORY);
 		node_set_online(i);
+	}
 #endif
 
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg.h linux-libre-2.6.38.8-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/include/asm/reg.h	2011-06-02 21:35:11.000000000 -0400
@@ -880,6 +880,7 @@
 #define PV_970		0x0039
 #define PV_POWER5	0x003A
 #define PV_POWER5p	0x003B
+#define PV_POWER7	0x003F
 #define PV_970FX	0x003C
 #define PV_630		0x0040
 #define PV_630p	0x0041
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/crash.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/crash.c	2011-06-02 21:35:11.000000000 -0400
@@ -170,7 +170,7 @@
 	int i;
 
 	msecs = 10000;
-	for (i=0; i < NR_CPUS && msecs > 0; i++) {
+	for (i=0; i < nr_cpu_ids && msecs > 0; i++) {
 		if (i == cpu)
 			continue;
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/misc_64.S linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/misc_64.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/misc_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/misc_64.S	2011-06-02 21:35:11.000000000 -0400
@@ -462,7 +462,8 @@
  * wait for the flag to change, indicating this kernel is going away but
  * the slave code for the next one is at addresses 0 to 100.
  *
- * This is used by all slaves.
+ * This is used by all slaves, even those that did not find a matching
+ * paca in the secondary startup code.
  *
  * Physical (hardware) cpu id should be in r3.
  */
@@ -471,10 +472,6 @@
 1:	mflr	r5
 	addi	r5,r5,kexec_flag-1b
 
-	li	r4,KEXEC_STATE_REAL_MODE
-	stb	r4,PACAKEXECSTATE(r13)
-	SYNC
-
 99:	HMT_LOW
 #ifdef CONFIG_KEXEC		/* use no memory without kexec */
 	lwz	r4,0(r5)
@@ -499,11 +496,17 @@
  *
  * get phys id from paca
  * switch to real mode
+ * mark the paca as no longer used
  * join other cpus in kexec_wait(phys_id)
  */
 _GLOBAL(kexec_smp_wait)
 	lhz	r3,PACAHWCPUID(r13)
 	bl	real_mode
+
+	li	r4,KEXEC_STATE_REAL_MODE
+	stb	r4,PACAKEXECSTATE(r13)
+	SYNC
+
 	b	.kexec_wait
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/paca.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/paca.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/paca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/paca.c	2011-06-02 21:35:11.000000000 -0400
@@ -203,7 +203,7 @@
 {
 	int new_size;
 
-	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus());
+	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
 
 	if (new_size >= paca_size)
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/perf_event.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/perf_event.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/perf_event.c	2011-06-02 21:35:11.000000000 -0400
@@ -398,6 +398,25 @@
 	return 0;
 }
 
+static u64 check_and_compute_delta(u64 prev, u64 val)
+{
+	u64 delta = (val - prev) & 0xfffffffful;
+
+	/*
+	 * POWER7 can roll back counter values, if the new value is smaller
+	 * than the previous value it will cause the delta and the counter to
+	 * have bogus values unless we rolled a counter over.  If a coutner is
+	 * rolled back, it will be smaller, but within 256, which is the maximum
+	 * number of events to rollback at once.  If we dectect a rollback
+	 * return 0.  This can lead to a small lack of precision in the
+	 * counters.
+	 */
+	if (prev > val && (prev - val) < 256)
+		delta = 0;
+
+	return delta;
+}
+
 static void power_pmu_read(struct perf_event *event)
 {
 	s64 val, delta, prev;
@@ -416,10 +435,11 @@
 		prev = local64_read(&event->hw.prev_count);
 		barrier();
 		val = read_pmc(event->hw.idx);
+		delta = check_and_compute_delta(prev, val);
+		if (!delta)
+			return;
 	} while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
 
-	/* The counters are only 32 bits wide */
-	delta = (val - prev) & 0xfffffffful;
 	local64_add(delta, &event->count);
 	local64_sub(delta, &event->hw.period_left);
 }
@@ -449,8 +469,9 @@
 		val = (event->hw.idx == 5) ? pmc5 : pmc6;
 		prev = local64_read(&event->hw.prev_count);
 		event->hw.idx = 0;
-		delta = (val - prev) & 0xfffffffful;
-		local64_add(delta, &event->count);
+		delta = check_and_compute_delta(prev, val);
+		if (delta)
+			local64_add(delta, &event->count);
 	}
 }
 
@@ -458,14 +479,16 @@
 				  unsigned long pmc5, unsigned long pmc6)
 {
 	struct perf_event *event;
-	u64 val;
+	u64 val, prev;
 	int i;
 
 	for (i = 0; i < cpuhw->n_limited; ++i) {
 		event = cpuhw->limited_counter[i];
 		event->hw.idx = cpuhw->limited_hwidx[i];
 		val = (event->hw.idx == 5) ? pmc5 : pmc6;
-		local64_set(&event->hw.prev_count, val);
+		prev = local64_read(&event->hw.prev_count);
+		if (check_and_compute_delta(prev, val))
+			local64_set(&event->hw.prev_count, val);
 		perf_event_update_userpage(event);
 	}
 }
@@ -1197,7 +1220,7 @@
 
 	/* we don't have to worry about interrupts here */
 	prev = local64_read(&event->hw.prev_count);
-	delta = (val - prev) & 0xfffffffful;
+	delta = check_and_compute_delta(prev, val);
 	local64_add(delta, &event->count);
 
 	/*
@@ -1269,6 +1292,28 @@
 	return ip;
 }
 
+static bool pmc_overflow(unsigned long val)
+{
+	if ((int)val < 0)
+		return true;
+
+	/*
+	 * Events on POWER7 can roll back if a speculative event doesn't
+	 * eventually complete. Unfortunately in some rare cases they will
+	 * raise a performance monitor exception. We need to catch this to
+	 * ensure we reset the PMC. In all cases the PMC will be 256 or less
+	 * cycles from overflow.
+	 *
+	 * We only do this if the first pass fails to find any overflowing
+	 * PMCs because a user might set a period of less than 256 and we
+	 * don't want to mistakenly reset them.
+	 */
+	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+		return true;
+
+	return false;
+}
+
 /*
  * Performance monitor interrupt stuff
  */
@@ -1316,7 +1361,7 @@
 			if (is_limited_pmc(i + 1))
 				continue;
 			val = read_pmc(i + 1);
-			if ((int)val < 0)
+			if (pmc_overflow(val))
 				write_pmc(i + 1, 0);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/ptrace.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/ptrace.c	2011-06-02 21:35:11.000000000 -0400
@@ -924,12 +924,16 @@
 	if (data && !(data & DABR_TRANSLATION))
 		return -EIO;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
+	if (ptrace_get_breakpoints(task) < 0)
+		return -ESRCH;
+
 	bp = thread->ptrace_bps[0];
 	if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
 		if (bp) {
 			unregister_hw_breakpoint(bp);
 			thread->ptrace_bps[0] = NULL;
 		}
+		ptrace_put_breakpoints(task);
 		return 0;
 	}
 	if (bp) {
@@ -939,9 +943,12 @@
 					(DABR_DATA_WRITE | DABR_DATA_READ),
 							&attr.bp_type);
 		ret =  modify_user_hw_breakpoint(bp, &attr);
-		if (ret)
+		if (ret) {
+			ptrace_put_breakpoints(task);
 			return ret;
+		}
 		thread->ptrace_bps[0] = bp;
+		ptrace_put_breakpoints(task);
 		thread->dabr = data;
 		return 0;
 	}
@@ -956,9 +963,12 @@
 							ptrace_triggered, task);
 	if (IS_ERR(bp)) {
 		thread->ptrace_bps[0] = NULL;
+		ptrace_put_breakpoints(task);
 		return PTR_ERR(bp);
 	}
 
+	ptrace_put_breakpoints(task);
+
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
 	/* Move contents to the DABR register */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/setup-common.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/setup-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/setup-common.c	2011-06-02 21:35:11.000000000 -0400
@@ -509,6 +509,9 @@
 	 */
 	cpu_init_thread_core_maps(nthreads);
 
+	/* Now that possible cpus are set, set nr_cpu_ids for later use */
+	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
+
 	free_unused_pacas();
 }
 #endif /* CONFIG_SMP */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/time.c linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/kernel/time.c	2011-06-02 21:35:11.000000000 -0400
@@ -229,6 +229,9 @@
 	u64 stolen = 0;
 	u64 dtb;
 
+	if (!dtl)
+		return 0;
+
 	if (i == vpa->dtl_idx)
 		return 0;
 	while (i < vpa->dtl_idx) {
@@ -356,7 +359,7 @@
 	}
 	get_paca()->user_time_scaled += user_scaled;
 
-	if (in_irq() || idle_task(smp_processor_id()) != tsk) {
+	if (in_interrupt() || idle_task(smp_processor_id()) != tsk) {
 		account_system_time(tsk, 0, delta, sys_scaled);
 		if (stolen)
 			account_steal_time(stolen);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_power4.c linux-libre-2.6.38.8-gnu/arch/powerpc/oprofile/op_model_power4.c
--- linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_power4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/powerpc/oprofile/op_model_power4.c	2011-06-02 21:35:11.000000000 -0400
@@ -261,6 +261,28 @@
 	return is_kernel;
 }
 
+static bool pmc_overflow(unsigned long val)
+{
+	if ((int)val < 0)
+		return true;
+
+	/*
+	 * Events on POWER7 can roll back if a speculative event doesn't
+	 * eventually complete. Unfortunately in some rare cases they will
+	 * raise a performance monitor exception. We need to catch this to
+	 * ensure we reset the PMC. In all cases the PMC will be 256 or less
+	 * cycles from overflow.
+	 *
+	 * We only do this if the first pass fails to find any overflowing
+	 * PMCs because a user might set a period of less than 256 and we
+	 * don't want to mistakenly reset them.
+	 */
+	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+		return true;
+
+	return false;
+}
+
 static void power4_handle_interrupt(struct pt_regs *regs,
 				    struct op_counter_config *ctr)
 {
@@ -281,7 +303,7 @@
 
 	for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
 		val = classic_ctr_read(i);
-		if (val < 0) {
+		if (pmc_overflow(val)) {
 			if (oprofile_running && ctr[i].enabled) {
 				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				classic_ctr_write(i, reset_value[i]);
diff -druN linux-libre-2.6.38-gnu/arch/s390/kvm/sie64a.S linux-libre-2.6.38.8-gnu/arch/s390/kvm/sie64a.S
--- linux-libre-2.6.38-gnu/arch/s390/kvm/sie64a.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/s390/kvm/sie64a.S	2011-06-02 21:35:11.000000000 -0400
@@ -48,10 +48,10 @@
 	tm	__TI_flags+7(%r2),_TIF_EXIT_SIE
 	jz	0f
 	larl	%r2,sie_exit			# work pending, leave sie
-	stg	%r2,__LC_RETURN_PSW+8
+	stg	%r2,SPI_PSW+8(0,%r15)
 	br	%r14
 0:	larl	%r2,sie_reenter			# re-enter with guest id
-	stg	%r2,__LC_RETURN_PSW+8
+	stg	%r2,SPI_PSW+8(0,%r15)
 1:	br	%r14
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/s390/mm/fault.c linux-libre-2.6.38.8-gnu/arch/s390/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/s390/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/s390/mm/fault.c	2011-06-02 21:35:11.000000000 -0400
@@ -558,9 +558,9 @@
 	 * Get the token (= address of the task structure of the affected task).
 	 */
 #ifdef CONFIG_64BIT
-	tsk = *(struct task_struct **) param64;
+	tsk = (struct task_struct *) param64;
 #else
-	tsk = *(struct task_struct **) param32;
+	tsk = (struct task_struct *) param32;
 #endif
 
 	if (subcode & 0x0080) {
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/Makefile linux-libre-2.6.38.8-gnu/arch/sh/kernel/cpu/Makefile
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sh/kernel/cpu/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -17,7 +17,5 @@
 
 obj-$(CONFIG_SH_ADC)		+= adc.o
 obj-$(CONFIG_SH_CLK_CPG_LEGACY)	+= clock-cpg.o
-obj-$(CONFIG_SH_FPU)		+= fpu.o
-obj-$(CONFIG_SH_FPU_EMU)	+= fpu.o
 
-obj-y	+= irq/ init.o clock.o hwblk.o proc.o
+obj-y	+= irq/ init.o clock.o fpu.o hwblk.o proc.o
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_32.c linux-libre-2.6.38.8-gnu/arch/sh/kernel/ptrace_32.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sh/kernel/ptrace_32.c	2011-06-02 21:35:11.000000000 -0400
@@ -101,6 +101,8 @@
 
 		attr = bp->attr;
 		attr.bp_addr = addr;
+		/* reenable breakpoint */
+		attr.disabled = false;
 		err = modify_user_hw_breakpoint(bp, &attr);
 		if (unlikely(err))
 			return err;
@@ -392,6 +394,9 @@
 					tmp = 0;
 			} else {
 				unsigned long index;
+				ret = init_fpu(child);
+				if (ret)
+					break;
 				index = addr - offsetof(struct user, fpu);
 				tmp = ((unsigned long *)child->thread.xstate)
 					[index >> 2];
@@ -423,6 +428,9 @@
 		else if (addr >= offsetof(struct user, fpu) &&
 			 addr < offsetof(struct user, u_fpvalid)) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			set_stopped_child_used_math(child);
 			((unsigned long *)child->thread.xstate)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_64.c linux-libre-2.6.38.8-gnu/arch/sh/kernel/ptrace_64.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sh/kernel/ptrace_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -403,6 +403,9 @@
 		else if ((addr >= offsetof(struct user, fpu)) &&
 			 (addr <  offsetof(struct user, u_fpvalid))) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			tmp = get_fpu_long(child, index);
 		} else if (addr == offsetof(struct user, u_fpvalid)) {
@@ -442,6 +445,9 @@
 		else if ((addr >= offsetof(struct user, fpu)) &&
 			 (addr <  offsetof(struct user, u_fpvalid))) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			ret = put_fpu_long(child, index, data);
 		}
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.S linux-libre-2.6.38.8-gnu/arch/sparc/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/entry.S	2011-06-02 21:35:11.000000000 -0400
@@ -1283,7 +1283,7 @@
 	.globl	ret_from_fork
 ret_from_fork:
 	call	schedule_tail
-	 mov	%g3, %o0
+	 ld	[%g3 + TI_TASK], %o0
 	b	ret_sys_call
 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/iommu.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/iommu.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/iommu.c	2011-06-02 21:35:11.000000000 -0400
@@ -333,13 +333,10 @@
 				 void *cpu, dma_addr_t dvma)
 {
 	struct iommu *iommu;
-	iopte_t *iopte;
 	unsigned long flags, order, npages;
 
 	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
 	iommu = dev->archdata.iommu;
-	iopte = iommu->page_table +
-		((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ldc.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/ldc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ldc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/ldc.c	2011-06-02 21:35:11.000000000 -0400
@@ -790,16 +790,20 @@
 static irqreturn_t ldc_rx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long orig_state, hv_err, flags;
+	unsigned long orig_state, flags;
 	unsigned int event_mask;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_rx_get_state(lp->id,
-					&lp->rx_head,
-					&lp->rx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_rx_get_state(lp->id,
+			       &lp->rx_head,
+			       &lp->rx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
@@ -904,16 +908,20 @@
 static irqreturn_t ldc_tx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long flags, hv_err, orig_state;
+	unsigned long flags, orig_state;
 	unsigned int event_mask = 0;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_tx_get_state(lp->id,
-					&lp->tx_head,
-					&lp->tx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_tx_get_state(lp->id,
+			       &lp->tx_head,
+			       &lp->tx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci.c	2011-06-02 21:35:11.000000000 -0400
@@ -675,6 +675,7 @@
 		 * humanoid.
 		 */
 		err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr);
+		(void) err;
 	}
 	list_for_each_entry(child_bus, &bus->children, node)
 		pci_bus_register_of_sysfs(child_bus);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_common.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_common.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_common.c	2011-06-02 21:35:11.000000000 -0400
@@ -295,14 +295,17 @@
 	unsigned int bus = bus_dev->number;
 	unsigned int device = PCI_SLOT(devfn);
 	unsigned int func = PCI_FUNC(devfn);
-	unsigned long ret;
 
 	if (config_out_of_range(pbm, bus, devfn, where)) {
 		/* Do nothing. */
 	} else {
-		ret = pci_sun4v_config_put(devhandle,
-				HV_PCI_DEVICE_BUILD(bus, device, func),
-				where, size, value);
+		/* We don't check for hypervisor errors here, but perhaps
+		 * we should and influence our return value depending upon
+		 * what kind of error is thrown.
+		 */
+		pci_sun4v_config_put(devhandle,
+				     HV_PCI_DEVICE_BUILD(bus, device, func),
+				     where, size, value);
 	}
 	return PCIBIOS_SUCCESSFUL;
 }
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_fire.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_fire.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_fire.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_fire.c	2011-06-02 21:35:11.000000000 -0400
@@ -214,11 +214,9 @@
 
 static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi)
 {
-	unsigned long msiqid;
 	u64 val;
 
 	val = upa_readq(pbm->pbm_regs + MSI_MAP(msi));
-	msiqid = (val & MSI_MAP_EQNUM);
 
 	val &= ~MSI_MAP_VALID;
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_schizo.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_schizo.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_schizo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_schizo.c	2011-06-02 21:35:11.000000000 -0400
@@ -1313,7 +1313,7 @@
 	const struct linux_prom64_registers *regs;
 	struct device_node *dp = op->dev.of_node;
 	const char *chipset_name;
-	int is_pbm_a, err;
+	int err;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1343,8 +1343,6 @@
 	 */
 	regs = of_get_property(dp, "reg", NULL);
 
-	is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
-
 	pbm->next = pci_pbm_root;
 	pci_pbm_root = pbm;
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sun4v.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sun4v.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pci_sun4v.c	2011-06-02 21:35:11.000000000 -0400
@@ -580,7 +580,7 @@
 {
 	static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
 	struct iommu *iommu = pbm->iommu;
-	unsigned long num_tsb_entries, sz, tsbsize;
+	unsigned long num_tsb_entries, sz;
 	u32 dma_mask, dma_offset;
 	const u32 *vdma;
 
@@ -596,7 +596,6 @@
 
 	dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
 	num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
-	tsbsize = num_tsb_entries * sizeof(iopte_t);
 
 	dma_offset = vdma[0];
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pcr.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pcr.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pcr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/pcr.c	2011-06-02 21:35:11.000000000 -0400
@@ -81,7 +81,7 @@
 	unsigned long ret;
 
 	ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-	if (val != HV_EOK)
+	if (ret != HV_EOK)
 		write_pcr(val);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ptrace_64.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/ptrace_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ptrace_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/ptrace_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -1086,6 +1086,7 @@
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
+#ifdef CONFIG_AUDITSYSCALL
 	if (unlikely(current->audit_context)) {
 		unsigned long tstate = regs->tstate;
 		int result = AUDITSC_SUCCESS;
@@ -1095,7 +1096,7 @@
 
 		audit_syscall_exit(result, regs->u_regs[UREG_I0]);
 	}
-
+#endif
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_exit(regs, regs->u_regs[UREG_G1]);
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_64.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/smp_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -189,7 +189,7 @@
 void smp_synchronize_tick_client(void)
 {
 	long i, delta, adj, adjust_latency = 0, done = 0;
-	unsigned long flags, rt, master_time_stamp, bound;
+	unsigned long flags, rt, master_time_stamp;
 #if DEBUG_TICK_SYNC
 	struct {
 		long rt;	/* roundtrip time */
@@ -208,10 +208,8 @@
 	{
 		for (i = 0; i < NUM_ROUNDS; i++) {
 			delta = get_delta(&rt, &master_time_stamp);
-			if (delta == 0) {
+			if (delta == 0)
 				done = 1;	/* let's lock on to this... */
-				bound = rt;
-			}
 
 			if (!done) {
 				if (i > 0) {
@@ -933,13 +931,12 @@
 void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 {
 	void *pg_addr;
-	int this_cpu;
 	u64 data0;
 
 	if (tlb_type == hypervisor)
 		return;
 
-	this_cpu = get_cpu();
+	preempt_disable();
 
 #ifdef CONFIG_DEBUG_DCFLUSH
 	atomic_inc(&dcpage_flushes);
@@ -964,7 +961,7 @@
 	}
 	__local_flush_dcache_page(page);
 
-	put_cpu();
+	preempt_enable();
 }
 
 void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/traps_64.c linux-libre-2.6.38.8-gnu/arch/sparc/kernel/traps_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/traps_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/traps_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -2152,7 +2152,7 @@
 
 void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
-	unsigned long fp, thread_base, ksp;
+	unsigned long fp, ksp;
 	struct thread_info *tp;
 	int count = 0;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -2173,7 +2173,6 @@
 		flushw_all();
 
 	fp = ksp + STACK_BIAS;
-	thread_base = (unsigned long) tp;
 
 	printk("Call Trace:\n");
 	do {
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/una_asm_64.S linux-libre-2.6.38.8-gnu/arch/sparc/kernel/una_asm_64.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/una_asm_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/kernel/una_asm_64.S	2011-06-02 21:35:11.000000000 -0400
@@ -127,7 +127,7 @@
 	wr	%o5, 0x0, %asi
 	retl
 	 mov	0, %o0
-	.size	__do_int_load, .-__do_int_load
+	.size	do_int_load, .-do_int_load
 
 	.section	__ex_table,"a"
 	.word		4b, __retl_efault
diff -druN linux-libre-2.6.38-gnu/arch/sparc/mm/fault_32.c linux-libre-2.6.38.8-gnu/arch/sparc/mm/fault_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/mm/fault_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/sparc/mm/fault_32.c	2011-06-02 21:35:11.000000000 -0400
@@ -240,11 +240,10 @@
 	 * only copy the information from the master page table,
 	 * nothing more.
 	 */
+	code = SEGV_MAPERR;
 	if (!ARCH_SUN4C && address >= TASK_SIZE)
 		goto vmalloc_fault;
 
-	code = SEGV_MAPERR;
-
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-i386/atomic64_cx8_32.S linux-libre-2.6.38.8-gnu/arch/um/sys-i386/atomic64_cx8_32.S
--- linux-libre-2.6.38-gnu/arch/um/sys-i386/atomic64_cx8_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38.8-gnu/arch/um/sys-i386/atomic64_cx8_32.S	2011-06-02 21:35:11.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * atomic64_t for 586+
+ *
+ * Copied from arch/x86/lib/atomic64_cx8_32.S
+ *
+ * Copyright © 2010  Luca Barbieri
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+.macro SAVE reg
+	pushl_cfi %\reg
+	CFI_REL_OFFSET \reg, 0
+.endm
+
+.macro RESTORE reg
+	popl_cfi %\reg
+	CFI_RESTORE \reg
+.endm
+
+.macro read64 reg
+	movl %ebx, %eax
+	movl %ecx, %edx
+/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
+	LOCK_PREFIX
+	cmpxchg8b (\reg)
+.endm
+
+ENTRY(atomic64_read_cx8)
+	CFI_STARTPROC
+
+	read64 %ecx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_read_cx8)
+
+ENTRY(atomic64_set_cx8)
+	CFI_STARTPROC
+
+1:
+/* we don't need LOCK_PREFIX since aligned 64-bit writes
+ * are atomic on 586 and newer */
+	cmpxchg8b (%esi)
+	jne 1b
+
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_set_cx8)
+
+ENTRY(atomic64_xchg_cx8)
+	CFI_STARTPROC
+
+	movl %ebx, %eax
+	movl %ecx, %edx
+1:
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_xchg_cx8)
+
+.macro addsub_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+	CFI_STARTPROC
+	SAVE ebp
+	SAVE ebx
+	SAVE esi
+	SAVE edi
+
+	movl %eax, %esi
+	movl %edx, %edi
+	movl %ecx, %ebp
+
+	read64 %ebp
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	\ins\()l %esi, %ebx
+	\insc\()l %edi, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%ebp)
+	jne 1b
+
+10:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE edi
+	RESTORE esi
+	RESTORE ebx
+	RESTORE ebp
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+addsub_return add add adc
+addsub_return sub sub sbb
+
+.macro incdec_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	\ins\()l $1, %ebx
+	\insc\()l $0, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+10:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE ebx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+incdec_return inc add adc
+incdec_return dec sub sbb
+
+ENTRY(atomic64_dec_if_positive_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	subl $1, %ebx
+	sbb $0, %ecx
+	js 2f
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+2:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE ebx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_dec_if_positive_cx8)
+
+ENTRY(atomic64_add_unless_cx8)
+	CFI_STARTPROC
+	SAVE ebp
+	SAVE ebx
+/* these just push these two parameters on the stack */
+	SAVE edi
+	SAVE esi
+
+	movl %ecx, %ebp
+	movl %eax, %esi
+	movl %edx, %edi
+
+	read64 %ebp
+1:
+	cmpl %eax, 0(%esp)
+	je 4f
+2:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	addl %esi, %ebx
+	adcl %edi, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%ebp)
+	jne 1b
+
+	movl $1, %eax
+3:
+	addl $8, %esp
+	CFI_ADJUST_CFA_OFFSET -8
+	RESTORE ebx
+	RESTORE ebp
+	ret
+4:
+	cmpl %edx, 4(%esp)
+	jne 2b
+	xorl %eax, %eax
+	jmp 3b
+	CFI_ENDPROC
+ENDPROC(atomic64_add_unless_cx8)
+
+ENTRY(atomic64_inc_not_zero_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	testl %eax, %eax
+	je 4f
+2:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	addl $1, %ebx
+	adcl $0, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+	movl $1, %eax
+3:
+	RESTORE ebx
+	ret
+4:
+	testl %edx, %edx
+	jne 2b
+	jmp 3b
+	CFI_ENDPROC
+ENDPROC(atomic64_inc_not_zero_cx8)
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-i386/Makefile linux-libre-2.6.38.8-gnu/arch/um/sys-i386/Makefile
--- linux-libre-2.6.38-gnu/arch/um/sys-i386/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/um/sys-i386/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-	sys_call_table.o tls.o
+	sys_call_table.o tls.o atomic64_cx8_32.o
 
 obj-$(CONFIG_BINFMT_ELF) += elfcore.o
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_asm.S linux-libre-2.6.38.8-gnu/arch/x86/crypto/aesni-intel_asm.S
--- linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_asm.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/crypto/aesni-intel_asm.S	2011-06-02 21:35:11.000000000 -0400
@@ -1612,6 +1612,7 @@
         movdqa SHUF_MASK(%rip), %xmm10
 	PSHUFB_XMM %xmm10, %xmm0
 
+
 	ENCRYPT_SINGLE_BLOCK	%xmm0, %xmm1        # Encrypt(K, Yn)
 	sub $16, %r11
 	add %r13, %r11
@@ -1634,7 +1635,9 @@
 	# GHASH computation for the last <16 byte block
 	sub	%r13, %r11
 	add	$16, %r11
-	PSHUFB_XMM %xmm10, %xmm1
+
+	movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm0
 
 	# shuffle xmm0 back to output as ciphertext
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-2.6.38.8-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_glue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/crypto/aesni-intel_glue.c	2011-06-02 21:35:11.000000000 -0400
@@ -828,9 +828,15 @@
 	struct cryptd_aead *cryptd_tfm;
 	struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *)
 		PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
+	struct crypto_aead *cryptd_child;
+	struct aesni_rfc4106_gcm_ctx *child_ctx;
 	cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0);
 	if (IS_ERR(cryptd_tfm))
 		return PTR_ERR(cryptd_tfm);
+
+	cryptd_child = cryptd_aead_child(cryptd_tfm);
+	child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child);
+	memcpy(child_ctx, ctx, sizeof(*ctx));
 	ctx->cryptd_tfm = cryptd_tfm;
 	tfm->crt_aead.reqsize = sizeof(struct aead_request)
 		+ crypto_aead_reqsize(&cryptd_tfm->base);
@@ -925,6 +931,9 @@
 	int ret = 0;
 	struct crypto_tfm *tfm = crypto_aead_tfm(parent);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
+	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+	struct aesni_rfc4106_gcm_ctx *child_ctx =
+                                 aesni_rfc4106_gcm_ctx_get(cryptd_child);
 	u8 *new_key_mem = NULL;
 
 	if (key_len < 4) {
@@ -968,6 +977,7 @@
 		goto exit;
 	}
 	ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
+	memcpy(child_ctx, ctx, sizeof(*ctx));
 exit:
 	kfree(new_key_mem);
 	return ret;
@@ -999,7 +1009,6 @@
 	int ret;
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
 	if (!irq_fpu_usable()) {
 		struct aead_request *cryptd_req =
@@ -1008,6 +1017,7 @@
 		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 		return crypto_aead_encrypt(cryptd_req);
 	} else {
+		struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 		kernel_fpu_begin();
 		ret = cryptd_child->base.crt_aead.encrypt(req);
 		kernel_fpu_end();
@@ -1020,7 +1030,6 @@
 	int ret;
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
 	if (!irq_fpu_usable()) {
 		struct aead_request *cryptd_req =
@@ -1029,6 +1038,7 @@
 		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 		return crypto_aead_decrypt(cryptd_req);
 	} else {
+		struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 		kernel_fpu_begin();
 		ret = cryptd_child->base.crt_aead.decrypt(req);
 		kernel_fpu_end();
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/apicdef.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/apicdef.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/apicdef.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/apicdef.h	2011-06-02 21:35:11.000000000 -0400
@@ -78,6 +78,7 @@
 #define		APIC_DEST_LOGICAL	0x00800
 #define		APIC_DEST_PHYSICAL	0x00000
 #define		APIC_DM_FIXED		0x00000
+#define		APIC_DM_FIXED_MASK	0x00700
 #define		APIC_DM_LOWEST		0x00100
 #define		APIC_DM_SMI		0x00200
 #define		APIC_DM_REMRD		0x00300
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/cpufeature.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/cpufeature.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/cpufeature.h	2011-06-02 21:35:11.000000000 -0400
@@ -125,7 +125,7 @@
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
 #define X86_FEATURE_AVX		(4*32+28) /* Advanced Vector Extensions */
 #define X86_FEATURE_F16C	(4*32+29) /* 16-bit fp conversions */
-#define X86_FEATURE_RDRND	(4*32+30) /* The RDRAND instruction */
+#define X86_FEATURE_RDRAND	(4*32+30) /* The RDRAND instruction */
 #define X86_FEATURE_HYPERVISOR	(4*32+31) /* Running on a hypervisor */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/gart.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/gart.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/gart.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/gart.h	2011-06-02 21:35:11.000000000 -0400
@@ -66,7 +66,7 @@
 	 * Don't enable translation but enable GART IO and CPU accesses.
 	 * Also, set DISTLBWALKPRB since GART tables memory is UC.
 	 */
-	ctl = DISTLBWALKPRB | order << 1;
+	ctl = order << 1;
 
 	pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
@@ -83,7 +83,7 @@
 
         /* Enable GART translation for this hammer. */
         pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
-        ctl |= GARTEN;
+        ctl |= GARTEN | DISTLBWALKPRB;
         ctl &= ~(DISGARTCPU | DISGARTIO);
         pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/msr-index.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/msr-index.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/msr-index.h	2011-06-02 21:35:11.000000000 -0400
@@ -92,11 +92,15 @@
 #define MSR_IA32_MC0_ADDR		0x00000402
 #define MSR_IA32_MC0_MISC		0x00000403
 
+#define MSR_AMD64_MC0_MASK		0xc0010044
+
 #define MSR_IA32_MCx_CTL(x)		(MSR_IA32_MC0_CTL + 4*(x))
 #define MSR_IA32_MCx_STATUS(x)		(MSR_IA32_MC0_STATUS + 4*(x))
 #define MSR_IA32_MCx_ADDR(x)		(MSR_IA32_MC0_ADDR + 4*(x))
 #define MSR_IA32_MCx_MISC(x)		(MSR_IA32_MC0_MISC + 4*(x))
 
+#define MSR_AMD64_MCx_MASK(x)		(MSR_AMD64_MC0_MASK + (x))
+
 /* These are consecutive and not in the normal 4er MCE bank block */
 #define MSR_IA32_MC0_CTL2		0x00000280
 #define MSR_IA32_MCx_CTL2(x)		(MSR_IA32_MC0_CTL2 + (x))
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable-3level.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/pgtable-3level.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable-3level.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/pgtable-3level.h	2011-06-02 21:35:11.000000000 -0400
@@ -69,8 +69,6 @@
 
 static inline void pud_clear(pud_t *pudp)
 {
-	unsigned long pgd;
-
 	set_pud(pudp, __pud(0));
 
 	/*
@@ -79,13 +77,10 @@
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 *
-	 * Make sure the pud entry we're updating is within the
-	 * current pgd to avoid unnecessary TLB flushes.
+	 * Currently all places where pud_clear() is called either have
+	 * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or
+	 * pud_clear_bad()), so we don't need TLB flush here.
 	 */
-	pgd = read_cr3();
-	if (__pa(pudp) >= pgd && __pa(pudp) <
-	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
-		write_cr3(pgd);
 }
 
 #ifdef CONFIG_SMP
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/uaccess.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/uaccess.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/uaccess.h	2011-06-02 21:35:11.000000000 -0400
@@ -42,7 +42,7 @@
  * Returns 0 if the range is valid, nonzero otherwise.
  *
  * This is equivalent to the following test:
- * (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64)
+ * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64)
  *
  * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry...
  */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-2.6.38.8-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_bau.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/include/asm/uv/uv_bau.h	2011-06-02 21:35:11.000000000 -0400
@@ -94,6 +94,8 @@
 /* after this # consecutive successes, bump up the throttle if it was lowered */
 #define COMPLETE_THRESHOLD 5
 
+#define UV_LB_SUBNODEID 0x10
+
 /*
  * number of entries in the destination side payload queue
  */
@@ -124,7 +126,7 @@
  * The distribution specification (32 bytes) is interpreted as a 256-bit
  * distribution vector. Adjacent bits correspond to consecutive even numbered
  * nodeIDs. The result of adding the index of a given bit to the 15-bit
- * 'base_dest_nodeid' field of the header corresponds to the
+ * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
 struct bau_target_uvhubmask {
@@ -176,7 +178,7 @@
 struct bau_msg_header {
 	unsigned int dest_subnodeid:6;	/* must be 0x10, for the LB */
 	/* bits 5:0 */
-	unsigned int base_dest_nodeid:15; /* nasid of the */
+	unsigned int base_dest_nasid:15; /* nasid of the */
 	/* bits 20:6 */			  /* first bit in uvhub map */
 	unsigned int command:8;	/* message type */
 	/* bits 28:21 */
@@ -378,6 +380,10 @@
 	unsigned long d_rcanceled; /* number of messages canceled by resets */
 };
 
+struct hub_and_pnode {
+	short uvhub;
+	short pnode;
+};
 /*
  * one per-cpu; to locate the software tables
  */
@@ -399,10 +405,12 @@
 	int baudisabled;
 	int set_bau_off;
 	short cpu;
+	short osnode;
 	short uvhub_cpu;
 	short uvhub;
 	short cpus_in_socket;
 	short cpus_in_uvhub;
+	short partition_base_pnode;
 	unsigned short message_number;
 	unsigned short uvhub_quiesce;
 	short socket_acknowledge_count[DEST_Q_SIZE];
@@ -422,15 +430,16 @@
 	int congested_period;
 	cycles_t period_time;
 	long period_requests;
+	struct hub_and_pnode *target_hub_and_pnode;
 };
 
 static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
 {
 	return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct bau_target_uvhubmask *dstp)
 {
-	__set_bit(uvhub, &dstp->bits[0]);
+	__set_bit(pnode, &dstp->bits[0]);
 }
 static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp,
 				    int nbits)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/alternative.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/alternative.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/alternative.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/alternative.c	2011-06-02 21:35:11.000000000 -0400
@@ -620,7 +620,12 @@
 		flush_icache_range((unsigned long)p->addr,
 				   (unsigned long)p->addr + p->len);
 	}
-
+	/*
+	 * Intel Archiecture Software Developer's Manual section 7.1.3 specifies
+	 * that a core serializing instruction such as "cpuid" should be
+	 * executed on _each_ core before the new instruction is made visible.
+	 */
+	sync_core();
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/aperture_64.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/aperture_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/aperture_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/aperture_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -500,7 +500,7 @@
 		 * Don't enable translation yet but enable GART IO and CPU
 		 * accesses and set DISTLBWALKPRB since GART table memory is UC.
 		 */
-		u32 ctl = DISTLBWALKPRB | aper_order << 1;
+		u32 ctl = aper_order << 1;
 
 		bus = amd_nb_bus_dev_ranges[i].bus;
 		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/io_apic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/apic/io_apic.c	2011-06-02 21:35:11.000000000 -0400
@@ -615,14 +615,14 @@
 	struct IO_APIC_route_entry **ioapic_entries;
 
 	ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
-				GFP_KERNEL);
+				GFP_ATOMIC);
 	if (!ioapic_entries)
 		return 0;
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 		ioapic_entries[apic] =
 			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				nr_ioapic_registers[apic], GFP_KERNEL);
+				nr_ioapic_registers[apic], GFP_ATOMIC);
 		if (!ioapic_entries[apic])
 			goto nomem;
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/amd.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/amd.c	2011-06-02 21:35:11.000000000 -0400
@@ -594,6 +594,35 @@
 		}
 	}
 #endif
+
+	/*
+	 * Family 0x12 and above processors have APIC timer
+	 * running in deep C states.
+	 */
+	if (c->x86 > 0x11)
+		set_cpu_cap(c, X86_FEATURE_ARAT);
+
+	/*
+	 * Disable GART TLB Walk Errors on Fam10h. We do this here
+	 * because this is always needed when GART is enabled, even in a
+	 * kernel which has no MCE support built in.
+	 */
+	if (c->x86 == 0x10) {
+		/*
+		 * BIOS should disable GartTlbWlk Errors themself. If
+		 * it doesn't do it here as suggested by the BKDG.
+		 *
+		 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
+		 */
+		u64 mask;
+		int err;
+
+		err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask);
+		if (err == 0) {
+			mask |= (1 << 10);
+			checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+		}
+	}
 }
 
 #ifdef CONFIG_X86_32
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/common.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/common.c	2011-06-02 21:35:11.000000000 -0400
@@ -565,8 +565,7 @@
 
 		cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
 
-		if (eax > 0)
-			c->x86_capability[9] = ebx;
+		c->x86_capability[9] = ebx;
 	}
 
 	/* AMD-defined flags: level 0x80000001 */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-06-02 21:35:11.000000000 -0400
@@ -39,7 +39,7 @@
 
 #include <acpi/processor.h>
 
-#define PCC_VERSION 	"1.00.00"
+#define PCC_VERSION	"1.10.00"
 #define POLL_LOOPS 	300
 
 #define CMD_COMPLETE 	0x1
@@ -102,7 +102,7 @@
 static u64 doorbell_preserve;
 static u64 doorbell_write;
 
-static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f,
+static u8 OSC_UUID[16] = {0x9F, 0x2C, 0x9B, 0x63, 0x91, 0x70, 0x1f, 0x49,
 			  0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46};
 
 struct pcc_cpu {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-06-02 21:35:11.000000000 -0400
@@ -509,6 +509,7 @@
 out_free:
 	if (b) {
 		kobject_put(&b->kobj);
+		list_del(&b->miscj);
 		kfree(b);
 	}
 	return err;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-06-02 21:35:11.000000000 -0400
@@ -446,18 +446,20 @@
 	 */
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 
+	h = lvtthmr_init;
 	/*
 	 * The initial value of thermal LVT entries on all APs always reads
 	 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
 	 * sequence to them and LVT registers are reset to 0s except for
 	 * the mask bits which are set to 1s when APs receive INIT IPI.
-	 * Always restore the value that BIOS has programmed on AP based on
-	 * BSP's info we saved since BIOS is always setting the same value
-	 * for all threads/cores
+	 * If BIOS takes over the thermal interrupt and sets its interrupt
+	 * delivery mode to SMI (not fixed), it restores the value that the
+	 * BIOS has programmed on AP based on BSP's info we saved since BIOS
+	 * is always setting the same value for all threads/cores.
 	 */
-	apic_write(APIC_LVTTHMR, lvtthmr_init);
+	if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
+		apic_write(APIC_LVTTHMR, lvtthmr_init);
 
-	h = lvtthmr_init;
 
 	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
 		printk(KERN_DEBUG
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/main.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mtrr/main.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/cpu/mtrr/main.c	2011-06-02 21:35:11.000000000 -0400
@@ -292,14 +292,24 @@
 
 	/*
 	 * HACK!
-	 * We use this same function to initialize the mtrrs on boot.
-	 * The state of the boot cpu's mtrrs has been saved, and we want
-	 * to replicate across all the APs.
-	 * If we're doing that @reg is set to something special...
+	 *
+	 * We use this same function to initialize the mtrrs during boot,
+	 * resume, runtime cpu online and on an explicit request to set a
+	 * specific MTRR.
+	 *
+	 * During boot or suspend, the state of the boot cpu's mtrrs has been
+	 * saved, and we want to replicate that across all the cpus that come
+	 * online (either at the end of boot or resume or during a runtime cpu
+	 * online). If we're doing that, @reg is set to something special and on
+	 * this cpu we still do mtrr_if->set_all(). During boot/resume, this
+	 * is unnecessary if at this point we are still on the cpu that started
+	 * the boot/resume sequence. But there is no guarantee that we are still
+	 * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
+	 * sure that we are in sync with everyone else.
 	 */
 	if (reg != ~0U)
 		mtrr_if->set(reg, base, size, type);
-	else if (!mtrr_aps_delayed_init)
+	else
 		mtrr_if->set_all();
 
 	/* Wait for the others */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/e820.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/e820.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/e820.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/e820.c	2011-06-02 21:35:11.000000000 -0400
@@ -847,15 +847,21 @@
 	if (!p)
 		return -EINVAL;
 
-#ifdef CONFIG_X86_32
 	if (!strcmp(p, "nopentium")) {
+#ifdef CONFIG_X86_32
 		setup_clear_cpu_cap(X86_FEATURE_PSE);
 		return 0;
-	}
+#else
+		printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+		return -EINVAL;
 #endif
+	}
 
 	userdef = 1;
 	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" param */
+	if (mem_size == 0)
+		return -EINVAL;
 	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/early-quirks.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/early-quirks.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/early-quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/early-quirks.c	2011-06-02 21:35:11.000000000 -0400
@@ -159,7 +159,12 @@
 	if (rev >= 0x40)
 		acpi_fix_pin2_polarity = 1;
 
-	if (rev > 0x13)
+	/*
+	 * SB600: revisions 0x11, 0x12, 0x13, 0x14, ...
+	 * SB700: revisions 0x39, 0x3a, ...
+	 * SB800: revisions 0x40, 0x41, ...
+	 */
+	if (rev >= 0x39)
 		return;
 
 	if (acpi_use_timer_override)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/entry_32.S linux-libre-2.6.38.8-gnu/arch/x86/kernel/entry_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/entry_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/entry_32.S	2011-06-02 21:35:11.000000000 -0400
@@ -1413,7 +1413,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
-END(apf_page_fault)
+END(async_page_fault)
 #endif
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/entry_64.S linux-libre-2.6.38.8-gnu/arch/x86/kernel/entry_64.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/entry_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/entry_64.S	2011-06-02 21:35:11.000000000 -0400
@@ -1248,7 +1248,7 @@
 	decl PER_CPU_VAR(irq_count)
 	jmp  error_exit
 	CFI_ENDPROC
-END(do_hypervisor_callback)
+END(xen_do_hypervisor_callback)
 
 /*
  * Hypervisor uses this for application faults while it executes.
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/pci-gart_64.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/pci-gart_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/pci-gart_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/pci-gart_64.c	2011-06-02 21:35:11.000000000 -0400
@@ -81,6 +81,9 @@
 #define AGPEXTERN
 #endif
 
+/* GART can only remap to physical addresses < 1TB */
+#define GART_MAX_PHYS_ADDR	(1ULL << 40)
+
 /* backdoor interface to AGP driver */
 AGPEXTERN int agp_memory_reserved;
 AGPEXTERN __u32 *agp_gatt_table;
@@ -212,9 +215,13 @@
 				size_t size, int dir, unsigned long align_mask)
 {
 	unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
-	unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
+	unsigned long iommu_page;
 	int i;
 
+	if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR))
+		return bad_dma_addr;
+
+	iommu_page = alloc_iommu(dev, npages, align_mask);
 	if (iommu_page == -1) {
 		if (!nonforced_iommu(dev, phys_mem, size))
 			return phys_mem;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/ptrace.c linux-libre-2.6.38.8-gnu/arch/x86/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kernel/ptrace.c	2011-06-02 21:35:11.000000000 -0400
@@ -608,6 +608,9 @@
 	unsigned len, type;
 	struct perf_event *bp;
 
+	if (ptrace_get_breakpoints(tsk) < 0)
+		return -ESRCH;
+
 	data &= ~DR_CONTROL_RESERVED;
 	old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
 restore:
@@ -655,6 +658,9 @@
 		}
 		goto restore;
 	}
+
+	ptrace_put_breakpoints(tsk);
+
 	return ((orig_ret < 0) ? orig_ret : rc);
 }
 
@@ -668,10 +674,17 @@
 
 	if (n < HBP_NUM) {
 		struct perf_event *bp;
+
+		if (ptrace_get_breakpoints(tsk) < 0)
+			return -ESRCH;
+
 		bp = thread->ptrace_bps[n];
 		if (!bp)
-			return 0;
-		val = bp->hw.info.address;
+			val = 0;
+		else
+			val = bp->hw.info.address;
+
+		ptrace_put_breakpoints(tsk);
 	} else if (n == 6) {
 		val = thread->debugreg6;
 	 } else if (n == 7) {
@@ -686,6 +699,10 @@
 	struct perf_event *bp;
 	struct thread_struct *t = &tsk->thread;
 	struct perf_event_attr attr;
+	int err = 0;
+
+	if (ptrace_get_breakpoints(tsk) < 0)
+		return -ESRCH;
 
 	if (!t->ptrace_bps[nr]) {
 		ptrace_breakpoint_init(&attr);
@@ -709,24 +726,23 @@
 		 * writing for the user. And anyway this is the previous
 		 * behaviour.
 		 */
-		if (IS_ERR(bp))
-			return PTR_ERR(bp);
+		if (IS_ERR(bp)) {
+			err = PTR_ERR(bp);
+			goto put;
+		}
 
 		t->ptrace_bps[nr] = bp;
 	} else {
-		int err;
-
 		bp = t->ptrace_bps[nr];
 
 		attr = bp->attr;
 		attr.bp_addr = addr;
 		err = modify_user_hw_breakpoint(bp, &attr);
-		if (err)
-			return err;
 	}
 
-
-	return 0;
+put:
+	ptrace_put_breakpoints(tsk);
+	return err;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/svm.c linux-libre-2.6.38.8-gnu/arch/x86/kvm/svm.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/svm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/kvm/svm.c	2011-06-02 21:35:11.000000000 -0400
@@ -135,6 +135,8 @@
 
 	u32 *msrpm;
 
+	ulong nmi_iret_rip;
+
 	struct nested_state nested;
 
 	bool nmi_singlestep;
@@ -2653,6 +2655,7 @@
 	++svm->vcpu.stat.nmi_window_exits;
 	clr_intercept(svm, INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
+	svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
 	return 1;
 }
 
@@ -3474,7 +3477,12 @@
 
 	svm->int3_injected = 0;
 
-	if (svm->vcpu.arch.hflags & HF_IRET_MASK) {
+	/*
+	 * If we've made progress since setting HF_IRET_MASK, we've
+	 * executed an IRET and can allow NMI injection.
+	 */
+	if ((svm->vcpu.arch.hflags & HF_IRET_MASK)
+	    && kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) {
 		svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
 		kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/copy_user_64.S linux-libre-2.6.38.8-gnu/arch/x86/lib/copy_user_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/copy_user_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/lib/copy_user_64.S	2011-06-02 21:35:11.000000000 -0400
@@ -72,7 +72,7 @@
 	addq %rdx,%rcx
 	jc bad_to_user
 	cmpq TI_addr_limit(%rax),%rcx
-	jae bad_to_user
+	ja bad_to_user
 	ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
 	CFI_ENDPROC
 ENDPROC(_copy_to_user)
@@ -85,7 +85,7 @@
 	addq %rdx,%rcx
 	jc bad_from_user
 	cmpq TI_addr_limit(%rax),%rcx
-	jae bad_from_user
+	ja bad_from_user
 	ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
 	CFI_ENDPROC
 ENDPROC(_copy_from_user)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/semaphore_32.S linux-libre-2.6.38.8-gnu/arch/x86/lib/semaphore_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/semaphore_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/lib/semaphore_32.S	2011-06-02 21:35:11.000000000 -0400
@@ -36,7 +36,7 @@
  */
 #ifdef CONFIG_SMP
 ENTRY(__write_lock_failed)
-	CFI_STARTPROC simple
+	CFI_STARTPROC
 	FRAME
 2: 	LOCK_PREFIX
 	addl	$ RW_LOCK_BIAS,(%eax)
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/pgtable.c linux-libre-2.6.38.8-gnu/arch/x86/mm/pgtable.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/pgtable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/mm/pgtable.c	2011-06-02 21:35:11.000000000 -0400
@@ -168,8 +168,7 @@
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 */
-	if (mm == current->active_mm)
-		write_cr3(read_cr3());
+	flush_tlb_mm(mm);
 }
 #else  /* !CONFIG_X86_PAE */
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/oprofile/op_model_amd.c linux-libre-2.6.38.8-gnu/arch/x86/oprofile/op_model_amd.c
--- linux-libre-2.6.38-gnu/arch/x86/oprofile/op_model_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/oprofile/op_model_amd.c	2011-06-02 21:35:11.000000000 -0400
@@ -316,16 +316,23 @@
 		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
-static inline int eilvt_is_available(int offset)
+static inline int get_eilvt(int offset)
 {
-	/* check if we may assign a vector */
 	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
 }
 
+static inline int put_eilvt(int offset)
+{
+	return !setup_APIC_eilvt(offset, 0, 0, 1);
+}
+
 static inline int ibs_eilvt_valid(void)
 {
 	int offset;
 	u64 val;
+	int valid = 0;
+
+	preempt_disable();
 
 	rdmsrl(MSR_AMD64_IBSCTL, val);
 	offset = val & IBSCTL_LVT_OFFSET_MASK;
@@ -333,16 +340,20 @@
 	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
 		pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
 		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		return 0;
+		goto out;
 	}
 
-	if (!eilvt_is_available(offset)) {
+	if (!get_eilvt(offset)) {
 		pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
 		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		return 0;
+		goto out;
 	}
 
-	return 1;
+	valid = 1;
+out:
+	preempt_enable();
+
+	return valid;
 }
 
 static inline int get_ibs_offset(void)
@@ -600,67 +611,69 @@
 
 static int force_ibs_eilvt_setup(void)
 {
-	int i;
+	int offset;
 	int ret;
 
-	/* find the next free available EILVT entry */
-	for (i = 1; i < 4; i++) {
-		if (!eilvt_is_available(i))
-			continue;
-		ret = setup_ibs_ctl(i);
-		if (ret)
-			return ret;
-		pr_err(FW_BUG "using offset %d for IBS interrupts\n", i);
-		return 0;
+	/*
+	 * find the next free available EILVT entry, skip offset 0,
+	 * pin search to this cpu
+	 */
+	preempt_disable();
+	for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
+		if (get_eilvt(offset))
+			break;
 	}
+	preempt_enable();
 
-	printk(KERN_DEBUG "No EILVT entry available\n");
-
-	return -EBUSY;
-}
-
-static int __init_ibs_nmi(void)
-{
-	int ret;
-
-	if (ibs_eilvt_valid())
-		return 0;
+	if (offset == APIC_EILVT_NR_MAX) {
+		printk(KERN_DEBUG "No EILVT entry available\n");
+		return -EBUSY;
+	}
 
-	ret = force_ibs_eilvt_setup();
+	ret = setup_ibs_ctl(offset);
 	if (ret)
-		return ret;
+		goto out;
 
-	if (!ibs_eilvt_valid())
-		return -EFAULT;
+	if (!ibs_eilvt_valid()) {
+		ret = -EFAULT;
+		goto out;
+	}
 
+	pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
 	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
 
 	return 0;
+out:
+	preempt_disable();
+	put_eilvt(offset);
+	preempt_enable();
+	return ret;
 }
 
 /*
  * check and reserve APIC extended interrupt LVT offset for IBS if
  * available
- *
- * init_ibs() preforms implicitly cpu-local operations, so pin this
- * thread to its current CPU
  */
 
 static void init_ibs(void)
 {
-	preempt_disable();
-
 	ibs_caps = get_ibs_caps();
+
 	if (!ibs_caps)
+		return;
+
+	if (ibs_eilvt_valid())
 		goto out;
 
-	if (__init_ibs_nmi() < 0)
-		ibs_caps = 0;
-	else
-		printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
+	if (!force_ibs_eilvt_setup())
+		goto out;
+
+	/* Failed to setup ibs */
+	ibs_caps = 0;
+	return;
 
 out:
-	preempt_enable();
+	printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
 }
 
 static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-2.6.38.8-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/uv/tlb_uv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/platform/uv/tlb_uv.c	2011-06-02 21:35:11.000000000 -0400
@@ -698,16 +698,17 @@
 					  struct mm_struct *mm,
 					  unsigned long va, unsigned int cpu)
 {
-	int tcpu;
-	int uvhub;
 	int locals = 0;
 	int remotes = 0;
 	int hubs = 0;
+	int tcpu;
+	int tpnode;
 	struct bau_desc *bau_desc;
 	struct cpumask *flush_mask;
 	struct ptc_stats *stat;
 	struct bau_control *bcp;
 	struct bau_control *tbcp;
+	struct hub_and_pnode *hpp;
 
 	/* kernel was booted 'nobau' */
 	if (nobau)
@@ -749,11 +750,18 @@
 	bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
 	bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
 
-	/* cpu statistics */
 	for_each_cpu(tcpu, flush_mask) {
-		uvhub = uv_cpu_to_blade_id(tcpu);
-		bau_uvhub_set(uvhub, &bau_desc->distribution);
-		if (uvhub == bcp->uvhub)
+		/*
+		 * The distribution vector is a bit map of pnodes, relative
+		 * to the partition base pnode (and the partition base nasid
+		 * in the header).
+		 * Translate cpu to pnode and hub using an array stored
+		 * in local memory.
+		 */
+		hpp = &bcp->socket_master->target_hub_and_pnode[tcpu];
+		tpnode = hpp->pnode - bcp->partition_base_pnode;
+		bau_uvhub_set(tpnode, &bau_desc->distribution);
+		if (hpp->uvhub == bcp->uvhub)
 			locals++;
 		else
 			remotes++;
@@ -854,7 +862,7 @@
  * an interrupt, but causes an error message to be returned to
  * the sender.
  */
-static void uv_enable_timeouts(void)
+static void __init uv_enable_timeouts(void)
 {
 	int uvhub;
 	int nuvhubs;
@@ -1325,10 +1333,10 @@
 }
 
 /*
- * initialize the sending side's sending buffers
+ * Initialize the sending side's sending buffers.
  */
 static void
-uv_activation_descriptor_init(int node, int pnode)
+uv_activation_descriptor_init(int node, int pnode, int base_pnode)
 {
 	int i;
 	int cpu;
@@ -1351,11 +1359,11 @@
 	n = pa >> uv_nshift;
 	m = pa & uv_mmask;
 
+	/* the 14-bit pnode */
 	uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
 			      (n << UV_DESC_BASE_PNODE_SHIFT | m));
-
 	/*
-	 * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
+	 * Initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
 	 * cpu even though we only use the first one; one descriptor can
 	 * describe a broadcast to 256 uv hubs.
 	 */
@@ -1364,12 +1372,13 @@
 		memset(bd2, 0, sizeof(struct bau_desc));
 		bd2->header.sw_ack_flag = 1;
 		/*
-		 * base_dest_nodeid is the nasid of the first uvhub
-		 * in the partition. The bit map will indicate uvhub numbers,
-		 * which are 0-N in a partition. Pnodes are unique system-wide.
+		 * The base_dest_nasid set in the message header is the nasid
+		 * of the first uvhub in the partition. The bit map will
+		 * indicate destination pnode numbers relative to that base.
+		 * They may not be consecutive if nasid striding is being used.
 		 */
-		bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode);
-		bd2->header.dest_subnodeid = 0x10; /* the LB */
+		bd2->header.base_dest_nasid = UV_PNODE_TO_NASID(base_pnode);
+		bd2->header.dest_subnodeid = UV_LB_SUBNODEID;
 		bd2->header.command = UV_NET_ENDPOINT_INTD;
 		bd2->header.int_both = 1;
 		/*
@@ -1441,7 +1450,7 @@
 /*
  * Initialization of each UV hub's structures
  */
-static void __init uv_init_uvhub(int uvhub, int vector)
+static void __init uv_init_uvhub(int uvhub, int vector, int base_pnode)
 {
 	int node;
 	int pnode;
@@ -1449,11 +1458,11 @@
 
 	node = uvhub_to_first_node(uvhub);
 	pnode = uv_blade_to_pnode(uvhub);
-	uv_activation_descriptor_init(node, pnode);
+	uv_activation_descriptor_init(node, pnode, base_pnode);
 	uv_payload_queue_init(node, pnode);
 	/*
-	 * the below initialization can't be in firmware because the
-	 * messaging IRQ will be determined by the OS
+	 * The below initialization can't be in firmware because the
+	 * messaging IRQ will be determined by the OS.
 	 */
 	apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
@@ -1490,10 +1499,11 @@
 /*
  * initialize the bau_control structure for each cpu
  */
-static int __init uv_init_per_cpu(int nuvhubs)
+static int __init uv_init_per_cpu(int nuvhubs, int base_part_pnode)
 {
 	int i;
 	int cpu;
+	int tcpu;
 	int pnode;
 	int uvhub;
 	int have_hmaster;
@@ -1527,6 +1537,15 @@
 		bcp = &per_cpu(bau_control, cpu);
 		memset(bcp, 0, sizeof(struct bau_control));
 		pnode = uv_cpu_hub_info(cpu)->pnode;
+		if ((pnode - base_part_pnode) >= UV_DISTRIBUTION_SIZE) {
+			printk(KERN_EMERG
+				"cpu %d pnode %d-%d beyond %d; BAU disabled\n",
+				cpu, pnode, base_part_pnode,
+				UV_DISTRIBUTION_SIZE);
+			return 1;
+		}
+		bcp->osnode = cpu_to_node(cpu);
+		bcp->partition_base_pnode = uv_partition_base_pnode;
 		uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
 		*(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8));
 		bdp = &uvhub_descs[uvhub];
@@ -1535,7 +1554,7 @@
 		bdp->pnode = pnode;
 		/* kludge: 'assuming' one node per socket, and assuming that
 		   disabling a socket just leaves a gap in node numbers */
-		socket = (cpu_to_node(cpu) & 1);
+		socket = bcp->osnode & 1;
 		bdp->socket_mask |= (1 << socket);
 		sdp = &bdp->socket[socket];
 		sdp->cpu_number[sdp->num_cpus] = cpu;
@@ -1584,6 +1603,20 @@
 nextsocket:
 			socket++;
 			socket_mask = (socket_mask >> 1);
+			/* each socket gets a local array of pnodes/hubs */
+			bcp = smaster;
+			bcp->target_hub_and_pnode = kmalloc_node(
+				sizeof(struct hub_and_pnode) *
+				num_possible_cpus(), GFP_KERNEL, bcp->osnode);
+			memset(bcp->target_hub_and_pnode, 0,
+				sizeof(struct hub_and_pnode) *
+				num_possible_cpus());
+			for_each_present_cpu(tcpu) {
+				bcp->target_hub_and_pnode[tcpu].pnode =
+					uv_cpu_hub_info(tcpu)->pnode;
+				bcp->target_hub_and_pnode[tcpu].uvhub =
+					uv_cpu_hub_info(tcpu)->numa_blade_id;
+			}
 		}
 	}
 	kfree(uvhub_descs);
@@ -1636,21 +1669,22 @@
 	spin_lock_init(&disable_lock);
 	congested_cycles = microsec_2_cycles(congested_response_us);
 
-	if (uv_init_per_cpu(nuvhubs)) {
-		nobau = 1;
-		return 0;
-	}
-
 	uv_partition_base_pnode = 0x7fffffff;
-	for (uvhub = 0; uvhub < nuvhubs; uvhub++)
+	for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
 		if (uv_blade_nr_possible_cpus(uvhub) &&
 			(uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
 			uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
+	}
+
+	if (uv_init_per_cpu(nuvhubs, uv_partition_base_pnode)) {
+		nobau = 1;
+		return 0;
+	}
 
 	vector = UV_BAU_MESSAGE;
 	for_each_possible_blade(uvhub)
 		if (uv_blade_nr_possible_cpus(uvhub))
-			uv_init_uvhub(uvhub, vector);
+			uv_init_uvhub(uvhub, vector, uv_partition_base_pnode);
 
 	uv_enable_timeouts();
 	alloc_intr_gate(vector, uv_bau_message_intr1);
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/mmu.c linux-libre-2.6.38.8-gnu/arch/x86/xen/mmu.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/mmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/arch/x86/xen/mmu.c	2011-06-02 21:35:11.000000000 -0400
@@ -1138,7 +1138,7 @@
 
 	active_mm = percpu_read(cpu_tlbstate.active_mm);
 
-	if (active_mm == mm)
+	if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK)
 		leave_mm(smp_processor_id());
 
 	/* If this cpu still has a stale cr3 reference, then make sure
@@ -1651,9 +1651,6 @@
 		for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
 			pte_t pte;
 
-			if (pfn > max_pfn_mapped)
-				max_pfn_mapped = pfn;
-
 			if (!pte_none(pte_page[pteidx]))
 				continue;
 
@@ -1711,6 +1708,12 @@
 	pud_t *l3;
 	pmd_t *l2;
 
+	/* max_pfn_mapped is the last pfn mapped in the initial memory
+	 * mappings. Considering that on Xen after the kernel mappings we
+	 * have the mappings of some pages that don't exist in pfn space, we
+	 * set max_pfn_mapped to the last real pfn mapped. */
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
+
 	/* Zap identity mapping */
 	init_level4_pgt[0] = __pgd(0);
 
@@ -1815,9 +1818,7 @@
 	initial_kernel_pmd =
 		extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
-	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
-				  xen_start_info->nr_pt_frames * PAGE_SIZE +
-				  512*1024);
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
 
 	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
 	memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
diff -druN linux-libre-2.6.38-gnu/block/blk.h linux-libre-2.6.38.8-gnu/block/blk.h
--- linux-libre-2.6.38-gnu/block/blk.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/block/blk.h	2011-06-02 21:35:11.000000000 -0400
@@ -68,7 +68,8 @@
 				return rq;
 		}
 
-		if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
+		if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) ||
+		    !q->elevator->ops->elevator_dispatch_fn(q, 0))
 			return NULL;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/block/blk-settings.c linux-libre-2.6.38.8-gnu/block/blk-settings.c
--- linux-libre-2.6.38-gnu/block/blk-settings.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/block/blk-settings.c	2011-06-02 21:35:11.000000000 -0400
@@ -120,7 +120,7 @@
 	lim->discard_granularity = 0;
 	lim->discard_alignment = 0;
 	lim->discard_misaligned = 0;
-	lim->discard_zeroes_data = -1;
+	lim->discard_zeroes_data = 1;
 	lim->logical_block_size = lim->physical_block_size = lim->io_min = 512;
 	lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT);
 	lim->alignment_offset = 0;
@@ -174,6 +174,7 @@
 
 	blk_set_default_limits(&q->limits);
 	blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
+	q->limits.discard_zeroes_data = 0;
 
 	/*
 	 * If the caller didn't supply a lock, fall back to our embedded
diff -druN linux-libre-2.6.38-gnu/block/blk-sysfs.c linux-libre-2.6.38.8-gnu/block/blk-sysfs.c
--- linux-libre-2.6.38-gnu/block/blk-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/block/blk-sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -152,7 +152,8 @@
 
 static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
 {
-	return queue_var_show(q->limits.max_discard_sectors << 9, page);
+	return sprintf(page, "%llu\n",
+		       (unsigned long long)q->limits.max_discard_sectors << 9);
 }
 
 static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
@@ -511,8 +512,10 @@
 		return ret;
 
 	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
-	if (ret < 0)
+	if (ret < 0) {
+		blk_trace_remove_sysfs(dev);
 		return ret;
+	}
 
 	kobject_uevent(&q->kobj, KOBJ_ADD);
 
diff -druN linux-libre-2.6.38-gnu/block/genhd.c linux-libre-2.6.38.8-gnu/block/genhd.c
--- linux-libre-2.6.38-gnu/block/genhd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/block/genhd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1724,7 +1724,7 @@
 {
 	struct disk_events *ev;
 
-	if (!disk->fops->check_events || !(disk->events | disk->async_events))
+	if (!disk->fops->check_events)
 		return;
 
 	ev = kzalloc(sizeof(*ev), GFP_KERNEL);
diff -druN linux-libre-2.6.38-gnu/Documentation/flexible-arrays.txt linux-libre-2.6.38.8-gnu/Documentation/flexible-arrays.txt
--- linux-libre-2.6.38-gnu/Documentation/flexible-arrays.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Documentation/flexible-arrays.txt	2011-06-02 21:35:11.000000000 -0400
@@ -66,10 +66,10 @@
 entering atomic context, using:
 
     int flex_array_prealloc(struct flex_array *array, unsigned int start,
-			    unsigned int end, gfp_t flags);
+			    unsigned int nr_elements, gfp_t flags);
 
 This function will ensure that memory for the elements indexed in the range
-defined by start and end has been allocated.  Thereafter, a
+defined by start and nr_elements has been allocated.  Thereafter, a
 flex_array_put() call on an element in that range is guaranteed not to
 block.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/instantiating-devices linux-libre-2.6.38.8-gnu/Documentation/i2c/instantiating-devices
--- linux-libre-2.6.38-gnu/Documentation/i2c/instantiating-devices	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Documentation/i2c/instantiating-devices	2011-06-02 21:35:11.000000000 -0400
@@ -100,7 +100,7 @@
 	(...)
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c, NULL);
 	i2c_put_adapter(i2c_adap);
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/writing-clients linux-libre-2.6.38.8-gnu/Documentation/i2c/writing-clients
--- linux-libre-2.6.38-gnu/Documentation/i2c/writing-clients	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Documentation/i2c/writing-clients	2011-06-02 21:35:11.000000000 -0400
@@ -38,7 +38,7 @@
 		.name	= "foo",
 	},
 
-	.id_table	= foo_ids,
+	.id_table	= foo_idtable,
 	.probe		= foo_probe,
 	.remove		= foo_remove,
 	/* if device autodetection is needed: */
diff -druN linux-libre-2.6.38-gnu/Documentation/usb/linux-cdc-acm.inf linux-libre-2.6.38.8-gnu/Documentation/usb/linux-cdc-acm.inf
--- linux-libre-2.6.38-gnu/Documentation/usb/linux-cdc-acm.inf	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Documentation/usb/linux-cdc-acm.inf	2011-06-02 21:35:11.000000000 -0400
@@ -90,10 +90,10 @@
 [SourceDisksFiles]
 [SourceDisksNames]
 [DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
 
 [DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
 
 
 ;------------------------------------------------------------------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/usb/linux.inf linux-libre-2.6.38.8-gnu/Documentation/usb/linux.inf
--- linux-libre-2.6.38-gnu/Documentation/usb/linux.inf	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Documentation/usb/linux.inf	2011-06-02 21:35:11.000000000 -0400
@@ -18,15 +18,15 @@
 
 ; Decoration for x86 architecture
 [LinuxDevices.NTx86]
-%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
 
 ; Decoration for x64 architecture
 [LinuxDevices.NTamd64]
-%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
 
 ; Decoration for ia64 architecture
 [LinuxDevices.NTia64]
-%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
 
 ;@@@ This is the common setting for setup
 [ControlFlags]
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/battery.c linux-libre-2.6.38.8-gnu/drivers/acpi/battery.c
--- linux-libre-2.6.38-gnu/drivers/acpi/battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/acpi/battery.c	2011-06-02 21:35:11.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/async.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
@@ -102,6 +103,7 @@
 	struct mutex lock;
 	struct power_supply bat;
 	struct acpi_device *device;
+	struct notifier_block pm_nb;
 	unsigned long update_time;
 	int rate_now;
 	int capacity_now;
@@ -940,6 +942,21 @@
 		power_supply_changed(&battery->bat);
 }
 
+static int battery_notify(struct notifier_block *nb,
+			       unsigned long mode, void *_unused)
+{
+	struct acpi_battery *battery = container_of(nb, struct acpi_battery,
+						    pm_nb);
+	switch (mode) {
+	case PM_POST_SUSPEND:
+		sysfs_remove_battery(battery);
+		sysfs_add_battery(battery);
+		break;
+	}
+
+	return 0;
+}
+
 static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
@@ -972,6 +989,10 @@
 #endif
 		kfree(battery);
 	}
+
+	battery->pm_nb.notifier_call = battery_notify;
+	register_pm_notifier(&battery->pm_nb);
+
 	return result;
 }
 
@@ -982,6 +1003,7 @@
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 	battery = acpi_driver_data(device);
+	unregister_pm_notifier(&battery->pm_nb);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/pci_root.c linux-libre-2.6.38.8-gnu/drivers/acpi/pci_root.c
--- linux-libre-2.6.38-gnu/drivers/acpi/pci_root.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/acpi/pci_root.c	2011-06-02 21:35:11.000000000 -0400
@@ -564,7 +564,7 @@
 	/* Indicate support for various _OSC capabilities. */
 	if (pci_ext_cfg_avail(root->bus->self))
 		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-	if (pcie_aspm_enabled())
+	if (pcie_aspm_support_enabled())
 		flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
 			OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
 	if (pci_msi_enabled())
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/scan.c linux-libre-2.6.38.8-gnu/drivers/acpi/scan.c
--- linux-libre-2.6.38-gnu/drivers/acpi/scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/acpi/scan.c	2011-06-02 21:35:11.000000000 -0400
@@ -944,6 +944,10 @@
 	if (ACPI_SUCCESS(status))
 		device->flags.lockable = 1;
 
+	/* Power resources cannot be power manageable. */
+	if (device->device_type == ACPI_BUS_TYPE_POWER)
+		return 0;
+
 	/* Presence of _PS0|_PR0 indicates 'power manageable' */
 	status = acpi_get_handle(device->handle, "_PS0", &temp);
 	if (ACPI_FAILURE(status))
diff -druN linux-libre-2.6.38-gnu/drivers/ata/ahci.c linux-libre-2.6.38.8-gnu/drivers/ata/ahci.c
--- linux-libre-2.6.38-gnu/drivers/ata/ahci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ata/ahci.c	2011-06-02 21:35:11.000000000 -0400
@@ -150,7 +150,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
 				 AHCI_HFLAG_YES_NCQ),
-		.flags		= AHCI_FLAG_COMMON,
+		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -260,6 +260,7 @@
 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
@@ -383,6 +384,8 @@
 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
 	  .class_mask = 0xffffff,
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
+	{ PCI_DEVICE(0x1b4b, 0x9125),
+	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
 
 	/* Promise */
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libahci.c linux-libre-2.6.38.8-gnu/drivers/ata/libahci.c
--- linux-libre-2.6.38-gnu/drivers/ata/libahci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ata/libahci.c	2011-06-02 21:35:11.000000000 -0400
@@ -1897,7 +1897,17 @@
 	ahci_enable_fbs(ap);
 
 	pp->intr_mask |= PORT_IRQ_BAD_PMP;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+	/*
+	 * We must not change the port interrupt mask register if the
+	 * port is marked frozen, the value in pp->intr_mask will be
+	 * restored later when the port is thawed.
+	 *
+	 * Note that during initialization, the port is marked as
+	 * frozen since the irq handler is not yet registered.
+	 */
+	if (!(ap->pflags & ATA_PFLAG_FROZEN))
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 static void ahci_pmp_detach(struct ata_port *ap)
@@ -1913,7 +1923,10 @@
 	writel(cmd, port_mmio + PORT_CMD);
 
 	pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+	/* see comment above in ahci_pmp_attach() */
+	if (!(ap->pflags & ATA_PFLAG_FROZEN))
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 int ahci_port_resume(struct ata_port *ap)
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-core.c linux-libre-2.6.38.8-gnu/drivers/ata/libata-core.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ata/libata-core.c	2011-06-02 21:35:11.000000000 -0400
@@ -5479,8 +5479,8 @@
 	ap = kzalloc(sizeof(*ap), GFP_KERNEL);
 	if (!ap)
 		return NULL;
-	
-	ap->pflags |= ATA_PFLAG_INITIALIZING;
+
+	ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN;
 	ap->lock = &host->lock;
 	ap->print_id = -1;
 	ap->host = host;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-eh.c linux-libre-2.6.38.8-gnu/drivers/ata/libata-eh.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-eh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ata/libata-eh.c	2011-06-02 21:35:11.000000000 -0400
@@ -1618,7 +1618,7 @@
 	 * host links.  For disabled PMP links, only N bit is
 	 * considered as X bit is left at 1 for link plugging.
 	 */
-	if (link->lpm_policy != ATA_LPM_MAX_POWER)
+	if (link->lpm_policy > ATA_LPM_MAX_POWER)
 		hotplug_mask = 0;	/* hotplug doesn't work w/ LPM */
 	else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
 		hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
@@ -3276,6 +3276,7 @@
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
 	enum ata_lpm_policy old_policy = link->lpm_policy;
+	bool no_dipm = link->ap->flags & ATA_FLAG_NO_DIPM;
 	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
 	unsigned int err_mask;
 	int rc;
@@ -3292,7 +3293,7 @@
 	 */
 	ata_for_each_dev(dev, link, ENABLED) {
 		bool hipm = ata_id_has_hipm(dev->id);
-		bool dipm = ata_id_has_dipm(dev->id);
+		bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;
 
 		/* find the first enabled and LPM enabled devices */
 		if (!link_dev)
@@ -3349,7 +3350,8 @@
 
 	/* host config updated, enable DIPM if transitioning to MIN_POWER */
 	ata_for_each_dev(dev, link, ENABLED) {
-		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+		if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
+		    ata_id_has_dipm(dev->id)) {
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_ENABLE, SATA_DIPM);
 			if (err_mask && err_mask != AC_ERR_DEV) {
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_cmd64x.c linux-libre-2.6.38.8-gnu/drivers/ata/pata_cmd64x.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_cmd64x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ata/pata_cmd64x.c	2011-06-02 21:35:11.000000000 -0400
@@ -41,6 +41,9 @@
 enum {
 	CFR 		= 0x50,
 		CFR_INTR_CH0  = 0x04,
+	CNTRL		= 0x51,
+		CNTRL_CH0     = 0x04,
+		CNTRL_CH1     = 0x08,
 	CMDTIM 		= 0x52,
 	ARTTIM0 	= 0x53,
 	DRWTIM0 	= 0x54,
@@ -328,9 +331,19 @@
 			.port_ops = &cmd648_port_ops
 		}
 	};
-	const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
-	u8 mrdmode;
+	const struct ata_port_info *ppi[] = {
+		&cmd_info[id->driver_data],
+		&cmd_info[id->driver_data],
+		NULL
+	};
+	u8 mrdmode, reg;
 	int rc;
+	struct pci_dev *bridge = pdev->bus->self;
+	/* mobility split bridges don't report enabled ports correctly */
+	int port_ok = !(bridge && bridge->vendor ==
+			PCI_VENDOR_ID_MOBILITY_ELECTRONICS);
+	/* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */
+	int cntrl_ch0_ok = (id->driver_data != 0);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -341,11 +354,18 @@
 
 	if (pdev->device == PCI_DEVICE_ID_CMD_646) {
 		/* Does UDMA work ? */
-		if (pdev->revision > 4)
+		if (pdev->revision > 4) {
 			ppi[0] = &cmd_info[2];
+			ppi[1] = &cmd_info[2];
+		}
 		/* Early rev with other problems ? */
-		else if (pdev->revision == 1)
+		else if (pdev->revision == 1) {
 			ppi[0] = &cmd_info[3];
+			ppi[1] = &cmd_info[3];
+		}
+		/* revs 1,2 have no CNTRL_CH0 */
+		if (pdev->revision < 3)
+			cntrl_ch0_ok = 0;
 	}
 
 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
@@ -354,6 +374,20 @@
 	mrdmode |= 0x02;	/* Memory read line enable */
 	pci_write_config_byte(pdev, MRDMODE, mrdmode);
 
+	/* check for enabled ports */
+	pci_read_config_byte(pdev, CNTRL, &reg);
+	if (!port_ok)
+		dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
+	if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
+		dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
+		ppi[0] = &ata_dummy_port_info;
+
+	}
+	if (port_ok && !(reg & CNTRL_CH1)) {
+		dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
+		ppi[1] = &ata_dummy_port_info;
+	}
+
 	/* Force PIO 0 here.. */
 
 	/* PPC specific fixup copied from old driver */
diff -druN linux-libre-2.6.38-gnu/drivers/atm/solos-pci.c linux-libre-2.6.38.8-gnu/drivers/atm/solos-pci.c
--- linux-libre-2.6.38-gnu/drivers/atm/solos-pci.c	2012-03-24 00:59:52.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/atm/solos-pci.c	2012-03-25 07:09:09.000000000 -0400
@@ -163,7 +163,6 @@
 static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
-static void release_vccs(struct atm_dev *dev);
 static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -382,7 +381,6 @@
 	/* Anything but 'Showtime' is down */
 	if (strcmp(state_str, "Showtime")) {
 		atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
-		release_vccs(card->atmdev[port]);
 		dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
 		return 0;
 	}
@@ -695,7 +693,7 @@
 					      size);
 			}
 			if (atmdebug) {
-				dev_info(&card->dev->dev, "Received: device %d\n", port);
+				dev_info(&card->dev->dev, "Received: port %d\n", port);
 				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
 					 size, le16_to_cpu(header->vpi),
 					 le16_to_cpu(header->vci));
@@ -828,28 +826,6 @@
 	return num_found;
 }
 
-static void release_vccs(struct atm_dev *dev)
-{
-        int i;
-
-        write_lock_irq(&vcc_sklist_lock);
-        for (i = 0; i < VCC_HTABLE_SIZE; i++) {
-                struct hlist_head *head = &vcc_hash[i];
-                struct hlist_node *node, *tmp;
-                struct sock *s;
-                struct atm_vcc *vcc;
-
-                sk_for_each_safe(s, node, tmp, head) {
-                        vcc = atm_sk(s);
-                        if (vcc->dev == dev) {
-                                vcc_release_async(vcc, -EPIPE);
-                                sk_del_node_init(s);
-                        }
-                }
-        }
-        write_unlock_irq(&vcc_sklist_lock);
-}
-
 
 static int popen(struct atm_vcc *vcc)
 {
@@ -1016,8 +992,15 @@
 
 			/* Clean up and free oldskb now it's gone */
 			if (atmdebug) {
+				struct pkt_hdr *header = (void *)oldskb->data;
+				int size = le16_to_cpu(header->size);
+
+				skb_pull(oldskb, sizeof(*header));
 				dev_info(&card->dev->dev, "Transmitted: port %d\n",
 					 port);
+				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
+					 size, le16_to_cpu(header->vpi),
+					 le16_to_cpu(header->vci));
 				print_buffer(oldskb);
 			}
 
@@ -1260,7 +1243,7 @@
 		card->atmdev[i]->ci_range.vci_bits = 16;
 		card->atmdev[i]->dev_data = card;
 		card->atmdev[i]->phy_data = (void *)(unsigned long)i;
-		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
+		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
 
 		skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
 		if (!skb) {
diff -druN linux-libre-2.6.38-gnu/drivers/block/brd.c linux-libre-2.6.38.8-gnu/drivers/block/brd.c
--- linux-libre-2.6.38-gnu/drivers/block/brd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/brd.c	2011-06-02 21:35:11.000000000 -0400
@@ -552,7 +552,7 @@
 	struct kobject *kobj;
 
 	mutex_lock(&brd_devices_mutex);
-	brd = brd_init_one(dev & MINORMASK);
+	brd = brd_init_one(MINOR(dev) >> part_shift);
 	kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM);
 	mutex_unlock(&brd_devices_mutex);
 
@@ -585,15 +585,18 @@
 	if (max_part > 0)
 		part_shift = fls(max_part);
 
+	if ((1UL << part_shift) > DISK_MAX_PARTS)
+		return -EINVAL;
+
 	if (rd_nr > 1UL << (MINORBITS - part_shift))
 		return -EINVAL;
 
 	if (rd_nr) {
 		nr = rd_nr;
-		range = rd_nr;
+		range = rd_nr << part_shift;
 	} else {
 		nr = CONFIG_BLK_DEV_RAM_COUNT;
-		range = 1UL << (MINORBITS - part_shift);
+		range = 1UL << MINORBITS;
 	}
 
 	if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
@@ -632,7 +635,7 @@
 	unsigned long range;
 	struct brd_device *brd, *next;
 
-	range = rd_nr ? rd_nr :  1UL << (MINORBITS - part_shift);
+	range = rd_nr ? rd_nr << part_shift : 1UL << MINORBITS;
 
 	list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
 		brd_del_one(brd);
diff -druN linux-libre-2.6.38-gnu/drivers/block/cciss.h linux-libre-2.6.38.8-gnu/drivers/block/cciss.h
--- linux-libre-2.6.38-gnu/drivers/block/cciss.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/cciss.h	2011-06-02 21:35:11.000000000 -0400
@@ -222,6 +222,7 @@
 			h->ctlr, c->busaddr);
 #endif /* CCISS_DEBUG */
          writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
 	 h->commands_outstanding++;
 	 if ( h->commands_outstanding > h->max_outstanding)
 		h->max_outstanding = h->commands_outstanding;
diff -druN linux-libre-2.6.38-gnu/drivers/block/loop.c linux-libre-2.6.38.8-gnu/drivers/block/loop.c
--- linux-libre-2.6.38-gnu/drivers/block/loop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/loop.c	2011-06-02 21:35:11.000000000 -0400
@@ -1674,7 +1674,7 @@
 	struct kobject *kobj;
 
 	mutex_lock(&loop_devices_mutex);
-	lo = loop_init_one(dev & MINORMASK);
+	lo = loop_init_one(MINOR(dev) >> part_shift);
 	kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
 	mutex_unlock(&loop_devices_mutex);
 
@@ -1707,15 +1707,18 @@
 	if (max_part > 0)
 		part_shift = fls(max_part);
 
+	if ((1UL << part_shift) > DISK_MAX_PARTS)
+		return -EINVAL;
+
 	if (max_loop > 1UL << (MINORBITS - part_shift))
 		return -EINVAL;
 
 	if (max_loop) {
 		nr = max_loop;
-		range = max_loop;
+		range = max_loop << part_shift;
 	} else {
 		nr = 8;
-		range = 1UL << (MINORBITS - part_shift);
+		range = 1UL << MINORBITS;
 	}
 
 	if (register_blkdev(LOOP_MAJOR, "loop"))
@@ -1754,7 +1757,7 @@
 	unsigned long range;
 	struct loop_device *lo, *next;
 
-	range = max_loop ? max_loop :  1UL << (MINORBITS - part_shift);
+	range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
 
 	list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
 		loop_del_one(lo);
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pcd.c linux-libre-2.6.38.8-gnu/drivers/block/paride/pcd.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/paride/pcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -172,7 +172,8 @@
 static int pcd_open(struct cdrom_device_info *cdi, int purpose);
 static void pcd_release(struct cdrom_device_info *cdi);
 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+				     unsigned int clearing, int slot_nr);
 static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
 static int pcd_drive_reset(struct cdrom_device_info *cdi);
@@ -257,10 +258,11 @@
 	return ret;
 }
 
-static int pcd_block_media_changed(struct gendisk *disk)
+static unsigned int pcd_block_check_events(struct gendisk *disk,
+					   unsigned int clearing)
 {
 	struct pcd_unit *cd = disk->private_data;
-	return cdrom_media_changed(&cd->info);
+	return cdrom_check_events(&cd->info, clearing);
 }
 
 static const struct block_device_operations pcd_bdops = {
@@ -268,14 +270,14 @@
 	.open		= pcd_block_open,
 	.release	= pcd_block_release,
 	.ioctl		= pcd_block_ioctl,
-	.media_changed	= pcd_block_media_changed,
+	.check_events	= pcd_block_check_events,
 };
 
 static struct cdrom_device_ops pcd_dops = {
 	.open		= pcd_open,
 	.release	= pcd_release,
 	.drive_status	= pcd_drive_status,
-	.media_changed	= pcd_media_changed,
+	.check_events	= pcd_check_events,
 	.tray_move	= pcd_tray_move,
 	.lock_door	= pcd_lock_door,
 	.get_mcn	= pcd_get_mcn,
@@ -318,6 +320,8 @@
 		disk->first_minor = unit;
 		strcpy(disk->disk_name, cd->name);	/* umm... */
 		disk->fops = &pcd_bdops;
+		disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+		disk->events = DISK_EVENT_MEDIA_CHANGE;
 	}
 }
 
@@ -502,13 +506,14 @@
 
 #define DBMSG(msg)	((verbose>1)?(msg):NULL)
 
-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+				     unsigned int clearing, int slot_nr)
 {
 	struct pcd_unit *cd = cdi->handle;
 	int res = cd->changed;
 	if (res)
 		cd->changed = 0;
-	return res;
+	return res ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pd.c linux-libre-2.6.38.8-gnu/drivers/block/paride/pd.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/paride/pd.c	2011-06-02 21:35:11.000000000 -0400
@@ -794,7 +794,7 @@
 	return 0;
 }
 
-static int pd_check_media(struct gendisk *p)
+static unsigned int pd_check_events(struct gendisk *p, unsigned int clearing)
 {
 	struct pd_unit *disk = p->private_data;
 	int r;
@@ -803,7 +803,7 @@
 	pd_special_command(disk, pd_media_check);
 	r = disk->changed;
 	disk->changed = 0;
-	return r;
+	return r ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int pd_revalidate(struct gendisk *p)
@@ -822,7 +822,7 @@
 	.release	= pd_release,
 	.ioctl		= pd_ioctl,
 	.getgeo		= pd_getgeo,
-	.media_changed	= pd_check_media,
+	.check_events	= pd_check_events,
 	.revalidate_disk= pd_revalidate
 };
 
@@ -837,6 +837,7 @@
 	p->fops = &pd_fops;
 	p->major = major;
 	p->first_minor = (disk - pd) << PD_BITS;
+	p->events = DISK_EVENT_MEDIA_CHANGE;
 	disk->gd = p;
 	p->private_data = disk;
 	p->queue = pd_queue;
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pf.c linux-libre-2.6.38.8-gnu/drivers/block/paride/pf.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/block/paride/pf.c	2011-06-02 21:35:11.000000000 -0400
@@ -243,7 +243,8 @@
 static int pf_identify(struct pf_unit *pf);
 static void pf_lock(struct pf_unit *pf, int func);
 static void pf_eject(struct pf_unit *pf);
-static int pf_check_media(struct gendisk *disk);
+static unsigned int pf_check_events(struct gendisk *disk,
+				    unsigned int clearing);
 
 static char pf_scratch[512];	/* scratch block buffer */
 
@@ -270,7 +271,7 @@
 	.release	= pf_release,
 	.ioctl		= pf_ioctl,
 	.getgeo		= pf_getgeo,
-	.media_changed	= pf_check_media,
+	.check_events	= pf_check_events,
 };
 
 static void __init pf_init_units(void)
@@ -293,6 +294,7 @@
 		disk->first_minor = unit;
 		strcpy(disk->disk_name, pf->name);
 		disk->fops = &pf_fops;
+		disk->events = DISK_EVENT_MEDIA_CHANGE;
 		if (!(*drives[unit])[D_PRT])
 			pf_drive_count++;
 	}
@@ -377,9 +379,9 @@
 
 }
 
-static int pf_check_media(struct gendisk *disk)
+static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing)
 {
-	return 1;
+	return DISK_EVENT_MEDIA_CHANGE;
 }
 
 static inline int status_reg(struct pf_unit *pf)
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/btusb.c linux-libre-2.6.38.8-gnu/drivers/bluetooth/btusb.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/btusb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/bluetooth/btusb.c	2011-06-02 21:35:11.000000000 -0400
@@ -71,6 +71,9 @@
 	/* Apple MacBookAir3,1, MacBookAir3,2 */
 	{ USB_DEVICE(0x05ac, 0x821b) },
 
+	/* Apple MacBookPro8,2 */
+	{ USB_DEVICE(0x05ac, 0x821a) },
+
 	/* AVM BlueFRITZ! USB v2.0 */
 	{ USB_DEVICE(0x057c, 0x3800) },
 
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/cdrom.c linux-libre-2.6.38.8-gnu/drivers/cdrom/cdrom.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/cdrom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cdrom/cdrom.c	2011-06-02 21:35:11.000000000 -0400
@@ -986,6 +986,9 @@
 
 	cdinfo(CD_OPEN, "entering cdrom_open\n"); 
 
+	/* open is event synchronization point, check events first */
+	check_disk_change(bdev);
+
 	/* if this was a O_NONBLOCK open and we should honor the flags,
 	 * do a quick open without drive/disc integrity checks. */
 	cdi->use_count++;
@@ -1012,9 +1015,6 @@
 
 	cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
 			cdi->name, cdi->use_count);
-	/* Do this on open.  Don't wait for mount, because they might
-	    not be mounting, but opening with O_NONBLOCK */
-	check_disk_change(bdev);
 	return 0;
 err_release:
 	if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/gdrom.c linux-libre-2.6.38.8-gnu/drivers/cdrom/gdrom.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/gdrom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cdrom/gdrom.c	2011-06-02 21:35:11.000000000 -0400
@@ -395,10 +395,12 @@
 	return CDS_NO_INFO;
 }
 
-static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore)
+static unsigned int gdrom_check_events(struct cdrom_device_info *cd_info,
+				       unsigned int clearing, int ignore)
 {
 	/* check the sense key */
-	return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60;
+	return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60 ?
+		DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 /* reset the G1 bus */
@@ -483,7 +485,7 @@
 	.open			= gdrom_open,
 	.release		= gdrom_release,
 	.drive_status		= gdrom_drivestatus,
-	.media_changed		= gdrom_mediachanged,
+	.check_events		= gdrom_check_events,
 	.get_last_session	= gdrom_get_last_session,
 	.reset			= gdrom_hardreset,
 	.audio_ioctl		= gdrom_audio_ioctl,
@@ -509,9 +511,10 @@
 	return 0;
 }
 
-static int gdrom_bdops_mediachanged(struct gendisk *disk)
+static unsigned int gdrom_bdops_check_events(struct gendisk *disk,
+					     unsigned int clearing)
 {
-	return cdrom_media_changed(gd.cd_info);
+	return cdrom_check_events(gd.cd_info, clearing);
 }
 
 static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
@@ -530,7 +533,7 @@
 	.owner			= THIS_MODULE,
 	.open			= gdrom_bdops_open,
 	.release		= gdrom_bdops_release,
-	.media_changed		= gdrom_bdops_mediachanged,
+	.check_events		= gdrom_bdops_check_events,
 	.ioctl			= gdrom_bdops_ioctl,
 };
 
@@ -800,6 +803,7 @@
 		goto probe_fail_cdrom_register;
 	}
 	gd.disk->fops = &gdrom_bdops;
+	gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
 	/* latch on to the interrupt */
 	err = gdrom_set_interrupt_handlers();
 	if (err)
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/viocd.c linux-libre-2.6.38.8-gnu/drivers/cdrom/viocd.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/viocd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cdrom/viocd.c	2011-06-02 21:35:11.000000000 -0400
@@ -186,10 +186,11 @@
 	return ret;
 }
 
-static int viocd_blk_media_changed(struct gendisk *disk)
+static unsigned int viocd_blk_check_events(struct gendisk *disk,
+					   unsigned int clearing)
 {
 	struct disk_info *di = disk->private_data;
-	return cdrom_media_changed(&di->viocd_info);
+	return cdrom_check_events(&di->viocd_info, clearing);
 }
 
 static const struct block_device_operations viocd_fops = {
@@ -197,7 +198,7 @@
 	.open =			viocd_blk_open,
 	.release =		viocd_blk_release,
 	.ioctl =		viocd_blk_ioctl,
-	.media_changed =	viocd_blk_media_changed,
+	.check_events =		viocd_blk_check_events,
 };
 
 static int viocd_open(struct cdrom_device_info *cdi, int purpose)
@@ -320,7 +321,8 @@
 	}
 }
 
-static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static unsigned int viocd_check_events(struct cdrom_device_info *cdi,
+				       unsigned int clearing, int disc_nr)
 {
 	struct viocd_waitevent we;
 	HvLpEvent_Rc hvrc;
@@ -340,7 +342,7 @@
 	if (hvrc != 0) {
 		pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
 			   (int)hvrc);
-		return -EIO;
+		return 0;
 	}
 
 	wait_for_completion(&we.com);
@@ -354,7 +356,7 @@
 		return 0;
 	}
 
-	return we.changed;
+	return we.changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int viocd_lock_door(struct cdrom_device_info *cdi, int locking)
@@ -550,7 +552,7 @@
 static struct cdrom_device_ops viocd_dops = {
 	.open = viocd_open,
 	.release = viocd_release,
-	.media_changed = viocd_media_changed,
+	.check_events = viocd_check_events,
 	.lock_door = viocd_lock_door,
 	.generic_packet = viocd_packet,
 	.audio_ioctl = viocd_audio_ioctl,
@@ -623,7 +625,9 @@
 	blk_queue_max_hw_sectors(q, 4096 / 512);
 	gendisk->queue = q;
 	gendisk->fops = &viocd_fops;
-	gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
+	gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
+			 GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+	gendisk->events = DISK_EVENT_MEDIA_CHANGE;
 	set_capacity(gendisk, 0);
 	gendisk->private_data = d;
 	d->viocd_disk = gendisk;
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/generic.c linux-libre-2.6.38.8-gnu/drivers/char/agp/generic.c
--- linux-libre-2.6.38-gnu/drivers/char/agp/generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/char/agp/generic.c	2011-06-02 21:35:11.000000000 -0400
@@ -115,6 +115,9 @@
 	struct agp_memory *new;
 	unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
 
+	if (INT_MAX/sizeof(struct page *) < num_agp_pages)
+		return NULL;
+
 	new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
 	if (new == NULL)
 		return NULL;
@@ -234,11 +237,14 @@
 	int scratch_pages;
 	struct agp_memory *new;
 	size_t i;
+	int cur_memory;
 
 	if (!bridge)
 		return NULL;
 
-	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
+	cur_memory = atomic_read(&bridge->current_memory_agp);
+	if ((cur_memory + page_count > bridge->max_memory_agp) ||
+	    (cur_memory + page_count < page_count))
 		return NULL;
 
 	if (type >= AGP_USER_TYPES) {
@@ -1089,8 +1095,8 @@
 		return -EINVAL;
 	}
 
-	/* AK: could wrap */
-	if ((pg_start + mem->page_count) > num_entries)
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
 		return -EINVAL;
 
 	j = pg_start;
@@ -1124,7 +1130,7 @@
 {
 	size_t i;
 	struct agp_bridge_data *bridge;
-	int mask_type;
+	int mask_type, num_entries;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -1136,6 +1142,11 @@
 	if (type != mem->type)
 		return -EINVAL;
 
+	num_entries = agp_num_entries();
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
+		return -EINVAL;
+
 	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
 	if (mask_type != 0) {
 		/* The generic routines know nothing of memory types */
diff -druN linux-libre-2.6.38-gnu/drivers/char/i8k.c linux-libre-2.6.38.8-gnu/drivers/char/i8k.c
--- linux-libre-2.6.38-gnu/drivers/char/i8k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/char/i8k.c	2011-06-02 21:35:11.000000000 -0400
@@ -139,8 +139,8 @@
 		"movl %%edi,20(%%rax)\n\t"
 		"popq %%rdx\n\t"
 		"movl %%edx,0(%%rax)\n\t"
-		"lahf\n\t"
-		"shrl $8,%%eax\n\t"
+		"pushfq\n\t"
+		"popq %%rax\n\t"
 		"andl $1,%%eax\n"
 		:"=a"(rc)
 		:    "a"(regs)
diff -druN linux-libre-2.6.38-gnu/drivers/char/tpm/tpm.c linux-libre-2.6.38.8-gnu/drivers/char/tpm/tpm.c
--- linux-libre-2.6.38-gnu/drivers/char/tpm/tpm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/char/tpm/tpm.c	2011-06-02 21:35:11.000000000 -0400
@@ -980,7 +980,7 @@
 		return -EBUSY;
 	}
 
-	chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
 	if (chip->data_buffer == NULL) {
 		clear_bit(0, &chip->is_open);
 		put_device(chip->dev);
diff -druN linux-libre-2.6.38-gnu/drivers/char/virtio_console.c linux-libre-2.6.38.8-gnu/drivers/char/virtio_console.c
--- linux-libre-2.6.38-gnu/drivers/char/virtio_console.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/char/virtio_console.c	2011-06-02 21:35:11.000000000 -0400
@@ -1280,18 +1280,7 @@
 		spin_lock_irq(&pdrvdata_lock);
 		list_del(&port->cons.list);
 		spin_unlock_irq(&pdrvdata_lock);
-#if 0
-		/*
-		 * hvc_remove() not called as removing one hvc port
-		 * results in other hvc ports getting frozen.
-		 *
-		 * Once this is resolved in hvc, this functionality
-		 * will be enabled.  Till that is done, the -EPIPE
-		 * return from get_chars() above will help
-		 * hvc_console.c to clean up on ports we remove here.
-		 */
 		hvc_remove(port->cons.hvc);
-#endif
 	}
 
 	/* Remove unused data this port might have received. */
diff -druN linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq.c linux-libre-2.6.38.8-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cpufreq/cpufreq.c	2011-06-02 21:35:11.000000000 -0400
@@ -1207,12 +1207,28 @@
 		cpufreq_driver->exit(data);
 	unlock_policy_rwsem_write(cpu);
 
+	cpufreq_debug_enable_ratelimit();
+
+#ifdef CONFIG_HOTPLUG_CPU
+	/* when the CPU which is the parent of the kobj is hotplugged
+	 * offline, check for siblings, and create cpufreq sysfs interface
+	 * and symlinks
+	 */
+	if (unlikely(cpumask_weight(data->cpus) > 1)) {
+		/* first sibling now owns the new sysfs dir */
+		cpumask_clear_cpu(cpu, data->cpus);
+		cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus)));
+
+		/* finally remove our own symlink */
+		lock_policy_rwsem_write(cpu);
+		__cpufreq_remove_dev(sys_dev);
+	}
+#endif
+
 	free_cpumask_var(data->related_cpus);
 	free_cpumask_var(data->cpus);
 	kfree(data);
-	per_cpu(cpufreq_cpu_data, cpu) = NULL;
 
-	cpufreq_debug_enable_ratelimit();
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_stats.c linux-libre-2.6.38.8-gnu/drivers/cpufreq/cpufreq_stats.c
--- linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_stats.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cpufreq/cpufreq_stats.c	2011-06-02 21:35:11.000000000 -0400
@@ -165,17 +165,27 @@
 	return -1;
 }
 
+/* should be called late in the CPU removal sequence so that the stats
+ * memory is still available in case someone tries to use it.
+ */
 static void cpufreq_stats_free_table(unsigned int cpu)
 {
 	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
-	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-	if (policy && policy->cpu == cpu)
-		sysfs_remove_group(&policy->kobj, &stats_attr_group);
 	if (stat) {
 		kfree(stat->time_in_state);
 		kfree(stat);
 	}
 	per_cpu(cpufreq_stats_table, cpu) = NULL;
+}
+
+/* must be called early in the CPU removal sequence (before
+ * cpufreq_remove_dev) so that policy is still valid.
+ */
+static void cpufreq_stats_free_sysfs(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	if (policy && policy->cpu == cpu)
+		sysfs_remove_group(&policy->kobj, &stats_attr_group);
 	if (policy)
 		cpufreq_cpu_put(policy);
 }
@@ -316,6 +326,9 @@
 	case CPU_ONLINE_FROZEN:
 		cpufreq_update_policy(cpu);
 		break;
+	case CPU_DOWN_PREPARE:
+		cpufreq_stats_free_sysfs(cpu);
+		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 		cpufreq_stats_free_table(cpu);
@@ -324,9 +337,11 @@
 	return NOTIFY_OK;
 }
 
+/* priority=1 so this will get called before cpufreq_remove_dev */
 static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
 {
 	.notifier_call = cpufreq_stat_cpu_callback,
+	.priority = 1,
 };
 
 static struct notifier_block notifier_policy_block = {
diff -druN linux-libre-2.6.38-gnu/drivers/cpuidle/governors/menu.c linux-libre-2.6.38.8-gnu/drivers/cpuidle/governors/menu.c
--- linux-libre-2.6.38-gnu/drivers/cpuidle/governors/menu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/cpuidle/governors/menu.c	2011-06-02 21:35:11.000000000 -0400
@@ -237,6 +237,7 @@
 	unsigned int power_usage = -1;
 	int i;
 	int multiplier;
+	struct timespec t;
 
 	if (data->needs_update) {
 		menu_update(dev);
@@ -251,8 +252,9 @@
 		return 0;
 
 	/* determine the expected residency time, round up */
+	t = ktime_to_timespec(tick_nohz_get_sleep_length());
 	data->expected_us =
-	    DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000);
+		t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
 
 
 	data->bucket = which_bucket(data->expected_us);
diff -druN linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.c linux-libre-2.6.38.8-gnu/drivers/edac/amd64_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/edac/amd64_edac.c	2011-06-02 21:35:11.000000000 -0400
@@ -2765,7 +2765,7 @@
 	mcis	  = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
 	ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
 	if (!(mcis && ecc_stngs))
-		goto err_ret;
+		goto err_free;
 
 	msrs = msrs_alloc();
 	if (!msrs)
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/ohci.c linux-libre-2.6.38.8-gnu/drivers/firewire/ohci.c
--- linux-libre-2.6.38-gnu/drivers/firewire/ohci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/firewire/ohci.c	2011-06-02 21:35:11.000000000 -0400
@@ -2163,7 +2163,6 @@
 {
 	struct fw_ohci *ohci;
 	unsigned long flags;
-	int ret = -EBUSY;
 	__be32 *next_config_rom;
 	dma_addr_t uninitialized_var(next_config_rom_bus);
 
@@ -2204,22 +2203,37 @@
 
 	spin_lock_irqsave(&ohci->lock, flags);
 
+	/*
+	 * If there is not an already pending config_rom update,
+	 * push our new allocation into the ohci->next_config_rom
+	 * and then mark the local variable as null so that we
+	 * won't deallocate the new buffer.
+	 *
+	 * OTOH, if there is a pending config_rom update, just
+	 * use that buffer with the new config_rom data, and
+	 * let this routine free the unused DMA allocation.
+	 */
+
 	if (ohci->next_config_rom == NULL) {
 		ohci->next_config_rom = next_config_rom;
 		ohci->next_config_rom_bus = next_config_rom_bus;
+		next_config_rom = NULL;
+	}
 
-		copy_config_rom(ohci->next_config_rom, config_rom, length);
+	copy_config_rom(ohci->next_config_rom, config_rom, length);
 
-		ohci->next_header = config_rom[0];
-		ohci->next_config_rom[0] = 0;
+	ohci->next_header = config_rom[0];
+	ohci->next_config_rom[0] = 0;
 
-		reg_write(ohci, OHCI1394_ConfigROMmap,
-			  ohci->next_config_rom_bus);
-		ret = 0;
-	}
+	reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
 
 	spin_unlock_irqrestore(&ohci->lock, flags);
 
+	/* If we didn't use the DMA allocation, delete it. */
+	if (next_config_rom != NULL)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  next_config_rom, next_config_rom_bus);
+
 	/*
 	 * Now initiate a bus reset to have the changes take
 	 * effect. We clean up the old config rom memory and DMA
@@ -2227,13 +2241,10 @@
 	 * controller could need to access it before the bus reset
 	 * takes effect.
 	 */
-	if (ret == 0)
-		fw_schedule_bus_reset(&ohci->card, true, true);
-	else
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  next_config_rom, next_config_rom_bus);
 
-	return ret;
+	fw_schedule_bus_reset(&ohci->card, true, true);
+
+	return 0;
 }
 
 static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/dcdbas.c linux-libre-2.6.38.8-gnu/drivers/firmware/dcdbas.c
--- linux-libre-2.6.38-gnu/drivers/firmware/dcdbas.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/firmware/dcdbas.c	2011-06-02 21:35:11.000000000 -0400
@@ -268,8 +268,10 @@
 	}
 
 	/* generate SMI */
+	/* inb to force posted write through and make SMI happen now */
 	asm volatile (
-		"outb %b0,%w1"
+		"outb %b0,%w1\n"
+		"inb %w1"
 		: /* no output args */
 		: "a" (smi_cmd->command_code),
 		  "d" (smi_cmd->command_address),
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_crtc.c	2011-06-02 21:35:11.000000000 -0400
@@ -1073,6 +1073,9 @@
 	uint32_t __user *encoder_id;
 	struct drm_mode_group *mode_group;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	/*
@@ -1244,6 +1247,9 @@
 	struct drm_mode_object *obj;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
@@ -1312,6 +1318,9 @@
 	uint64_t __user *prop_values;
 	uint32_t __user *encoder_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
@@ -1431,6 +1440,9 @@
 	struct drm_encoder *encoder;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, enc_resp->encoder_id,
 				   DRM_MODE_OBJECT_ENCODER);
@@ -1486,6 +1498,9 @@
 	int ret = 0;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_req->crtc_id,
 				   DRM_MODE_OBJECT_CRTC);
@@ -1603,6 +1618,9 @@
 	struct drm_crtc *crtc;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	if (!req->flags) {
 		DRM_ERROR("no operation set\n");
 		return -EINVAL;
@@ -1667,6 +1685,9 @@
 	struct drm_framebuffer *fb;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
 		DRM_ERROR("mode new framebuffer width not within limits\n");
 		return -EINVAL;
@@ -1724,6 +1745,9 @@
 	int ret = 0;
 	int found = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
 	/* TODO check that we realy get a framebuffer back. */
@@ -1780,6 +1804,9 @@
 	struct drm_framebuffer *fb;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
 	if (!obj) {
@@ -1813,6 +1840,9 @@
 	int num_clips;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
 	if (!obj) {
@@ -1996,6 +2026,9 @@
 	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2042,6 +2075,9 @@
 	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2211,6 +2247,9 @@
 	uint64_t __user *values_ptr;
 	uint32_t __user *blob_length_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
 	if (!obj) {
@@ -2333,6 +2372,9 @@
 	int ret = 0;
 	void *blob_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
 	if (!obj) {
@@ -2393,6 +2435,9 @@
 	int ret = -EINVAL;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2509,6 +2554,9 @@
 	int size;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
@@ -2560,6 +2608,9 @@
 	int size;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_gem.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_gem.c	2011-06-02 21:35:11.000000000 -0400
@@ -498,11 +498,12 @@
 void drm_gem_vm_close(struct vm_area_struct *vma)
 {
 	struct drm_gem_object *obj = vma->vm_private_data;
+	struct drm_device *dev = obj->dev;
 
-	mutex_lock(&obj->dev->struct_mutex);
+	mutex_lock(&dev->struct_mutex);
 	drm_vm_close_locked(vma);
 	drm_gem_object_unreference(obj);
-	mutex_unlock(&obj->dev->struct_mutex);
+	mutex_unlock(&dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_irq.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_irq.c	2011-06-02 21:35:11.000000000 -0400
@@ -942,11 +942,34 @@
 
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
+	struct drm_pending_vblank_event *e, *t;
+	struct timeval now;
 	unsigned long irqflags;
+	unsigned int seq;
 
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	vblank_disable_and_save(dev, crtc);
 	DRM_WAKEUP(&dev->vbl_queue[crtc]);
+
+	/* Send any queued vblank events, lest the natives grow disquiet */
+	seq = drm_vblank_count_and_time(dev, crtc, &now);
+	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
+		if (e->pipe != crtc)
+			continue;
+		DRM_DEBUG("Sending premature vblank event on disable: \
+			  wanted %d, current %d\n",
+			  e->event.sequence, seq);
+
+		e->event.sequence = seq;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		drm_vblank_put(dev, e->pipe);
+		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+						 e->event.sequence);
+	}
+
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/drm_sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -158,8 +158,15 @@
 {
 	struct drm_connector *connector = to_drm_connector(device);
 	enum drm_connector_status status;
+	int ret;
+
+	ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex);
+	if (ret)
+		return ret;
 
 	status = connector->funcs->detect(connector, true);
+	mutex_unlock(&connector->dev->mode_config.mutex);
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			drm_get_connector_status_name(status));
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_gem.c	2011-06-02 21:35:11.000000000 -0400
@@ -1749,8 +1749,10 @@
 		return;
 
 	spin_lock(&file_priv->mm.lock);
-	list_del(&request->client_list);
-	request->file_priv = NULL;
+	if (request->file_priv) {
+		list_del(&request->client_list);
+		request->file_priv = NULL;
+	}
 	spin_unlock(&file_priv->mm.lock);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-06-02 21:35:11.000000000 -0400
@@ -388,6 +388,10 @@
 		uint32_t __iomem *reloc_entry;
 		void __iomem *reloc_page;
 
+		/* We can't wait for rendering with pagefaults disabled */
+		if (obj->active && in_atomic())
+			return -EFAULT;
+
 		ret = i915_gem_object_set_to_gtt_domain(obj, 1);
 		if (ret)
 			return ret;
@@ -461,15 +465,24 @@
 			     struct list_head *objects)
 {
 	struct drm_i915_gem_object *obj;
-	int ret;
+	int ret = 0;
 
+	/* This is the fast path and we cannot handle a pagefault whilst
+	 * holding the struct mutex lest the user pass in the relocations
+	 * contained within a mmaped bo. For in such a case we, the page
+	 * fault handler would call i915_gem_fault() and we would try to
+	 * acquire the struct mutex again. Obviously this is bad and so
+	 * lockdep complains vehemently.
+	 */
+	pagefault_disable();
 	list_for_each_entry(obj, objects, exec_list) {
 		ret = i915_gem_execbuffer_relocate_object(obj, eb);
 		if (ret)
-			return ret;
+			break;
 	}
+	pagefault_enable();
 
-	return 0;
+	return ret;
 }
 
 static int
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_irq.c	2011-06-02 21:35:11.000000000 -0400
@@ -1377,7 +1377,12 @@
 	else
 		i915_enable_pipestat(dev_priv, pipe,
 				     PIPE_VBLANK_INTERRUPT_ENABLE);
+
+	/* maintain vblank delivery even in deep C-states */
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
 	return 0;
 }
 
@@ -1390,6 +1395,10 @@
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM,
+			   INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS);
+
 	if (HAS_PCH_SPLIT(dev))
 		ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
 					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/i915_reg.h	2011-06-02 21:35:11.000000000 -0400
@@ -405,9 +405,12 @@
 #define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
 #define   INSTPM_SELF_EN (1<<12) /* 915GM only */
+#define   INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts
+					will not assert AGPBUSY# and will only
+					be delivered when out of C3. */
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8
-#define FW_BLC2	 	0x020dc
+#define FW_BLC2		0x020dc
 #define FW_BLC_SELF	0x020e0 /* 915+ only */
 #define   FW_BLC_SELF_EN_MASK      (1<<31)
 #define   FW_BLC_SELF_FIFO_MASK    (1<<16) /* 945 only */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_display.c	2011-06-02 21:35:11.000000000 -0400
@@ -5630,36 +5630,6 @@
 	return ret;
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	/* Reset flags back to the 'unknown' status so that they
-	 * will be correctly set on the initial modeset.
-	 */
-	intel_crtc->dpms_mode = -1;
-}
-
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.dpms = intel_crtc_dpms,
-	.mode_fixup = intel_crtc_mode_fixup,
-	.mode_set = intel_crtc_mode_set,
-	.mode_set_base = intel_pipe_set_base,
-	.mode_set_base_atomic = intel_pipe_set_base_atomic,
-	.load_lut = intel_crtc_load_lut,
-	.disable = intel_crtc_disable,
-};
-
-static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.reset = intel_crtc_reset,
-	.cursor_set = intel_crtc_cursor_set,
-	.cursor_move = intel_crtc_cursor_move,
-	.gamma_set = intel_crtc_gamma_set,
-	.set_config = drm_crtc_helper_set_config,
-	.destroy = intel_crtc_destroy,
-	.page_flip = intel_crtc_page_flip,
-};
-
 static void intel_sanitize_modesetting(struct drm_device *dev,
 				       int pipe, int plane)
 {
@@ -5710,6 +5680,42 @@
 	}
 }
 
+static void intel_crtc_reset(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	/* Reset flags back to the 'unknown' status so that they
+	 * will be correctly set on the initial modeset.
+	 */
+	intel_crtc->dpms_mode = -1;
+
+	/* We need to fix up any BIOS configuration that conflicts with
+	 * our expectations.
+	 */
+	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
+}
+
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+	.dpms = intel_crtc_dpms,
+	.mode_fixup = intel_crtc_mode_fixup,
+	.mode_set = intel_crtc_mode_set,
+	.mode_set_base = intel_pipe_set_base,
+	.mode_set_base_atomic = intel_pipe_set_base_atomic,
+	.load_lut = intel_crtc_load_lut,
+	.disable = intel_crtc_disable,
+};
+
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+	.reset = intel_crtc_reset,
+	.cursor_set = intel_crtc_cursor_set,
+	.cursor_move = intel_crtc_cursor_move,
+	.gamma_set = intel_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = intel_crtc_destroy,
+	.page_flip = intel_crtc_page_flip,
+};
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -5759,8 +5765,6 @@
 
 	setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
 		    (unsigned long)intel_crtc);
-
-	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -6001,8 +6005,10 @@
 		return ERR_PTR(-ENOENT);
 
 	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-	if (!intel_fb)
+	if (!intel_fb) {
+		drm_gem_object_unreference_unlocked(&obj->base);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
 	if (ret) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_dp.c	2011-06-02 21:35:11.000000000 -0400
@@ -1455,7 +1455,8 @@
 
 	if (!HAS_PCH_CPT(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+
 		/* Hardware workaround: leaving our transcoder select
 		 * set to transcoder B while it's off will prevent the
 		 * corresponding HDMI output on transcoder A.
@@ -1470,7 +1471,19 @@
 		/* Changes to enable or select take place the vblank
 		 * after being written.
 		 */
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
+		if (crtc == NULL) {
+			/* We can arrive here never having been attached
+			 * to a CRTC, for instance, due to inheriting
+			 * random state from the BIOS.
+			 *
+			 * If the pipe is not running, play safe and
+			 * wait for the clocks to stabilise before
+			 * continuing.
+			 */
+			POSTING_READ(intel_dp->output_reg);
+			msleep(50);
+		} else
+			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
 	}
 
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_lvds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_lvds.c	2011-06-02 21:35:11.000000000 -0400
@@ -540,6 +540,9 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
+		return NOTIFY_OK;
+
 	/*
 	 * check and update the status of LVDS connector after receiving
 	 * the LID nofication event.
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-06-02 21:35:11.000000000 -0400
@@ -684,12 +684,37 @@
 static bool
 bsd_ring_get_irq(struct intel_ring_buffer *ring)
 {
-	return ring_get_irq(ring, GT_BSD_USER_INTERRUPT);
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!dev->irq_enabled)
+		return false;
+
+	spin_lock(&ring->irq_lock);
+	if (ring->irq_refcount++ == 0) {
+		if (IS_G4X(dev))
+			i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
+		else
+			ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
+	}
+	spin_unlock(&ring->irq_lock);
+
+	return true;
 }
 static void
 bsd_ring_put_irq(struct intel_ring_buffer *ring)
 {
-	ring_put_irq(ring, GT_BSD_USER_INTERRUPT);
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	spin_lock(&ring->irq_lock);
+	if (--ring->irq_refcount == 0) {
+		if (IS_G4X(dev))
+			i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
+		else
+			ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
+	}
+	spin_unlock(&ring->irq_lock);
 }
 
 static int
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_tv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/i915/intel_tv.c	2011-06-02 21:35:11.000000000 -0400
@@ -1380,7 +1380,9 @@
 	if (type < 0)
 		return connector_status_disconnected;
 
+	intel_tv->type = type;
 	intel_tv_find_better_format(connector);
+
 	return connector_status_connected;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/Kconfig linux-libre-2.6.38.8-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -24,6 +24,7 @@
 	depends on DRM
 	select FB
 	select FRAMEBUFFER_CONSOLE if !EXPERT
+	select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
 	help
 	  FB and CRTC helpers for KMS drivers.
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-06-02 21:35:11.000000000 -0400
@@ -181,13 +181,13 @@
 		OUT_RING  (chan, 0);
 	}
 
-	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
+	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3, 0xffffffff);
 	FIRE_RING(chan);
 	mutex_unlock(&chan->mutex);
 
 	ret = -EBUSY;
 	for (i = 0; i < 100000; i++) {
-		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) {
+		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3)) {
 			ret = 0;
 			break;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2011-06-02 21:35:11.000000000 -0400
@@ -61,8 +61,8 @@
 			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 		} else if (a2 > a1) {
-			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
-			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
 		}
 		break;
 	case RMX_FULL:
@@ -531,6 +531,9 @@
 			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
 			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+		if (rdev->family < CHIP_RV770)
+			pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
 	} else {
 		pll->flags |= RADEON_PLL_LEGACY;
 
@@ -559,7 +562,6 @@
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 				if (ss_enabled) {
 					if (ss->refdiv) {
-						pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
 						pll->flags |= RADEON_PLL_USE_REF_DIV;
 						pll->reference_div = ss->refdiv;
 						if (ASIC_IS_AVIVO(rdev))
@@ -957,7 +959,11 @@
 	/* adjust pixel clock as needed */
 	adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss);
 
-	if (ASIC_IS_AVIVO(rdev))
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+		/* TV seems to prefer the legacy algo on some boards */
+		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+					  &ref_div, &post_div);
+	else if (ASIC_IS_AVIVO(rdev))
 		radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
 					 &ref_div, &post_div);
 	else
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atom.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/atom.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/atom.c	2011-06-02 21:35:11.000000000 -0400
@@ -32,6 +32,7 @@
 #include "atom.h"
 #include "atom-names.h"
 #include "atom-bits.h"
+#include "radeon.h"
 
 #define ATOM_COND_ABOVE		0
 #define ATOM_COND_ABOVEOREQUAL	1
@@ -101,7 +102,9 @@
 static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
 				 uint32_t index, uint32_t data)
 {
+	struct radeon_device *rdev = ctx->card->dev->dev_private;
 	uint32_t temp = 0xCDCDCDCD;
+
 	while (1)
 		switch (CU8(base)) {
 		case ATOM_IIO_NOP:
@@ -112,7 +115,8 @@
 			base += 3;
 			break;
 		case ATOM_IIO_WRITE:
-			(void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
+			if (rdev->family == CHIP_RV515)
+				(void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
 			ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
 			base += 3;
 			break;
@@ -131,7 +135,7 @@
 		case ATOM_IIO_MOVE_INDEX:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((index >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -141,7 +145,7 @@
 		case ATOM_IIO_MOVE_DATA:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((data >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -151,7 +155,7 @@
 		case ATOM_IIO_MOVE_ATTR:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((ctx->
 			      io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/evergreen.c	2011-06-02 21:35:11.000000000 -0400
@@ -869,9 +869,15 @@
 		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
 		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
 		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
-	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
-	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
-	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	if (rdev->flags & RADEON_IS_IGP) {
+		WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp);
+		WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp);
+		WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp);
+	} else {
+		WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+		WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+		WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	}
 	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
@@ -1579,7 +1585,7 @@
 	u32 sq_stack_resource_mgmt_2;
 	u32 sq_stack_resource_mgmt_3;
 	u32 vgt_cache_invalidation;
-	u32 hdp_host_path_cntl;
+	u32 hdp_host_path_cntl, tmp;
 	int i, j, num_shader_engines, ps_thread_count;
 
 	switch (rdev->family) {
@@ -2139,6 +2145,10 @@
 	for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
 		WREG32(i, 0);
 
+	tmp = RREG32(HDP_MISC_CNTL);
+	tmp |= HDP_FLUSH_INVALIDATE_CACHE;
+	WREG32(HDP_MISC_CNTL, tmp);
+
 	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
 	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
 
@@ -2930,11 +2940,6 @@
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
-	/* XXX: ontario has problems blitting to gart at the moment */
-	if (rdev->family == CHIP_PALM) {
-		rdev->asic->copy = NULL;
-		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-	}
 
 	/* allocate wb buffer */
 	r = radeon_wb_init(rdev);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreend.h linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreend.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/evergreend.h	2011-06-02 21:35:11.000000000 -0400
@@ -64,6 +64,8 @@
 #define GB_BACKEND_MAP  				0x98FC
 #define DMIF_ADDR_CONFIG  				0xBD4
 #define HDP_ADDR_CONFIG  				0x2F48
+#define HDP_MISC_CNTL  					0x2F4C
+#define		HDP_FLUSH_INVALIDATE_CACHE      	(1 << 0)
 
 #define	CC_SYS_RB_BACKEND_DISABLE			0x3F88
 #define	GC_USER_RB_BACKEND_DISABLE			0x9B7C
@@ -221,6 +223,11 @@
 #define	MC_VM_MD_L1_TLB0_CNTL				0x2654
 #define	MC_VM_MD_L1_TLB1_CNTL				0x2658
 #define	MC_VM_MD_L1_TLB2_CNTL				0x265C
+
+#define	FUS_MC_VM_MD_L1_TLB0_CNTL			0x265C
+#define	FUS_MC_VM_MD_L1_TLB1_CNTL			0x2660
+#define	FUS_MC_VM_MD_L1_TLB2_CNTL			0x2664
+
 #define	MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR		0x203C
 #define	MC_VM_SYSTEM_APERTURE_HIGH_ADDR			0x2038
 #define	MC_VM_SYSTEM_APERTURE_LOW_ADDR			0x2034
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2011-06-02 21:35:11.000000000 -0400
@@ -782,6 +782,7 @@
 	.hpd_fini = &evergreen_hpd_fini,
 	.hpd_sense = &evergreen_hpd_sense,
 	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
 	.pm_misc = &evergreen_pm_misc,
 	.pm_prepare = &evergreen_pm_prepare,
@@ -828,6 +829,7 @@
 	.hpd_fini = &evergreen_hpd_fini,
 	.hpd_sense = &evergreen_hpd_sense,
 	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
 	.pm_misc = &evergreen_pm_misc,
 	.pm_prepare = &evergreen_pm_prepare,
@@ -874,6 +876,8 @@
 	.hpd_fini = &evergreen_hpd_fini,
 	.hpd_sense = &evergreen_hpd_sense,
 	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
 	.pm_misc = &evergreen_pm_misc,
 	.pm_prepare = &evergreen_pm_prepare,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2011-06-02 21:35:11.000000000 -0400
@@ -431,7 +431,7 @@
 		}
 	}
 
-	/* Acer laptop (Acer TravelMate 5730G) has an HDMI port
+	/* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
 	 * on the laptop and a DVI port on the docking station and
 	 * both share the same encoder, hpd pin, and ddc line.
 	 * So while the bios table is technically correct,
@@ -440,7 +440,7 @@
 	 * with different crtcs which isn't possible on the hardware
 	 * side and leaves no crtcs for LVDS or VGA.
 	 */
-	if ((dev->pdev->device == 0x95c4) &&
+	if (((dev->pdev->device == 0x95c4) || (dev->pdev->device == 0x9591)) &&
 	    (dev->pdev->subsystem_vendor == 0x1025) &&
 	    (dev->pdev->subsystem_device == 0x013c)) {
 		if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
@@ -675,7 +675,8 @@
 							ATOM_ENCODER_CAP_RECORD *cap_record;
 							u16 caps = 0;
 
-							while (record->ucRecordType > 0 &&
+							while (record->ucRecordSize > 0 &&
+							       record->ucRecordType > 0 &&
 							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 								switch (record->ucRecordType) {
 								case ATOM_ENCODER_CAP_RECORD_TYPE:
@@ -720,7 +721,8 @@
 									break;
 							}
 
-							while (record->ucRecordType > 0 &&
+							while (record->ucRecordSize > 0 &&
+							       record->ucRecordType > 0 &&
 							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 								switch (record->ucRecordType) {
 								case ATOM_I2C_RECORD_TYPE:
@@ -782,10 +784,9 @@
 						ATOM_HPD_INT_RECORD *hpd_record;
 						ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
 
-						while (record->ucRecordType > 0
-						       && record->
-						       ucRecordType <=
-						       ATOM_MAX_OBJECT_RECORD_NUMBER) {
+						while (record->ucRecordSize > 0 &&
+						       record->ucRecordType > 0 &&
+						       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 							switch (record->ucRecordType) {
 							case ATOM_I2C_RECORD_TYPE:
 								i2c_record =
@@ -1573,9 +1574,17 @@
 			ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
 			ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
 			bool bad_record = false;
-			u8 *record = (u8 *)(mode_info->atom_context->bios +
-					    data_offset +
-					    le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+			u8 *record;
+
+			if ((frev == 1) && (crev < 2))
+				/* absolute */
+				record = (u8 *)(mode_info->atom_context->bios +
+						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+			else
+				/* relative */
+				record = (u8 *)(mode_info->atom_context->bios +
+						data_offset +
+						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
 			while (*record != ATOM_RECORD_END_TYPE) {
 				switch (*record) {
 				case LCD_MODE_PATCH_RECORD_MODE_TYPE:
@@ -1598,9 +1607,10 @@
 							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
 							       fake_edid_record->ucFakeEDIDLength);
 
-							if (drm_edid_is_valid(edid))
+							if (drm_edid_is_valid(edid)) {
 								rdev->mode_info.bios_hardcoded_edid = edid;
-							else
+								rdev->mode_info.bios_hardcoded_edid_size = edid_size;
+							} else
 								kfree(edid);
 						}
 					}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2011-06-02 21:35:11.000000000 -0400
@@ -448,7 +448,7 @@
 
 bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
 {
-	int edid_info;
+	int edid_info, size;
 	struct edid *edid;
 	unsigned char *raw;
 	edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
@@ -456,11 +456,12 @@
 		return false;
 
 	raw = rdev->bios + edid_info;
-	edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL);
+	size = EDID_LENGTH * (raw[0x7e] + 1);
+	edid = kmalloc(size, GFP_KERNEL);
 	if (edid == NULL)
 		return false;
 
-	memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1));
+	memcpy((unsigned char *)edid, raw, size);
 
 	if (!drm_edid_is_valid(edid)) {
 		kfree(edid);
@@ -468,6 +469,7 @@
 	}
 
 	rdev->mode_info.bios_hardcoded_edid = edid;
+	rdev->mode_info.bios_hardcoded_edid_size = size;
 	return true;
 }
 
@@ -475,8 +477,17 @@
 struct edid *
 radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
 {
-	if (rdev->mode_info.bios_hardcoded_edid)
-		return rdev->mode_info.bios_hardcoded_edid;
+	struct edid *edid;
+
+	if (rdev->mode_info.bios_hardcoded_edid) {
+		edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
+		if (edid) {
+			memcpy((unsigned char *)edid,
+			       (unsigned char *)rdev->mode_info.bios_hardcoded_edid,
+			       rdev->mode_info.bios_hardcoded_edid_size);
+			return edid;
+		}
+	}
 	return NULL;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2011-06-02 21:35:11.000000000 -0400
@@ -629,6 +629,8 @@
 static enum drm_connector_status
 radeon_vga_detect(struct drm_connector *connector, bool force)
 {
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder;
 	struct drm_encoder_helper_funcs *encoder_funcs;
@@ -679,6 +681,17 @@
 
 	if (ret == connector_status_connected)
 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
+
+	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
+	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
+	 * by other means, assume the CRT is connected and use that EDID.
+	 */
+	if ((!rdev->is_atom_bios) &&
+	    (ret == connector_status_disconnected) &&
+	    rdev->mode_info.bios_hardcoded_edid_size) {
+		ret = connector_status_connected;
+	}
+
 	radeon_connector_update_scratch_regs(connector, ret);
 	return ret;
 }
@@ -790,6 +803,8 @@
 static enum drm_connector_status
 radeon_dvi_detect(struct drm_connector *connector, bool force)
 {
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder = NULL;
 	struct drm_encoder_helper_funcs *encoder_funcs;
@@ -829,8 +844,6 @@
 			 * you don't really know what's connected to which port as both are digital.
 			 */
 			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
-				struct drm_device *dev = connector->dev;
-				struct radeon_device *rdev = dev->dev_private;
 				struct drm_connector *list_connector;
 				struct radeon_connector *list_radeon_connector;
 				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
@@ -895,6 +908,19 @@
 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
 	}
 
+	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
+	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
+	 * by other means, assume the DFP is connected and use that EDID.  In most
+	 * cases the DVI port is actually a virtual KVM port connected to the service
+	 * processor.
+	 */
+	if ((!rdev->is_atom_bios) &&
+	    (ret == connector_status_disconnected) &&
+	    rdev->mode_info.bios_hardcoded_edid_size) {
+		radeon_connector->use_digital = true;
+		ret = connector_status_connected;
+	}
+
 out:
 	/* updated in get modes as well since we need to know if it's analog or digital */
 	radeon_connector_update_scratch_regs(connector, ret);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2011-06-02 21:35:11.000000000 -0400
@@ -80,7 +80,7 @@
 			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
 		else
 			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-		seq = rdev->wb.wb[scratch_index/4];
+		seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
 	} else
 		seq = RREG32(rdev->fence_drv.scratch_reg);
 	if (seq != rdev->fence_drv.last_seq) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2011-06-02 21:35:11.000000000 -0400
@@ -205,6 +205,9 @@
 		/* return clock value in KHz */
 		value = rdev->clock.spll.reference_freq * 10;
 		break;
+	case RADEON_INFO_FUSION_GART_WORKING:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2011-06-02 21:35:11.000000000 -0400
@@ -239,6 +239,7 @@
 	struct drm_property *underscan_vborder_property;
 	/* hardcoded DFP edid from BIOS */
 	struct edid *bios_hardcoded_edid;
+	int bios_hardcoded_edid_size;
 
 	/* pointer to fbdev info structure */
 	struct radeon_fbdev *rfbdev;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2011-06-02 21:35:11.000000000 -0400
@@ -248,7 +248,7 @@
 void radeon_ring_free_size(struct radeon_device *rdev)
 {
 	if (rdev->wb.enabled)
-		rdev->cp.rptr = rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4];
+		rdev->cp.rptr = le32_to_cpu(rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4]);
 	else {
 		if (rdev->family >= CHIP_R600)
 			rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-apple.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-apple.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-apple.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-apple.c	2011-06-02 21:35:11.000000000 -0400
@@ -481,6 +481,12 @@
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-axff.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-axff.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-axff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-axff.c	2011-06-02 21:35:11.000000000 -0400
@@ -33,6 +33,8 @@
 #include <linux/hid.h>
 
 #include "hid-ids.h"
+
+#ifdef CONFIG_HID_ACRUX_FF
 #include "usbhid/usbhid.h"
 
 struct axff_device {
@@ -109,6 +111,12 @@
 	kfree(axff);
 	return error;
 }
+#else
+static inline int axff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
 
 static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
@@ -139,9 +147,25 @@
 			 error);
 	}
 
+	/*
+	 * We need to start polling device right away, otherwise
+	 * it will go into a coma.
+	 */
+	error = hid_hw_open(hdev);
+	if (error) {
+		dev_err(&hdev->dev, "hw open failed\n");
+		return error;
+	}
+
 	return 0;
 }
 
+static void ax_remove(struct hid_device *hdev)
+{
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id ax_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), },
 	{ }
@@ -149,9 +173,10 @@
 MODULE_DEVICE_TABLE(hid, ax_devices);
 
 static struct hid_driver ax_driver = {
-	.name = "acrux",
-	.id_table = ax_devices,
-	.probe = ax_probe,
+	.name		= "acrux",
+	.id_table	= ax_devices,
+	.probe		= ax_probe,
+	.remove		= ax_remove,
 };
 
 static int __init ax_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-core.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-core.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-core.c	2011-06-02 21:35:11.000000000 -0400
@@ -1256,9 +1256,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
-#if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
-#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
@@ -1302,6 +1300,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -1400,6 +1401,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
@@ -1801,6 +1803,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-ids.h linux-libre-2.6.38.8-gnu/drivers/hid/hid-ids.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-ids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-ids.h	2011-06-02 21:35:11.000000000 -0400
@@ -103,6 +103,9 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
@@ -466,6 +469,7 @@
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
 #define USB_VENDOR_ID_ORTEK		0x05a4
+#define USB_DEVICE_ID_ORTEK_PKB1700	0x1700
 #define USB_DEVICE_ID_ORTEK_WKB2000	0x2000
 
 #define USB_VENDOR_ID_PANJIT		0x134c
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-input.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-input.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-input.c	2011-06-02 21:35:11.000000000 -0400
@@ -290,14 +290,6 @@
 		goto ignore;
 	}
 
-	if (field->report_type == HID_FEATURE_REPORT) {
-		if (device->driver->feature_mapping) {
-			device->driver->feature_mapping(device, hidinput, field,
-				usage);
-		}
-		goto ignore;
-	}
-
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -835,6 +827,24 @@
 	hid_hw_close(hid);
 }
 
+static void report_features(struct hid_device *hid)
+{
+	struct hid_driver *drv = hid->driver;
+	struct hid_report_enum *rep_enum;
+	struct hid_report *rep;
+	int i, j;
+
+	if (!drv->feature_mapping)
+		return;
+
+	rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
+	list_for_each_entry(rep, &rep_enum->report_list, list)
+		for (i = 0; i < rep->maxfield; i++)
+			for (j = 0; j < rep->field[i]->maxusage; j++)
+				drv->feature_mapping(hid, rep->field[i],
+						     rep->field[i]->usage + j);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -863,7 +873,9 @@
 			return -1;
 	}
 
-	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) {
+	report_features(hid);
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
 		if (k == HID_OUTPUT_REPORT &&
 			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
 			continue;
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-magicmouse.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-magicmouse.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-magicmouse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-magicmouse.c	2011-06-02 21:35:11.000000000 -0400
@@ -258,7 +258,7 @@
 		input_report_abs(input, ABS_MT_TRACKING_ID, id);
 		input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
 		input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
-		input_report_abs(input, ABS_MT_ORIENTATION, orientation);
+		input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
 		input_report_abs(input, ABS_MT_POSITION_X, x);
 		input_report_abs(input, ABS_MT_POSITION_Y, y);
 
@@ -397,7 +397,7 @@
 		input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
-		input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0);
+		input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
 
 		/* Note: Touch Y position from the device is inverted relative
 		 * to how pointer motion is reported (and relative to how USB
@@ -418,6 +418,8 @@
 			input_set_abs_params(input, ABS_MT_POSITION_Y, -2456,
 				2565, 4, 0);
 		}
+
+		input_set_events_per_packet(input, 60);
 	}
 
 	if (report_undeciphered) {
@@ -499,9 +501,17 @@
 	}
 	report->size = 6;
 
+	/*
+	 * The device reponds with 'invalid report id' when feature
+	 * report switching it into multitouch mode is sent to it.
+	 *
+	 * This results in -EIO from the _raw low-level transport callback,
+	 * but there seems to be no other way of switching the mode.
+	 * Thus the super-ugly hacky success check below.
+	 */
 	ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
 			HID_FEATURE_REPORT);
-	if (ret != sizeof(feature)) {
+	if (ret != -EIO) {
 		hid_err(hdev, "unable to request touch data (%d)\n", ret);
 		goto err_stop_hw;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-multitouch.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-multitouch.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-multitouch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-multitouch.c	2011-06-02 21:35:11.000000000 -0400
@@ -122,7 +122,7 @@
 	{ }
 };
 
-static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+static void mt_feature_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
 	if (usage->hid == HID_DG_INPUTMODE) {
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-ortek.c linux-libre-2.6.38.8-gnu/drivers/hid/hid-ortek.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-ortek.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/hid-ortek.c	2011-06-02 21:35:11.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- *  HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad).
+ *  HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad).
  *  Fixes LogicalMaximum error in USB report description, see
  *  http://bugzilla.kernel.org/show_bug.cgi?id=14787
  *
@@ -30,6 +30,7 @@
 }
 
 static const struct hid_device_id ortek_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ }
 };
diff -druN linux-libre-2.6.38-gnu/drivers/hid/Kconfig linux-libre-2.6.38.8-gnu/drivers/hid/Kconfig
--- linux-libre-2.6.38-gnu/drivers/hid/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -68,9 +68,15 @@
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
-config HID_ACRUX_FF
-	tristate "ACRUX force feedback"
+config HID_ACRUX
+	tristate "ACRUX game controller support"
 	depends on USB_HID
+	---help---
+	Say Y here if you want to enable support for ACRUX game controllers.
+
+config HID_ACRUX_FF
+	tristate "ACRUX force feedback support"
+	depends on HID_ACRUX
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you want to enable force feedback support for ACRUX
@@ -319,10 +325,10 @@
 	Support for N-Trig touch screen.
 
 config HID_ORTEK
-	tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad"
+	tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad"
 	depends on USB_HID
 	---help---
-	Support for Ortek WKB-2000 wireless keyboard + mouse trackpad.
+	Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad.
 
 config HID_PANTHERLORD
 	tristate "Pantherlord/GreenAsia game controller"
diff -druN linux-libre-2.6.38-gnu/drivers/hid/Makefile linux-libre-2.6.38.8-gnu/drivers/hid/Makefile
--- linux-libre-2.6.38-gnu/drivers/hid/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hid/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -27,7 +27,7 @@
 
 obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
-obj-$(CONFIG_HID_ACRUX_FF)	+= hid-axff.o
+obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
 obj-$(CONFIG_HID_CANDO)		+= hid-cando.o
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/sht15.c linux-libre-2.6.38.8-gnu/drivers/hwmon/sht15.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/sht15.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/hwmon/sht15.c	2011-06-02 21:35:11.000000000 -0400
@@ -333,11 +333,11 @@
 
 	const int c1 = -4;
 	const int c2 = 40500; /* x 10 ^ -6 */
-	const int c3 = -2800; /* x10 ^ -9 */
+	const int c3 = -28; /* x 10 ^ -7 */
 
 	RHlinear = c1*1000
 		+ c2 * data->val_humid/1000
-		+ (data->val_humid * data->val_humid * c3)/1000000;
+		+ (data->val_humid * data->val_humid * c3) / 10000;
 	return (temp - 25000) * (10000 + 80 * data->val_humid)
 		/ 1000000 + RHlinear;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-bit.c linux-libre-2.6.38.8-gnu/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-bit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/i2c/algos/i2c-algo-bit.c	2011-06-02 21:35:11.000000000 -0400
@@ -232,9 +232,17 @@
  * Sanity check for the adapter hardware - check the reaction of
  * the bus lines only if it seems to be idle.
  */
-static int test_bus(struct i2c_algo_bit_data *adap, char *name)
+static int test_bus(struct i2c_adapter *i2c_adap)
 {
-	int scl, sda;
+	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+	const char *name = i2c_adap->name;
+	int scl, sda, ret;
+
+	if (adap->pre_xfer) {
+		ret = adap->pre_xfer(i2c_adap);
+		if (ret < 0)
+			return -ENODEV;
+	}
 
 	if (adap->getscl == NULL)
 		pr_info("%s: Testing SDA only, SCL is not readable\n", name);
@@ -297,11 +305,19 @@
 		       "while pulling SCL high!\n", name);
 		goto bailout;
 	}
+
+	if (adap->post_xfer)
+		adap->post_xfer(i2c_adap);
+
 	pr_info("%s: Test OK\n", name);
 	return 0;
 bailout:
 	sdahi(adap);
 	sclhi(adap);
+
+	if (adap->post_xfer)
+		adap->post_xfer(i2c_adap);
+
 	return -ENODEV;
 }
 
@@ -607,7 +623,7 @@
 	int ret;
 
 	if (bit_test) {
-		ret = test_bus(bit_adap, adap->name);
+		ret = test_bus(adap);
 		if (ret < 0)
 			return -ENODEV;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-parport.c linux-libre-2.6.38.8-gnu/drivers/i2c/busses/i2c-parport.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-parport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/i2c/busses/i2c-parport.c	2011-06-02 21:35:11.000000000 -0400
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-smbus.h>
 #include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@
 	struct i2c_algo_bit_data algo_data;
 	struct i2c_smbus_alert_setup alert_data;
 	struct i2c_client *ara;
-	struct i2c_par *next;
+	struct list_head node;
 };
 
-static struct i2c_par *adapter_list;
+static LIST_HEAD(adapter_list);
+static DEFINE_MUTEX(adapter_list_lock);
 
 /* ----- Low-level parallel port access ----------------------------------- */
 
@@ -228,8 +231,9 @@
 	}
 
 	/* Add the new adapter to the list */
-	adapter->next = adapter_list;
-	adapter_list = adapter;
+	mutex_lock(&adapter_list_lock);
+	list_add_tail(&adapter->node, &adapter_list);
+	mutex_unlock(&adapter_list_lock);
         return;
 
 ERROR1:
@@ -241,11 +245,11 @@
 
 static void i2c_parport_detach (struct parport *port)
 {
-	struct i2c_par *adapter, *prev;
+	struct i2c_par *adapter, *_n;
 
 	/* Walk the list */
-	for (prev = NULL, adapter = adapter_list; adapter;
-	     prev = adapter, adapter = adapter->next) {
+	mutex_lock(&adapter_list_lock);
+	list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
 		if (adapter->pdev->port == port) {
 			if (adapter->ara) {
 				parport_disable_irq(port);
@@ -259,14 +263,11 @@
 				
 			parport_release(adapter->pdev);
 			parport_unregister_device(adapter->pdev);
-			if (prev)
-				prev->next = adapter->next;
-			else
-				adapter_list = adapter->next;
+			list_del(&adapter->node);
 			kfree(adapter);
-			return;
 		}
 	}
+	mutex_unlock(&adapter_list_lock);
 }
 
 static struct parport_driver i2c_parport_driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd.c linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1177,7 +1177,7 @@
 	.open			= ide_cdrom_open_real,
 	.release		= ide_cdrom_release_real,
 	.drive_status		= ide_cdrom_drive_status,
-	.media_changed		= ide_cdrom_check_media_change_real,
+	.check_events		= ide_cdrom_check_events_real,
 	.tray_move		= ide_cdrom_tray_move,
 	.lock_door		= ide_cdrom_lock_door,
 	.select_speed		= ide_cdrom_select_speed,
@@ -1702,10 +1702,11 @@
 }
 
 
-static int idecd_media_changed(struct gendisk *disk)
+static unsigned int idecd_check_events(struct gendisk *disk,
+				       unsigned int clearing)
 {
 	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
-	return cdrom_media_changed(&info->devinfo);
+	return cdrom_check_events(&info->devinfo, clearing);
 }
 
 static int idecd_revalidate_disk(struct gendisk *disk)
@@ -1723,7 +1724,7 @@
 	.open			= idecd_open,
 	.release		= idecd_release,
 	.ioctl			= idecd_ioctl,
-	.media_changed		= idecd_media_changed,
+	.check_events		= idecd_check_events,
 	.revalidate_disk	= idecd_revalidate_disk
 };
 
@@ -1789,7 +1790,8 @@
 
 	ide_cd_read_toc(drive, &sense);
 	g->fops = &idecd_ops;
-	g->flags |= GENHD_FL_REMOVABLE;
+	g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+	g->events = DISK_EVENT_MEDIA_CHANGE;
 	add_disk(g);
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd.h linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd.h
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd.h	2011-06-02 21:35:11.000000000 -0400
@@ -111,7 +111,8 @@
 int ide_cdrom_open_real(struct cdrom_device_info *, int);
 void ide_cdrom_release_real(struct cdrom_device_info *);
 int ide_cdrom_drive_status(struct cdrom_device_info *, int);
-int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *,
+					 unsigned int clearing, int slot_nr);
 int ide_cdrom_tray_move(struct cdrom_device_info *, int);
 int ide_cdrom_lock_door(struct cdrom_device_info *, int);
 int ide_cdrom_select_speed(struct cdrom_device_info *, int);
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd_ioctl.c linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd_ioctl.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd_ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ide/ide-cd_ioctl.c	2011-06-02 21:35:11.000000000 -0400
@@ -79,8 +79,8 @@
 	return CDS_DRIVE_NOT_READY;
 }
 
-int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
-				       int slot_nr)
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi,
+					 unsigned int clearing, int slot_nr)
 {
 	ide_drive_t *drive = cdi->handle;
 	int retval;
@@ -89,9 +89,9 @@
 		(void) cdrom_check_status(drive, NULL);
 		retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0;
 		drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
-		return retval;
+		return retval ? DISK_EVENT_MEDIA_CHANGE : 0;
 	} else {
-		return -EINVAL;
+		return 0;
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-gd.c linux-libre-2.6.38.8-gnu/drivers/ide/ide-gd.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-gd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/ide/ide-gd.c	2011-06-02 21:35:11.000000000 -0400
@@ -285,11 +285,12 @@
 	return 0;
 }
 
-static int ide_gd_media_changed(struct gendisk *disk)
+static unsigned int ide_gd_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
-	int ret;
+	bool ret;
 
 	/* do not scan partitions twice if this is a removable device */
 	if (drive->dev_flags & IDE_DFLAG_ATTACH) {
@@ -297,10 +298,10 @@
 		return 0;
 	}
 
-	ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
+	ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
 	drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
 
-	return ret;
+	return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static void ide_gd_unlock_native_capacity(struct gendisk *disk)
@@ -318,7 +319,7 @@
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
 
-	if (ide_gd_media_changed(disk))
+	if (ide_gd_check_events(disk, 0))
 		drive->disk_ops->get_capacity(drive);
 
 	set_capacity(disk, ide_gd_capacity(drive));
@@ -340,7 +341,7 @@
 	.release		= ide_gd_release,
 	.ioctl			= ide_gd_ioctl,
 	.getgeo			= ide_gd_getgeo,
-	.media_changed		= ide_gd_media_changed,
+	.check_events		= ide_gd_check_events,
 	.unlock_native_capacity	= ide_gd_unlock_native_capacity,
 	.revalidate_disk	= ide_gd_revalidate_disk
 };
@@ -412,6 +413,7 @@
 	if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
 		g->flags = GENHD_FL_REMOVABLE;
 	g->fops = &ide_gd_ops;
+	g->events = DISK_EVENT_MEDIA_CHANGE;
 	add_disk(g);
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/cma.c linux-libre-2.6.38.8-gnu/drivers/infiniband/core/cma.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/cma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/infiniband/core/cma.c	2011-06-02 21:35:11.000000000 -0400
@@ -1210,6 +1210,11 @@
 	cm_id->context = conn_id;
 	cm_id->cm_handler = cma_ib_handler;
 
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (!ret) {
 		/*
@@ -1222,8 +1227,10 @@
 			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
 		mutex_unlock(&lock);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		goto out;
 	}
+	cma_deref_id(conn_id);
 
 	/* Destroy the CM ID by returning a non-zero value. */
 	conn_id->cm_id.ib = NULL;
@@ -1425,17 +1432,25 @@
 	event.param.conn.private_data_len = iw_event->private_data_len;
 	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
 	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret) {
 		/* User wants to destroy the CM ID */
 		conn_id->cm_id.iw = NULL;
 		cma_exch(conn_id, CMA_DESTROYING);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		rdma_destroy_id(&conn_id->id);
 		goto out;
 	}
 
 	mutex_unlock(&conn_id->handler_mutex);
+	cma_deref_id(conn_id);
 
 out:
 	if (dev)
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/cm.c linux-libre-2.6.38.8-gnu/drivers/infiniband/core/cm.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/cm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/infiniband/core/cm.c	2011-06-02 21:35:11.000000000 -0400
@@ -2989,6 +2989,7 @@
 		goto out; /* No match. */
 	}
 	atomic_inc(&cur_cm_id_priv->refcount);
+	atomic_inc(&cm_id_priv->refcount);
 	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/bcm5974.c linux-libre-2.6.38.8-gnu/drivers/input/mouse/bcm5974.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/bcm5974.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/input/mouse/bcm5974.c	2011-06-02 21:35:11.000000000 -0400
@@ -63,6 +63,10 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+/* Macbook8 (unibody, March 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 
 #define BCM5974_DEVICE(prod) {					\
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -96,6 +100,10 @@
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
+	/* MacbookPro8 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
 	/* Terminating entry */
 	{}
 };
@@ -274,6 +282,18 @@
 		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
 		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
 	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
+		{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+	},
 	{}
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics.c linux-libre-2.6.38.8-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/input/mouse/synaptics.c	2011-06-02 21:35:11.000000000 -0400
@@ -836,8 +836,8 @@
 		},
 
 	},
-	{ }
 #endif
+	{ }
 };
 
 static bool broken_olpc_ec;
@@ -851,8 +851,8 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
 		},
 	},
-	{ }
 #endif
+	{ }
 };
 
 void __init synaptics_module_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/xen-kbdfront.c linux-libre-2.6.38.8-gnu/drivers/input/xen-kbdfront.c
--- linux-libre-2.6.38-gnu/drivers/input/xen-kbdfront.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/input/xen-kbdfront.c	2011-06-02 21:35:11.000000000 -0400
@@ -110,7 +110,7 @@
 static int __devinit xenkbd_probe(struct xenbus_device *dev,
 				  const struct xenbus_device_id *id)
 {
-	int ret, i;
+	int ret, i, abs;
 	struct xenkbd_info *info;
 	struct input_dev *kbd, *ptr;
 
@@ -128,6 +128,11 @@
 	if (!info->page)
 		goto error_nomem;
 
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
+		abs = 0;
+	if (abs)
+		xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+
 	/* keyboard */
 	kbd = input_allocate_device();
 	if (!kbd)
@@ -137,11 +142,12 @@
 	kbd->id.bustype = BUS_PCI;
 	kbd->id.vendor = 0x5853;
 	kbd->id.product = 0xffff;
-	kbd->evbit[0] = BIT(EV_KEY);
+
+	__set_bit(EV_KEY, kbd->evbit);
 	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
-		set_bit(i, kbd->keybit);
+		__set_bit(i, kbd->keybit);
 	for (i = KEY_OK; i < KEY_MAX; i++)
-		set_bit(i, kbd->keybit);
+		__set_bit(i, kbd->keybit);
 
 	ret = input_register_device(kbd);
 	if (ret) {
@@ -160,12 +166,20 @@
 	ptr->id.bustype = BUS_PCI;
 	ptr->id.vendor = 0x5853;
 	ptr->id.product = 0xfffe;
-	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+
+	if (abs) {
+		__set_bit(EV_ABS, ptr->evbit);
+		input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+		input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+	} else {
+		input_set_capability(ptr, EV_REL, REL_X);
+		input_set_capability(ptr, EV_REL, REL_Y);
+	}
+	input_set_capability(ptr, EV_REL, REL_WHEEL);
+
+	__set_bit(EV_KEY, ptr->evbit);
 	for (i = BTN_LEFT; i <= BTN_TASK; i++)
-		set_bit(i, ptr->keybit);
-	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
-	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+		__set_bit(i, ptr->keybit);
 
 	ret = input_register_device(ptr);
 	if (ret) {
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-lp5521.c linux-libre-2.6.38.8-gnu/drivers/leds/leds-lp5521.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-lp5521.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/leds/leds-lp5521.c	2011-06-02 21:35:11.000000000 -0400
@@ -534,7 +534,7 @@
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5521_led_attributes[] = {
@@ -548,15 +548,15 @@
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
 
 static struct attribute *lp5521_attributes[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-lp5523.c linux-libre-2.6.38.8-gnu/drivers/leds/leds-lp5523.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-lp5523.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/leds/leds-lp5523.c	2011-06-02 21:35:11.000000000 -0400
@@ -713,7 +713,7 @@
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5523_led_attributes[] = {
@@ -727,21 +727,21 @@
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR,
 		   show_engine1_leds, store_engine1_leds);
-static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR,
 		   show_engine2_leds, store_engine2_leds);
-static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR,
 		   show_engine3_leds, store_engine3_leds);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL);
 
 static struct attribute *lp5523_attributes[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/md/bitmap.c linux-libre-2.6.38.8-gnu/drivers/md/bitmap.c
--- linux-libre-2.6.38-gnu/drivers/md/bitmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/md/bitmap.c	2011-06-02 21:35:11.000000000 -0400
@@ -493,11 +493,11 @@
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
 	sb->events = cpu_to_le64(bitmap->mddev->events);
-	if (bitmap->mddev->events < bitmap->events_cleared) {
+	if (bitmap->mddev->events < bitmap->events_cleared)
 		/* rocking back to read-only */
 		bitmap->events_cleared = bitmap->mddev->events;
-		sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
-	}
+	sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
+	sb->state = cpu_to_le32(bitmap->flags);
 	/* Just in case these have been changed via sysfs: */
 	sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);
 	sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);
@@ -618,7 +618,7 @@
 	if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
 		bitmap->flags |= BITMAP_HOSTENDIAN;
 	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
-	if (sb->state & cpu_to_le32(BITMAP_STALE))
+	if (bitmap->flags & BITMAP_STALE)
 		bitmap->events_cleared = bitmap->mddev->events;
 	err = 0;
 out:
@@ -652,9 +652,11 @@
 	switch (op) {
 	case MASK_SET:
 		sb->state |= cpu_to_le32(bits);
+		bitmap->flags |= bits;
 		break;
 	case MASK_UNSET:
 		sb->state &= cpu_to_le32(~bits);
+		bitmap->flags &= ~bits;
 		break;
 	default:
 		BUG();
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-table.c linux-libre-2.6.38.8-gnu/drivers/md/dm-table.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-table.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/md/dm-table.c	2011-06-02 21:35:11.000000000 -0400
@@ -361,6 +361,7 @@
 static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
 				  sector_t start, sector_t len, void *data)
 {
+	struct request_queue *q;
 	struct queue_limits *limits = data;
 	struct block_device *bdev = dev->bdev;
 	sector_t dev_size =
@@ -369,6 +370,22 @@
 		limits->logical_block_size >> SECTOR_SHIFT;
 	char b[BDEVNAME_SIZE];
 
+	/*
+	 * Some devices exist without request functions,
+	 * such as loop devices not yet bound to backing files.
+	 * Forbid the use of such devices.
+	 */
+	q = bdev_get_queue(bdev);
+	if (!q || !q->make_request_fn) {
+		DMWARN("%s: %s is not yet initialised: "
+		       "start=%llu, len=%llu, dev_size=%llu",
+		       dm_device_name(ti->table->md), bdevname(bdev, b),
+		       (unsigned long long)start,
+		       (unsigned long long)len,
+		       (unsigned long long)dev_size);
+		return 1;
+	}
+
 	if (!dev_size)
 		return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/md/md.c linux-libre-2.6.38.8-gnu/drivers/md/md.c
--- linux-libre-2.6.38-gnu/drivers/md/md.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/md/md.c	2011-06-02 21:35:11.000000000 -0400
@@ -4335,13 +4335,19 @@
 	disk->fops = &md_fops;
 	disk->private_data = mddev;
 	disk->queue = mddev->queue;
+	blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
 	/* Allow extended partitions.  This makes the
 	 * 'mdp' device redundant, but we can't really
 	 * remove it now.
 	 */
 	disk->flags |= GENHD_FL_EXT_DEVT;
-	add_disk(disk);
 	mddev->gendisk = disk;
+	/* As soon as we call add_disk(), another thread could get
+	 * through to md_open, so make sure it doesn't get too far
+	 */
+	mutex_lock(&mddev->open_mutex);
+	add_disk(disk);
+
 	error = kobject_init_and_add(&mddev->kobj, &md_ktype,
 				     &disk_to_dev(disk)->kobj, "%s", "md");
 	if (error) {
@@ -4355,8 +4361,7 @@
 	if (mddev->kobj.sd &&
 	    sysfs_create_group(&mddev->kobj, &md_bitmap_group))
 		printk(KERN_DEBUG "pointless warning\n");
-
-	blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
+	mutex_unlock(&mddev->open_mutex);
  abort:
 	mutex_unlock(&disks_mutex);
 	if (!error && mddev->kobj.sd) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/b2c2/flexcop-pci.c linux-libre-2.6.38.8-gnu/drivers/media/dvb/b2c2/flexcop-pci.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/b2c2/flexcop-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/dvb/b2c2/flexcop-pci.c	2011-06-02 21:35:11.000000000 -0400
@@ -38,7 +38,7 @@
 	DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_NAME "flexcop-pci"
 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 
 struct flexcop_pci {
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/Kconfig linux-libre-2.6.38.8-gnu/drivers/media/radio/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/radio/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/radio/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -441,6 +441,7 @@
 config RADIO_WL1273
 	tristate "Texas Instruments WL1273 I2C FM Radio"
 	depends on I2C && VIDEO_V4L2
+	select MFD_CORE
 	select MFD_WL1273_CORE
 	select FW_LOADER
 	---help---
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/saa7706h.c linux-libre-2.6.38.8-gnu/drivers/media/radio/saa7706h.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/saa7706h.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/radio/saa7706h.c	2011-06-02 21:35:11.000000000 -0400
@@ -376,7 +376,7 @@
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/tef6862.c linux-libre-2.6.38.8-gnu/drivers/media/radio/tef6862.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/tef6862.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/radio/tef6862.c	2011-06-02 21:35:11.000000000 -0400
@@ -176,7 +176,7 @@
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	state->freq = TEF6862_LO_FREQ;
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/imon.c linux-libre-2.6.38.8-gnu/drivers/media/rc/imon.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/imon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/rc/imon.c	2011-06-02 21:35:11.000000000 -0400
@@ -46,7 +46,7 @@
 #define MOD_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
 #define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
 #define MOD_NAME	"imon"
-#define MOD_VERSION	"0.9.2"
+#define MOD_VERSION	"0.9.3"
 
 #define DISPLAY_MINOR_BASE	144
 #define DEVICE_NAME	"lcd%d"
@@ -451,8 +451,9 @@
 }
 
 /**
- * Sends a packet to the device -- this function must be called
- * with ictx->lock held.
+ * Sends a packet to the device -- this function must be called with
+ * ictx->lock held, or its unlock/lock sequence while waiting for tx
+ * to complete can/will lead to a deadlock.
  */
 static int send_packet(struct imon_context *ictx)
 {
@@ -982,12 +983,21 @@
  * the iMON remotes, and those used by the Windows MCE remotes (which is
  * really just RC-6), but only one or the other at a time, as the signals
  * are decoded onboard the receiver.
+ *
+ * This function gets called two different ways, one way is from
+ * rc_register_device, for initial protocol selection/setup, and the other is
+ * via a userspace-initiated protocol change request, either by direct sysfs
+ * prodding or by something like ir-keytable. In the rc_register_device case,
+ * the imon context lock is already held, but when initiated from userspace,
+ * it is not, so we must acquire it prior to calling send_packet, which
+ * requires that the lock is held.
  */
 static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
 	int retval;
 	struct imon_context *ictx = rc->priv;
 	struct device *dev = ictx->dev;
+	bool unlock = false;
 	unsigned char ir_proto_packet[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
@@ -1020,6 +1030,11 @@
 
 	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
 
+	if (!mutex_is_locked(&ictx->lock)) {
+		unlock = true;
+		mutex_lock(&ictx->lock);
+	}
+
 	retval = send_packet(ictx);
 	if (retval)
 		goto out;
@@ -1028,6 +1043,9 @@
 	ictx->pad_mouse = false;
 
 out:
+	if (unlock)
+		mutex_unlock(&ictx->lock);
+
 	return retval;
 }
 
@@ -2125,6 +2143,7 @@
 		goto rdev_setup_failed;
 	}
 
+	mutex_unlock(&ictx->lock);
 	return ictx;
 
 rdev_setup_failed:
@@ -2196,6 +2215,7 @@
 		goto urb_submit_failed;
 	}
 
+	mutex_unlock(&ictx->lock);
 	return ictx;
 
 urb_submit_failed:
@@ -2290,6 +2310,8 @@
 	usb_set_intfdata(interface, ictx);
 
 	if (ifnum == 0) {
+		mutex_lock(&ictx->lock);
+
 		if (product == 0xffdc && ictx->rf_device) {
 			sysfs_err = sysfs_create_group(&interface->dev.kobj,
 						       &imon_rf_attr_group);
@@ -2300,13 +2322,14 @@
 
 		if (ictx->display_supported)
 			imon_init_display(ictx, interface);
+
+		mutex_unlock(&ictx->lock);
 	}
 
 	dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
 		 "usb<%d:%d> initialized\n", vendor, product, ifnum,
 		 usbdev->bus->busnum, usbdev->devnum);
 
-	mutex_unlock(&ictx->lock);
 	mutex_unlock(&driver_lock);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-blackbird.c linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-blackbird.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-blackbird.c	2012-03-24 01:04:50.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-blackbird.c	2012-03-25 07:11:36.000000000 -0400
@@ -1122,7 +1122,6 @@
 	mutex_lock(&dev->core->lock);
 	file->private_data = NULL;
 	kfree(fh);
-	mutex_unlock(&dev->core->lock);
 
 	/* Make sure we release the hardware */
 	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
@@ -1131,6 +1130,8 @@
 
 	atomic_dec(&dev->core->mpeg_users);
 
+	mutex_unlock(&dev->core->lock);
+
 	return 0;
 }
 
@@ -1334,11 +1335,9 @@
 	blackbird_register_video(dev);
 
 	/* initial device configuration: needed ? */
-	mutex_lock(&dev->core->lock);
 //	init_controls(core);
 	cx88_set_tvnorm(core,core->tvnorm);
 	cx88_video_mux(core,0);
-	mutex_unlock(&dev->core->lock);
 
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-dvb.c linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-25 07:09:46.000000000 -0400
@@ -132,6 +132,7 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&dev->core->lock);
 	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
 	if (drv) {
 		if (acquire){
@@ -142,6 +143,7 @@
 			dev->frontends.active_fe_id = 0;
 		}
 	}
+	mutex_unlock(&dev->core->lock);
 
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88.h linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88.h	2011-06-02 21:35:11.000000000 -0400
@@ -495,6 +495,8 @@
 	int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
 	int (*resume)(struct pci_dev *pci_dev);
 
+	/* Callers to the following functions must hold core->lock */
+
 	/* MPEG 8802 -> mini driver - Driver probe and configuration */
 	int (*probe)(struct cx8802_driver *drv);
 	int (*remove)(struct cx8802_driver *drv);
@@ -551,8 +553,9 @@
 	/* for switching modulation types */
 	unsigned char              ts_gen_cntrl;
 
-	/* List of attached drivers */
+	/* List of attached drivers; must hold core->lock to access */
 	struct list_head	   drvlist;
+
 	struct work_struct	   request_module_wk;
 };
 
@@ -675,6 +678,8 @@
 
 int cx8802_register_driver(struct cx8802_driver *drv);
 int cx8802_unregister_driver(struct cx8802_driver *drv);
+
+/* Caller must hold core->lock */
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
 
 /* ----------------------------------------------------------- */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-input.c linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-input.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-input.c	2011-06-02 21:35:11.000000000 -0400
@@ -283,7 +283,7 @@
 	case CX88_BOARD_PCHDTV_HD3000:
 	case CX88_BOARD_PCHDTV_HD5500:
 	case CX88_BOARD_HAUPPAUGE_IRONLY:
-		ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW;
 		ir->sampling = 1;
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
@@ -523,7 +523,7 @@
 	for (todo = 32; todo > 0; todo -= bits) {
 		ev.pulse = samples & 0x80000000 ? false : true;
 		bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
-		ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
+		ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
 		ir_raw_event_store_with_filter(ir->dev, &ev);
 		samples <<= bits;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-mpeg.c linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-mpeg.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-mpeg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/cx88/cx88-mpeg.c	2011-06-02 21:35:11.000000000 -0400
@@ -624,13 +624,11 @@
 
 	if (drv->advise_acquire)
 	{
-		mutex_lock(&drv->core->lock);
 		core->active_ref++;
 		if (core->active_type_id == CX88_BOARD_NONE) {
 			core->active_type_id = drv->type_id;
 			drv->advise_acquire(drv);
 		}
-		mutex_unlock(&drv->core->lock);
 
 		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
 	}
@@ -643,14 +641,12 @@
 {
 	struct cx88_core *core = drv->core;
 
-	mutex_lock(&drv->core->lock);
 	if (drv->advise_release && --core->active_ref == 0)
 	{
 		drv->advise_release(drv);
 		core->active_type_id = CX88_BOARD_NONE;
 		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
 	}
-	mutex_unlock(&drv->core->lock);
 
 	return 0;
 }
@@ -713,18 +709,17 @@
 		drv->request_release = cx8802_request_release;
 		memcpy(driver, drv, sizeof(*driver));
 
+		mutex_lock(&drv->core->lock);
 		err = drv->probe(driver);
 		if (err == 0) {
 			i++;
-			mutex_lock(&drv->core->lock);
 			list_add_tail(&driver->drvlist, &dev->drvlist);
-			mutex_unlock(&drv->core->lock);
 		} else {
 			printk(KERN_ERR
 			       "%s/2: cx8802 probe failed, err = %d\n",
 			       dev->core->name, err);
 		}
-
+		mutex_unlock(&drv->core->lock);
 	}
 
 	return i ? 0 : -ENODEV;
@@ -748,6 +743,8 @@
 		       dev->pci->subsystem_device, dev->core->board.name,
 		       dev->core->boardnr);
 
+		mutex_lock(&dev->core->lock);
+
 		list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
 			/* only unregister the correct driver type */
 			if (d->type_id != drv->type_id)
@@ -755,15 +752,14 @@
 
 			err = d->remove(d);
 			if (err == 0) {
-				mutex_lock(&drv->core->lock);
 				list_del(&d->drvlist);
-				mutex_unlock(&drv->core->lock);
 				kfree(d);
 			} else
 				printk(KERN_ERR "%s/2: cx8802 driver remove "
 				       "failed (%d)\n", dev->core->name, err);
 		}
 
+		mutex_unlock(&dev->core->lock);
 	}
 
 	return err;
@@ -827,6 +823,8 @@
 
 	flush_request_modules(dev);
 
+	mutex_lock(&dev->core->lock);
+
 	if (!list_empty(&dev->drvlist)) {
 		struct cx8802_driver *drv, *tmp;
 		int err;
@@ -838,9 +836,7 @@
 		list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
 			err = drv->remove(drv);
 			if (err == 0) {
-				mutex_lock(&drv->core->lock);
 				list_del(&drv->drvlist);
-				mutex_unlock(&drv->core->lock);
 			} else
 				printk(KERN_ERR "%s/2: cx8802 driver remove "
 				       "failed (%d)\n", dev->core->name, err);
@@ -848,6 +844,8 @@
 		}
 	}
 
+	mutex_unlock(&dev->core->lock);
+
 	/* Destroy any 8802 reference. */
 	dev->core->dvbdev = NULL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/m52790.c linux-libre-2.6.38.8-gnu/drivers/media/video/m52790.c
--- linux-libre-2.6.38-gnu/drivers/media/video/m52790.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/m52790.c	2011-06-02 21:35:11.000000000 -0400
@@ -174,7 +174,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_core.c linux-libre-2.6.38.8-gnu/drivers/media/video/sn9c102/sn9c102_core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/sn9c102/sn9c102_core.c	2011-06-02 21:35:11.000000000 -0400
@@ -1430,9 +1430,9 @@
 		   sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
 		   sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
+static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
+static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
+static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
 static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tda9840.c linux-libre-2.6.38.8-gnu/drivers/media/video/tda9840.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tda9840.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/tda9840.c	2011-06-02 21:35:11.000000000 -0400
@@ -171,7 +171,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tea6415c.c linux-libre-2.6.38.8-gnu/drivers/media/video/tea6415c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tea6415c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/tea6415c.c	2011-06-02 21:35:11.000000000 -0400
@@ -152,7 +152,7 @@
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tea6420.c linux-libre-2.6.38.8-gnu/drivers/media/video/tea6420.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tea6420.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/tea6420.c	2011-06-02 21:35:11.000000000 -0400
@@ -125,7 +125,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tlg2300/pd-video.c linux-libre-2.6.38.8-gnu/drivers/media/video/tlg2300/pd-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tlg2300/pd-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/tlg2300/pd-video.c	2011-06-02 21:35:11.000000000 -0400
@@ -764,10 +764,8 @@
 	}
 	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
 				vid_resol, &cmd_status);
-	if (ret || cmd_status) {
-		mutex_unlock(&pd->lock);
+	if (ret || cmd_status)
 		return -EBUSY;
-	}
 
 	pix_def->pixelformat = pix->pixelformat; /* save it */
 	pix->height = (context->tvnormid & V4L2_STD_525_60) ?  480 : 576;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/upd64031a.c linux-libre-2.6.38.8-gnu/drivers/media/video/upd64031a.c
--- linux-libre-2.6.38-gnu/drivers/media/video/upd64031a.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/upd64031a.c	2011-06-02 21:35:11.000000000 -0400
@@ -230,7 +230,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/upd64083.c linux-libre-2.6.38.8-gnu/drivers/media/video/upd64083.c
--- linux-libre-2.6.38-gnu/drivers/media/video/upd64083.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/upd64083.c	2011-06-02 21:35:11.000000000 -0400
@@ -202,7 +202,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_driver.c linux-libre-2.6.38.8-gnu/drivers/media/video/uvc/uvc_driver.c
--- linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/uvc/uvc_driver.c	2011-06-02 21:35:11.000000000 -0400
@@ -1264,6 +1264,14 @@
 
 		break;
 
+	case UVC_OTT_VENDOR_SPECIFIC:
+	case UVC_OTT_DISPLAY:
+	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+		if (uvc_trace_param & UVC_TRACE_PROBE)
+			printk(" OT %d", entity->id);
+
+		break;
+
 	case UVC_TT_STREAMING:
 		if (UVC_ENTITY_IS_ITERM(entity)) {
 			if (uvc_trace_param & UVC_TRACE_PROBE)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_video.c linux-libre-2.6.38.8-gnu/drivers/media/video/uvc/uvc_video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/uvc/uvc_video.c	2011-06-02 21:35:11.000000000 -0400
@@ -89,15 +89,19 @@
 static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl)
 {
-	struct uvc_format *format;
+	struct uvc_format *format = NULL;
 	struct uvc_frame *frame = NULL;
 	unsigned int i;
 
-	if (ctrl->bFormatIndex <= 0 ||
-	    ctrl->bFormatIndex > stream->nformats)
-		return;
+	for (i = 0; i < stream->nformats; ++i) {
+		if (stream->format[i].index == ctrl->bFormatIndex) {
+			format = &stream->format[i];
+			break;
+		}
+	}
 
-	format = &stream->format[ctrl->bFormatIndex - 1];
+	if (format == NULL)
+		return;
 
 	for (i = 0; i < format->nframes; ++i) {
 		if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-device.c linux-libre-2.6.38.8-gnu/drivers/media/video/v4l2-device.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/media/video/v4l2-device.c	2011-06-02 21:35:11.000000000 -0400
@@ -131,14 +131,17 @@
 	sd->v4l2_dev = v4l2_dev;
 	if (sd->internal_ops && sd->internal_ops->registered) {
 		err = sd->internal_ops->registered(sd);
-		if (err)
+		if (err) {
+			module_put(sd->owner);
 			return err;
+		}
 	}
 	/* This just returns 0 if either of the two args is NULL */
 	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
 	if (err) {
 		if (sd->internal_ops && sd->internal_ops->unregistered)
 			sd->internal_ops->unregistered(sd);
+		module_put(sd->owner);
 		return err;
 	}
 	spin_lock(&v4l2_dev->lock);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab3100-core.c linux-libre-2.6.38.8-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab3100-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mfd/ab3100-core.c	2011-06-02 21:35:11.000000000 -0400
@@ -613,7 +613,7 @@
 	ab3100_get_priv.ab3100 = ab3100;
 	ab3100_get_priv.mode = false;
 	ab3100_get_reg_file = debugfs_create_file("get_reg",
-				S_IWUGO, ab3100_dir, &ab3100_get_priv,
+				S_IWUSR, ab3100_dir, &ab3100_get_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_get_reg_file) {
 		err = -ENOMEM;
@@ -623,7 +623,7 @@
 	ab3100_set_priv.ab3100 = ab3100;
 	ab3100_set_priv.mode = true;
 	ab3100_set_reg_file = debugfs_create_file("set_reg",
-				S_IWUGO, ab3100_dir, &ab3100_set_priv,
+				S_IWUSR, ab3100_dir, &ab3100_set_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_set_reg_file) {
 		err = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab3550-core.c linux-libre-2.6.38.8-gnu/drivers/mfd/ab3550-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab3550-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mfd/ab3550-core.c	2011-06-02 21:35:11.000000000 -0400
@@ -1053,17 +1053,17 @@
 		goto exit_destroy_dir;
 
 	ab3550_bank_file = debugfs_create_file("register-bank",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops);
 	if (!ab3550_bank_file)
 		goto exit_destroy_reg;
 
 	ab3550_address_file = debugfs_create_file("register-address",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops);
 	if (!ab3550_address_file)
 		goto exit_destroy_bank;
 
 	ab3550_val_file = debugfs_create_file("register-value",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
 	if (!ab3550_val_file)
 		goto exit_destroy_address;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-debugfs.c linux-libre-2.6.38.8-gnu/drivers/mfd/ab8500-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mfd/ab8500-debugfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -585,18 +585,18 @@
 		goto exit_destroy_dir;
 
 	ab8500_bank_file = debugfs_create_file("register-bank",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops);
 	if (!ab8500_bank_file)
 		goto exit_destroy_reg;
 
 	ab8500_address_file = debugfs_create_file("register-address",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev,
 		&ab8500_address_fops);
 	if (!ab8500_address_file)
 		goto exit_destroy_bank;
 
 	ab8500_val_file = debugfs_create_file("register-value",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
 	if (!ab8500_val_file)
 		goto exit_destroy_address;
 
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ep93xx_pwm.c linux-libre-2.6.38.8-gnu/drivers/misc/ep93xx_pwm.c
--- linux-libre-2.6.38-gnu/drivers/misc/ep93xx_pwm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/misc/ep93xx_pwm.c	2011-06-02 21:35:11.000000000 -0400
@@ -249,11 +249,11 @@
 
 static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
 static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
-static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
-static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
-static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
 
 static struct attribute *ep93xx_pwm_attrs[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/sdio.c linux-libre-2.6.38.8-gnu/drivers/mmc/core/sdio.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/sdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mmc/core/sdio.c	2011-06-02 21:35:11.000000000 -0400
@@ -395,6 +395,14 @@
 		if (err)
 			goto remove;
 
+		/*
+		 * Update oldcard with the new RCA received from the SDIO
+		 * device -- we're doing this so that it's updated in the
+		 * "card" struct when oldcard overwrites that later.
+		 */
+		if (oldcard)
+			oldcard->rca = card->rca;
+
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.c linux-libre-2.6.38.8-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mmc/host/sdhci.c	2011-06-02 21:35:11.000000000 -0400
@@ -1334,6 +1334,13 @@
 
 	host = (struct sdhci_host*)param;
 
+        /*
+         * If this tasklet gets rescheduled while running, it will
+         * be run again afterwards but without any active request.
+         */
+	if (!host->mrq)
+		return;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	del_timer(&host->timer);
@@ -1345,7 +1352,7 @@
 	 * upon error conditions.
 	 */
 	if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-		(mrq->cmd->error ||
+	    ((mrq->cmd && mrq->cmd->error) ||
 		 (mrq->data && (mrq->data->error ||
 		  (mrq->data->stop && mrq->data->stop->error))) ||
 		   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pci.c linux-libre-2.6.38.8-gnu/drivers/mmc/host/sdhci-pci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mmc/host/sdhci-pci.c	2011-06-02 21:35:11.000000000 -0400
@@ -547,6 +547,14 @@
 	},
 
 	{
+		.vendor         = PCI_VENDOR_ID_RICOH,
+		.device         = 0xe823,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.driver_data    = (kernel_ulong_t)&sdhci_ricoh_mmc,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_ENE,
 		.device		= PCI_DEVICE_ID_ENE_CB712_SD,
 		.subvendor	= PCI_ANY_ID,
@@ -953,6 +961,7 @@
 	host->ioaddr = pci_ioremap_bar(pdev, bar);
 	if (!host->ioaddr) {
 		dev_err(&pdev->dev, "failed to remap registers\n");
+		ret = -ENOMEM;
 		goto release;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdconcat.c linux-libre-2.6.38.8-gnu/drivers/mtd/mtdconcat.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdconcat.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mtd/mtdconcat.c	2011-06-02 21:35:11.000000000 -0400
@@ -319,7 +319,7 @@
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
-	ops->retlen = 0;
+	ops->retlen = ops->oobretlen = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
@@ -334,7 +334,7 @@
 			devops.len = subdev->size - to;
 
 		err = subdev->write_oob(subdev, to, &devops);
-		ops->retlen += devops.retlen;
+		ops->retlen += devops.oobretlen;
 		if (err)
 			return err;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_base.c linux-libre-2.6.38.8-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/mtd/nand/nand_base.c	2011-06-02 21:35:11.000000000 -0400
@@ -3111,6 +3111,8 @@
 		chip->chip_shift += 32 - 1;
 	}
 
+	chip->badblockbits = 8;
+
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
 		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c.h linux-libre-2.6.38.8-gnu/drivers/net/atl1c/atl1c.h
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/atl1c/atl1c.h	2011-06-02 21:35:11.000000000 -0400
@@ -566,9 +566,9 @@
 #define __AT_TESTING        0x0001
 #define __AT_RESETTING      0x0002
 #define __AT_DOWN           0x0003
-	u8 work_event;
-#define ATL1C_WORK_EVENT_RESET 		0x01
-#define ATL1C_WORK_EVENT_LINK_CHANGE	0x02
+	unsigned long work_event;
+#define	ATL1C_WORK_EVENT_RESET		0
+#define	ATL1C_WORK_EVENT_LINK_CHANGE	1
 	u32 msg_enable;
 
 	bool have_msi;
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_main.c linux-libre-2.6.38.8-gnu/drivers/net/atl1c/atl1c_main.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/atl1c/atl1c_main.c	2011-06-02 21:35:11.000000000 -0400
@@ -325,7 +325,7 @@
 		}
 	}
 
-	adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
+	set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
 	schedule_work(&adapter->common_task);
 }
 
@@ -337,20 +337,16 @@
 	adapter = container_of(work, struct atl1c_adapter, common_task);
 	netdev = adapter->netdev;
 
-	if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
-		adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
+	if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) {
 		netif_device_detach(netdev);
 		atl1c_down(adapter);
 		atl1c_up(adapter);
 		netif_device_attach(netdev);
-		return;
 	}
 
-	if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
-		adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
+	if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
+		&adapter->work_event))
 		atl1c_check_link_status(adapter);
-	}
-	return;
 }
 
 
@@ -369,7 +365,7 @@
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
 	/* Do the reset outside of interrupt context */
-	adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+	set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
 	schedule_work(&adapter->common_task);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.c linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_3ad.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_3ad.c	2011-06-02 21:35:11.000000000 -0400
@@ -1482,8 +1482,11 @@
 
 static int agg_device_up(const struct aggregator *agg)
 {
-	return (netif_running(agg->slave->dev) &&
-		netif_carrier_ok(agg->slave->dev));
+	struct port *port = agg->lag_ports;
+	if (!port)
+		return 0;
+	return (netif_running(port->slave->dev) &&
+		netif_carrier_ok(port->slave->dev));
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.c linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_alb.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_alb.c	2011-06-02 21:35:11.000000000 -0400
@@ -163,8 +163,6 @@
 	struct tlb_client_info *new_hashtbl;
 	int i;
 
-	spin_lock_init(&(bond_info->tx_hashtbl_lock));
-
 	new_hashtbl = kzalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
 		pr_err("%s: Error: Failed to allocate TLB hash table\n",
@@ -764,8 +762,6 @@
 	int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	int i;
 
-	spin_lock_init(&(bond_info->rx_hashtbl_lock));
-
 	new_hashtbl = kmalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
 		pr_err("%s: Error: Failed to allocate RLB hash table\n",
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_main.c linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_main.c	2011-06-02 21:35:11.000000000 -0400
@@ -1441,12 +1441,6 @@
 			   bond_dev->name, slave_dev->name);
 	}
 
-	/* bond must be initialized by bond_open() before enslaving */
-	if (!(bond_dev->flags & IFF_UP)) {
-		pr_warning("%s: master_dev is not up in bond_enslave\n",
-			   bond_dev->name);
-	}
-
 	/* already enslaved */
 	if (slave_dev->flags & IFF_SLAVE) {
 		pr_debug("Error, Device was already enslaved\n");
@@ -5157,9 +5151,19 @@
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
 	pr_debug("Begin bond_init for %s\n", bond_dev->name);
 
+	/*
+	 * Initialize locks that may be required during
+	 * en/deslave operations.  All of the bond_open work
+	 * (of which this is part) should really be moved to
+	 * a phase prior to dev_open
+	 */
+	spin_lock_init(&(bond_info->tx_hashtbl_lock));
+	spin_lock_init(&(bond_info->rx_hashtbl_lock));
+
 	bond->wq = create_singlethread_workqueue(bond_dev->name);
 	if (!bond->wq)
 		return -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/bonding/bond_sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -224,12 +224,6 @@
 	struct net_device *dev;
 	struct bonding *bond = to_bond(d);
 
-	/* Quick sanity check -- is the bond interface up? */
-	if (!(bond->dev->flags & IFF_UP)) {
-		pr_warning("%s: doing slave updates when interface is down.\n",
-			   bond->dev->name);
-	}
-
 	if (!rtnl_trylock())
 		return restart_syscall();
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000.c linux-libre-2.6.38.8-gnu/drivers/net/can/sja1000/sja1000.c
--- linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/can/sja1000/sja1000.c	2011-06-02 21:35:11.000000000 -0400
@@ -346,10 +346,10 @@
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
 
+	cf->can_dlc = get_can_dlc(fi & 0x0F);
 	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
 	} else {
-		cf->can_dlc = get_can_dlc(fi & 0x0F);
 		for (i = 0; i < cf->can_dlc; i++)
 			cf->data[i] = priv->read_reg(priv, dreg++);
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/slcan.c linux-libre-2.6.38.8-gnu/drivers/net/can/slcan.c
--- linux-libre-2.6.38-gnu/drivers/net/can/slcan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/can/slcan.c	2011-06-02 21:35:11.000000000 -0400
@@ -583,7 +583,9 @@
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
 	tty->receive_room = 65536;	/* We don't flow control */
-	return sl->dev->base_addr;
+
+	/* TTY layer expects 0 on success */
+	return 0;
 
 err_free_chan:
 	sl->tty = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_ethtool.c linux-libre-2.6.38.8-gnu/drivers/net/ehea/ehea_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/ehea/ehea_ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -55,15 +55,20 @@
 		cmd->duplex = -1;
 	}
 
-	cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full
-		       | SUPPORTED_100baseT_Full |  SUPPORTED_100baseT_Half
-		       | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half
-		       | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-	cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg
-			 | ADVERTISED_FIBRE);
+	if (cmd->speed == SPEED_10000) {
+		cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+		cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+		cmd->port = PORT_FIBRE;
+	} else {
+		cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full
+			       | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full
+			       | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg
+			       | SUPPORTED_TP);
+		cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg
+				 | ADVERTISED_TP);
+		cmd->port = PORT_TP;
+	}
 
-	cmd->port = PORT_FIBRE;
 	cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_main.c linux-libre-2.6.38.8-gnu/drivers/net/ehea/ehea_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/ehea/ehea_main.c	2011-06-02 21:35:11.000000000 -0400
@@ -2688,9 +2688,6 @@
 		netif_start_queue(dev);
 	}
 
-	init_waitqueue_head(&port->swqe_avail_wq);
-	init_waitqueue_head(&port->restart_wq);
-
 	mutex_unlock(&port->port_lock);
 
 	return ret;
@@ -3273,6 +3270,9 @@
 
 	INIT_WORK(&port->reset_task, ehea_reset_port);
 
+	init_waitqueue_head(&port->swqe_avail_wq);
+	init_waitqueue_head(&port->restart_wq);
+
 	ret = register_netdev(dev);
 	if (ret) {
 		pr_err("register_netdev failed. ret=%d\n", ret);
diff -druN linux-libre-2.6.38-gnu/drivers/net/gianfar.c linux-libre-2.6.38.8-gnu/drivers/net/gianfar.c
--- linux-libre-2.6.38-gnu/drivers/net/gianfar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/gianfar.c	2011-06-02 21:35:11.000000000 -0400
@@ -950,6 +950,11 @@
 			(pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
 		priv->errata |= GFAR_ERRATA_A002;
 
+	/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
+	if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
+			(pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
+		priv->errata |= GFAR_ERRATA_12;
+
 	if (priv->errata)
 		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
 			 priv->errata);
@@ -2156,8 +2161,15 @@
 	/* Set up checksumming */
 	if (CHECKSUM_PARTIAL == skb->ip_summed) {
 		fcb = gfar_add_fcb(skb);
-		lstatus |= BD_LFLAG(TXBD_TOE);
-		gfar_tx_checksum(skb, fcb);
+		/* as specified by errata */
+		if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12)
+			     && ((unsigned long)fcb % 0x20) > 0x18)) {
+			__skb_pull(skb, GMAC_FCB_LEN);
+			skb_checksum_help(skb);
+		} else {
+			lstatus |= BD_LFLAG(TXBD_TOE);
+			gfar_tx_checksum(skb, fcb);
+		}
 	}
 
 	if (vlan_tx_tag_present(skb)) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/gianfar.h linux-libre-2.6.38.8-gnu/drivers/net/gianfar.h
--- linux-libre-2.6.38-gnu/drivers/net/gianfar.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/gianfar.h	2011-06-02 21:35:11.000000000 -0400
@@ -1039,6 +1039,7 @@
 	GFAR_ERRATA_74		= 0x01,
 	GFAR_ERRATA_76		= 0x02,
 	GFAR_ERRATA_A002	= 0x04,
+	GFAR_ERRATA_12		= 0x08, /* a.k.a errata eTSEC49 */
 };
 
 /* Struct stolen almost completely (and shamelessly) from the FCC enet source
diff -druN linux-libre-2.6.38-gnu/drivers/net/hydra.c linux-libre-2.6.38.8-gnu/drivers/net/hydra.c
--- linux-libre-2.6.38-gnu/drivers/net/hydra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/hydra.c	2011-06-02 21:35:11.000000000 -0400
@@ -98,15 +98,15 @@
 	.ndo_open		= hydra_open,
 	.ndo_stop		= hydra_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -125,7 +125,7 @@
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
 
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/Kconfig linux-libre-2.6.38.8-gnu/drivers/net/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -2533,7 +2533,7 @@
 source "drivers/net/stmmac/Kconfig"
 
 config PCH_GBE
-	tristate "PCH Gigabit Ethernet"
+	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
 	depends on PCI
 	select MII
 	---help---
@@ -2545,6 +2545,12 @@
 	  to Gigabit Ethernet.
 	  This driver enables Gigabit Ethernet function.
 
+	  This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+	  Output Hub), ML7223.
+	  ML7223 IOH is for MP(Media Phone) use.
+	  ML7223 is companion chip for Intel Atom E6xx series.
+	  ML7223 is completely compatible for Intel EG20T PCH.
+
 endif # NETDEV_1000
 
 #
diff -druN linux-libre-2.6.38-gnu/drivers/net/macvlan.c linux-libre-2.6.38.8-gnu/drivers/net/macvlan.c
--- linux-libre-2.6.38-gnu/drivers/net/macvlan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/macvlan.c	2011-06-02 21:35:11.000000000 -0400
@@ -586,8 +586,8 @@
 	err = netdev_rx_handler_register(dev, macvlan_handle_frame, port);
 	if (err)
 		kfree(port);
-
-	dev->priv_flags |= IFF_MACVLAN_PORT;
+	else
+		dev->priv_flags |= IFF_MACVLAN_PORT;
 	return err;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/Makefile linux-libre-2.6.38.8-gnu/drivers/net/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -144,7 +144,7 @@
 obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
 
@@ -217,7 +217,7 @@
 obj-$(CONFIG_LP486E) += lp486e.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o
 obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
 obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
 obj-$(CONFIG_EQUALIZER) += eql.o
@@ -229,7 +229,7 @@
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/myri10ge/myri10ge.c linux-libre-2.6.38.8-gnu/drivers/net/myri10ge/myri10ge.c
--- linux-libre-2.6.38-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-24 01:08:05.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-25 07:13:05.000000000 -0400
@@ -3635,6 +3635,7 @@
 			dma_free_coherent(&pdev->dev, bytes,
 					  ss->fw_stats, ss->fw_stats_bus);
 			ss->fw_stats = NULL;
+			netif_napi_del(&ss->napi);
 		}
 	}
 	kfree(mgp->ss);
diff -druN linux-libre-2.6.38-gnu/drivers/net/ne-h8300.c linux-libre-2.6.38.8-gnu/drivers/net/ne-h8300.c
--- linux-libre-2.6.38-gnu/drivers/net/ne-h8300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/ne-h8300.c	2011-06-02 21:35:11.000000000 -0400
@@ -167,7 +167,7 @@
 #ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
-	struct net_device *dev = alloc_ei_netdev();
+	struct net_device *dev = ____alloc_ei_netdev(0);
 	int err;
 
 	if (!dev)
@@ -197,15 +197,15 @@
 	.ndo_open		= ne_open,
 	.ndo_stop		= ne_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -637,7 +637,7 @@
 	int err;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = alloc_ei_netdev();
+		struct net_device *dev = ____alloc_ei_netdev(0);
 		if (!dev)
 			break;
 		if (io[this_dev]) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ethtool.c linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -901,7 +901,7 @@
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	int hw_lro;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic.h linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic.h
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic.h	2012-03-24 01:08:10.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic.h	2012-03-25 07:13:07.000000000 -0400
@@ -174,7 +174,7 @@
 
 #define	MAX_NUM_CARDS		4
 
-#define MAX_BUFFERS_PER_CMD	32
+#define NETXEN_MAX_FRAGS_PER_TX	14
 #define MAX_TSO_HEADER_DESC	2
 #define MGMT_CMD_DESC_RESV	4
 #define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
@@ -558,7 +558,7 @@
  */
 struct netxen_cmd_buffer {
 	struct sk_buff *skb;
-	struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+	struct netxen_skb_frag frag_array[MAX_SKB_FRAGS + 1];
 	u32 frag_count;
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_main.c linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic_main.c
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_main.c	2012-03-24 01:08:16.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/netxen/netxen_nic_main.c	2012-03-25 07:13:10.000000000 -0400
@@ -1841,6 +1841,8 @@
 	struct cmd_desc_type0 *hwdesc, *first_desc;
 	struct pci_dev *pdev;
 	int i, k;
+	int delta = 0;
+	struct skb_frag_struct *frag;
 
 	u32 producer;
 	int frag_count, no_of_desc;
@@ -1848,6 +1850,21 @@
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
 
+	/* 14 frags supported for normal packet and
+	 * 32 frags supported for TSO packet
+	 */
+	if (!skb_is_gso(skb) && frag_count > NETXEN_MAX_FRAGS_PER_TX) {
+
+		for (i = 0; i < (frag_count - NETXEN_MAX_FRAGS_PER_TX); i++) {
+			frag = &skb_shinfo(skb)->frags[i];
+			delta += frag->size;
+		}
+
+		if (!__pskb_pull_tail(skb, delta))
+			goto drop_packet;
+
+		frag_count = 1 + skb_shinfo(skb)->nr_frags;
+	}
 	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_main.c linux-libre-2.6.38.8-gnu/drivers/net/pch_gbe/pch_gbe_main.c
--- linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/pch_gbe/pch_gbe_main.c	2011-06-02 21:35:11.000000000 -0400
@@ -34,6 +34,10 @@
 #define PCH_GBE_COPYBREAK_DEFAULT	256
 #define PCH_GBE_PCI_BAR			1
 
+/* Macros for ML7223 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7223_GBE		0x8013
+
 #define PCH_GBE_TX_WEIGHT         64
 #define PCH_GBE_RX_WEIGHT         64
 #define PCH_GBE_RX_BUFFER_WRITE   16
@@ -43,8 +47,7 @@
 
 #define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \
 	PCH_GBE_CHIP_TYPE_INTERNAL | \
-	PCH_GBE_RGMII_MODE_RGMII   | \
-	PCH_GBE_CRS_SEL              \
+	PCH_GBE_RGMII_MODE_RGMII     \
 	)
 
 /* Ethertype field values */
@@ -1494,12 +1497,11 @@
 			/* Write meta date of skb */
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, netdev);
-			if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) ==
-			    PCH_GBE_RXD_ACC_STAT_TCPIPOK) {
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-			} else {
+			if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
 				skb->ip_summed = CHECKSUM_NONE;
-			}
+			else
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+
 			napi_gro_receive(&adapter->napi, skb);
 			(*work_done)++;
 			pr_debug("Receive skb->ip_summed: %d length: %d\n",
@@ -2418,6 +2420,13 @@
 	 .subvendor = PCI_ANY_ID,
 	 .subdevice = PCI_ANY_ID,
 	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+	 .class_mask = (0xFFFF00)
+	 },
+	{.vendor = PCI_VENDOR_ID_ROHM,
+	 .device = PCI_DEVICE_ID_ROHM_ML7223_GBE,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
 	 .class_mask = (0xFFFF00)
 	 },
 	/* required last entry */
diff -druN linux-libre-2.6.38-gnu/drivers/net/pppoe.c linux-libre-2.6.38.8-gnu/drivers/net/pppoe.c
--- linux-libre-2.6.38-gnu/drivers/net/pppoe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/pppoe.c	2011-06-02 21:35:11.000000000 -0400
@@ -317,7 +317,7 @@
 			lock_sock(sk);
 
 			if (po->pppoe_dev == dev &&
-			    sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+			    sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
 				pppox_unbind_sock(sk);
 				sk->sk_state = PPPOX_ZOMBIE;
 				sk->sk_state_change(sk);
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_ethtool.c linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic_ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -1003,7 +1003,7 @@
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int hw_lro;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic.h linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic.h
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic.h	2012-03-24 01:08:21.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic.h	2012-03-25 07:13:12.000000000 -0400
@@ -99,6 +99,7 @@
 #define TX_UDPV6_PKT	0x0c
 
 /* Tx defines */
+#define QLCNIC_MAX_FRAGS_PER_TX	14
 #define MAX_TSO_HEADER_DESC	2
 #define MGMT_CMD_DESC_RESV	4
 #define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_main.c linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic_main.c
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_main.c	2012-03-24 01:08:27.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/qlcnic/qlcnic_main.c	2012-03-25 07:13:16.000000000 -0400
@@ -2099,6 +2099,7 @@
 	struct cmd_desc_type0 *hwdesc, *first_desc;
 	struct pci_dev *pdev;
 	struct ethhdr *phdr;
+	int delta = 0;
 	int i, k;
 
 	u32 producer;
@@ -2118,6 +2119,19 @@
 	}
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
+	/* 14 frags supported for normal packet and
+	 * 32 frags supported for TSO packet
+	 */
+	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+
+		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+			delta += skb_shinfo(skb)->frags[i].size;
+
+		if (!__pskb_pull_tail(skb, delta))
+			goto drop_packet;
+
+		frag_count = 1 + skb_shinfo(skb)->nr_frags;
+	}
 
 	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
diff -druN linux-libre-2.6.38-gnu/drivers/net/s2io.c linux-libre-2.6.38.8-gnu/drivers/net/s2io.c
--- linux-libre-2.6.38-gnu/drivers/net/s2io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/s2io.c	2011-06-02 21:35:11.000000000 -0400
@@ -6726,7 +6726,7 @@
 	int rc = 0;
 	int changed = 0;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (data & ETH_FLAG_LRO) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/slip.c linux-libre-2.6.38.8-gnu/drivers/net/slip.c
--- linux-libre-2.6.38-gnu/drivers/net/slip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/slip.c	2011-06-02 21:35:11.000000000 -0400
@@ -853,7 +853,9 @@
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
 	tty->receive_room = 65536;	/* We don't flow control */
-	return sl->dev->base_addr;
+
+	/* TTY layer expects 0 on success */
+	return 0;
 
 err_free_bufs:
 	sl_free_bufs(sl);
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ether.c linux-libre-2.6.38.8-gnu/drivers/net/usb/cdc_ether.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ether.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/usb/cdc_ether.c	2011-06-02 21:35:11.000000000 -0400
@@ -458,7 +458,7 @@
 	.manage_power =	cdc_manage_power,
 };
 
-static const struct driver_info mbm_info = {
+static const struct driver_info wwan_info = {
 	.description =	"Mobile Broadband Network Device",
 	.flags =	FLAG_WWAN,
 	.bind = 	cdc_bind,
@@ -469,6 +469,7 @@
 
 /*-------------------------------------------------------------------------*/
 
+#define HUAWEI_VENDOR_ID	0x12D1
 
 static const struct usb_device_id	products [] = {
 /*
@@ -578,8 +579,17 @@
 }, {
 	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
 			USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long)&mbm_info,
+	.driver_info = (unsigned long)&wwan_info,
 
+}, {
+	/* Various Huawei modems with a network port like the UMG1831 */
+	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+		 | USB_DEVICE_ID_MATCH_INT_INFO,
+	.idVendor               = HUAWEI_VENDOR_ID,
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol	= 255,
+	.driver_info = (unsigned long)&wwan_info,
 },
 	{ },		// END
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc-phonet.c linux-libre-2.6.38.8-gnu/drivers/net/usb/cdc-phonet.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc-phonet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/usb/cdc-phonet.c	2011-06-02 21:35:11.000000000 -0400
@@ -328,13 +328,13 @@
 {
 	static const char ifname[] = "usbpn%d";
 	const struct usb_cdc_union_desc *union_header = NULL;
-	const struct usb_cdc_header_desc *phonet_header = NULL;
 	const struct usb_host_interface *data_desc;
 	struct usb_interface *data_intf;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	struct net_device *dev;
 	struct usbpn_dev *pnd;
 	u8 *data;
+	int phonet = 0;
 	int len, err;
 
 	data = intf->altsetting->extra;
@@ -355,10 +355,7 @@
 					(struct usb_cdc_union_desc *)data;
 				break;
 			case 0xAB:
-				if (phonet_header || dlen < 5)
-					break;
-				phonet_header =
-					(struct usb_cdc_header_desc *)data;
+				phonet = 1;
 				break;
 			}
 		}
@@ -366,7 +363,7 @@
 		len -= dlen;
 	}
 
-	if (!union_header || !phonet_header)
+	if (!union_header || !phonet)
 		return -EINVAL;
 
 	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/ipheth.c linux-libre-2.6.38.8-gnu/drivers/net/usb/ipheth.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/ipheth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/usb/ipheth.c	2011-06-02 21:35:11.000000000 -0400
@@ -65,6 +65,7 @@
 #define IPHETH_USBINTF_PROTO    1
 
 #define IPHETH_BUF_SIZE         1516
+#define IPHETH_IP_ALIGN		2	/* padding at front of URB */
 #define IPHETH_TX_TIMEOUT       (5 * HZ)
 
 #define IPHETH_INTFNUM          2
@@ -202,18 +203,21 @@
 		return;
 	}
 
-	len = urb->actual_length;
-	buf = urb->transfer_buffer;
+	if (urb->actual_length <= IPHETH_IP_ALIGN) {
+		dev->net->stats.rx_length_errors++;
+		return;
+	}
+	len = urb->actual_length - IPHETH_IP_ALIGN;
+	buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
 
-	skb = dev_alloc_skb(NET_IP_ALIGN + len);
+	skb = dev_alloc_skb(len);
 	if (!skb) {
 		err("%s: dev_alloc_skb: -ENOMEM", __func__);
 		dev->net->stats.rx_dropped++;
 		return;
 	}
 
-	skb_reserve(skb, NET_IP_ALIGN);
-	memcpy(skb_put(skb, len), buf + NET_IP_ALIGN, len - NET_IP_ALIGN);
+	memcpy(skb_put(skb, len), buf, len);
 	skb->dev = dev->net;
 	skb->protocol = eth_type_trans(skb, dev->net);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_drv.c linux-libre-2.6.38.8-gnu/drivers/net/vmxnet3/vmxnet3_drv.c
--- linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2011-06-02 21:35:11.000000000 -0400
@@ -178,6 +178,7 @@
 vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 {
 	int i;
+	unsigned long flags;
 	u32 events = le32_to_cpu(adapter->shared->ecr);
 	if (!events)
 		return;
@@ -190,10 +191,10 @@
 
 	/* Check if there is an error on xmit/recv queues */
 	if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
-		spin_lock(&adapter->cmd_lock);
+		spin_lock_irqsave(&adapter->cmd_lock, flags);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_GET_QUEUE_STATUS);
-		spin_unlock(&adapter->cmd_lock);
+		spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			if (adapter->tqd_start[i].status.stopped)
@@ -2733,13 +2734,14 @@
 vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 {
 	u32 cfg;
+	unsigned long flags;
 
 	/* intr settings */
-	spin_lock(&adapter->cmd_lock);
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_GET_CONF_INTR);
 	cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
-	spin_unlock(&adapter->cmd_lock);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 	adapter->intr.type = cfg & 0x3;
 	adapter->intr.mask_mode = (cfg >> 2) & 0x3;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c linux-libre-2.6.38.8-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -304,13 +304,16 @@
 	u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
 	unsigned long flags;
 
-	if (data & ~ETH_FLAG_LRO)
-		return -EOPNOTSUPP;
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
+		return -EINVAL;
 
 	if (lro_requested ^ lro_present) {
 		/* toggle the LRO feature*/
 		netdev->features ^= NETIF_F_LRO;
 
+		/* Update private LRO flag */
+		adapter->lro = lro_requested;
+
 		/* update harware LRO capability accordingly */
 		if (lro_requested)
 			adapter->shared->devRead.misc.uptFeatures |=
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-ethtool.c linux-libre-2.6.38.8-gnu/drivers/net/vxge/vxge-ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/vxge/vxge-ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -1117,8 +1117,8 @@
 	struct vxgedev *vdev = netdev_priv(dev);
 	enum vxge_hw_status status;
 
-	if (data & ~ETH_FLAG_RXHASH)
-		return -EOPNOTSUPP;
+	if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
+		return -EINVAL;
 
 	if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
 		return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-06-02 21:35:11.000000000 -0400
@@ -652,7 +652,7 @@
 		.regDmn = { LE16(0), LE16(0x1f) },
 		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
 		.opCapFlags = {
-			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+			.opFlags = AR5416_OPFLAGS_11A,
 			.eepMisc = 0,
 		},
 		.rfSilent = 0,
@@ -922,7 +922,7 @@
 		.db_stage2 = {3, 3, 3}, /* 3 chain */
 		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
 		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */
-		.xpaBiasLvl = 0,
+		.xpaBiasLvl = 0xf,
 		.txFrameToDataStart = 0x0e,
 		.txFrameToPaOn = 0x0e,
 		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
@@ -3994,6 +3994,16 @@
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
 	    );
 
+        /* Write the power for duplicated frames - HT40 */
+
+        /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
+	REG_WRITE(ah, 0xa3e0,
+		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
+		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
+		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24],  8) |
+		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L],  0)
+	    );
+
 	/* Write the HT20 power per rate set */
 
 	/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-06-02 21:35:11.000000000 -0400
@@ -615,7 +615,7 @@
 		 */
 		if (rxsp->status11 & AR_CRCErr)
 			rxs->rs_status |= ATH9K_RXERR_CRC;
-		if (rxsp->status11 & AR_PHYErr) {
+		else if (rxsp->status11 & AR_PHYErr) {
 			phyerr = MS(rxsp->status11, AR_PHYErrCode);
 			/*
 			 * If we reach a point here where AR_PostDelimCRCErr is
@@ -638,11 +638,11 @@
 				rxs->rs_phyerr = phyerr;
 			}
 
-		}
-		if (rxsp->status11 & AR_DecryptCRCErr)
+		} else if (rxsp->status11 & AR_DecryptCRCErr)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (rxsp->status11 & AR_MichaelErr)
+		else if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/calib.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/calib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/calib.c	2011-06-02 21:35:11.000000000 -0400
@@ -69,15 +69,21 @@
 					      int16_t *nfarray)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_conf *conf = &common->hw->conf;
 	struct ath_nf_limits *limit;
 	struct ath9k_nfcal_hist *h;
 	bool high_nf_mid = false;
+	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
 	int i;
 
 	h = cal->nfCalHist;
 	limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
 
 	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (!(chainmask & (1 << i)) ||
+		    ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+			continue;
+
 		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
 
 		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
@@ -225,6 +231,7 @@
 	int32_t val;
 	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_conf *conf = &common->hw->conf;
 	s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
 
 	if (ah->caldata)
@@ -234,6 +241,9 @@
 		if (chainmask & (1 << i)) {
 			s16 nfval;
 
+			if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
+				continue;
+
 			if (h)
 				nfval = h[i].privNF;
 			else
@@ -293,6 +303,9 @@
 	ENABLE_REGWRITE_BUFFER(ah);
 	for (i = 0; i < NUM_NF_READINGS; i++) {
 		if (chainmask & (1 << i)) {
+			if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
+				continue;
+
 			val = REG_READ(ah, ah->nf_regs[i]);
 			val &= 0xFFFFFE00;
 			val |= (((u32) (-50) << 1) & 0x1ff);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/hw.c	2011-06-02 21:35:11.000000000 -0400
@@ -495,6 +495,17 @@
 	if (ah->hw_version.devid == AR5416_AR9100_DEVID)
 		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 
+	/*
+	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
+	 * We need to do this to avoid RMW of this register. We cannot
+	 * read the reg when chip is asleep.
+	 */
+	ah->WARegVal = REG_READ(ah, AR_WA);
+	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+			 AR_WA_ASPM_TIMER_BASED_DISABLE);
+
+	ath9k_hw_read_revisions(ah);
+
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
 		ath_err(common, "Couldn't reset chip\n");
 		return -EIO;
@@ -563,14 +574,6 @@
 
 	ath9k_hw_init_mode_regs(ah);
 
-	/*
-	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
-	 * We need to do this to avoid RMW of this register. We cannot
-	 * read the reg when chip is asleep.
-	 */
-	ah->WARegVal = REG_READ(ah, AR_WA);
-	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
-			 AR_WA_ASPM_TIMER_BASED_DISABLE);
 
 	if (ah->is_pciexpress)
 		ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -1082,8 +1085,6 @@
 		return false;
 	}
 
-	ath9k_hw_read_revisions(ah);
-
 	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
 }
 
@@ -1217,15 +1218,6 @@
 	ah->txchainmask = common->tx_chainmask;
 	ah->rxchainmask = common->rx_chainmask;
 
-	if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) {
-		ath9k_hw_abortpcurecv(ah);
-		if (!ath9k_hw_stopdmarecv(ah)) {
-			ath_dbg(common, ATH_DBG_XMIT,
-				"Failed to stop receive dma\n");
-			bChannelChange = false;
-		}
-	}
-
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/mac.c	2011-06-02 21:35:11.000000000 -0400
@@ -690,17 +690,23 @@
 		rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
 
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+		/*
+		 * Treat these errors as mutually exclusive to avoid spurious
+		 * extra error reports from the hardware. If a CRC error is
+		 * reported, then decryption and MIC errors are irrelevant,
+		 * the frame is going to be dropped either way
+		 */
 		if (ads.ds_rxstatus8 & AR_CRCErr)
 			rs->rs_status |= ATH9K_RXERR_CRC;
-		if (ads.ds_rxstatus8 & AR_PHYErr) {
+		else if (ads.ds_rxstatus8 & AR_PHYErr) {
 			rs->rs_status |= ATH9K_RXERR_PHY;
 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
 			rs->rs_phyerr = phyerr;
-		}
-		if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (ads.ds_rxstatus8 & AR_MichaelErr)
+		else if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
@@ -770,28 +776,47 @@
 }
 EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
 
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
 {
 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
 #define AH_RX_TIME_QUANTUM     100     /* usec */
 	struct ath_common *common = ath9k_hw_common(ah);
+	u32 mac_status, last_mac_status = 0;
 	int i;
 
+	/* Enable access to the DMA observation bus */
+	REG_WRITE(ah, AR_MACMISC,
+		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+		   (AR_MACMISC_MISC_OBS_BUS_1 <<
+		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
 	REG_WRITE(ah, AR_CR, AR_CR_RXD);
 
 	/* Wait for rx enable bit to go low */
 	for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
 		if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
 			break;
+
+		if (!AR_SREV_9300_20_OR_LATER(ah)) {
+			mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+			if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+				*reset = true;
+				break;
+			}
+
+			last_mac_status = mac_status;
+		}
+
 		udelay(AH_TIME_QUANTUM);
 	}
 
 	if (i == 0) {
 		ath_err(common,
-			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
 			AH_RX_STOP_DMA_TIMEOUT / 1000,
 			REG_READ(ah, AR_CR),
-			REG_READ(ah, AR_DIAG_SW));
+			REG_READ(ah, AR_DIAG_SW),
+			REG_READ(ah, AR_DMADBG_7));
 		return false;
 	} else {
 		return true;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/mac.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/mac.h	2011-06-02 21:35:11.000000000 -0400
@@ -692,7 +692,7 @@
 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
 void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_abortpcurecv(struct ath_hw *ah);
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
 int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 /* Interrupt Handling */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/main.c	2011-06-02 21:35:11.000000000 -0400
@@ -1063,6 +1063,8 @@
 		"Starting driver with initial channel: %d MHz\n",
 		curchan->center_freq);
 
+	ath9k_ps_wakeup(sc);
+
 	mutex_lock(&sc->mutex);
 
 	if (ath9k_wiphy_started(sc)) {
@@ -1179,6 +1181,8 @@
 mutex_unlock:
 	mutex_unlock(&sc->mutex);
 
+	ath9k_ps_restore(sc);
+
 	return r;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/recv.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/recv.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/recv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/recv.c	2011-06-02 21:35:11.000000000 -0400
@@ -439,9 +439,7 @@
 	 * mode interface or when in monitor mode. AP mode does not need this
 	 * since it receives all in-BSS frames anyway.
 	 */
-	if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
-	     (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
-	    (sc->sc_ah->is_monitoring))
+	if (sc->sc_ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
 	if (sc->rx.rxfilter & FIF_CONTROL)
@@ -515,12 +513,12 @@
 bool ath_stoprecv(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
-	bool stopped;
+	bool stopped, reset = false;
 
 	spin_lock_bh(&sc->rx.rxbuflock);
 	ath9k_hw_abortpcurecv(ah);
 	ath9k_hw_setrxfilter(ah, 0);
-	stopped = ath9k_hw_stopdmarecv(ah);
+	stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
 		ath_edma_stop_recv(sc);
@@ -535,7 +533,7 @@
 			"confusing the DMA engine when we start RX up\n");
 		ATH_DBG_WARN_ON_ONCE(!stopped);
 	}
-	return stopped;
+	return stopped && !reset;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2011-06-02 21:35:11.000000000 -0400
@@ -1699,8 +1699,8 @@
 	u8 tidno;
 
 	spin_lock_bh(&txctl->txq->axq_lock);
-
-	if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) {
+	if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
+		ieee80211_is_data_qos(hdr->frame_control)) {
 		tidno = ieee80211_get_qos_ctl(hdr)[0] &
 			IEEE80211_QOS_CTL_TID_MASK;
 		tid = ATH_AN_2_TID(txctl->an, tidno);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd_common.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/regd_common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/ath/regd_common.h	2011-06-02 21:35:11.000000000 -0400
@@ -195,6 +195,7 @@
 	{APL9_WORLD, CTL_ETSI, CTL_ETSI},
 
 	{APL3_FCCA, CTL_FCC, CTL_FCC},
+	{APL7_FCCA, CTL_FCC, CTL_FCC},
 	{APL1_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_APLD, CTL_FCC, NO_CTL},
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/b43/dma.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/b43/dma.c	2011-06-02 21:35:11.000000000 -0400
@@ -1536,7 +1536,7 @@
 		dmaaddr = meta->dmaaddr;
 		goto drop_recycle_buffer;
 	}
-	if (unlikely(len > ring->rx_buffersize)) {
+	if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
 		/* The data did not fit into one descriptor buffer
 		 * and is split over multiple buffers.
 		 * This should never happen, as we try to allocate buffers
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/b43/dma.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/b43/dma.h	2011-06-02 21:35:11.000000000 -0400
@@ -163,7 +163,7 @@
 /* DMA engine tuning knobs */
 #define B43_TXRING_SLOTS		256
 #define B43_RXRING_SLOTS		64
-#define B43_DMA0_RX_BUFFERSIZE		IEEE80211_MAX_FRAME_LEN
+#define B43_DMA0_RX_BUFFERSIZE		(B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
 
 /* Pointer poison */
 #define B43_DMA_PTR_POISON		((void *)ERR_PTR(-ENOMEM))
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	2012-03-24 01:12:08.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	2012-03-25 07:15:02.000000000 -0400
@@ -94,6 +94,7 @@
 struct iwl_mod_params iwl3945_mod_params = {
 	.sw_crypto = 1,
 	.restart_fw = 1,
+	.disable_hw_scan = 1,
 	/* the rest are 0 by default */
 };
 
@@ -3858,10 +3859,6 @@
 	priv->force_reset[IWL_FW_RESET].reset_duration =
 		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
-
-	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
-	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
-
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
 		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
 			 eeprom->version);
@@ -3995,8 +3992,7 @@
 	 * "the hard way", rather than using device's scan.
 	 */
 	if (iwl3945_mod_params.disable_hw_scan) {
-		dev_printk(KERN_DEBUG, &(pdev->dev),
-			"sw scan support is deprecated\n");
+		IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
 		iwl3945_hw_ops.hw_scan = NULL;
 	}
 
@@ -4318,8 +4314,7 @@
 #endif
 module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
 		   int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan,
-		 "disable hardware scanning (default 0) (deprecated)");
+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
 module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
 MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	2011-06-02 21:35:11.000000000 -0400
@@ -1823,7 +1823,7 @@
 
 	/* If we issue a new RXON command which required a tune then we must
 	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	rc = priv->cfg->ops->lib->send_tx_power(priv);
+	rc = iwl_set_tx_power(priv, priv->tx_power_next, true);
 	if (rc) {
 		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
 		return rc;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h	2011-06-02 21:35:11.000000000 -0400
@@ -74,8 +74,6 @@
 /* RSSI to dBm */
 #define IWL39_RSSI_OFFSET	95
 
-#define IWL_DEFAULT_TX_POWER	0x0F
-
 /*
  * EEPROM related constants, enums, and structures.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	2012-03-24 01:12:25.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	2012-03-25 07:15:11.000000000 -0400
@@ -1571,7 +1571,7 @@
 
 	/* If we issue a new RXON command which required a tune then we must
 	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
 	if (ret) {
 		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 		return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-24 01:12:19.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-25 07:15:08.000000000 -0400
@@ -3841,12 +3841,6 @@
 		priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
 	}
 
-	/* Set the tx_power_user_lmt to the lowest power level
-	 * this value will get overwritten by channel max power avg
-	 * from eeprom */
-	priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
-	priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
-
 	ret = iwl_init_channel_map(priv);
 	if (ret) {
 		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
@@ -4592,3 +4586,9 @@
 module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
 MODULE_PARM_DESC(bt_ch_inhibition,
 		 "Disable BT channel inhibition (default: enable)");
+
+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
+MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
+
+module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
+MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-06-02 21:35:11.000000000 -0400
@@ -604,6 +604,7 @@
 struct iwl_mod_params iwlagn_mod_params = {
 	.amsdu_size_8K = 1,
 	.restart_fw = 1,
+	.plcp_check = true,
 	/* the rest are 0 by default */
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	2011-06-02 21:35:11.000000000 -0400
@@ -288,10 +288,9 @@
 	 * If we issue a new RXON command which required a tune then we must
 	 * send a new TXPOWER command or we won't be able to Tx any frames.
 	 *
-	 * FIXME: which RXON requires a tune? Can we optimise this out in
-	 *        some cases?
+	 * It's expected we set power here if channel is changing.
 	 */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
 	if (ret) {
 		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 		return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-06-02 21:35:11.000000000 -0400
@@ -561,12 +561,17 @@
 
 	hdr_len = ieee80211_hdrlen(fc);
 
-	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-			       hdr->addr1);
-		goto drop_unlock;
+	/* For management frames use broadcast id to do not break aggregation */
+	if (!ieee80211_is_data(fc))
+		sta_id = ctx->bcast_sta_id;
+	else {
+		/* Find index into station table for destination station */
+		sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+		if (sta_id == IWL_INVALID_STATION) {
+			IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+				       hdr->addr1);
+			goto drop_unlock;
+		}
 	}
 
 	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -1207,12 +1212,16 @@
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
-		iwlagn_tx_status(priv, tx_info,
-				 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
+
+		if (WARN_ON_ONCE(tx_info->skb == NULL))
+			continue;
 
 		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-		if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+		if (ieee80211_is_data_qos(hdr->frame_control))
 			nfreed++;
+
+		iwlagn_tx_status(priv, tx_info,
+				 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
 		tx_info->skb = NULL;
 
 		if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-core.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2011-06-02 21:35:11.000000000 -0400
@@ -168,6 +168,7 @@
 	struct ieee80211_channel *geo_ch;
 	struct ieee80211_rate *rates;
 	int i = 0;
+	s8 max_tx_power = 0;
 
 	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
 	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
@@ -244,8 +245,8 @@
 
 			geo_ch->flags |= ch->ht40_extension_channel;
 
-			if (ch->max_power_avg > priv->tx_power_device_lmt)
-				priv->tx_power_device_lmt = ch->max_power_avg;
+			if (ch->max_power_avg > max_tx_power)
+				max_tx_power = ch->max_power_avg;
 		} else {
 			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
 		}
@@ -258,6 +259,10 @@
 				 geo_ch->flags);
 	}
 
+	priv->tx_power_device_lmt = max_tx_power;
+	priv->tx_power_user_lmt = max_tx_power;
+	priv->tx_power_next = max_tx_power;
+
 	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
 	     priv->cfg->sku & IWL_SKU_A) {
 		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
@@ -1161,6 +1166,8 @@
 {
 	int ret;
 	s8 prev_tx_power;
+	bool defer;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	lockdep_assert_held(&priv->mutex);
 
@@ -1188,10 +1195,15 @@
 	if (!iwl_is_ready_rf(priv))
 		return -EIO;
 
-	/* scan complete use tx_power_next, need to be updated */
+	/* scan complete and commit_rxon use tx_power_next value,
+	 * it always need to be updated for newest request */
 	priv->tx_power_next = tx_power;
-	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
-		IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+
+	/* do not set tx power when scanning or channel changing */
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
+		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+	if (defer && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
 		return 0;
 	}
 
@@ -1867,6 +1879,15 @@
 
 	mutex_lock(&priv->mutex);
 
+	if (!ctx->vif || !iwl_is_ready_rf(priv)) {
+		/*
+		 * Huh? But wait ... this can maybe happen when
+		 * we're in the middle of a firmware restart!
+		 */
+		err = -EBUSY;
+		goto out;
+	}
+
 	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
 
 	if (!(interface_modes & BIT(newtype))) {
@@ -1894,6 +1915,7 @@
 	/* success */
 	iwl_teardown_interface(priv, vif, true);
 	vif->type = newtype;
+	vif->p2p = newp2p;
 	err = iwl_setup_interface(priv, ctx);
 	WARN_ON(err);
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2011-06-02 21:35:11.000000000 -0400
@@ -263,6 +263,8 @@
 	int amsdu_size_8K;	/* def: 1 = enable 8K amsdu size */
 	int antenna;  		/* def: 0 = both antennas (use diversity) */
 	int restart_fw;		/* def: 1 = restart firmware */
+	bool plcp_check;	/* def: true = enable plcp health check */
+	bool ack_check;		/* def: false = disable ack health check */
 };
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-06-02 21:35:11.000000000 -0400
@@ -1604,21 +1604,24 @@
 	     ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++)	\
 		if (priv->valid_contexts & BIT(ctx->ctxid))
 
-static inline int iwl_is_associated(struct iwl_priv *priv,
-				    enum iwl_rxon_context_id ctxid)
+static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
 {
-	return (priv->contexts[ctxid].active.filter_flags &
-			RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+	return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
 }
 
-static inline int iwl_is_any_associated(struct iwl_priv *priv)
+static inline int iwl_is_associated(struct iwl_priv *priv,
+				    enum iwl_rxon_context_id ctxid)
 {
-	return iwl_is_associated(priv, IWL_RXON_CTX_BSS);
+	return iwl_is_associated_ctx(&priv->contexts[ctxid]);
 }
 
-static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
+static inline int iwl_is_any_associated(struct iwl_priv *priv)
 {
-	return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+	struct iwl_rxon_context *ctx;
+	for_each_context(priv, ctx)
+		if (iwl_is_associated_ctx(ctx))
+			return true;
+	return false;
 }
 
 static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-06-02 21:35:11.000000000 -0400
@@ -724,13 +724,6 @@
 					     flags & EEPROM_CHANNEL_RADAR))
 				       ? "" : "not ");
 
-			/* Set the tx_power_user_lmt to the highest power
-			 * supported by any channel */
-			if (eeprom_ch_info[ch].max_power_avg >
-						priv->tx_power_user_lmt)
-				priv->tx_power_user_lmt =
-				    eeprom_ch_info[ch].max_power_avg;
-
 			ch_info++;
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-06-02 21:35:11.000000000 -0400
@@ -241,7 +241,7 @@
 
 /* 6x00 Specific */
 #define EEPROM_6000_TX_POWER_VERSION    (4)
-#define EEPROM_6000_EEPROM_VERSION	(0x434)
+#define EEPROM_6000_EEPROM_VERSION	(0x423)
 
 /* 6x50 Specific */
 #define EEPROM_6050_TX_POWER_VERSION    (4)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c	2011-06-02 21:35:11.000000000 -0400
@@ -123,6 +123,13 @@
 			goto set_ch_out;
 		}
 
+		if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+		    !is_channel_ibss(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - not IBSS channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
 		spin_lock_irqsave(&priv->lock, flags);
 
 		for_each_context(priv, ctx) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-06-02 21:35:11.000000000 -0400
@@ -234,10 +234,13 @@
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt)
 {
+	const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
+
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 	if (iwl_is_any_associated(priv)) {
-		if (priv->cfg->ops->lib->check_ack_health) {
+		if (mod_params->ack_check &&
+		    priv->cfg->ops->lib->check_ack_health) {
 			if (!priv->cfg->ops->lib->check_ack_health(
 			    priv, pkt)) {
 				/*
@@ -250,7 +253,8 @@
 					return;
 			}
 		}
-		if (priv->cfg->ops->lib->check_plcp_health) {
+		if (mod_params->plcp_check &&
+		    priv->cfg->ops->lib->check_plcp_health) {
 			if (!priv->cfg->ops->lib->check_plcp_health(
 			    priv, pkt)) {
 				/*
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cmd.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/libertas/cmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/libertas/cmd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1335,8 +1335,8 @@
 				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 
@@ -1348,8 +1348,8 @@
 				    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 					priv->needtowakeup = 1;
@@ -1362,7 +1362,9 @@
 				       "EXEC_NEXT_CMD: sending EXIT_PS\n");
 			}
 		}
+		spin_lock_irqsave(&priv->driver_lock, flags);
 		list_del(&cmdnode->list);
+		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
 			    le16_to_cpu(cmd->command));
 		lbs_submit_command(priv, cmdnode);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54usb.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/p54/p54usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-24 01:13:46.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-25 07:15:51.000000000 -0400
@@ -55,6 +55,7 @@
 	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
 	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
 	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
+	{USB_DEVICE(0x0bf8, 0x1007)},	/* Fujitsu E-5400 USB */
 	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
 	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */
 	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */
@@ -67,6 +68,7 @@
 	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
 	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
 	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */
+	{USB_DEVICE(0x2001, 0x3762)},	/* Conceptronic C54U */
 	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */
 	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */
 
@@ -79,6 +81,7 @@
 	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */
 	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
 	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
+	{USB_DEVICE(0x083a, 0xc501)},	/* Zoom Wireless-G 4410 */
 	{USB_DEVICE(0x083a, 0xf503)},	/* Accton FD7050E ver 1010ec  */
 	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */
 	{USB_DEVICE(0x0915, 0x2000)},	/* Cohiba Proto board */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/txrx.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/p54/txrx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/txrx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/p54/txrx.c	2011-06-02 21:35:11.000000000 -0400
@@ -705,7 +705,7 @@
 	struct p54_tx_info *p54info;
 	struct p54_hdr *hdr;
 	struct p54_tx_data *txhdr;
-	unsigned int padding, len, extra_len;
+	unsigned int padding, len, extra_len = 0;
 	int i, j, ridx;
 	u16 hdr_flags = 0, aid = 0;
 	u8 rate, queue = 0, crypt_offset = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2011-06-02 21:35:11.000000000 -0400
@@ -2810,10 +2810,7 @@
 
 	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
 	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
 	/* Wait for DMA, ignore error */
@@ -2823,9 +2820,6 @@
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
 }
 EXPORT_SYMBOL_GPL(rt2800_disable_radio);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800pci.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2800pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2012-03-24 01:14:22.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2012-03-25 07:16:10.000000000 -0400
@@ -475,39 +475,23 @@
 
 static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
-
-	rt2800_disable_radio(rt2x00dev);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
-
-	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	if (rt2x00_is_soc(rt2x00dev)) {
+		rt2800_disable_radio(rt2x00dev);
+		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+	}
 }
 
 static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	/*
-	 * Always put the device to sleep (even when we intend to wakeup!)
-	 * if the device is booting and wasn't asleep it will return
-	 * failure when attempting to wakeup.
-	 */
-	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
-
 	if (state == STATE_AWAKE) {
-		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
+	} else if (state == STATE_SLEEP) {
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -1031,8 +1031,10 @@
 	 * Stop all work.
 	 */
 	cancel_work_sync(&rt2x00dev->intf_work);
-	cancel_work_sync(&rt2x00dev->rxdone_work);
-	cancel_work_sync(&rt2x00dev->txdone_work);
+	if (rt2x00_is_usb(rt2x00dev)) {
+		cancel_work_sync(&rt2x00dev->rxdone_work);
+		cancel_work_sync(&rt2x00dev->txdone_work);
+	}
 
 	/*
 	 * Free the tx status fifo.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -871,23 +871,35 @@
 	/* The RTL8187 returns the retry count through register 0xFFFA. In
 	 * addition, it appears to be a cumulative retry count, not the
 	 * value for the current TX packet. When multiple TX entries are
-	 * queued, the retry count will be valid for the last one in the queue.
-	 * The "error" should not matter for purposes of rate setting. */
+	 * waiting in the queue, the retry count will be the total for all.
+	 * The "error" may matter for purposes of rate setting, but there is
+	 * no other choice with this hardware.
+	 */
 	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
 				    work.work);
 	struct ieee80211_tx_info *info;
 	struct ieee80211_hw *dev = priv->dev;
 	static u16 retry;
 	u16 tmp;
+	u16 avg_retry;
+	int length;
 
 	mutex_lock(&priv->conf_mutex);
 	tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA);
+	length = skb_queue_len(&priv->b_tx_status.queue);
+	if (unlikely(!length))
+		length = 1;
+	if (unlikely(tmp < retry))
+		tmp = retry;
+	avg_retry = (tmp - retry) / length;
 	while (skb_queue_len(&priv->b_tx_status.queue) > 0) {
 		struct sk_buff *old_skb;
 
 		old_skb = skb_dequeue(&priv->b_tx_status.queue);
 		info = IEEE80211_SKB_CB(old_skb);
-		info->status.rates[0].count = tmp - retry + 1;
+		info->status.rates[0].count = avg_retry + 1;
+		if (info->status.rates[0].count > RETRY_COUNT)
+			info->flags &= ~IEEE80211_TX_STAT_ACK;
 		ieee80211_tx_status_irqsafe(dev, old_skb);
 	}
 	retry = tmp;
@@ -933,8 +945,8 @@
 		rtl818x_iowrite32(priv, &priv->map->TX_CONF,
 				  RTL818X_TX_CONF_HW_SEQNUM |
 				  RTL818X_TX_CONF_DISREQQSIZE |
-				  (7 << 8  /* short retry limit */) |
-				  (7 << 0  /* long retry limit */) |
+				  (RETRY_COUNT << 8  /* short retry limit */) |
+				  (RETRY_COUNT << 0  /* long retry limit */) |
 				  (7 << 21 /* MAX TX DMA */));
 		rtl8187_init_urbs(dev);
 		rtl8187b_init_status_urb(dev);
@@ -1378,6 +1390,9 @@
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_SIGNAL_DBM |
 		     IEEE80211_HW_RX_INCLUDES_FCS;
+	/* Initialize rate-control variables */
+	dev->max_rates = 1;
+	dev->max_rate_tries = RETRY_COUNT;
 
 	eeprom.data = dev;
 	eeprom.register_read = rtl8187_eeprom_register_read;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h linux-libre-2.6.38.8-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h	2011-06-02 21:35:11.000000000 -0400
@@ -35,6 +35,8 @@
 #define RFKILL_MASK_8187_89_97	0x2
 #define RFKILL_MASK_8198	0x4
 
+#define RETRY_COUNT		7
+
 struct rtl8187_rx_info {
 	struct urb *urb;
 	struct ieee80211_hw *dev;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/testmode.c linux-libre-2.6.38.8-gnu/drivers/net/wireless/wl12xx/testmode.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/testmode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/wireless/wl12xx/testmode.c	2011-06-02 21:35:11.000000000 -0400
@@ -204,7 +204,10 @@
 
 	kfree(wl->nvs);
 
-	wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+	if (len != sizeof(struct wl1271_nvs_file))
+		return -EINVAL;
+
+	wl->nvs = kzalloc(len, GFP_KERNEL);
 	if (!wl->nvs) {
 		wl1271_error("could not allocate memory for the nvs file");
 		ret = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/net/zorro8390.c linux-libre-2.6.38.8-gnu/drivers/net/zorro8390.c
--- linux-libre-2.6.38-gnu/drivers/net/zorro8390.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/net/zorro8390.c	2011-06-02 21:35:11.000000000 -0400
@@ -126,7 +126,7 @@
 
     board = z->resource.start;
     ioaddr = board+cards[i].offset;
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
     if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
@@ -146,15 +146,15 @@
 static const struct net_device_ops zorro8390_netdev_ops = {
 	.ndo_open		= zorro8390_open,
 	.ndo_stop		= zorro8390_close,
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpiphp_glue.c linux-libre-2.6.38.8-gnu/drivers/pci/hotplug/acpiphp_glue.c
--- linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpiphp_glue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/pci/hotplug/acpiphp_glue.c	2011-06-02 21:35:11.000000000 -0400
@@ -212,6 +212,7 @@
 
 	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
 	if (pdev) {
+		pdev->current_state = PCI_D0;
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 		pci_dev_put(pdev);
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/pci/intel-iommu.c linux-libre-2.6.38.8-gnu/drivers/pci/intel-iommu.c
--- linux-libre-2.6.38-gnu/drivers/pci/intel-iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/pci/intel-iommu.c	2011-06-02 21:35:11.000000000 -0400
@@ -1835,7 +1835,7 @@
 
 	ret = iommu_attach_domain(domain, iommu);
 	if (ret) {
-		domain_exit(domain);
+		free_domain_mem(domain);
 		goto error;
 	}
 
@@ -3260,9 +3260,15 @@
 	if (!domain)
 		return 0;
 
-	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
 		domain_remove_one_dev_info(domain, pdev);
 
+		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+		    list_empty(&domain->devices))
+			domain_exit(domain);
+	}
+
 	return 0;
 }
 
@@ -3411,6 +3417,11 @@
 		domain->iommu_count--;
 		domain_update_iommu_cap(domain);
 		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+		spin_lock_irqsave(&iommu->lock, tmp_flags);
+		clear_bit(domain->id, iommu->domain_ids);
+		iommu->domains[domain->id] = NULL;
+		spin_unlock_irqrestore(&iommu->lock, tmp_flags);
 	}
 
 	spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3627,9 +3638,9 @@
 
 		pte = dmar_domain->pgd;
 		if (dma_pte_present(pte)) {
-			free_pgtable_page(dmar_domain->pgd);
 			dmar_domain->pgd = (struct dma_pte *)
 				phys_to_virt(dma_pte_addr(pte));
+			free_pgtable_page(pte);
 		}
 		dmar_domain->agaw--;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/aspm.c linux-libre-2.6.38.8-gnu/drivers/pci/pcie/aspm.c
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/aspm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/pci/pcie/aspm.c	2011-06-02 21:35:11.000000000 -0400
@@ -69,6 +69,7 @@
 };
 
 static int aspm_disabled, aspm_force, aspm_clear_state;
+static bool aspm_support_enabled = true;
 static DEFINE_MUTEX(aspm_lock);
 static LIST_HEAD(link_list);
 
@@ -896,6 +897,7 @@
 {
 	if (!strcmp(str, "off")) {
 		aspm_disabled = 1;
+		aspm_support_enabled = false;
 		printk(KERN_INFO "PCIe ASPM is disabled\n");
 	} else if (!strcmp(str, "force")) {
 		aspm_force = 1;
@@ -930,3 +932,8 @@
 }
 EXPORT_SYMBOL(pcie_aspm_enabled);
 
+bool pcie_aspm_support_enabled(void)
+{
+	return aspm_support_enabled;
+}
+EXPORT_SYMBOL(pcie_aspm_support_enabled);
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci-sysfs.c linux-libre-2.6.38.8-gnu/drivers/pci/pci-sysfs.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/pci/pci-sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -1088,7 +1088,7 @@
 		attr->write = write_vpd_attr;
 		retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
 		if (retval) {
-			kfree(dev->vpd->attr);
+			kfree(attr);
 			return retval;
 		}
 		dev->vpd->attr = attr;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/quirks.c linux-libre-2.6.38.8-gnu/drivers/pci/quirks.c
--- linux-libre-2.6.38-gnu/drivers/pci/quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/pci/quirks.c	2011-06-02 21:35:11.000000000 -0400
@@ -533,6 +533,17 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi);
 
+#define ICH_PMBASE	0x40
+#define ICH_ACPI_CNTL	0x44
+#define  ICH4_ACPI_EN	0x10
+#define  ICH6_ACPI_EN	0x80
+#define ICH4_GPIOBASE	0x58
+#define ICH4_GPIO_CNTL	0x5c
+#define  ICH4_GPIO_EN	0x10
+#define ICH6_GPIOBASE	0x48
+#define ICH6_GPIO_CNTL	0x4c
+#define  ICH6_GPIO_EN	0x10
+
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
@@ -541,12 +552,33 @@
 static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
+	/*
+	 * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict
+	 * with low legacy (and fixed) ports. We don't know the decoding
+	 * priority and can't tell whether the legacy device or the one created
+	 * here is really at that address.  This happens on boards with broken
+	 * BIOSes.
+	*/
 
-	pci_read_config_dword(dev, 0x58, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH4_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH4 ACPI/GPIO/TCO");
+	}
+
+	pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH4_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
+	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi);
@@ -562,12 +594,25 @@
 static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH6_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH6 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x48, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+	pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH6_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
+	}
 }
 
 static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -2618,58 +2663,6 @@
 
 #endif /* CONFIG_PCI_MSI */
 
-#ifdef CONFIG_PCI_IOV
-
-/*
- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
- * old Flash Memory Space.
- */
-static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
-{
-	int pos, flags;
-	u32 bar, start, size;
-
-	if (PAGE_SIZE > 0x10000)
-		return;
-
-	flags = pci_resource_flags(dev, 0);
-	if ((flags & PCI_BASE_ADDRESS_SPACE) !=
-			PCI_BASE_ADDRESS_SPACE_MEMORY ||
-	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
-			PCI_BASE_ADDRESS_MEM_TYPE_32)
-		return;
-
-	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
-	if (!pos)
-		return;
-
-	pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
-	if (bar & PCI_BASE_ADDRESS_MEM_MASK)
-		return;
-
-	start = pci_resource_start(dev, 1);
-	size = pci_resource_len(dev, 1);
-	if (!start || size != 0x400000 || start & (size - 1))
-		return;
-
-	pci_resource_flags(dev, 1) = 0;
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
-
-	dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
-
-#endif	/* CONFIG_PCI_IOV */
-
 /* Allow manual resource allocation for PCI hotplug bridges
  * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
  * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6),
@@ -2791,6 +2784,16 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
 #endif
 
+static void __devinit fixup_ti816x_class(struct pci_dev* dev)
+{
+	/* TI 816x devices do not have class code set when in PCIe boot mode */
+	if (dev->class == PCI_CLASS_NOT_DEFINED) {
+		dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
+		dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+	}
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/acer-wmi.c linux-libre-2.6.38.8-gnu/drivers/platform/x86/acer-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/acer-wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/platform/x86/acer-wmi.c	2011-06-02 21:35:11.000000000 -0400
@@ -222,6 +222,7 @@
 static struct rfkill *wireless_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *threeg_rfkill;
+static bool rfkill_inited;
 
 /* Each low-level interface must define at least some of the following */
 struct wmi_interface {
@@ -1161,9 +1162,13 @@
 {
 	acpi_status status;
 	u32 cap = (unsigned long)data;
-	status = set_u32(!blocked, cap);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+
+	if (rfkill_inited) {
+		status = set_u32(!blocked, cap);
+		if (ACPI_FAILURE(status))
+			return -ENODEV;
+	}
+
 	return 0;
 }
 
@@ -1187,14 +1192,16 @@
 		return ERR_PTR(-ENOMEM);
 
 	status = get_device_status(&state, cap);
-	if (ACPI_SUCCESS(status))
-		rfkill_init_sw_state(rfkill_dev, !state);
 
 	err = rfkill_register(rfkill_dev);
 	if (err) {
 		rfkill_destroy(rfkill_dev);
 		return ERR_PTR(err);
 	}
+
+	if (ACPI_SUCCESS(status))
+		rfkill_set_sw_state(rfkill_dev, !state);
+
 	return rfkill_dev;
 }
 
@@ -1229,6 +1236,8 @@
 		}
 	}
 
+	rfkill_inited = true;
+
 	schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/ideapad-laptop.c linux-libre-2.6.38.8-gnu/drivers/platform/x86/ideapad-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/ideapad-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/platform/x86/ideapad-laptop.c	2011-06-02 21:35:11.000000000 -0400
@@ -459,6 +459,8 @@
 		if (test_bit(vpc_bit, &vpc1)) {
 			if (vpc_bit == 9)
 				ideapad_sync_rfk_state(adevice);
+			else if (vpc_bit == 4)
+				read_ec_data(handle, 0x12, &vpc2);
 			else
 				ideapad_input_report(priv, vpc_bit);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_ips.c linux-libre-2.6.38.8-gnu/drivers/platform/x86/intel_ips.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_ips.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/platform/x86/intel_ips.c	2011-06-02 21:35:11.000000000 -0400
@@ -1111,7 +1111,7 @@
 		last_msecs = jiffies_to_msecs(jiffies);
 		expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD);
 
-		__set_current_state(TASK_UNINTERRUPTIBLE);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		mod_timer(&timer, expire);
 		schedule();
 
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/thinkpad_acpi.c linux-libre-2.6.38.8-gnu/drivers/platform/x86/thinkpad_acpi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/thinkpad_acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/platform/x86/thinkpad_acpi.c	2011-06-02 21:35:11.000000000 -0400
@@ -128,7 +128,8 @@
 };
 
 /* ACPI HIDs */
-#define TPACPI_ACPI_HKEY_HID		"IBM0068"
+#define TPACPI_ACPI_IBM_HKEY_HID	"IBM0068"
+#define TPACPI_ACPI_LENOVO_HKEY_HID	"LEN0068"
 #define TPACPI_ACPI_EC_HID		"PNP0C09"
 
 /* Input IDs */
@@ -3879,7 +3880,8 @@
 }
 
 static const struct acpi_device_id ibm_htk_device_ids[] = {
-	{TPACPI_ACPI_HKEY_HID, 0},
+	{TPACPI_ACPI_IBM_HKEY_HID, 0},
+	{TPACPI_ACPI_LENOVO_HKEY_HID, 0},
 	{"", 0},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/idtcps.c linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/idtcps.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/idtcps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/idtcps.c	2011-06-02 21:35:11.000000000 -0400
@@ -26,6 +26,9 @@
 {
 	u32 result;
 
+	if (route_port == RIO_INVALID_ROUTE)
+		route_port = CPS_DEFAULT_ROUTE;
+
 	if (table == RIO_GLOBAL_TABLE) {
 		rio_mport_write_config_32(mport, destid, hopcount,
 				RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
@@ -130,6 +133,9 @@
 		/* set TVAL = ~50us */
 		rio_write_config_32(rdev,
 			rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev,
+				    RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/idt_gen2.c linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/idt_gen2.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/idt_gen2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/idt_gen2.c	2011-06-02 21:35:11.000000000 -0400
@@ -95,6 +95,9 @@
 	else
 		table++;
 
+	if (route_port == RIO_INVALID_ROUTE)
+		route_port = IDT_DEFAULT_ROUTE;
+
 	rio_mport_write_config_32(mport, destid, hopcount,
 				  LOCAL_RTE_CONF_DESTID_SEL, table);
 
@@ -411,6 +414,12 @@
 	rdev->rswitch->em_handle = idtg2_em_handler;
 	rdev->rswitch->sw_sysfs = idtg2_sysfs;
 
+	if (do_enum) {
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev,
+				    RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE);
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/tsi57x.c linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/tsi57x.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/tsi57x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rapidio/switches/tsi57x.c	2011-06-02 21:35:11.000000000 -0400
@@ -303,6 +303,12 @@
 	rdev->rswitch->em_init = tsi57x_em_init;
 	rdev->rswitch->em_handle = tsi57x_em_handler;
 
+	if (do_enum) {
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT,
+				    RIO_INVALID_ROUTE);
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-bfin.c linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-bfin.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-bfin.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-bfin.c	2011-06-02 21:35:11.000000000 -0400
@@ -276,6 +276,8 @@
 		bfin_rtc_int_set_alarm(rtc);
 	else
 		bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+
+	return 0;
 }
 
 static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1511.c linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-ds1511.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1511.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-ds1511.c	2011-06-02 21:35:11.000000000 -0400
@@ -485,7 +485,7 @@
 static struct bin_attribute ds1511_nvram_attr = {
 	.attr = {
 		.name = "nvram",
-		.mode = S_IRUGO | S_IWUGO,
+		.mode = S_IRUGO | S_IWUSR,
 	},
 	.size = DS1511_RAM_MAX,
 	.read = ds1511_nvram_read,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-s3c.c linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-s3c.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-s3c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/rtc/rtc-s3c.c	2011-06-02 21:35:11.000000000 -0400
@@ -46,6 +46,7 @@
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
 static int s3c_rtc_tickno  = NO_IRQ;
+static bool wake_en;
 static enum s3c_cpu_type s3c_rtc_cpu_type;
 
 static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
@@ -597,8 +598,12 @@
 	}
 	s3c_rtc_enable(pdev, 0);
 
-	if (device_may_wakeup(&pdev->dev))
-		enable_irq_wake(s3c_rtc_alarmno);
+	if (device_may_wakeup(&pdev->dev) && !wake_en) {
+		if (enable_irq_wake(s3c_rtc_alarmno) == 0)
+			wake_en = true;
+		else
+			dev_err(&pdev->dev, "enable_irq_wake failed\n");
+	}
 
 	return 0;
 }
@@ -614,8 +619,10 @@
 		writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
 	}
 
-	if (device_may_wakeup(&pdev->dev))
+	if (device_may_wakeup(&pdev->dev) && wake_en) {
 		disable_irq_wake(s3c_rtc_alarmno);
+		wake_en = false;
+	}
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2011-06-02 21:35:11.000000000 -0400
@@ -1221,6 +1221,7 @@
 	iscsi_init.dummy_buffer_addr_hi =
 		(u32) ((u64) hba->dummy_buf_dma >> 32);
 
+	hba->num_ccell = hba->max_sqes >> 1;
 	hba->ctx_ccell_tasks =
 			((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16));
 	iscsi_init.num_ccells_per_conn = hba->num_ccell;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_init.c linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2011-06-02 21:35:11.000000000 -0400
@@ -227,7 +227,7 @@
 	wait_event_interruptible_timeout(hba->eh_wait,
 					 (list_empty(&hba->ep_ofld_list) &&
 					 list_empty(&hba->ep_destroy_list)),
-					 10 * HZ);
+					 2 * HZ);
 	/* Wait for all endpoints to be torn down, Chip will be reset once
 	 *  control returns to network driver. So it is required to cleanup and
 	 * release all connection resources before returning from this routine.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2011-06-02 21:35:11.000000000 -0400
@@ -858,7 +858,7 @@
 	mutex_init(&hba->net_dev_lock);
 	init_waitqueue_head(&hba->eh_wait);
 	if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
-		hba->hba_shutdown_tmo = 20 * HZ;
+		hba->hba_shutdown_tmo = 30 * HZ;
 		hba->conn_teardown_tmo = 20 * HZ;
 		hba->conn_ctx_destroy_tmo = 6 * HZ;
 	} else {	/* 5706/5708/5709 */
@@ -1205,6 +1205,9 @@
 	struct bnx2i_cmd *cmd = task->dd_data;
 	struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
 
+	if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
+		return -ENOMEM;
+
 	/*
 	 * If there is no scsi_cmnd this must be a mgmt task
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_alua.c linux-libre-2.6.38.8-gnu/drivers/scsi/device_handler/scsi_dh_alua.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2011-06-02 21:35:11.000000000 -0400
@@ -285,7 +285,8 @@
 			    print_alua_state(h->state));
 	}
 done:
-	blk_put_request(req);
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
 	if (h->callback_fn) {
 		h->callback_fn(h->callback_data, err);
 		h->callback_fn = h->callback_data = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh.c linux-libre-2.6.38.8-gnu/drivers/scsi/device_handler/scsi_dh.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/device_handler/scsi_dh.c	2011-06-02 21:35:11.000000000 -0400
@@ -437,12 +437,14 @@
 	unsigned long flags;
 	struct scsi_device *sdev;
 	struct scsi_device_handler *scsi_dh = NULL;
+	struct device *dev = NULL;
 
 	spin_lock_irqsave(q->queue_lock, flags);
 	sdev = q->queuedata;
 	if (sdev && sdev->scsi_dh_data)
 		scsi_dh = sdev->scsi_dh_data->scsi_dh;
-	if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+	dev = get_device(&sdev->sdev_gendev);
+	if (!scsi_dh || !dev ||
 	    sdev->sdev_state == SDEV_CANCEL ||
 	    sdev->sdev_state == SDEV_DEL)
 		err = SCSI_DH_NOSYS;
@@ -453,12 +455,13 @@
 	if (err) {
 		if (fn)
 			fn(data, err);
-		return err;
+		goto out;
 	}
 
 	if (scsi_dh->activate)
 		err = scsi_dh->activate(sdev, fn, data);
-	put_device(&sdev->sdev_gendev);
+out:
+	put_device(dev);
 	return err;
 }
 EXPORT_SYMBOL_GPL(scsi_dh_activate);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_base.c linux-libre-2.6.38.8-gnu/drivers/scsi/megaraid/megaraid_sas_base.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2011-06-02 21:35:11.000000000 -0400
@@ -4611,6 +4611,9 @@
 	 * For each user buffer, create a mirror buffer and copy in
 	 */
 	for (i = 0; i < ioc->sge_count; i++) {
+		if (!ioc->sgl[i].iov_len)
+			continue;
+
 		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
 						    ioc->sgl[i].iov_len,
 						    &buf_handle, GFP_KERNEL);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c linux-libre-2.6.38.8-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c	2011-06-02 21:35:11.000000000 -0400
@@ -688,6 +688,13 @@
 		goto out;
 	}
 
+	/* Check for overflow and wraparound */
+	if (karg.data_sge_offset * 4 > ioc->request_sz ||
+	    karg.data_sge_offset > (UINT_MAX / 4)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* copy in request message frame from user */
 	if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
 		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
@@ -1963,7 +1970,7 @@
 	Mpi2DiagBufferPostReply_t *mpi_reply;
 	int rc, i;
 	u8 buffer_type;
-	unsigned long timeleft;
+	unsigned long timeleft, request_size, copy_size;
 	u16 smid;
 	u16 ioc_status;
 	u8 issue_reset = 0;
@@ -1999,6 +2006,8 @@
 		return -ENOMEM;
 	}
 
+	request_size = ioc->diag_buffer_sz[buffer_type];
+
 	if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
 		printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
 		    "or bytes_to_read are not 4 byte aligned\n", ioc->name,
@@ -2006,13 +2015,23 @@
 		return -EINVAL;
 	}
 
+	if (karg.starting_offset > request_size)
+		return -EINVAL;
+
 	diag_data = (void *)(request_data + karg.starting_offset);
 	dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
 	    "offset(%d), sz(%d)\n", ioc->name, __func__,
 	    diag_data, karg.starting_offset, karg.bytes_to_read));
 
+	/* Truncate data on requests that are too large */
+	if ((diag_data + karg.bytes_to_read < diag_data) ||
+	    (diag_data + karg.bytes_to_read > request_data + request_size))
+		copy_size = request_size - karg.starting_offset;
+	else
+		copy_size = karg.bytes_to_read;
+
 	if (copy_to_user((void __user *)uarg->diagnostic_data,
-	    diag_data, karg.bytes_to_read)) {
+	    diag_data, copy_size)) {
 		printk(MPT2SAS_ERR_FMT "%s: Unable to write "
 		    "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
 		    __func__, diag_data);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c linux-libre-2.6.38.8-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2011-06-02 21:35:11.000000000 -0400
@@ -113,6 +113,7 @@
 };
 
 
+#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
 #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
 
 /**
@@ -121,6 +122,7 @@
  * @work: work object (ioc->fault_reset_work_q)
  * @cancel_pending_work: flag set during reset handling
  * @ioc: per adapter object
+ * @device_handle: device handle
  * @VF_ID: virtual function id
  * @VP_ID: virtual port id
  * @ignore: flag meaning this event has been marked to ignore
@@ -134,6 +136,7 @@
 	u8			cancel_pending_work;
 	struct delayed_work	delayed_work;
 	struct MPT2SAS_ADAPTER *ioc;
+	u16			device_handle;
 	u8			VF_ID;
 	u8			VP_ID;
 	u8			ignore;
@@ -3708,17 +3711,75 @@
 #endif
 
 /**
- * _scsih_smart_predicted_fault - illuminate Fault LED
+ * _scsih_turn_on_fault_led - illuminate Fault LED
  * @ioc: per adapter object
  * @handle: device handle
+ * Context: process
  *
  * Return nothing.
  */
 static void
-_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+_scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 {
 	Mpi2SepReply_t mpi_reply;
 	Mpi2SepRequest_t mpi_request;
+
+	memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
+	mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+	mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
+	mpi_request.SlotStatus =
+	    cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+	mpi_request.DevHandle = cpu_to_le16(handle);
+	mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
+	if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
+	    &mpi_request)) != 0) {
+		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
+		__FILE__, __LINE__, __func__);
+		return;
+	}
+
+	if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
+		dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
+		    "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
+		    le16_to_cpu(mpi_reply.IOCStatus),
+		    le32_to_cpu(mpi_reply.IOCLogInfo)));
+		return;
+	}
+}
+
+/**
+ * _scsih_send_event_to_turn_on_fault_led - fire delayed event
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+	struct fw_event_work *fw_event;
+
+	fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+	if (!fw_event)
+		return;
+	fw_event->event = MPT2SAS_TURN_ON_FAULT_LED;
+	fw_event->device_handle = handle;
+	fw_event->ioc = ioc;
+	_scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * _scsih_smart_predicted_fault - process smart errors
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
 	struct scsi_target *starget;
 	struct MPT2SAS_TARGET *sas_target_priv_data;
 	Mpi2EventNotificationReply_t *event_reply;
@@ -3745,30 +3806,8 @@
 	starget_printk(KERN_WARNING, starget, "predicted fault\n");
 	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
-	if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) {
-		memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
-		mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-		mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
-		mpi_request.SlotStatus =
-		    cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
-		mpi_request.DevHandle = cpu_to_le16(handle);
-		mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
-		if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
-		    &mpi_request)) != 0) {
-			printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-			    ioc->name, __FILE__, __LINE__, __func__);
-			return;
-		}
-
-		if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
-			dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-			    "enclosure_processor: ioc_status (0x%04x), "
-			    "loginfo(0x%08x)\n", ioc->name,
-			    le16_to_cpu(mpi_reply.IOCStatus),
-			    le32_to_cpu(mpi_reply.IOCLogInfo)));
-			return;
-		}
-	}
+	if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
+		_scsih_send_event_to_turn_on_fault_led(ioc, handle);
 
 	/* insert into event log */
 	sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
@@ -6330,6 +6369,9 @@
 	}
 
 	switch (fw_event->event) {
+	case MPT2SAS_TURN_ON_FAULT_LED:
+		_scsih_turn_on_fault_led(ioc, fw_event->device_handle);
+		break;
 	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
 		_scsih_sas_topology_change_event(ioc, fw_event);
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.c linux-libre-2.6.38.8-gnu/drivers/scsi/pmcraid.c
--- linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/pmcraid.c	2011-06-02 21:35:11.000000000 -0400
@@ -3814,6 +3814,9 @@
 			rc = -EFAULT;
 			goto out_free_buffer;
 		}
+	} else if (request_size < 0) {
+		rc = -EINVAL;
+		goto out_free_buffer;
 	}
 
 	/* check if we have any additional command parameters */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_attr.c linux-libre-2.6.38.8-gnu/drivers/scsi/qla2xxx/qla_attr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_attr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/qla2xxx/qla_attr.c	2011-06-02 21:35:11.000000000 -0400
@@ -1877,14 +1877,15 @@
 
 	scsi_remove_host(vha->host);
 
+	/* Allow timer to run to drain queued items, when removing vp */
+	qla24xx_deallocate_vp_id(vha);
+
 	if (vha->timer_active) {
 		qla2x00_vp_stop_timer(vha);
 		DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
 		" = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
 	}
 
-	qla24xx_deallocate_vp_id(vha);
-
 	/* No pending activities shall be there on the vha now */
 	DEBUG(msleep(random32()%10));  /* Just to see if something falls on
 					* the net we have placed below */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_os.c linux-libre-2.6.38.8-gnu/drivers/scsi/qla2xxx/qla_os.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_os.c	2012-03-24 01:18:28.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/qla2xxx/qla_os.c	2012-03-25 07:18:09.000000000 -0400
@@ -2359,21 +2359,26 @@
 	base_vha = pci_get_drvdata(pdev);
 	ha = base_vha->hw;
 
-	spin_lock_irqsave(&ha->vport_slock, flags);
-	list_for_each_entry(vha, &ha->vp_list, list) {
-		atomic_inc(&vha->vref_count);
+	mutex_lock(&ha->vport_lock);
+	while (ha->cur_vport_count) {
+		struct Scsi_Host *scsi_host;
 
-		if (vha->fc_vport) {
-			spin_unlock_irqrestore(&ha->vport_slock, flags);
+		spin_lock_irqsave(&ha->vport_slock, flags);
 
-			fc_vport_terminate(vha->fc_vport);
+		BUG_ON(base_vha->list.next == &ha->vp_list);
+		/* This assumes first entry in ha->vp_list is always base vha */
+		vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
+		scsi_host = scsi_host_get(vha->host);
 
-			spin_lock_irqsave(&ha->vport_slock, flags);
-		}
+		spin_unlock_irqrestore(&ha->vport_slock, flags);
+		mutex_unlock(&ha->vport_lock);
 
-		atomic_dec(&vha->vref_count);
+		fc_vport_terminate(vha->fc_vport);
+		scsi_host_put(vha->host);
+
+		mutex_lock(&ha->vport_lock);
 	}
-	spin_unlock_irqrestore(&ha->vport_slock, flags);
+	mutex_unlock(&ha->vport_lock);
 
 	set_bit(UNLOADING, &base_vha->dpc_flags);
 
@@ -3603,7 +3608,8 @@
 	if (!pci_channel_offline(ha->pdev))
 		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
 
-	if (IS_QLA82XX(ha)) {
+	/* Make sure qla82xx_watchdog is run only for physical port */
+	if (!vha->vp_idx && IS_QLA82XX(ha)) {
 		if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
 			start_dpc++;
 		qla82xx_watchdog(vha);
@@ -3674,8 +3680,8 @@
 		    atomic_read(&vha->loop_down_timer)));
 	}
 
-	/* Check if beacon LED needs to be blinked */
-	if (ha->beacon_blink_led == 1) {
+	/* Check if beacon LED needs to be blinked for physical host only */
+	if (!vha->vp_idx && (ha->beacon_blink_led == 1)) {
 		set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
 		start_dpc++;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_lib.c linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_lib.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_lib.c	2011-06-02 21:35:11.000000000 -0400
@@ -400,10 +400,15 @@
 static void scsi_run_queue(struct request_queue *q)
 {
 	struct scsi_device *sdev = q->queuedata;
-	struct Scsi_Host *shost = sdev->host;
+	struct Scsi_Host *shost;
 	LIST_HEAD(starved_list);
 	unsigned long flags;
 
+	/* if the device is dead, sdev will be NULL, so no queue to run */
+	if (!sdev)
+		return;
+
+	shost = sdev->host;
 	if (scsi_target(sdev)->single_lun)
 		scsi_single_lun_run(sdev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_sysfs.c linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -322,14 +322,8 @@
 		kfree(evt);
 	}
 
-	if (sdev->request_queue) {
-		sdev->request_queue->queuedata = NULL;
-		/* user context needed to free queue */
-		scsi_free_queue(sdev->request_queue);
-		/* temporary expedient, try to catch use of queue lock
-		 * after free of sdev */
-		sdev->request_queue = NULL;
-	}
+	/* NULL queue means the device can't be used */
+	sdev->request_queue = NULL;
 
 	scsi_target_reap(scsi_target(sdev));
 
@@ -937,6 +931,12 @@
 	if (sdev->host->hostt->slave_destroy)
 		sdev->host->hostt->slave_destroy(sdev);
 	transport_destroy_device(dev);
+
+	/* cause the request function to reject all I/O requests */
+	sdev->request_queue->queuedata = NULL;
+
+	/* Freeing the queue signals to block that we're done */
+	scsi_free_queue(sdev->request_queue);
 	put_device(dev);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_iscsi.c linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_transport_iscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_iscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/scsi_transport_iscsi.c	2011-06-02 21:35:11.000000000 -0400
@@ -1847,7 +1847,7 @@
 #define iscsi_priv_session_rw_attr(field, format)			\
 	iscsi_priv_session_attr_show(field, format)			\
 	iscsi_priv_session_attr_store(field)				\
-static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUGO,		\
+static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR,		\
 			show_priv_session_##field,			\
 			store_priv_session_##field)
 iscsi_priv_session_rw_attr(recovery_tmo, "%d");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sd.c linux-libre-2.6.38.8-gnu/drivers/scsi/sd.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/sd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1910,14 +1910,10 @@
 	int old_rcd = sdkp->RCD;
 	int old_dpofua = sdkp->DPOFUA;
 
-	if (sdp->skip_ms_page_8) {
-		if (sdp->type == TYPE_RBC)
-			goto defaults;
-		else {
-			modepage = 0x3F;
-			dbd = 0;
-		}
-	} else if (sdp->type == TYPE_RBC) {
+	if (sdp->skip_ms_page_8)
+		goto defaults;
+
+	if (sdp->type == TYPE_RBC) {
 		modepage = 6;
 		dbd = 8;
 	} else {
@@ -1945,11 +1941,13 @@
 	 */
 	if (len < 3)
 		goto bad_sense;
-	else if (len > SD_BUF_SIZE) {
-		sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
-			  "data from %d to %d bytes\n", len, SD_BUF_SIZE);
-		len = SD_BUF_SIZE;
-	}
+	if (len > 20)
+		len = 20;
+
+	/* Take headers and block descriptors into account */
+	len += data.header_length + data.block_descriptor_length;
+	if (len > SD_BUF_SIZE)
+		goto bad_sense;
 
 	/* Get the data */
 	res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1957,45 +1955,16 @@
 	if (scsi_status_is_good(res)) {
 		int offset = data.header_length + data.block_descriptor_length;
 
-		while (offset < len) {
-			u8 page_code = buffer[offset] & 0x3F;
-			u8 spf       = buffer[offset] & 0x40;
-
-			if (page_code == 8 || page_code == 6) {
-				/* We're interested only in the first 3 bytes.
-				 */
-				if (len - offset <= 2) {
-					sd_printk(KERN_ERR, sdkp, "Incomplete "
-						  "mode parameter data\n");
-					goto defaults;
-				} else {
-					modepage = page_code;
-					goto Page_found;
-				}
-			} else {
-				/* Go to the next page */
-				if (spf && len - offset > 3)
-					offset += 4 + (buffer[offset+2] << 8) +
-						buffer[offset+3];
-				else if (!spf && len - offset > 1)
-					offset += 2 + buffer[offset+1];
-				else {
-					sd_printk(KERN_ERR, sdkp, "Incomplete "
-						  "mode parameter data\n");
-					goto defaults;
-				}
-			}
+		if (offset >= SD_BUF_SIZE - 2) {
+			sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
+			goto defaults;
 		}
 
-		if (modepage == 0x3F) {
-			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
-				  "present\n");
-			goto defaults;
-		} else if ((buffer[offset] & 0x3f) != modepage) {
+		if ((buffer[offset] & 0x3f) != modepage) {
 			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
 			goto defaults;
 		}
-	Page_found:
+
 		if (modepage == 8) {
 			sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
 			sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ses.c linux-libre-2.6.38.8-gnu/drivers/scsi/ses.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ses.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/ses.c	2011-06-02 21:35:11.000000000 -0400
@@ -390,9 +390,9 @@
 		len = (desc_ptr[2] << 8) + desc_ptr[3];
 		/* skip past overall descriptor */
 		desc_ptr += len + 4;
-		if (ses_dev->page10)
-			addl_desc_ptr = ses_dev->page10 + 8;
 	}
+	if (ses_dev->page10)
+		addl_desc_ptr = ses_dev->page10 + 8;
 	type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
 	components = 0;
 	for (i = 0; i < types; i++, type_ptr += 4) {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sr.c linux-libre-2.6.38.8-gnu/drivers/scsi/sr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/sr.c	2011-06-02 21:35:11.000000000 -0400
@@ -636,7 +636,7 @@
 	disk->first_minor = minor;
 	sprintf(disk->disk_name, "sr%d", minor);
 	disk->fops = &sr_bdops;
-	disk->flags = GENHD_FL_CD;
+	disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
 	disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
 
 	blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ultrastor.c linux-libre-2.6.38.8-gnu/drivers/scsi/ultrastor.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ultrastor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/scsi/ultrastor.c	2011-06-02 21:35:11.000000000 -0400
@@ -306,7 +306,7 @@
 	"0: bsfw %1,%w0\n\t"
 	"btr %0,%1\n\t"
 	"jnc 0b"
-	: "=&r" (rv), "=m" (*field) :);
+	: "=&r" (rv), "+m" (*field) :);
 
   return rv;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/sh/clk/cpg.c linux-libre-2.6.38.8-gnu/drivers/sh/clk/cpg.c
--- linux-libre-2.6.38-gnu/drivers/sh/clk/cpg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/sh/clk/cpg.c	2011-06-02 21:35:11.000000000 -0400
@@ -105,7 +105,7 @@
 
 	/* Rebuild the frequency table */
 	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-			     table, &clk->arch_flags);
+			     table, NULL);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/hv/channel.c linux-libre-2.6.38.8-gnu/drivers/staging/hv/channel.c
--- linux-libre-2.6.38-gnu/drivers/staging/hv/channel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/hv/channel.c	2011-06-02 21:35:11.000000000 -0400
@@ -76,14 +76,14 @@
 
 	if (channel->offermsg.monitor_allocated) {
 		/* Each u32 represents 32 channels */
-		set_bit(channel->offermsg.child_relid & 31,
+		sync_set_bit(channel->offermsg.child_relid & 31,
 			(unsigned long *) gVmbusConnection.SendInterruptPage +
 			(channel->offermsg.child_relid >> 5));
 
 		monitorpage = gVmbusConnection.MonitorPages;
 		monitorpage++; /* Get the child to parent monitor page */
 
-		set_bit(channel->monitor_bit,
+		sync_set_bit(channel->monitor_bit,
 			(unsigned long *)&monitorpage->trigger_group
 					[channel->monitor_grp].pending);
 
@@ -99,7 +99,7 @@
 
 	if (Channel->offermsg.monitor_allocated) {
 		/* Each u32 represents 32 channels */
-		clear_bit(Channel->offermsg.child_relid & 31,
+		sync_clear_bit(Channel->offermsg.child_relid & 31,
 			  (unsigned long *)gVmbusConnection.SendInterruptPage +
 			  (Channel->offermsg.child_relid >> 5));
 
@@ -107,7 +107,7 @@
 			(struct hv_monitor_page *)gVmbusConnection.MonitorPages;
 		monitorPage++; /* Get the child to parent monitor page */
 
-		clear_bit(Channel->monitor_bit,
+		sync_clear_bit(Channel->monitor_bit,
 			  (unsigned long *)&monitorPage->trigger_group
 					[Channel->monitor_grp].Pending);
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/hv/connection.c linux-libre-2.6.38.8-gnu/drivers/staging/hv/connection.c
--- linux-libre-2.6.38-gnu/drivers/staging/hv/connection.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/hv/connection.c	2011-06-02 21:35:11.000000000 -0400
@@ -281,7 +281,7 @@
 		for (dword = 0; dword < maxdword; dword++) {
 			if (recvInterruptPage[dword]) {
 				for (bit = 0; bit < 32; bit++) {
-					if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
+					if (sync_test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
 						relid = (dword << 5) + bit;
 						DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
 
@@ -320,7 +320,7 @@
 int VmbusSetEvent(u32 childRelId)
 {
 	/* Each u32 represents 32 channels */
-	set_bit(childRelId & 31,
+	sync_set_bit(childRelId & 31,
 		(unsigned long *)gVmbusConnection.SendInterruptPage +
 		(childRelId >> 5));
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/hv/netvsc_drv.c linux-libre-2.6.38.8-gnu/drivers/staging/hv/netvsc_drv.c
--- linux-libre-2.6.38-gnu/drivers/staging/hv/netvsc_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/hv/netvsc_drv.c	2011-06-02 21:35:11.000000000 -0400
@@ -46,6 +46,7 @@
 	/* point back to our device context */
 	struct vm_device *device_ctx;
 	unsigned long avail;
+	struct work_struct work;
 };
 
 struct netvsc_driver_context {
@@ -225,6 +226,7 @@
 				       unsigned int status)
 {
 	struct vm_device *device_ctx = to_vm_device(device_obj);
+	struct net_device_context *ndev_ctx;
 	struct net_device *net = dev_get_drvdata(&device_ctx->device);
 
 	if (!net) {
@@ -237,6 +239,8 @@
 		netif_carrier_on(net);
 		netif_wake_queue(net);
 		netif_notify_peers(net);
+		ndev_ctx = netdev_priv(net);
+		schedule_work(&ndev_ctx->work);
 	} else {
 		netif_carrier_off(net);
 		netif_stop_queue(net);
@@ -336,6 +340,25 @@
 	.ndo_set_mac_address =		eth_mac_addr,
 };
 
+/*
+ * Send GARP packet to network peers after migrations.
+ * After Quick Migration, the network is not immediately operational in the
+ * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
+ * another netif_notify_peers() into a scheduled work, otherwise GARP packet
+ * will not be sent after quick migration, and cause network disconnection.
+ */
+static void netvsc_send_garp(struct work_struct *w)
+{
+	struct net_device_context *ndev_ctx;
+	struct net_device *net;
+
+	msleep(20);
+	ndev_ctx = container_of(w, struct net_device_context, work);
+	net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
+	netif_notify_peers(net);
+}
+
+
 static int netvsc_probe(struct device *device)
 {
 	struct driver_context *driver_ctx =
@@ -364,6 +387,7 @@
 	net_device_ctx->device_ctx = device_ctx;
 	net_device_ctx->avail = ring_size;
 	dev_set_drvdata(device, net);
+	INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
 
 	/* Notify the netvsc driver of the new device */
 	ret = net_drv_obj->base.OnDeviceAdd(device_obj, &device_info);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/hv/vmbus_drv.c linux-libre-2.6.38.8-gnu/drivers/staging/hv/vmbus_drv.c
--- linux-libre-2.6.38-gnu/drivers/staging/hv/vmbus_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/hv/vmbus_drv.c	2011-06-02 21:35:11.000000000 -0400
@@ -291,7 +291,7 @@
 	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
 
 	/* Since we are a child, we only need to check bit 0 */
-	if (test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
+	if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
 		DPRINT_DBG(VMBUS, "received event %d", event->flags32[0]);
 		ret |= 0x2;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/hv/vmbus_private.h linux-libre-2.6.38.8-gnu/drivers/staging/hv/vmbus_private.h
--- linux-libre-2.6.38-gnu/drivers/staging/hv/vmbus_private.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/hv/vmbus_private.h	2011-06-02 21:35:11.000000000 -0400
@@ -31,6 +31,7 @@
 #include "channel_mgmt.h"
 #include "ring_buffer.h"
 #include <linux/list.h>
+#include <asm/sync_bitops.h>
 
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400_core.c linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400_core.c
--- linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400_core.c	2011-06-02 21:35:11.000000000 -0400
@@ -93,7 +93,6 @@
 			.tx_buf = st->tx + 2,
 			.bits_per_word = 8,
 			.len = 2,
-			.cs_change = 1,
 		},
 	};
 
@@ -137,7 +136,6 @@
 			.rx_buf = st->rx,
 			.bits_per_word = 8,
 			.len = 2,
-			.cs_change = 1,
 		},
 	};
 
@@ -375,7 +373,7 @@
 		dev_err(dev, "problem starting self test");
 		goto err_ret;
 	}
-
+	msleep(ADIS16400_MTEST_DELAY);
 	adis16400_check_status(dev);
 
 err_ret:
@@ -497,12 +495,12 @@
 			_reg)
 
 static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_X, ADIS16400_XGYRO_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_XGYRO_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_XGYRO_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_YGYRO_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_ZGYRO_OFF);
 
 static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_X, ADIS16400_XACCL_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_XACCL_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_XACCL_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_YACCL_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_ZACCL_OFF);
 
 
 static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16400_read_14bit_signed,
diff -druN linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400.h linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400.h
--- linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400.h	2011-06-02 21:35:11.000000000 -0400
@@ -17,7 +17,8 @@
 #ifndef SPI_ADIS16400_H_
 #define SPI_ADIS16400_H_
 
-#define ADIS16400_STARTUP_DELAY	220 /* ms */
+#define ADIS16400_STARTUP_DELAY	290 /* ms */
+#define ADIS16400_MTEST_DELAY 90 /* ms */
 
 #define ADIS16400_READ_REG(a)    a
 #define ADIS16400_WRITE_REG(a) ((a) | 0x80)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400_ring.c linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400_ring.c
--- linux-libre-2.6.38-gnu/drivers/staging/iio/imu/adis16400_ring.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/iio/imu/adis16400_ring.c	2011-06-02 21:35:11.000000000 -0400
@@ -122,12 +122,10 @@
 			.tx_buf = st->tx,
 			.bits_per_word = 8,
 			.len = 2,
-			.cs_change = 0,
 		}, {
 			.rx_buf = rx,
 			.bits_per_word = 8,
 			.len = 24,
-			.cs_change = 1,
 		},
 	};
 
@@ -162,9 +160,10 @@
 			       work_trigger_to_ring);
 	struct iio_ring_buffer *ring = st->indio_dev->ring;
 
-	int i = 0;
+	int i = 0, j;
 	s16 *data;
 	size_t datasize = ring->access.get_bytes_per_datum(ring);
+	unsigned long mask = ring->scan_mask;
 
 	data = kmalloc(datasize , GFP_KERNEL);
 	if (data == NULL) {
@@ -174,9 +173,12 @@
 
 	if (ring->scan_count)
 		if (adis16400_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
-			for (; i < ring->scan_count; i++)
+			for (; i < ring->scan_count; i++) {
+				j = __ffs(mask);
+				mask &= ~(1 << j);
 				data[i]	= be16_to_cpup(
-					(__be16 *)&(st->rx[i*2]));
+					(__be16 *)&(st->rx[j*2]));
+			}
 
 	/* Guaranteed to be aligned with 8 byte boundary */
 	if (ring->scan_timestamp)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c linux-libre-2.6.38.8-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c
--- linux-libre-2.6.38-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c	2011-06-02 21:35:11.000000000 -0400
@@ -68,7 +68,10 @@
 	pmlmepriv->fw_state |= _FW_UNDER_LINKING;
 	pmlmepriv->pscanned = plist;
 	pmlmepriv->to_join = true;
-	if (_queue_empty(queue) == true) {
+
+	/* adhoc mode will start with an empty queue, but skip checking */
+	if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
+	    _queue_empty(queue)) {
 		if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
 			pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 		/* when set_ssid/set_bssid for do_join(), but scanning queue
diff -druN linux-libre-2.6.38-gnu/drivers/staging/tidspbridge/rmgr/proc.c linux-libre-2.6.38.8-gnu/drivers/staging/tidspbridge/rmgr/proc.c
--- linux-libre-2.6.38-gnu/drivers/staging/tidspbridge/rmgr/proc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/tidspbridge/rmgr/proc.c	2011-06-02 21:35:11.000000000 -0400
@@ -781,12 +781,14 @@
 							(u32)pmpu_addr,
 							ul_size, dir);
 
+	mutex_lock(&proc_lock);
+
 	/* find requested memory are in cached mapping information */
 	map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
 	if (!map_obj) {
 		pr_err("%s: find_containing_mapping failed\n", __func__);
 		status = -EFAULT;
-		goto err_out;
+		goto no_map;
 	}
 
 	if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
@@ -795,6 +797,8 @@
 		status = -EFAULT;
 	}
 
+no_map:
+	mutex_unlock(&proc_lock);
 err_out:
 
 	return status;
@@ -819,21 +823,24 @@
 							(u32)pmpu_addr,
 							ul_size, dir);
 
+	mutex_lock(&proc_lock);
+
 	/* find requested memory are in cached mapping information */
 	map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
 	if (!map_obj) {
 		pr_err("%s: find_containing_mapping failed\n", __func__);
 		status = -EFAULT;
-		goto err_out;
+		goto no_map;
 	}
 
 	if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
 		pr_err("%s: InValid address parameters %p %x\n",
 		       __func__, pmpu_addr, ul_size);
 		status = -EFAULT;
-		goto err_out;
 	}
 
+no_map:
+	mutex_unlock(&proc_lock);
 err_out:
 	return status;
 }
@@ -1726,9 +1733,8 @@
 		    (p_proc_object->hbridge_context, va_align, size_align);
 	}
 
-	mutex_unlock(&proc_lock);
 	if (status)
-		goto func_end;
+		goto unmap_failed;
 
 	/*
 	 * A successful unmap should be followed by removal of map_obj
@@ -1737,6 +1743,9 @@
 	 */
 	remove_mapping_information(pr_ctxt, (u32) map_addr, size_align);
 
+unmap_failed:
+	mutex_unlock(&proc_lock);
+
 func_end:
 	dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n",
 		__func__, hprocessor, map_addr, status);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/stub_rx.c linux-libre-2.6.38.8-gnu/drivers/staging/usbip/stub_rx.c
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/stub_rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/stub_rx.c	2011-06-02 21:35:11.000000000 -0400
@@ -170,33 +170,23 @@
 
 static int tweak_reset_device_cmd(struct urb *urb)
 {
-	struct usb_ctrlrequest *req;
-	__u16 value;
-	__u16 index;
-	int ret;
-
-	req = (struct usb_ctrlrequest *) urb->setup_packet;
-	value = le16_to_cpu(req->wValue);
-	index = le16_to_cpu(req->wIndex);
-
-	usbip_uinfo("reset_device (port %d) to %s\n", index,
-						dev_name(&urb->dev->dev));
-
-	/* all interfaces should be owned by usbip driver, so just reset it.  */
-	ret = usb_lock_device_for_reset(urb->dev, NULL);
-	if (ret < 0) {
-		dev_err(&urb->dev->dev, "lock for reset\n");
-		return ret;
-	}
-
-	/* try to reset the device */
-	ret = usb_reset_device(urb->dev);
-	if (ret < 0)
-		dev_err(&urb->dev->dev, "device reset\n");
+	struct stub_priv *priv = (struct stub_priv *) urb->context;
+	struct stub_device *sdev = priv->sdev;
 
-	usb_unlock_device(urb->dev);
+	usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev));
 
-	return ret;
+	/*
+	 * usb_lock_device_for_reset caused a deadlock: it causes the driver
+	 * to unbind. In the shutdown the rx thread is signalled to shut down
+	 * but this thread is pending in the usb_lock_device_for_reset.
+	 *
+	 * Instead queue the reset.
+	 *
+	 * Unfortunatly an existing usbip connection will be dropped due to
+	 * driver unbinding.
+	 */
+	usb_queue_reset_device(sdev->interface);
+	return 0;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/stub_tx.c linux-libre-2.6.38.8-gnu/drivers/staging/usbip/stub_tx.c
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/stub_tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/stub_tx.c	2011-06-02 21:35:11.000000000 -0400
@@ -169,7 +169,6 @@
 	struct stub_priv *priv, *tmp;
 
 	struct msghdr msg;
-	struct kvec iov[3];
 	size_t txsize;
 
 	size_t total_size = 0;
@@ -179,28 +178,73 @@
 		struct urb *urb = priv->urb;
 		struct usbip_header pdu_header;
 		void *iso_buffer = NULL;
+		struct kvec *iov = NULL;
+		int iovnum = 0;
 
 		txsize = 0;
 		memset(&pdu_header, 0, sizeof(pdu_header));
 		memset(&msg, 0, sizeof(msg));
-		memset(&iov, 0, sizeof(iov));
 
-		usbip_dbg_stub_tx("setup txdata urb %p\n", urb);
+		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+			iovnum = 2 + urb->number_of_packets;
+		else
+			iovnum = 2;
 
+		iov = kzalloc(iovnum * sizeof(struct kvec), GFP_KERNEL);
+
+		if (!iov) {
+			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
+			return -1;
+		}
+
+		iovnum = 0;
 
 		/* 1. setup usbip_header */
 		setup_ret_submit_pdu(&pdu_header, urb);
+		usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
+						pdu_header.base.seqnum, urb);
+		/*usbip_dump_header(pdu_header);*/
 		usbip_header_correct_endian(&pdu_header, 1);
 
-		iov[0].iov_base = &pdu_header;
-		iov[0].iov_len  = sizeof(pdu_header);
+		iov[iovnum].iov_base = &pdu_header;
+		iov[iovnum].iov_len  = sizeof(pdu_header);
+		iovnum++;
 		txsize += sizeof(pdu_header);
 
 		/* 2. setup transfer buffer */
-		if (usb_pipein(urb->pipe) && urb->actual_length > 0) {
-			iov[1].iov_base = urb->transfer_buffer;
-			iov[1].iov_len  = urb->actual_length;
+		if (usb_pipein(urb->pipe) &&
+				usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
+					urb->actual_length > 0) {
+			iov[iovnum].iov_base = urb->transfer_buffer;
+			iov[iovnum].iov_len  = urb->actual_length;
+			iovnum++;
 			txsize += urb->actual_length;
+		} else if (usb_pipein(urb->pipe) &&
+				usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+			/*
+			 * For isochronous packets: actual length is the sum of
+			 * the actual length of the individual, packets, but as
+			 * the packet offsets are not changed there will be
+			 * padding between the packets. To optimally use the
+			 * bandwidth the padding is not transmitted.
+			 */
+
+			int i;
+			for (i = 0; i < urb->number_of_packets; i++) {
+				iov[iovnum].iov_base = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+				iov[iovnum].iov_len = urb->iso_frame_desc[i].actual_length;
+				iovnum++;
+				txsize += urb->iso_frame_desc[i].actual_length;
+			}
+
+			if (txsize != sizeof(pdu_header) + urb->actual_length) {
+				dev_err(&sdev->interface->dev,
+					"actual length of urb (%d) does not match iso packet sizes (%d)\n",
+					urb->actual_length, txsize-sizeof(pdu_header));
+				kfree(iov);
+				usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+			   return -1;
+			}
 		}
 
 		/* 3. setup iso_packet_descriptor */
@@ -211,32 +255,34 @@
 			if (!iso_buffer) {
 				usbip_event_add(&sdev->ud,
 						SDEV_EVENT_ERROR_MALLOC);
+				kfree(iov);
 				return -1;
 			}
 
-			iov[2].iov_base = iso_buffer;
-			iov[2].iov_len  = len;
+			iov[iovnum].iov_base = iso_buffer;
+			iov[iovnum].iov_len  = len;
 			txsize += len;
+			iovnum++;
 		}
 
-		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
-				     3, txsize);
+		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
+						iov,  iovnum, txsize);
 		if (ret != txsize) {
 			dev_err(&sdev->interface->dev,
 				"sendmsg failed!, retval %d for %zd\n",
 				ret, txsize);
+			kfree(iov);
 			kfree(iso_buffer);
 			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
 			return -1;
 		}
 
+		kfree(iov);
 		kfree(iso_buffer);
-		usbip_dbg_stub_tx("send txdata\n");
 
 		total_size += txsize;
 	}
 
-
 	spin_lock_irqsave(&sdev->priv_lock, flags);
 
 	list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/usbip_common.c linux-libre-2.6.38.8-gnu/drivers/staging/usbip/usbip_common.c
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/usbip_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/usbip_common.c	2011-06-02 21:35:11.000000000 -0400
@@ -334,10 +334,11 @@
 		usbip_udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum);
 		break;
 	case USBIP_RET_SUBMIT:
-		usbip_udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n",
+		usbip_udbg("RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n",
 				pdu->u.ret_submit.status,
 				pdu->u.ret_submit.actual_length,
 				pdu->u.ret_submit.start_frame,
+				pdu->u.ret_submit.number_of_packets,
 				pdu->u.ret_submit.error_count);
 	case USBIP_RET_UNLINK:
 		usbip_udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status);
@@ -625,6 +626,7 @@
 		rpdu->status		= urb->status;
 		rpdu->actual_length	= urb->actual_length;
 		rpdu->start_frame	= urb->start_frame;
+		rpdu->number_of_packets = urb->number_of_packets;
 		rpdu->error_count	= urb->error_count;
 	} else {
 		/* vhci_rx.c */
@@ -632,6 +634,7 @@
 		urb->status		= rpdu->status;
 		urb->actual_length	= rpdu->actual_length;
 		urb->start_frame	= rpdu->start_frame;
+		urb->number_of_packets = rpdu->number_of_packets;
 		urb->error_count	= rpdu->error_count;
 	}
 }
@@ -700,11 +703,13 @@
 		cpu_to_be32s(&pdu->status);
 		cpu_to_be32s(&pdu->actual_length);
 		cpu_to_be32s(&pdu->start_frame);
+		cpu_to_be32s(&pdu->number_of_packets);
 		cpu_to_be32s(&pdu->error_count);
 	} else {
 		be32_to_cpus(&pdu->status);
 		be32_to_cpus(&pdu->actual_length);
 		be32_to_cpus(&pdu->start_frame);
+		be32_to_cpus(&pdu->number_of_packets);
 		be32_to_cpus(&pdu->error_count);
 	}
 }
@@ -830,6 +835,7 @@
 	int size = np * sizeof(*iso);
 	int i;
 	int ret;
+	int total_length = 0;
 
 	if (!usb_pipeisoc(urb->pipe))
 		return 0;
@@ -859,19 +865,75 @@
 		return -EPIPE;
 	}
 
+
 	for (i = 0; i < np; i++) {
 		iso = buff + (i * sizeof(*iso));
 
 		usbip_iso_pakcet_correct_endian(iso, 0);
 		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
+		total_length += urb->iso_frame_desc[i].actual_length;
 	}
 
 	kfree(buff);
 
+	if (total_length != urb->actual_length) {
+		dev_err(&urb->dev->dev,
+		  "total length of iso packets (%d) not equal to actual length of buffer (%d)\n",
+		  total_length, urb->actual_length);
+
+		if (ud->side == USBIP_STUB)
+			usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+		else
+			usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+
+		return -EPIPE;
+	}
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(usbip_recv_iso);
 
+/*
+ * This functions restores the padding which was removed for optimizing
+ * the bandwidth during transfer over tcp/ip
+ *
+ * buffer and iso packets need to be stored and be in propeper endian in urb
+ * before calling this function
+ */
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
+{
+	int np = urb->number_of_packets;
+	int i;
+	int ret;
+	int actualoffset = urb->actual_length;
+
+	if (!usb_pipeisoc(urb->pipe))
+		return 0;
+
+	/* if no packets or length of data is 0, then nothing to unpack */
+	if (np == 0 || urb->actual_length == 0)
+		return 0;
+
+	/*
+	 * if actual_length is transfer_buffer_length then no padding is
+	 * present.
+	*/
+	if (urb->actual_length == urb->transfer_buffer_length)
+		return 0;
+
+	/*
+	 * loop over all packets from last to first (to prevent overwritting
+	 * memory when padding) and move them into the proper place
+	 */
+	for (i = np-1; i > 0; i--) {
+		actualoffset -= urb->iso_frame_desc[i].actual_length;
+		memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+				  urb->transfer_buffer + actualoffset,
+				  urb->iso_frame_desc[i].actual_length);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_pad_iso);
 
 /* some members of urb must be substituted before. */
 int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/usbip_common.h linux-libre-2.6.38.8-gnu/drivers/staging/usbip/usbip_common.h
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/usbip_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/usbip_common.h	2011-06-02 21:35:11.000000000 -0400
@@ -393,6 +393,8 @@
 int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
 /* some members of urb must be substituted before. */
 int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
+/* some members of urb must be substituted before. */
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
 void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/vhci_hcd.c linux-libre-2.6.38.8-gnu/drivers/staging/usbip/vhci_hcd.c
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/vhci_hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/vhci_hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1135,7 +1135,7 @@
 		usbip_uerr("create hcd failed\n");
 		return -ENOMEM;
 	}
-
+	hcd->has_tt = 1;
 
 	/* this is private data for vhci_hcd */
 	the_controller = hcd_to_vhci(hcd);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/usbip/vhci_rx.c linux-libre-2.6.38.8-gnu/drivers/staging/usbip/vhci_rx.c
--- linux-libre-2.6.38-gnu/drivers/staging/usbip/vhci_rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/usbip/vhci_rx.c	2011-06-02 21:35:11.000000000 -0400
@@ -99,6 +99,9 @@
 	if (usbip_recv_iso(ud, urb) < 0)
 		return;
 
+	/* restore the padding in iso packets */
+	if (usbip_pad_iso(ud, urb) < 0)
+		return;
 
 	if (usbip_dbg_flag_vhci_rx)
 		usbip_dump_urb(urb);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/winbond/core.h linux-libre-2.6.38.8-gnu/drivers/staging/winbond/core.h
--- linux-libre-2.6.38-gnu/drivers/staging/winbond/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/staging/winbond/core.h	2011-06-02 21:35:11.000000000 -0400
@@ -3,6 +3,7 @@
 
 #include <linux/wireless.h>
 #include <linux/types.h>
+#include <linux/delay.h>
 
 #include "wbhal.h"
 #include "mto.h"
diff -druN linux-libre-2.6.38-gnu/drivers/target/target_core_cdb.c linux-libre-2.6.38.8-gnu/drivers/target/target_core_cdb.c
--- linux-libre-2.6.38-gnu/drivers/target/target_core_cdb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/target/target_core_cdb.c	2011-06-02 21:35:11.000000000 -0400
@@ -667,7 +667,13 @@
 {
 	struct se_device *dev = SE_DEV(cmd);
 	unsigned char *buf = cmd->t_task->t_task_buf;
-	u32 blocks = dev->transport->get_blocks(dev);
+	unsigned long long blocks_long = dev->transport->get_blocks(dev);
+	u32 blocks;
+
+	if (blocks_long >= 0x00000000ffffffff)
+		blocks = 0xffffffff;
+	else
+		blocks = (u32)blocks_long;
 
 	buf[0] = (blocks >> 24) & 0xff;
 	buf[1] = (blocks >> 16) & 0xff;
diff -druN linux-libre-2.6.38-gnu/drivers/target/target_core_device.c linux-libre-2.6.38.8-gnu/drivers/target/target_core_device.c
--- linux-libre-2.6.38-gnu/drivers/target/target_core_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/target/target_core_device.c	2011-06-02 21:35:11.000000000 -0400
@@ -151,13 +151,13 @@
 
 	{
 	struct se_device *dev = se_lun->lun_se_dev;
-	spin_lock(&dev->stats_lock);
+	spin_lock_irq(&dev->stats_lock);
 	dev->num_cmds++;
 	if (se_cmd->data_direction == DMA_TO_DEVICE)
 		dev->write_bytes += se_cmd->data_length;
 	else if (se_cmd->data_direction == DMA_FROM_DEVICE)
 		dev->read_bytes += se_cmd->data_length;
-	spin_unlock(&dev->stats_lock);
+	spin_unlock_irq(&dev->stats_lock);
 	}
 
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/target/target_core_tmr.c linux-libre-2.6.38.8-gnu/drivers/target/target_core_tmr.c
--- linux-libre-2.6.38-gnu/drivers/target/target_core_tmr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/target/target_core_tmr.c	2011-06-02 21:35:11.000000000 -0400
@@ -55,7 +55,8 @@
 {
 	struct se_tmr_req *tmr;
 
-	tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL);
+	tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ?
+					GFP_ATOMIC : GFP_KERNEL);
 	if (!(tmr)) {
 		printk(KERN_ERR "Unable to allocate struct se_tmr_req\n");
 		return ERR_PTR(-ENOMEM);
@@ -398,9 +399,9 @@
 		printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n");
 	}
 
-	spin_lock(&dev->stats_lock);
+	spin_lock_irq(&dev->stats_lock);
 	dev->num_resets++;
-	spin_unlock(&dev->stats_lock);
+	spin_unlock_irq(&dev->stats_lock);
 
 	DEBUG_LR("LUN_RESET: %s for [%s] Complete\n",
 			(preempt_and_abort_list) ? "Preempt" : "TMR",
diff -druN linux-libre-2.6.38-gnu/drivers/target/target_core_transport.c linux-libre-2.6.38.8-gnu/drivers/target/target_core_transport.c
--- linux-libre-2.6.38-gnu/drivers/target/target_core_transport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/target/target_core_transport.c	2011-06-02 21:35:11.000000000 -0400
@@ -765,7 +765,6 @@
 	transport_all_task_dev_remove_state(cmd);
 	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
 
-	transport_free_dev_tasks(cmd);
 
 check_lun:
 	spin_lock_irqsave(&lun->lun_cmd_lock, flags);
@@ -1198,6 +1197,7 @@
 		break;
 
 	list_del(&task->t_execute_list);
+	atomic_set(&task->task_execute_queue, 0);
 	atomic_dec(&dev->execute_tasks);
 
 	return task;
@@ -1213,8 +1213,14 @@
 {
 	unsigned long flags;
 
+	if (atomic_read(&task->task_execute_queue) == 0) {
+		dump_stack();
+		return;
+	}
+
 	spin_lock_irqsave(&dev->execute_task_lock, flags);
 	list_del(&task->t_execute_list);
+	atomic_set(&task->task_execute_queue, 0);
 	atomic_dec(&dev->execute_tasks);
 	spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
@@ -2062,6 +2068,13 @@
 }
 EXPORT_SYMBOL(transport_generic_handle_tmr);
 
+void transport_generic_free_cmd_intr(
+	struct se_cmd *cmd)
+{
+	transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR);
+}
+EXPORT_SYMBOL(transport_generic_free_cmd_intr);
+
 static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
 {
 	struct se_task *task, *task_tmp;
@@ -4777,18 +4790,20 @@
 				sg_end_cur->page_link &= ~0x02;
 
 				sg_chain(sg_head, task_sg_num, sg_head_cur);
-				sg_count += (task->task_sg_num + 1);
-			} else
 				sg_count += task->task_sg_num;
+				task_sg_num = (task->task_sg_num + 1);
+			} else {
+				sg_chain(sg_head, task_sg_num, sg_head_cur);
+				sg_count += task->task_sg_num;
+				task_sg_num = task->task_sg_num;
+			}
 
 			sg_head = sg_head_cur;
 			sg_link = sg_link_cur;
-			task_sg_num = task->task_sg_num;
 			continue;
 		}
 		sg_head = sg_first = &task->task_sg[0];
 		sg_link = &task->task_sg[task->task_sg_num];
-		task_sg_num = task->task_sg_num;
 		/*
 		 * Check for single task..
 		 */
@@ -4799,9 +4814,12 @@
 			 */
 			sg_end = &task->task_sg[task->task_sg_num - 1];
 			sg_end->page_link &= ~0x02;
-			sg_count += (task->task_sg_num + 1);
-		} else
 			sg_count += task->task_sg_num;
+			task_sg_num = (task->task_sg_num + 1);
+		} else {
+			sg_count += task->task_sg_num;
+			task_sg_num = task->task_sg_num;
+		}
 	}
 	/*
 	 * Setup the starting pointer and total t_tasks_sg_linked_no including
@@ -4810,21 +4828,20 @@
 	T_TASK(cmd)->t_tasks_sg_chained = sg_first;
 	T_TASK(cmd)->t_tasks_sg_chained_no = sg_count;
 
-	DEBUG_CMD_M("Setup T_TASK(cmd)->t_tasks_sg_chained: %p and"
-		" t_tasks_sg_chained_no: %u\n", T_TASK(cmd)->t_tasks_sg_chained,
+	DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and"
+		" t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained,
 		T_TASK(cmd)->t_tasks_sg_chained_no);
 
 	for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg,
 			T_TASK(cmd)->t_tasks_sg_chained_no, i) {
 
-		DEBUG_CMD_M("SG: %p page: %p length: %d offset: %d\n",
-			sg, sg_page(sg), sg->length, sg->offset);
+		DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n",
+			i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic);
 		if (sg_is_chain(sg))
 			DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg);
 		if (sg_is_last(sg))
 			DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg);
 	}
-
 }
 EXPORT_SYMBOL(transport_do_task_sg_chain);
 
@@ -5298,6 +5315,8 @@
 		if (wait_for_tasks && cmd->transport_wait_for_tasks)
 			cmd->transport_wait_for_tasks(cmd, 0, 0);
 
+		transport_free_dev_tasks(cmd);
+
 		transport_generic_remove(cmd, release_to_pool,
 				session_reinstatement);
 	}
@@ -6138,6 +6157,9 @@
 		case TRANSPORT_REMOVE:
 			transport_generic_remove(cmd, 1, 0);
 			break;
+		case TRANSPORT_FREE_CMD_INTR:
+			transport_generic_free_cmd(cmd, 0, 1, 0);
+			break;
 		case TRANSPORT_PROCESS_TMR:
 			transport_generic_do_tmr(cmd);
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/tty/n_gsm.c linux-libre-2.6.38.8-gnu/drivers/tty/n_gsm.c
--- linux-libre-2.6.38-gnu/drivers/tty/n_gsm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/tty/n_gsm.c	2011-06-02 21:35:11.000000000 -0400
@@ -1659,8 +1659,12 @@
 
 	if ((gsm->control & ~PF) == UI)
 		gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
-	/* generate final CRC with received FCS */
-	gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
+	if (gsm->encoding == 0){
+		/* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only.
+		            In this case it contain the last piece of data
+		            required to generate final CRC */
+		gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
+	}
 	if (gsm->fcs != GOOD_FCS) {
 		gsm->bad_fcs++;
 		if (debug & 4)
diff -druN linux-libre-2.6.38-gnu/drivers/tty/serial/8250.c linux-libre-2.6.38.8-gnu/drivers/tty/serial/8250.c
--- linux-libre-2.6.38-gnu/drivers/tty/serial/8250.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/tty/serial/8250.c	2011-06-02 21:35:11.000000000 -0400
@@ -954,6 +954,23 @@
 	return 0;
 }
 
+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+{
+	unsigned char status;
+
+	status = serial_in(up, 0x04); /* EXCR2 */
+#define PRESL(x) ((x) & 0x30)
+	if (PRESL(status) == 0x10) {
+		/* already in high speed mode */
+		return 0;
+	} else {
+		status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+		status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
+		serial_outp(up, 0x04, status);
+	}
+	return 1;
+}
+
 /*
  * We know that the chip has FIFOs.  Does it have an EFR?  The
  * EFR is located in the same register position as the IIR and
@@ -1025,12 +1042,8 @@
 			quot = serial_dl_read(up);
 			quot <<= 3;
 
-			status1 = serial_in(up, 0x04); /* EXCR2 */
-			status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-			serial_outp(up, 0x04, status1);
-
-			serial_dl_write(up, quot);
+			if (ns16550a_goto_highspeed(up))
+				serial_dl_write(up, quot);
 
 			serial_outp(up, UART_LCR, 0);
 
@@ -3025,17 +3038,13 @@
 	struct uart_8250_port *up = &serial8250_ports[line];
 
 	if (up->capabilities & UART_NATSEMI) {
-		unsigned char tmp;
-
 		/* Ensure it's still in high speed mode */
 		serial_outp(up, UART_LCR, 0xE0);
 
-		tmp = serial_in(up, 0x04); /* EXCR2 */
-		tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-		tmp |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-		serial_outp(up, 0x04, tmp);
+		ns16550a_goto_highspeed(up);
 
 		serial_outp(up, UART_LCR, 0);
+		up->port.uartclk = 921600*16;
 	}
 	uart_resume_port(&serial8250_reg, &up->port);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/tty/serial/imx.c linux-libre-2.6.38.8-gnu/drivers/tty/serial/imx.c
--- linux-libre-2.6.38-gnu/drivers/tty/serial/imx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/tty/serial/imx.c	2011-06-02 21:35:11.000000000 -0400
@@ -382,12 +382,13 @@
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
-	unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
+	unsigned int val;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 	writel(USR1_RTSD, sport->port.membase + USR1);
+	val = readl(sport->port.membase + USR1) & USR1_RTSS;
 	uart_handle_cts_change(&sport->port, !!val);
 	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 
diff -druN linux-libre-2.6.38-gnu/drivers/tty/serial/mrst_max3110.c linux-libre-2.6.38.8-gnu/drivers/tty/serial/mrst_max3110.c
--- linux-libre-2.6.38-gnu/drivers/tty/serial/mrst_max3110.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/tty/serial/mrst_max3110.c	2011-06-02 21:35:11.000000000 -0400
@@ -51,7 +51,7 @@
 struct uart_max3110 {
 	struct uart_port port;
 	struct spi_device *spi;
-	char name[24];
+	char name[SPI_NAME_SIZE];
 
 	wait_queue_head_t wq;
 	struct task_struct *main_thread;
diff -druN linux-libre-2.6.38-gnu/drivers/usb/class/cdc-acm.c linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-acm.c
--- linux-libre-2.6.38-gnu/drivers/usb/class/cdc-acm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-acm.c	2011-06-02 21:35:11.000000000 -0400
@@ -297,6 +297,8 @@
 	if (!ACM_READY(acm))
 		goto exit;
 
+	usb_mark_last_busy(acm->dev);
+
 	data = (unsigned char *)(dr + 1);
 	switch (dr->bNotificationType) {
 	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -336,7 +338,6 @@
 		break;
 	}
 exit:
-	usb_mark_last_busy(acm->dev);
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with "
@@ -533,6 +534,8 @@
 	if (!ACM_READY(acm))
 		return;
 	tty = tty_port_tty_get(&acm->port);
+	if (!tty)
+		return;
 	tty_wakeup(tty);
 	tty_kref_put(tty);
 }
@@ -646,8 +649,10 @@
 		usb_kill_urb(acm->ctrlurb);
 		for (i = 0; i < ACM_NW; i++)
 			usb_kill_urb(acm->wb[i].urb);
+		tasklet_disable(&acm->urb_task);
 		for (i = 0; i < nr; i++)
 			usb_kill_urb(acm->ru[i].urb);
+		tasklet_enable(&acm->urb_task);
 		acm->control->needs_remote_wakeup = 0;
 		usb_autopm_put_interface(acm->control);
 	}
@@ -941,7 +946,7 @@
 	u8 ac_management_function = 0;
 	u8 call_management_function = 0;
 	int call_interface_num = -1;
-	int data_interface_num;
+	int data_interface_num = -1;
 	unsigned long quirks;
 	int num_rx_buf;
 	int i;
@@ -1025,7 +1030,11 @@
 	if (!union_header) {
 		if (call_interface_num > 0) {
 			dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n");
-			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+			/* quirks for Droids MuIn LCD */
+			if (quirks & NO_DATA_INTERFACE)
+				data_interface = usb_ifnum_to_if(usb_dev, 0);
+			else
+				data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
 			control_interface = intf;
 		} else {
 			if (intf->cur_altsetting->desc.bNumEndpoints != 3) {
@@ -1617,6 +1626,11 @@
 	.driver_info = NOT_A_MODEM,
 	},
 
+	/* Support for Droids MuIn LCD */
+	{ USB_DEVICE(0x04d8, 0x000b),
+	.driver_info = NO_DATA_INTERFACE,
+	},
+
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_PROTO_NONE) },
diff -druN linux-libre-2.6.38-gnu/drivers/usb/class/cdc-acm.h linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-acm.h
--- linux-libre-2.6.38-gnu/drivers/usb/class/cdc-acm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-acm.h	2011-06-02 21:35:11.000000000 -0400
@@ -137,3 +137,4 @@
 #define SINGLE_RX_URB			2
 #define NO_CAP_LINE			4
 #define NOT_A_MODEM			8
+#define NO_DATA_INTERFACE		16
diff -druN linux-libre-2.6.38-gnu/drivers/usb/class/cdc-wdm.c linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-wdm.c
--- linux-libre-2.6.38-gnu/drivers/usb/class/cdc-wdm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/class/cdc-wdm.c	2011-06-02 21:35:11.000000000 -0400
@@ -281,7 +281,7 @@
 			  desc->sbuf,
 			  desc->validity->transfer_dma);
 	usb_free_coherent(interface_to_usbdev(desc->intf),
-			  desc->wMaxCommand,
+			  desc->bMaxPacketSize0,
 			  desc->inbuf,
 			  desc->response->transfer_dma);
 	kfree(desc->orq);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/core/devices.c linux-libre-2.6.38.8-gnu/drivers/usb/core/devices.c
--- linux-libre-2.6.38-gnu/drivers/usb/core/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/core/devices.c	2011-06-02 21:35:11.000000000 -0400
@@ -221,7 +221,7 @@
 		break;
 	case USB_ENDPOINT_XFER_INT:
 		type = "Int.";
-		if (speed == USB_SPEED_HIGH)
+		if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
 			interval = 1 << (desc->bInterval - 1);
 		else
 			interval = desc->bInterval;
@@ -229,7 +229,8 @@
 	default:	/* "can't happen" */
 		return start;
 	}
-	interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+	interval *= (speed == USB_SPEED_HIGH ||
+		     speed == USB_SPEED_SUPER) ? 125 : 1000;
 	if (interval % 1000)
 		unit = 'u';
 	else {
@@ -542,8 +543,9 @@
 	if (level == 0) {
 		int	max;
 
-		/* high speed reserves 80%, full/low reserves 90% */
-		if (usbdev->speed == USB_SPEED_HIGH)
+		/* super/high speed reserves 80%, full/low reserves 90% */
+		if (usbdev->speed == USB_SPEED_HIGH ||
+		    usbdev->speed == USB_SPEED_SUPER)
 			max = 800;
 		else
 			max = FRAME_TIME_MAX_USECS_ALLOC;
diff -druN linux-libre-2.6.38-gnu/drivers/usb/core/devio.c linux-libre-2.6.38.8-gnu/drivers/usb/core/devio.c
--- linux-libre-2.6.38-gnu/drivers/usb/core/devio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/core/devio.c	2011-06-02 21:35:11.000000000 -0400
@@ -802,7 +802,7 @@
 				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
 		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
-			tbuf, i);
+			  tbuf, max(i, 0));
 		if ((i > 0) && ctrl.wLength) {
 			if (copy_to_user(ctrl.data, tbuf, i)) {
 				free_page((unsigned long)tbuf);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/core/hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/core/hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/core/hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/core/hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -983,7 +983,7 @@
 		spin_unlock_irq (&hcd_root_hub_lock);
 
 		/* Did the HC die before the root hub was registered? */
-		if (hcd->state == HC_STATE_HALT)
+		if (HCD_DEAD(hcd))
 			usb_hc_died (hcd);	/* This time clean up */
 	}
 
@@ -1089,13 +1089,10 @@
 	 * Check the host controller's state and add the URB to the
 	 * endpoint's queue.
 	 */
-	switch (hcd->state) {
-	case HC_STATE_RUNNING:
-	case HC_STATE_RESUMING:
+	if (HCD_RH_RUNNING(hcd)) {
 		urb->unlinked = 0;
 		list_add_tail(&urb->urb_list, &urb->ep->urb_list);
-		break;
-	default:
+	} else {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
@@ -1888,7 +1885,7 @@
 
 	/* Streams only apply to bulk endpoints. */
 	for (i = 0; i < num_eps; i++)
-		if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
+		if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
 			return;
 
 	hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
@@ -1913,7 +1910,7 @@
 {
 	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
 
-	if (!HC_IS_RUNNING (hcd->state))
+	if (!HCD_RH_RUNNING(hcd))
 		return -ESHUTDOWN;
 	return hcd->driver->get_frame_number (hcd);
 }
@@ -1930,9 +1927,15 @@
 
 	dev_dbg(&rhdev->dev, "bus %s%s\n",
 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
+	if (HCD_DEAD(hcd)) {
+		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
+		return 0;
+	}
+
 	if (!hcd->driver->bus_suspend) {
 		status = -ENOENT;
 	} else {
+		clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 		hcd->state = HC_STATE_QUIESCING;
 		status = hcd->driver->bus_suspend(hcd);
 	}
@@ -1940,7 +1943,12 @@
 		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
 		hcd->state = HC_STATE_SUSPENDED;
 	} else {
-		hcd->state = old_state;
+		spin_lock_irq(&hcd_root_hub_lock);
+		if (!HCD_DEAD(hcd)) {
+			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+			hcd->state = old_state;
+		}
+		spin_unlock_irq(&hcd_root_hub_lock);
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
 				"suspend", status);
 	}
@@ -1955,9 +1963,13 @@
 
 	dev_dbg(&rhdev->dev, "usb %s%s\n",
 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+	if (HCD_DEAD(hcd)) {
+		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
+		return 0;
+	}
 	if (!hcd->driver->bus_resume)
 		return -ENOENT;
-	if (hcd->state == HC_STATE_RUNNING)
+	if (HCD_RH_RUNNING(hcd))
 		return 0;
 
 	hcd->state = HC_STATE_RESUMING;
@@ -1966,10 +1978,15 @@
 	if (status == 0) {
 		/* TRSMRCY = 10 msec */
 		msleep(10);
-		usb_set_device_state(rhdev, rhdev->actconfig
-				? USB_STATE_CONFIGURED
-				: USB_STATE_ADDRESS);
-		hcd->state = HC_STATE_RUNNING;
+		spin_lock_irq(&hcd_root_hub_lock);
+		if (!HCD_DEAD(hcd)) {
+			usb_set_device_state(rhdev, rhdev->actconfig
+					? USB_STATE_CONFIGURED
+					: USB_STATE_ADDRESS);
+			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+			hcd->state = HC_STATE_RUNNING;
+		}
+		spin_unlock_irq(&hcd_root_hub_lock);
 	} else {
 		hcd->state = old_state;
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
@@ -2080,15 +2097,12 @@
 	 */
 	local_irq_save(flags);
 
-	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
+	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
 		rc = IRQ_NONE;
 	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
 		rc = IRQ_NONE;
 	} else {
 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
-
-		if (unlikely(hcd->state == HC_STATE_HALT))
-			usb_hc_died(hcd);
 		rc = IRQ_HANDLED;
 	}
 
@@ -2114,6 +2128,8 @@
 	dev_err (hcd->self.controller, "HC died; cleaning up\n");
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+	set_bit(HCD_FLAG_DEAD, &hcd->flags);
 	if (hcd->rh_registered) {
 		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
@@ -2256,6 +2272,12 @@
 	 */
 	device_init_wakeup(&rhdev->dev, 1);
 
+	/* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
+	 * registered.  But since the controller can die at any time,
+	 * let's initialize the flag before touching the hardware.
+	 */
+	set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+
 	/* "reset" is misnamed; its role is now one-time init. the controller
 	 * should already have been reset (and boot firmware kicked off etc).
 	 */
@@ -2323,6 +2345,7 @@
 	return retval;
 
 error_create_attr_group:
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 	if (HC_IS_RUNNING(hcd->state))
 		hcd->state = HC_STATE_QUIESCING;
 	spin_lock_irq(&hcd_root_hub_lock);
@@ -2375,6 +2398,7 @@
 	usb_get_dev(rhdev);
 	sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
 
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 	if (HC_IS_RUNNING (hcd->state))
 		hcd->state = HC_STATE_QUIESCING;
 
diff -druN linux-libre-2.6.38-gnu/drivers/usb/core/hcd-pci.c linux-libre-2.6.38.8-gnu/drivers/usb/core/hcd-pci.c
--- linux-libre-2.6.38-gnu/drivers/usb/core/hcd-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/core/hcd-pci.c	2011-06-02 21:35:11.000000000 -0400
@@ -363,8 +363,7 @@
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 
-	if (!(hcd->state == HC_STATE_SUSPENDED ||
-			hcd->state == HC_STATE_HALT)) {
+	if (HCD_RH_RUNNING(hcd)) {
 		dev_warn(dev, "Root hub is not suspended\n");
 		return -EBUSY;
 	}
@@ -386,7 +385,7 @@
 	if (retval)
 		return retval;
 
-	if (hcd->driver->pci_suspend) {
+	if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) {
 		/* Optimization: Don't suspend if a root-hub wakeup is
 		 * pending and it would cause the HCD to wake up anyway.
 		 */
@@ -427,7 +426,7 @@
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int			retval;
 
-	if (hcd->state != HC_STATE_SUSPENDED) {
+	if (HCD_RH_RUNNING(hcd)) {
 		dev_dbg(dev, "can't resume, not suspended!\n");
 		return 0;
 	}
@@ -442,7 +441,7 @@
 
 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
 
-	if (hcd->driver->pci_resume) {
+	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
 		if (event != PM_EVENT_AUTO_RESUME)
 			wait_for_companions(pci_dev, hcd);
 
@@ -475,10 +474,10 @@
 
 	pci_save_state(pci_dev);
 
-	/* If the root hub is HALTed rather than SUSPENDed,
+	/* If the root hub is dead rather than suspended,
 	 * disallow remote wakeup.
 	 */
-	if (hcd->state == HC_STATE_HALT)
+	if (HCD_DEAD(hcd))
 		device_set_wakeup_enable(dev, 0);
 	dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev));
 
diff -druN linux-libre-2.6.38-gnu/drivers/usb/core/urb.c linux-libre-2.6.38.8-gnu/drivers/usb/core/urb.c
--- linux-libre-2.6.38-gnu/drivers/usb/core/urb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/core/urb.c	2011-06-02 21:35:11.000000000 -0400
@@ -366,7 +366,16 @@
 	if (xfertype == USB_ENDPOINT_XFER_ISOC) {
 		int	n, len;
 
-		/* FIXME SuperSpeed isoc endpoints have up to 16 bursts */
+		/* SuperSpeed isoc endpoints have up to 16 bursts of up to
+		 * 3 packets each
+		 */
+		if (dev->speed == USB_SPEED_SUPER) {
+			int     burst = 1 + ep->ss_ep_comp.bMaxBurst;
+			int     mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes);
+			max *= burst;
+			max *= mult;
+		}
+
 		/* "high bandwidth" mode, 1-3 packets/uframe? */
 		if (dev->speed == USB_SPEED_HIGH) {
 			int	mult = 1 + ((max >> 11) & 0x03);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/gadget/at91_udc.c linux-libre-2.6.38.8-gnu/drivers/usb/gadget/at91_udc.c
--- linux-libre-2.6.38-gnu/drivers/usb/gadget/at91_udc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/gadget/at91_udc.c	2011-06-02 21:35:11.000000000 -0400
@@ -1767,7 +1767,7 @@
 	}
 
 	/* newer chips have more FIFO memory than rm9200 */
-	if (cpu_is_at91sam9260()) {
+	if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
 		udc->ep[0].maxpacket = 64;
 		udc->ep[3].maxpacket = 64;
 		udc->ep[4].maxpacket = 512;
diff -druN linux-libre-2.6.38-gnu/drivers/usb/gadget/f_rndis.c linux-libre-2.6.38.8-gnu/drivers/usb/gadget/f_rndis.c
--- linux-libre-2.6.38-gnu/drivers/usb/gadget/f_rndis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/gadget/f_rndis.c	2011-06-02 21:35:11.000000000 -0400
@@ -420,8 +420,7 @@
 	 */
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
 			| USB_CDC_SEND_ENCAPSULATED_COMMAND:
-		if (w_length > req->length || w_value
-				|| w_index != rndis->ctrl_id)
+		if (w_value || w_index != rndis->ctrl_id)
 			goto invalid;
 		/* read the request; process it later */
 		value = w_length;
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ehci-hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ehci-hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -776,8 +776,9 @@
 		goto dead;
 	}
 
+	/* Shared IRQ? */
 	masked_status = status & INTR_MASK;
-	if (!masked_status) {		/* irq sharing? */
+	if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
 		spin_unlock(&ehci->lock);
 		return IRQ_NONE;
 	}
@@ -872,6 +873,7 @@
 dead:
 		ehci_reset(ehci);
 		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+		usb_hc_died(hcd);
 		/* generic layer kills/unlinks all urbs, then
 		 * uses ehci_stop to clean up the rest
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ehci-hub.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-hub.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ehci-hub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-hub.c	2011-06-02 21:35:11.000000000 -0400
@@ -106,6 +106,27 @@
 	ehci->owned_ports = 0;
 }
 
+static int ehci_port_change(struct ehci_hcd *ehci)
+{
+	int i = HCS_N_PORTS(ehci->hcs_params);
+
+	/* First check if the controller indicates a change event */
+
+	if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)
+		return 1;
+
+	/*
+	 * Not all controllers appear to update this while going from D3 to D0,
+	 * so check the individual port status registers as well
+	 */
+
+	while (i--)
+		if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC)
+			return 1;
+
+	return 0;
+}
+
 static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 		bool suspending, bool do_wakeup)
 {
@@ -173,7 +194,7 @@
 	}
 
 	/* Does the root hub have a port wakeup pending? */
-	if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
+	if (!suspending && ehci_port_change(ehci))
 		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
 
 	spin_unlock_irqrestore(&ehci->lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ehci-q.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-q.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ehci-q.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-q.c	2011-06-02 21:35:11.000000000 -0400
@@ -315,7 +315,6 @@
 	int			stopped;
 	unsigned		count = 0;
 	u8			state;
-	const __le32		halt = HALT_BIT(ehci);
 	struct ehci_qh_hw	*hw = qh->hw;
 
 	if (unlikely (list_empty (&qh->qtd_list)))
@@ -422,7 +421,6 @@
 					&& !(qtd->hw_alt_next
 						& EHCI_LIST_END(ehci))) {
 				stopped = 1;
-				goto halt;
 			}
 
 		/* stop scanning when we reach qtds the hc is using */
@@ -456,16 +454,6 @@
 				 */
 				ehci_clear_tt_buffer(ehci, qh, urb, token);
 			}
-
-			/* force halt for unlinked or blocked qh, so we'll
-			 * patch the qh later and so that completions can't
-			 * activate it while we "know" it's stopped.
-			 */
-			if ((halt & hw->hw_token) == 0) {
-halt:
-				hw->hw_token |= halt;
-				wmb ();
-			}
 		}
 
 		/* unless we already know the urb's status, collect qtd status
@@ -1257,24 +1245,27 @@
 
 static void scan_async (struct ehci_hcd *ehci)
 {
+	bool			stopped;
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
 	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
+	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
 	qh = ehci->async->qh_next.qh;
 	if (likely (qh != NULL)) {
 		do {
 			/* clean any finished work for this qh */
-			if (!list_empty (&qh->qtd_list)
-					&& qh->stamp != ehci->stamp) {
+			if (!list_empty(&qh->qtd_list) && (stopped ||
+					qh->stamp != ehci->stamp)) {
 				int temp;
 
 				/* unlinks could happen here; completion
 				 * reporting drops the lock.  rescan using
 				 * the latest schedule, but don't rescan
-				 * qhs we already finished (no looping).
+				 * qhs we already finished (no looping)
+				 * unless the controller is stopped.
 				 */
 				qh = qh_get (qh);
 				qh->stamp = ehci->stamp;
@@ -1295,9 +1286,9 @@
 			 */
 			if (list_empty(&qh->qtd_list)
 					&& qh->qh_state == QH_STATE_LINKED) {
-				if (!ehci->reclaim
-					&& ((ehci->stamp - qh->stamp) & 0x1fff)
-						>= (EHCI_SHRINK_FRAMES * 8))
+				if (!ehci->reclaim && (stopped ||
+					((ehci->stamp - qh->stamp) & 0x1fff)
+						>= EHCI_SHRINK_FRAMES * 8))
 					start_unlink_async(ehci, qh);
 				else
 					action = TIMER_ASYNC_SHRINK;
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ehci-sched.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-sched.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ehci-sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ehci-sched.c	2011-06-02 21:35:11.000000000 -0400
@@ -471,8 +471,10 @@
 	 */
 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
 					     STS_PSS, 0, 9 * 125);
-	if (status)
+	if (status) {
+		usb_hc_died(ehci_to_hcd(ehci));
 		return status;
+	}
 
 	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
 	ehci_writel(ehci, cmd, &ehci->regs->command);
@@ -510,8 +512,10 @@
 	 */
 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
 					     STS_PSS, STS_PSS, 9 * 125);
-	if (status)
+	if (status) {
+		usb_hc_died(ehci_to_hcd(ehci));
 		return status;
+	}
 
 	cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
 	ehci_writel(ehci, cmd, &ehci->regs->command);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/isp116x-hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/host/isp116x-hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/isp116x-hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/isp116x-hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -612,6 +612,7 @@
 			/* IRQ's are off, we do no DMA,
 			   perfectly ready to die ... */
 			hcd->state = HC_STATE_HALT;
+			usb_hc_died(hcd);
 			ret = IRQ_HANDLED;
 			goto done;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/isp1760-hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/host/isp1760-hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/isp1760-hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/isp1760-hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -33,6 +33,7 @@
 	struct inter_packet_info atl_ints[32];
 	struct inter_packet_info int_ints[32];
 	struct memory_chunk memory_pool[BLOCKS];
+	u32 atl_queued;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024
@@ -850,6 +851,11 @@
 	skip_map &= ~queue_entry;
 	isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
 
+	priv->atl_queued++;
+	if (priv->atl_queued == 2)
+		isp1760_writel(INTERRUPT_ENABLE_SOT_MASK,
+				hcd->regs + HC_INTERRUPT_ENABLE);
+
 	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
 	buffstatus |= ATL_BUFFER;
 	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
@@ -992,6 +998,7 @@
 		u32 dw3;
 
 		status = 0;
+		priv->atl_queued--;
 
 		queue_entry = __ffs(done_map);
 		done_map &= ~(1 << queue_entry);
@@ -1054,11 +1061,6 @@
 			 * device is not able to send data fast enough.
 			 * This happens mostly on slower hardware.
 			 */
-			printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: "
-					"%d of %zu done: %08x cur: %08x\n", qtd,
-					urb, qh, PTD_XFERRED_LENGTH(dw3),
-					qtd->length, done_map,
-					(1 << queue_entry));
 
 			/* RL counter = ERR counter */
 			dw3 &= ~(0xf << 19);
@@ -1086,6 +1088,11 @@
 			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
 					atl_regs, sizeof(ptd));
 
+			priv->atl_queued++;
+			if (priv->atl_queued == 2)
+				isp1760_writel(INTERRUPT_ENABLE_SOT_MASK,
+				    usb_hcd->regs + HC_INTERRUPT_ENABLE);
+
 			buffstatus = isp1760_readl(usb_hcd->regs +
 					HC_BUFFER_STATUS_REG);
 			buffstatus |= ATL_BUFFER;
@@ -1191,6 +1198,9 @@
 		skip_map = isp1760_readl(usb_hcd->regs +
 				HC_ATL_PTD_SKIPMAP_REG);
 	}
+	if (priv->atl_queued <= 1)
+		isp1760_writel(INTERRUPT_ENABLE_MASK,
+				usb_hcd->regs + HC_INTERRUPT_ENABLE);
 }
 
 static void do_intl_int(struct usb_hcd *usb_hcd)
@@ -1770,7 +1780,7 @@
 		goto leave;
 
 	isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG);
-	if (imask & HC_ATL_INT)
+	if (imask & (HC_ATL_INT | HC_SOT_INT))
 		do_atl_int(usb_hcd);
 
 	if (imask & HC_INTL_INT)
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/isp1760-hcd.h linux-libre-2.6.38.8-gnu/drivers/usb/host/isp1760-hcd.h
--- linux-libre-2.6.38-gnu/drivers/usb/host/isp1760-hcd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/isp1760-hcd.h	2011-06-02 21:35:11.000000000 -0400
@@ -69,6 +69,7 @@
 
 #define HC_INTERRUPT_ENABLE	0x314
 #define INTERRUPT_ENABLE_MASK	(HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
+#define INTERRUPT_ENABLE_SOT_MASK	(HC_INTL_INT | HC_SOT_INT | HC_EOT_INT)
 
 #define HC_ISO_INT		(1 << 9)
 #define HC_ATL_INT		(1 << 8)
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ohci-hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ohci-hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ohci-hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ohci-hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -773,6 +773,7 @@
 	if (ints == ~(u32)0) {
 		disable (ohci);
 		ohci_dbg (ohci, "device removed!\n");
+		usb_hc_died(hcd);
 		return IRQ_HANDLED;
 	}
 
@@ -780,7 +781,7 @@
 	ints &= ohci_readl(ohci, &regs->intrenable);
 
 	/* interrupt for some other device? */
-	if (ints == 0)
+	if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
 		return IRQ_NOTMINE;
 
 	if (ints & OHCI_INTR_UE) {
@@ -797,6 +798,7 @@
 		} else {
 			disable (ohci);
 			ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+			usb_hc_died(hcd);
 		}
 
 		ohci_dump (ohci, 1);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/ohci-pci.c linux-libre-2.6.38.8-gnu/drivers/usb/host/ohci-pci.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/ohci-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/ohci-pci.c	2011-06-02 21:35:11.000000000 -0400
@@ -207,10 +207,18 @@
  */
 static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
 {
+	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
 
-	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
-	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+	/* Evidently nVidia fixed their later hardware; this is a guess at
+	 * the changeover point.
+	 */
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB		0x026d
+
+	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
+		ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+		ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+	}
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/oxu210hp-hcd.c linux-libre-2.6.38.8-gnu/drivers/usb/host/oxu210hp-hcd.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/oxu210hp-hcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/oxu210hp-hcd.c	2011-06-02 21:35:11.000000000 -0400
@@ -1884,6 +1884,7 @@
 	status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125);
 	if (status != 0) {
 		oxu_to_hcd(oxu)->state = HC_STATE_HALT;
+		usb_hc_died(oxu_to_hcd(oxu));
 		return status;
 	}
 
@@ -1909,6 +1910,7 @@
 	status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125);
 	if (status != 0) {
 		oxu_to_hcd(oxu)->state = HC_STATE_HALT;
+		usb_hc_died(oxu_to_hcd(oxu));
 		return status;
 	}
 
@@ -2449,8 +2451,9 @@
 		goto dead;
 	}
 
+	/* Shared IRQ? */
 	status &= INTR_MASK;
-	if (!status) {			/* irq sharing? */
+	if (!status || unlikely(hcd->state == HC_STATE_HALT)) {
 		spin_unlock(&oxu->lock);
 		return IRQ_NONE;
 	}
@@ -2516,6 +2519,7 @@
 dead:
 			ehci_reset(oxu);
 			writel(0, &oxu->regs->configured_flag);
+			usb_hc_died(hcd);
 			/* generic layer kills/unlinks all urbs, then
 			 * uses oxu_stop to clean up the rest
 			 */
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/xhci.c linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/xhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci.c	2011-06-02 21:35:11.000000000 -0400
@@ -1636,8 +1636,17 @@
 	xhci_dbg_ctx(xhci, virt_dev->out_ctx,
 			LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
 
+	/* Free any rings that were dropped, but not changed. */
+	for (i = 1; i < 31; ++i) {
+		if ((ctrl_ctx->drop_flags & (1 << (i + 1))) &&
+				!(ctrl_ctx->add_flags & (1 << (i + 1))))
+			xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+	}
 	xhci_zero_in_ctx(xhci, virt_dev);
-	/* Install new rings and free or cache any old rings */
+	/*
+	 * Install any rings for completely new endpoints or changed endpoints,
+	 * and free or cache any old rings from changed endpoints.
+	 */
 	for (i = 1; i < 31; ++i) {
 		if (!virt_dev->eps[i].new_ring)
 			continue;
@@ -2335,10 +2344,18 @@
 	/* Everything but endpoint 0 is disabled, so free or cache the rings. */
 	last_freed_endpoint = 1;
 	for (i = 1; i < 31; ++i) {
-		if (!virt_dev->eps[i].ring)
-			continue;
-		xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
-		last_freed_endpoint = i;
+		struct xhci_virt_ep *ep = &virt_dev->eps[i];
+
+		if (ep->ep_state & EP_HAS_STREAMS) {
+			xhci_free_stream_info(xhci, ep->stream_info);
+			ep->stream_info = NULL;
+			ep->ep_state &= ~EP_HAS_STREAMS;
+		}
+
+		if (ep->ring) {
+			xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+			last_freed_endpoint = i;
+		}
 	}
 	xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
 	xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/xhci.h linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci.h
--- linux-libre-2.6.38-gnu/drivers/usb/host/xhci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci.h	2011-06-02 21:35:11.000000000 -0400
@@ -232,7 +232,7 @@
  * notification type that matches a bit set in this bit field.
  */
 #define	DEV_NOTE_MASK		(0xffff)
-#define ENABLE_DEV_NOTE(x)	(1 << x)
+#define ENABLE_DEV_NOTE(x)	(1 << (x))
 /* Most of the device notification types should only be used for debug.
  * SW does need to pay attention to function wake notifications.
  */
@@ -601,11 +601,11 @@
 #define EP_STATE_STOPPED	3
 #define EP_STATE_ERROR		4
 /* Mult - Max number of burtst within an interval, in EP companion desc. */
-#define EP_MULT(p)		((p & 0x3) << 8)
+#define EP_MULT(p)		(((p) & 0x3) << 8)
 /* bits 10:14 are Max Primary Streams */
 /* bit 15 is Linear Stream Array */
 /* Interval - period between requests to an endpoint - 125u increments. */
-#define EP_INTERVAL(p)		((p & 0xff) << 16)
+#define EP_INTERVAL(p)		(((p) & 0xff) << 16)
 #define EP_INTERVAL_TO_UFRAMES(p)		(1 << (((p) >> 16) & 0xff))
 #define EP_MAXPSTREAMS_MASK	(0x1f << 10)
 #define EP_MAXPSTREAMS(p)	(((p) << 10) & EP_MAXPSTREAMS_MASK)
@@ -644,6 +644,9 @@
 #define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
 #define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
 
+/* deq bitmasks */
+#define EP_CTX_CYCLE_MASK		(1 << 0)
+
 
 /**
  * struct xhci_input_control_context
@@ -746,6 +749,12 @@
 	struct timer_list	stop_cmd_timer;
 	int			stop_cmds_pending;
 	struct xhci_hcd		*xhci;
+	/* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue
+	 * command.  We'll need to update the ring's dequeue segment and dequeue
+	 * pointer after the command completes.
+	 */
+	struct xhci_segment	*queued_deq_seg;
+	union xhci_trb		*queued_deq_ptr;
 	/*
 	 * Sometimes the xHC can not process isochronous endpoint ring quickly
 	 * enough, and it will miss some isoc tds on the ring and generate
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/xhci-mem.c linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci-mem.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/xhci-mem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci-mem.c	2011-06-02 21:35:11.000000000 -0400
@@ -207,14 +207,13 @@
 
 	rings_cached = virt_dev->num_rings_cached;
 	if (rings_cached < XHCI_MAX_RINGS_CACHED) {
-		virt_dev->num_rings_cached++;
-		rings_cached = virt_dev->num_rings_cached;
 		virt_dev->ring_cache[rings_cached] =
 			virt_dev->eps[ep_index].ring;
+		virt_dev->num_rings_cached++;
 		xhci_dbg(xhci, "Cached old ring, "
 				"%d ring%s cached\n",
-				rings_cached,
-				(rings_cached > 1) ? "s" : "");
+				virt_dev->num_rings_cached,
+				(virt_dev->num_rings_cached > 1) ? "s" : "");
 	} else {
 		xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
 		xhci_dbg(xhci, "Ring cache full (%d rings), "
@@ -920,6 +919,47 @@
 	return 0;
 }
 
+/*
+ * Convert interval expressed as 2^(bInterval - 1) == interval into
+ * straight exponent value 2^n == interval.
+ *
+ */
+static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
+		struct usb_host_endpoint *ep)
+{
+	unsigned int interval;
+
+	interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
+	if (interval != ep->desc.bInterval - 1)
+		dev_warn(&udev->dev,
+			 "ep %#x - rounding interval to %d microframes\n",
+			 ep->desc.bEndpointAddress,
+			 1 << interval);
+
+	return interval;
+}
+
+/*
+ * Convert bInterval expressed in frames (in 1-255 range) to exponent of
+ * microframes, rounded down to nearest power of 2.
+ */
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+		struct usb_host_endpoint *ep)
+{
+	unsigned int interval;
+
+	interval = fls(8 * ep->desc.bInterval) - 1;
+	interval = clamp_val(interval, 3, 10);
+	if ((1 << interval) != 8 * ep->desc.bInterval)
+		dev_warn(&udev->dev,
+			 "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
+			 ep->desc.bEndpointAddress,
+			 1 << interval,
+			 8 * ep->desc.bInterval);
+
+	return interval;
+}
+
 /* Return the polling or NAK interval.
  *
  * The polling interval is expressed in "microframes".  If xHCI's Interval field
@@ -937,45 +977,38 @@
 	case USB_SPEED_HIGH:
 		/* Max NAK rate */
 		if (usb_endpoint_xfer_control(&ep->desc) ||
-				usb_endpoint_xfer_bulk(&ep->desc))
+		    usb_endpoint_xfer_bulk(&ep->desc)) {
 			interval = ep->desc.bInterval;
+			break;
+		}
 		/* Fall through - SS and HS isoc/int have same decoding */
+
 	case USB_SPEED_SUPER:
 		if (usb_endpoint_xfer_int(&ep->desc) ||
-				usb_endpoint_xfer_isoc(&ep->desc)) {
-			if (ep->desc.bInterval == 0)
-				interval = 0;
-			else
-				interval = ep->desc.bInterval - 1;
-			if (interval > 15)
-				interval = 15;
-			if (interval != ep->desc.bInterval + 1)
-				dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
-						ep->desc.bEndpointAddress, 1 << interval);
+		    usb_endpoint_xfer_isoc(&ep->desc)) {
+			interval = xhci_parse_exponent_interval(udev, ep);
 		}
 		break;
-	/* Convert bInterval (in 1-255 frames) to microframes and round down to
-	 * nearest power of 2.
-	 */
+
 	case USB_SPEED_FULL:
+		if (usb_endpoint_xfer_isoc(&ep->desc)) {
+			interval = xhci_parse_exponent_interval(udev, ep);
+			break;
+		}
+		/*
+		 * Fall through for interrupt endpoint interval decoding
+		 * since it uses the same rules as low speed interrupt
+		 * endpoints.
+		 */
+
 	case USB_SPEED_LOW:
 		if (usb_endpoint_xfer_int(&ep->desc) ||
-				usb_endpoint_xfer_isoc(&ep->desc)) {
-			interval = fls(8*ep->desc.bInterval) - 1;
-			if (interval > 10)
-				interval = 10;
-			if (interval < 3)
-				interval = 3;
-			if ((1 << interval) != 8*ep->desc.bInterval)
-				dev_warn(&udev->dev,
-						"ep %#x - rounding interval"
-						" to %d microframes, "
-						"ep desc says %d microframes\n",
-						ep->desc.bEndpointAddress,
-						1 << interval,
-						8*ep->desc.bInterval);
+		    usb_endpoint_xfer_isoc(&ep->desc)) {
+
+			interval = xhci_parse_frame_interval(udev, ep);
 		}
 		break;
+
 	default:
 		BUG();
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/usb/host/xhci-ring.c linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci-ring.c
--- linux-libre-2.6.38-gnu/drivers/usb/host/xhci-ring.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/host/xhci-ring.c	2011-06-02 21:35:11.000000000 -0400
@@ -500,15 +500,26 @@
 		state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
+	/*
+	 * If there is only one segment in a ring, find_trb_seg()'s while loop
+	 * will not run, and it will return before it has a chance to see if it
+	 * needs to toggle the cycle bit.  It can't tell if the stalled transfer
+	 * ended just before the link TRB on a one-segment ring, or if the TD
+	 * wrapped around the top of the ring, because it doesn't have the TD in
+	 * question.  Look for the one-segment case where stalled TRB's address
+	 * is greater than the new dequeue pointer address.
+	 */
+	if (ep_ring->first_seg == ep_ring->first_seg->next &&
+			state->new_deq_ptr < dev->eps[ep_index].stopped_trb)
+		state->new_cycle_state ^= 0x1;
+	xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state);
+
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
 			state->new_deq_seg);
 	addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
 	xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
 			(unsigned long long) addr);
-	xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
-	ep_ring->dequeue = state->new_deq_ptr;
-	ep_ring->deq_seg = state->new_deq_seg;
 }
 
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
@@ -951,9 +962,26 @@
 	} else {
 		xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
 				ep_ctx->deq);
+		if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr) ==
+				(ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) {
+			/* Update the ring's dequeue segment and dequeue pointer
+			 * to reflect the new position.
+			 */
+			ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg;
+			ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr;
+		} else {
+			xhci_warn(xhci, "Mismatch between completed Set TR Deq "
+					"Ptr command & xHCI internal state.\n");
+			xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
+					dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr);
+		}
 	}
 
 	dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
+	dev->eps[ep_index].queued_deq_seg = NULL;
+	dev->eps[ep_index].queued_deq_ptr = NULL;
 	/* Restart any rings with pending URBs */
 	ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
@@ -1504,6 +1532,9 @@
 		else
 			*status = 0;
 		break;
+	case COMP_STOP_INVAL:
+	case COMP_STOP:
+		return finish_td(xhci, td, event_trb, event, ep, status, false);
 	default:
 		if (!xhci_requires_manual_halt_cleanup(xhci,
 					ep_ctx, trb_comp_code))
@@ -1548,15 +1579,12 @@
 			}
 		} else {
 		/* Maybe the event was for the data stage? */
-			if (trb_comp_code != COMP_STOP_INVAL) {
-				/* We didn't stop on a link TRB in the middle */
-				td->urb->actual_length =
-					td->urb->transfer_buffer_length -
-					TRB_LEN(event->transfer_len);
-				xhci_dbg(xhci, "Waiting for status "
-						"stage event\n");
-				return 0;
-			}
+			td->urb->actual_length =
+				td->urb->transfer_buffer_length -
+				TRB_LEN(le32_to_cpu(event->transfer_len));
+			xhci_dbg(xhci, "Waiting for status "
+					"stage event\n");
+			return 0;
 		}
 	}
 
@@ -3229,6 +3257,7 @@
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
 	u32 type = TRB_TYPE(TRB_SET_DEQ);
+	struct xhci_virt_ep *ep;
 
 	addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
 	if (addr == 0) {
@@ -3237,6 +3266,14 @@
 				deq_seg, deq_ptr);
 		return 0;
 	}
+	ep = &xhci->devs[slot_id]->eps[ep_index];
+	if ((ep->ep_state & SET_DEQ_PENDING)) {
+		xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
+		xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n");
+		return 0;
+	}
+	ep->queued_deq_seg = deq_seg;
+	ep->queued_deq_ptr = deq_ptr;
 	return queue_command(xhci, lower_32_bits(addr) | cycle_state,
 			upper_32_bits(addr), trb_stream_id,
 			trb_slot_id | trb_ep_index | type, false);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/misc/uss720.c linux-libre-2.6.38.8-gnu/drivers/usb/misc/uss720.c
--- linux-libre-2.6.38-gnu/drivers/usb/misc/uss720.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/misc/uss720.c	2011-06-02 21:35:11.000000000 -0400
@@ -177,12 +177,11 @@
 	spin_lock_irqsave(&priv->asynclock, flags);
 	list_add_tail(&rq->asynclist, &priv->asynclist);
 	spin_unlock_irqrestore(&priv->asynclock, flags);
+	kref_get(&rq->ref_count);
 	ret = usb_submit_urb(rq->urb, mem_flags);
-	if (!ret) {
-		kref_get(&rq->ref_count);
+	if (!ret)
 		return rq;
-	}
-	kref_put(&rq->ref_count, destroy_async);
+	destroy_async(&rq->ref_count);
 	err("submit_async_request submit_urb failed with %d", ret);
 	return NULL;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/usb/musb/blackfin.c linux-libre-2.6.38.8-gnu/drivers/usb/musb/blackfin.c
--- linux-libre-2.6.38-gnu/drivers/usb/musb/blackfin.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/musb/blackfin.c	2011-06-02 21:35:11.000000000 -0400
@@ -322,7 +322,7 @@
 		mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
 }
 
-static int bfin_musb_get_vbus_status(struct musb *musb)
+static int bfin_musb_vbus_status(struct musb *musb)
 {
 	return 0;
 }
@@ -540,7 +540,7 @@
 	.resume		= bfin_resume,
 };
 
-#define DEV_PM_OPS	&bfin_pm_op,
+#define DEV_PM_OPS	&bfin_pm_ops
 #else
 #define DEV_PM_OPS	NULL
 #endif
@@ -548,7 +548,7 @@
 static struct platform_driver bfin_driver = {
 	.remove		= __exit_p(bfin_remove),
 	.driver		= {
-		.name	= "musb-bfin",
+		.name	= "musb-blackfin",
 		.pm	= DEV_PM_OPS,
 	},
 };
diff -druN linux-libre-2.6.38-gnu/drivers/usb/musb/Kconfig linux-libre-2.6.38.8-gnu/drivers/usb/musb/Kconfig
--- linux-libre-2.6.38-gnu/drivers/usb/musb/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/musb/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -14,7 +14,7 @@
 	select TWL4030_USB if MACH_OMAP_3430SDP
 	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 	select USB_OTG_UTILS
-	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
+	bool 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	help
 	  Say Y here if your system has a dual role high speed USB
 	  controller based on the Mentor Graphics silicon IP.  Then
@@ -30,8 +30,8 @@
 
 	  If you do not know what this is, please say N.
 
-	  To compile this driver as a module, choose M here; the
-	  module will be called "musb-hdrc".
+#	  To compile this driver as a module, choose M here; the
+#	  module will be called "musb-hdrc".
 
 choice
 	prompt "Platform Glue Layer"
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/ch341.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/ch341.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/ch341.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/ch341.c	2011-06-02 21:35:11.000000000 -0400
@@ -75,6 +75,7 @@
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x4348, 0x5523) },
 	{ USB_DEVICE(0x1a86, 0x7523) },
+	{ USB_DEVICE(0x1a86, 0x5523) },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/cp210x.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/cp210x.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/cp210x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/cp210x.c	2011-06-02 21:35:11.000000000 -0400
@@ -113,6 +113,10 @@
 	{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
 	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
+	{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
+	{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+	{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
+	{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/ftdi_sio.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/ftdi_sio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/ftdi_sio.c	2011-06-02 21:35:11.000000000 -0400
@@ -151,6 +151,8 @@
  * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
  */
 static struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
@@ -525,6 +527,7 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
+	{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
@@ -563,6 +566,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
 	/*
 	 * ELV devices:
 	 */
@@ -785,6 +789,8 @@
 	{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+	{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
+	{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
 	{ USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
 	{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/ftdi_sio_ids.h linux-libre-2.6.38.8-gnu/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-2.6.38-gnu/drivers/usb/serial/ftdi_sio_ids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/ftdi_sio_ids.h	2011-06-02 21:35:11.000000000 -0400
@@ -300,6 +300,8 @@
  * Hameg HO820 and HO870 interface (using VID 0x0403)
  */
 #define HAMEG_HO820_PID			0xed74
+#define HAMEG_HO730_PID			0xed73
+#define HAMEG_HO720_PID			0xed72
 #define HAMEG_HO870_PID			0xed71
 
 /*
@@ -489,6 +491,11 @@
 /* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
 #define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
 
+/*
+ * TavIR AVR product ids (FTDI_VID)
+ */
+#define FTDI_TAVIR_STK500_PID	0xFA33	/* STK500 AVR programmer */
+
 
 
 /********************************/
@@ -572,6 +579,7 @@
 /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
 /* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
 /* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
+#define OCT_DK201_PID		0x0103	/* OCT DK201 USB docking station */
 #define OCT_US101_PID		0x0421	/* OCT US101 USB to RS-232 */
 
 /*
@@ -1140,3 +1148,12 @@
 #define QIHARDWARE_VID			0x20B7
 #define MILKYMISTONE_JTAGSERIAL_PID	0x0713
 
+/*
+ * CTI GmbH RS485 Converter http://www.cti-lean.com/
+ */
+/* USB-485-Mini*/
+#define FTDI_CTI_MINI_PID	0xF608
+/* USB-Nano-485*/
+#define FTDI_CTI_NANO_PID	0xF60B
+
+
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/garmin_gps.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/garmin_gps.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/garmin_gps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/garmin_gps.c	2011-06-02 21:35:11.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Garmin GPS driver
  *
- * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de
  *
  * The latest version of the driver can be found at
  * http://sourceforge.net/projects/garmin-gps/
@@ -51,7 +51,7 @@
  */
 
 #define VERSION_MAJOR	0
-#define VERSION_MINOR	33
+#define VERSION_MINOR	36
 
 #define _STR(s) #s
 #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
@@ -410,6 +410,7 @@
  */
 static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
 {
+	unsigned long flags;
 	const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
 	__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
 
@@ -458,7 +459,9 @@
 	/* if this was an abort-transfer command, flush all
 	   queued data. */
 	if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags |= FLAGS_DROP_DATA;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 		pkt_clear(garmin_data_p);
 	}
 
@@ -943,7 +946,7 @@
 	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->mode  = initial_mode;
 	garmin_data_p->count = 0;
-	garmin_data_p->flags = 0;
+	garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN;
 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	/* shutdown any bulk reads that might be going on */
@@ -1178,7 +1181,8 @@
 
 
 static void garmin_read_process(struct garmin_data *garmin_data_p,
-				 unsigned char *data, unsigned data_length)
+				 unsigned char *data, unsigned data_length,
+				 int bulk_data)
 {
 	unsigned long flags;
 
@@ -1193,7 +1197,8 @@
 		   send it directly to the tty port */
 		if (garmin_data_p->flags & FLAGS_QUEUING) {
 			pkt_add(garmin_data_p, data, data_length);
-		} else if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+		} else if (bulk_data ||
+			   getLayerId(data) == GARMIN_LAYERID_APPL) {
 
 			spin_lock_irqsave(&garmin_data_p->lock, flags);
 			garmin_data_p->flags |= APP_RESP_SEEN;
@@ -1237,7 +1242,7 @@
 	usb_serial_debug_data(debug, &port->dev,
 				__func__, urb->actual_length, data);
 
-	garmin_read_process(garmin_data_p, data, urb->actual_length);
+	garmin_read_process(garmin_data_p, data, urb->actual_length, 1);
 
 	if (urb->actual_length == 0 &&
 			0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
@@ -1346,7 +1351,7 @@
 			__func__, garmin_data_p->serial_num);
 	}
 
-	garmin_read_process(garmin_data_p, data, urb->actual_length);
+	garmin_read_process(garmin_data_p, data, urb->actual_length, 0);
 
 	port->interrupt_in_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1461,6 +1466,7 @@
 	garmin_data_p->timer.function = timeout_handler;
 	garmin_data_p->port = port;
 	garmin_data_p->state = 0;
+	garmin_data_p->flags = 0;
 	garmin_data_p->count = 0;
 	usb_set_serial_port_data(port, garmin_data_p);
 
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/kobil_sct.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/kobil_sct.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/kobil_sct.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/kobil_sct.c	2011-06-02 21:35:11.000000000 -0400
@@ -372,7 +372,7 @@
 	}
 
 	tty = tty_port_tty_get(&port->port);
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 
 		/* BEGIN DEBUG */
 		/*
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/moto_modem.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/moto_modem.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/moto_modem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/moto_modem.c	2011-06-02 21:35:11.000000000 -0400
@@ -25,6 +25,7 @@
 	{ USB_DEVICE(0x05c6, 0x3197) },	/* unknown Motorola phone */
 	{ USB_DEVICE(0x0c44, 0x0022) },	/* unknown Mororola phone */
 	{ USB_DEVICE(0x22b8, 0x2a64) },	/* Motorola KRZR K1m */
+	{ USB_DEVICE(0x22b8, 0x2c84) }, /* Motorola VE240 phone */
 	{ USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
 	{ },
 };
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/option.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/option.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/option.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/option.c	2011-06-02 21:35:11.000000000 -0400
@@ -149,6 +149,7 @@
 #define HUAWEI_PRODUCT_K3765			0x1465
 #define HUAWEI_PRODUCT_E14AC			0x14AC
 #define HUAWEI_PRODUCT_ETS1220			0x1803
+#define HUAWEI_PRODUCT_E353			0x1506
 
 #define QUANTA_VENDOR_ID			0x0408
 #define QUANTA_PRODUCT_Q101			0xEA02
@@ -407,6 +408,10 @@
 /* ONDA MT825UP HSDPA 14.2 modem */
 #define ONDA_MT825UP         0x000b
 
+/* Samsung products */
+#define SAMSUNG_VENDOR_ID                       0x04e8
+#define SAMSUNG_PRODUCT_GT_B3730                0x6889
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -528,6 +533,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
@@ -652,7 +658,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff,
+	  0xff, 0xff), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) },
@@ -967,6 +974,7 @@
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
 	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1103,6 +1111,12 @@
 		serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
 		return -ENODEV;
 
+	/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
+	if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
+		serial->dev->descriptor.idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
+		serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA)
+		return -ENODEV;
+
 	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
 
 	if (!data)
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/qcserial.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/qcserial.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/qcserial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/qcserial.c	2011-06-02 21:35:11.000000000 -0400
@@ -111,7 +111,7 @@
 	ifnum = intf->desc.bInterfaceNumber;
 	dbg("This Interface = %d", ifnum);
 
-	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+	data = kzalloc(sizeof(struct usb_wwan_intf_private),
 					 GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -134,8 +134,10 @@
 		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
 			dbg("QDL port found");
 
-			if (serial->interface->num_altsetting == 1)
-				return 0;
+			if (serial->interface->num_altsetting == 1) {
+				retval = 0; /* Success */
+				break;
+			}
 
 			retval = usb_set_interface(serial->dev, ifnum, 1);
 			if (retval < 0) {
@@ -145,7 +147,6 @@
 				retval = -ENODEV;
 				kfree(data);
 			}
-			return retval;
 		}
 		break;
 
@@ -166,6 +167,7 @@
 					"Could not set interface, error %d\n",
 					retval);
 				retval = -ENODEV;
+				kfree(data);
 			}
 		} else if (ifnum == 2) {
 			dbg("Modem port found");
@@ -177,7 +179,6 @@
 				retval = -ENODEV;
 				kfree(data);
 			}
-			return retval;
 		} else if (ifnum==3) {
 			/*
 			 * NMEA (serial line 9600 8N1)
@@ -191,6 +192,7 @@
 					"Could not set interface, error %d\n",
 					retval);
 				retval = -ENODEV;
+				kfree(data);
 			}
 		}
 		break;
@@ -199,12 +201,27 @@
 		dev_err(&serial->dev->dev,
 			"unknown number of interfaces: %d\n", nintf);
 		kfree(data);
-		return -ENODEV;
+		retval = -ENODEV;
 	}
 
+	/* Set serial->private if not returning -ENODEV */
+	if (retval != -ENODEV)
+		usb_set_serial_data(serial, data);
 	return retval;
 }
 
+static void qc_release(struct usb_serial *serial)
+{
+	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
+
+	dbg("%s", __func__);
+
+	/* Call usb_wwan release & free the private data allocated in qcprobe */
+	usb_wwan_release(serial);
+	usb_set_serial_data(serial, NULL);
+	kfree(priv);
+}
+
 static struct usb_serial_driver qcdevice = {
 	.driver = {
 		.owner     = THIS_MODULE,
@@ -222,7 +239,7 @@
 	.chars_in_buffer     = usb_wwan_chars_in_buffer,
 	.attach		     = usb_wwan_startup,
 	.disconnect	     = usb_wwan_disconnect,
-	.release	     = usb_wwan_release,
+	.release	     = qc_release,
 #ifdef CONFIG_PM
 	.suspend	     = usb_wwan_suspend,
 	.resume		     = usb_wwan_resume,
diff -druN linux-libre-2.6.38-gnu/drivers/usb/serial/usb-serial.c linux-libre-2.6.38.8-gnu/drivers/usb/serial/usb-serial.c
--- linux-libre-2.6.38-gnu/drivers/usb/serial/usb-serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/usb/serial/usb-serial.c	2011-06-02 21:35:11.000000000 -0400
@@ -911,9 +911,8 @@
 			dev_err(&interface->dev, "No free urbs available\n");
 			goto probe_error;
 		}
-		buffer_size = serial->type->bulk_in_size;
-		if (!buffer_size)
-			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+		buffer_size = max_t(int, serial->type->bulk_in_size,
+				le16_to_cpu(endpoint->wMaxPacketSize));
 		port->bulk_in_size = buffer_size;
 		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
 		port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
diff -druN linux-libre-2.6.38-gnu/drivers/video/console/tileblit.c linux-libre-2.6.38.8-gnu/drivers/video/console/tileblit.c
--- linux-libre-2.6.38-gnu/drivers/video/console/tileblit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/video/console/tileblit.c	2011-06-02 21:35:11.000000000 -0400
@@ -83,7 +83,7 @@
 			int softback_lines, int fg, int bg)
 {
 	struct fb_tilecursor cursor;
-	int use_sw = (vc->vc_cursor_type & 0x01);
+	int use_sw = (vc->vc_cursor_type & 0x10);
 
 	cursor.sx = vc->vc_x;
 	cursor.sy = vc->vc_y;
diff -druN linux-libre-2.6.38-gnu/drivers/video/via/viafbdev.h linux-libre-2.6.38.8-gnu/drivers/video/via/viafbdev.h
--- linux-libre-2.6.38-gnu/drivers/video/via/viafbdev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/video/via/viafbdev.h	2011-06-02 21:35:11.000000000 -0400
@@ -94,9 +94,6 @@
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-extern int strict_strtoul(const char *cp, unsigned int base,
-	unsigned long *res);
-
 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
 	*plvds_setting_info, struct lvds_chip_information
 	*plvds_chip_info, u8 index);
diff -druN linux-libre-2.6.38-gnu/drivers/virtio/virtio_ring.c linux-libre-2.6.38.8-gnu/drivers/virtio/virtio_ring.c
--- linux-libre-2.6.38-gnu/drivers/virtio/virtio_ring.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/virtio/virtio_ring.c	2011-06-02 21:35:11.000000000 -0400
@@ -371,6 +371,7 @@
 		/* detach_buf clears data, so grab it now. */
 		buf = vq->data[i];
 		detach_buf(vq, i);
+		vq->vring.avail->idx--;
 		END_USE(vq);
 		return buf;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/watchdog/davinci_wdt.c linux-libre-2.6.38.8-gnu/drivers/watchdog/davinci_wdt.c
--- linux-libre-2.6.38-gnu/drivers/watchdog/davinci_wdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/watchdog/davinci_wdt.c	2011-06-02 21:35:11.000000000 -0400
@@ -202,7 +202,6 @@
 static int __devinit davinci_wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0, size;
-	struct resource *res;
 	struct device *dev = &pdev->dev;
 
 	wdt_clk = clk_get(dev, NULL);
@@ -216,31 +215,31 @@
 
 	dev_info(dev, "heartbeat %d sec\n", heartbeat);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (wdt_mem == NULL) {
 		dev_err(dev, "failed to get memory region resource\n");
 		return -ENOENT;
 	}
 
-	size = resource_size(res);
-	wdt_mem = request_mem_region(res->start, size, pdev->name);
-
-	if (wdt_mem == NULL) {
+	size = resource_size(wdt_mem);
+	if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
 		dev_err(dev, "failed to get memory region\n");
 		return -ENOENT;
 	}
 
-	wdt_base = ioremap(res->start, size);
+	wdt_base = ioremap(wdt_mem->start, size);
 	if (!wdt_base) {
 		dev_err(dev, "failed to map memory region\n");
+		release_mem_region(wdt_mem->start, size);
+		wdt_mem = NULL;
 		return -ENOMEM;
 	}
 
 	ret = misc_register(&davinci_wdt_miscdev);
 	if (ret < 0) {
 		dev_err(dev, "cannot register misc device\n");
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, size);
+		wdt_mem = NULL;
 	} else {
 		set_bit(WDT_DEVICE_INITED, &wdt_status);
 	}
@@ -253,8 +252,7 @@
 {
 	misc_deregister(&davinci_wdt_miscdev);
 	if (wdt_mem) {
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, resource_size(wdt_mem));
 		wdt_mem = NULL;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/watchdog/max63xx_wdt.c linux-libre-2.6.38.8-gnu/drivers/watchdog/max63xx_wdt.c
--- linux-libre-2.6.38-gnu/drivers/watchdog/max63xx_wdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/watchdog/max63xx_wdt.c	2011-06-02 21:35:11.000000000 -0400
@@ -270,7 +270,6 @@
 {
 	int ret = 0;
 	int size;
-	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct max63xx_timeout *table;
 
@@ -294,21 +293,19 @@
 
 	max63xx_pdev = pdev;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (wdt_mem == NULL) {
 		dev_err(dev, "failed to get memory region resource\n");
 		return -ENOENT;
 	}
 
-	size = resource_size(res);
-	wdt_mem = request_mem_region(res->start, size, pdev->name);
-
-	if (wdt_mem == NULL) {
+	size = resource_size(wdt_mem);
+	if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
 		dev_err(dev, "failed to get memory region\n");
 		return -ENOENT;
 	}
 
-	wdt_base = ioremap(res->start, size);
+	wdt_base = ioremap(wdt_mem->start, size);
 	if (!wdt_base) {
 		dev_err(dev, "failed to map memory region\n");
 		ret = -ENOMEM;
@@ -326,8 +323,8 @@
 out_unmap:
 	iounmap(wdt_base);
 out_request:
-	release_resource(wdt_mem);
-	kfree(wdt_mem);
+	release_mem_region(wdt_mem->start, size);
+	wdt_mem = NULL;
 
 	return ret;
 }
@@ -336,8 +333,7 @@
 {
 	misc_deregister(&max63xx_wdt_miscdev);
 	if (wdt_mem) {
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, resource_size(wdt_mem));
 		wdt_mem = NULL;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/watchdog/pnx4008_wdt.c linux-libre-2.6.38.8-gnu/drivers/watchdog/pnx4008_wdt.c
--- linux-libre-2.6.38-gnu/drivers/watchdog/pnx4008_wdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/watchdog/pnx4008_wdt.c	2011-06-02 21:35:11.000000000 -0400
@@ -254,7 +254,6 @@
 static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0, size;
-	struct resource *res;
 
 	if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
 		heartbeat = DEFAULT_HEARTBEAT;
@@ -262,42 +261,42 @@
 	printk(KERN_INFO MODULE_NAME
 		"PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (wdt_mem == NULL) {
 		printk(KERN_INFO MODULE_NAME
 			"failed to get memory region resouce\n");
 		return -ENOENT;
 	}
 
-	size = resource_size(res);
-	wdt_mem = request_mem_region(res->start, size, pdev->name);
+	size = resource_size(wdt_mem);
 
-	if (wdt_mem == NULL) {
+	if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
 		printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
 		return -ENOENT;
 	}
-	wdt_base = (void __iomem *)IO_ADDRESS(res->start);
+	wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
 
 	wdt_clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(wdt_clk)) {
 		ret = PTR_ERR(wdt_clk);
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, size);
+		wdt_mem = NULL;
 		goto out;
 	}
 
 	ret = clk_enable(wdt_clk);
 	if (ret) {
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, size);
+		wdt_mem = NULL;
+		clk_put(wdt_clk);
 		goto out;
 	}
 
 	ret = misc_register(&pnx4008_wdt_miscdev);
 	if (ret < 0) {
 		printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, size);
+		wdt_mem = NULL;
 		clk_disable(wdt_clk);
 		clk_put(wdt_clk);
 	} else {
@@ -320,8 +319,7 @@
 	clk_put(wdt_clk);
 
 	if (wdt_mem) {
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
+		release_mem_region(wdt_mem->start, resource_size(wdt_mem));
 		wdt_mem = NULL;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/watchdog/s3c2410_wdt.c linux-libre-2.6.38.8-gnu/drivers/watchdog/s3c2410_wdt.c
--- linux-libre-2.6.38-gnu/drivers/watchdog/s3c2410_wdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/watchdog/s3c2410_wdt.c	2011-06-02 21:35:11.000000000 -0400
@@ -402,7 +402,6 @@
 
 static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 {
-	struct resource *res;
 	struct device *dev;
 	unsigned int wtcon;
 	int started = 0;
@@ -416,20 +415,19 @@
 
 	/* get the memory region for the watchdog timer */
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (wdt_mem == NULL) {
 		dev_err(dev, "no memory resource specified\n");
 		return -ENOENT;
 	}
 
-	size = resource_size(res);
-	wdt_mem = request_mem_region(res->start, size, pdev->name);
-	if (wdt_mem == NULL) {
+	size = resource_size(wdt_mem);
+	if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
 		dev_err(dev, "failed to get memory region\n");
 		return -EBUSY;
 	}
 
-	wdt_base = ioremap(res->start, size);
+	wdt_base = ioremap(wdt_mem->start, size);
 	if (wdt_base == NULL) {
 		dev_err(dev, "failed to ioremap() region\n");
 		ret = -EINVAL;
@@ -524,8 +522,8 @@
 	iounmap(wdt_base);
 
  err_req:
-	release_resource(wdt_mem);
-	kfree(wdt_mem);
+	release_mem_region(wdt_mem->start, size);
+	wdt_mem = NULL;
 
 	return ret;
 }
@@ -545,8 +543,7 @@
 
 	iounmap(wdt_base);
 
-	release_resource(wdt_mem);
-	kfree(wdt_mem);
+	release_mem_region(wdt_mem->start, resource_size(wdt_mem));
 	wdt_mem = NULL;
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/watchdog/sp5100_tco.c linux-libre-2.6.38.8-gnu/drivers/watchdog/sp5100_tco.c
--- linux-libre-2.6.38-gnu/drivers/watchdog/sp5100_tco.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/drivers/watchdog/sp5100_tco.c	2011-06-02 21:35:11.000000000 -0400
@@ -42,6 +42,7 @@
 #define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
+static u32 tcobase_phys;
 static void __iomem *tcobase;
 static unsigned int pm_iobase;
 static DEFINE_SPINLOCK(tco_lock);	/* Guards the hardware */
@@ -305,10 +306,18 @@
 	/* Low three bits of BASE0 are reserved. */
 	val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
 
+	if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
+								"SP5100 TCO")) {
+		printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
+			val);
+		goto unreg_region;
+	}
+	tcobase_phys = val;
+
 	tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
 	if (tcobase == 0) {
 		printk(KERN_ERR PFX "failed to get tcobase address\n");
-		goto unreg_region;
+		goto unreg_mem_region;
 	}
 
 	/* Enable watchdog decode bit */
@@ -346,7 +355,8 @@
 	/* Done */
 	return 1;
 
-	iounmap(tcobase);
+unreg_mem_region:
+	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
 unreg_region:
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 exit:
@@ -401,6 +411,7 @@
 
 exit:
 	iounmap(tcobase);
+	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 	return ret;
 }
@@ -414,6 +425,7 @@
 	/* Deregister */
 	misc_deregister(&sp5100_tco_miscdev);
 	iounmap(tcobase);
+	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/aio.c linux-libre-2.6.38.8-gnu/fs/aio.c
--- linux-libre-2.6.38-gnu/fs/aio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/aio.c	2011-06-02 21:35:11.000000000 -0400
@@ -520,7 +520,7 @@
 	ctx->reqs_active--;
 
 	if (unlikely(!ctx->reqs_active && ctx->dead))
-		wake_up(&ctx->wait);
+		wake_up_all(&ctx->wait);
 }
 
 static void aio_fput_routine(struct work_struct *data)
@@ -1229,7 +1229,7 @@
 	 * by other CPUs at this point.  Right now, we rely on the
 	 * locking done by the above calls to ensure this consistency.
 	 */
-	wake_up(&ioctx->wait);
+	wake_up_all(&ioctx->wait);
 	put_ioctx(ioctx);	/* once for the lookup */
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/binfmt_elf.c linux-libre-2.6.38.8-gnu/fs/binfmt_elf.c
--- linux-libre-2.6.38-gnu/fs/binfmt_elf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/binfmt_elf.c	2011-06-02 21:35:11.000000000 -0400
@@ -941,9 +941,13 @@
 	current->mm->start_stack = bprm->p;
 
 #ifdef arch_randomize_brk
-	if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
+	if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
 		current->mm->brk = current->mm->start_brk =
 			arch_randomize_brk(current->mm);
+#ifdef CONFIG_COMPAT_BRK
+		current->brk_randomized = 1;
+#endif
+	}
 #endif
 
 	if (current->personality & MMAP_PAGE_ZERO) {
diff -druN linux-libre-2.6.38-gnu/fs/block_dev.c linux-libre-2.6.38.8-gnu/fs/block_dev.c
--- linux-libre-2.6.38-gnu/fs/block_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/block_dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -1099,6 +1099,7 @@
 			if (!bdev->bd_part)
 				goto out_clear;
 
+			ret = 0;
 			if (disk->fops->open) {
 				ret = disk->fops->open(bdev, mode);
 				if (ret == -ERESTARTSYS) {
@@ -1114,18 +1115,26 @@
 					mutex_unlock(&bdev->bd_mutex);
 					goto restart;
 				}
-				if (ret)
-					goto out_clear;
 			}
-			if (!bdev->bd_openers) {
+
+			if (!ret && !bdev->bd_openers) {
 				bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
 				bdi = blk_get_backing_dev_info(bdev);
 				if (bdi == NULL)
 					bdi = &default_backing_dev_info;
 				bdev_inode_switch_bdi(bdev->bd_inode, bdi);
 			}
-			if (bdev->bd_invalidated)
+
+			/*
+			 * If the device is invalidated, rescan partition
+			 * if open succeeded or failed with -ENOMEDIUM.
+			 * The latter is necessary to prevent ghost
+			 * partitions on a removed medium.
+			 */
+			if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
 				rescan_partitions(disk, bdev);
+			if (ret)
+				goto out_clear;
 		} else {
 			struct block_device *whole;
 			whole = bdget_disk(disk, 0);
@@ -1152,13 +1161,14 @@
 		put_disk(disk);
 		disk = NULL;
 		if (bdev->bd_contains == bdev) {
-			if (bdev->bd_disk->fops->open) {
+			ret = 0;
+			if (bdev->bd_disk->fops->open)
 				ret = bdev->bd_disk->fops->open(bdev, mode);
-				if (ret)
-					goto out_unlock_bdev;
-			}
-			if (bdev->bd_invalidated)
+			/* the same as first opener case, read comment there */
+			if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
 				rescan_partitions(bdev->bd_disk, bdev);
+			if (ret)
+				goto out_unlock_bdev;
 		}
 	}
 	bdev->bd_openers++;
@@ -1223,6 +1233,8 @@
 	res = __blkdev_get(bdev, mode, 0);
 
 	if (whole) {
+		struct gendisk *disk = whole->bd_disk;
+
 		/* finish claiming */
 		mutex_lock(&bdev->bd_mutex);
 		spin_lock(&bdev_lock);
@@ -1249,15 +1261,16 @@
 		spin_unlock(&bdev_lock);
 
 		/*
-		 * Block event polling for write claims.  Any write
-		 * holder makes the write_holder state stick until all
-		 * are released.  This is good enough and tracking
-		 * individual writeable reference is too fragile given
-		 * the way @mode is used in blkdev_get/put().
+		 * Block event polling for write claims if requested.  Any
+		 * write holder makes the write_holder state stick until
+		 * all are released.  This is good enough and tracking
+		 * individual writeable reference is too fragile given the
+		 * way @mode is used in blkdev_get/put().
 		 */
-		if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
+		if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) &&
+		    !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
 			bdev->bd_write_holder = true;
-			disk_block_events(bdev->bd_disk);
+			disk_block_events(disk);
 		}
 
 		mutex_unlock(&bdev->bd_mutex);
diff -druN linux-libre-2.6.38-gnu/fs/btrfs/ctree.h linux-libre-2.6.38.8-gnu/fs/btrfs/ctree.h
--- linux-libre-2.6.38-gnu/fs/btrfs/ctree.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/btrfs/ctree.h	2011-06-02 21:35:11.000000000 -0400
@@ -1284,6 +1284,8 @@
 #define BTRFS_INODE_NOATIME		(1 << 9)
 #define BTRFS_INODE_DIRSYNC		(1 << 10)
 
+#define BTRFS_INODE_ROOT_ITEM_INIT	(1 << 31)
+
 /* some macros to generate set/get funcs for the struct fields.  This
  * assumes there is a lefoo_to_cpu for every type, so lets make a simple
  * one for u8:
@@ -2355,6 +2357,8 @@
 int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
 int btrfs_set_root_node(struct btrfs_root_item *item,
 			struct extent_buffer *node);
+void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
+
 /* dir-item.c */
 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root, const char *name,
diff -druN linux-libre-2.6.38-gnu/fs/btrfs/disk-io.c linux-libre-2.6.38.8-gnu/fs/btrfs/disk-io.c
--- linux-libre-2.6.38-gnu/fs/btrfs/disk-io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/btrfs/disk-io.c	2011-06-02 21:35:11.000000000 -0400
@@ -1184,8 +1184,10 @@
 	root->commit_root = btrfs_root_node(root);
 	BUG_ON(!root->node);
 out:
-	if (location->objectid != BTRFS_TREE_LOG_OBJECTID)
+	if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
 		root->ref_cows = 1;
+		btrfs_check_and_init_root_item(&root->root_item);
+	}
 
 	return root;
 }
diff -druN linux-libre-2.6.38-gnu/fs/btrfs/ioctl.c linux-libre-2.6.38.8-gnu/fs/btrfs/ioctl.c
--- linux-libre-2.6.38-gnu/fs/btrfs/ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/btrfs/ioctl.c	2011-06-02 21:35:11.000000000 -0400
@@ -294,6 +294,10 @@
 	inode_item->nbytes = cpu_to_le64(root->leafsize);
 	inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
 
+	root_item.flags = 0;
+	root_item.byte_limit = 0;
+	inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT);
+
 	btrfs_set_root_bytenr(&root_item, leaf->start);
 	btrfs_set_root_generation(&root_item, trans->transid);
 	btrfs_set_root_level(&root_item, 0);
diff -druN linux-libre-2.6.38-gnu/fs/btrfs/root-tree.c linux-libre-2.6.38.8-gnu/fs/btrfs/root-tree.c
--- linux-libre-2.6.38-gnu/fs/btrfs/root-tree.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/btrfs/root-tree.c	2011-06-02 21:35:11.000000000 -0400
@@ -471,3 +471,21 @@
 	btrfs_free_path(path);
 	return 0;
 }
+
+/*
+ * Old btrfs forgets to init root_item->flags and root_item->byte_limit
+ * for subvolumes. To work around this problem, we steal a bit from
+ * root_item->inode_item->flags, and use it to indicate if those fields
+ * have been properly initialized.
+ */
+void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
+{
+	u64 inode_flags = le64_to_cpu(root_item->inode.flags);
+
+	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
+		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
+		root_item->inode.flags = cpu_to_le64(inode_flags);
+		root_item->flags = 0;
+		root_item->byte_limit = 0;
+	}
+}
diff -druN linux-libre-2.6.38-gnu/fs/btrfs/transaction.c linux-libre-2.6.38.8-gnu/fs/btrfs/transaction.c
--- linux-libre-2.6.38-gnu/fs/btrfs/transaction.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/btrfs/transaction.c	2011-06-02 21:35:11.000000000 -0400
@@ -970,6 +970,7 @@
 	record_root_in_trans(trans, root);
 	btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
 	memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
+	btrfs_check_and_init_root_item(new_root_item);
 
 	root_flags = btrfs_root_flags(new_root_item);
 	if (pending->readonly)
diff -druN linux-libre-2.6.38-gnu/fs/cifs/cifsencrypt.c linux-libre-2.6.38.8-gnu/fs/cifs/cifsencrypt.c
--- linux-libre-2.6.38-gnu/fs/cifs/cifsencrypt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/cifsencrypt.c	2011-06-02 21:35:11.000000000 -0400
@@ -30,12 +30,13 @@
 #include <linux/ctype.h>
 #include <linux/random.h>
 
-/* Calculate and return the CIFS signature based on the mac key and SMB PDU */
-/* the 16 byte signature must be allocated by the caller  */
-/* Note we only use the 1st eight bytes */
-/* Note that the smb header signature field on input contains the
-	sequence number before this function is called */
-
+/*
+ * Calculate and return the CIFS signature based on the mac key and SMB PDU.
+ * The 16 byte signature must be allocated by the caller. Note we only use the
+ * 1st eight bytes and that the smb header signature field on input contains
+ * the sequence number before this function is called. Also, this function
+ * should be called with the server->srv_mutex held.
+ */
 static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
 				struct TCP_Server_Info *server, char *signature)
 {
@@ -209,8 +210,10 @@
 					cpu_to_le32(expected_sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
+	mutex_lock(&server->srv_mutex);
 	rc = cifs_calculate_signature(cifs_pdu, server,
 		what_we_think_sig_should_be);
+	mutex_unlock(&server->srv_mutex);
 
 	if (rc)
 		return rc;
diff -druN linux-libre-2.6.38-gnu/fs/cifs/cifsfs.c linux-libre-2.6.38.8-gnu/fs/cifs/cifsfs.c
--- linux-libre-2.6.38-gnu/fs/cifs/cifsfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/cifsfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -127,6 +127,7 @@
 		kfree(cifs_sb);
 		return rc;
 	}
+	cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	/* copy mount params to sb for use in submounts */
diff -druN linux-libre-2.6.38-gnu/fs/cifs/cifs_unicode.c linux-libre-2.6.38.8-gnu/fs/cifs/cifs_unicode.c
--- linux-libre-2.6.38-gnu/fs/cifs/cifs_unicode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/cifs_unicode.c	2011-06-02 21:35:11.000000000 -0400
@@ -90,7 +90,7 @@
 	case UNI_COLON:
 		*target = ':';
 		break;
-	case UNI_ASTERIK:
+	case UNI_ASTERISK:
 		*target = '*';
 		break;
 	case UNI_QUESTION:
@@ -264,40 +264,41 @@
  * names are little endian 16 bit Unicode on the wire
  */
 int
-cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
+cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 		 const struct nls_table *cp, int mapChars)
 {
 	int i, j, charlen;
-	int len_remaining = maxlen;
 	char src_char;
-	__u16 temp;
+	__le16 dst_char;
+	wchar_t tmp;
 
 	if (!mapChars)
 		return cifs_strtoUCS(target, source, PATH_MAX, cp);
 
-	for (i = 0, j = 0; i < maxlen; j++) {
+	for (i = 0, j = 0; i < srclen; j++) {
 		src_char = source[i];
+		charlen = 1;
 		switch (src_char) {
 		case 0:
-			put_unaligned_le16(0, &target[j]);
+			put_unaligned(0, &target[j]);
 			goto ctoUCS_out;
 		case ':':
-			temp = UNI_COLON;
+			dst_char = cpu_to_le16(UNI_COLON);
 			break;
 		case '*':
-			temp = UNI_ASTERIK;
+			dst_char = cpu_to_le16(UNI_ASTERISK);
 			break;
 		case '?':
-			temp = UNI_QUESTION;
+			dst_char = cpu_to_le16(UNI_QUESTION);
 			break;
 		case '<':
-			temp = UNI_LESSTHAN;
+			dst_char = cpu_to_le16(UNI_LESSTHAN);
 			break;
 		case '>':
-			temp = UNI_GRTRTHAN;
+			dst_char = cpu_to_le16(UNI_GRTRTHAN);
 			break;
 		case '|':
-			temp = UNI_PIPE;
+			dst_char = cpu_to_le16(UNI_PIPE);
 			break;
 		/*
 		 * FIXME: We can not handle remapping backslash (UNI_SLASH)
@@ -305,28 +306,24 @@
 		 * as they use backslash as separator.
 		 */
 		default:
-			charlen = cp->char2uni(source+i, len_remaining,
-						&temp);
+			charlen = cp->char2uni(source + i, srclen - i, &tmp);
+			dst_char = cpu_to_le16(tmp);
+
 			/*
 			 * if no match, use question mark, which at least in
 			 * some cases serves as wild card
 			 */
 			if (charlen < 1) {
-				temp = 0x003f;
+				dst_char = cpu_to_le16(0x003f);
 				charlen = 1;
 			}
-			len_remaining -= charlen;
-			/*
-			 * character may take more than one byte in the source
-			 * string, but will take exactly two bytes in the
-			 * target string
-			 */
-			i += charlen;
-			continue;
 		}
-		put_unaligned_le16(temp, &target[j]);
-		i++; /* move to next char in source string */
-		len_remaining--;
+		/*
+		 * character may take more than one byte in the source string,
+		 * but will take exactly two bytes in the target string
+		 */
+		i += charlen;
+		put_unaligned(dst_char, &target[j]);
 	}
 
 ctoUCS_out:
diff -druN linux-libre-2.6.38-gnu/fs/cifs/cifs_unicode.h linux-libre-2.6.38.8-gnu/fs/cifs/cifs_unicode.h
--- linux-libre-2.6.38-gnu/fs/cifs/cifs_unicode.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/cifs_unicode.h	2011-06-02 21:35:11.000000000 -0400
@@ -44,7 +44,7 @@
  * reserved symbols (along with \ and /), otherwise illegal to store
  * in filenames in NTFS
  */
-#define UNI_ASTERIK     (__u16) ('*' + 0xF000)
+#define UNI_ASTERISK    (__u16) ('*' + 0xF000)
 #define UNI_QUESTION    (__u16) ('?' + 0xF000)
 #define UNI_COLON       (__u16) (':' + 0xF000)
 #define UNI_GRTRTHAN    (__u16) ('>' + 0xF000)
diff -druN linux-libre-2.6.38-gnu/fs/cifs/connect.c linux-libre-2.6.38.8-gnu/fs/cifs/connect.c
--- linux-libre-2.6.38-gnu/fs/cifs/connect.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/connect.c	2011-06-02 21:35:11.000000000 -0400
@@ -275,7 +275,8 @@
 	char *data_area_of_target;
 	char *data_area_of_buf2;
 	int remaining;
-	__u16 byte_count, total_data_size, total_in_buf, total_in_buf2;
+	unsigned int byte_count, total_in_buf;
+	__u16 total_data_size, total_in_buf2;
 
 	total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
 
@@ -288,7 +289,7 @@
 	remaining = total_data_size - total_in_buf;
 
 	if (remaining < 0)
-		return -EINVAL;
+		return -EPROTO;
 
 	if (remaining == 0) /* nothing to do, ignore */
 		return 0;
@@ -309,20 +310,29 @@
 	data_area_of_target += total_in_buf;
 
 	/* copy second buffer into end of first buffer */
-	memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
 	total_in_buf += total_in_buf2;
+	/* is the result too big for the field? */
+	if (total_in_buf > USHRT_MAX)
+		return -EPROTO;
 	put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
+
+	/* fix up the BCC */
 	byte_count = get_bcc_le(pTargetSMB);
 	byte_count += total_in_buf2;
+	/* is the result too big for the field? */
+	if (byte_count > USHRT_MAX)
+		return -EPROTO;
 	put_bcc_le(byte_count, pTargetSMB);
 
 	byte_count = pTargetSMB->smb_buf_length;
 	byte_count += total_in_buf2;
-
-	/* BB also add check that we are not beyond maximum buffer size */
-
+	/* don't allow buffer to overflow */
+	if (byte_count > CIFSMaxBufSize)
+		return -ENOBUFS;
 	pTargetSMB->smb_buf_length = byte_count;
 
+	memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
+
 	if (remaining == total_in_buf2) {
 		cFYI(1, "found the last secondary response");
 		return 0; /* we are done */
@@ -608,59 +618,63 @@
 		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
 			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 
-			if ((mid_entry->mid == smb_buffer->Mid) &&
-			    (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
-			    (mid_entry->command == smb_buffer->Command)) {
-				if (length == 0 &&
-				   check2ndT2(smb_buffer, server->maxBuf) > 0) {
-					/* We have a multipart transact2 resp */
-					isMultiRsp = true;
-					if (mid_entry->resp_buf) {
-						/* merge response - fix up 1st*/
-						if (coalesce_t2(smb_buffer,
-							mid_entry->resp_buf)) {
-							mid_entry->multiRsp =
-								 true;
-							break;
-						} else {
-							/* all parts received */
-							mid_entry->multiEnd =
-								 true;
-							goto multi_t2_fnd;
-						}
+			if (mid_entry->mid != smb_buffer->Mid ||
+			    mid_entry->midState != MID_REQUEST_SUBMITTED ||
+			    mid_entry->command != smb_buffer->Command) {
+				mid_entry = NULL;
+				continue;
+			}
+
+			if (length == 0 &&
+			    check2ndT2(smb_buffer, server->maxBuf) > 0) {
+				/* We have a multipart transact2 resp */
+				isMultiRsp = true;
+				if (mid_entry->resp_buf) {
+					/* merge response - fix up 1st*/
+					length = coalesce_t2(smb_buffer,
+							mid_entry->resp_buf);
+					if (length > 0) {
+						length = 0;
+						mid_entry->multiRsp = true;
+						break;
 					} else {
-						if (!isLargeBuf) {
-							cERROR(1, "1st trans2 resp needs bigbuf");
-					/* BB maybe we can fix this up,  switch
-					   to already allocated large buffer? */
-						} else {
-							/* Have first buffer */
-							mid_entry->resp_buf =
-								 smb_buffer;
-							mid_entry->largeBuf =
-								 true;
-							bigbuf = NULL;
-						}
+						/* all parts received or
+						 * packet is malformed
+						 */
+						mid_entry->multiEnd = true;
+						goto multi_t2_fnd;
+					}
+				} else {
+					if (!isLargeBuf) {
+						/*
+						 * FIXME: switch to already
+						 *        allocated largebuf?
+						 */
+						cERROR(1, "1st trans2 resp "
+							  "needs bigbuf");
+					} else {
+						/* Have first buffer */
+						mid_entry->resp_buf =
+							 smb_buffer;
+						mid_entry->largeBuf = true;
+						bigbuf = NULL;
 					}
-					break;
 				}
-				mid_entry->resp_buf = smb_buffer;
-				mid_entry->largeBuf = isLargeBuf;
+				break;
+			}
+			mid_entry->resp_buf = smb_buffer;
+			mid_entry->largeBuf = isLargeBuf;
 multi_t2_fnd:
-				if (length == 0)
-					mid_entry->midState =
-							MID_RESPONSE_RECEIVED;
-				else
-					mid_entry->midState =
-							MID_RESPONSE_MALFORMED;
+			if (length == 0)
+				mid_entry->midState = MID_RESPONSE_RECEIVED;
+			else
+				mid_entry->midState = MID_RESPONSE_MALFORMED;
 #ifdef CONFIG_CIFS_STATS2
-				mid_entry->when_received = jiffies;
+			mid_entry->when_received = jiffies;
 #endif
-				list_del_init(&mid_entry->qhead);
-				mid_entry->callback(mid_entry);
-				break;
-			}
-			mid_entry = NULL;
+			list_del_init(&mid_entry->qhead);
+			mid_entry->callback(mid_entry);
+			break;
 		}
 		spin_unlock(&GlobalMid_Lock);
 
@@ -808,8 +822,7 @@
 cifs_parse_mount_options(char *options, const char *devname,
 			 struct smb_vol *vol)
 {
-	char *value;
-	char *data;
+	char *value, *data, *end;
 	unsigned int  temp_len, i, j;
 	char separator[2];
 	short int override_uid = -1;
@@ -852,6 +865,7 @@
 	if (!options)
 		return 1;
 
+	end = options + strlen(options);
 	if (strncmp(options, "sep=", 4) == 0) {
 		if (options[4] != 0) {
 			separator[0] = options[4];
@@ -916,6 +930,7 @@
 			the only illegal character in a password is null */
 
 			if ((value[temp_len] == 0) &&
+			    (value + temp_len < end) &&
 			    (value[temp_len+1] == separator[0])) {
 				/* reinsert comma */
 				value[temp_len] = separator[0];
@@ -2416,7 +2431,7 @@
 
 	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
 		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
-
+		cFYI(1, "unix caps which server supports %lld", cap);
 		/* check for reconnect case in which we do not
 		   want to change the mount behavior if we can avoid it */
 		if (vol_info == NULL) {
@@ -2434,6 +2449,9 @@
 			}
 		}
 
+		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
+			cERROR(1, "per-share encryption not supported yet");
+
 		cap &= CIFS_UNIX_CAP_MASK;
 		if (vol_info && vol_info->no_psx_acl)
 			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
@@ -2482,6 +2500,10 @@
 			cFYI(1, "very large read cap");
 		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
 			cFYI(1, "very large write cap");
+		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
+			cFYI(1, "transport encryption cap");
+		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
+			cFYI(1, "mandatory transport encryption cap");
 #endif /* CIFS_DEBUG2 */
 		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
 			if (vol_info == NULL) {
@@ -2642,6 +2664,11 @@
 			      0 /* not legacy */, cifs_sb->local_nls,
 			      cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+	if (rc == -EOPNOTSUPP || rc == -EINVAL)
+		rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
+				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+				  CIFS_MOUNT_MAP_SPECIAL_CHR);
 	kfree(pfile_info);
 	return rc;
 }
@@ -2795,20 +2822,26 @@
 		goto remote_path_check;
 	}
 
-	/* do not care if following two calls succeed - informational */
-	if (!tcon->ipc) {
-		CIFSSMBQFSDeviceInfo(xid, tcon);
-		CIFSSMBQFSAttributeInfo(xid, tcon);
-	}
-
 	/* tell server which Unix caps we support */
-	if (tcon->ses->capabilities & CAP_UNIX)
+	if (tcon->ses->capabilities & CAP_UNIX) {
 		/* reset of caps checks mount to see if unix extensions
 		   disabled for just this mount */
 		reset_cifs_unix_caps(xid, tcon, sb, volume_info);
-	else
+		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
+		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
+		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
+			rc = -EACCES;
+			goto mount_fail_check;
+		}
+	} else
 		tcon->unix_ext = 0; /* server does not support them */
 
+	/* do not care if following two calls succeed - informational */
+	if (!tcon->ipc) {
+		CIFSSMBQFSDeviceInfo(xid, tcon);
+		CIFSSMBQFSAttributeInfo(xid, tcon);
+	}
+
 	/* convert forward to back slashes in prepath here if needed */
 	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
 		convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
@@ -2826,7 +2859,7 @@
 
 remote_path_check:
 	/* check if a whole path (including prepath) is not remote */
-	if (!rc && cifs_sb->prepathlen && tcon) {
+	if (!rc && tcon) {
 		/* build_path_to_root works only when we have a valid tcon */
 		full_path = cifs_build_path_to_root(cifs_sb, tcon);
 		if (full_path == NULL) {
diff -druN linux-libre-2.6.38-gnu/fs/cifs/file.c linux-libre-2.6.38.8-gnu/fs/cifs/file.c
--- linux-libre-2.6.38-gnu/fs/cifs/file.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/file.c	2011-06-02 21:35:11.000000000 -0400
@@ -575,8 +575,10 @@
 
 int cifs_close(struct inode *inode, struct file *file)
 {
-	cifsFileInfo_put(file->private_data);
-	file->private_data = NULL;
+	if (file->private_data != NULL) {
+		cifsFileInfo_put(file->private_data);
+		file->private_data = NULL;
+	}
 
 	/* return code from the ->release op is always ignored */
 	return 0;
diff -druN linux-libre-2.6.38-gnu/fs/cifs/sess.c linux-libre-2.6.38.8-gnu/fs/cifs/sess.c
--- linux-libre-2.6.38-gnu/fs/cifs/sess.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/cifs/sess.c	2011-06-02 21:35:11.000000000 -0400
@@ -277,7 +277,7 @@
 }
 
 static void
-decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses,
+decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
 		      const struct nls_table *nls_cp)
 {
 	int len;
@@ -285,19 +285,6 @@
 
 	cFYI(1, "bleft %d", bleft);
 
-	/*
-	 * Windows servers do not always double null terminate their final
-	 * Unicode string. Check to see if there are an uneven number of bytes
-	 * left. If so, then add an extra NULL pad byte to the end of the
-	 * response.
-	 *
-	 * See section 2.7.2 in "Implementing CIFS" for details
-	 */
-	if (bleft % 2) {
-		data[bleft] = 0;
-		++bleft;
-	}
-
 	kfree(ses->serverOS);
 	ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
 	cFYI(1, "serverOS=%s", ses->serverOS);
@@ -930,7 +917,9 @@
 	}
 
 	/* BB check if Unicode and decode strings */
-	if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+	if (bytes_remaining == 0) {
+		/* no string area to decode, do nothing */
+	} else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
 		/* unicode string area must be word-aligned */
 		if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
 			++bcc_ptr;
diff -druN linux-libre-2.6.38-gnu/fs/dcache.c linux-libre-2.6.38.8-gnu/fs/dcache.c
--- linux-libre-2.6.38-gnu/fs/dcache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/dcache.c	2011-06-02 21:35:11.000000000 -0400
@@ -296,8 +296,12 @@
 	__releases(parent->d_lock)
 	__releases(dentry->d_inode->i_lock)
 {
-	dentry->d_parent = NULL;
 	list_del(&dentry->d_u.d_child);
+	/*
+	 * Inform try_to_ascend() that we are no longer attached to the
+	 * dentry tree
+	 */
+	dentry->d_flags |= DCACHE_DISCONNECTED;
 	if (parent)
 		spin_unlock(&parent->d_lock);
 	dentry_iput(dentry);
@@ -1012,6 +1016,35 @@
 }
 
 /*
+ * This tries to ascend one level of parenthood, but
+ * we can race with renaming, so we need to re-check
+ * the parenthood after dropping the lock and check
+ * that the sequence number still matches.
+ */
+static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq)
+{
+	struct dentry *new = old->d_parent;
+
+	rcu_read_lock();
+	spin_unlock(&old->d_lock);
+	spin_lock(&new->d_lock);
+
+	/*
+	 * might go back up the wrong parent if we have had a rename
+	 * or deletion
+	 */
+	if (new != old->d_parent ||
+		 (old->d_flags & DCACHE_DISCONNECTED) ||
+		 (!locked && read_seqretry(&rename_lock, seq))) {
+		spin_unlock(&new->d_lock);
+		new = NULL;
+	}
+	rcu_read_unlock();
+	return new;
+}
+
+
+/*
  * Search for at least 1 mount point in the dentry's subdirs.
  * We descend to the next level whenever the d_subdirs
  * list is non-empty and continue searching.
@@ -1066,24 +1099,10 @@
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			 (!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		struct dentry *child = this_parent;
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
@@ -1181,24 +1200,10 @@
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			(!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		struct dentry *child = this_parent;
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
@@ -1607,10 +1612,13 @@
 	__bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
 	spin_unlock(&tmp->d_lock);
 	spin_unlock(&inode->i_lock);
+	security_d_instantiate(tmp, inode);
 
 	return tmp;
 
  out_iput:
+	if (res && !IS_ERR(res))
+		security_d_instantiate(res, inode);
 	iput(inode);
 	return res;
 }
@@ -2942,28 +2950,14 @@
 		spin_unlock(&dentry->d_lock);
 	}
 	if (this_parent != root) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
+		struct dentry *child = this_parent;
 		if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
 			this_parent->d_flags |= DCACHE_GENOCIDE;
 			this_parent->d_count--;
 		}
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			 (!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
diff -druN linux-libre-2.6.38-gnu/fs/ecryptfs/keystore.c linux-libre-2.6.38.8-gnu/fs/ecryptfs/keystore.c
--- linux-libre-2.6.38-gnu/fs/ecryptfs/keystore.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ecryptfs/keystore.c	2011-06-02 21:35:11.000000000 -0400
@@ -492,8 +492,8 @@
 	struct mutex *tfm_mutex;
 	char *block_aligned_filename;
 	struct ecryptfs_auth_tok *auth_tok;
-	struct scatterlist src_sg;
-	struct scatterlist dst_sg;
+	struct scatterlist src_sg[2];
+	struct scatterlist dst_sg[2];
 	struct blkcipher_desc desc;
 	char iv[ECRYPTFS_MAX_IV_BYTES];
 	char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
@@ -709,23 +709,21 @@
 	memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
 	       filename_size);
 	rc = virt_to_scatterlist(s->block_aligned_filename,
-				 s->block_aligned_filename_size, &s->src_sg, 1);
-	if (rc != 1) {
+				 s->block_aligned_filename_size, s->src_sg, 2);
+	if (rc < 1) {
 		printk(KERN_ERR "%s: Internal error whilst attempting to "
-		       "convert filename memory to scatterlist; "
-		       "expected rc = 1; got rc = [%d]. "
+		       "convert filename memory to scatterlist; rc = [%d]. "
 		       "block_aligned_filename_size = [%zd]\n", __func__, rc,
 		       s->block_aligned_filename_size);
 		goto out_release_free_unlock;
 	}
 	rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
-				 &s->dst_sg, 1);
-	if (rc != 1) {
+				 s->dst_sg, 2);
+	if (rc < 1) {
 		printk(KERN_ERR "%s: Internal error whilst attempting to "
 		       "convert encrypted filename memory to scatterlist; "
-		       "expected rc = 1; got rc = [%d]. "
-		       "block_aligned_filename_size = [%zd]\n", __func__, rc,
-		       s->block_aligned_filename_size);
+		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+		       __func__, rc, s->block_aligned_filename_size);
 		goto out_release_free_unlock;
 	}
 	/* The characters in the first block effectively do the job
@@ -748,7 +746,7 @@
 		       mount_crypt_stat->global_default_fn_cipher_key_bytes);
 		goto out_release_free_unlock;
 	}
-	rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+	rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg,
 					 s->block_aligned_filename_size);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to encrypt filename; "
@@ -782,8 +780,8 @@
 	struct mutex *tfm_mutex;
 	char *decrypted_filename;
 	struct ecryptfs_auth_tok *auth_tok;
-	struct scatterlist src_sg;
-	struct scatterlist dst_sg;
+	struct scatterlist src_sg[2];
+	struct scatterlist dst_sg[2];
 	struct blkcipher_desc desc;
 	char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
 	char iv[ECRYPTFS_MAX_IV_BYTES];
@@ -890,13 +888,12 @@
 	}
 	mutex_lock(s->tfm_mutex);
 	rc = virt_to_scatterlist(&data[(*packet_size)],
-				 s->block_aligned_filename_size, &s->src_sg, 1);
-	if (rc != 1) {
+				 s->block_aligned_filename_size, s->src_sg, 2);
+	if (rc < 1) {
 		printk(KERN_ERR "%s: Internal error whilst attempting to "
 		       "convert encrypted filename memory to scatterlist; "
-		       "expected rc = 1; got rc = [%d]. "
-		       "block_aligned_filename_size = [%zd]\n", __func__, rc,
-		       s->block_aligned_filename_size);
+		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+		       __func__, rc, s->block_aligned_filename_size);
 		goto out_unlock;
 	}
 	(*packet_size) += s->block_aligned_filename_size;
@@ -910,13 +907,12 @@
 		goto out_unlock;
 	}
 	rc = virt_to_scatterlist(s->decrypted_filename,
-				 s->block_aligned_filename_size, &s->dst_sg, 1);
-	if (rc != 1) {
+				 s->block_aligned_filename_size, s->dst_sg, 2);
+	if (rc < 1) {
 		printk(KERN_ERR "%s: Internal error whilst attempting to "
 		       "convert decrypted filename memory to scatterlist; "
-		       "expected rc = 1; got rc = [%d]. "
-		       "block_aligned_filename_size = [%zd]\n", __func__, rc,
-		       s->block_aligned_filename_size);
+		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
+		       __func__, rc, s->block_aligned_filename_size);
 		goto out_free_unlock;
 	}
 	/* The characters in the first block effectively do the job of
@@ -956,7 +952,7 @@
 		       mount_crypt_stat->global_default_fn_cipher_key_bytes);
 		goto out_free_unlock;
 	}
-	rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+	rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg,
 					 s->block_aligned_filename_size);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to decrypt filename; "
@@ -1563,6 +1559,7 @@
 		printk(KERN_ERR "Could not find key with description: [%s]\n",
 		       sig);
 		rc = process_request_key_err(PTR_ERR(*auth_tok_key));
+		(*auth_tok_key) = NULL;
 		goto out;
 	}
 	(*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
diff -druN linux-libre-2.6.38-gnu/fs/ecryptfs/mmap.c linux-libre-2.6.38.8-gnu/fs/ecryptfs/mmap.c
--- linux-libre-2.6.38-gnu/fs/ecryptfs/mmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ecryptfs/mmap.c	2011-06-02 21:35:11.000000000 -0400
@@ -374,6 +374,11 @@
 	    && (pos != 0))
 		zero_user(page, 0, PAGE_CACHE_SIZE);
 out:
+	if (unlikely(rc)) {
+		unlock_page(page);
+		page_cache_release(page);
+		*pagep = NULL;
+	}
 	return rc;
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/ext3/namei.c linux-libre-2.6.38.8-gnu/fs/ext3/namei.c
--- linux-libre-2.6.38-gnu/fs/ext3/namei.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext3/namei.c	2011-06-02 21:35:11.000000000 -0400
@@ -1416,10 +1416,19 @@
 	frame->at = entries;
 	frame->bh = bh;
 	bh = bh2;
+	/*
+	 * Mark buffers dirty here so that if do_split() fails we write a
+	 * consistent set of buffers to disk.
+	 */
+	ext3_journal_dirty_metadata(handle, frame->bh);
+	ext3_journal_dirty_metadata(handle, bh);
 	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-	dx_release (frames);
-	if (!(de))
+	if (!de) {
+		ext3_mark_inode_dirty(handle, dir);
+		dx_release(frames);
 		return retval;
+	}
+	dx_release(frames);
 
 	return add_dirent_to_buf(handle, dentry, inode, de, bh);
 }
@@ -1540,8 +1549,8 @@
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
 		entries2 = node2->entries;
+		memset(&node2->fake, 0, sizeof(struct fake_dirent));
 		node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
-		node2->fake.inode = 0;
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext3_journal_get_write_access(handle, frame->bh);
 		if (err)
diff -druN linux-libre-2.6.38-gnu/fs/ext3/super.c linux-libre-2.6.38.8-gnu/fs/ext3/super.c
--- linux-libre-2.6.38-gnu/fs/ext3/super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext3/super.c	2011-06-02 21:35:11.000000000 -0400
@@ -1464,6 +1464,13 @@
 		return;
 	}
 
+	/* Check if feature set allows readwrite operations */
+	if (EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) {
+		ext3_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
+			 "unknown ROCOMPAT features");
+		return;
+	}
+
 	if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
 		if (es->s_last_orphan)
 			jbd_debug(1, "Errors on filesystem, "
diff -druN linux-libre-2.6.38-gnu/fs/ext4/ext4.h linux-libre-2.6.38.8-gnu/fs/ext4/ext4.h
--- linux-libre-2.6.38-gnu/fs/ext4/ext4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext4/ext4.h	2011-06-02 21:35:11.000000000 -0400
@@ -1590,12 +1590,8 @@
  */
 struct ext4_lazy_init {
 	unsigned long		li_state;
-
-	wait_queue_head_t	li_wait_daemon;
 	wait_queue_head_t	li_wait_task;
-	struct timer_list	li_timer;
 	struct task_struct	*li_task;
-
 	struct list_head	li_request_list;
 	struct mutex		li_list_mtx;
 };
diff -druN linux-libre-2.6.38-gnu/fs/ext4/inode.c linux-libre-2.6.38.8-gnu/fs/ext4/inode.c
--- linux-libre-2.6.38-gnu/fs/ext4/inode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext4/inode.c	2011-06-02 21:35:11.000000000 -0400
@@ -5460,13 +5460,12 @@
 	/* if nrblocks are contiguous */
 	if (chunk) {
 		/*
-		 * With N contiguous data blocks, it need at most
-		 * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
-		 * 2 dindirect blocks
-		 * 1 tindirect block
+		 * With N contiguous data blocks, we need at most
+		 * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
+		 * 2 dindirect blocks, and 1 tindirect block
 		 */
-		indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
-		return indirects + 3;
+		return DIV_ROUND_UP(nrblocks,
+				    EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
 	}
 	/*
 	 * if nrblocks are not contiguous, worse case, each block touch
diff -druN linux-libre-2.6.38-gnu/fs/ext4/mballoc.c linux-libre-2.6.38.8-gnu/fs/ext4/mballoc.c
--- linux-libre-2.6.38-gnu/fs/ext4/mballoc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext4/mballoc.c	2011-06-02 21:35:11.000000000 -0400
@@ -1268,6 +1268,8 @@
 	return 0;
 
 err:
+	if (page)
+		page_cache_release(page);
 	if (e4b->bd_bitmap_page)
 		page_cache_release(e4b->bd_bitmap_page);
 	if (e4b->bd_buddy_page)
diff -druN linux-libre-2.6.38-gnu/fs/ext4/super.c linux-libre-2.6.38.8-gnu/fs/ext4/super.c
--- linux-libre-2.6.38-gnu/fs/ext4/super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ext4/super.c	2011-06-02 21:35:11.000000000 -0400
@@ -75,6 +75,7 @@
 static int ext4_freeze(struct super_block *sb);
 static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
 		       const char *dev_name, void *data);
+static int ext4_feature_set_ok(struct super_block *sb, int readonly);
 static void ext4_destroy_lazyinit_thread(void);
 static void ext4_unregister_li_request(struct super_block *sb);
 static void ext4_clear_request_list(void);
@@ -2120,6 +2121,13 @@
 		return;
 	}
 
+	/* Check if feature set would not allow a r/w mount */
+	if (!ext4_feature_set_ok(sb, 0)) {
+		ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
+			 "unknown ROCOMPAT features");
+		return;
+	}
+
 	if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
 		if (es->s_last_orphan)
 			jbd_debug(1, "Errors on filesystem, "
@@ -2637,12 +2645,6 @@
 	mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);  /* Once a day */
 }
 
-static void ext4_lazyinode_timeout(unsigned long data)
-{
-	struct task_struct *p = (struct task_struct *)data;
-	wake_up_process(p);
-}
-
 /* Find next suitable group and run ext4_init_inode_table */
 static int ext4_run_li_request(struct ext4_li_request *elr)
 {
@@ -2690,7 +2692,7 @@
 
 /*
  * Remove lr_request from the list_request and free the
- * request tructure. Should be called with li_list_mtx held
+ * request structure. Should be called with li_list_mtx held
  */
 static void ext4_remove_li_request(struct ext4_li_request *elr)
 {
@@ -2708,14 +2710,16 @@
 
 static void ext4_unregister_li_request(struct super_block *sb)
 {
-	struct ext4_li_request *elr = EXT4_SB(sb)->s_li_request;
-
-	if (!ext4_li_info)
+	mutex_lock(&ext4_li_mtx);
+	if (!ext4_li_info) {
+		mutex_unlock(&ext4_li_mtx);
 		return;
+	}
 
 	mutex_lock(&ext4_li_info->li_list_mtx);
-	ext4_remove_li_request(elr);
+	ext4_remove_li_request(EXT4_SB(sb)->s_li_request);
 	mutex_unlock(&ext4_li_info->li_list_mtx);
+	mutex_unlock(&ext4_li_mtx);
 }
 
 static struct task_struct *ext4_lazyinit_task;
@@ -2734,14 +2738,10 @@
 	struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg;
 	struct list_head *pos, *n;
 	struct ext4_li_request *elr;
-	unsigned long next_wakeup;
-	DEFINE_WAIT(wait);
+	unsigned long next_wakeup, cur;
 
 	BUG_ON(NULL == eli);
 
-	eli->li_timer.data = (unsigned long)current;
-	eli->li_timer.function = ext4_lazyinode_timeout;
-
 	eli->li_task = current;
 	wake_up(&eli->li_wait_task);
 
@@ -2775,19 +2775,15 @@
 		if (freezing(current))
 			refrigerator();
 
-		if ((time_after_eq(jiffies, next_wakeup)) ||
+		cur = jiffies;
+		if ((time_after_eq(cur, next_wakeup)) ||
 		    (MAX_JIFFY_OFFSET == next_wakeup)) {
 			cond_resched();
 			continue;
 		}
 
-		eli->li_timer.expires = next_wakeup;
-		add_timer(&eli->li_timer);
-		prepare_to_wait(&eli->li_wait_daemon, &wait,
-				TASK_INTERRUPTIBLE);
-		if (time_before(jiffies, next_wakeup))
-			schedule();
-		finish_wait(&eli->li_wait_daemon, &wait);
+		schedule_timeout_interruptible(next_wakeup - cur);
+
 		if (kthread_should_stop()) {
 			ext4_clear_request_list();
 			goto exit_thread;
@@ -2811,12 +2807,10 @@
 		goto cont_thread;
 	}
 	mutex_unlock(&eli->li_list_mtx);
-	del_timer_sync(&ext4_li_info->li_timer);
 	eli->li_task = NULL;
 	wake_up(&eli->li_wait_task);
 
 	kfree(ext4_li_info);
-	ext4_lazyinit_task = NULL;
 	ext4_li_info = NULL;
 	mutex_unlock(&ext4_li_mtx);
 
@@ -2844,7 +2838,6 @@
 	if (IS_ERR(ext4_lazyinit_task)) {
 		int err = PTR_ERR(ext4_lazyinit_task);
 		ext4_clear_request_list();
-		del_timer_sync(&ext4_li_info->li_timer);
 		kfree(ext4_li_info);
 		ext4_li_info = NULL;
 		printk(KERN_CRIT "EXT4: error %d creating inode table "
@@ -2893,9 +2886,7 @@
 	INIT_LIST_HEAD(&eli->li_request_list);
 	mutex_init(&eli->li_list_mtx);
 
-	init_waitqueue_head(&eli->li_wait_daemon);
 	init_waitqueue_head(&eli->li_wait_task);
-	init_timer(&eli->li_timer);
 	eli->li_state |= EXT4_LAZYINIT_QUIT;
 
 	ext4_li_info = eli;
@@ -2970,6 +2961,12 @@
 	mutex_unlock(&ext4_li_info->li_list_mtx);
 
 	sbi->s_li_request = elr;
+	/*
+	 * set elr to NULL here since it has been inserted to
+	 * the request_list and the removal and free of it is
+	 * handled by ext4_clear_request_list from now on.
+	 */
+	elr = NULL;
 
 	if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) {
 		ret = ext4_run_lazyinit_thread();
diff -druN linux-libre-2.6.38-gnu/fs/file.c linux-libre-2.6.38.8-gnu/fs/file.c
--- linux-libre-2.6.38-gnu/fs/file.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/file.c	2011-06-02 21:35:11.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/mmzone.h>
 #include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -39,14 +40,17 @@
  */
 static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
-static inline void *alloc_fdmem(unsigned int size)
+static void *alloc_fdmem(unsigned int size)
 {
-	void *data;
-
-	data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
-	if (data != NULL)
-		return data;
-
+	/*
+	 * Very large allocations can stress page reclaim, so fall back to
+	 * vmalloc() if the allocation size will be considered "large" by the VM.
+	 */
+	if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+		void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
+		if (data != NULL)
+			return data;
+	}
 	return vmalloc(size);
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/jbd/commit.c linux-libre-2.6.38.8-gnu/fs/jbd/commit.c
--- linux-libre-2.6.38-gnu/fs/jbd/commit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/jbd/commit.c	2011-06-02 21:35:11.000000000 -0400
@@ -722,8 +722,13 @@
                    required. */
 		JBUFFER_TRACE(jh, "file as BJ_Forget");
 		journal_file_buffer(jh, commit_transaction, BJ_Forget);
-		/* Wake up any transactions which were waiting for this
-		   IO to complete */
+		/*
+		 * Wake up any transactions which were waiting for this
+		 * IO to complete. The barrier must be here so that changes
+		 * by journal_file_buffer() take effect before wake_up_bit()
+		 * does the waitqueue check.
+		 */
+		smp_mb();
 		wake_up_bit(&bh->b_state, BH_Unshadow);
 		JBUFFER_TRACE(jh, "brelse shadowed buffer");
 		__brelse(bh);
diff -druN linux-libre-2.6.38-gnu/fs/jbd/journal.c linux-libre-2.6.38.8-gnu/fs/jbd/journal.c
--- linux-libre-2.6.38-gnu/fs/jbd/journal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/jbd/journal.c	2011-06-02 21:35:11.000000000 -0400
@@ -437,9 +437,12 @@
 int __log_start_commit(journal_t *journal, tid_t target)
 {
 	/*
-	 * Are we already doing a recent enough commit?
+	 * The only transaction we can possibly wait upon is the
+	 * currently running transaction (if it exists).  Otherwise,
+	 * the target tid must be an old one.
 	 */
-	if (!tid_geq(journal->j_commit_request, target)) {
+	if (journal->j_running_transaction &&
+	    journal->j_running_transaction->t_tid == target) {
 		/*
 		 * We want a new commit: OK, mark the request and wakeup the
 		 * commit thread.  We do _not_ do the commit ourselves.
@@ -451,7 +454,14 @@
 			  journal->j_commit_sequence);
 		wake_up(&journal->j_wait_commit);
 		return 1;
-	}
+	} else if (!tid_geq(journal->j_commit_request, target))
+		/* This should never happen, but if it does, preserve
+		   the evidence before kjournald goes into a loop and
+		   increments j_commit_sequence beyond all recognition. */
+		WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
+		    journal->j_commit_request, journal->j_commit_sequence,
+		    target, journal->j_running_transaction ?
+		    journal->j_running_transaction->t_tid : 0);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/namei.c linux-libre-2.6.38.8-gnu/fs/namei.c
--- linux-libre-2.6.38-gnu/fs/namei.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/namei.c	2011-06-02 21:35:11.000000000 -0400
@@ -712,6 +712,7 @@
 		do {
 			seq = read_seqcount_begin(&fs->seq);
 			nd->root = fs->root;
+			nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
 		} while (read_seqcount_retry(&fs->seq, seq));
 	}
 }
diff -druN linux-libre-2.6.38-gnu/fs/namespace.c linux-libre-2.6.38.8-gnu/fs/namespace.c
--- linux-libre-2.6.38-gnu/fs/namespace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/namespace.c	2011-06-02 21:35:11.000000000 -0400
@@ -2469,9 +2469,6 @@
 	error = user_path_dir(new_root, &new);
 	if (error)
 		goto out0;
-	error = -EINVAL;
-	if (!check_mnt(new.mnt))
-		goto out1;
 
 	error = user_path_dir(put_old, &old);
 	if (error)
@@ -2491,7 +2488,7 @@
 		IS_MNT_SHARED(new.mnt->mnt_parent) ||
 		IS_MNT_SHARED(root.mnt->mnt_parent))
 		goto out2;
-	if (!check_mnt(root.mnt))
+	if (!check_mnt(root.mnt) || !check_mnt(new.mnt))
 		goto out2;
 	error = -ENOENT;
 	if (cant_mount(old.dentry))
@@ -2515,19 +2512,19 @@
 		goto out2; /* not attached */
 	/* make sure we can reach put_old from new_root */
 	tmp = old.mnt;
-	br_write_lock(vfsmount_lock);
 	if (tmp != new.mnt) {
 		for (;;) {
 			if (tmp->mnt_parent == tmp)
-				goto out3; /* already mounted on put_old */
+				goto out2; /* already mounted on put_old */
 			if (tmp->mnt_parent == new.mnt)
 				break;
 			tmp = tmp->mnt_parent;
 		}
 		if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
-			goto out3;
+			goto out2;
 	} else if (!is_subdir(old.dentry, new.dentry))
-		goto out3;
+		goto out2;
+	br_write_lock(vfsmount_lock);
 	detach_mnt(new.mnt, &parent_path);
 	detach_mnt(root.mnt, &root_parent);
 	/* mount old root on put_old */
@@ -2550,9 +2547,6 @@
 	path_put(&new);
 out0:
 	return error;
-out3:
-	br_write_unlock(vfsmount_lock);
-	goto out2;
 }
 
 static void __init init_mount_tree(void)
diff -druN linux-libre-2.6.38-gnu/fs/nfs/nfs4proc.c linux-libre-2.6.38.8-gnu/fs/nfs/nfs4proc.c
--- linux-libre-2.6.38-gnu/fs/nfs/nfs4proc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfs/nfs4proc.c	2011-06-02 21:35:11.000000000 -0400
@@ -258,9 +258,11 @@
 				break;
 			nfs4_schedule_stateid_recovery(server, state);
 			goto wait_on_recovery;
+		case -NFS4ERR_EXPIRED:
+			if (state != NULL)
+				nfs4_schedule_stateid_recovery(server, state);
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_STALE_CLIENTID:
-		case -NFS4ERR_EXPIRED:
 			nfs4_schedule_lease_recovery(clp);
 			goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
@@ -3504,9 +3506,11 @@
 				break;
 			nfs4_schedule_stateid_recovery(server, state);
 			goto wait_on_recovery;
+		case -NFS4ERR_EXPIRED:
+			if (state != NULL)
+				nfs4_schedule_stateid_recovery(server, state);
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_STALE_CLIENTID:
-		case -NFS4ERR_EXPIRED:
 			nfs4_schedule_lease_recovery(clp);
 			goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
@@ -4397,6 +4401,7 @@
 			case -ESTALE:
 				goto out;
 			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_stateid_recovery(server, state);
 			case -NFS4ERR_STALE_CLIENTID:
 			case -NFS4ERR_STALE_STATEID:
 				nfs4_schedule_lease_recovery(server->nfs_client);
diff -druN linux-libre-2.6.38-gnu/fs/nfs/nfs4state.c linux-libre-2.6.38.8-gnu/fs/nfs/nfs4state.c
--- linux-libre-2.6.38-gnu/fs/nfs/nfs4state.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfs/nfs4state.c	2011-06-02 21:35:11.000000000 -0400
@@ -1446,7 +1446,10 @@
 #ifdef CONFIG_NFS_V4_1
 void nfs4_schedule_session_recovery(struct nfs4_session *session)
 {
-	nfs4_schedule_lease_recovery(session->clp);
+	struct nfs_client *clp = session->clp;
+
+	set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+	nfs4_schedule_lease_recovery(clp);
 }
 
 void nfs41_handle_recall_slot(struct nfs_client *clp)
@@ -1528,6 +1531,7 @@
 		status = nfs4_recovery_handle_error(clp, status);
 		goto out;
 	}
+	clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
 	/* create_session negotiated new slot table */
 	clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
 
@@ -1600,7 +1604,7 @@
 	int status = 0;
 
 	/* Ensure exclusive access to NFSv4 state */
-	for(;;) {
+	do {
 		if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
 			/* We're going to have to re-establish a clientid */
 			status = nfs4_reclaim_lease(clp);
@@ -1684,7 +1688,7 @@
 			break;
 		if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
 			break;
-	}
+	} while (atomic_read(&clp->cl_count) > 1);
 	return;
 out_error:
 	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
diff -druN linux-libre-2.6.38-gnu/fs/nfs/super.c linux-libre-2.6.38.8-gnu/fs/nfs/super.c
--- linux-libre-2.6.38-gnu/fs/nfs/super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfs/super.c	2011-06-02 21:35:11.000000000 -0400
@@ -2077,6 +2077,15 @@
 	if (error < 0)
 		goto out;
 
+	/*
+	 * noac is a special case. It implies -o sync, but that's not
+	 * necessarily reflected in the mtab options. do_remount_sb
+	 * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the
+	 * remount options, so we have to explicitly reset it.
+	 */
+	if (data->flags & NFS_MOUNT_NOAC)
+		*flags |= MS_SYNCHRONOUS;
+
 	/* compare new mount options with old ones */
 	error = nfs_compare_remount_data(nfss, data);
 out:
diff -druN linux-libre-2.6.38-gnu/fs/nfs/write.c linux-libre-2.6.38.8-gnu/fs/nfs/write.c
--- linux-libre-2.6.38-gnu/fs/nfs/write.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfs/write.c	2011-06-02 21:35:11.000000000 -0400
@@ -1214,13 +1214,17 @@
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait)
 {
+	int ret;
+
 	if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags))
 		return 1;
-	if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags,
-				NFS_INO_COMMIT, nfs_wait_bit_killable,
-				TASK_KILLABLE))
-		return 1;
-	return 0;
+	if (!may_wait)
+		return 0;
+	ret = out_of_line_wait_on_bit_lock(&nfsi->flags,
+				NFS_INO_COMMIT,
+				nfs_wait_bit_killable,
+				TASK_KILLABLE);
+	return (ret < 0) ? ret : 1;
 }
 
 static void nfs_commit_clear_lock(struct nfs_inode *nfsi)
@@ -1396,9 +1400,10 @@
 {
 	LIST_HEAD(head);
 	int may_wait = how & FLUSH_SYNC;
-	int res = 0;
+	int res;
 
-	if (!nfs_commit_set_lock(NFS_I(inode), may_wait))
+	res = nfs_commit_set_lock(NFS_I(inode), may_wait);
+	if (res <= 0)
 		goto out_mark_dirty;
 	spin_lock(&inode->i_lock);
 	res = nfs_scan_commit(inode, &head, 0, 0);
@@ -1407,12 +1412,14 @@
 		int error = nfs_commit_list(inode, &head, how);
 		if (error < 0)
 			return error;
-		if (may_wait)
-			wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT,
-					nfs_wait_bit_killable,
-					TASK_KILLABLE);
-		else
+		if (!may_wait)
 			goto out_mark_dirty;
+		error = wait_on_bit(&NFS_I(inode)->flags,
+				NFS_INO_COMMIT,
+				nfs_wait_bit_killable,
+				TASK_KILLABLE);
+		if (error < 0)
+			return error;
 	} else
 		nfs_commit_clear_lock(NFS_I(inode));
 	return res;
diff -druN linux-libre-2.6.38-gnu/fs/nfsd/lockd.c linux-libre-2.6.38.8-gnu/fs/nfsd/lockd.c
--- linux-libre-2.6.38-gnu/fs/nfsd/lockd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfsd/lockd.c	2011-06-02 21:35:11.000000000 -0400
@@ -38,7 +38,6 @@
 	exp_readlock();
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
 	fh_put(&fh);
-	rqstp->rq_client = NULL;
 	exp_readunlock();
  	/* We return nlm error codes as nlm doesn't know
 	 * about nfsd, but nfsd does know about nlm..
diff -druN linux-libre-2.6.38-gnu/fs/nfsd/nfs4proc.c linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4proc.c
--- linux-libre-2.6.38-gnu/fs/nfsd/nfs4proc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4proc.c	2011-06-02 21:35:11.000000000 -0400
@@ -984,8 +984,8 @@
 			      void *);
 enum nfsd4_op_flags {
 	ALLOWED_WITHOUT_FH = 1 << 0,	/* No current filehandle required */
-	ALLOWED_ON_ABSENT_FS = 2 << 0,	/* ops processed on absent fs */
-	ALLOWED_AS_FIRST_OP = 3 << 0,	/* ops reqired first in compound */
+	ALLOWED_ON_ABSENT_FS = 1 << 1,	/* ops processed on absent fs */
+	ALLOWED_AS_FIRST_OP = 1 << 2,	/* ops reqired first in compound */
 };
 
 struct nfsd4_operation {
diff -druN linux-libre-2.6.38-gnu/fs/nfsd/nfs4state.c linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4state.c
--- linux-libre-2.6.38-gnu/fs/nfsd/nfs4state.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4state.c	2011-06-02 21:35:11.000000000 -0400
@@ -258,6 +258,7 @@
 	if (atomic_dec_and_test(&fp->fi_delegees)) {
 		vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
 		fp->fi_lease = NULL;
+		fput(fp->fi_deleg_file);
 		fp->fi_deleg_file = NULL;
 	}
 }
@@ -316,64 +317,6 @@
 static struct list_head client_lru;
 static struct list_head close_lru;
 
-static void unhash_generic_stateid(struct nfs4_stateid *stp)
-{
-	list_del(&stp->st_hash);
-	list_del(&stp->st_perfile);
-	list_del(&stp->st_perstateowner);
-}
-
-static void free_generic_stateid(struct nfs4_stateid *stp)
-{
-	put_nfs4_file(stp->st_file);
-	kmem_cache_free(stateid_slab, stp);
-}
-
-static void release_lock_stateid(struct nfs4_stateid *stp)
-{
-	struct file *file;
-
-	unhash_generic_stateid(stp);
-	file = find_any_file(stp->st_file);
-	if (file)
-		locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
-	free_generic_stateid(stp);
-}
-
-static void unhash_lockowner(struct nfs4_stateowner *sop)
-{
-	struct nfs4_stateid *stp;
-
-	list_del(&sop->so_idhash);
-	list_del(&sop->so_strhash);
-	list_del(&sop->so_perstateid);
-	while (!list_empty(&sop->so_stateids)) {
-		stp = list_first_entry(&sop->so_stateids,
-				struct nfs4_stateid, st_perstateowner);
-		release_lock_stateid(stp);
-	}
-}
-
-static void release_lockowner(struct nfs4_stateowner *sop)
-{
-	unhash_lockowner(sop);
-	nfs4_put_stateowner(sop);
-}
-
-static void
-release_stateid_lockowners(struct nfs4_stateid *open_stp)
-{
-	struct nfs4_stateowner *lock_sop;
-
-	while (!list_empty(&open_stp->st_lockowners)) {
-		lock_sop = list_entry(open_stp->st_lockowners.next,
-				struct nfs4_stateowner, so_perstateid);
-		/* list_del(&open_stp->st_lockowners);  */
-		BUG_ON(lock_sop->so_is_open_owner);
-		release_lockowner(lock_sop);
-	}
-}
-
 /*
  * We store the NONE, READ, WRITE, and BOTH bits separately in the
  * st_{access,deny}_bmap field of the stateid, in order to track not
@@ -446,13 +389,74 @@
 	return nfs4_access_to_omode(access);
 }
 
-static void release_open_stateid(struct nfs4_stateid *stp)
+static void unhash_generic_stateid(struct nfs4_stateid *stp)
 {
-	int oflag = nfs4_access_bmap_to_omode(stp);
+	list_del(&stp->st_hash);
+	list_del(&stp->st_perfile);
+	list_del(&stp->st_perstateowner);
+}
+
+static void free_generic_stateid(struct nfs4_stateid *stp)
+{
+	int oflag;
+
+	if (stp->st_access_bmap) {
+		oflag = nfs4_access_bmap_to_omode(stp);
+		nfs4_file_put_access(stp->st_file, oflag);
+	}
+	put_nfs4_file(stp->st_file);
+	kmem_cache_free(stateid_slab, stp);
+}
 
+static void release_lock_stateid(struct nfs4_stateid *stp)
+{
+	struct file *file;
+
+	unhash_generic_stateid(stp);
+	file = find_any_file(stp->st_file);
+	if (file)
+		locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
+	free_generic_stateid(stp);
+}
+
+static void unhash_lockowner(struct nfs4_stateowner *sop)
+{
+	struct nfs4_stateid *stp;
+
+	list_del(&sop->so_idhash);
+	list_del(&sop->so_strhash);
+	list_del(&sop->so_perstateid);
+	while (!list_empty(&sop->so_stateids)) {
+		stp = list_first_entry(&sop->so_stateids,
+				struct nfs4_stateid, st_perstateowner);
+		release_lock_stateid(stp);
+	}
+}
+
+static void release_lockowner(struct nfs4_stateowner *sop)
+{
+	unhash_lockowner(sop);
+	nfs4_put_stateowner(sop);
+}
+
+static void
+release_stateid_lockowners(struct nfs4_stateid *open_stp)
+{
+	struct nfs4_stateowner *lock_sop;
+
+	while (!list_empty(&open_stp->st_lockowners)) {
+		lock_sop = list_entry(open_stp->st_lockowners.next,
+				struct nfs4_stateowner, so_perstateid);
+		/* list_del(&open_stp->st_lockowners);  */
+		BUG_ON(lock_sop->so_is_open_owner);
+		release_lockowner(lock_sop);
+	}
+}
+
+static void release_open_stateid(struct nfs4_stateid *stp)
+{
 	unhash_generic_stateid(stp);
 	release_stateid_lockowners(stp);
-	nfs4_file_put_access(stp->st_file, oflag);
 	free_generic_stateid(stp);
 }
 
@@ -3735,6 +3739,7 @@
 	stp->st_stateid.si_stateownerid = sop->so_id;
 	stp->st_stateid.si_fileid = fp->fi_id;
 	stp->st_stateid.si_generation = 0;
+	stp->st_access_bmap = 0;
 	stp->st_deny_bmap = open_stp->st_deny_bmap;
 	stp->st_openstp = open_stp;
 
@@ -3749,6 +3754,17 @@
 	     LOFF_OVERFLOW(offset, length)));
 }
 
+static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access)
+{
+	struct nfs4_file *fp = lock_stp->st_file;
+	int oflag = nfs4_access_to_omode(access);
+
+	if (test_bit(access, &lock_stp->st_access_bmap))
+		return;
+	nfs4_file_get_access(fp, oflag);
+	__set_bit(access, &lock_stp->st_access_bmap);
+}
+
 /*
  *  LOCK operation 
  */
@@ -3765,7 +3781,6 @@
 	struct file_lock conflock;
 	__be32 status = 0;
 	unsigned int strhashval;
-	unsigned int cmd;
 	int err;
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -3847,22 +3862,18 @@
 	switch (lock->lk_type) {
 		case NFS4_READ_LT:
 		case NFS4_READW_LT:
-			if (find_readable_file(lock_stp->st_file)) {
-				nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ);
-				filp = find_readable_file(lock_stp->st_file);
-			}
+			filp = find_readable_file(lock_stp->st_file);
+			if (filp)
+				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
 			file_lock.fl_type = F_RDLCK;
-			cmd = F_SETLK;
-		break;
+			break;
 		case NFS4_WRITE_LT:
 		case NFS4_WRITEW_LT:
-			if (find_writeable_file(lock_stp->st_file)) {
-				nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE);
-				filp = find_writeable_file(lock_stp->st_file);
-			}
+			filp = find_writeable_file(lock_stp->st_file);
+			if (filp)
+				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
 			file_lock.fl_type = F_WRLCK;
-			cmd = F_SETLK;
-		break;
+			break;
 		default:
 			status = nfserr_inval;
 		goto out;
@@ -3886,7 +3897,7 @@
 	* Note: locks.c uses the BKL to protect the inode's lock list.
 	*/
 
-	err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
+	err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
 	switch (-err) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);
diff -druN linux-libre-2.6.38-gnu/fs/nfsd/nfs4xdr.c linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4xdr.c
--- linux-libre-2.6.38-gnu/fs/nfsd/nfs4xdr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfsd/nfs4xdr.c	2011-06-02 21:35:11.000000000 -0400
@@ -1142,7 +1142,7 @@
 
 	u32 dummy;
 	char *machine_name;
-	int i, j;
+	int i;
 	int nr_secflavs;
 
 	READ_BUF(16);
@@ -1215,8 +1215,6 @@
 			READ_BUF(4);
 			READ32(dummy);
 			READ_BUF(dummy * 4);
-			for (j = 0; j < dummy; ++j)
-				READ32(dummy);
 			break;
 		case RPC_AUTH_GSS:
 			dprintk("RPC_AUTH_GSS callback secflavor "
@@ -1232,7 +1230,6 @@
 			READ_BUF(4);
 			READ32(dummy);
 			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
 			break;
 		default:
 			dprintk("Illegal callback secflavor\n");
diff -druN linux-libre-2.6.38-gnu/fs/nfsd/vfs.c linux-libre-2.6.38.8-gnu/fs/nfsd/vfs.c
--- linux-libre-2.6.38-gnu/fs/nfsd/vfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nfsd/vfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -1363,7 +1363,7 @@
 		goto out;
 	if (!(iap->ia_valid & ATTR_MODE))
 		iap->ia_mode = 0;
-	err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+	err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
 	if (err)
 		goto out;
 
@@ -1385,6 +1385,13 @@
 	if (IS_ERR(dchild))
 		goto out_nfserr;
 
+	/* If file doesn't exist, check for permissions to create one */
+	if (!dchild->d_inode) {
+		err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+		if (err)
+			goto out;
+	}
+
 	err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
 	if (err)
 		goto out;
diff -druN linux-libre-2.6.38-gnu/fs/nilfs2/file.c linux-libre-2.6.38.8-gnu/fs/nilfs2/file.c
--- linux-libre-2.6.38-gnu/fs/nilfs2/file.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/nilfs2/file.c	2011-06-02 21:35:11.000000000 -0400
@@ -72,10 +72,9 @@
 	/*
 	 * check to see if the page is mapped already (no holes)
 	 */
-	if (PageMappedToDisk(page)) {
-		unlock_page(page);
+	if (PageMappedToDisk(page))
 		goto mapped;
-	}
+
 	if (page_has_buffers(page)) {
 		struct buffer_head *bh, *head;
 		int fully_mapped = 1;
@@ -90,7 +89,6 @@
 
 		if (fully_mapped) {
 			SetPageMappedToDisk(page);
-			unlock_page(page);
 			goto mapped;
 		}
 	}
@@ -105,16 +103,17 @@
 		return VM_FAULT_SIGBUS;
 
 	ret = block_page_mkwrite(vma, vmf, nilfs_get_block);
-	if (unlikely(ret)) {
+	if (ret != VM_FAULT_LOCKED) {
 		nilfs_transaction_abort(inode->i_sb);
 		return ret;
 	}
+	nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits));
 	nilfs_transaction_commit(inode->i_sb);
 
  mapped:
 	SetPageChecked(page);
 	wait_on_page_writeback(page);
-	return 0;
+	return VM_FAULT_LOCKED;
 }
 
 static const struct vm_operations_struct nilfs_file_vm_ops = {
diff -druN linux-libre-2.6.38-gnu/fs/notify/inotify/inotify_fsnotify.c linux-libre-2.6.38.8-gnu/fs/notify/inotify/inotify_fsnotify.c
--- linux-libre-2.6.38-gnu/fs/notify/inotify/inotify_fsnotify.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/notify/inotify/inotify_fsnotify.c	2011-06-02 21:35:11.000000000 -0400
@@ -198,6 +198,7 @@
 	idr_for_each(&group->inotify_data.idr, idr_callback, group);
 	idr_remove_all(&group->inotify_data.idr);
 	idr_destroy(&group->inotify_data.idr);
+	atomic_dec(&group->inotify_data.user->inotify_devs);
 	free_uid(group->inotify_data.user);
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/notify/inotify/inotify_user.c linux-libre-2.6.38.8-gnu/fs/notify/inotify/inotify_user.c
--- linux-libre-2.6.38-gnu/fs/notify/inotify/inotify_user.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/notify/inotify/inotify_user.c	2011-06-02 21:35:11.000000000 -0400
@@ -290,7 +290,6 @@
 static int inotify_release(struct inode *ignored, struct file *file)
 {
 	struct fsnotify_group *group = file->private_data;
-	struct user_struct *user = group->inotify_data.user;
 
 	pr_debug("%s: group=%p\n", __func__, group);
 
@@ -299,8 +298,6 @@
 	/* free this group, matching get was inotify_init->fsnotify_obtain_group */
 	fsnotify_put_group(group);
 
-	atomic_dec(&user->inotify_devs);
-
 	return 0;
 }
 
@@ -697,7 +694,7 @@
 	return ret;
 }
 
-static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsigned int max_events)
+static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 {
 	struct fsnotify_group *group;
 
@@ -710,8 +707,14 @@
 	spin_lock_init(&group->inotify_data.idr_lock);
 	idr_init(&group->inotify_data.idr);
 	group->inotify_data.last_wd = 0;
-	group->inotify_data.user = user;
 	group->inotify_data.fa = NULL;
+	group->inotify_data.user = get_current_user();
+
+	if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
+	    inotify_max_user_instances) {
+		fsnotify_put_group(group);
+		return ERR_PTR(-EMFILE);
+	}
 
 	return group;
 }
@@ -721,7 +724,6 @@
 SYSCALL_DEFINE1(inotify_init1, int, flags)
 {
 	struct fsnotify_group *group;
-	struct user_struct *user;
 	int ret;
 
 	/* Check the IN_* constants for consistency.  */
@@ -731,31 +733,16 @@
 	if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
 		return -EINVAL;
 
-	user = get_current_user();
-	if (unlikely(atomic_read(&user->inotify_devs) >=
-			inotify_max_user_instances)) {
-		ret = -EMFILE;
-		goto out_free_uid;
-	}
-
 	/* fsnotify_obtain_group took a reference to group, we put this when we kill the file in the end */
-	group = inotify_new_group(user, inotify_max_queued_events);
-	if (IS_ERR(group)) {
-		ret = PTR_ERR(group);
-		goto out_free_uid;
-	}
-
-	atomic_inc(&user->inotify_devs);
+	group = inotify_new_group(inotify_max_queued_events);
+	if (IS_ERR(group))
+		return PTR_ERR(group);
 
 	ret = anon_inode_getfd("inotify", &inotify_fops, group,
 				  O_RDONLY | flags);
-	if (ret >= 0)
-		return ret;
+	if (ret < 0)
+		fsnotify_put_group(group);
 
-	fsnotify_put_group(group);
-	atomic_dec(&user->inotify_devs);
-out_free_uid:
-	free_uid(user);
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/ocfs2/aops.c linux-libre-2.6.38.8-gnu/fs/ocfs2/aops.c
--- linux-libre-2.6.38-gnu/fs/ocfs2/aops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ocfs2/aops.c	2011-06-02 21:35:11.000000000 -0400
@@ -1026,6 +1026,12 @@
 	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
 					&cluster_start, &cluster_end);
 
+	/* treat the write as new if the a hole/lseek spanned across
+	 * the page boundary.
+	 */
+	new = new | ((i_size_read(inode) <= page_offset(page)) &&
+			(page_offset(page) <= user_pos));
+
 	if (page == wc->w_target_page) {
 		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
 		map_to = map_from + user_len;
diff -druN linux-libre-2.6.38-gnu/fs/partitions/efi.c linux-libre-2.6.38.8-gnu/fs/partitions/efi.c
--- linux-libre-2.6.38-gnu/fs/partitions/efi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/partitions/efi.c	2011-06-02 21:35:11.000000000 -0400
@@ -348,6 +348,12 @@
 		goto fail;
 	}
 
+	/* Check that sizeof_partition_entry has the correct value */
+	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
+		pr_debug("GUID Partitition Entry Size check failed.\n");
+		goto fail;
+	}
+
 	if (!(*ptes = alloc_read_gpt_entries(state, *gpt)))
 		goto fail;
 
diff -druN linux-libre-2.6.38-gnu/fs/partitions/ldm.c linux-libre-2.6.38.8-gnu/fs/partitions/ldm.c
--- linux-libre-2.6.38-gnu/fs/partitions/ldm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/partitions/ldm.c	2011-06-02 21:35:11.000000000 -0400
@@ -1299,6 +1299,11 @@
 
 	BUG_ON (!data || !frags);
 
+	if (size < 2 * VBLK_SIZE_HEAD) {
+		ldm_error("Value of size is to small.");
+		return false;
+	}
+
 	group = get_unaligned_be32(data + 0x08);
 	rec   = get_unaligned_be16(data + 0x0C);
 	num   = get_unaligned_be16(data + 0x0E);
@@ -1306,6 +1311,10 @@
 		ldm_error ("A VBLK claims to have %d parts.", num);
 		return false;
 	}
+	if (rec >= num) {
+		ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num);
+		return false;
+	}
 
 	list_for_each (item, frags) {
 		f = list_entry (item, struct frag, list);
@@ -1326,6 +1335,11 @@
 
 	list_add_tail (&f->list, frags);
 found:
+	if (rec >= f->num) {
+		ldm_error("REC value (%d) exceeds NUM value (%d)", rec, f->num);
+		return false;
+	}
+
 	if (f->map & (1 << rec)) {
 		ldm_error ("Duplicate VBLK, part %d.", rec);
 		f->map &= 0x7F;			/* Mark the group as broken */
@@ -1334,10 +1348,9 @@
 
 	f->map |= (1 << rec);
 
-	if (num > 0) {
-		data += VBLK_SIZE_HEAD;
-		size -= VBLK_SIZE_HEAD;
-	}
+	data += VBLK_SIZE_HEAD;
+	size -= VBLK_SIZE_HEAD;
+
 	memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
 
 	return true;
diff -druN linux-libre-2.6.38-gnu/fs/partitions/osf.c linux-libre-2.6.38.8-gnu/fs/partitions/osf.c
--- linux-libre-2.6.38-gnu/fs/partitions/osf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/partitions/osf.c	2011-06-02 21:35:11.000000000 -0400
@@ -10,7 +10,7 @@
 #include "check.h"
 #include "osf.h"
 
-#define MAX_OSF_PARTITIONS 8
+#define MAX_OSF_PARTITIONS 18
 
 int osf_partition(struct parsed_partitions *state)
 {
diff -druN linux-libre-2.6.38-gnu/fs/proc/array.c linux-libre-2.6.38.8-gnu/fs/proc/array.c
--- linux-libre-2.6.38-gnu/fs/proc/array.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/proc/array.c	2011-06-02 21:35:11.000000000 -0400
@@ -489,8 +489,8 @@
 		vsize,
 		mm ? get_mm_rss(mm) : 0,
 		rsslim,
-		mm ? mm->start_code : 0,
-		mm ? mm->end_code : 0,
+		mm ? (permitted ? mm->start_code : 1) : 0,
+		mm ? (permitted ? mm->end_code : 1) : 0,
 		(permitted && mm) ? mm->start_stack : 0,
 		esp,
 		eip,
diff -druN linux-libre-2.6.38-gnu/fs/proc/base.c linux-libre-2.6.38.8-gnu/fs/proc/base.c
--- linux-libre-2.6.38-gnu/fs/proc/base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/proc/base.c	2011-06-02 21:35:11.000000000 -0400
@@ -3066,11 +3066,16 @@
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-	struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
+	unsigned int nr;
+	struct task_struct *reaper;
 	struct tgid_iter iter;
 	struct pid_namespace *ns;
 
+	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+		goto out_no_task;
+	nr = filp->f_pos - FIRST_PROCESS_ENTRY;
+
+	reaper = get_proc_task(filp->f_path.dentry->d_inode);
 	if (!reaper)
 		goto out_no_task;
 
diff -druN linux-libre-2.6.38-gnu/fs/proc/task_mmu.c linux-libre-2.6.38.8-gnu/fs/proc/task_mmu.c
--- linux-libre-2.6.38-gnu/fs/proc/task_mmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/proc/task_mmu.c	2011-06-02 21:35:11.000000000 -0400
@@ -211,7 +211,7 @@
 	int flags = vma->vm_flags;
 	unsigned long ino = 0;
 	unsigned long long pgoff = 0;
-	unsigned long start;
+	unsigned long start, end;
 	dev_t dev = 0;
 	int len;
 
@@ -224,13 +224,15 @@
 
 	/* We don't show the stack guard page in /proc/maps */
 	start = vma->vm_start;
-	if (vma->vm_flags & VM_GROWSDOWN)
-		if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
-			start += PAGE_SIZE;
+	if (stack_guard_page_start(vma, start))
+		start += PAGE_SIZE;
+	end = vma->vm_end;
+	if (stack_guard_page_end(vma, end))
+		end -= PAGE_SIZE;
 
 	seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
 			start,
-			vma->vm_end,
+			end,
 			flags & VM_READ ? 'r' : '-',
 			flags & VM_WRITE ? 'w' : '-',
 			flags & VM_EXEC ? 'x' : '-',
@@ -249,8 +251,8 @@
 		const char *name = arch_vma_name(vma);
 		if (!name) {
 			if (mm) {
-				if (vma->vm_start <= mm->start_brk &&
-						vma->vm_end >= mm->brk) {
+				if (vma->vm_start <= mm->brk &&
+						vma->vm_end >= mm->start_brk) {
 					name = "[heap]";
 				} else if (vma->vm_start <= mm->start_stack &&
 					   vma->vm_end >= mm->start_stack) {
diff -druN linux-libre-2.6.38-gnu/fs/quota/dquot.c linux-libre-2.6.38.8-gnu/fs/quota/dquot.c
--- linux-libre-2.6.38-gnu/fs/quota/dquot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/quota/dquot.c	2011-06-02 21:35:11.000000000 -0400
@@ -442,7 +442,7 @@
  */
 int dquot_commit(struct dquot *dquot)
 {
-	int ret = 0, ret2 = 0;
+	int ret = 0;
 	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
 	mutex_lock(&dqopt->dqio_mutex);
@@ -454,15 +454,10 @@
 	spin_unlock(&dq_list_lock);
 	/* Inactive dquot can be only if there was error during read/init
 	 * => we have better not writing it */
-	if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+	if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
 		ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
-		if (info_dirty(&dqopt->info[dquot->dq_type])) {
-			ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
-						dquot->dq_sb, dquot->dq_type);
-		}
-		if (ret >= 0)
-			ret = ret2;
-	}
+	else
+		ret = -EIO;
 out_sem:
 	mutex_unlock(&dqopt->dqio_mutex);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/fs/ramfs/file-nommu.c linux-libre-2.6.38.8-gnu/fs/ramfs/file-nommu.c
--- linux-libre-2.6.38-gnu/fs/ramfs/file-nommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ramfs/file-nommu.c	2011-06-02 21:35:11.000000000 -0400
@@ -112,6 +112,7 @@
 		SetPageDirty(page);
 
 		unlock_page(page);
+		put_page(page);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/fs/squashfs/dir.c linux-libre-2.6.38.8-gnu/fs/squashfs/dir.c
--- linux-libre-2.6.38-gnu/fs/squashfs/dir.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/squashfs/dir.c	2011-06-02 21:35:11.000000000 -0400
@@ -172,6 +172,11 @@
 		length += sizeof(dirh);
 
 		dir_count = le32_to_cpu(dirh.count) + 1;
+
+		/* dir_count should never be larger than 256 */
+		if (dir_count > 256)
+			goto failed_read;
+
 		while (dir_count--) {
 			/*
 			 * Read directory entry.
@@ -183,6 +188,10 @@
 
 			size = le16_to_cpu(dire->size) + 1;
 
+			/* size should never be larger than SQUASHFS_NAME_LEN */
+			if (size > SQUASHFS_NAME_LEN)
+				goto failed_read;
+
 			err = squashfs_read_metadata(inode->i_sb, dire->name,
 					&block, &offset, size);
 			if (err < 0)
diff -druN linux-libre-2.6.38-gnu/fs/squashfs/namei.c linux-libre-2.6.38.8-gnu/fs/squashfs/namei.c
--- linux-libre-2.6.38-gnu/fs/squashfs/namei.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/squashfs/namei.c	2011-06-02 21:35:11.000000000 -0400
@@ -176,6 +176,11 @@
 		length += sizeof(dirh);
 
 		dir_count = le32_to_cpu(dirh.count) + 1;
+
+		/* dir_count should never be larger than 256 */
+		if (dir_count > 256)
+			goto data_error;
+
 		while (dir_count--) {
 			/*
 			 * Read directory entry.
@@ -187,6 +192,10 @@
 
 			size = le16_to_cpu(dire->size) + 1;
 
+			/* size should never be larger than SQUASHFS_NAME_LEN */
+			if (size > SQUASHFS_NAME_LEN)
+				goto data_error;
+
 			err = squashfs_read_metadata(dir->i_sb, dire->name,
 					&block, &offset, size);
 			if (err < 0)
@@ -228,6 +237,9 @@
 	d_add(dentry, inode);
 	return ERR_PTR(0);
 
+data_error:
+	err = -EIO;
+
 read_failure:
 	ERROR("Unable to read directory block [%llx:%x]\n",
 		squashfs_i(dir)->start + msblk->directory_table,
diff -druN linux-libre-2.6.38-gnu/fs/squashfs/zlib_wrapper.c linux-libre-2.6.38.8-gnu/fs/squashfs/zlib_wrapper.c
--- linux-libre-2.6.38-gnu/fs/squashfs/zlib_wrapper.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/squashfs/zlib_wrapper.c	2011-06-02 21:35:11.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/buffer_head.h>
 #include <linux/slab.h>
 #include <linux/zlib.h>
+#include <linux/vmalloc.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -37,8 +38,7 @@
 	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
 	if (stream == NULL)
 		goto failed;
-	stream->workspace = kmalloc(zlib_inflate_workspacesize(),
-		GFP_KERNEL);
+	stream->workspace = vmalloc(zlib_inflate_workspacesize());
 	if (stream->workspace == NULL)
 		goto failed;
 
@@ -56,7 +56,7 @@
 	z_stream *stream = strm;
 
 	if (stream)
-		kfree(stream->workspace);
+		vfree(stream->workspace);
 	kfree(stream);
 }
 
diff -druN linux-libre-2.6.38-gnu/fs/super.c linux-libre-2.6.38.8-gnu/fs/super.c
--- linux-libre-2.6.38-gnu/fs/super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/super.c	2011-06-02 21:35:11.000000000 -0400
@@ -71,6 +71,7 @@
 #else
 		INIT_LIST_HEAD(&s->s_files);
 #endif
+		s->s_bdi = &default_backing_dev_info;
 		INIT_LIST_HEAD(&s->s_instances);
 		INIT_HLIST_BL_HEAD(&s->s_anon);
 		INIT_LIST_HEAD(&s->s_inodes);
@@ -1003,6 +1004,7 @@
 	}
 	BUG_ON(!mnt->mnt_sb);
 	WARN_ON(!mnt->mnt_sb->s_bdi);
+	WARN_ON(mnt->mnt_sb->s_bdi == &default_backing_dev_info);
 	mnt->mnt_sb->s_flags |= MS_BORN;
 
 	error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
diff -druN linux-libre-2.6.38-gnu/fs/sync.c linux-libre-2.6.38.8-gnu/fs/sync.c
--- linux-libre-2.6.38-gnu/fs/sync.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/sync.c	2011-06-02 21:35:11.000000000 -0400
@@ -33,7 +33,7 @@
 	 * This should be safe, as we require bdi backing to actually
 	 * write out data in the first place
 	 */
-	if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info)
+	if (sb->s_bdi == &noop_backing_dev_info)
 		return 0;
 
 	if (sb->s_qcop && sb->s_qcop->quota_sync)
@@ -79,7 +79,7 @@
 
 static void sync_one_sb(struct super_block *sb, void *arg)
 {
-	if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi)
+	if (!(sb->s_flags & MS_RDONLY))
 		__sync_filesystem(sb, *(int *)arg);
 }
 /*
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/commit.c linux-libre-2.6.38.8-gnu/fs/ubifs/commit.c
--- linux-libre-2.6.38-gnu/fs/ubifs/commit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/commit.c	2011-06-02 21:35:11.000000000 -0400
@@ -521,7 +521,7 @@
 	size_t sz;
 
 	if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
-		goto out;
+		return 0;
 
 	INIT_LIST_HEAD(&list);
 
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/debug.c linux-libre-2.6.38.8-gnu/fs/ubifs/debug.c
--- linux-libre-2.6.38-gnu/fs/ubifs/debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/debug.c	2011-06-02 21:35:11.000000000 -0400
@@ -961,11 +961,39 @@
 void dbg_save_space_info(struct ubifs_info *c)
 {
 	struct ubifs_debug_info *d = c->dbg;
-
-	ubifs_get_lp_stats(c, &d->saved_lst);
+	int freeable_cnt;
 
 	spin_lock(&c->space_lock);
+	memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
+
+	/*
+	 * We use a dirty hack here and zero out @c->freeable_cnt, because it
+	 * affects the free space calculations, and UBIFS might not know about
+	 * all freeable eraseblocks. Indeed, we know about freeable eraseblocks
+	 * only when we read their lprops, and we do this only lazily, upon the
+	 * need. So at any given point of time @c->freeable_cnt might be not
+	 * exactly accurate.
+	 *
+	 * Just one example about the issue we hit when we did not zero
+	 * @c->freeable_cnt.
+	 * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the
+	 *    amount of free space in @d->saved_free
+	 * 2. We re-mount R/W, which makes UBIFS to read the "lsave"
+	 *    information from flash, where we cache LEBs from various
+	 *    categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()'
+	 *    -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()'
+	 *    -> 'ubifs_get_pnode()' -> 'update_cats()'
+	 *    -> 'ubifs_add_to_cat()').
+	 * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt
+	 *    becomes %1.
+	 * 4. We calculate the amount of free space when the re-mount is
+	 *    finished in 'dbg_check_space_info()' and it does not match
+	 *    @d->saved_free.
+	 */
+	freeable_cnt = c->freeable_cnt;
+	c->freeable_cnt = 0;
 	d->saved_free = ubifs_get_free_space_nolock(c);
+	c->freeable_cnt = freeable_cnt;
 	spin_unlock(&c->space_lock);
 }
 
@@ -982,12 +1010,15 @@
 {
 	struct ubifs_debug_info *d = c->dbg;
 	struct ubifs_lp_stats lst;
-	long long avail, free;
+	long long free;
+	int freeable_cnt;
 
 	spin_lock(&c->space_lock);
-	avail = ubifs_calc_available(c, c->min_idx_lebs);
+	freeable_cnt = c->freeable_cnt;
+	c->freeable_cnt = 0;
+	free = ubifs_get_free_space_nolock(c);
+	c->freeable_cnt = freeable_cnt;
 	spin_unlock(&c->space_lock);
-	free = ubifs_get_free_space(c);
 
 	if (free != d->saved_free) {
 		ubifs_err("free space changed from %lld to %lld",
@@ -2813,19 +2844,19 @@
 	}
 
 	fname = "dump_lprops";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_lprops = dent;
 
 	fname = "dump_budg";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_budg = dent;
 
 	fname = "dump_tnc";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_tnc = dent;
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/file.c linux-libre-2.6.38.8-gnu/fs/ubifs/file.c
--- linux-libre-2.6.38-gnu/fs/ubifs/file.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/file.c	2011-06-02 21:35:11.000000000 -0400
@@ -1309,6 +1309,9 @@
 
 	dbg_gen("syncing inode %lu", inode->i_ino);
 
+	if (inode->i_sb->s_flags & MS_RDONLY)
+		return 0;
+
 	/*
 	 * VFS has already synchronized dirty pages for this inode. Synchronize
 	 * the inode unless this is a 'datasync()' call.
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/log.c linux-libre-2.6.38.8-gnu/fs/ubifs/log.c
--- linux-libre-2.6.38-gnu/fs/ubifs/log.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/log.c	2011-06-02 21:35:11.000000000 -0400
@@ -175,26 +175,6 @@
 }
 
 /**
- * ubifs_create_buds_lists - create journal head buds lists for remount rw.
- * @c: UBIFS file-system description object
- */
-void ubifs_create_buds_lists(struct ubifs_info *c)
-{
-	struct rb_node *p;
-
-	spin_lock(&c->buds_lock);
-	p = rb_first(&c->buds);
-	while (p) {
-		struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
-		struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
-
-		list_add_tail(&bud->list, &jhead->buds_list);
-		p = rb_next(p);
-	}
-	spin_unlock(&c->buds_lock);
-}
-
-/**
  * ubifs_add_bud_to_log - add a new bud to the log.
  * @c: UBIFS file-system description object
  * @jhead: journal head the bud belongs to
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/lpt.c linux-libre-2.6.38.8-gnu/fs/ubifs/lpt.c
--- linux-libre-2.6.38-gnu/fs/ubifs/lpt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/lpt.c	2011-06-02 21:35:11.000000000 -0400
@@ -1270,10 +1270,9 @@
 	lnum = branch->lnum;
 	offs = branch->offs;
 	pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
-	if (!pnode) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!pnode)
+		return -ENOMEM;
+
 	if (lnum == 0) {
 		/*
 		 * This pnode was not written which just means that the LEB
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/recovery.c linux-libre-2.6.38.8-gnu/fs/ubifs/recovery.c
--- linux-libre-2.6.38-gnu/fs/ubifs/recovery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/recovery.c	2011-06-02 21:35:11.000000000 -0400
@@ -300,6 +300,32 @@
 			goto out_free;
 		}
 		memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
+
+		/*
+		 * We had to recover the master node, which means there was an
+		 * unclean reboot. However, it is possible that the master node
+		 * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
+		 * E.g., consider the following chain of events:
+		 *
+		 * 1. UBIFS was cleanly unmounted, so the master node is clean
+		 * 2. UBIFS is being mounted R/W and starts changing the master
+		 *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
+		 *    so this LEB ends up with some amount of garbage at the
+		 *    end.
+		 * 3. UBIFS is being mounted R/O. We reach this place and
+		 *    recover the master node from the second LEB
+		 *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
+		 *    because we are being mounted R/O. We have to defer the
+		 *    operation.
+		 * 4. However, this master node (@c->mst_node) is marked as
+		 *    clean (since the step 1). And if we just return, the
+		 *    mount code will be confused and won't recover the master
+		 *    node when it is re-mounter R/W later.
+		 *
+		 *    Thus, to force the recovery by marking the master node as
+		 *    dirty.
+		 */
+		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
 	} else {
 		/* Write the recovered master node */
 		c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/replay.c linux-libre-2.6.38.8-gnu/fs/ubifs/replay.c
--- linux-libre-2.6.38-gnu/fs/ubifs/replay.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/replay.c	2011-06-02 21:35:11.000000000 -0400
@@ -59,6 +59,7 @@
  * @new_size: truncation new size
  * @free: amount of free space in a bud
  * @dirty: amount of dirty space in a bud from padding and deletion nodes
+ * @jhead: journal head number of the bud
  *
  * UBIFS journal replay must compare node sequence numbers, which means it must
  * build a tree of node information to insert into the TNC.
@@ -80,6 +81,7 @@
 		struct {
 			int free;
 			int dirty;
+			int jhead;
 		};
 	};
 };
@@ -159,6 +161,11 @@
 		err = PTR_ERR(lp);
 		goto out;
 	}
+
+	/* Make sure the journal head points to the latest bud */
+	err = ubifs_wbuf_seek_nolock(&c->jheads[r->jhead].wbuf, r->lnum,
+				     c->leb_size - r->free, UBI_SHORTTERM);
+
 out:
 	ubifs_release_lprops(c);
 	return err;
@@ -627,10 +634,6 @@
 	ubifs_assert(sleb->endpt - offs >= used);
 	ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-	if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
-		err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
-					     sleb->endpt, UBI_SHORTTERM);
-
 	*dirty = sleb->endpt - offs - used;
 	*free = c->leb_size - sleb->endpt;
 
@@ -653,12 +656,14 @@
  * @sqnum: sequence number
  * @free: amount of free space in bud
  * @dirty: amount of dirty space from padding and deletion nodes
+ * @jhead: journal head number for the bud
  *
  * This function inserts a reference node to the replay tree and returns zero
  * in case of success or a negative error code in case of failure.
  */
 static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
-			   unsigned long long sqnum, int free, int dirty)
+			   unsigned long long sqnum, int free, int dirty,
+			   int jhead)
 {
 	struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
 	struct replay_entry *r;
@@ -688,6 +693,7 @@
 	r->flags = REPLAY_REF;
 	r->free = free;
 	r->dirty = dirty;
+	r->jhead = jhead;
 
 	rb_link_node(&r->rb, parent, p);
 	rb_insert_color(&r->rb, &c->replay_tree);
@@ -712,7 +718,7 @@
 		if (err)
 			return err;
 		err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum,
-				      free, dirty);
+				      free, dirty, b->bud->jhead);
 		if (err)
 			return err;
 	}
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/sb.c linux-libre-2.6.38.8-gnu/fs/ubifs/sb.c
--- linux-libre-2.6.38-gnu/fs/ubifs/sb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/sb.c	2011-06-02 21:35:11.000000000 -0400
@@ -475,7 +475,8 @@
  * @c: UBIFS file-system description object
  *
  * This function returns a pointer to the superblock node or a negative error
- * code.
+ * code. Note, the user of this function is responsible of kfree()'ing the
+ * returned superblock buffer.
  */
 struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
 {
diff -druN linux-libre-2.6.38-gnu/fs/ubifs/super.c linux-libre-2.6.38.8-gnu/fs/ubifs/super.c
--- linux-libre-2.6.38-gnu/fs/ubifs/super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/ubifs/super.c	2011-06-02 21:35:11.000000000 -0400
@@ -1235,12 +1235,12 @@
 		goto out_free;
 	}
 
+	err = alloc_wbufs(c);
+	if (err)
+		goto out_cbuf;
+
 	sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
 	if (!c->ro_mount) {
-		err = alloc_wbufs(c);
-		if (err)
-			goto out_cbuf;
-
 		/* Create background thread */
 		c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
 		if (IS_ERR(c->bgt)) {
@@ -1543,6 +1543,7 @@
 	mutex_lock(&c->umount_mutex);
 	dbg_save_space_info(c);
 	c->remounting_rw = 1;
+	c->ro_mount = 0;
 	c->always_chk_crc = 1;
 
 	err = check_free_space(c);
@@ -1559,6 +1560,7 @@
 		}
 		sup->leb_cnt = cpu_to_le32(c->leb_cnt);
 		err = ubifs_write_sb_node(c, sup);
+		kfree(sup);
 		if (err)
 			goto out;
 	}
@@ -1602,12 +1604,6 @@
 	if (err)
 		goto out;
 
-	err = alloc_wbufs(c);
-	if (err)
-		goto out;
-
-	ubifs_create_buds_lists(c);
-
 	/* Create background thread */
 	c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
 	if (IS_ERR(c->bgt)) {
@@ -1642,20 +1638,32 @@
 	if (err)
 		goto out;
 
+	dbg_gen("re-mounted read-write");
+	c->remounting_rw = 0;
+
 	if (c->need_recovery) {
 		c->need_recovery = 0;
 		ubifs_msg("deferred recovery completed");
+	} else {
+		/*
+		 * Do not run the debugging space check if the were doing
+		 * recovery, because when we saved the information we had the
+		 * file-system in a state where the TNC and lprops has been
+		 * modified in memory, but all the I/O operations (including a
+		 * commit) were deferred. So the file-system was in
+		 * "non-committed" state. Now the file-system is in committed
+		 * state, and of course the amount of free space will change
+		 * because, for example, the old index size was imprecise.
+		 */
+		err = dbg_check_space_info(c);
 	}
 
-	dbg_gen("re-mounted read-write");
-	c->ro_mount = 0;
-	c->remounting_rw = 0;
 	c->always_chk_crc = 0;
-	err = dbg_check_space_info(c);
 	mutex_unlock(&c->umount_mutex);
 	return err;
 
 out:
+	c->ro_mount = 1;
 	vfree(c->orph_buf);
 	c->orph_buf = NULL;
 	if (c->bgt) {
@@ -1704,7 +1712,6 @@
 	if (err)
 		ubifs_ro_mode(c, err);
 
-	free_wbufs(c);
 	vfree(c->orph_buf);
 	c->orph_buf = NULL;
 	vfree(c->ileb_buf);
diff -druN linux-libre-2.6.38-gnu/fs/xfs/linux-2.6/xfs_super.c linux-libre-2.6.38.8-gnu/fs/xfs/linux-2.6/xfs_super.c
--- linux-libre-2.6.38-gnu/fs/xfs/linux-2.6/xfs_super.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/fs/xfs/linux-2.6/xfs_super.c	2011-06-02 21:35:11.000000000 -0400
@@ -1551,10 +1551,14 @@
 	if (error)
 		goto out_free_sb;
 
-	error = xfs_mountfs(mp);
-	if (error)
-		goto out_filestream_unmount;
-
+	/*
+	 * we must configure the block size in the superblock before we run the
+	 * full mount process as the mount process can lookup and cache inodes.
+	 * For the same reason we must also initialise the syncd and register
+	 * the inode cache shrinker so that inodes can be reclaimed during
+	 * operations like a quotacheck that iterate all inodes in the
+	 * filesystem.
+	 */
 	sb->s_magic = XFS_SB_MAGIC;
 	sb->s_blocksize = mp->m_sb.sb_blocksize;
 	sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
@@ -1562,6 +1566,16 @@
 	sb->s_time_gran = 1;
 	set_posix_acl_flag(sb);
 
+	error = xfs_syncd_init(mp);
+	if (error)
+		goto out_filestream_unmount;
+
+	xfs_inode_shrinker_register(mp);
+
+	error = xfs_mountfs(mp);
+	if (error)
+		goto out_syncd_stop;
+
 	root = igrab(VFS_I(mp->m_rootip));
 	if (!root) {
 		error = ENOENT;
@@ -1577,14 +1591,11 @@
 		goto fail_vnrele;
 	}
 
-	error = xfs_syncd_init(mp);
-	if (error)
-		goto fail_vnrele;
-
-	xfs_inode_shrinker_register(mp);
-
 	return 0;
 
+ out_syncd_stop:
+	xfs_inode_shrinker_unregister(mp);
+	xfs_syncd_stop(mp);
  out_filestream_unmount:
 	xfs_filestream_unmount(mp);
  out_free_sb:
@@ -1608,6 +1619,9 @@
 	}
 
  fail_unmount:
+	xfs_inode_shrinker_unregister(mp);
+	xfs_syncd_stop(mp);
+
 	/*
 	 * Blow away any referenced inode in the filestreams cache.
 	 * This can and will cause log traffic as inodes go inactive
diff -druN linux-libre-2.6.38-gnu/include/drm/drm_pciids.h linux-libre-2.6.38.8-gnu/include/drm/drm_pciids.h
--- linux-libre-2.6.38-gnu/include/drm/drm_pciids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/drm/drm_pciids.h	2011-06-02 21:35:11.000000000 -0400
@@ -153,6 +153,7 @@
 	{0x1002, 0x6729, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6739, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x673e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6741, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -185,6 +186,7 @@
 	{0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x689b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
@@ -195,7 +197,9 @@
 	{0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68ba, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68bf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -458,6 +462,8 @@
 	{0x1002, 0x9803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9804, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0, 0, 0}
 
 #define r128_PCI_IDS \
diff -druN linux-libre-2.6.38-gnu/include/drm/radeon_drm.h linux-libre-2.6.38.8-gnu/include/drm/radeon_drm.h
--- linux-libre-2.6.38-gnu/include/drm/radeon_drm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/drm/radeon_drm.h	2011-06-02 21:35:11.000000000 -0400
@@ -908,6 +908,7 @@
 #define RADEON_INFO_WANT_HYPERZ		0x07
 #define RADEON_INFO_WANT_CMASK		0x08 /* get access to CMASK on r300 */
 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ	0x09 /* clock crystal frequency */
+#define RADEON_INFO_FUSION_GART_WORKING	0x0c /* fusion writes to GTT were broken before this */
 
 struct drm_radeon_info {
 	uint32_t		request;
diff -druN linux-libre-2.6.38-gnu/include/linux/atmdev.h linux-libre-2.6.38.8-gnu/include/linux/atmdev.h
--- linux-libre-2.6.38-gnu/include/linux/atmdev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/atmdev.h	2011-06-02 21:35:11.000000000 -0400
@@ -443,6 +443,7 @@
 
 void vcc_insert_socket(struct sock *sk);
 
+void atm_dev_release_vccs(struct atm_dev *dev);
 
 /*
  * This is approximately the algorithm used by alloc_skb.
diff -druN linux-libre-2.6.38-gnu/include/linux/blkdev.h linux-libre-2.6.38.8-gnu/include/linux/blkdev.h
--- linux-libre-2.6.38-gnu/include/linux/blkdev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/blkdev.h	2011-06-02 21:35:11.000000000 -0400
@@ -252,7 +252,7 @@
 	unsigned char		misaligned;
 	unsigned char		discard_misaligned;
 	unsigned char		cluster;
-	signed char		discard_zeroes_data;
+	unsigned char		discard_zeroes_data;
 };
 
 struct request_queue
@@ -1032,13 +1032,16 @@
 {
 	unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1);
 
+	if (!lim->max_discard_sectors)
+		return 0;
+
 	return (lim->discard_granularity + lim->discard_alignment - alignment)
 		& (lim->discard_granularity - 1);
 }
 
 static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
 {
-	if (q->limits.discard_zeroes_data == 1)
+	if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
 		return 1;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/include/linux/bootmem.h linux-libre-2.6.38.8-gnu/include/linux/bootmem.h
--- linux-libre-2.6.38-gnu/include/linux/bootmem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/bootmem.h	2011-06-02 21:35:11.000000000 -0400
@@ -115,6 +115,8 @@
 	__alloc_bootmem_nopanic(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_node(pgdat, x) \
 	__alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_node_nopanic(pgdat, x) \
+	__alloc_bootmem_node_nopanic(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node(pgdat, x) \
 	__alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node_nopanic(pgdat, x) \
diff -druN linux-libre-2.6.38-gnu/include/linux/compaction.h linux-libre-2.6.38.8-gnu/include/linux/compaction.h
--- linux-libre-2.6.38-gnu/include/linux/compaction.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/compaction.h	2011-06-02 21:35:11.000000000 -0400
@@ -11,9 +11,6 @@
 /* The full zone was compacted */
 #define COMPACT_COMPLETE	3
 
-#define COMPACT_MODE_DIRECT_RECLAIM	0
-#define COMPACT_MODE_KSWAPD		1
-
 #ifdef CONFIG_COMPACTION
 extern int sysctl_compact_memory;
 extern int sysctl_compaction_handler(struct ctl_table *table, int write,
@@ -28,8 +25,7 @@
 			bool sync);
 extern unsigned long compaction_suitable(struct zone *zone, int order);
 extern unsigned long compact_zone_order(struct zone *zone, int order,
-					gfp_t gfp_mask, bool sync,
-					int compact_mode);
+					gfp_t gfp_mask, bool sync);
 
 /* Do not skip compaction more than 64 times */
 #define COMPACT_MAX_DEFER_SHIFT 6
@@ -74,8 +70,7 @@
 }
 
 static inline unsigned long compact_zone_order(struct zone *zone, int order,
-					       gfp_t gfp_mask, bool sync,
-					       int compact_mode)
+					       gfp_t gfp_mask, bool sync)
 {
 	return COMPACT_CONTINUE;
 }
diff -druN linux-libre-2.6.38-gnu/include/linux/ethtool.h linux-libre-2.6.38.8-gnu/include/linux/ethtool.h
--- linux-libre-2.6.38-gnu/include/linux/ethtool.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/ethtool.h	2011-06-02 21:35:11.000000000 -0400
@@ -13,6 +13,9 @@
 #ifndef _LINUX_ETHTOOL_H
 #define _LINUX_ETHTOOL_H
 
+#ifdef __KERNEL__
+#include <linux/compat.h>
+#endif
 #include <linux/types.h>
 #include <linux/if_ether.h>
 
@@ -449,6 +452,37 @@
 	__u32				rule_locs[0];
 };
 
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+struct compat_ethtool_rx_flow_spec {
+	u32		flow_type;
+	union {
+		struct ethtool_tcpip4_spec		tcp_ip4_spec;
+		struct ethtool_tcpip4_spec		udp_ip4_spec;
+		struct ethtool_tcpip4_spec		sctp_ip4_spec;
+		struct ethtool_ah_espip4_spec		ah_ip4_spec;
+		struct ethtool_ah_espip4_spec		esp_ip4_spec;
+		struct ethtool_usrip4_spec		usr_ip4_spec;
+		struct ethhdr				ether_spec;
+		u8					hdata[72];
+	} h_u, m_u;
+	compat_u64	ring_cookie;
+	u32		location;
+};
+
+struct compat_ethtool_rxnfc {
+	u32				cmd;
+	u32				flow_type;
+	compat_u64			data;
+	struct compat_ethtool_rx_flow_spec fs;
+	u32				rule_cnt;
+	u32				rule_locs[0];
+};
+
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+
 /**
  * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
  * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
@@ -557,6 +591,7 @@
 u32 ethtool_op_get_flags(struct net_device *dev);
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
 void ethtool_ntuple_flush(struct net_device *dev);
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
 
 /**
  * &ethtool_ops - Alter and report network device settings
diff -druN linux-libre-2.6.38-gnu/include/linux/flex_array.h linux-libre-2.6.38.8-gnu/include/linux/flex_array.h
--- linux-libre-2.6.38-gnu/include/linux/flex_array.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/flex_array.h	2011-06-02 21:35:11.000000000 -0400
@@ -61,7 +61,7 @@
 struct flex_array *flex_array_alloc(int element_size, unsigned int total,
 		gfp_t flags);
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-		unsigned int end, gfp_t flags);
+		unsigned int nr_elements, gfp_t flags);
 void flex_array_free(struct flex_array *fa);
 void flex_array_free_parts(struct flex_array *fa);
 int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
diff -druN linux-libre-2.6.38-gnu/include/linux/ftrace.h linux-libre-2.6.38.8-gnu/include/linux/ftrace.h
--- linux-libre-2.6.38-gnu/include/linux/ftrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/ftrace.h	2011-06-02 21:35:11.000000000 -0400
@@ -428,6 +428,7 @@
 
 extern void ftrace_graph_init_task(struct task_struct *t);
 extern void ftrace_graph_exit_task(struct task_struct *t);
+extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu);
 
 static inline int task_curr_ret_stack(struct task_struct *t)
 {
@@ -451,6 +452,7 @@
 
 static inline void ftrace_graph_init_task(struct task_struct *t) { }
 static inline void ftrace_graph_exit_task(struct task_struct *t) { }
+static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { }
 
 static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc,
 			  trace_func_graph_ent_t entryfunc)
diff -druN linux-libre-2.6.38-gnu/include/linux/genhd.h linux-libre-2.6.38.8-gnu/include/linux/genhd.h
--- linux-libre-2.6.38-gnu/include/linux/genhd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/genhd.h	2011-06-02 21:35:11.000000000 -0400
@@ -127,6 +127,7 @@
 #define GENHD_FL_SUPPRESS_PARTITION_INFO	32
 #define GENHD_FL_EXT_DEVT			64 /* allow extended devt */
 #define GENHD_FL_NATIVE_CAPACITY		128
+#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE	256
 
 enum {
 	DISK_EVENT_MEDIA_CHANGE			= 1 << 0, /* media changed */
diff -druN linux-libre-2.6.38-gnu/include/linux/hid.h linux-libre-2.6.38.8-gnu/include/linux/hid.h
--- linux-libre-2.6.38-gnu/include/linux/hid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/hid.h	2011-06-02 21:35:11.000000000 -0400
@@ -638,7 +638,7 @@
 			struct hid_input *hidinput, struct hid_field *field,
 			struct hid_usage *usage, unsigned long **bit, int *max);
 	void (*feature_mapping)(struct hid_device *hdev,
-			struct hid_input *hidinput, struct hid_field *field,
+			struct hid_field *field,
 			struct hid_usage *usage);
 #ifdef CONFIG_PM
 	int (*suspend)(struct hid_device *hdev, pm_message_t message);
diff -druN linux-libre-2.6.38-gnu/include/linux/huge_mm.h linux-libre-2.6.38.8-gnu/include/linux/huge_mm.h
--- linux-libre-2.6.38-gnu/include/linux/huge_mm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/huge_mm.h	2011-06-02 21:35:11.000000000 -0400
@@ -117,7 +117,7 @@
 					 unsigned long end,
 					 long adjust_next)
 {
-	if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+	if (!vma->anon_vma || vma->vm_ops)
 		return;
 	__vma_adjust_trans_huge(vma, start, end, adjust_next);
 }
diff -druN linux-libre-2.6.38-gnu/include/linux/kernel.h linux-libre-2.6.38.8-gnu/include/linux/kernel.h
--- linux-libre-2.6.38-gnu/include/linux/kernel.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/kernel.h	2011-06-02 21:35:11.000000000 -0400
@@ -187,14 +187,76 @@
 	ATTRIB_NORET;
 NORET_TYPE void complete_and_exit(struct completion *, long)
 	ATTRIB_NORET;
+
+/* Internal, do not use. */
+int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res);
+int __must_check _kstrtol(const char *s, unsigned int base, long *res);
+
+int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res);
+int __must_check kstrtoll(const char *s, unsigned int base, long long *res);
+static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+	/*
+	 * We want to shortcut function call, but
+	 * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0.
+	 */
+	if (sizeof(unsigned long) == sizeof(unsigned long long) &&
+	    __alignof__(unsigned long) == __alignof__(unsigned long long))
+		return kstrtoull(s, base, (unsigned long long *)res);
+	else
+		return _kstrtoul(s, base, res);
+}
+
+static inline int __must_check kstrtol(const char *s, unsigned int base, long *res)
+{
+	/*
+	 * We want to shortcut function call, but
+	 * __builtin_types_compatible_p(long, long long) = 0.
+	 */
+	if (sizeof(long) == sizeof(long long) &&
+	    __alignof__(long) == __alignof__(long long))
+		return kstrtoll(s, base, (long long *)res);
+	else
+		return _kstrtol(s, base, res);
+}
+
+int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res);
+int __must_check kstrtoint(const char *s, unsigned int base, int *res);
+
+static inline int __must_check kstrtou64(const char *s, unsigned int base, u64 *res)
+{
+	return kstrtoull(s, base, res);
+}
+
+static inline int __must_check kstrtos64(const char *s, unsigned int base, s64 *res)
+{
+	return kstrtoll(s, base, res);
+}
+
+static inline int __must_check kstrtou32(const char *s, unsigned int base, u32 *res)
+{
+	return kstrtouint(s, base, res);
+}
+
+static inline int __must_check kstrtos32(const char *s, unsigned int base, s32 *res)
+{
+	return kstrtoint(s, base, res);
+}
+
+int __must_check kstrtou16(const char *s, unsigned int base, u16 *res);
+int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
+int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
+int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
+
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
 extern long long simple_strtoll(const char *,char **,unsigned int);
-extern int __must_check strict_strtoul(const char *, unsigned int, unsigned long *);
-extern int __must_check strict_strtol(const char *, unsigned int, long *);
-extern int __must_check strict_strtoull(const char *, unsigned int, unsigned long long *);
-extern int __must_check strict_strtoll(const char *, unsigned int, long long *);
+#define strict_strtoul	kstrtoul
+#define strict_strtol	kstrtol
+#define strict_strtoull	kstrtoull
+#define strict_strtoll	kstrtoll
+
 extern int sprintf(char * buf, const char * fmt, ...)
 	__attribute__ ((format (printf, 2, 3)));
 extern int vsprintf(char *buf, const char *, va_list)
diff -druN linux-libre-2.6.38-gnu/include/linux/libata.h linux-libre-2.6.38.8-gnu/include/linux/libata.h
--- linux-libre-2.6.38-gnu/include/linux/libata.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/libata.h	2011-06-02 21:35:11.000000000 -0400
@@ -203,6 +203,7 @@
 					      * management */
 	ATA_FLAG_SW_ACTIVITY	= (1 << 22), /* driver supports sw activity
 					      * led */
+	ATA_FLAG_NO_DIPM	= (1 << 23), /* host not happy with DIPM */
 
 	/* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
diff -druN linux-libre-2.6.38-gnu/include/linux/mm.h linux-libre-2.6.38.8-gnu/include/linux/mm.h
--- linux-libre-2.6.38-gnu/include/linux/mm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/mm.h	2011-06-02 21:35:11.000000000 -0400
@@ -137,7 +137,8 @@
 #define VM_RandomReadHint(v)		((v)->vm_flags & VM_RAND_READ)
 
 /*
- * special vmas that are non-mergable, non-mlock()able
+ * Special vmas that are non-mergable, non-mlock()able.
+ * Note: mm/huge_memory.c VM_NO_THP depends on this definition.
  */
 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
 
@@ -402,16 +403,23 @@
 /*
  * PageBuddy() indicate that the page is free and in the buddy system
  * (see mm/page_alloc.c).
+ *
+ * PAGE_BUDDY_MAPCOUNT_VALUE must be <= -2 but better not too close to
+ * -2 so that an underflow of the page_mapcount() won't be mistaken
+ * for a genuine PAGE_BUDDY_MAPCOUNT_VALUE. -128 can be created very
+ * efficiently by most CPU architectures.
  */
+#define PAGE_BUDDY_MAPCOUNT_VALUE (-128)
+
 static inline int PageBuddy(struct page *page)
 {
-	return atomic_read(&page->_mapcount) == -2;
+	return atomic_read(&page->_mapcount) == PAGE_BUDDY_MAPCOUNT_VALUE;
 }
 
 static inline void __SetPageBuddy(struct page *page)
 {
 	VM_BUG_ON(atomic_read(&page->_mapcount) != -1);
-	atomic_set(&page->_mapcount, -2);
+	atomic_set(&page->_mapcount, PAGE_BUDDY_MAPCOUNT_VALUE);
 }
 
 static inline void __ClearPageBuddy(struct page *page)
@@ -986,11 +994,33 @@
 int clear_page_dirty_for_io(struct page *page);
 
 /* Is the vma a continuation of the stack vma above it? */
-static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
+static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
 {
 	return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
 }
 
+static inline int stack_guard_page_start(struct vm_area_struct *vma,
+					     unsigned long addr)
+{
+	return (vma->vm_flags & VM_GROWSDOWN) &&
+		(vma->vm_start == addr) &&
+		!vma_growsdown(vma->vm_prev, addr);
+}
+
+/* Is the vma a continuation of the stack vma below it? */
+static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
+{
+	return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
+}
+
+static inline int stack_guard_page_end(struct vm_area_struct *vma,
+					   unsigned long addr)
+{
+	return (vma->vm_flags & VM_GROWSUP) &&
+		(vma->vm_end == addr) &&
+		!vma_growsup(vma->vm_next, addr);
+}
+
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
 		unsigned long old_addr, struct vm_area_struct *new_vma,
 		unsigned long new_addr, unsigned long len);
diff -druN linux-libre-2.6.38-gnu/include/linux/pci.h linux-libre-2.6.38.8-gnu/include/linux/pci.h
--- linux-libre-2.6.38-gnu/include/linux/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/pci.h	2011-06-02 21:35:11.000000000 -0400
@@ -1002,12 +1002,11 @@
 #endif
 
 #ifndef CONFIG_PCIEASPM
-static inline int pcie_aspm_enabled(void)
-{
-	return 0;
-}
+static inline int pcie_aspm_enabled(void) { return 0; }
+static inline bool pcie_aspm_support_enabled(void) { return false; }
 #else
 extern int pcie_aspm_enabled(void);
+extern bool pcie_aspm_support_enabled(void);
 #endif
 
 #ifdef CONFIG_PCIEAER
diff -druN linux-libre-2.6.38-gnu/include/linux/pci_ids.h linux-libre-2.6.38.8-gnu/include/linux/pci_ids.h
--- linux-libre-2.6.38-gnu/include/linux/pci_ids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/pci_ids.h	2011-06-02 21:35:11.000000000 -0400
@@ -607,6 +607,8 @@
 #define PCI_DEVICE_ID_MATROX_G550	0x2527
 #define PCI_DEVICE_ID_MATROX_VIA	0x4536
 
+#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS	0x14f2
+
 #define PCI_VENDOR_ID_CT		0x102c
 #define PCI_DEVICE_ID_CT_69000		0x00c0
 #define PCI_DEVICE_ID_CT_65545		0x00d8
diff -druN linux-libre-2.6.38-gnu/include/linux/perf_event.h linux-libre-2.6.38.8-gnu/include/linux/perf_event.h
--- linux-libre-2.6.38-gnu/include/linux/perf_event.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/perf_event.h	2011-06-02 21:35:11.000000000 -0400
@@ -1052,7 +1052,7 @@
 {
 	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
 
-	COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
+	__perf_event_task_sched_out(task, next);
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
diff -druN linux-libre-2.6.38-gnu/include/linux/pid.h linux-libre-2.6.38.8-gnu/include/linux/pid.h
--- linux-libre-2.6.38-gnu/include/linux/pid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/pid.h	2011-06-02 21:35:11.000000000 -0400
@@ -117,7 +117,7 @@
  */
 extern struct pid *find_get_pid(int nr);
 extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
-int next_pidmap(struct pid_namespace *pid_ns, int last);
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last);
 
 extern struct pid *alloc_pid(struct pid_namespace *ns);
 extern void free_pid(struct pid *pid);
diff -druN linux-libre-2.6.38-gnu/include/linux/pm_qos_params.h linux-libre-2.6.38.8-gnu/include/linux/pm_qos_params.h
--- linux-libre-2.6.38-gnu/include/linux/pm_qos_params.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/pm_qos_params.h	2011-06-02 21:35:11.000000000 -0400
@@ -16,6 +16,10 @@
 #define PM_QOS_NUM_CLASSES 4
 #define PM_QOS_DEFAULT_VALUE -1
 
+#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE	(2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE	(2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE	0
+
 struct pm_qos_request_list {
 	struct plist_node list;
 	int pm_qos_class;
diff -druN linux-libre-2.6.38-gnu/include/linux/ptrace.h linux-libre-2.6.38.8-gnu/include/linux/ptrace.h
--- linux-libre-2.6.38-gnu/include/linux/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/ptrace.h	2011-06-02 21:35:11.000000000 -0400
@@ -189,6 +189,10 @@
 		child->ptrace = current->ptrace;
 		__ptrace_link(child, current->parent);
 	}
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	atomic_set(&child->ptrace_bp_refcnt, 1);
+#endif
 }
 
 /**
@@ -350,6 +354,13 @@
 				unsigned long args[6], unsigned int maxargs,
 				unsigned long *sp, unsigned long *pc);
 
-#endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+extern int ptrace_get_breakpoints(struct task_struct *tsk);
+extern void ptrace_put_breakpoints(struct task_struct *tsk);
+#else
+static inline void ptrace_put_breakpoints(struct task_struct *tsk) { }
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+#endif /* __KERNEL */
 
 #endif
diff -druN linux-libre-2.6.38-gnu/include/linux/sched.h linux-libre-2.6.38.8-gnu/include/linux/sched.h
--- linux-libre-2.6.38-gnu/include/linux/sched.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/sched.h	2011-06-02 21:35:11.000000000 -0400
@@ -1254,6 +1254,9 @@
 #endif
 
 	struct mm_struct *mm, *active_mm;
+#ifdef CONFIG_COMPAT_BRK
+	unsigned brk_randomized:1;
+#endif
 #if defined(SPLIT_RSS_COUNTING)
 	struct task_rss_stat	rss_stat;
 #endif
@@ -1528,6 +1531,9 @@
 		unsigned long memsw_bytes; /* uncharged mem+swap usage */
 	} memcg_batch;
 #endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	atomic_t ptrace_bp_refcnt;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
diff -druN linux-libre-2.6.38-gnu/include/linux/seqlock.h linux-libre-2.6.38.8-gnu/include/linux/seqlock.h
--- linux-libre-2.6.38-gnu/include/linux/seqlock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/seqlock.h	2011-06-02 21:35:11.000000000 -0400
@@ -88,12 +88,12 @@
 	unsigned ret;
 
 repeat:
-	ret = sl->sequence;
-	smp_rmb();
+	ret = ACCESS_ONCE(sl->sequence);
 	if (unlikely(ret & 1)) {
 		cpu_relax();
 		goto repeat;
 	}
+	smp_rmb();
 
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/include/linux/usb/ch9.h linux-libre-2.6.38.8-gnu/include/linux/usb/ch9.h
--- linux-libre-2.6.38-gnu/include/linux/usb/ch9.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/usb/ch9.h	2011-06-02 21:35:11.000000000 -0400
@@ -585,6 +585,8 @@
 #define USB_DT_SS_EP_COMP_SIZE		6
 /* Bits 4:0 of bmAttributes if this is a bulk endpoint */
 #define USB_SS_MAX_STREAMS(p)		(1 << (p & 0x1f))
+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
+#define USB_SS_MULT(p)			(1 + ((p) & 0x3))
 
 /*-------------------------------------------------------------------------*/
 
diff -druN linux-libre-2.6.38-gnu/include/linux/usb/hcd.h linux-libre-2.6.38.8-gnu/include/linux/usb/hcd.h
--- linux-libre-2.6.38-gnu/include/linux/usb/hcd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/usb/hcd.h	2011-06-02 21:35:11.000000000 -0400
@@ -99,6 +99,8 @@
 #define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
 #define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
 #define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
+#define HCD_FLAG_RH_RUNNING		5	/* root hub is running? */
+#define HCD_FLAG_DEAD			6	/* controller has died? */
 
 	/* The flags can be tested using these macros; they are likely to
 	 * be slightly faster than test_bit().
@@ -108,6 +110,8 @@
 #define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
 #define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
 #define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
+#define HCD_RH_RUNNING(hcd)	((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
+#define HCD_DEAD(hcd)		((hcd)->flags & (1U << HCD_FLAG_DEAD))
 
 	/* Flags that get set only during HCD registration or removal. */
 	unsigned		rh_registered:1;/* is root hub registered? */
diff -druN linux-libre-2.6.38-gnu/include/linux/usb/serial.h linux-libre-2.6.38.8-gnu/include/linux/usb/serial.h
--- linux-libre-2.6.38-gnu/include/linux/usb/serial.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/linux/usb/serial.h	2011-06-02 21:35:11.000000000 -0400
@@ -191,7 +191,8 @@
  * @id_table: pointer to a list of usb_device_id structures that define all
  *	of the devices this structure can support.
  * @num_ports: the number of different ports this device will have.
- * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size)
+ * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
+ *	(0 = end-point size)
  * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
  * @calc_num_ports: pointer to a function to determine how many ports this
  *	device has dynamically.  It will be called after the probe()
diff -druN linux-libre-2.6.38-gnu/include/net/bluetooth/hci.h linux-libre-2.6.38.8-gnu/include/net/bluetooth/hci.h
--- linux-libre-2.6.38-gnu/include/net/bluetooth/hci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/net/bluetooth/hci.h	2011-06-02 21:35:11.000000000 -0400
@@ -76,6 +76,8 @@
 	HCI_INQUIRY,
 
 	HCI_RAW,
+
+	HCI_RESET,
 };
 
 /* HCI ioctl defines */
diff -druN linux-libre-2.6.38-gnu/include/scsi/scsi_device.h linux-libre-2.6.38.8-gnu/include/scsi/scsi_device.h
--- linux-libre-2.6.38-gnu/include/scsi/scsi_device.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/scsi/scsi_device.h	2011-06-02 21:35:11.000000000 -0400
@@ -461,7 +461,7 @@
 }
 static inline int scsi_device_enclosure(struct scsi_device *sdev)
 {
-	return sdev->inquiry[6] & (1<<6);
+	return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1;
 }
 
 static inline int scsi_device_protection(struct scsi_device *sdev)
diff -druN linux-libre-2.6.38-gnu/include/sound/pcm.h linux-libre-2.6.38.8-gnu/include/sound/pcm.h
--- linux-libre-2.6.38-gnu/include/sound/pcm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/sound/pcm.h	2011-06-02 21:35:11.000000000 -0400
@@ -1030,9 +1030,7 @@
 #define snd_pcm_lib_mmap_iomem	NULL
 #endif
 
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
-			       struct vm_area_struct *area);
-#define snd_pcm_lib_mmap_vmalloc	snd_pcm_lib_mmap_noncached
+#define snd_pcm_lib_mmap_vmalloc NULL
 
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
diff -druN linux-libre-2.6.38-gnu/include/sound/soc-dapm.h linux-libre-2.6.38.8-gnu/include/sound/soc-dapm.h
--- linux-libre-2.6.38-gnu/include/sound/soc-dapm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/sound/soc-dapm.h	2011-06-02 21:35:11.000000000 -0400
@@ -45,25 +45,25 @@
 /* platform domain */
 #define SND_SOC_DAPM_INPUT(wname) \
 {	.id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0}
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_OUTPUT(wname) \
 {	.id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0}
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_MIC(wname, wevent) \
 {	.id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
 #define SND_SOC_DAPM_HP(wname, wevent) \
 {	.id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_SPK(wname, wevent) \
 {	.id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_LINE(wname, wevent) \
 {	.id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 
 /* path domain */
@@ -177,11 +177,11 @@
 /* events that are pre and post DAPM */
 #define SND_SOC_DAPM_PRE(wname, wevent) \
 {	.id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_POST(wname, wevent) \
 {	.id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
 
 /* stream domain */
diff -druN linux-libre-2.6.38-gnu/include/target/target_core_base.h linux-libre-2.6.38.8-gnu/include/target/target_core_base.h
--- linux-libre-2.6.38-gnu/include/target/target_core_base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/target/target_core_base.h	2011-06-02 21:35:11.000000000 -0400
@@ -98,6 +98,7 @@
 	TRANSPORT_REMOVE	= 14,
 	TRANSPORT_FREE		= 15,
 	TRANSPORT_NEW_CMD_MAP	= 16,
+	TRANSPORT_FREE_CMD_INTR = 17,
 };
 
 /* Used for struct se_cmd->se_cmd_flags */
diff -druN linux-libre-2.6.38-gnu/include/target/target_core_transport.h linux-libre-2.6.38.8-gnu/include/target/target_core_transport.h
--- linux-libre-2.6.38-gnu/include/target/target_core_transport.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/include/target/target_core_transport.h	2011-06-02 21:35:11.000000000 -0400
@@ -170,6 +170,7 @@
 extern int transport_generic_handle_data(struct se_cmd *);
 extern void transport_new_cmd_failure(struct se_cmd *);
 extern int transport_generic_handle_tmr(struct se_cmd *);
+extern void transport_generic_free_cmd_intr(struct se_cmd *);
 extern void __transport_stop_task_timer(struct se_task *, unsigned long *);
 extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]);
 extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
diff -druN linux-libre-2.6.38-gnu/init/Kconfig linux-libre-2.6.38.8-gnu/init/Kconfig
--- linux-libre-2.6.38-gnu/init/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/init/Kconfig	2011-06-02 21:35:11.000000000 -0400
@@ -1209,6 +1209,7 @@
 	  per cpu and per node queues.
 
 config SLUB
+	depends on BROKEN || NUMA || !DISCONTIGMEM
 	bool "SLUB (Unqueued Allocator)"
 	help
 	   SLUB is a slab allocator that minimizes cache line usage
diff -druN linux-libre-2.6.38-gnu/init/main.c linux-libre-2.6.38.8-gnu/init/main.c
--- linux-libre-2.6.38-gnu/init/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/init/main.c	2011-06-02 21:35:11.000000000 -0400
@@ -668,8 +668,8 @@
 #endif
 	page_cgroup_init();
 	enable_debug_pagealloc();
-	kmemleak_init();
 	debug_objects_mem_init();
+	kmemleak_init();
 	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)
diff -druN linux-libre-2.6.38-gnu/kernel/cgroup.c linux-libre-2.6.38.8-gnu/kernel/cgroup.c
--- linux-libre-2.6.38-gnu/kernel/cgroup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/cgroup.c	2011-06-02 21:35:11.000000000 -0400
@@ -1813,10 +1813,8 @@
 
 	/* Update the css_set linked lists if we're using them */
 	write_lock(&css_set_lock);
-	if (!list_empty(&tsk->cg_list)) {
-		list_del(&tsk->cg_list);
-		list_add(&tsk->cg_list, &newcg->tasks);
-	}
+	if (!list_empty(&tsk->cg_list))
+		list_move(&tsk->cg_list, &newcg->tasks);
 	write_unlock(&css_set_lock);
 
 	for_each_subsys(root, ss) {
@@ -3655,12 +3653,12 @@
 	spin_lock(&release_list_lock);
 	set_bit(CGRP_REMOVED, &cgrp->flags);
 	if (!list_empty(&cgrp->release_list))
-		list_del(&cgrp->release_list);
+		list_del_init(&cgrp->release_list);
 	spin_unlock(&release_list_lock);
 
 	cgroup_lock_hierarchy(cgrp->root);
 	/* delete this cgroup from parent->children */
-	list_del(&cgrp->sibling);
+	list_del_init(&cgrp->sibling);
 	cgroup_unlock_hierarchy(cgrp->root);
 
 	d = dget(cgrp->dentry);
@@ -3879,7 +3877,7 @@
 	subsys[ss->subsys_id] = NULL;
 
 	/* remove subsystem from rootnode's list of subsystems */
-	list_del(&ss->sibling);
+	list_del_init(&ss->sibling);
 
 	/*
 	 * disentangle the css from all css_sets attached to the dummytop. as
@@ -4253,7 +4251,7 @@
 	if (!list_empty(&tsk->cg_list)) {
 		write_lock(&css_set_lock);
 		if (!list_empty(&tsk->cg_list))
-			list_del(&tsk->cg_list);
+			list_del_init(&tsk->cg_list);
 		write_unlock(&css_set_lock);
 	}
 
diff -druN linux-libre-2.6.38-gnu/kernel/exit.c linux-libre-2.6.38.8-gnu/kernel/exit.c
--- linux-libre-2.6.38-gnu/kernel/exit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/exit.c	2011-06-02 21:35:11.000000000 -0400
@@ -1015,7 +1015,7 @@
 	/*
 	 * FIXME: do that only when needed, using sched_exit tracepoint
 	 */
-	flush_ptrace_hw_breakpoint(tsk);
+	ptrace_put_breakpoints(tsk);
 
 	exit_notify(tsk, group_dead);
 #ifdef CONFIG_NUMA
diff -druN linux-libre-2.6.38-gnu/kernel/futex.c linux-libre-2.6.38.8-gnu/kernel/futex.c
--- linux-libre-2.6.38-gnu/kernel/futex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/futex.c	2011-06-02 21:35:11.000000000 -0400
@@ -1886,7 +1886,7 @@
 	restart->futex.val = val;
 	restart->futex.time = abs_time->tv64;
 	restart->futex.bitset = bitset;
-	restart->futex.flags = flags;
+	restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
 
 	ret = -ERESTART_RESTARTBLOCK;
 
diff -druN linux-libre-2.6.38-gnu/kernel/perf_event.c linux-libre-2.6.38.8-gnu/kernel/perf_event.c
--- linux-libre-2.6.38-gnu/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/perf_event.c	2011-06-02 21:35:11.000000000 -0400
@@ -62,7 +62,8 @@
  */
 int sysctl_perf_event_paranoid __read_mostly = 1;
 
-int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
+/* Minimum for 512 kiB + 1 user control page */
+int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
 
 /*
  * max perf event sample rate
@@ -4567,7 +4568,7 @@
 			      struct pt_regs *regs)
 {
 	if (event->hw.state & PERF_HES_STOPPED)
-		return 0;
+		return 1;
 
 	if (regs) {
 		if (event->attr.exclude_user && user_mode(regs))
@@ -4923,6 +4924,8 @@
 				struct perf_sample_data *data,
 				struct pt_regs *regs)
 {
+	if (event->hw.state & PERF_HES_STOPPED)
+		return 0;
 	/*
 	 * All tracepoints are from kernel-space.
 	 */
@@ -5914,6 +5917,11 @@
 		goto err_alloc;
 	}
 
+	if (task) {
+		put_task_struct(task);
+		task = NULL;
+	}
+
 	/*
 	 * Look up the group leader (we will attach this event to it):
 	 */
@@ -6113,17 +6121,20 @@
 			 struct perf_event_context *child_ctx,
 			 struct task_struct *child)
 {
-	struct perf_event *parent_event;
+	if (child_event->parent) {
+		raw_spin_lock_irq(&child_ctx->lock);
+		perf_group_detach(child_event);
+		raw_spin_unlock_irq(&child_ctx->lock);
+	}
 
 	perf_event_remove_from_context(child_event);
 
-	parent_event = child_event->parent;
 	/*
-	 * It can happen that parent exits first, and has events
+	 * It can happen that the parent exits first, and has events
 	 * that are still around due to the child reference. These
-	 * events need to be zapped - but otherwise linger.
+	 * events need to be zapped.
 	 */
-	if (parent_event) {
+	if (child_event->parent) {
 		sync_child_event(child_event, child);
 		free_event(child_event);
 	}
diff -druN linux-libre-2.6.38-gnu/kernel/pid.c linux-libre-2.6.38.8-gnu/kernel/pid.c
--- linux-libre-2.6.38-gnu/kernel/pid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/pid.c	2011-06-02 21:35:11.000000000 -0400
@@ -217,11 +217,14 @@
 	return -1;
 }
 
-int next_pidmap(struct pid_namespace *pid_ns, int last)
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
 {
 	int offset;
 	struct pidmap *map, *end;
 
+	if (last >= PID_MAX_LIMIT)
+		return -1;
+
 	offset = (last + 1) & BITS_PER_PAGE_MASK;
 	map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
 	end = &pid_ns->pidmap[PIDMAP_ENTRIES];
diff -druN linux-libre-2.6.38-gnu/kernel/pm_qos_params.c linux-libre-2.6.38.8-gnu/kernel/pm_qos_params.c
--- linux-libre-2.6.38-gnu/kernel/pm_qos_params.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/pm_qos_params.c	2011-06-02 21:35:11.000000000 -0400
@@ -53,11 +53,17 @@
 	PM_QOS_MIN		/* return the smallest value */
 };
 
+/*
+ * Note: The lockless read path depends on the CPU accessing
+ * target_value atomically.  Atomic access is only guaranteed on all CPU
+ * types linux supports for 32 bit quantites
+ */
 struct pm_qos_object {
 	struct plist_head requests;
 	struct blocking_notifier_head *notifiers;
 	struct miscdevice pm_qos_power_miscdev;
 	char *name;
+	s32 target_value;	/* Do not change to 64 bit */
 	s32 default_value;
 	enum pm_qos_type type;
 };
@@ -70,7 +76,8 @@
 	.requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests, pm_qos_lock),
 	.notifiers = &cpu_dma_lat_notifier,
 	.name = "cpu_dma_latency",
-	.default_value = 2000 * USEC_PER_SEC,
+	.target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
+	.default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
 	.type = PM_QOS_MIN,
 };
 
@@ -79,7 +86,8 @@
 	.requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests, pm_qos_lock),
 	.notifiers = &network_lat_notifier,
 	.name = "network_latency",
-	.default_value = 2000 * USEC_PER_SEC,
+	.target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
+	.default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
 	.type = PM_QOS_MIN
 };
 
@@ -89,7 +97,8 @@
 	.requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests, pm_qos_lock),
 	.notifiers = &network_throughput_notifier,
 	.name = "network_throughput",
-	.default_value = 0,
+	.target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
+	.default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
 	.type = PM_QOS_MAX,
 };
 
@@ -132,6 +141,16 @@
 	}
 }
 
+static inline s32 pm_qos_read_value(struct pm_qos_object *o)
+{
+	return o->target_value;
+}
+
+static inline void pm_qos_set_value(struct pm_qos_object *o, s32 value)
+{
+	o->target_value = value;
+}
+
 static void update_target(struct pm_qos_object *o, struct plist_node *node,
 			  int del, int value)
 {
@@ -156,6 +175,7 @@
 		plist_add(node, &o->requests);
 	}
 	curr_value = pm_qos_get_value(o);
+	pm_qos_set_value(o, curr_value);
 	spin_unlock_irqrestore(&pm_qos_lock, flags);
 
 	if (prev_value != curr_value)
@@ -190,18 +210,11 @@
  * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested
  *
- * This function returns the current target value in an atomic manner.
+ * This function returns the current target value.
  */
 int pm_qos_request(int pm_qos_class)
 {
-	unsigned long flags;
-	int value;
-
-	spin_lock_irqsave(&pm_qos_lock, flags);
-	value = pm_qos_get_value(pm_qos_array[pm_qos_class]);
-	spin_unlock_irqrestore(&pm_qos_lock, flags);
-
-	return value;
+	return pm_qos_read_value(pm_qos_array[pm_qos_class]);
 }
 EXPORT_SYMBOL_GPL(pm_qos_request);
 
diff -druN linux-libre-2.6.38-gnu/kernel/power/suspend.c linux-libre-2.6.38.8-gnu/kernel/power/suspend.c
--- linux-libre-2.6.38-gnu/kernel/power/suspend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/power/suspend.c	2011-06-02 21:35:11.000000000 -0400
@@ -209,7 +209,6 @@
 			goto Close;
 	}
 	suspend_console();
-	pm_restrict_gfp_mask();
 	suspend_test_start();
 	error = dpm_suspend_start(PMSG_SUSPEND);
 	if (error) {
@@ -226,7 +225,6 @@
 	suspend_test_start();
 	dpm_resume_end(PMSG_RESUME);
 	suspend_test_finish("resume devices");
-	pm_restore_gfp_mask();
 	resume_console();
  Close:
 	if (suspend_ops->end)
@@ -287,7 +285,9 @@
 		goto Finish;
 
 	pr_debug("PM: Entering %s sleep\n", pm_states[state]);
+	pm_restrict_gfp_mask();
 	error = suspend_devices_and_enter(state);
+	pm_restore_gfp_mask();
 
  Finish:
 	pr_debug("PM: Finishing wakeup.\n");
diff -druN linux-libre-2.6.38-gnu/kernel/power/user.c linux-libre-2.6.38.8-gnu/kernel/power/user.c
--- linux-libre-2.6.38-gnu/kernel/power/user.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/power/user.c	2011-06-02 21:35:11.000000000 -0400
@@ -135,8 +135,10 @@
 	free_basic_memory_bitmaps();
 	data = filp->private_data;
 	free_all_swap_pages(data->swap);
-	if (data->frozen)
+	if (data->frozen) {
+		pm_restore_gfp_mask();
 		thaw_processes();
+	}
 	pm_notifier_call_chain(data->mode == O_RDONLY ?
 			PM_POST_HIBERNATION : PM_POST_RESTORE);
 	atomic_inc(&snapshot_device_available);
@@ -379,6 +381,7 @@
 		 * PM_HIBERNATION_PREPARE
 		 */
 		error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+		data->ready = 0;
 		break;
 
 	case SNAPSHOT_PLATFORM_SUPPORT:
diff -druN linux-libre-2.6.38-gnu/kernel/ptrace.c linux-libre-2.6.38.8-gnu/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/ptrace.c	2011-06-02 21:35:11.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <linux/regset.h>
+#include <linux/hw_breakpoint.h>
 
 
 /*
@@ -876,3 +877,19 @@
 	return ret;
 }
 #endif	/* CONFIG_COMPAT */
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+int ptrace_get_breakpoints(struct task_struct *tsk)
+{
+	if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt))
+		return 0;
+
+	return -1;
+}
+
+void ptrace_put_breakpoints(struct task_struct *tsk)
+{
+	if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt))
+		flush_ptrace_hw_breakpoint(tsk);
+}
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
diff -druN linux-libre-2.6.38-gnu/kernel/sched.c linux-libre-2.6.38.8-gnu/kernel/sched.c
--- linux-libre-2.6.38-gnu/kernel/sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/sched.c	2011-06-02 21:35:11.000000000 -0400
@@ -5572,7 +5572,7 @@
 	 * The idle tasks have their own, simple scheduling class:
 	 */
 	idle->sched_class = &idle_sched_class;
-	ftrace_graph_init_task(idle);
+	ftrace_graph_init_idle_task(idle, cpu);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/kernel/sched_fair.c linux-libre-2.6.38.8-gnu/kernel/sched_fair.c
--- linux-libre-2.6.38-gnu/kernel/sched_fair.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/sched_fair.c	2011-06-02 21:35:11.000000000 -0400
@@ -2043,21 +2043,20 @@
 	      enum cpu_idle_type idle, int *all_pinned,
 	      int *this_best_prio, struct cfs_rq *busiest_cfs_rq)
 {
-	int loops = 0, pulled = 0, pinned = 0;
+	int loops = 0, pulled = 0;
 	long rem_load_move = max_load_move;
 	struct task_struct *p, *n;
 
 	if (max_load_move == 0)
 		goto out;
 
-	pinned = 1;
-
 	list_for_each_entry_safe(p, n, &busiest_cfs_rq->tasks, se.group_node) {
 		if (loops++ > sysctl_sched_nr_migrate)
 			break;
 
 		if ((p->se.load.weight >> 1) > rem_load_move ||
-		    !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned))
+		    !can_migrate_task(p, busiest, this_cpu, sd, idle,
+				      all_pinned))
 			continue;
 
 		pull_task(busiest, p, this_rq, this_cpu);
@@ -2092,9 +2091,6 @@
 	 */
 	schedstat_add(sd, lb_gained[idle], pulled);
 
-	if (all_pinned)
-		*all_pinned = pinned;
-
 	return max_load_move - rem_load_move;
 }
 
@@ -3297,6 +3293,7 @@
 		 * still unbalanced. ld_moved simply stays zero, so it is
 		 * correctly treated as an imbalance.
 		 */
+		all_pinned = 1;
 		local_irq_save(flags);
 		double_rq_lock(this_rq, busiest);
 		ld_moved = move_tasks(this_rq, this_cpu, busiest,
diff -druN linux-libre-2.6.38-gnu/kernel/signal.c linux-libre-2.6.38.8-gnu/kernel/signal.c
--- linux-libre-2.6.38-gnu/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/signal.c	2011-06-02 21:35:11.000000000 -0400
@@ -2421,9 +2421,13 @@
 		return -EFAULT;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info.si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info.si_code >= 0 || info.si_code == SI_TKILL) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info.si_code < 0);
 		return -EPERM;
+	}
 	info.si_signo = sig;
 
 	/* POSIX.1b doesn't mention process groups.  */
@@ -2437,9 +2441,13 @@
 		return -EINVAL;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info->si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info->si_code >= 0 || info->si_code == SI_TKILL) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info->si_code < 0);
 		return -EPERM;
+	}
 	info->si_signo = sig;
 
 	return do_send_specific(tgid, pid, sig, info);
diff -druN linux-libre-2.6.38-gnu/kernel/smp.c linux-libre-2.6.38.8-gnu/kernel/smp.c
--- linux-libre-2.6.38-gnu/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/smp.c	2011-06-02 21:35:11.000000000 -0400
@@ -450,7 +450,7 @@
 {
 	struct call_function_data *data;
 	unsigned long flags;
-	int cpu, next_cpu, this_cpu = smp_processor_id();
+	int refs, cpu, next_cpu, this_cpu = smp_processor_id();
 
 	/*
 	 * Can deadlock when called with interrupts disabled.
@@ -461,7 +461,7 @@
 	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
 		     && !oops_in_progress && !early_boot_irqs_disabled);
 
-	/* So, what's a CPU they want? Ignoring this one. */
+	/* Try to fastpath.  So, what's a CPU they want? Ignoring this one. */
 	cpu = cpumask_first_and(mask, cpu_online_mask);
 	if (cpu == this_cpu)
 		cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
@@ -483,22 +483,49 @@
 
 	data = &__get_cpu_var(cfd_data);
 	csd_lock(&data->csd);
+
+	/* This BUG_ON verifies our reuse assertions and can be removed */
 	BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask));
 
+	/*
+	 * The global call function queue list add and delete are protected
+	 * by a lock, but the list is traversed without any lock, relying
+	 * on the rcu list add and delete to allow safe concurrent traversal.
+	 * We reuse the call function data without waiting for any grace
+	 * period after some other cpu removes it from the global queue.
+	 * This means a cpu might find our data block as it is being
+	 * filled out.
+	 *
+	 * We hold off the interrupt handler on the other cpu by
+	 * ordering our writes to the cpu mask vs our setting of the
+	 * refs counter.  We assert only the cpu owning the data block
+	 * will set a bit in cpumask, and each bit will only be cleared
+	 * by the subject cpu.  Each cpu must first find its bit is
+	 * set and then check that refs is set indicating the element is
+	 * ready to be processed, otherwise it must skip the entry.
+	 *
+	 * On the previous iteration refs was set to 0 by another cpu.
+	 * To avoid the use of transitivity, set the counter to 0 here
+	 * so the wmb will pair with the rmb in the interrupt handler.
+	 */
+	atomic_set(&data->refs, 0);	/* convert 3rd to 1st party write */
+
 	data->csd.func = func;
 	data->csd.info = info;
-	cpumask_and(data->cpumask, mask, cpu_online_mask);
-	cpumask_clear_cpu(this_cpu, data->cpumask);
 
-	/*
-	 * To ensure the interrupt handler gets an complete view
-	 * we order the cpumask and refs writes and order the read
-	 * of them in the interrupt handler.  In addition we may
-	 * only clear our own cpu bit from the mask.
-	 */
+	/* Ensure 0 refs is visible before mask.  Also orders func and info */
 	smp_wmb();
 
-	atomic_set(&data->refs, cpumask_weight(data->cpumask));
+	/* We rely on the "and" being processed before the store */
+	cpumask_and(data->cpumask, mask, cpu_online_mask);
+	cpumask_clear_cpu(this_cpu, data->cpumask);
+	refs = cpumask_weight(data->cpumask);
+
+	/* Some callers race with other cpus changing the passed mask */
+	if (unlikely(!refs)) {
+		csd_unlock(&data->csd);
+		return;
+	}
 
 	raw_spin_lock_irqsave(&call_function.lock, flags);
 	/*
@@ -507,6 +534,12 @@
 	 * will not miss any other list entries:
 	 */
 	list_add_rcu(&data->csd.list, &call_function.queue);
+	/*
+	 * We rely on the wmb() in list_add_rcu to complete our writes
+	 * to the cpumask before this write to refs, which indicates
+	 * data is on the list and is ready to be processed.
+	 */
+	atomic_set(&data->refs, refs);
 	raw_spin_unlock_irqrestore(&call_function.lock, flags);
 
 	/*
diff -druN linux-libre-2.6.38-gnu/kernel/sysctl.c linux-libre-2.6.38.8-gnu/kernel/sysctl.c
--- linux-libre-2.6.38-gnu/kernel/sysctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/sysctl.c	2011-06-02 21:35:11.000000000 -0400
@@ -169,6 +169,11 @@
 			       void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
+#ifdef CONFIG_PRINTK
+static int proc_dmesg_restrict(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
+
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses it's own private copy */
 static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
@@ -713,7 +718,7 @@
 		.data		= &kptr_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
+		.proc_handler	= proc_dmesg_restrict,
 		.extra1		= &zero,
 		.extra2		= &two,
 	},
@@ -2397,6 +2402,17 @@
 	return err;
 }
 
+#ifdef CONFIG_PRINTK
+static int proc_dmesg_restrict(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	if (write && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+}
+#endif
+
 struct do_proc_dointvec_minmax_conv_param {
 	int *min;
 	int *max;
diff -druN linux-libre-2.6.38-gnu/kernel/time/clocksource.c linux-libre-2.6.38.8-gnu/kernel/time/clocksource.c
--- linux-libre-2.6.38-gnu/kernel/time/clocksource.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/time/clocksource.c	2011-06-02 21:35:11.000000000 -0400
@@ -685,8 +685,8 @@
 	/* Add clocksource to the clcoksource list */
 	mutex_lock(&clocksource_mutex);
 	clocksource_enqueue(cs);
-	clocksource_select();
 	clocksource_enqueue_watchdog(cs);
+	clocksource_select();
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
@@ -706,8 +706,8 @@
 
 	mutex_lock(&clocksource_mutex);
 	clocksource_enqueue(cs);
-	clocksource_select();
 	clocksource_enqueue_watchdog(cs);
+	clocksource_select();
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/kernel/time/tick-broadcast.c linux-libre-2.6.38.8-gnu/kernel/time/tick-broadcast.c
--- linux-libre-2.6.38-gnu/kernel/time/tick-broadcast.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/time/tick-broadcast.c	2011-06-02 21:35:11.000000000 -0400
@@ -523,10 +523,11 @@
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
+	int cpu = smp_processor_id();
+
 	/* Set it up only once ! */
 	if (bc->event_handler != tick_handle_oneshot_broadcast) {
 		int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
-		int cpu = smp_processor_id();
 
 		bc->event_handler = tick_handle_oneshot_broadcast;
 		clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
@@ -552,6 +553,15 @@
 			tick_broadcast_set_event(tick_next_period, 1);
 		} else
 			bc->next_event.tv64 = KTIME_MAX;
+	} else {
+		/*
+		 * The first cpu which switches to oneshot mode sets
+		 * the bit for all other cpus which are in the general
+		 * (periodic) broadcast mask. So the bit is set and
+		 * would prevent the first broadcast enter after this
+		 * to program the bc device.
+		 */
+		tick_broadcast_clear_oneshot(cpu);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/kernel/trace/ftrace.c linux-libre-2.6.38.8-gnu/kernel/trace/ftrace.c
--- linux-libre-2.6.38-gnu/kernel/trace/ftrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/trace/ftrace.c	2011-06-02 21:35:11.000000000 -0400
@@ -2414,14 +2414,16 @@
 		ftrace_match_records(parser->buffer, parser->idx, enable);
 	}
 
-	mutex_lock(&ftrace_lock);
-	if (ftrace_start_up && ftrace_enabled)
-		ftrace_run_update_code(FTRACE_ENABLE_CALLS);
-	mutex_unlock(&ftrace_lock);
-
 	trace_parser_put(parser);
 	kfree(iter);
 
+	if (file->f_mode & FMODE_WRITE) {
+		mutex_lock(&ftrace_lock);
+		if (ftrace_start_up && ftrace_enabled)
+			ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+		mutex_unlock(&ftrace_lock);
+	}
+
 	mutex_unlock(&ftrace_regex_lock);
 	return 0;
 }
@@ -3328,7 +3330,7 @@
 	/* The cpu_boot init_task->ret_stack will never be freed */
 	for_each_online_cpu(cpu) {
 		if (!idle_task(cpu)->ret_stack)
-			ftrace_graph_init_task(idle_task(cpu));
+			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
 	}
 
 	do {
@@ -3418,6 +3420,49 @@
 	mutex_unlock(&ftrace_lock);
 }
 
+static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
+
+static void
+graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
+{
+	atomic_set(&t->tracing_graph_pause, 0);
+	atomic_set(&t->trace_overrun, 0);
+	t->ftrace_timestamp = 0;
+	/* make curr_ret_stack visable before we add the ret_stack */
+	smp_wmb();
+	t->ret_stack = ret_stack;
+}
+
+/*
+ * Allocate a return stack for the idle task. May be the first
+ * time through, or it may be done by CPU hotplug online.
+ */
+void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
+{
+	t->curr_ret_stack = -1;
+	/*
+	 * The idle task has no parent, it either has its own
+	 * stack or no stack at all.
+	 */
+	if (t->ret_stack)
+		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
+
+	if (ftrace_graph_active) {
+		struct ftrace_ret_stack *ret_stack;
+
+		ret_stack = per_cpu(idle_ret_stack, cpu);
+		if (!ret_stack) {
+			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
+					    * sizeof(struct ftrace_ret_stack),
+					    GFP_KERNEL);
+			if (!ret_stack)
+				return;
+			per_cpu(idle_ret_stack, cpu) = ret_stack;
+		}
+		graph_init_task(t, ret_stack);
+	}
+}
+
 /* Allocate a return stack for newly created task */
 void ftrace_graph_init_task(struct task_struct *t)
 {
@@ -3433,12 +3478,7 @@
 				GFP_KERNEL);
 		if (!ret_stack)
 			return;
-		atomic_set(&t->tracing_graph_pause, 0);
-		atomic_set(&t->trace_overrun, 0);
-		t->ftrace_timestamp = 0;
-		/* make curr_ret_stack visable before we add the ret_stack */
-		smp_wmb();
-		t->ret_stack = ret_stack;
+		graph_init_task(t, ret_stack);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/kernel/workqueue.c linux-libre-2.6.38.8-gnu/kernel/workqueue.c
--- linux-libre-2.6.38-gnu/kernel/workqueue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/kernel/workqueue.c	2011-06-02 21:35:11.000000000 -0400
@@ -1283,8 +1283,14 @@
 			return true;
 		spin_unlock_irq(&gcwq->lock);
 
-		/* CPU has come up inbetween, retry migration */
+		/*
+		 * We've raced with CPU hot[un]plug.  Give it a breather
+		 * and retry migration.  cond_resched() is required here;
+		 * otherwise, we might deadlock against cpu_stop trying to
+		 * bring down the CPU on non-preemptive kernel.
+		 */
 		cpu_relax();
+		cond_resched();
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/lib/flex_array.c linux-libre-2.6.38.8-gnu/lib/flex_array.c
--- linux-libre-2.6.38-gnu/lib/flex_array.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/flex_array.c	2011-06-02 21:35:11.000000000 -0400
@@ -232,10 +232,10 @@
 
 /**
  * flex_array_prealloc - guarantee that array space exists
- * @fa:		the flex array for which to preallocate parts
- * @start:	index of first array element for which space is allocated
- * @end:	index of last (inclusive) element for which space is allocated
- * @flags:	page allocation flags
+ * @fa:			the flex array for which to preallocate parts
+ * @start:		index of first array element for which space is allocated
+ * @nr_elements:	number of elements for which space is allocated
+ * @flags:		page allocation flags
  *
  * This will guarantee that no future calls to flex_array_put()
  * will allocate memory.  It can be used if you are expecting to
@@ -245,14 +245,24 @@
  * Locking must be provided by the caller.
  */
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-			unsigned int end, gfp_t flags)
+			unsigned int nr_elements, gfp_t flags)
 {
 	int start_part;
 	int end_part;
 	int part_nr;
+	unsigned int end;
 	struct flex_array_part *part;
 
-	if (start >= fa->total_nr_elements || end >= fa->total_nr_elements)
+	if (!start && !nr_elements)
+		return 0;
+	if (start >= fa->total_nr_elements)
+		return -ENOSPC;
+	if (!nr_elements)
+		return 0;
+
+	end = start + nr_elements - 1;
+
+	if (end >= fa->total_nr_elements)
 		return -ENOSPC;
 	if (elements_fit_in_base(fa))
 		return 0;
@@ -343,6 +353,8 @@
 	int part_nr;
 	int ret = 0;
 
+	if (!fa->total_nr_elements)
+		return 0;
 	if (elements_fit_in_base(fa))
 		return ret;
 	for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) {
diff -druN linux-libre-2.6.38-gnu/lib/Kconfig.debug linux-libre-2.6.38.8-gnu/lib/Kconfig.debug
--- linux-libre-2.6.38-gnu/lib/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/Kconfig.debug	2011-06-02 21:35:11.000000000 -0400
@@ -1236,3 +1236,6 @@
 source "lib/Kconfig.kgdb"
 
 source "lib/Kconfig.kmemcheck"
+
+config TEST_KSTRTOX
+	tristate "Test kstrto*() family of functions at runtime"
diff -druN linux-libre-2.6.38-gnu/lib/kstrtox.c linux-libre-2.6.38.8-gnu/lib/kstrtox.c
--- linux-libre-2.6.38-gnu/lib/kstrtox.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38.8-gnu/lib/kstrtox.c	2011-06-02 21:35:11.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ * Convert integer string representation to an integer.
+ * If an integer doesn't fit into specified type, -E is returned.
+ *
+ * Integer starts with optional sign.
+ * kstrtou*() functions do not accept sign "-".
+ *
+ * Radix 0 means autodetection: leading "0x" implies radix 16,
+ * leading "0" implies radix 8, otherwise radix is 10.
+ * Autodetection hints work after optional sign, but not before.
+ *
+ * If -E is returned, result is not touched.
+ */
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+static inline char _tolower(const char c)
+{
+	return c | 0x20;
+}
+
+static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+	unsigned long long acc;
+	int ok;
+
+	if (base == 0) {
+		if (s[0] == '0') {
+			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
+				base = 16;
+			else
+				base = 8;
+		} else
+			base = 10;
+	}
+	if (base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
+		s += 2;
+
+	acc = 0;
+	ok = 0;
+	while (*s) {
+		unsigned int val;
+
+		if ('0' <= *s && *s <= '9')
+			val = *s - '0';
+		else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
+			val = _tolower(*s) - 'a' + 10;
+		else if (*s == '\n') {
+			if (*(s + 1) == '\0')
+				break;
+			else
+				return -EINVAL;
+		} else
+			return -EINVAL;
+
+		if (val >= base)
+			return -EINVAL;
+		if (acc > div_u64(ULLONG_MAX - val, base))
+			return -ERANGE;
+		acc = acc * base + val;
+		ok = 1;
+
+		s++;
+	}
+	if (!ok)
+		return -EINVAL;
+	*res = acc;
+	return 0;
+}
+
+int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+	if (s[0] == '+')
+		s++;
+	return _kstrtoull(s, base, res);
+}
+EXPORT_SYMBOL(kstrtoull);
+
+int kstrtoll(const char *s, unsigned int base, long long *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	if (s[0] == '-') {
+		rv = _kstrtoull(s + 1, base, &tmp);
+		if (rv < 0)
+			return rv;
+		if ((long long)(-tmp) >= 0)
+			return -ERANGE;
+		*res = -tmp;
+	} else {
+		rv = kstrtoull(s, base, &tmp);
+		if (rv < 0)
+			return rv;
+		if ((long long)tmp < 0)
+			return -ERANGE;
+		*res = tmp;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(kstrtoll);
+
+/* Internal, do not use. */
+int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(unsigned long)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(_kstrtoul);
+
+/* Internal, do not use. */
+int _kstrtol(const char *s, unsigned int base, long *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(long)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(_kstrtol);
+
+int kstrtouint(const char *s, unsigned int base, unsigned int *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(unsigned int)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtouint);
+
+int kstrtoint(const char *s, unsigned int base, int *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(int)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtoint);
+
+int kstrtou16(const char *s, unsigned int base, u16 *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(u16)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtou16);
+
+int kstrtos16(const char *s, unsigned int base, s16 *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(s16)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtos16);
+
+int kstrtou8(const char *s, unsigned int base, u8 *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(u8)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtou8);
+
+int kstrtos8(const char *s, unsigned int base, s8 *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(s8)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtos8);
diff -druN linux-libre-2.6.38-gnu/lib/locking-selftest.c linux-libre-2.6.38.8-gnu/lib/locking-selftest.c
--- linux-libre-2.6.38-gnu/lib/locking-selftest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/locking-selftest.c	2011-06-02 21:35:11.000000000 -0400
@@ -144,7 +144,7 @@
 
 #define HARDIRQ_ENTER()				\
 	local_irq_disable();			\
-	irq_enter();				\
+	__irq_enter();				\
 	WARN_ON(!in_irq());
 
 #define HARDIRQ_EXIT()				\
diff -druN linux-libre-2.6.38-gnu/lib/Makefile linux-libre-2.6.38.8-gnu/lib/Makefile
--- linux-libre-2.6.38-gnu/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -22,6 +22,8 @@
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
 	 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
 	 string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o
+obj-y += kstrtox.o
+obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff -druN linux-libre-2.6.38-gnu/lib/test-kstrtox.c linux-libre-2.6.38.8-gnu/lib/test-kstrtox.c
--- linux-libre-2.6.38-gnu/lib/test-kstrtox.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38.8-gnu/lib/test-kstrtox.c	2011-06-02 21:35:11.000000000 -0400
@@ -0,0 +1,739 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define for_each_test(i, test)	\
+	for (i = 0; i < sizeof(test) / sizeof(test[0]); i++)
+
+struct test_fail {
+	const char *str;
+	unsigned int base;
+};
+
+#define DEFINE_TEST_FAIL(test)	\
+	const struct test_fail test[] __initdata
+
+#define DECLARE_TEST_OK(type, test_type)	\
+	test_type {				\
+		const char *str;		\
+		unsigned int base;		\
+		type expected_res;		\
+	}
+
+#define DEFINE_TEST_OK(type, test)	\
+	const type test[] __initdata
+
+#define TEST_FAIL(fn, type, fmt, test)					\
+{									\
+	unsigned int i;							\
+									\
+	for_each_test(i, test) {					\
+		const struct test_fail *t = &test[i];			\
+		type tmp;						\
+		int rv;							\
+									\
+		tmp = 0;						\
+		rv = fn(t->str, t->base, &tmp);				\
+		if (rv >= 0) {						\
+			WARN(1, "str '%s', base %u, expected -E, got %d/" fmt "\n",	\
+				t->str, t->base, rv, tmp);		\
+			continue;					\
+		}							\
+	}								\
+}
+
+#define TEST_OK(fn, type, fmt, test)					\
+{									\
+	unsigned int i;							\
+									\
+	for_each_test(i, test) {					\
+		const typeof(test[0]) *t = &test[i];			\
+		type res;						\
+		int rv;							\
+									\
+		rv = fn(t->str, t->base, &res);				\
+		if (rv != 0) {						\
+			WARN(1, "str '%s', base %u, expected 0/" fmt ", got %d\n",	\
+				t->str, t->base, t->expected_res, rv);	\
+			continue;					\
+		}							\
+		if (res != t->expected_res) {				\
+			WARN(1, "str '%s', base %u, expected " fmt ", got " fmt "\n",	\
+				t->str, t->base, t->expected_res, res);	\
+			continue;					\
+		}							\
+	}								\
+}
+
+static void __init test_kstrtoull_ok(void)
+{
+	DECLARE_TEST_OK(unsigned long long, struct test_ull);
+	static DEFINE_TEST_OK(struct test_ull, test_ull_ok) = {
+		{"0",	10,	0ULL},
+		{"1",	10,	1ULL},
+		{"127",	10,	127ULL},
+		{"128",	10,	128ULL},
+		{"129",	10,	129ULL},
+		{"255",	10,	255ULL},
+		{"256",	10,	256ULL},
+		{"257",	10,	257ULL},
+		{"32767",	10,	32767ULL},
+		{"32768",	10,	32768ULL},
+		{"32769",	10,	32769ULL},
+		{"65535",	10,	65535ULL},
+		{"65536",	10,	65536ULL},
+		{"65537",	10,	65537ULL},
+		{"2147483647",	10,	2147483647ULL},
+		{"2147483648",	10,	2147483648ULL},
+		{"2147483649",	10,	2147483649ULL},
+		{"4294967295",	10,	4294967295ULL},
+		{"4294967296",	10,	4294967296ULL},
+		{"4294967297",	10,	4294967297ULL},
+		{"9223372036854775807",	10,	9223372036854775807ULL},
+		{"9223372036854775808",	10,	9223372036854775808ULL},
+		{"9223372036854775809",	10,	9223372036854775809ULL},
+		{"18446744073709551614",	10,	18446744073709551614ULL},
+		{"18446744073709551615",	10,	18446744073709551615ULL},
+
+		{"00",		8,	00ULL},
+		{"01",		8,	01ULL},
+		{"0177",	8,	0177ULL},
+		{"0200",	8,	0200ULL},
+		{"0201",	8,	0201ULL},
+		{"0377",	8,	0377ULL},
+		{"0400",	8,	0400ULL},
+		{"0401",	8,	0401ULL},
+		{"077777",	8,	077777ULL},
+		{"0100000",	8,	0100000ULL},
+		{"0100001",	8,	0100001ULL},
+		{"0177777",	8,	0177777ULL},
+		{"0200000",	8,	0200000ULL},
+		{"0200001",	8,	0200001ULL},
+		{"017777777777",	8,	017777777777ULL},
+		{"020000000000",	8,	020000000000ULL},
+		{"020000000001",	8,	020000000001ULL},
+		{"037777777777",	8,	037777777777ULL},
+		{"040000000000",	8,	040000000000ULL},
+		{"040000000001",	8,	040000000001ULL},
+		{"0777777777777777777777",	8,	0777777777777777777777ULL},
+		{"01000000000000000000000",	8,	01000000000000000000000ULL},
+		{"01000000000000000000001",	8,	01000000000000000000001ULL},
+		{"01777777777777777777776",	8,	01777777777777777777776ULL},
+		{"01777777777777777777777",	8,	01777777777777777777777ULL},
+
+		{"0x0",		16,	0x0ULL},
+		{"0x1",		16,	0x1ULL},
+		{"0x7f",	16,	0x7fULL},
+		{"0x80",	16,	0x80ULL},
+		{"0x81",	16,	0x81ULL},
+		{"0xff",	16,	0xffULL},
+		{"0x100",	16,	0x100ULL},
+		{"0x101",	16,	0x101ULL},
+		{"0x7fff",	16,	0x7fffULL},
+		{"0x8000",	16,	0x8000ULL},
+		{"0x8001",	16,	0x8001ULL},
+		{"0xffff",	16,	0xffffULL},
+		{"0x10000",	16,	0x10000ULL},
+		{"0x10001",	16,	0x10001ULL},
+		{"0x7fffffff",	16,	0x7fffffffULL},
+		{"0x80000000",	16,	0x80000000ULL},
+		{"0x80000001",	16,	0x80000001ULL},
+		{"0xffffffff",	16,	0xffffffffULL},
+		{"0x100000000",	16,	0x100000000ULL},
+		{"0x100000001",	16,	0x100000001ULL},
+		{"0x7fffffffffffffff",	16,	0x7fffffffffffffffULL},
+		{"0x8000000000000000",	16,	0x8000000000000000ULL},
+		{"0x8000000000000001",	16,	0x8000000000000001ULL},
+		{"0xfffffffffffffffe",	16,	0xfffffffffffffffeULL},
+		{"0xffffffffffffffff",	16,	0xffffffffffffffffULL},
+
+		{"0\n",	0,	0ULL},
+	};
+	TEST_OK(kstrtoull, unsigned long long, "%llu", test_ull_ok);
+}
+
+static void __init test_kstrtoull_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_ull_fail) = {
+		{"",	0},
+		{"",	8},
+		{"",	10},
+		{"",	16},
+		{"\n",	0},
+		{"\n",	8},
+		{"\n",	10},
+		{"\n",	16},
+		{"\n0",	0},
+		{"\n0",	8},
+		{"\n0",	10},
+		{"\n0",	16},
+		{"+",	0},
+		{"+",	8},
+		{"+",	10},
+		{"+",	16},
+		{"-",	0},
+		{"-",	8},
+		{"-",	10},
+		{"-",	16},
+		{"0x",	0},
+		{"0x",	16},
+		{"0X",	0},
+		{"0X",	16},
+		{"0 ",	0},
+		{"1+",	0},
+		{"1-",	0},
+		{" 2",	0},
+		/* base autodetection */
+		{"0x0z",	0},
+		{"0z",		0},
+		{"a",		0},
+		/* digit >= base */
+		{"2",	2},
+		{"8",	8},
+		{"a",	10},
+		{"A",	10},
+		{"g",	16},
+		{"G",	16},
+		/* overflow */
+		{"10000000000000000000000000000000000000000000000000000000000000000",	2},
+		{"2000000000000000000000",	8},
+		{"18446744073709551616",	10},
+		{"10000000000000000",	16},
+		/* negative */
+		{"-0", 0},
+		{"-0", 8},
+		{"-0", 10},
+		{"-0", 16},
+		{"-1", 0},
+		{"-1", 8},
+		{"-1", 10},
+		{"-1", 16},
+		/* sign is first character if any */
+		{"-+1", 0},
+		{"-+1", 8},
+		{"-+1", 10},
+		{"-+1", 16},
+		/* nothing after \n */
+		{"0\n0", 0},
+		{"0\n0", 8},
+		{"0\n0", 10},
+		{"0\n0", 16},
+		{"0\n+", 0},
+		{"0\n+", 8},
+		{"0\n+", 10},
+		{"0\n+", 16},
+		{"0\n-", 0},
+		{"0\n-", 8},
+		{"0\n-", 10},
+		{"0\n-", 16},
+		{"0\n ", 0},
+		{"0\n ", 8},
+		{"0\n ", 10},
+		{"0\n ", 16},
+	};
+	TEST_FAIL(kstrtoull, unsigned long long, "%llu", test_ull_fail);
+}
+
+static void __init test_kstrtoll_ok(void)
+{
+	DECLARE_TEST_OK(long long, struct test_ll);
+	static DEFINE_TEST_OK(struct test_ll, test_ll_ok) = {
+		{"0",	10,	0LL},
+		{"1",	10,	1LL},
+		{"127",	10,	127LL},
+		{"128",	10,	128LL},
+		{"129",	10,	129LL},
+		{"255",	10,	255LL},
+		{"256",	10,	256LL},
+		{"257",	10,	257LL},
+		{"32767",	10,	32767LL},
+		{"32768",	10,	32768LL},
+		{"32769",	10,	32769LL},
+		{"65535",	10,	65535LL},
+		{"65536",	10,	65536LL},
+		{"65537",	10,	65537LL},
+		{"2147483647",	10,	2147483647LL},
+		{"2147483648",	10,	2147483648LL},
+		{"2147483649",	10,	2147483649LL},
+		{"4294967295",	10,	4294967295LL},
+		{"4294967296",	10,	4294967296LL},
+		{"4294967297",	10,	4294967297LL},
+		{"9223372036854775807",	10,	9223372036854775807LL},
+
+		{"-1",	10,	-1LL},
+		{"-2",	10,	-2LL},
+		{"-9223372036854775808",	10,	LLONG_MIN},
+	};
+	TEST_OK(kstrtoll, long long, "%lld", test_ll_ok);
+}
+
+static void __init test_kstrtoll_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_ll_fail) = {
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"-9223372036854775809",	10},
+		{"-18446744073709551614",	10},
+		{"-18446744073709551615",	10},
+		/* negative zero isn't an integer in Linux */
+		{"-0",	0},
+		{"-0",	8},
+		{"-0",	10},
+		{"-0",	16},
+		/* sign is first character if any */
+		{"-+1", 0},
+		{"-+1", 8},
+		{"-+1", 10},
+		{"-+1", 16},
+	};
+	TEST_FAIL(kstrtoll, long long, "%lld", test_ll_fail);
+}
+
+static void __init test_kstrtou64_ok(void)
+{
+	DECLARE_TEST_OK(u64, struct test_u64);
+	static DEFINE_TEST_OK(struct test_u64, test_u64_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+		{"4294967296",	10,	4294967296},
+		{"4294967297",	10,	4294967297},
+		{"9223372036854775806",	10,	9223372036854775806ULL},
+		{"9223372036854775807",	10,	9223372036854775807ULL},
+		{"9223372036854775808",	10,	9223372036854775808ULL},
+		{"9223372036854775809",	10,	9223372036854775809ULL},
+		{"18446744073709551614",	10,	18446744073709551614ULL},
+		{"18446744073709551615",	10,	18446744073709551615ULL},
+	};
+	TEST_OK(kstrtou64, u64, "%llu", test_u64_ok);
+}
+
+static void __init test_kstrtou64_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u64_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou64, u64, "%llu", test_u64_fail);
+}
+
+static void __init test_kstrtos64_ok(void)
+{
+	DECLARE_TEST_OK(s64, struct test_s64);
+	static DEFINE_TEST_OK(struct test_s64, test_s64_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+		{"4294967296",	10,	4294967296},
+		{"4294967297",	10,	4294967297},
+		{"9223372036854775806",	10,	9223372036854775806LL},
+		{"9223372036854775807",	10,	9223372036854775807LL},
+	};
+	TEST_OK(kstrtos64, s64, "%lld", test_s64_ok);
+}
+
+static void __init test_kstrtos64_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s64_fail) = {
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos64, s64, "%lld", test_s64_fail);
+}
+
+static void __init test_kstrtou32_ok(void)
+{
+	DECLARE_TEST_OK(u32, struct test_u32);
+	static DEFINE_TEST_OK(struct test_u32, test_u32_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+	};
+	TEST_OK(kstrtou32, u32, "%u", test_u32_ok);
+}
+
+static void __init test_kstrtou32_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u32_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou32, u32, "%u", test_u32_fail);
+}
+
+static void __init test_kstrtos32_ok(void)
+{
+	DECLARE_TEST_OK(s32, struct test_s32);
+	static DEFINE_TEST_OK(struct test_s32, test_s32_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+	};
+	TEST_OK(kstrtos32, s32, "%d", test_s32_ok);
+}
+
+static void __init test_kstrtos32_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s32_fail) = {
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos32, s32, "%d", test_s32_fail);
+}
+
+static void __init test_kstrtou16_ok(void)
+{
+	DECLARE_TEST_OK(u16, struct test_u16);
+	static DEFINE_TEST_OK(struct test_u16, test_u16_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+	};
+	TEST_OK(kstrtou16, u16, "%hu", test_u16_ok);
+}
+
+static void __init test_kstrtou16_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u16_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou16, u16, "%hu", test_u16_fail);
+}
+
+static void __init test_kstrtos16_ok(void)
+{
+	DECLARE_TEST_OK(s16, struct test_s16);
+	static DEFINE_TEST_OK(struct test_s16, test_s16_ok) = {
+		{"-130",	10,	-130},
+		{"-129",	10,	-129},
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+	};
+	TEST_OK(kstrtos16, s16, "%hd", test_s16_ok);
+}
+
+static void __init test_kstrtos16_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s16_fail) = {
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos16, s16, "%hd", test_s16_fail);
+}
+
+static void __init test_kstrtou8_ok(void)
+{
+	DECLARE_TEST_OK(u8, struct test_u8);
+	static DEFINE_TEST_OK(struct test_u8, test_u8_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+	};
+	TEST_OK(kstrtou8, u8, "%hhu", test_u8_ok);
+}
+
+static void __init test_kstrtou8_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u8_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"256",	10},
+		{"257",	10},
+		{"32766",	10},
+		{"32767",	10},
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou8, u8, "%hhu", test_u8_fail);
+}
+
+static void __init test_kstrtos8_ok(void)
+{
+	DECLARE_TEST_OK(s8, struct test_s8);
+	static DEFINE_TEST_OK(struct test_s8, test_s8_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+	};
+	TEST_OK(kstrtos8, s8, "%hhd", test_s8_ok);
+}
+
+static void __init test_kstrtos8_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s8_fail) = {
+		{"-130",	10},
+		{"-129",	10},
+		{"128",	10},
+		{"129",	10},
+		{"254",	10},
+		{"255",	10},
+		{"256",	10},
+		{"257",	10},
+		{"32766",	10},
+		{"32767",	10},
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos8, s8, "%hhd", test_s8_fail);
+}
+
+static int __init test_kstrtox_init(void)
+{
+	test_kstrtoull_ok();
+	test_kstrtoull_fail();
+	test_kstrtoll_ok();
+	test_kstrtoll_fail();
+
+	test_kstrtou64_ok();
+	test_kstrtou64_fail();
+	test_kstrtos64_ok();
+	test_kstrtos64_fail();
+
+	test_kstrtou32_ok();
+	test_kstrtou32_fail();
+	test_kstrtos32_ok();
+	test_kstrtos32_fail();
+
+	test_kstrtou16_ok();
+	test_kstrtou16_fail();
+	test_kstrtos16_ok();
+	test_kstrtos16_fail();
+
+	test_kstrtou8_ok();
+	test_kstrtou8_fail();
+	test_kstrtos8_ok();
+	test_kstrtos8_fail();
+	return -EINVAL;
+}
+module_init(test_kstrtox_init);
+MODULE_LICENSE("Dual BSD/GPL");
diff -druN linux-libre-2.6.38-gnu/lib/vsprintf.c linux-libre-2.6.38.8-gnu/lib/vsprintf.c
--- linux-libre-2.6.38-gnu/lib/vsprintf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/vsprintf.c	2011-06-02 21:35:11.000000000 -0400
@@ -120,147 +120,6 @@
 }
 EXPORT_SYMBOL(simple_strtoll);
 
-/**
- * strict_strtoul - convert a string to an unsigned long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoul converts a string to an unsigned long only if the
- * string is really an unsigned long string, any string containing
- * any invalid char at the tail will be rejected and -EINVAL is returned,
- * only a newline char at the tail is acceptible because people generally
- * change a module parameter in the following way:
- *
- * 	echo 1024 > /sys/module/e1000/parameters/copybreak
- *
- * echo will append a newline to the tail.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- *
- * simple_strtoul just ignores the successive invalid characters and
- * return the converted value of prefix part of the string.
- */
-int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
-{
-	char *tail;
-	unsigned long val;
-
-	*res = 0;
-	if (!*cp)
-		return -EINVAL;
-
-	val = simple_strtoul(cp, &tail, base);
-	if (tail == cp)
-		return -EINVAL;
-
-	if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
-		*res = val;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(strict_strtoul);
-
-/**
- * strict_strtol - convert a string to a long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtol is similiar to strict_strtoul, but it allows the first
- * character of a string is '-'.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- */
-int strict_strtol(const char *cp, unsigned int base, long *res)
-{
-	int ret;
-	if (*cp == '-') {
-		ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
-		if (!ret)
-			*res = -(*res);
-	} else {
-		ret = strict_strtoul(cp, base, (unsigned long *)res);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(strict_strtol);
-
-/**
- * strict_strtoull - convert a string to an unsigned long long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoull converts a string to an unsigned long long only if the
- * string is really an unsigned long long string, any string containing
- * any invalid char at the tail will be rejected and -EINVAL is returned,
- * only a newline char at the tail is acceptible because people generally
- * change a module parameter in the following way:
- *
- * 	echo 1024 > /sys/module/e1000/parameters/copybreak
- *
- * echo will append a newline to the tail of the string.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- *
- * simple_strtoull just ignores the successive invalid characters and
- * return the converted value of prefix part of the string.
- */
-int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
-{
-	char *tail;
-	unsigned long long val;
-
-	*res = 0;
-	if (!*cp)
-		return -EINVAL;
-
-	val = simple_strtoull(cp, &tail, base);
-	if (tail == cp)
-		return -EINVAL;
-	if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
-		*res = val;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(strict_strtoull);
-
-/**
- * strict_strtoll - convert a string to a long long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoll is similiar to strict_strtoull, but it allows the first
- * character of a string is '-'.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- */
-int strict_strtoll(const char *cp, unsigned int base, long long *res)
-{
-	int ret;
-	if (*cp == '-') {
-		ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
-		if (!ret)
-			*res = -(*res);
-	} else {
-		ret = strict_strtoull(cp, base, (unsigned long long *)res);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(strict_strtoll);
-
 static noinline_for_stack
 int skip_atoi(const char **s)
 {
diff -druN linux-libre-2.6.38-gnu/lib/xz/xz_dec_lzma2.c linux-libre-2.6.38.8-gnu/lib/xz/xz_dec_lzma2.c
--- linux-libre-2.6.38-gnu/lib/xz/xz_dec_lzma2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/lib/xz/xz_dec_lzma2.c	2011-06-02 21:35:11.000000000 -0400
@@ -969,6 +969,9 @@
 			 */
 			tmp = b->in[b->in_pos++];
 
+			if (tmp == 0x00)
+				return XZ_STREAM_END;
+
 			if (tmp >= 0xE0 || tmp == 0x01) {
 				s->lzma2.need_props = true;
 				s->lzma2.need_dict_reset = false;
@@ -1001,9 +1004,6 @@
 						lzma_reset(s);
 				}
 			} else {
-				if (tmp == 0x00)
-					return XZ_STREAM_END;
-
 				if (tmp > 0x02)
 					return XZ_DATA_ERROR;
 
diff -druN linux-libre-2.6.38-gnu/MAINTAINERS linux-libre-2.6.38.8-gnu/MAINTAINERS
--- linux-libre-2.6.38-gnu/MAINTAINERS	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/MAINTAINERS	2011-06-02 21:35:11.000000000 -0400
@@ -5944,7 +5944,6 @@
 
 STABLE BRANCH
 M:	Greg Kroah-Hartman <greg@kroah.com>
-M:	Chris Wright <chrisw@sous-sol.org>
 L:	stable@kernel.org
 S:	Maintained
 
diff -druN linux-libre-2.6.38-gnu/Makefile linux-libre-2.6.38.8-gnu/Makefile
--- linux-libre-2.6.38-gnu/Makefile	2012-03-24 00:59:05.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/Makefile	2012-03-25 07:08:39.000000000 -0400
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 38
-EXTRAVERSION =-gnu
+EXTRAVERSION = .8-gnu
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
@@ -1368,7 +1368,7 @@
 clean: $(clean-dirs)
 	$(call cmd,rmdirs)
 	$(call cmd,rmfiles)
-	@find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+	@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
 		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
 		-o -name '*.symtypes' -o -name 'modules.order' \
diff -druN linux-libre-2.6.38-gnu/mm/backing-dev.c linux-libre-2.6.38.8-gnu/mm/backing-dev.c
--- linux-libre-2.6.38-gnu/mm/backing-dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/backing-dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -604,7 +604,7 @@
 	spin_lock(&sb_lock);
 	list_for_each_entry(sb, &super_blocks, s_list) {
 		if (sb->s_bdi == bdi)
-			sb->s_bdi = NULL;
+			sb->s_bdi = &default_backing_dev_info;
 	}
 	spin_unlock(&sb_lock);
 }
diff -druN linux-libre-2.6.38-gnu/mm/compaction.c linux-libre-2.6.38.8-gnu/mm/compaction.c
--- linux-libre-2.6.38-gnu/mm/compaction.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/compaction.c	2011-06-02 21:35:11.000000000 -0400
@@ -42,8 +42,6 @@
 	unsigned int order;		/* order a direct compactor needs */
 	int migratetype;		/* MOVABLE, RECLAIMABLE etc */
 	struct zone *zone;
-
-	int compact_mode;
 };
 
 static unsigned long release_freepages(struct list_head *freelist)
@@ -397,10 +395,7 @@
 		return COMPACT_COMPLETE;
 
 	/* Compaction run is not finished if the watermark is not met */
-	if (cc->compact_mode != COMPACT_MODE_KSWAPD)
-		watermark = low_wmark_pages(zone);
-	else
-		watermark = high_wmark_pages(zone);
+	watermark = low_wmark_pages(zone);
 	watermark += (1 << cc->order);
 
 	if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
@@ -413,15 +408,6 @@
 	if (cc->order == -1)
 		return COMPACT_CONTINUE;
 
-	/*
-	 * Generating only one page of the right order is not enough
-	 * for kswapd, we must continue until we're above the high
-	 * watermark as a pool for high order GFP_ATOMIC allocations
-	 * too.
-	 */
-	if (cc->compact_mode == COMPACT_MODE_KSWAPD)
-		return COMPACT_CONTINUE;
-
 	/* Direct compactor: Is a suitable page free? */
 	for (order = cc->order; order < MAX_ORDER; order++) {
 		/* Job done if page is free of the right migratetype */
@@ -543,8 +529,7 @@
 
 unsigned long compact_zone_order(struct zone *zone,
 				 int order, gfp_t gfp_mask,
-				 bool sync,
-				 int compact_mode)
+				 bool sync)
 {
 	struct compact_control cc = {
 		.nr_freepages = 0,
@@ -553,7 +538,6 @@
 		.migratetype = allocflags_to_migratetype(gfp_mask),
 		.zone = zone,
 		.sync = sync,
-		.compact_mode = compact_mode,
 	};
 	INIT_LIST_HEAD(&cc.freepages);
 	INIT_LIST_HEAD(&cc.migratepages);
@@ -599,8 +583,7 @@
 								nodemask) {
 		int status;
 
-		status = compact_zone_order(zone, order, gfp_mask, sync,
-					    COMPACT_MODE_DIRECT_RECLAIM);
+		status = compact_zone_order(zone, order, gfp_mask, sync);
 		rc = max(status, rc);
 
 		/* If a normal allocation would succeed, stop compacting */
@@ -631,7 +614,6 @@
 			.nr_freepages = 0,
 			.nr_migratepages = 0,
 			.order = -1,
-			.compact_mode = COMPACT_MODE_DIRECT_RECLAIM,
 		};
 
 		zone = &pgdat->node_zones[zoneid];
diff -druN linux-libre-2.6.38-gnu/mm/huge_memory.c linux-libre-2.6.38.8-gnu/mm/huge_memory.c
--- linux-libre-2.6.38-gnu/mm/huge_memory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/huge_memory.c	2011-06-02 21:35:11.000000000 -0400
@@ -244,24 +244,28 @@
 				struct kobj_attribute *attr, char *buf,
 				enum transparent_hugepage_flag flag)
 {
-	if (test_bit(flag, &transparent_hugepage_flags))
-		return sprintf(buf, "[yes] no\n");
-	else
-		return sprintf(buf, "yes [no]\n");
+	return sprintf(buf, "%d\n",
+		       !!test_bit(flag, &transparent_hugepage_flags));
 }
+
 static ssize_t single_flag_store(struct kobject *kobj,
 				 struct kobj_attribute *attr,
 				 const char *buf, size_t count,
 				 enum transparent_hugepage_flag flag)
 {
-	if (!memcmp("yes", buf,
-		    min(sizeof("yes")-1, count))) {
+	unsigned long value;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &value);
+	if (ret < 0)
+		return ret;
+	if (value > 1)
+		return -EINVAL;
+
+	if (value)
 		set_bit(flag, &transparent_hugepage_flags);
-	} else if (!memcmp("no", buf,
-			   min(sizeof("no")-1, count))) {
+	else
 		clear_bit(flag, &transparent_hugepage_flags);
-	} else
-		return -EINVAL;
 
 	return count;
 }
@@ -1396,6 +1400,9 @@
 	return ret;
 }
 
+#define VM_NO_THP (VM_SPECIAL|VM_INSERTPAGE|VM_MIXEDMAP|VM_SAO| \
+		   VM_HUGETLB|VM_SHARED|VM_MAYSHARE)
+
 int hugepage_madvise(struct vm_area_struct *vma,
 		     unsigned long *vm_flags, int advice)
 {
@@ -1404,11 +1411,7 @@
 		/*
 		 * Be somewhat over-protective like KSM for now!
 		 */
-		if (*vm_flags & (VM_HUGEPAGE |
-				 VM_SHARED   | VM_MAYSHARE   |
-				 VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-				 VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-				 VM_MIXEDMAP | VM_SAO))
+		if (*vm_flags & (VM_HUGEPAGE | VM_NO_THP))
 			return -EINVAL;
 		*vm_flags &= ~VM_NOHUGEPAGE;
 		*vm_flags |= VM_HUGEPAGE;
@@ -1424,11 +1427,7 @@
 		/*
 		 * Be somewhat over-protective like KSM for now!
 		 */
-		if (*vm_flags & (VM_NOHUGEPAGE |
-				 VM_SHARED   | VM_MAYSHARE   |
-				 VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-				 VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-				 VM_MIXEDMAP | VM_SAO))
+		if (*vm_flags & (VM_NOHUGEPAGE | VM_NO_THP))
 			return -EINVAL;
 		*vm_flags &= ~VM_HUGEPAGE;
 		*vm_flags |= VM_NOHUGEPAGE;
@@ -1562,10 +1561,14 @@
 		 * page fault if needed.
 		 */
 		return 0;
-	if (vma->vm_file || vma->vm_ops)
+	if (vma->vm_ops)
 		/* khugepaged not yet working on file or special mappings */
 		return 0;
-	VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+	/*
+	 * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+	 * true too, verify it here.
+	 */
+	VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
 	hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
 	hend = vma->vm_end & HPAGE_PMD_MASK;
 	if (hstart < hend)
@@ -1814,12 +1817,15 @@
 	    (vma->vm_flags & VM_NOHUGEPAGE))
 		goto out;
 
-	/* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-	if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+	if (!vma->anon_vma || vma->vm_ops)
 		goto out;
 	if (is_vma_temporary_stack(vma))
 		goto out;
-	VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+	/*
+	 * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+	 * true too, verify it here.
+	 */
+	VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
@@ -2052,13 +2058,16 @@
 			progress++;
 			continue;
 		}
-		/* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-		if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+		if (!vma->anon_vma || vma->vm_ops)
 			goto skip;
 		if (is_vma_temporary_stack(vma))
 			goto skip;
-
-		VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+		/*
+		 * If is_pfn_mapping() is true is_learn_pfn_mapping()
+		 * must be true too, verify it here.
+		 */
+		VM_BUG_ON(is_linear_pfn_mapping(vma) ||
+			  vma->vm_flags & VM_NO_THP);
 
 		hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
 		hend = vma->vm_end & HPAGE_PMD_MASK;
diff -druN linux-libre-2.6.38-gnu/mm/kmemleak.c linux-libre-2.6.38.8-gnu/mm/kmemleak.c
--- linux-libre-2.6.38-gnu/mm/kmemleak.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/kmemleak.c	2011-06-02 21:35:11.000000000 -0400
@@ -1414,9 +1414,12 @@
 	++(*pos);
 
 	list_for_each_continue_rcu(n, &object_list) {
-		next_obj = list_entry(n, struct kmemleak_object, object_list);
-		if (get_object(next_obj))
+		struct kmemleak_object *obj =
+			list_entry(n, struct kmemleak_object, object_list);
+		if (get_object(obj)) {
+			next_obj = obj;
 			break;
+		}
 	}
 
 	put_object(prev_obj);
diff -druN linux-libre-2.6.38-gnu/mm/memory.c linux-libre-2.6.38.8-gnu/mm/memory.c
--- linux-libre-2.6.38-gnu/mm/memory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/memory.c	2011-06-02 21:35:11.000000000 -0400
@@ -1359,7 +1359,7 @@
 		 */
 		mark_page_accessed(page);
 	}
-	if (flags & FOLL_MLOCK) {
+	if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
 		/*
 		 * The preliminary mapping check is mainly to avoid the
 		 * pointless overhead of lock_page on the ZERO_PAGE
@@ -1410,6 +1410,12 @@
 	return page;
 }
 
+static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	return stack_guard_page_start(vma, addr) ||
+	       stack_guard_page_end(vma, addr+PAGE_SIZE);
+}
+
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 		     unsigned long start, int nr_pages, unsigned int gup_flags,
 		     struct page **pages, struct vm_area_struct **vmas,
@@ -1439,7 +1445,6 @@
 		vma = find_extend_vma(mm, start);
 		if (!vma && in_gate_area(tsk, start)) {
 			unsigned long pg = start & PAGE_MASK;
-			struct vm_area_struct *gate_vma = get_gate_vma(tsk);
 			pgd_t *pgd;
 			pud_t *pud;
 			pmd_t *pmd;
@@ -1464,10 +1469,11 @@
 				pte_unmap(pte);
 				return i ? : -EFAULT;
 			}
+			vma = get_gate_vma(tsk);
 			if (pages) {
 				struct page *page;
 
-				page = vm_normal_page(gate_vma, start, *pte);
+				page = vm_normal_page(vma, start, *pte);
 				if (!page) {
 					if (!(gup_flags & FOLL_DUMP) &&
 					     is_zero_pfn(pte_pfn(*pte)))
@@ -1481,12 +1487,7 @@
 				get_page(page);
 			}
 			pte_unmap(pte);
-			if (vmas)
-				vmas[i] = gate_vma;
-			i++;
-			start += PAGE_SIZE;
-			nr_pages--;
-			continue;
+			goto next_page;
 		}
 
 		if (!vma ||
@@ -1516,6 +1517,11 @@
 				int ret;
 				unsigned int fault_flags = 0;
 
+				/* For mlock, just skip the stack guard page. */
+				if (foll_flags & FOLL_MLOCK) {
+					if (stack_guard_page(vma, start))
+						goto next_page;
+				}
 				if (foll_flags & FOLL_WRITE)
 					fault_flags |= FAULT_FLAG_WRITE;
 				if (nonblocking)
@@ -1569,6 +1575,7 @@
 				flush_anon_page(vma, page, start);
 				flush_dcache_page(page);
 			}
+next_page:
 			if (vmas)
 				vmas[i] = vma;
 			i++;
@@ -3322,7 +3329,7 @@
 	 * run pte_offset_map on the pmd, if an huge pmd could
 	 * materialize from under us from a different thread.
 	 */
-	if (unlikely(__pte_alloc(mm, vma, pmd, address)))
+	if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
 		return VM_FAULT_OOM;
 	/* if an huge pmd materialized from under us just retry later */
 	if (unlikely(pmd_trans_huge(*pmd)))
diff -druN linux-libre-2.6.38-gnu/mm/mlock.c linux-libre-2.6.38.8-gnu/mm/mlock.c
--- linux-libre-2.6.38-gnu/mm/mlock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/mlock.c	2011-06-02 21:35:11.000000000 -0400
@@ -135,13 +135,6 @@
 	}
 }
 
-static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
-{
-	return (vma->vm_flags & VM_GROWSDOWN) &&
-		(vma->vm_start == addr) &&
-		!vma_stack_continue(vma->vm_prev, addr);
-}
-
 /**
  * __mlock_vma_pages_range() -  mlock a range of pages in the vma.
  * @vma:   target vma
@@ -169,7 +162,7 @@
 	VM_BUG_ON(end   > vma->vm_end);
 	VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
 
-	gup_flags = FOLL_TOUCH;
+	gup_flags = FOLL_TOUCH | FOLL_MLOCK;
 	/*
 	 * We want to touch writable mappings with a write fault in order
 	 * to break COW, except for shared mappings because these don't COW
@@ -185,15 +178,6 @@
 	if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))
 		gup_flags |= FOLL_FORCE;
 
-	if (vma->vm_flags & VM_LOCKED)
-		gup_flags |= FOLL_MLOCK;
-
-	/* We don't try to access the guard page of a stack vma */
-	if (stack_guard_page(vma, start)) {
-		addr += PAGE_SIZE;
-		nr_pages--;
-	}
-
 	return __get_user_pages(current, mm, addr, nr_pages, gup_flags,
 				NULL, NULL, nonblocking);
 }
diff -druN linux-libre-2.6.38-gnu/mm/mmap.c linux-libre-2.6.38.8-gnu/mm/mmap.c
--- linux-libre-2.6.38-gnu/mm/mmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/mmap.c	2011-06-02 21:35:11.000000000 -0400
@@ -259,7 +259,7 @@
 	 * randomize_va_space to 2, which will still cause mm->start_brk
 	 * to be arbitrarily shifted
 	 */
-	if (mm->start_brk > PAGE_ALIGN(mm->end_data))
+	if (current->brk_randomized)
 		min_brk = mm->start_brk;
 	else
 		min_brk = mm->end_data;
@@ -1767,10 +1767,13 @@
 		size = address - vma->vm_start;
 		grow = (address - vma->vm_end) >> PAGE_SHIFT;
 
-		error = acct_stack_growth(vma, size, grow);
-		if (!error) {
-			vma->vm_end = address;
-			perf_event_mmap(vma);
+		error = -ENOMEM;
+		if (vma->vm_pgoff + (size >> PAGE_SHIFT) >= vma->vm_pgoff) {
+			error = acct_stack_growth(vma, size, grow);
+			if (!error) {
+				vma->vm_end = address;
+				perf_event_mmap(vma);
+			}
 		}
 	}
 	vma_unlock_anon_vma(vma);
@@ -1814,11 +1817,14 @@
 		size = vma->vm_end - address;
 		grow = (vma->vm_start - address) >> PAGE_SHIFT;
 
-		error = acct_stack_growth(vma, size, grow);
-		if (!error) {
-			vma->vm_start = address;
-			vma->vm_pgoff -= grow;
-			perf_event_mmap(vma);
+		error = -ENOMEM;
+		if (grow <= vma->vm_pgoff) {
+			error = acct_stack_growth(vma, size, grow);
+			if (!error) {
+				vma->vm_start = address;
+				vma->vm_pgoff -= grow;
+				perf_event_mmap(vma);
+			}
 		}
 	}
 	vma_unlock_anon_vma(vma);
diff -druN linux-libre-2.6.38-gnu/mm/mremap.c linux-libre-2.6.38.8-gnu/mm/mremap.c
--- linux-libre-2.6.38-gnu/mm/mremap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/mremap.c	2011-06-02 21:35:11.000000000 -0400
@@ -277,9 +277,16 @@
 	if (old_len > vma->vm_end - addr)
 		goto Efault;
 
-	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
-		if (new_len > old_len)
+	/* Need to be careful about a growing mapping */
+	if (new_len > old_len) {
+		unsigned long pgoff;
+
+		if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
 			goto Efault;
+		pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+		pgoff += vma->vm_pgoff;
+		if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
+			goto Einval;
 	}
 
 	if (vma->vm_flags & VM_LOCKED) {
diff -druN linux-libre-2.6.38-gnu/mm/oom_kill.c linux-libre-2.6.38.8-gnu/mm/oom_kill.c
--- linux-libre-2.6.38-gnu/mm/oom_kill.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/oom_kill.c	2011-06-02 21:35:11.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/memcontrol.h>
 #include <linux/mempolicy.h>
 #include <linux/security.h>
+#include <linux/ptrace.h>
 
 int sysctl_panic_on_oom;
 int sysctl_oom_kill_allocating_task;
@@ -83,24 +84,6 @@
 #endif /* CONFIG_NUMA */
 
 /*
- * If this is a system OOM (not a memcg OOM) and the task selected to be
- * killed is not already running at high (RT) priorities, speed up the
- * recovery by boosting the dying task to the lowest FIFO priority.
- * That helps with the recovery and avoids interfering with RT tasks.
- */
-static void boost_dying_task_prio(struct task_struct *p,
-				  struct mem_cgroup *mem)
-{
-	struct sched_param param = { .sched_priority = 1 };
-
-	if (mem)
-		return;
-
-	if (!rt_task(p))
-		sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
-}
-
-/*
  * The process p may have detached its own ->mm while exiting or through
  * use_mm(), but one or more of its subthreads may still have a valid
  * pointer.  Return p, or any of its subthreads with a valid ->mm, with
@@ -189,10 +172,13 @@
 
 	/*
 	 * The baseline for the badness score is the proportion of RAM that each
-	 * task's rss and swap space use.
+	 * task's rss, pagetable and swap space use.
 	 */
-	points = (get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS)) * 1000 /
-			totalpages;
+	points = get_mm_rss(p->mm) + p->mm->nr_ptes;
+	points += get_mm_counter(p->mm, MM_SWAPENTS);
+
+	points *= 1000;
+	points /= totalpages;
 	task_unlock(p);
 
 	/*
@@ -292,13 +278,15 @@
 		unsigned long totalpages, struct mem_cgroup *mem,
 		const nodemask_t *nodemask)
 {
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	struct task_struct *chosen = NULL;
 	*ppoints = 0;
 
-	for_each_process(p) {
+	do_each_thread(g, p) {
 		unsigned int points;
 
+		if (!p->mm)
+			continue;
 		if (oom_unkillable_task(p, mem, nodemask))
 			continue;
 
@@ -314,22 +302,29 @@
 		if (test_tsk_thread_flag(p, TIF_MEMDIE))
 			return ERR_PTR(-1UL);
 
-		/*
-		 * This is in the process of releasing memory so wait for it
-		 * to finish before killing some other task by mistake.
-		 *
-		 * However, if p is the current task, we allow the 'kill' to
-		 * go ahead if it is exiting: this will simply set TIF_MEMDIE,
-		 * which will allow it to gain access to memory reserves in
-		 * the process of exiting and releasing its resources.
-		 * Otherwise we could get an easy OOM deadlock.
-		 */
-		if (thread_group_empty(p) && (p->flags & PF_EXITING) && p->mm) {
-			if (p != current)
-				return ERR_PTR(-1UL);
-
-			chosen = p;
-			*ppoints = 1000;
+		if (p->flags & PF_EXITING) {
+			/*
+			 * If p is the current task and is in the process of
+			 * releasing memory, we allow the "kill" to set
+			 * TIF_MEMDIE, which will allow it to gain access to
+			 * memory reserves.  Otherwise, it may stall forever.
+			 *
+			 * The loop isn't broken here, however, in case other
+			 * threads are found to have already been oom killed.
+			 */
+			if (p == current) {
+				chosen = p;
+				*ppoints = 1000;
+			} else {
+				/*
+				 * If this task is not being ptraced on exit,
+				 * then wait for it to finish before killing
+				 * some other task unnecessarily.
+				 */
+				if (!(task_ptrace(p->group_leader) &
+							PT_TRACE_EXIT))
+					return ERR_PTR(-1UL);
+			}
 		}
 
 		points = oom_badness(p, mem, nodemask, totalpages);
@@ -337,7 +332,7 @@
 			chosen = p;
 			*ppoints = points;
 		}
-	}
+	} while_each_thread(g, p);
 
 	return chosen;
 }
@@ -442,13 +437,6 @@
 	set_tsk_thread_flag(p, TIF_MEMDIE);
 	force_sig(SIGKILL, p);
 
-	/*
-	 * We give our sacrificial lamb high priority and access to
-	 * all the memory it needs. That way it should be able to
-	 * exit() and clear out its resources quickly...
-	 */
-	boost_dying_task_prio(p, mem);
-
 	return 0;
 }
 #undef K
@@ -472,7 +460,6 @@
 	 */
 	if (p->flags & PF_EXITING) {
 		set_tsk_thread_flag(p, TIF_MEMDIE);
-		boost_dying_task_prio(p, mem);
 		return 0;
 	}
 
@@ -491,6 +478,8 @@
 		list_for_each_entry(child, &t->children, sibling) {
 			unsigned int child_points;
 
+			if (child->mm == p->mm)
+				continue;
 			/*
 			 * oom_badness() returns 0 if the thread is unkillable
 			 */
@@ -689,7 +678,6 @@
 	 */
 	if (fatal_signal_pending(current)) {
 		set_thread_flag(TIF_MEMDIE);
-		boost_dying_task_prio(current, NULL);
 		return;
 	}
 
diff -druN linux-libre-2.6.38-gnu/mm/page_alloc.c linux-libre-2.6.38.8-gnu/mm/page_alloc.c
--- linux-libre-2.6.38-gnu/mm/page_alloc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/page_alloc.c	2011-06-02 21:35:11.000000000 -0400
@@ -286,7 +286,7 @@
 
 	/* Don't complain about poisoned pages */
 	if (PageHWPoison(page)) {
-		__ClearPageBuddy(page);
+		reset_page_mapcount(page); /* remove PageBuddy */
 		return;
 	}
 
@@ -317,7 +317,7 @@
 	dump_stack();
 out:
 	/* Leave bad fields for debug, except PageBuddy could make trouble */
-	__ClearPageBuddy(page);
+	reset_page_mapcount(page); /* remove PageBuddy */
 	add_taint(TAINT_BAD_PAGE);
 }
 
@@ -2044,6 +2044,7 @@
 		first_zones_zonelist(zonelist, high_zoneidx, NULL,
 					&preferred_zone);
 
+rebalance:
 	/* This is the last chance, in general, before the goto nopage. */
 	page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist,
 			high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS,
@@ -2051,7 +2052,6 @@
 	if (page)
 		goto got_pg;
 
-rebalance:
 	/* Allocate without watermarks if the context allows */
 	if (alloc_flags & ALLOC_NO_WATERMARKS) {
 		page = __alloc_pages_high_priority(gfp_mask, order,
@@ -3498,7 +3498,7 @@
 
 	if (!slab_is_available()) {
 		zone->wait_table = (wait_queue_head_t *)
-			alloc_bootmem_node(pgdat, alloc_size);
+			alloc_bootmem_node_nopanic(pgdat, alloc_size);
 	} else {
 		/*
 		 * This case means that a zone whose size was 0 gets new memory
@@ -4071,7 +4071,8 @@
 	unsigned long usemapsize = usemap_size(zonesize);
 	zone->pageblock_flags = NULL;
 	if (usemapsize)
-		zone->pageblock_flags = alloc_bootmem_node(pgdat, usemapsize);
+		zone->pageblock_flags = alloc_bootmem_node_nopanic(pgdat,
+								   usemapsize);
 }
 #else
 static inline void setup_usemap(struct pglist_data *pgdat,
@@ -4237,7 +4238,7 @@
 		size =  (end - start) * sizeof(struct page);
 		map = alloc_remap(pgdat->node_id, size);
 		if (!map)
-			map = alloc_bootmem_node(pgdat, size);
+			map = alloc_bootmem_node_nopanic(pgdat, size);
 		pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
 	}
 #ifndef CONFIG_NEED_MULTIPLE_NODES
diff -druN linux-libre-2.6.38-gnu/mm/shmem.c linux-libre-2.6.38.8-gnu/mm/shmem.c
--- linux-libre-2.6.38-gnu/mm/shmem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/shmem.c	2011-06-02 21:35:11.000000000 -0400
@@ -422,7 +422,8 @@
 		 * a waste to allocate index if we cannot allocate data.
 		 */
 		if (sbinfo->max_blocks) {
-			if (percpu_counter_compare(&sbinfo->used_blocks, (sbinfo->max_blocks - 1)) > 0)
+			if (percpu_counter_compare(&sbinfo->used_blocks,
+						sbinfo->max_blocks - 1) >= 0)
 				return ERR_PTR(-ENOSPC);
 			percpu_counter_inc(&sbinfo->used_blocks);
 			spin_lock(&inode->i_lock);
@@ -852,7 +853,7 @@
 
 static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
 {
-	struct inode *inode;
+	struct address_space *mapping;
 	unsigned long idx;
 	unsigned long size;
 	unsigned long limit;
@@ -875,8 +876,10 @@
 	if (size > SHMEM_NR_DIRECT)
 		size = SHMEM_NR_DIRECT;
 	offset = shmem_find_swp(entry, ptr, ptr+size);
-	if (offset >= 0)
+	if (offset >= 0) {
+		shmem_swp_balance_unmap();
 		goto found;
+	}
 	if (!info->i_indirect)
 		goto lost2;
 
@@ -917,6 +920,7 @@
 			shmem_swp_unmap(ptr);
 			if (offset >= 0) {
 				shmem_dir_unmap(dir);
+				ptr = shmem_swp_map(subdir);
 				goto found;
 			}
 		}
@@ -928,8 +932,7 @@
 	return 0;
 found:
 	idx += offset;
-	inode = igrab(&info->vfs_inode);
-	spin_unlock(&info->lock);
+	ptr += offset;
 
 	/*
 	 * Move _head_ to start search for next from here.
@@ -940,37 +943,18 @@
 	 */
 	if (shmem_swaplist.next != &info->swaplist)
 		list_move_tail(&shmem_swaplist, &info->swaplist);
-	mutex_unlock(&shmem_swaplist_mutex);
 
-	error = 1;
-	if (!inode)
-		goto out;
 	/*
-	 * Charge page using GFP_KERNEL while we can wait.
-	 * Charged back to the user(not to caller) when swap account is used.
-	 * add_to_page_cache() will be called with GFP_NOWAIT.
+	 * We rely on shmem_swaplist_mutex, not only to protect the swaplist,
+	 * but also to hold up shmem_evict_inode(): so inode cannot be freed
+	 * beneath us (pagelock doesn't help until the page is in pagecache).
 	 */
-	error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
-	if (error)
-		goto out;
-	error = radix_tree_preload(GFP_KERNEL);
-	if (error) {
-		mem_cgroup_uncharge_cache_page(page);
-		goto out;
-	}
-	error = 1;
-
-	spin_lock(&info->lock);
-	ptr = shmem_swp_entry(info, idx, NULL);
-	if (ptr && ptr->val == entry.val) {
-		error = add_to_page_cache_locked(page, inode->i_mapping,
-						idx, GFP_NOWAIT);
-		/* does mem_cgroup_uncharge_cache_page on error */
-	} else	/* we must compensate for our precharge above */
-		mem_cgroup_uncharge_cache_page(page);
+	mapping = info->vfs_inode.i_mapping;
+	error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT);
+	/* which does mem_cgroup_uncharge_cache_page on error */
 
 	if (error == -EEXIST) {
-		struct page *filepage = find_get_page(inode->i_mapping, idx);
+		struct page *filepage = find_get_page(mapping, idx);
 		error = 1;
 		if (filepage) {
 			/*
@@ -990,14 +974,8 @@
 		swap_free(entry);
 		error = 1;	/* not an error, but entry was found */
 	}
-	if (ptr)
-		shmem_swp_unmap(ptr);
+	shmem_swp_unmap(ptr);
 	spin_unlock(&info->lock);
-	radix_tree_preload_end();
-out:
-	unlock_page(page);
-	page_cache_release(page);
-	iput(inode);		/* allows for NULL */
 	return error;
 }
 
@@ -1009,6 +987,26 @@
 	struct list_head *p, *next;
 	struct shmem_inode_info *info;
 	int found = 0;
+	int error;
+
+	/*
+	 * Charge page using GFP_KERNEL while we can wait, before taking
+	 * the shmem_swaplist_mutex which might hold up shmem_writepage().
+	 * Charged back to the user (not to caller) when swap account is used.
+	 * add_to_page_cache() will be called with GFP_NOWAIT.
+	 */
+	error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
+	if (error)
+		goto out;
+	/*
+	 * Try to preload while we can wait, to not make a habit of
+	 * draining atomic reserves; but don't latch on to this cpu,
+	 * it's okay if sometimes we get rescheduled after this.
+	 */
+	error = radix_tree_preload(GFP_KERNEL);
+	if (error)
+		goto uncharge;
+	radix_tree_preload_end();
 
 	mutex_lock(&shmem_swaplist_mutex);
 	list_for_each_safe(p, next, &shmem_swaplist) {
@@ -1016,17 +1014,19 @@
 		found = shmem_unuse_inode(info, entry, page);
 		cond_resched();
 		if (found)
-			goto out;
+			break;
 	}
 	mutex_unlock(&shmem_swaplist_mutex);
-	/*
-	 * Can some race bring us here?  We've been holding page lock,
-	 * so I think not; but would rather try again later than BUG()
-	 */
+
+uncharge:
+	if (!found)
+		mem_cgroup_uncharge_cache_page(page);
+	if (found < 0)
+		error = found;
+out:
 	unlock_page(page);
 	page_cache_release(page);
-out:
-	return (found < 0) ? found : 0;
+	return error;
 }
 
 /*
@@ -1064,7 +1064,25 @@
 	else
 		swap.val = 0;
 
+	/*
+	 * Add inode to shmem_unuse()'s list of swapped-out inodes,
+	 * if it's not already there.  Do it now because we cannot take
+	 * mutex while holding spinlock, and must do so before the page
+	 * is moved to swap cache, when its pagelock no longer protects
+	 * the inode from eviction.  But don't unlock the mutex until
+	 * we've taken the spinlock, because shmem_unuse_inode() will
+	 * prune a !swapped inode from the swaplist under both locks.
+	 */
+	if (swap.val) {
+		mutex_lock(&shmem_swaplist_mutex);
+		if (list_empty(&info->swaplist))
+			list_add_tail(&info->swaplist, &shmem_swaplist);
+	}
+
 	spin_lock(&info->lock);
+	if (swap.val)
+		mutex_unlock(&shmem_swaplist_mutex);
+
 	if (index >= info->next_index) {
 		BUG_ON(!(info->flags & SHMEM_TRUNCATE));
 		goto unlock;
@@ -1084,22 +1102,11 @@
 		remove_from_page_cache(page);
 		shmem_swp_set(info, entry, swap.val);
 		shmem_swp_unmap(entry);
-		if (list_empty(&info->swaplist))
-			inode = igrab(inode);
-		else
-			inode = NULL;
-		spin_unlock(&info->lock);
 		swap_shmem_alloc(swap);
+		spin_unlock(&info->lock);
 		BUG_ON(page_mapped(page));
 		page_cache_release(page);	/* pagecache ref */
 		swap_writepage(page, wbc);
-		if (inode) {
-			mutex_lock(&shmem_swaplist_mutex);
-			/* move instead of add in case we're racing */
-			list_move_tail(&info->swaplist, &shmem_swaplist);
-			mutex_unlock(&shmem_swaplist_mutex);
-			iput(inode);
-		}
 		return 0;
 	}
 
@@ -1399,21 +1406,16 @@
 		shmem_swp_unmap(entry);
 		sbinfo = SHMEM_SB(inode->i_sb);
 		if (sbinfo->max_blocks) {
-			if ((percpu_counter_compare(&sbinfo->used_blocks, sbinfo->max_blocks) > 0) ||
-			    shmem_acct_block(info->flags)) {
-				spin_unlock(&info->lock);
-				error = -ENOSPC;
-				goto failed;
-			}
+			if (percpu_counter_compare(&sbinfo->used_blocks,
+						sbinfo->max_blocks) >= 0 ||
+			    shmem_acct_block(info->flags))
+				goto nospace;
 			percpu_counter_inc(&sbinfo->used_blocks);
 			spin_lock(&inode->i_lock);
 			inode->i_blocks += BLOCKS_PER_PAGE;
 			spin_unlock(&inode->i_lock);
-		} else if (shmem_acct_block(info->flags)) {
-			spin_unlock(&info->lock);
-			error = -ENOSPC;
-			goto failed;
-		}
+		} else if (shmem_acct_block(info->flags))
+			goto nospace;
 
 		if (!filepage) {
 			int ret;
@@ -1493,6 +1495,24 @@
 	error = 0;
 	goto out;
 
+nospace:
+	/*
+	 * Perhaps the page was brought in from swap between find_lock_page
+	 * and taking info->lock?  We allow for that at add_to_page_cache_lru,
+	 * but must also avoid reporting a spurious ENOSPC while working on a
+	 * full tmpfs.  (When filepage has been passed in to shmem_getpage, it
+	 * is already in page cache, which prevents this race from occurring.)
+	 */
+	if (!filepage) {
+		struct page *page = find_get_page(mapping, idx);
+		if (page) {
+			spin_unlock(&info->lock);
+			page_cache_release(page);
+			goto repeat;
+		}
+	}
+	spin_unlock(&info->lock);
+	error = -ENOSPC;
 failed:
 	if (*pagep != filepage) {
 		unlock_page(filepage);
@@ -2791,5 +2811,6 @@
 		fput(vma->vm_file);
 	vma->vm_file = file;
 	vma->vm_ops = &shmem_vm_ops;
+	vma->vm_flags |= VM_CAN_NONLINEAR;
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/mm/slab.c linux-libre-2.6.38.8-gnu/mm/slab.c
--- linux-libre-2.6.38-gnu/mm/slab.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/slab.c	2011-06-02 21:35:11.000000000 -0400
@@ -2288,8 +2288,8 @@
 	if (ralign < align) {
 		ralign = align;
 	}
-	/* disable debug if not aligning with REDZONE_ALIGN */
-	if (ralign & (__alignof__(unsigned long long) - 1))
+	/* disable debug if necessary */
+	if (ralign > __alignof__(unsigned long long))
 		flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 	/*
 	 * 4) Store it.
@@ -2315,8 +2315,8 @@
 	 */
 	if (flags & SLAB_RED_ZONE) {
 		/* add space for red zone words */
-		cachep->obj_offset += align;
-		size += align + sizeof(unsigned long long);
+		cachep->obj_offset += sizeof(unsigned long long);
+		size += 2 * sizeof(unsigned long long);
 	}
 	if (flags & SLAB_STORE_USER) {
 		/* user store requires one word storage behind the end of
diff -druN linux-libre-2.6.38-gnu/mm/swapfile.c linux-libre-2.6.38.8-gnu/mm/swapfile.c
--- linux-libre-2.6.38-gnu/mm/swapfile.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/swapfile.c	2011-06-02 21:35:11.000000000 -0400
@@ -2149,8 +2149,13 @@
 	p->flags = 0;
 	spin_unlock(&swap_lock);
 	vfree(swap_map);
-	if (swap_file)
+	if (swap_file) {
+		if (did_down) {
+			mutex_unlock(&inode->i_mutex);
+			did_down = 0;
+		}
 		filp_close(swap_file, NULL);
+	}
 out:
 	if (page && !IS_ERR(page)) {
 		kunmap(page);
diff -druN linux-libre-2.6.38-gnu/mm/vmscan.c linux-libre-2.6.38.8-gnu/mm/vmscan.c
--- linux-libre-2.6.38-gnu/mm/vmscan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/mm/vmscan.c	2011-06-02 21:35:11.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/memcontrol.h>
 #include <linux/delayacct.h>
 #include <linux/sysctl.h>
+#include <linux/oom.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -229,8 +230,11 @@
 	if (scanned == 0)
 		scanned = SWAP_CLUSTER_MAX;
 
-	if (!down_read_trylock(&shrinker_rwsem))
-		return 1;	/* Assume we'll be able to shrink next time */
+	if (!down_read_trylock(&shrinker_rwsem)) {
+		/* Assume we'll be able to shrink next time */
+		ret = 1;
+		goto out;
+	}
 
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
@@ -281,6 +285,8 @@
 		shrinker->nr += total_scan;
 	}
 	up_read(&shrinker_rwsem);
+out:
+	cond_resched();
 	return ret;
 }
 
@@ -1988,17 +1994,12 @@
 	return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
 }
 
-/*
- * As hibernation is going on, kswapd is freezed so that it can't mark
- * the zone into all_unreclaimable. It can't handle OOM during hibernation.
- * So let's check zone's unreclaimable in direct reclaim as well as kswapd.
- */
+/* All zones in zonelist are unreclaimable? */
 static bool all_unreclaimable(struct zonelist *zonelist,
 		struct scan_control *sc)
 {
 	struct zoneref *z;
 	struct zone *zone;
-	bool all_unreclaimable = true;
 
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 			gfp_zone(sc->gfp_mask), sc->nodemask) {
@@ -2006,13 +2007,11 @@
 			continue;
 		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
-		if (zone_reclaimable(zone)) {
-			all_unreclaimable = false;
-			break;
-		}
+		if (!zone->all_unreclaimable)
+			return false;
 	}
 
-	return all_unreclaimable;
+	return true;
 }
 
 /*
@@ -2108,6 +2107,14 @@
 	if (sc->nr_reclaimed)
 		return sc->nr_reclaimed;
 
+	/*
+	 * As hibernation is going on, kswapd is freezed so that it can't mark
+	 * the zone into all_unreclaimable. Thus bypassing all_unreclaimable
+	 * check.
+	 */
+	if (oom_killer_disabled)
+		return 0;
+
 	/* top priority shrink_zones still had more to do? don't OOM, then */
 	if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc))
 		return 1;
@@ -2284,7 +2291,7 @@
 	 * must be balanced
 	 */
 	if (order)
-		return pgdat_balanced(pgdat, balanced, classzone_idx);
+		return !pgdat_balanced(pgdat, balanced, classzone_idx);
 	else
 		return !all_zones_ok;
 }
@@ -2397,7 +2404,6 @@
 		 * cause too much scanning of the lower zones.
 		 */
 		for (i = 0; i <= end_zone; i++) {
-			int compaction;
 			struct zone *zone = pgdat->node_zones + i;
 			int nr_slab;
 
@@ -2428,24 +2434,9 @@
 			sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 			total_scanned += sc.nr_scanned;
 
-			compaction = 0;
-			if (order &&
-			    zone_watermark_ok(zone, 0,
-					       high_wmark_pages(zone),
-					      end_zone, 0) &&
-			    !zone_watermark_ok(zone, order,
-					       high_wmark_pages(zone),
-					       end_zone, 0)) {
-				compact_zone_order(zone,
-						   order,
-						   sc.gfp_mask, false,
-						   COMPACT_MODE_KSWAPD);
-				compaction = 1;
-			}
-
 			if (zone->all_unreclaimable)
 				continue;
-			if (!compaction && nr_slab == 0 &&
+			if (nr_slab == 0 &&
 			    !zone_reclaimable(zone))
 				zone->all_unreclaimable = 1;
 			/*
diff -druN linux-libre-2.6.38-gnu/net/8021q/vlan.c linux-libre-2.6.38.8-gnu/net/8021q/vlan.c
--- linux-libre-2.6.38-gnu/net/8021q/vlan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/8021q/vlan.c	2011-06-02 21:35:11.000000000 -0400
@@ -124,6 +124,9 @@
 
 	grp->nr_vlans--;
 
+	if (vlan->flags & VLAN_FLAG_GVRP)
+		vlan_gvrp_request_leave(dev);
+
 	vlan_group_set_device(grp, vlan_id, NULL);
 	if (!grp->killall)
 		synchronize_net();
diff -druN linux-libre-2.6.38-gnu/net/8021q/vlan_dev.c linux-libre-2.6.38.8-gnu/net/8021q/vlan_dev.c
--- linux-libre-2.6.38-gnu/net/8021q/vlan_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/8021q/vlan_dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -487,9 +487,6 @@
 	struct vlan_dev_info *vlan = vlan_dev_info(dev);
 	struct net_device *real_dev = vlan->real_dev;
 
-	if (vlan->flags & VLAN_FLAG_GVRP)
-		vlan_gvrp_request_leave(dev);
-
 	dev_mc_unsync(real_dev, dev);
 	dev_uc_unsync(real_dev, dev);
 	if (dev->flags & IFF_ALLMULTI)
@@ -707,6 +704,7 @@
 	dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
 #endif
 
+	dev->needed_headroom = real_dev->needed_headroom;
 	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
 		dev->header_ops      = real_dev->header_ops;
 		dev->hard_header_len = real_dev->hard_header_len;
diff -druN linux-libre-2.6.38-gnu/net/atm/atm_sysfs.c linux-libre-2.6.38.8-gnu/net/atm/atm_sysfs.c
--- linux-libre-2.6.38-gnu/net/atm/atm_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/atm/atm_sysfs.c	2011-06-02 21:35:11.000000000 -0400
@@ -59,6 +59,14 @@
 	return pos - buf;
 }
 
+static ssize_t show_atmindex(struct device *cdev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct atm_dev *adev = to_atm_dev(cdev);
+
+	return sprintf(buf, "%d\n", adev->number);
+}
+
 static ssize_t show_carrier(struct device *cdev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -99,6 +107,7 @@
 
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
 static DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL);
+static DEVICE_ATTR(atmindex, S_IRUGO, show_atmindex, NULL);
 static DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
@@ -106,6 +115,7 @@
 static struct device_attribute *atm_attrs[] = {
 	&dev_attr_atmaddress,
 	&dev_attr_address,
+	&dev_attr_atmindex,
 	&dev_attr_carrier,
 	&dev_attr_type,
 	&dev_attr_link_rate,
diff -druN linux-libre-2.6.38-gnu/net/atm/common.c linux-libre-2.6.38.8-gnu/net/atm/common.c
--- linux-libre-2.6.38-gnu/net/atm/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/atm/common.c	2011-06-02 21:35:11.000000000 -0400
@@ -252,6 +252,7 @@
 	}
 	write_unlock_irq(&vcc_sklist_lock);
 }
+EXPORT_SYMBOL(atm_dev_release_vccs);
 
 static int adjust_tp(struct atm_trafprm *tp, unsigned char aal)
 {
diff -druN linux-libre-2.6.38-gnu/net/bluetooth/bnep/sock.c linux-libre-2.6.38.8-gnu/net/bluetooth/bnep/sock.c
--- linux-libre-2.6.38-gnu/net/bluetooth/bnep/sock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bluetooth/bnep/sock.c	2011-06-02 21:35:11.000000000 -0400
@@ -88,6 +88,7 @@
 			sockfd_put(nsock);
 			return -EBADFD;
 		}
+		ca.device[sizeof(ca.device)-1] = 0;
 
 		err = bnep_add_connection(&ca, nsock);
 		if (!err) {
diff -druN linux-libre-2.6.38-gnu/net/bluetooth/hci_core.c linux-libre-2.6.38.8-gnu/net/bluetooth/hci_core.c
--- linux-libre-2.6.38-gnu/net/bluetooth/hci_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bluetooth/hci_core.c	2011-06-02 21:35:11.000000000 -0400
@@ -184,6 +184,7 @@
 	BT_DBG("%s %ld", hdev->name, opt);
 
 	/* Reset device */
+	set_bit(HCI_RESET, &hdev->flags);
 	hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
 }
 
@@ -210,8 +211,10 @@
 	/* Mandatory initialization */
 
 	/* Reset */
-	if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks))
+	if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
+			set_bit(HCI_RESET, &hdev->flags);
 			hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
+	}
 
 	/* Read Local Supported Features */
 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
diff -druN linux-libre-2.6.38-gnu/net/bluetooth/hci_event.c linux-libre-2.6.38.8-gnu/net/bluetooth/hci_event.c
--- linux-libre-2.6.38-gnu/net/bluetooth/hci_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bluetooth/hci_event.c	2011-06-02 21:35:11.000000000 -0400
@@ -183,6 +183,8 @@
 
 	BT_DBG("%s status 0x%x", hdev->name, status);
 
+	clear_bit(HCI_RESET, &hdev->flags);
+
 	hci_req_complete(hdev, HCI_OP_RESET, status);
 }
 
@@ -1464,7 +1466,7 @@
 		break;
 	}
 
-	if (ev->ncmd) {
+	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
 			tasklet_schedule(&hdev->cmd_task);
diff -druN linux-libre-2.6.38-gnu/net/bluetooth/sco.c linux-libre-2.6.38.8-gnu/net/bluetooth/sco.c
--- linux-libre-2.6.38-gnu/net/bluetooth/sco.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bluetooth/sco.c	2011-06-02 21:35:11.000000000 -0400
@@ -703,6 +703,7 @@
 			break;
 		}
 
+		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
 		memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
diff -druN linux-libre-2.6.38-gnu/net/bridge/br_input.c linux-libre-2.6.38.8-gnu/net/bridge/br_input.c
--- linux-libre-2.6.38-gnu/net/bridge/br_input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bridge/br_input.c	2011-06-02 21:35:11.000000000 -0400
@@ -163,7 +163,7 @@
 			goto drop;
 
 		/* If STP is turned off, then forward */
-		if (p->br->stp_enabled == BR_NO_STP)
+		if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
 			goto forward;
 
 		if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
diff -druN linux-libre-2.6.38-gnu/net/bridge/br_multicast.c linux-libre-2.6.38.8-gnu/net/bridge/br_multicast.c
--- linux-libre-2.6.38-gnu/net/bridge/br_multicast.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bridge/br_multicast.c	2011-06-02 21:35:11.000000000 -0400
@@ -445,9 +445,9 @@
 	ip6h->payload_len = htons(8 + sizeof(*mldq));
 	ip6h->nexthdr = IPPROTO_HOPOPTS;
 	ip6h->hop_limit = 1;
+	ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
 	ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
 			   &ip6h->saddr);
-	ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
 	ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 
 	hopopt = (u8 *)(ip6h + 1);
diff -druN linux-libre-2.6.38-gnu/net/bridge/br_netfilter.c linux-libre-2.6.38.8-gnu/net/bridge/br_netfilter.c
--- linux-libre-2.6.38-gnu/net/bridge/br_netfilter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bridge/br_netfilter.c	2011-06-02 21:35:11.000000000 -0400
@@ -249,11 +249,9 @@
 		goto drop;
 	}
 
-	/* Zero out the CB buffer if no options present */
-	if (iph->ihl == 5) {
-		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+	if (iph->ihl == 5)
 		return 0;
-	}
 
 	opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
 	if (ip_options_compile(dev_net(dev), opt, skb))
@@ -741,6 +739,9 @@
 		nf_bridge->mask |= BRNF_PKT_TYPE;
 	}
 
+	if (pf == PF_INET && br_parse_ip_options(skb))
+		return NF_DROP;
+
 	/* The physdev module checks on this */
 	nf_bridge->mask |= BRNF_BRIDGED;
 	nf_bridge->physoutdev = skb->dev;
diff -druN linux-libre-2.6.38-gnu/net/bridge/netfilter/ebtables.c linux-libre-2.6.38.8-gnu/net/bridge/netfilter/ebtables.c
--- linux-libre-2.6.38-gnu/net/bridge/netfilter/ebtables.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/bridge/netfilter/ebtables.c	2011-06-02 21:35:11.000000000 -0400
@@ -1107,6 +1107,8 @@
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
 
+	tmp.name[sizeof(tmp.name) - 1] = 0;
+
 	countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
 	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
diff -druN linux-libre-2.6.38-gnu/net/can/bcm.c linux-libre-2.6.38.8-gnu/net/can/bcm.c
--- linux-libre-2.6.38-gnu/net/can/bcm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/can/bcm.c	2011-06-02 21:35:11.000000000 -0400
@@ -1427,9 +1427,14 @@
 static int bcm_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct bcm_sock *bo = bcm_sk(sk);
+	struct bcm_sock *bo;
 	struct bcm_op *op, *next;
 
+	if (sk == NULL)
+		return 0;
+
+	bo = bcm_sk(sk);
+
 	/* remove bcm_ops, timer, rx_unregister(), etc. */
 
 	unregister_netdevice_notifier(&bo->notifier);
diff -druN linux-libre-2.6.38-gnu/net/can/raw.c linux-libre-2.6.38.8-gnu/net/can/raw.c
--- linux-libre-2.6.38-gnu/net/can/raw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/can/raw.c	2011-06-02 21:35:11.000000000 -0400
@@ -305,7 +305,12 @@
 static int raw_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct raw_sock *ro = raw_sk(sk);
+	struct raw_sock *ro;
+
+	if (!sk)
+		return 0;
+
+	ro = raw_sk(sk);
 
 	unregister_netdevice_notifier(&ro->notifier);
 
diff -druN linux-libre-2.6.38-gnu/net/core/dev.c linux-libre-2.6.38.8-gnu/net/core/dev.c
--- linux-libre-2.6.38-gnu/net/core/dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/core/dev.c	2011-06-02 21:35:11.000000000 -0400
@@ -1006,7 +1006,7 @@
 	}
 
 	write_lock_bh(&dev_base_lock);
-	hlist_del(&dev->name_hlist);
+	hlist_del_rcu(&dev->name_hlist);
 	write_unlock_bh(&dev_base_lock);
 
 	synchronize_rcu();
@@ -1332,11 +1332,13 @@
  */
 int dev_close(struct net_device *dev)
 {
-	LIST_HEAD(single);
+	if (dev->flags & IFF_UP) {
+		LIST_HEAD(single);
 
-	list_add(&dev->unreg_list, &single);
-	dev_close_many(&single);
-	list_del(&single);
+		list_add(&dev->unreg_list, &single);
+		dev_close_many(&single);
+		list_del(&single);
+	}
 	return 0;
 }
 EXPORT_SYMBOL(dev_close);
diff -druN linux-libre-2.6.38-gnu/net/core/ethtool.c linux-libre-2.6.38.8-gnu/net/core/ethtool.c
--- linux-libre-2.6.38-gnu/net/core/ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/core/ethtool.c	2011-06-02 21:35:11.000000000 -0400
@@ -146,9 +146,24 @@
 }
 EXPORT_SYMBOL(ethtool_op_get_flags);
 
+/* Check if device can enable (or disable) particular feature coded in "data"
+ * argument. Flags "supported" describe features that can be toggled by device.
+ * If feature can not be toggled, it state (enabled or disabled) must match
+ * hardcoded device features state, otherwise flags are marked as invalid.
+ */
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
+{
+	u32 features = dev->features & flags_dup_features;
+	/* "data" can contain only flags_dup_features bits,
+	 * see __ethtool_set_flags */
+
+	return (features & ~supported) != (data & ~supported);
+}
+EXPORT_SYMBOL(ethtool_invalid_flags);
+
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
 {
-	if (data & ~supported)
+	if (ethtool_invalid_flags(dev, data, supported))
 		return -EINVAL;
 
 	dev->features = ((dev->features & ~flags_dup_features) |
diff -druN linux-libre-2.6.38-gnu/net/core/skbuff.c linux-libre-2.6.38.8-gnu/net/core/skbuff.c
--- linux-libre-2.6.38-gnu/net/core/skbuff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/core/skbuff.c	2011-06-02 21:35:11.000000000 -0400
@@ -2997,6 +2997,9 @@
 	skb->destructor = sock_rmem_free;
 	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
 
+	/* before exiting rcu section, make sure dst is refcounted */
+	skb_dst_force(skb);
+
 	skb_queue_tail(&sk->sk_error_queue, skb);
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_data_ready(sk, skb->len);
diff -druN linux-libre-2.6.38-gnu/net/dccp/options.c linux-libre-2.6.38.8-gnu/net/dccp/options.c
--- linux-libre-2.6.38-gnu/net/dccp/options.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/dccp/options.c	2011-06-02 21:35:11.000000000 -0400
@@ -123,6 +123,8 @@
 		case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
 			if (pkt_type == DCCP_PKT_DATA)      /* RFC 4340, 6 */
 				break;
+			if (len == 0)
+				goto out_invalid_option;
 			rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
 						    *value, value + 1, len - 1);
 			if (rc)
diff -druN linux-libre-2.6.38-gnu/net/econet/af_econet.c linux-libre-2.6.38.8-gnu/net/econet/af_econet.c
--- linux-libre-2.6.38-gnu/net/econet/af_econet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/econet/af_econet.c	2011-06-02 21:35:11.000000000 -0400
@@ -435,10 +435,10 @@
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
+	memset(&ah, 0, sizeof(ah));
 	ah.port = port;
 	ah.cb = cb & 0x7f;
 	ah.code = 2;		/* magic */
-	ah.pad = 0;
 
 	/* tack our header on the front of the iovec */
 	size = sizeof(struct aunhdr);
diff -druN linux-libre-2.6.38-gnu/net/ieee802154/Makefile linux-libre-2.6.38.8-gnu/net/ieee802154/Makefile
--- linux-libre-2.6.38-gnu/net/ieee802154/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ieee802154/Makefile	2011-06-02 21:35:11.000000000 -0400
@@ -1,5 +1,3 @@
 obj-$(CONFIG_IEEE802154) +=	ieee802154.o af_802154.o
 ieee802154-y		:= netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
 af_802154-y		:= af_ieee802154.o raw.o dgram.o
-
-ccflags-y += -Wall -DDEBUG
diff -druN linux-libre-2.6.38-gnu/net/ipv4/fib_frontend.c linux-libre-2.6.38.8-gnu/net/ipv4/fib_frontend.c
--- linux-libre-2.6.38-gnu/net/ipv4/fib_frontend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/fib_frontend.c	2011-06-02 21:35:11.000000000 -0400
@@ -1041,6 +1041,7 @@
 	fib4_rules_exit(net);
 #endif
 
+	rtnl_lock();
 	for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
 		struct fib_table *tb;
 		struct hlist_head *head;
@@ -1053,6 +1054,7 @@
 			fib_free_table(tb);
 		}
 	}
+	rtnl_unlock();
 	kfree(net->ipv4.fib_table_hash);
 }
 
diff -druN linux-libre-2.6.38-gnu/net/ipv4/igmp.c linux-libre-2.6.38.8-gnu/net/ipv4/igmp.c
--- linux-libre-2.6.38-gnu/net/ipv4/igmp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/igmp.c	2011-06-02 21:35:11.000000000 -0400
@@ -1172,20 +1172,18 @@
 
 	if (!in_dev->dead) {
 		if (IGMP_V1_SEEN(in_dev))
-			goto done;
+			return;
 		if (IGMP_V2_SEEN(in_dev)) {
 			if (reporter)
 				igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
-			goto done;
+			return;
 		}
 		/* IGMPv3 */
 		igmpv3_add_delrec(in_dev, im);
 
 		igmp_ifc_event(in_dev);
 	}
-done:
 #endif
-	ip_mc_clear_src(im);
 }
 
 static void igmp_group_added(struct ip_mc_list *im)
@@ -1322,6 +1320,7 @@
 				*ip = i->next_rcu;
 				in_dev->mc_count--;
 				igmp_group_dropped(i);
+				ip_mc_clear_src(i);
 
 				if (!in_dev->dead)
 					ip_rt_multicast_event(in_dev);
@@ -1431,7 +1430,8 @@
 		in_dev->mc_list = i->next_rcu;
 		in_dev->mc_count--;
 
-		igmp_group_dropped(i);
+		/* We've dropped the groups in ip_mc_down already */
+		ip_mc_clear_src(i);
 		ip_ma_put(i);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/net/ipv4/inet_connection_sock.c linux-libre-2.6.38.8-gnu/net/ipv4/inet_connection_sock.c
--- linux-libre-2.6.38-gnu/net/ipv4/inet_connection_sock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/inet_connection_sock.c	2011-06-02 21:35:11.000000000 -0400
@@ -73,7 +73,7 @@
 		     !sk2->sk_bound_dev_if ||
 		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
 			if (!reuse || !sk2->sk_reuse ||
-			    ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) {
+			    sk2->sk_state == TCP_LISTEN) {
 				const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2);
 				if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) ||
 				    sk2_rcv_saddr == sk_rcv_saddr(sk))
@@ -122,8 +122,7 @@
 					    (tb->num_owners < smallest_size || smallest_size == -1)) {
 						smallest_size = tb->num_owners;
 						smallest_rover = rover;
-						if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 &&
-						    !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+						if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
 							spin_unlock(&head->lock);
 							snum = smallest_rover;
 							goto have_snum;
diff -druN linux-libre-2.6.38-gnu/net/ipv4/inetpeer.c linux-libre-2.6.38.8-gnu/net/ipv4/inetpeer.c
--- linux-libre-2.6.38-gnu/net/ipv4/inetpeer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/inetpeer.c	2011-06-02 21:35:11.000000000 -0400
@@ -366,7 +366,8 @@
 }
 
 /* May be called with local BH enabled. */
-static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
+static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
+			     struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
 	int do_free;
 
@@ -380,7 +381,6 @@
 	 * We use refcnt=-1 to alert lockless readers this entry is deleted.
 	 */
 	if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
-		struct inet_peer __rcu **stack[PEER_MAXDEPTH];
 		struct inet_peer __rcu ***stackptr, ***delp;
 		if (lookup(&p->daddr, stack, base) != p)
 			BUG();
@@ -435,7 +435,7 @@
 }
 
 /* May be called with local BH enabled. */
-static int cleanup_once(unsigned long ttl)
+static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
 	struct inet_peer *p = NULL;
 
@@ -467,7 +467,7 @@
 		 * happen because of entry limits in route cache. */
 		return -1;
 
-	unlink_from_pool(p, peer_to_base(p));
+	unlink_from_pool(p, peer_to_base(p), stack);
 	return 0;
 }
 
@@ -523,7 +523,7 @@
 
 	if (base->total >= inet_peer_threshold)
 		/* Remove one less-recently-used entry. */
-		cleanup_once(0);
+		cleanup_once(0, stack);
 
 	return p;
 }
@@ -539,6 +539,7 @@
 {
 	unsigned long now = jiffies;
 	int ttl, total;
+	struct inet_peer __rcu **stack[PEER_MAXDEPTH];
 
 	total = compute_total();
 	if (total >= inet_peer_threshold)
@@ -547,7 +548,7 @@
 		ttl = inet_peer_maxttl
 				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
 					total / inet_peer_threshold * HZ;
-	while (!cleanup_once(ttl)) {
+	while (!cleanup_once(ttl, stack)) {
 		if (jiffies != now)
 			break;
 	}
diff -druN linux-libre-2.6.38-gnu/net/ipv4/ip_fragment.c linux-libre-2.6.38.8-gnu/net/ipv4/ip_fragment.c
--- linux-libre-2.6.38-gnu/net/ipv4/ip_fragment.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/ip_fragment.c	2011-06-02 21:35:11.000000000 -0400
@@ -223,31 +223,30 @@
 
 	if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
 		struct sk_buff *head = qp->q.fragments;
+		const struct iphdr *iph;
+		int err;
 
 		rcu_read_lock();
 		head->dev = dev_get_by_index_rcu(net, qp->iif);
 		if (!head->dev)
 			goto out_rcu_unlock;
 
+		/* skb dst is stale, drop it, and perform route lookup again */
+		skb_dst_drop(head);
+		iph = ip_hdr(head);
+		err = ip_route_input_noref(head, iph->daddr, iph->saddr,
+					   iph->tos, head->dev);
+		if (err)
+			goto out_rcu_unlock;
+
 		/*
-		 * Only search router table for the head fragment,
-		 * when defraging timeout at PRE_ROUTING HOOK.
+		 * Only an end host needs to send an ICMP
+		 * "Fragment Reassembly Timeout" message, per RFC792.
 		 */
-		if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) {
-			const struct iphdr *iph = ip_hdr(head);
-			int err = ip_route_input(head, iph->daddr, iph->saddr,
-						 iph->tos, head->dev);
-			if (unlikely(err))
-				goto out_rcu_unlock;
-
-			/*
-			 * Only an end host needs to send an ICMP
-			 * "Fragment Reassembly Timeout" message, per RFC792.
-			 */
-			if (skb_rtable(head)->rt_type != RTN_LOCAL)
-				goto out_rcu_unlock;
+		if (qp->user == IP_DEFRAG_CONNTRACK_IN &&
+		    skb_rtable(head)->rt_type != RTN_LOCAL)
+			goto out_rcu_unlock;
 
-		}
 
 		/* Send an ICMP "Fragment Reassembly Timeout" message. */
 		icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
diff -druN linux-libre-2.6.38-gnu/net/ipv4/ip_options.c linux-libre-2.6.38.8-gnu/net/ipv4/ip_options.c
--- linux-libre-2.6.38-gnu/net/ipv4/ip_options.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/ip_options.c	2011-06-02 21:35:11.000000000 -0400
@@ -329,7 +329,7 @@
 					pp_ptr = optptr + 2;
 					goto error;
 				}
-				if (skb) {
+				if (rt) {
 					memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
 					opt->is_changed = 1;
 				}
@@ -371,7 +371,7 @@
 						goto error;
 					}
 					opt->ts = optptr - iph;
-					if (skb) {
+					if (rt)  {
 						memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
 						timeptr = (__be32*)&optptr[optptr[2]+3];
 					}
@@ -603,7 +603,7 @@
 	unsigned long orefdst;
 	int err;
 
-	if (!opt->srr)
+	if (!opt->srr || !rt)
 		return 0;
 
 	if (skb->pkt_type != PACKET_HOST)
diff -druN linux-libre-2.6.38-gnu/net/ipv4/netfilter/arp_tables.c linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/arp_tables.c
--- linux-libre-2.6.38-gnu/net/ipv4/netfilter/arp_tables.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/arp_tables.c	2011-06-02 21:35:11.000000000 -0400
@@ -1065,6 +1065,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1486,6 +1487,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1738,6 +1740,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
 							 rev.revision, 1, &ret),
diff -druN linux-libre-2.6.38-gnu/net/ipv4/netfilter/ip_tables.c linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/ip_tables.c
--- linux-libre-2.6.38-gnu/net/ipv4/netfilter/ip_tables.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/ip_tables.c	2011-06-02 21:35:11.000000000 -0400
@@ -387,7 +387,7 @@
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
-				if (*stackptr == 0) {
+				if (*stackptr <= origptr) {
 					e = get_entry(table_base,
 					    private->underflow[hook]);
 					pr_debug("Underflow (this is normal) "
@@ -427,10 +427,10 @@
 			/* Verdict */
 			break;
 	} while (!acpar.hotdrop);
-	xt_info_rdunlock_bh();
 	pr_debug("Exiting %s; resetting sp from %u to %u\n",
 		 __func__, *stackptr, origptr);
 	*stackptr = origptr;
+	xt_info_rdunlock_bh();
 #ifdef DEBUG_ALLOW_ALL
 	return NF_ACCEPT;
 #else
@@ -1261,6 +1261,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1805,6 +1806,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2034,6 +2036,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IPT_SO_GET_REVISION_TARGET)
 			target = 1;
diff -druN linux-libre-2.6.38-gnu/net/ipv4/netfilter/ipt_CLUSTERIP.c linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/ipt_CLUSTERIP.c
--- linux-libre-2.6.38-gnu/net/ipv4/netfilter/ipt_CLUSTERIP.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/netfilter/ipt_CLUSTERIP.c	2011-06-02 21:35:11.000000000 -0400
@@ -669,8 +669,11 @@
 	char buffer[PROC_WRITELEN+1];
 	unsigned long nodenum;
 
-	if (copy_from_user(buffer, input, PROC_WRITELEN))
+	if (size > PROC_WRITELEN)
+		return -EIO;
+	if (copy_from_user(buffer, input, size))
 		return -EFAULT;
+	buffer[size] = 0;
 
 	if (*buffer == '+') {
 		nodenum = simple_strtoul(buffer+1, NULL, 10);
diff -druN linux-libre-2.6.38-gnu/net/ipv4/route.c linux-libre-2.6.38.8-gnu/net/ipv4/route.c
--- linux-libre-2.6.38-gnu/net/ipv4/route.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/route.c	2011-06-02 21:35:11.000000000 -0400
@@ -171,7 +171,7 @@
 
 const __u8 ip_tos2prio[16] = {
 	TC_PRIO_BESTEFFORT,
-	ECN_OR_COST(FILLER),
+	ECN_OR_COST(BESTEFFORT),
 	TC_PRIO_BESTEFFORT,
 	ECN_OR_COST(BESTEFFORT),
 	TC_PRIO_BULK,
diff -druN linux-libre-2.6.38-gnu/net/ipv4/sysctl_net_ipv4.c linux-libre-2.6.38.8-gnu/net/ipv4/sysctl_net_ipv4.c
--- linux-libre-2.6.38-gnu/net/ipv4/sysctl_net_ipv4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/sysctl_net_ipv4.c	2011-06-02 21:35:11.000000000 -0400
@@ -311,7 +311,6 @@
 		.mode		= 0644,
 		.proc_handler	= proc_do_large_bitmap,
 	},
-#ifdef CONFIG_IP_MULTICAST
 	{
 		.procname	= "igmp_max_memberships",
 		.data		= &sysctl_igmp_max_memberships,
@@ -319,8 +318,6 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
-
-#endif
 	{
 		.procname	= "igmp_max_msf",
 		.data		= &sysctl_igmp_max_msf,
diff -druN linux-libre-2.6.38-gnu/net/ipv4/tcp_input.c linux-libre-2.6.38.8-gnu/net/ipv4/tcp_input.c
--- linux-libre-2.6.38-gnu/net/ipv4/tcp_input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/tcp_input.c	2011-06-02 21:35:11.000000000 -0400
@@ -2659,7 +2659,7 @@
 #define DBGUNDO(x...) do { } while (0)
 #endif
 
-static void tcp_undo_cwr(struct sock *sk, const int undo)
+static void tcp_undo_cwr(struct sock *sk, const int undo_ssthresh)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 
@@ -2671,14 +2671,13 @@
 		else
 			tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1);
 
-		if (undo && tp->prior_ssthresh > tp->snd_ssthresh) {
+		if (undo_ssthresh && tp->prior_ssthresh > tp->snd_ssthresh) {
 			tp->snd_ssthresh = tp->prior_ssthresh;
 			TCP_ECN_withdraw_cwr(tp);
 		}
 	} else {
 		tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh);
 	}
-	tcp_moderate_cwnd(tp);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
@@ -2822,8 +2821,11 @@
 static inline void tcp_complete_cwr(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
-	tp->snd_cwnd_stamp = tcp_time_stamp;
+	/* Do not moderate cwnd if it's already undone in cwr or recovery */
+	if (tp->undo_marker && tp->snd_cwnd > tp->snd_ssthresh) {
+		tp->snd_cwnd = tp->snd_ssthresh;
+		tp->snd_cwnd_stamp = tcp_time_stamp;
+	}
 	tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
 }
 
diff -druN linux-libre-2.6.38-gnu/net/ipv4/tcp_output.c linux-libre-2.6.38.8-gnu/net/ipv4/tcp_output.c
--- linux-libre-2.6.38-gnu/net/ipv4/tcp_output.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv4/tcp_output.c	2011-06-02 21:35:11.000000000 -0400
@@ -1003,7 +1003,8 @@
 	int nlen;
 	u8 flags;
 
-	BUG_ON(len > skb->len);
+	if (WARN_ON(len > skb->len))
+		return -EINVAL;
 
 	nsize = skb_headlen(skb) - len;
 	if (nsize < 0)
diff -druN linux-libre-2.6.38-gnu/net/ipv6/inet6_connection_sock.c linux-libre-2.6.38.8-gnu/net/ipv6/inet6_connection_sock.c
--- linux-libre-2.6.38-gnu/net/ipv6/inet6_connection_sock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv6/inet6_connection_sock.c	2011-06-02 21:35:11.000000000 -0400
@@ -44,7 +44,7 @@
 		     !sk2->sk_bound_dev_if ||
 		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
 		    (!sk->sk_reuse || !sk2->sk_reuse ||
-		     ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) &&
+		     sk2->sk_state == TCP_LISTEN) &&
 		     ipv6_rcv_saddr_equal(sk, sk2))
 			break;
 	}
diff -druN linux-libre-2.6.38-gnu/net/ipv6/netfilter/ip6_tables.c linux-libre-2.6.38.8-gnu/net/ipv6/netfilter/ip6_tables.c
--- linux-libre-2.6.38-gnu/net/ipv6/netfilter/ip6_tables.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv6/netfilter/ip6_tables.c	2011-06-02 21:35:11.000000000 -0400
@@ -410,7 +410,7 @@
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
-				if (*stackptr == 0)
+				if (*stackptr <= origptr)
 					e = get_entry(table_base,
 					    private->underflow[hook]);
 				else
@@ -441,8 +441,8 @@
 			break;
 	} while (!acpar.hotdrop);
 
-	xt_info_rdunlock_bh();
 	*stackptr = origptr;
+	xt_info_rdunlock_bh();
 
 #ifdef DEBUG_ALLOW_ALL
 	return NF_ACCEPT;
@@ -1274,6 +1274,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1820,6 +1821,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2049,6 +2051,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IP6T_SO_GET_REVISION_TARGET)
 			target = 1;
diff -druN linux-libre-2.6.38-gnu/net/ipv6/route.c linux-libre-2.6.38.8-gnu/net/ipv6/route.c
--- linux-libre-2.6.38-gnu/net/ipv6/route.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv6/route.c	2011-06-02 21:35:11.000000000 -0400
@@ -1970,7 +1970,6 @@
 	rt->dst.output = ip6_output;
 	rt->rt6i_dev = net->loopback_dev;
 	rt->rt6i_idev = idev;
-	dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
 	rt->dst.obsolete = -1;
 
 	rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
diff -druN linux-libre-2.6.38-gnu/net/ipv6/sysctl_net_ipv6.c linux-libre-2.6.38.8-gnu/net/ipv6/sysctl_net_ipv6.c
--- linux-libre-2.6.38-gnu/net/ipv6/sysctl_net_ipv6.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv6/sysctl_net_ipv6.c	2011-06-02 21:35:11.000000000 -0400
@@ -17,6 +17,16 @@
 
 static struct ctl_table empty[1];
 
+static ctl_table ipv6_static_skeleton[] = {
+	{
+		.procname	= "neigh",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= empty,
+	},
+	{ }
+};
+
 static ctl_table ipv6_table_template[] = {
 	{
 		.procname	= "route",
@@ -37,12 +47,6 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
-	{
-		.procname	= "neigh",
-		.maxlen		= 0,
-		.mode		= 0555,
-		.child		= empty,
-	},
 	{ }
 };
 
@@ -160,7 +164,7 @@
 
 int ipv6_static_sysctl_register(void)
 {
-	ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
+	ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton);
 	if (ip6_base == NULL)
 		return -ENOMEM;
 	return 0;
diff -druN linux-libre-2.6.38-gnu/net/ipv6/udp.c linux-libre-2.6.38.8-gnu/net/ipv6/udp.c
--- linux-libre-2.6.38-gnu/net/ipv6/udp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/ipv6/udp.c	2011-06-02 21:35:11.000000000 -0400
@@ -1339,7 +1339,7 @@
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Check if there is enough headroom to insert fragment header. */
-	if ((skb_headroom(skb) < frag_hdr_sz) &&
+	if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
 	    pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
 		goto out;
 
diff -druN linux-libre-2.6.38-gnu/net/irda/af_irda.c linux-libre-2.6.38.8-gnu/net/irda/af_irda.c
--- linux-libre-2.6.38-gnu/net/irda/af_irda.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/irda/af_irda.c	2011-06-02 21:35:11.000000000 -0400
@@ -1297,8 +1297,7 @@
 	/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
 	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
 			       MSG_NOSIGNAL)) {
-		err = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	lock_sock(sk);
diff -druN linux-libre-2.6.38-gnu/net/irda/iriap.c linux-libre-2.6.38.8-gnu/net/irda/iriap.c
--- linux-libre-2.6.38-gnu/net/irda/iriap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/irda/iriap.c	2011-06-02 21:35:11.000000000 -0400
@@ -656,10 +656,16 @@
 	n = 1;
 
 	name_len = fp[n++];
+
+	IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
+
 	memcpy(name, fp+n, name_len); n+=name_len;
 	name[name_len] = '\0';
 
 	attr_len = fp[n++];
+
+	IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
+
 	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
diff -druN linux-libre-2.6.38-gnu/net/irda/irnet/irnet_ppp.c linux-libre-2.6.38.8-gnu/net/irda/irnet/irnet_ppp.c
--- linux-libre-2.6.38-gnu/net/irda/irnet/irnet_ppp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/irda/irnet/irnet_ppp.c	2011-06-02 21:35:11.000000000 -0400
@@ -105,6 +105,9 @@
 	      while(isspace(start[length - 1]))
 		length--;
 
+	      DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
+		     -EINVAL, CTRL_ERROR, "Invalid nickname.\n");
+
 	      /* Copy the name for later reuse */
 	      memcpy(ap->rname, start + 5, length - 5);
 	      ap->rname[length - 5] = '\0';
diff -druN linux-libre-2.6.38-gnu/net/l2tp/l2tp_eth.c linux-libre-2.6.38.8-gnu/net/l2tp/l2tp_eth.c
--- linux-libre-2.6.38-gnu/net/l2tp/l2tp_eth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/l2tp/l2tp_eth.c	2011-06-02 21:35:11.000000000 -0400
@@ -283,7 +283,7 @@
 	return 0;
 }
 
-static __net_initdata struct pernet_operations l2tp_eth_net_ops = {
+static struct pernet_operations l2tp_eth_net_ops = {
 	.init = l2tp_eth_init_net,
 	.id   = &l2tp_eth_net_id,
 	.size = sizeof(struct l2tp_eth_net),
diff -druN linux-libre-2.6.38-gnu/net/mac80211/cfg.c linux-libre-2.6.38.8-gnu/net/mac80211/cfg.c
--- linux-libre-2.6.38-gnu/net/mac80211/cfg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/mac80211/cfg.c	2011-06-02 21:35:11.000000000 -0400
@@ -228,11 +228,11 @@
 			goto out;
 
 		if (pairwise)
-			key = sta->ptk;
+			key = rcu_dereference(sta->ptk);
 		else if (key_idx < NUM_DEFAULT_KEYS)
-			key = sta->gtk[key_idx];
+			key = rcu_dereference(sta->gtk[key_idx]);
 	} else
-		key = sdata->keys[key_idx];
+		key = rcu_dereference(sdata->keys[key_idx]);
 
 	if (!key)
 		goto out;
@@ -904,8 +904,10 @@
 static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
 			    struct mpath_info *pinfo)
 {
-	if (mpath->next_hop)
-		memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
+	struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop);
+
+	if (next_hop_sta)
+		memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN);
 	else
 		memset(next_hop, 0, ETH_ALEN);
 
@@ -1471,6 +1473,8 @@
 	enum ieee80211_smps_mode old_req;
 	int err;
 
+	lockdep_assert_held(&sdata->u.mgd.mtx);
+
 	old_req = sdata->u.mgd.req_smps;
 	sdata->u.mgd.req_smps = smps_mode;
 
diff -druN linux-libre-2.6.38-gnu/net/mac80211/debugfs_netdev.c linux-libre-2.6.38.8-gnu/net/mac80211/debugfs_netdev.c
--- linux-libre-2.6.38-gnu/net/mac80211/debugfs_netdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/mac80211/debugfs_netdev.c	2011-06-02 21:35:11.000000000 -0400
@@ -172,9 +172,9 @@
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return -EOPNOTSUPP;
 
-	mutex_lock(&local->iflist_mtx);
+	mutex_lock(&sdata->u.mgd.mtx);
 	err = __ieee80211_request_smps(sdata, smps_mode);
-	mutex_unlock(&local->iflist_mtx);
+	mutex_unlock(&sdata->u.mgd.mtx);
 
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/net/mac80211/rc80211_minstrel_ht.c linux-libre-2.6.38.8-gnu/net/mac80211/rc80211_minstrel_ht.c
--- linux-libre-2.6.38-gnu/net/mac80211/rc80211_minstrel_ht.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/mac80211/rc80211_minstrel_ht.c	2011-06-02 21:35:11.000000000 -0400
@@ -639,18 +639,14 @@
 	struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
 	struct ieee80211_local *local = hw_to_local(mp->hw);
 	u16 sta_cap = sta->ht_cap.cap;
+	int n_supported = 0;
 	int ack_dur;
 	int stbc;
 	int i;
 
 	/* fall back to the old minstrel for legacy stations */
-	if (!sta->ht_cap.ht_supported) {
-		msp->is_ht = false;
-		memset(&msp->legacy, 0, sizeof(msp->legacy));
-		msp->legacy.r = msp->ratelist;
-		msp->legacy.sample_table = msp->sample_table;
-		return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
-	}
+	if (!sta->ht_cap.ht_supported)
+		goto use_legacy;
 
 	BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
 		MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS);
@@ -705,7 +701,22 @@
 
 		mi->groups[i].supported =
 			mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
+
+		if (mi->groups[i].supported)
+			n_supported++;
 	}
+
+	if (!n_supported)
+		goto use_legacy;
+
+	return;
+
+use_legacy:
+	msp->is_ht = false;
+	memset(&msp->legacy, 0, sizeof(msp->legacy));
+	msp->legacy.r = msp->ratelist;
+	msp->legacy.sample_table = msp->sample_table;
+	return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
 }
 
 static void
diff -druN linux-libre-2.6.38-gnu/net/mac80211/sta_info.c linux-libre-2.6.38.8-gnu/net/mac80211/sta_info.c
--- linux-libre-2.6.38-gnu/net/mac80211/sta_info.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/mac80211/sta_info.c	2011-06-02 21:35:11.000000000 -0400
@@ -243,6 +243,7 @@
 	memcpy(sta->sta.addr, addr, ETH_ALEN);
 	sta->local = local;
 	sta->sdata = sdata;
+	sta->last_rx = jiffies;
 
 	ewma_init(&sta->avg_signal, 1024, 8);
 
diff -druN linux-libre-2.6.38-gnu/net/netfilter/nf_conntrack_h323_asn1.c linux-libre-2.6.38.8-gnu/net/netfilter/nf_conntrack_h323_asn1.c
--- linux-libre-2.6.38-gnu/net/netfilter/nf_conntrack_h323_asn1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/netfilter/nf_conntrack_h323_asn1.c	2011-06-02 21:35:11.000000000 -0400
@@ -631,7 +631,7 @@
 		CHECK_BOUND(bs, 2);
 		count = *bs->cur++;
 		count <<= 8;
-		count = *bs->cur++;
+		count += *bs->cur++;
 		break;
 	case SEMI:
 		BYTE_ALIGN(bs);
diff -druN linux-libre-2.6.38-gnu/net/rose/rose_subr.c linux-libre-2.6.38.8-gnu/net/rose/rose_subr.c
--- linux-libre-2.6.38-gnu/net/rose/rose_subr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/rose/rose_subr.c	2011-06-02 21:35:11.000000000 -0400
@@ -290,10 +290,15 @@
 				facilities->source_ndigis = 0;
 				facilities->dest_ndigis   = 0;
 				for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
-					if (pt[6] & AX25_HBIT)
+					if (pt[6] & AX25_HBIT) {
+						if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
+							return -1;
 						memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
-					else
+					} else {
+						if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
+							return -1;
 						memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
+					}
 				}
 			}
 			p   += l + 2;
@@ -333,6 +338,11 @@
 
 		case 0xC0:
 			l = p[1];
+
+			/* Prevent overflows*/
+			if (l < 10 || l > 20)
+				return -1;
+
 			if (*p == FAC_CCITT_DEST_NSAP) {
 				memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
 				memcpy(callsign, p + 12,   l - 10);
@@ -373,12 +383,16 @@
 			switch (*p) {
 			case FAC_NATIONAL:		/* National */
 				len = rose_parse_national(p + 1, facilities, facilities_len - 1);
+				if (len < 0)
+					return 0;
 				facilities_len -= len + 1;
 				p += len + 1;
 				break;
 
 			case FAC_CCITT:		/* CCITT */
 				len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
+				if (len < 0)
+					return 0;
 				facilities_len -= len + 1;
 				p += len + 1;
 				break;
diff -druN linux-libre-2.6.38-gnu/net/sched/sch_sfq.c linux-libre-2.6.38.8-gnu/net/sched/sch_sfq.c
--- linux-libre-2.6.38-gnu/net/sched/sch_sfq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sched/sch_sfq.c	2011-06-02 21:35:11.000000000 -0400
@@ -361,7 +361,7 @@
 {
 	struct sfq_sched_data *q = qdisc_priv(sch);
 	unsigned int hash;
-	sfq_index x;
+	sfq_index x, qlen;
 	struct sfq_slot *slot;
 	int uninitialized_var(ret);
 
@@ -405,20 +405,12 @@
 	if (++sch->q.qlen <= q->limit)
 		return NET_XMIT_SUCCESS;
 
+	qlen = slot->qlen;
 	sfq_drop(sch);
-	return NET_XMIT_CN;
-}
-
-static struct sk_buff *
-sfq_peek(struct Qdisc *sch)
-{
-	struct sfq_sched_data *q = qdisc_priv(sch);
-
-	/* No active slots */
-	if (q->tail == NULL)
-		return NULL;
-
-	return q->slots[q->tail->next].skblist_next;
+	/* Return Congestion Notification only if we dropped a packet
+	 * from this flow.
+	 */
+	return (qlen != slot->qlen) ? NET_XMIT_CN : NET_XMIT_SUCCESS;
 }
 
 static struct sk_buff *
@@ -679,7 +671,7 @@
 	.priv_size	=	sizeof(struct sfq_sched_data),
 	.enqueue	=	sfq_enqueue,
 	.dequeue	=	sfq_dequeue,
-	.peek		=	sfq_peek,
+	.peek		=	qdisc_peek_dequeued,
 	.drop		=	sfq_drop,
 	.init		=	sfq_init,
 	.reset		=	sfq_reset,
diff -druN linux-libre-2.6.38-gnu/net/sctp/associola.c linux-libre-2.6.38.8-gnu/net/sctp/associola.c
--- linux-libre-2.6.38-gnu/net/sctp/associola.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sctp/associola.c	2011-06-02 21:35:11.000000000 -0400
@@ -64,6 +64,7 @@
 /* Forward declarations for internal functions. */
 static void sctp_assoc_bh_rcv(struct work_struct *work);
 static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
+static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc);
 
 /* Keep track of the new idr low so that we don't re-use association id
  * numbers too fast.  It is protected by they idr spin lock is in the
@@ -446,6 +447,9 @@
 	/* Free any cached ASCONF_ACK chunk. */
 	sctp_assoc_free_asconf_acks(asoc);
 
+	/* Free the ASCONF queue. */
+	sctp_assoc_free_asconf_queue(asoc);
+
 	/* Free any cached ASCONF chunk. */
 	if (asoc->addip_last_asconf)
 		sctp_chunk_free(asoc->addip_last_asconf);
@@ -1576,6 +1580,18 @@
 	return error;
 }
 
+/* Free the ASCONF queue */
+static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc)
+{
+	struct sctp_chunk *asconf;
+	struct sctp_chunk *tmp;
+
+	list_for_each_entry_safe(asconf, tmp, &asoc->addip_chunk_list, list) {
+		list_del_init(&asconf->list);
+		sctp_chunk_free(asconf);
+	}
+}
+
 /* Free asconf_ack cache */
 static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc)
 {
diff -druN linux-libre-2.6.38-gnu/net/sctp/bind_addr.c linux-libre-2.6.38.8-gnu/net/sctp/bind_addr.c
--- linux-libre-2.6.38-gnu/net/sctp/bind_addr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sctp/bind_addr.c	2011-06-02 21:35:11.000000000 -0400
@@ -140,14 +140,12 @@
 /* Dispose of the address list. */
 static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
 {
-	struct sctp_sockaddr_entry *addr;
-	struct list_head *pos, *temp;
+	struct sctp_sockaddr_entry *addr, *temp;
 
 	/* Empty the bind address list. */
-	list_for_each_safe(pos, temp, &bp->address_list) {
-		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
-		list_del(pos);
-		kfree(addr);
+	list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
+		list_del_rcu(&addr->list);
+		call_rcu(&addr->rcu, sctp_local_addr_free);
 		SCTP_DBG_OBJCNT_DEC(addr);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/net/sctp/protocol.c linux-libre-2.6.38.8-gnu/net/sctp/protocol.c
--- linux-libre-2.6.38-gnu/net/sctp/protocol.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sctp/protocol.c	2011-06-02 21:35:11.000000000 -0400
@@ -1204,7 +1204,7 @@
 		if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0)
 			continue;
 		sctp_assoc_hashtable = (struct sctp_hashbucket *)
-					__get_free_pages(GFP_ATOMIC, order);
+			__get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
 	} while (!sctp_assoc_hashtable && --order > 0);
 	if (!sctp_assoc_hashtable) {
 		pr_err("Failed association hash alloc\n");
@@ -1237,7 +1237,7 @@
 		if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
 			continue;
 		sctp_port_hashtable = (struct sctp_bind_hashbucket *)
-					__get_free_pages(GFP_ATOMIC, order);
+			__get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
 	} while (!sctp_port_hashtable && --order > 0);
 	if (!sctp_port_hashtable) {
 		pr_err("Failed bind hash alloc\n");
diff -druN linux-libre-2.6.38-gnu/net/socket.c linux-libre-2.6.38.8-gnu/net/socket.c
--- linux-libre-2.6.38-gnu/net/socket.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/socket.c	2011-06-02 21:35:11.000000000 -0400
@@ -2117,14 +2117,16 @@
 		 */
 		if (MSG_CMSG_COMPAT & flags) {
 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
-					    &msg_sys, flags, datagrams);
+					    &msg_sys, flags & ~MSG_WAITFORONE,
+					    datagrams);
 			if (err < 0)
 				break;
 			err = __put_user(err, &compat_entry->msg_len);
 			++compat_entry;
 		} else {
 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
-					    &msg_sys, flags, datagrams);
+					    &msg_sys, flags & ~MSG_WAITFORONE,
+					    datagrams);
 			if (err < 0)
 				break;
 			err = put_user(err, &entry->msg_len);
@@ -2583,23 +2585,123 @@
 
 static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 {
+	struct compat_ethtool_rxnfc __user *compat_rxnfc;
+	bool convert_in = false, convert_out = false;
+	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
+	struct ethtool_rxnfc __user *rxnfc;
 	struct ifreq __user *ifr;
+	u32 rule_cnt = 0, actual_rule_cnt;
+	u32 ethcmd;
 	u32 data;
-	void __user *datap;
+	int ret;
 
-	ifr = compat_alloc_user_space(sizeof(*ifr));
+	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
+	compat_rxnfc = compat_ptr(data);
+
+	if (get_user(ethcmd, &compat_rxnfc->cmd))
 		return -EFAULT;
 
-	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+	/* Most ethtool structures are defined without padding.
+	 * Unfortunately struct ethtool_rxnfc is an exception.
+	 */
+	switch (ethcmd) {
+	default:
+		break;
+	case ETHTOOL_GRXCLSRLALL:
+		/* Buffer size is variable */
+		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
+			return -EFAULT;
+		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
+			return -ENOMEM;
+		buf_size += rule_cnt * sizeof(u32);
+		/* fall through */
+	case ETHTOOL_GRXRINGS:
+	case ETHTOOL_GRXCLSRLCNT:
+	case ETHTOOL_GRXCLSRULE:
+		convert_out = true;
+		/* fall through */
+	case ETHTOOL_SRXCLSRLDEL:
+	case ETHTOOL_SRXCLSRLINS:
+		buf_size += sizeof(struct ethtool_rxnfc);
+		convert_in = true;
+		break;
+	}
+
+	ifr = compat_alloc_user_space(buf_size);
+	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
+
+	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 		return -EFAULT;
 
-	datap = compat_ptr(data);
-	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
+	if (put_user(convert_in ? rxnfc : compat_ptr(data),
+		     &ifr->ifr_ifru.ifru_data))
 		return -EFAULT;
 
-	return dev_ioctl(net, SIOCETHTOOL, ifr);
+	if (convert_in) {
+		/* We expect there to be holes between fs.m_u and
+		 * fs.ring_cookie and at the end of fs, but nowhere else.
+		 */
+		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) +
+			     sizeof(compat_rxnfc->fs.m_u) !=
+			     offsetof(struct ethtool_rxnfc, fs.m_u) +
+			     sizeof(rxnfc->fs.m_u));
+		BUILD_BUG_ON(
+			offsetof(struct compat_ethtool_rxnfc, fs.location) -
+			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
+			offsetof(struct ethtool_rxnfc, fs.location) -
+			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
+
+		if (copy_in_user(rxnfc, compat_rxnfc,
+				 (void *)(&rxnfc->fs.m_u + 1) -
+				 (void *)rxnfc) ||
+		    copy_in_user(&rxnfc->fs.ring_cookie,
+				 &compat_rxnfc->fs.ring_cookie,
+				 (void *)(&rxnfc->fs.location + 1) -
+				 (void *)&rxnfc->fs.ring_cookie) ||
+		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
+				 sizeof(rxnfc->rule_cnt)))
+			return -EFAULT;
+	}
+
+	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
+	if (ret)
+		return ret;
+
+	if (convert_out) {
+		if (copy_in_user(compat_rxnfc, rxnfc,
+				 (const void *)(&rxnfc->fs.m_u + 1) -
+				 (const void *)rxnfc) ||
+		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
+				 &rxnfc->fs.ring_cookie,
+				 (const void *)(&rxnfc->fs.location + 1) -
+				 (const void *)&rxnfc->fs.ring_cookie) ||
+		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
+				 sizeof(rxnfc->rule_cnt)))
+			return -EFAULT;
+
+		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
+			/* As an optimisation, we only copy the actual
+			 * number of rules that the underlying
+			 * function returned.  Since Mallory might
+			 * change the rule count in user memory, we
+			 * check that it is less than the rule count
+			 * originally given (as the user buffer size),
+			 * which has been range-checked.
+			 */
+			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
+				return -EFAULT;
+			if (actual_rule_cnt < rule_cnt)
+				rule_cnt = actual_rule_cnt;
+			if (copy_in_user(&compat_rxnfc->rule_locs[0],
+					 &rxnfc->rule_locs[0],
+					 rule_cnt * sizeof(u32)))
+				return -EFAULT;
+		}
+	}
+
+	return 0;
 }
 
 static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
diff -druN linux-libre-2.6.38-gnu/net/sunrpc/auth_gss/gss_krb5_mech.c linux-libre-2.6.38.8-gnu/net/sunrpc/auth_gss/gss_krb5_mech.c
--- linux-libre-2.6.38-gnu/net/sunrpc/auth_gss/gss_krb5_mech.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sunrpc/auth_gss/gss_krb5_mech.c	2011-06-02 21:35:11.000000000 -0400
@@ -427,7 +427,7 @@
 context_derive_keys_rc4(struct krb5_ctx *ctx)
 {
 	struct crypto_hash *hmac;
-	static const char sigkeyconstant[] = "signaturekey";
+	char sigkeyconstant[] = "signaturekey";
 	int slen = strlen(sigkeyconstant) + 1;	/* include null terminator */
 	struct hash_desc desc;
 	struct scatterlist sg[1];
diff -druN linux-libre-2.6.38-gnu/net/sunrpc/clnt.c linux-libre-2.6.38.8-gnu/net/sunrpc/clnt.c
--- linux-libre-2.6.38-gnu/net/sunrpc/clnt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sunrpc/clnt.c	2011-06-02 21:35:11.000000000 -0400
@@ -436,7 +436,9 @@
 		if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
 			rovr->tk_flags |= RPC_TASK_KILLED;
 			rpc_exit(rovr, -EIO);
-			rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr);
+			if (RPC_IS_QUEUED(rovr))
+				rpc_wake_up_queued_task(rovr->tk_waitqueue,
+							rovr);
 		}
 	}
 	spin_unlock(&clnt->cl_lock);
diff -druN linux-libre-2.6.38-gnu/net/sunrpc/sched.c linux-libre-2.6.38.8-gnu/net/sunrpc/sched.c
--- linux-libre-2.6.38-gnu/net/sunrpc/sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sunrpc/sched.c	2011-06-02 21:35:11.000000000 -0400
@@ -637,14 +637,12 @@
 			save_callback = task->tk_callback;
 			task->tk_callback = NULL;
 			save_callback(task);
-		}
-
-		/*
-		 * Perform the next FSM step.
-		 * tk_action may be NULL when the task has been killed
-		 * by someone else.
-		 */
-		if (!RPC_IS_QUEUED(task)) {
+		} else {
+			/*
+			 * Perform the next FSM step.
+			 * tk_action may be NULL when the task has been killed
+			 * by someone else.
+			 */
 			if (task->tk_action == NULL)
 				break;
 			task->tk_action(task);
diff -druN linux-libre-2.6.38-gnu/net/sunrpc/xprtsock.c linux-libre-2.6.38.8-gnu/net/sunrpc/xprtsock.c
--- linux-libre-2.6.38-gnu/net/sunrpc/xprtsock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/sunrpc/xprtsock.c	2011-06-02 21:35:11.000000000 -0400
@@ -710,6 +710,8 @@
 	if (sk == NULL)
 		return;
 
+	transport->srcport = 0;
+
 	write_lock_bh(&sk->sk_callback_lock);
 	transport->inet = NULL;
 	transport->sock = NULL;
@@ -1342,7 +1344,6 @@
 	case TCP_CLOSE_WAIT:
 		/* The server initiated a shutdown of the socket */
 		xprt_force_disconnect(xprt);
-	case TCP_SYN_SENT:
 		xprt->connect_cookie++;
 	case TCP_CLOSING:
 		/*
@@ -1756,6 +1757,7 @@
 static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 {
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+	int ret = -ENOTCONN;
 
 	if (!transport->inet) {
 		struct sock *sk = sock->sk;
@@ -1787,12 +1789,22 @@
 	}
 
 	if (!xprt_bound(xprt))
-		return -ENOTCONN;
+		goto out;
 
 	/* Tell the socket layer to start connecting... */
 	xprt->stat.connect_count++;
 	xprt->stat.connect_start = jiffies;
-	return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
+	ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
+	switch (ret) {
+	case 0:
+	case -EINPROGRESS:
+		/* SYN_SENT! */
+		xprt->connect_cookie++;
+		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
+			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+	}
+out:
+	return ret;
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/net/unix/af_unix.c linux-libre-2.6.38.8-gnu/net/unix/af_unix.c
--- linux-libre-2.6.38-gnu/net/unix/af_unix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/unix/af_unix.c	2011-06-02 21:35:11.000000000 -0400
@@ -524,6 +524,8 @@
 			      int, int);
 static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
 				  struct msghdr *, size_t);
+static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
+				  struct msghdr *, size_t, int);
 
 static const struct proto_ops unix_stream_ops = {
 	.family =	PF_UNIX,
@@ -583,7 +585,7 @@
 	.setsockopt =	sock_no_setsockopt,
 	.getsockopt =	sock_no_getsockopt,
 	.sendmsg =	unix_seqpacket_sendmsg,
-	.recvmsg =	unix_dgram_recvmsg,
+	.recvmsg =	unix_seqpacket_recvmsg,
 	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 };
@@ -1695,6 +1697,18 @@
 	return unix_dgram_sendmsg(kiocb, sock, msg, len);
 }
 
+static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
+			      struct msghdr *msg, size_t size,
+			      int flags)
+{
+	struct sock *sk = sock->sk;
+
+	if (sk->sk_state != TCP_ESTABLISHED)
+		return -ENOTCONN;
+
+	return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
+}
+
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
 	struct unix_sock *u = unix_sk(sk);
diff -druN linux-libre-2.6.38-gnu/net/wireless/nl80211.c linux-libre-2.6.38.8-gnu/net/wireless/nl80211.c
--- linux-libre-2.6.38-gnu/net/wireless/nl80211.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/wireless/nl80211.c	2011-06-02 21:35:11.000000000 -0400
@@ -1679,14 +1679,6 @@
 		if (err)
 			goto out;
 
-		if (!(rdev->wiphy.flags &
-				WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) {
-			if (!key.def_uni || !key.def_multi) {
-				err = -EOPNOTSUPP;
-				goto out;
-			}
-		}
-
 		err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
 						 key.def_uni, key.def_multi);
 
diff -druN linux-libre-2.6.38-gnu/net/xfrm/xfrm_policy.c linux-libre-2.6.38.8-gnu/net/xfrm/xfrm_policy.c
--- linux-libre-2.6.38-gnu/net/xfrm/xfrm_policy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/net/xfrm/xfrm_policy.c	2011-06-02 21:35:11.000000000 -0400
@@ -1778,6 +1778,8 @@
 				goto no_transform;
 			}
 
+			dst_hold(&xdst->u.dst);
+
 			spin_lock_bh(&xfrm_policy_sk_bundle_lock);
 			xdst->u.dst.next = xfrm_policy_sk_bundles;
 			xfrm_policy_sk_bundles = &xdst->u.dst;
diff -druN linux-libre-2.6.38-gnu/scripts/checkpatch.pl linux-libre-2.6.38.8-gnu/scripts/checkpatch.pl
--- linux-libre-2.6.38-gnu/scripts/checkpatch.pl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/scripts/checkpatch.pl	2011-06-02 21:35:11.000000000 -0400
@@ -2809,9 +2809,9 @@
 			WARN("consider using a completion\n" . $herecurr);
 
 		}
-# recommend strict_strto* over simple_strto*
+# recommend kstrto* over simple_strto*
 		if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
-			WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+			WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr);
 		}
 # check for __initcall(), use device_initcall() explicitly please
 		if ($line =~ /^.\s*__initcall\s*\(/) {
diff -druN linux-libre-2.6.38-gnu/scripts/kconfig/conf.c linux-libre-2.6.38.8-gnu/scripts/kconfig/conf.c
--- linux-libre-2.6.38-gnu/scripts/kconfig/conf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/scripts/kconfig/conf.c	2011-06-02 21:35:11.000000000 -0400
@@ -332,7 +332,7 @@
 		}
 		if (!child)
 			continue;
-		if (line[strlen(line) - 1] == '?') {
+		if (line[0] && line[strlen(line) - 1] == '?') {
 			print_help(child);
 			continue;
 		}
diff -druN linux-libre-2.6.38-gnu/security/apparmor/lsm.c linux-libre-2.6.38.8-gnu/security/apparmor/lsm.c
--- linux-libre-2.6.38-gnu/security/apparmor/lsm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/security/apparmor/lsm.c	2011-06-02 21:35:11.000000000 -0400
@@ -592,7 +592,8 @@
 			sa.aad.op = OP_SETPROCATTR;
 			sa.aad.info = name;
 			sa.aad.error = -EINVAL;
-			return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
+			return aa_audit(AUDIT_APPARMOR_DENIED,
+					__aa_current_profile(), GFP_KERNEL,
 					&sa, NULL);
 		}
 	} else if (strcmp(name, "exec") == 0) {
diff -druN linux-libre-2.6.38-gnu/security/selinux/ss/policydb.c linux-libre-2.6.38.8-gnu/security/selinux/ss/policydb.c
--- linux-libre-2.6.38-gnu/security/selinux/ss/policydb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/security/selinux/ss/policydb.c	2011-06-02 21:35:11.000000000 -0400
@@ -497,7 +497,7 @@
 		goto out;
 
 	rc = flex_array_prealloc(p->type_val_to_struct_array, 0,
-				 p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO);
+				 p->p_types.nprim, GFP_KERNEL | __GFP_ZERO);
 	if (rc)
 		goto out;
 
@@ -514,7 +514,7 @@
 			goto out;
 
 		rc = flex_array_prealloc(p->sym_val_to_name[i],
-					 0, p->symtab[i].nprim - 1,
+					 0, p->symtab[i].nprim,
 					 GFP_KERNEL | __GFP_ZERO);
 		if (rc)
 			goto out;
@@ -2286,7 +2286,7 @@
 		goto bad;
 
 	/* preallocate so we don't have to worry about the put ever failing */
-	rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
+	rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim,
 				 GFP_KERNEL | __GFP_ZERO);
 	if (rc)
 		goto bad;
diff -druN linux-libre-2.6.38-gnu/security/tomoyo/file.c linux-libre-2.6.38.8-gnu/security/tomoyo/file.c
--- linux-libre-2.6.38-gnu/security/tomoyo/file.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/security/tomoyo/file.c	2011-06-02 21:35:11.000000000 -0400
@@ -927,7 +927,7 @@
 				 struct path *path, const int flag)
 {
 	const u8 acc_mode = ACC_MODE(flag);
-	int error = -ENOMEM;
+	int error = 0;
 	struct tomoyo_path_info buf;
 	struct tomoyo_request_info r;
 	int idx;
@@ -938,9 +938,6 @@
 	buf.name = NULL;
 	r.mode = TOMOYO_CONFIG_DISABLED;
 	idx = tomoyo_read_lock();
-	if (!tomoyo_get_realpath(&buf, path))
-		goto out;
-	error = 0;
 	/*
 	 * If the filename is specified by "deny_rewrite" keyword,
 	 * we need to check "allow_rewrite" permission when the filename is not
diff -druN linux-libre-2.6.38-gnu/sound/core/init.c linux-libre-2.6.38.8-gnu/sound/core/init.c
--- linux-libre-2.6.38-gnu/sound/core/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/core/init.c	2011-06-02 21:35:11.000000000 -0400
@@ -848,6 +848,7 @@
 		return -ENOMEM;
 	mfile->file = file;
 	mfile->disconnected_f_op = NULL;
+	INIT_LIST_HEAD(&mfile->shutdown_list);
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
@@ -883,6 +884,9 @@
 	list_for_each_entry(mfile, &card->files_list, list) {
 		if (mfile->file == file) {
 			list_del(&mfile->list);
+			spin_lock(&shutdown_lock);
+			list_del(&mfile->shutdown_list);
+			spin_unlock(&shutdown_lock);
 			if (mfile->disconnected_f_op)
 				fops_put(mfile->disconnected_f_op);
 			found = mfile;
diff -druN linux-libre-2.6.38-gnu/sound/core/pcm_lib.c linux-libre-2.6.38.8-gnu/sound/core/pcm_lib.c
--- linux-libre-2.6.38-gnu/sound/core/pcm_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/core/pcm_lib.c	2011-06-02 21:35:11.000000000 -0400
@@ -375,6 +375,7 @@
 	}
 
 	if (runtime->no_period_wakeup) {
+		snd_pcm_sframes_t xrun_threshold;
 		/*
 		 * Without regular period interrupts, we have to check
 		 * the elapsed time to detect xruns.
@@ -383,7 +384,8 @@
 		if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
 			goto no_delta_check;
 		hdelta = jdelta - delta * HZ / runtime->rate;
-		while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
+		xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1;
+		while (hdelta > xrun_threshold) {
 			delta += runtime->buffer_size;
 			hw_base += runtime->buffer_size;
 			if (hw_base >= runtime->boundary)
diff -druN linux-libre-2.6.38-gnu/sound/core/pcm_native.c linux-libre-2.6.38.8-gnu/sound/core/pcm_native.c
--- linux-libre-2.6.38-gnu/sound/core/pcm_native.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/core/pcm_native.c	2011-06-02 21:35:11.000000000 -0400
@@ -3201,15 +3201,6 @@
 EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
 #endif /* SNDRV_PCM_INFO_MMAP */
 
-/* mmap callback with pgprot_noncached */
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
-			       struct vm_area_struct *area)
-{
-	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
-	return snd_pcm_default_mmap(substream, area);
-}
-EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
-
 /*
  * mmap DMA buffer
  */
diff -druN linux-libre-2.6.38-gnu/sound/drivers/aloop.c linux-libre-2.6.38.8-gnu/sound/drivers/aloop.c
--- linux-libre-2.6.38-gnu/sound/drivers/aloop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/drivers/aloop.c	2011-06-02 21:35:11.000000000 -0400
@@ -482,8 +482,9 @@
 			cable->streams[SNDRV_PCM_STREAM_CAPTURE];
 	unsigned long delta_play = 0, delta_capt = 0;
 	unsigned int running;
+	unsigned long flags;
 
-	spin_lock(&cable->lock);	
+	spin_lock_irqsave(&cable->lock, flags);
 	running = cable->running ^ cable->pause;
 	if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
 		delta_play = jiffies - dpcm_play->last_jiffies;
@@ -495,10 +496,8 @@
 		dpcm_capt->last_jiffies += delta_capt;
 	}
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
 		
 	if (delta_play > delta_capt) {
 		loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
@@ -510,14 +509,14 @@
 		delta_capt = delta_play;
 	}
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
+
 	/* note delta_capt == delta_play at this moment */
 	loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
 	loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
-	spin_unlock(&cable->lock);
+ unlock:
+	spin_unlock_irqrestore(&cable->lock, flags);
 	return running;
 }
 
diff -druN linux-libre-2.6.38-gnu/sound/oss/dev_table.h linux-libre-2.6.38.8-gnu/sound/oss/dev_table.h
--- linux-libre-2.6.38-gnu/sound/oss/dev_table.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/oss/dev_table.h	2011-06-02 21:35:11.000000000 -0400
@@ -271,7 +271,7 @@
 	void (*reset) (int dev);
 	void (*hw_control) (int dev, unsigned char *event);
 	int (*load_patch) (int dev, int format, const char __user *addr,
-	     int offs, int count, int pmgr_flag);
+	     int count, int pmgr_flag);
 	void (*aftertouch) (int dev, int voice, int pressure);
 	void (*controller) (int dev, int voice, int ctrl_num, int value);
 	void (*panning) (int dev, int voice, int value);
diff -druN linux-libre-2.6.38-gnu/sound/oss/midi_synth.c linux-libre-2.6.38.8-gnu/sound/oss/midi_synth.c
--- linux-libre-2.6.38-gnu/sound/oss/midi_synth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/oss/midi_synth.c	2011-06-02 21:35:11.000000000 -0400
@@ -476,7 +476,7 @@
 
 int
 midi_synth_load_patch(int dev, int format, const char __user *addr,
-		      int offs, int count, int pmgr_flag)
+		      int count, int pmgr_flag)
 {
 	int             orig_dev = synth_devs[dev]->midi_dev;
 
@@ -491,33 +491,29 @@
 	if (!prefix_cmd(orig_dev, 0xf0))
 		return 0;
 
+	/* Invalid patch format */
 	if (format != SYSEX_PATCH)
-	{
-/*		  printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
 		  return -EINVAL;
-	}
+
+	/* Patch header too short */
 	if (count < hdr_size)
-	{
-/*		printk("MIDI Error: Patch header too short\n");*/
 		return -EINVAL;
-	}
+
 	count -= hdr_size;
 
 	/*
-	 * Copy the header from user space but ignore the first bytes which have
-	 * been transferred already.
+	 * Copy the header from user space
 	 */
 
-	if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
+	if (copy_from_user(&sysex, addr, hdr_size))
 		return -EFAULT;
- 
- 	if (count < sysex.len)
-	{
-/*		printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
+
+	/* Sysex record too short */
+	if ((unsigned)count < (unsigned)sysex.len)
 		sysex.len = count;
-	}
-  	left = sysex.len;
-  	src_offs = 0;
+
+	left = sysex.len;
+	src_offs = 0;
 
 	for (i = 0; i < left && !signal_pending(current); i++)
 	{
diff -druN linux-libre-2.6.38-gnu/sound/oss/midi_synth.h linux-libre-2.6.38.8-gnu/sound/oss/midi_synth.h
--- linux-libre-2.6.38-gnu/sound/oss/midi_synth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/oss/midi_synth.h	2011-06-02 21:35:11.000000000 -0400
@@ -8,7 +8,7 @@
 void midi_synth_close (int dev);
 void midi_synth_hw_control (int dev, unsigned char *event);
 int midi_synth_load_patch (int dev, int format, const char __user * addr,
-		 int offs, int count, int pmgr_flag);
+		 int count, int pmgr_flag);
 void midi_synth_panning (int dev, int channel, int pressure);
 void midi_synth_aftertouch (int dev, int channel, int pressure);
 void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
diff -druN linux-libre-2.6.38-gnu/sound/oss/opl3.c linux-libre-2.6.38.8-gnu/sound/oss/opl3.c
--- linux-libre-2.6.38-gnu/sound/oss/opl3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/oss/opl3.c	2011-06-02 21:35:11.000000000 -0400
@@ -820,7 +820,7 @@
 }
 
 static int opl3_load_patch(int dev, int format, const char __user *addr,
-		int offs, int count, int pmgr_flag)
+		int count, int pmgr_flag)
 {
 	struct sbi_instrument ins;
 
@@ -830,11 +830,7 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * What the fuck is going on here?  We leave junk in the beginning
-	 * of ins and then check the field pretty close to that beginning?
-	 */
-	if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs))
+	if (copy_from_user(&ins, addr, sizeof(ins)))
 		return -EFAULT;
 
 	if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
@@ -849,6 +845,10 @@
 
 static void opl3_panning(int dev, int voice, int value)
 {
+
+	if (voice < 0 || voice >= devc->nr_voice)
+		return;
+
 	devc->voc[voice].panning = value;
 }
 
@@ -1066,8 +1066,15 @@
 
 static void opl3_setup_voice(int dev, int voice, int chn)
 {
-	struct channel_info *info =
-	&synth_devs[dev]->chn_info[chn];
+	struct channel_info *info;
+
+	if (voice < 0 || voice >= devc->nr_voice)
+		return;
+
+	if (chn < 0 || chn > 15)
+		return;
+
+	info = &synth_devs[dev]->chn_info[chn];
 
 	opl3_set_instr(dev, voice, info->pgm_num);
 
diff -druN linux-libre-2.6.38-gnu/sound/oss/sequencer.c linux-libre-2.6.38.8-gnu/sound/oss/sequencer.c
--- linux-libre-2.6.38-gnu/sound/oss/sequencer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/oss/sequencer.c	2011-06-02 21:35:11.000000000 -0400
@@ -241,7 +241,7 @@
 				return -ENXIO;
 
 			fmt = (*(short *) &event_rec[0]) & 0xffff;
-			err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0);
+			err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0);
 			if (err < 0)
 				return err;
 
diff -druN linux-libre-2.6.38-gnu/sound/pci/asihpi/hpioctl.c linux-libre-2.6.38.8-gnu/sound/pci/asihpi/hpioctl.c
--- linux-libre-2.6.38-gnu/sound/pci/asihpi/hpioctl.c	2012-03-24 01:20:12.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/asihpi/hpioctl.c	2012-03-25 07:18:59.000000000 -0400
@@ -149,6 +149,11 @@
 		goto out;
 	}
 
+	if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	pa = &adapters[hm->h.adapter_index];
 	hr->h.size = 0;
 	if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
diff -druN linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctatc.c linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctatc.c
--- linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctatc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctatc.c	2011-06-02 21:35:11.000000000 -0400
@@ -869,7 +869,7 @@
 	mutex_lock(&atc->atc_mutex);
 	dao->ops->get_spos(dao, &status);
 	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
-		status &= ((~IEC958_AES3_CON_FS) << 24);
+		status &= ~(IEC958_AES3_CON_FS << 24);
 		status |= (iec958_con_fs << 24);
 		dao->ops->set_spos(dao, status);
 		dao->ops->commit_write(dao);
diff -druN linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctdaio.c linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctdaio.c
--- linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctdaio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctdaio.c	2011-06-02 21:35:11.000000000 -0400
@@ -176,6 +176,7 @@
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_left_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscl.ops->master(&daio->rscl);
@@ -204,6 +205,7 @@
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_right_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscr.ops->master(&daio->rscr);
diff -druN linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctmixer.c linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctmixer.c
--- linux-libre-2.6.38-gnu/sound/pci/ctxfi/ctmixer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/ctxfi/ctmixer.c	2011-06-02 21:35:11.000000000 -0400
@@ -566,19 +566,6 @@
 	return 0;
 }
 
-static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
-
-	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
-	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
-	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
-	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
-
-	return 0;
-}
-
 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
@@ -586,6 +573,10 @@
 	unsigned int status;
 
 	atc->spdif_out_get_status(atc, &status);
+
+	if (status == 0)
+		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
+
 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
@@ -629,7 +620,7 @@
 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 	.count		= 1,
 	.info		= ct_spdif_info,
-	.get		= ct_spdif_default_get,
+	.get		= ct_spdif_get,
 	.put		= ct_spdif_put,
 	.private_value	= MIXER_IEC958_DEFAULT
 };
diff -druN linux-libre-2.6.38-gnu/sound/pci/ens1370.c linux-libre-2.6.38.8-gnu/sound/pci/ens1370.c
--- linux-libre-2.6.38-gnu/sound/pci/ens1370.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/ens1370.c	2011-06-02 21:35:11.000000000 -0400
@@ -229,6 +229,7 @@
 #define ES_REG_1371_CODEC 0x14	/* W/R: Codec Read/Write register address */
 #define   ES_1371_CODEC_RDY	   (1<<31)	/* codec ready */
 #define   ES_1371_CODEC_WIP	   (1<<30)	/* codec register access in progress */
+#define   EV_1938_CODEC_MAGIC	   (1<<26)
 #define   ES_1371_CODEC_PIRD	   (1<<23)	/* codec read/write select register */
 #define   ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0))
 #define   ES_1371_CODEC_READS(a)   ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD)
@@ -603,12 +604,18 @@
 
 #ifdef CHIP1371
 
+static inline bool is_ev1938(struct ensoniq *ensoniq)
+{
+	return ensoniq->pci->device == 0x8938;
+}
+
 static void snd_es1371_codec_write(struct snd_ac97 *ac97,
 				   unsigned short reg, unsigned short val)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x;
+	unsigned int t, x, flag;
 
+	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
 	mutex_lock(&ensoniq->src_mutex);
 	for (t = 0; t < POLL_COUNT; t++) {
 		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
@@ -630,7 +637,8 @@
 				    0x00010000)
 					break;
 			}
-			outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
+			outl(ES_1371_CODEC_WRITE(reg, val) | flag,
+			     ES_REG(ensoniq, 1371_CODEC));
 			/* restore SRC reg */
 			snd_es1371_wait_src_ready(ensoniq);
 			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
@@ -647,8 +655,9 @@
 					    unsigned short reg)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x, fail = 0;
+	unsigned int t, x, flag, fail = 0;
 
+	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
       __again:
 	mutex_lock(&ensoniq->src_mutex);
 	for (t = 0; t < POLL_COUNT; t++) {
@@ -671,7 +680,8 @@
 				    0x00010000)
 					break;
 			}
-			outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
+			outl(ES_1371_CODEC_READS(reg) | flag,
+			     ES_REG(ensoniq, 1371_CODEC));
 			/* restore SRC reg */
 			snd_es1371_wait_src_ready(ensoniq);
 			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
@@ -683,6 +693,11 @@
 			/* now wait for the stinkin' data (RDY) */
 			for (t = 0; t < POLL_COUNT; t++) {
 				if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) {
+					if (is_ev1938(ensoniq)) {
+						for (t = 0; t < 100; t++)
+							inl(ES_REG(ensoniq, CONTROL));
+						x = inl(ES_REG(ensoniq, 1371_CODEC));
+					}
 					mutex_unlock(&ensoniq->src_mutex);
 					return ES_1371_CODEC_READ(x);
 				}
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/hda_intel.c linux-libre-2.6.38.8-gnu/sound/pci/hda/hda_intel.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/hda_intel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/hda_intel.c	2011-06-02 21:35:11.000000000 -0400
@@ -2346,9 +2346,16 @@
 	/* Check VIA/ATI HD Audio Controller exist */
 	switch (chip->driver_type) {
 	case AZX_DRIVER_VIA:
-	case AZX_DRIVER_ATI:
 		/* Use link position directly, avoid any transfer problem. */
 		return POS_FIX_VIACOMBO;
+	case AZX_DRIVER_ATI:
+		/* ATI chipsets don't work well with position-buffer */
+		return POS_FIX_LPIB;
+	case AZX_DRIVER_GENERIC:
+		/* AMD chipsets also don't work with position-buffer */
+		if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
+			return POS_FIX_LPIB;
+		break;
 	}
 
 	return POS_FIX_AUTO;
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_analog.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_analog.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_analog.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_analog.c	2011-06-02 21:35:11.000000000 -0400
@@ -3167,6 +3167,7 @@
 
 	for (i = 0; i < cfg->num_inputs; i++) {
 		hda_nid_t nid = cfg->inputs[i].pin;
+		int type = cfg->inputs[i].type;
 		switch (nid) {
 		case 0x15: /* port-C */
 			snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3176,7 +3177,7 @@
 			break;
 		}
 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-				    i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
+				    type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
 		if (nid != AD1988_PIN_CD_NID)
 			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 					    AMP_OUT_MUTE);
@@ -4353,6 +4354,84 @@
 }
 
 /*
+ * Precision R5500
+ * 0x12 - HP/line-out
+ * 0x13 - speaker (mono)
+ * 0x15 - mic-in
+ */
+
+static struct hda_verb ad1984a_precision_verbs[] = {
+	/* Unmute main output path */
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
+	/* Analog mixer; mute as default */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Select mic as input */
+	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
+	/* Configure as mic */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
+	/* HP unmute */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* turn on EAPD */
+	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	/* unsolicited event for pin-sense */
+	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new ad1984a_precision_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+
+/* mute internal speaker if HP is plugged */
+static void ad1984a_precision_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_jack_detect(codec, 0x12);
+	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+
+/* unsolicited event for HP jack sensing */
+static void ad1984a_precision_unsol_event(struct hda_codec *codec,
+					 unsigned int res)
+{
+	if ((res >> 26) != AD1884A_HP_EVENT)
+		return;
+	ad1984a_precision_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1984a_precision_init(struct hda_codec *codec)
+{
+	ad198x_init(codec);
+	ad1984a_precision_automute(codec);
+	return 0;
+}
+
+
+/*
  * HP Touchsmart
  * port-A (0x11)      - front hp-out
  * port-B (0x14)      - unused
@@ -4481,6 +4560,7 @@
 	AD1884A_MOBILE,
 	AD1884A_THINKPAD,
 	AD1984A_TOUCHSMART,
+	AD1984A_PRECISION,
 	AD1884A_MODELS
 };
 
@@ -4490,9 +4570,11 @@
 	[AD1884A_MOBILE]	= "mobile",
 	[AD1884A_THINKPAD]	= "thinkpad",
 	[AD1984A_TOUCHSMART]	= "touchsmart",
+	[AD1984A_PRECISION]	= "precision",
 };
 
 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
 	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
 	SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
 	SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
@@ -4586,6 +4668,14 @@
 		codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
 		codec->patch_ops.init = ad1984a_thinkpad_init;
 		break;
+	case AD1984A_PRECISION:
+		spec->mixers[0] = ad1984a_precision_mixers;
+		spec->init_verbs[spec->num_init_verbs++] =
+			ad1984a_precision_verbs;
+		spec->multiout.dig_out_nid = 0;
+		codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
+		codec->patch_ops.init = ad1984a_precision_init;
+		break;
 	case AD1984A_TOUCHSMART:
 		spec->mixers[0] = ad1984a_touchsmart_mixers;
 		spec->init_verbs[0] = ad1984a_touchsmart_verbs;
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_conexant.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_conexant.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_conexant.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_conexant.c	2011-06-02 21:35:11.000000000 -0400
@@ -3130,6 +3130,9 @@
 	SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
 	SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
  	SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
+	SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
+	SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
+	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
 	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
 	{}
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_hdmi.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_hdmi.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_hdmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_hdmi.c	2011-06-02 21:35:11.000000000 -0400
@@ -1276,6 +1276,39 @@
 					     stream_tag, format, substream);
 }
 
+static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
+						    int channels)
+{
+	unsigned int chanmask;
+	int chan = channels ? (channels - 1) : 1;
+
+	switch (channels) {
+	default:
+	case 0:
+	case 2:
+		chanmask = 0x00;
+		break;
+	case 4:
+		chanmask = 0x08;
+		break;
+	case 6:
+		chanmask = 0x0b;
+		break;
+	case 8:
+		chanmask = 0x13;
+		break;
+	}
+
+	/* Set the audio infoframe channel allocation and checksum fields.  The
+	 * channel count is computed implicitly by the hardware. */
+	snd_hda_codec_write(codec, 0x1, 0,
+			Nv_VERB_SET_Channel_Allocation, chanmask);
+
+	snd_hda_codec_write(codec, 0x1, 0,
+			Nv_VERB_SET_Info_Frame_Checksum,
+			(0x71 - chan - chanmask));
+}
+
 static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
 				   struct hda_codec *codec,
 				   struct snd_pcm_substream *substream)
@@ -1294,6 +1327,10 @@
 				AC_VERB_SET_STREAM_FORMAT, 0);
 	}
 
+	/* The audio hardware sends a channel count of 0x7 (8ch) when all the
+	 * streams are disabled. */
+	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
+
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
@@ -1304,37 +1341,16 @@
 				     struct snd_pcm_substream *substream)
 {
 	int chs;
-	unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
+	unsigned int dataDCC1, dataDCC2, channel_id;
 	int i;
 
 	mutex_lock(&codec->spdif_mutex);
 
 	chs = substream->runtime->channels;
-	chan = chs ? (chs - 1) : 1;
 
-	switch (chs) {
-	default:
-	case 0:
-	case 2:
-		chanmask = 0x00;
-		break;
-	case 4:
-		chanmask = 0x08;
-		break;
-	case 6:
-		chanmask = 0x0b;
-		break;
-	case 8:
-		chanmask = 0x13;
-		break;
-	}
 	dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
 	dataDCC2 = 0x2;
 
-	/* set the Audio InforFrame Channel Allocation */
-	snd_hda_codec_write(codec, 0x1, 0,
-			Nv_VERB_SET_Channel_Allocation, chanmask);
-
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
@@ -1409,10 +1425,7 @@
 		}
 	}
 
-	/* set the Audio Info Frame Checksum */
-	snd_hda_codec_write(codec, 0x1, 0,
-			Nv_VERB_SET_Info_Frame_Checksum,
-			(0x71 - chan - chanmask));
+	nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
 
 	mutex_unlock(&codec->spdif_mutex);
 	return 0;
@@ -1508,6 +1521,11 @@
 	spec->multiout.max_channels = 8;
 	spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x;
 	codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
+
+	/* Initialize the audio infoframe channel mask and checksum to something
+	 * valid */
+	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_realtek.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_realtek.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_realtek.c	2011-06-02 21:35:11.000000000 -0400
@@ -394,6 +394,7 @@
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
 	unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
+	unsigned int single_input_src:1;
 	int init_amp;
 	int codec_variant;	/* flag for other variants */
 
@@ -1359,7 +1360,7 @@
 		case 0x10ec0883:
 		case 0x10ec0885:
 		case 0x10ec0887:
-		case 0x10ec0889:
+		/*case 0x10ec0889:*/ /* this causes an SPDIF problem */
 			alc889_coef_init(codec);
 			break;
 		case 0x10ec0888:
@@ -1773,11 +1774,11 @@
 				   codec->chip_name, fix->type);
 			break;
 		}
-		if (!fix[id].chained)
+		if (!fix->chained)
 			break;
 		if (++depth > 10)
 			break;
-		id = fix[id].chain_id;
+		id = fix->chain_id;
 	}
 }
 
@@ -3919,6 +3920,8 @@
  * Common callbacks
  */
 
+static void alc_init_special_input_src(struct hda_codec *codec);
+
 static int alc_init(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -3929,6 +3932,7 @@
 
 	for (i = 0; i < spec->num_init_verbs; i++)
 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+	alc_init_special_input_src(codec);
 
 	if (spec->init_hook)
 		spec->init_hook(codec);
@@ -5151,7 +5155,9 @@
 
 	switch (cfg->line_out_type) {
 	case AUTO_PIN_SPEAKER_OUT:
-		return "Speaker";
+		if (cfg->line_outs == 1)
+			return "Speaker";
+		break;
 	case AUTO_PIN_HP_OUT:
 		return "Headphone";
 	default:
@@ -5205,16 +5211,19 @@
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
+				index = 0;
+			}
 			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, i,
+						name, index,
 					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
 							      HDA_OUTPUT));
 			if (err < 0)
 				return err;
 			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, i,
+					       name, index,
 					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
 							      HDA_INPUT));
 			if (err < 0)
@@ -5585,6 +5594,7 @@
 			spec->capsrc_nids += i;
 		spec->adc_nids += i;
 		spec->num_adc_nids = 1;
+		spec->single_input_src = 1;
 	}
 }
 
@@ -5596,6 +5606,16 @@
 	init_capsrc_for_pin(codec, spec->int_mic.pin);
 }
 
+/* initialize some special cases for input sources */
+static void alc_init_special_input_src(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	if (spec->dual_adc_switch)
+		fixup_dual_adc_switch(codec);
+	else if (spec->single_input_src)
+		init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
+}
+
 static void set_capture_mixer(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -5611,7 +5631,7 @@
 		int mux = 0;
 		int num_adcs = spec->num_adc_nids;
 		if (spec->dual_adc_switch)
-			fixup_dual_adc_switch(codec);
+			num_adcs = 1;
 		else if (spec->auto_mic)
 			fixup_automic_adc(codec);
 		else if (spec->input_mux) {
@@ -5620,8 +5640,6 @@
 			else if (spec->input_mux->num_items == 1)
 				fixup_single_adc(codec);
 		}
-		if (spec->dual_adc_switch)
-			num_adcs = 1;
 		spec->cap_mixer = caps[mux][num_adcs - 1];
 	}
 }
@@ -10748,6 +10766,7 @@
  */
 enum {
 	PINFIX_ABIT_AW9D_MAX,
+	PINFIX_LENOVO_Y530,
 	PINFIX_PB_M5210,
 	PINFIX_ACER_ASPIRE_7736,
 };
@@ -10762,6 +10781,14 @@
 			{ }
 		}
 	},
+	[PINFIX_LENOVO_Y530] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x15, 0x99130112 }, /* rear int speakers */
+			{ 0x16, 0x99130111 }, /* subwoofer */
+			{ }
+		}
+	},
 	[PINFIX_PB_M5210] = {
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -10777,6 +10804,7 @@
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
+	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
 	SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
 	SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
 	{}
@@ -10829,23 +10857,28 @@
 	hda_nid_t pin, dac;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-		pin = spec->autocfg.hp_pins[i];
-		if (!pin)
-			break;
-		dac = spec->multiout.hp_nid;
-		if (!dac)
-			dac = spec->multiout.dac_nids[0]; /* to front */
-		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
+		for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+			pin = spec->autocfg.hp_pins[i];
+			if (!pin)
+				break;
+			dac = spec->multiout.hp_nid;
+			if (!dac)
+				dac = spec->multiout.dac_nids[0]; /* to front */
+			alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+		}
 	}
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-		pin = spec->autocfg.speaker_pins[i];
-		if (!pin)
-			break;
-		dac = spec->multiout.extra_out_nid[0];
-		if (!dac)
-			dac = spec->multiout.dac_nids[0]; /* to front */
-		alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+
+	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
+		for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+			pin = spec->autocfg.speaker_pins[i];
+			if (!pin)
+				break;
+			dac = spec->multiout.extra_out_nid[0];
+			if (!dac)
+				dac = spec->multiout.dac_nids[0]; /* to front */
+			alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+		}
 	}
 }
 
@@ -14158,7 +14191,7 @@
 };
 
 static hda_nid_t alc269_adc_candidates[] = {
-	0x08, 0x09, 0x07,
+	0x08, 0x09, 0x07, 0x11,
 };
 
 #define alc269_modes		alc260_modes
@@ -14904,6 +14937,23 @@
 	alc_write_coef_idx(codec, 0x1e, coef | 0x80);
 }
 
+static void alc271_fixup_dmic(struct hda_codec *codec,
+			      const struct alc_fixup *fix, int action)
+{
+	static struct hda_verb verbs[] = {
+		{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
+		{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
+		{}
+	};
+	unsigned int cfg;
+
+	if (strcmp(codec->chip_name, "ALC271X"))
+		return;
+	cfg = snd_hda_codec_get_pincfg(codec, 0x12);
+	if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
+		snd_hda_sequence_write(codec, verbs);
+}
+
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -14912,6 +14962,7 @@
 	ALC269_FIXUP_ASUS_G73JW,
 	ALC269_FIXUP_LENOVO_EAPD,
 	ALC275_FIXUP_SONY_HWEQ,
+	ALC271_FIXUP_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14965,7 +15016,11 @@
 		.v.func = alc269_fixup_hweq,
 		.chained = true,
 		.chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
-	}
+	},
+	[ALC271_FIXUP_DMIC] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc271_fixup_dmic,
+	},
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -14974,6 +15029,7 @@
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
 	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -16052,9 +16108,12 @@
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
-			err = __alc861_create_out_sw(codec, name, nid, i, 3);
+				index = 0;
+			}
+			err = __alc861_create_out_sw(codec, name, nid, index, 3);
 			if (err < 0)
 				return err;
 		}
@@ -17205,16 +17264,19 @@
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
+				index = 0;
+			}
 			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, i,
+						name, index,
 					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
 							      HDA_OUTPUT));
 			if (err < 0)
 				return err;
 			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, i,
+					       name, index,
 					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
 							      HDA_INPUT));
 			if (err < 0)
@@ -19263,12 +19325,15 @@
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
-			err = __alc662_add_vol_ctl(spec, name, nid, i, 3);
+				index = 0;
+			}
+			err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
 			if (err < 0)
 				return err;
-			err = __alc662_add_sw_ctl(spec, name, mix, i, 3);
+			err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
 			if (err < 0)
 				return err;
 		}
@@ -19484,6 +19549,7 @@
 	ALC662_FIXUP_IDEAPAD,
 	ALC272_FIXUP_MARIO,
 	ALC662_FIXUP_CZC_P10T,
+	ALC662_FIXUP_SKU_IGNORE,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19512,10 +19578,15 @@
 			{}
 		}
 	},
+	[ALC662_FIXUP_SKU_IGNORE] = {
+		.type = ALC_FIXUP_SKU,
+		.v.sku = ALC_FIXUP_SKU_IGNORE,
+	},
 };
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_sigmatel.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_sigmatel.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_sigmatel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_sigmatel.c	2011-06-02 21:35:11.000000000 -0400
@@ -94,6 +94,7 @@
 	STAC_92HD83XXX_REF,
 	STAC_92HD83XXX_PWR_REF,
 	STAC_DELL_S14,
+	STAC_DELL_E5520M,
 	STAC_92HD83XXX_HP,
 	STAC_HP_DV7_4000,
 	STAC_92HD83XXX_MODELS
@@ -757,7 +758,7 @@
 	struct sigmatel_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int idx, prev_idx;
+	unsigned int idx, prev_idx, didx;
 
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
@@ -769,7 +770,8 @@
 		snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
 					  imux->items[idx].index);
-		if (prev_idx >= spec->num_analog_muxes) {
+		if (prev_idx >= spec->num_analog_muxes &&
+		    spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) {
 			imux = spec->dinput_mux;
 			/* 0 = analog */
 			snd_hda_codec_write_cache(codec,
@@ -779,9 +781,13 @@
 		}
 	} else {
 		imux = spec->dinput_mux;
+		/* first dimux item is hardcoded to select analog imux,
+		 * so lets skip it
+		 */
+		didx = idx - spec->num_analog_muxes + 1;
 		snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
-					  imux->items[idx - 1].index);
+					  imux->items[didx].index);
 	}
 	spec->cur_mux[adc_idx] = idx;
 	return 1;
@@ -1628,7 +1634,7 @@
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
 				"Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
-				"Dell Studio 1558", STAC_DELL_M6_BOTH),
+				"Dell Studio 1558", STAC_DELL_M6_DMIC),
 	{} /* terminator */
 };
 
@@ -1652,6 +1658,13 @@
 	0x40f000f0, 0x40f000f0,
 };
 
+/* Switch int mic from 0x20 to 0x11 */
+static unsigned int dell_e5520m_pin_configs[10] = {
+	0x04a11020, 0x0421101f, 0x400000f0, 0x90170110,
+	0x23011050, 0x23a1102e, 0x400000f3, 0xd5a30130,
+	0x400000f0, 0x40f000f0,
+};
+
 static unsigned int hp_dv7_4000_pin_configs[10] = {
 	0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
 	0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140,
@@ -1662,6 +1675,7 @@
 	[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
 	[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
 	[STAC_DELL_S14] = dell_s14_pin_configs,
+	[STAC_DELL_E5520M] = dell_e5520m_pin_configs,
 	[STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
 };
 
@@ -1670,6 +1684,7 @@
 	[STAC_92HD83XXX_REF] = "ref",
 	[STAC_92HD83XXX_PWR_REF] = "mic-ref",
 	[STAC_DELL_S14] = "dell-s14",
+	[STAC_DELL_E5520M] = "dell-e5520m",
 	[STAC_92HD83XXX_HP] = "hp",
 	[STAC_HP_DV7_4000] = "hp-dv7-4000",
 };
@@ -1682,6 +1697,14 @@
 		      "DFI LanParty", STAC_92HD83XXX_REF),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
 		      "unknown Dell", STAC_DELL_S14),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x049a,
+		      "Dell E5520", STAC_DELL_E5520M),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x049b,
+		      "Dell E5420", STAC_DELL_E5520M),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x04eb,
+		      "Dell E5420m", STAC_DELL_E5520M),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x04ec,
+		      "Dell E5520m", STAC_DELL_E5520M),
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
 		      "HP", STAC_92HD83XXX_HP),
 	{} /* terminator */
diff -druN linux-libre-2.6.38-gnu/sound/pci/hda/patch_via.c linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_via.c
--- linux-libre-2.6.38-gnu/sound/pci/hda/patch_via.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/pci/hda/patch_via.c	2011-06-02 21:35:11.000000000 -0400
@@ -159,6 +159,7 @@
 #endif
 };
 
+static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
 static struct via_spec * via_new_spec(struct hda_codec *codec)
 {
 	struct via_spec *spec;
@@ -169,6 +170,10 @@
 
 	codec->spec = spec;
 	spec->codec = codec;
+	spec->codec_type = get_codec_type(codec);
+	/* VT1708BCE & VT1708S are almost same */
+	if (spec->codec_type == VT1708BCE)
+		spec->codec_type = VT1708S;
 	return spec;
 }
 
@@ -1101,6 +1106,7 @@
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	int ret;
 
 	if (!spec->mux_nids[adc_idx])
 		return -EINVAL;
@@ -1109,12 +1115,14 @@
 			       AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
 		snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
 				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-	/* update jack power state */
-	set_jack_power_state(codec);
 
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+	ret = snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 				     spec->mux_nids[adc_idx],
 				     &spec->cur_mux[adc_idx]);
+	/* update jack power state */
+	set_jack_power_state(codec);
+
+	return ret;
 }
 
 static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
@@ -1188,8 +1196,16 @@
 	/* Get Independent Mode index of headphone pin widget */
 	spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel
 		? 1 : 0;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel);
+	if (spec->codec_type == VT1718S)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
+	else
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel);
 
+	if (spec->codec_type == VT1812)
+		snd_hda_codec_write(codec, 0x35, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel);
 	if (spec->multiout.hp_nid && spec->multiout.hp_nid
 	    != spec->multiout.dac_nids[HDA_FRONT])
 		snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid,
@@ -1208,6 +1224,8 @@
 		activate_ctl(codec, "Headphone Playback Switch",
 			     spec->hp_independent_mode);
 	}
+	/* update jack power state */
+	set_jack_power_state(codec);
 	return 0;
 }
 
@@ -1248,9 +1266,12 @@
 		break;
 	}
 
-	nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS);
-	if (nums <= 1)
-		return 0;
+	if (spec->codec_type != VT1708) {
+		nums = snd_hda_get_connections(codec, nid,
+					       conn, HDA_MAX_CONNECTIONS);
+		if (nums <= 1)
+			return 0;
+	}
 
 	knew = via_clone_control(spec, &via_hp_mixer[0]);
 	if (knew == NULL)
@@ -1310,6 +1331,11 @@
 		start_idx = 2;
 		end_idx = 4;
 		break;
+	case VT1718S:
+		nid_mixer = 0x21;
+		start_idx = 1;
+		end_idx = 3;
+		break;
 	default:
 		return;
 	}
@@ -2185,10 +2211,6 @@
 	for (i = 0; i < spec->num_iverbs; i++)
 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
 
-	spec->codec_type = get_codec_type(codec);
-	if (spec->codec_type == VT1708BCE)
-		spec->codec_type = VT1708S; /* VT1708BCE & VT1708S are almost
-					       same */
 	/* Lydia Add for EAPD enable */
 	if (!spec->dig_in_nid) { /* No Digital In connection */
 		if (spec->dig_in_pin) {
@@ -2438,7 +2460,14 @@
 		else
 			type_idx = 0;
 		label = hda_get_autocfg_input_label(codec, cfg, i);
-		err = via_new_analog_input(spec, label, type_idx, idx, cap_nid);
+		if (spec->codec_type == VT1708S ||
+		    spec->codec_type == VT1702 ||
+		    spec->codec_type == VT1716S)
+			err = via_new_analog_input(spec, label, type_idx,
+						   idx+1, cap_nid);
+		else
+			err = via_new_analog_input(spec, label, type_idx,
+						   idx, cap_nid);
 		if (err < 0)
 			return err;
 		snd_hda_add_imux_item(imux, label, idx, NULL);
diff -druN linux-libre-2.6.38-gnu/sound/soc/codecs/jz4740.c linux-libre-2.6.38.8-gnu/sound/soc/codecs/jz4740.c
--- linux-libre-2.6.38-gnu/sound/soc/codecs/jz4740.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/codecs/jz4740.c	2011-06-02 21:35:11.000000000 -0400
@@ -308,8 +308,6 @@
 	snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes,
 		ARRAY_SIZE(jz4740_codec_dapm_routes));
 
-	snd_soc_dapm_new_widgets(codec);
-
 	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/sound/soc/codecs/ssm2602.c linux-libre-2.6.38.8-gnu/sound/soc/codecs/ssm2602.c
--- linux-libre-2.6.38-gnu/sound/soc/codecs/ssm2602.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/codecs/ssm2602.c	2011-06-02 21:35:11.000000000 -0400
@@ -139,7 +139,7 @@
 SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
 
 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
-SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
+SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0),
 SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
 
 SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
diff -druN linux-libre-2.6.38-gnu/sound/soc/codecs/uda134x.c linux-libre-2.6.38.8-gnu/sound/soc/codecs/uda134x.c
--- linux-libre-2.6.38-gnu/sound/soc/codecs/uda134x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/codecs/uda134x.c	2011-06-02 21:35:11.000000000 -0400
@@ -486,7 +486,8 @@
 static int uda134x_soc_probe(struct snd_soc_codec *codec)
 {
 	struct uda134x_priv *uda134x;
-	struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
+	struct uda134x_platform_data *pd = codec->card->dev->platform_data;
+
 	int ret;
 
 	printk(KERN_INFO "UDA134X SoC Audio Codec\n");
@@ -600,9 +601,7 @@
 	.reg_cache_step = 1,
 	.read = uda134x_read_reg_cache,
 	.write = uda134x_write,
-#ifdef POWER_OFF_ON_STANDBY
 	.set_bias_level = uda134x_set_bias_level,
-#endif
 };
 
 static int __devinit uda134x_codec_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/sound/soc/codecs/wm_hubs.c linux-libre-2.6.38.8-gnu/sound/soc/codecs/wm_hubs.c
--- linux-libre-2.6.38-gnu/sound/soc/codecs/wm_hubs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/codecs/wm_hubs.c	2011-06-02 21:35:11.000000000 -0400
@@ -739,12 +739,12 @@
 
 	{ "SPKL", "Input Switch", "MIXINL" },
 	{ "SPKL", "IN1LP Switch", "IN1LP" },
-	{ "SPKL", "Output Switch", "Left Output Mixer" },
+	{ "SPKL", "Output Switch", "Left Output PGA" },
 	{ "SPKL", NULL, "TOCLK" },
 
 	{ "SPKR", "Input Switch", "MIXINR" },
 	{ "SPKR", "IN1RP Switch", "IN1RP" },
-	{ "SPKR", "Output Switch", "Right Output Mixer" },
+	{ "SPKR", "Output Switch", "Right Output PGA" },
 	{ "SPKR", NULL, "TOCLK" },
 
 	{ "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
@@ -766,8 +766,8 @@
 	{ "SPKOUTRP", NULL, "SPKR Driver" },
 	{ "SPKOUTRN", NULL, "SPKR Driver" },
 
-	{ "Left Headphone Mux", "Mixer", "Left Output Mixer" },
-	{ "Right Headphone Mux", "Mixer", "Right Output Mixer" },
+	{ "Left Headphone Mux", "Mixer", "Left Output PGA" },
+	{ "Right Headphone Mux", "Mixer", "Right Output PGA" },
 
 	{ "Headphone PGA", NULL, "Left Headphone Mux" },
 	{ "Headphone PGA", NULL, "Right Headphone Mux" },
@@ -786,17 +786,17 @@
 static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
 	{ "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
 	{ "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
-	{ "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
+	{ "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" },
 
 	{ "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
 	{ "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
 };
 
 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
-	{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
-	{ "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
+	{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
+	{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
 
-	{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
+	{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
 
 	{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
 	{ "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
@@ -805,17 +805,17 @@
 static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
 	{ "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
 	{ "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
-	{ "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
+	{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
 
 	{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
 	{ "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
 };
 
 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
-	{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
-	{ "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
+	{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
+	{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
 
-	{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
+	{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
 
 	{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
 	{ "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
@@ -835,17 +835,21 @@
 	snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
 			    WM8993_IN2_VU, WM8993_IN2_VU);
 
+	snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_LEFT,
+			    WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
 	snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
 			    WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
 
 	snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
-			    WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
+			    WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC,
+			    WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC);
 	snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
 			    WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
 			    WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
 
 	snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
-			    WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
+			    WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU,
+			    WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU);
 	snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
 			    WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
 			    WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
diff -druN linux-libre-2.6.38-gnu/sound/soc/imx/imx-pcm-dma-mx2.c linux-libre-2.6.38.8-gnu/sound/soc/imx/imx-pcm-dma-mx2.c
--- linux-libre-2.6.38-gnu/sound/soc/imx/imx-pcm-dma-mx2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/imx/imx-pcm-dma-mx2.c	2011-06-02 21:35:11.000000000 -0400
@@ -110,12 +110,12 @@
 		slave_config.direction = DMA_TO_DEVICE;
 		slave_config.dst_addr = dma_params->dma_addr;
 		slave_config.dst_addr_width = buswidth;
-		slave_config.dst_maxburst = dma_params->burstsize;
+		slave_config.dst_maxburst = dma_params->burstsize * buswidth;
 	} else {
 		slave_config.direction = DMA_FROM_DEVICE;
 		slave_config.src_addr = dma_params->dma_addr;
 		slave_config.src_addr_width = buswidth;
-		slave_config.src_maxburst = dma_params->burstsize;
+		slave_config.src_maxburst = dma_params->burstsize * buswidth;
 	}
 
 	ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
@@ -303,6 +303,11 @@
 
 static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
 {
+	struct imx_ssi *ssi = platform_get_drvdata(pdev);
+
+	ssi->dma_params_tx.burstsize = 6;
+	ssi->dma_params_rx.burstsize = 4;
+
 	return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
 }
 
diff -druN linux-libre-2.6.38-gnu/sound/soc/imx/imx-ssi.h linux-libre-2.6.38.8-gnu/sound/soc/imx/imx-ssi.h
--- linux-libre-2.6.38-gnu/sound/soc/imx/imx-ssi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/imx/imx-ssi.h	2011-06-02 21:35:11.000000000 -0400
@@ -234,7 +234,4 @@
  */
 #define IMX_SSI_DMABUF_SIZE	(64 * 1024)
 
-#define DMA_RXFIFO_BURST      0x4
-#define DMA_TXFIFO_BURST      0x6
-
 #endif /* _IMX_SSI_H */
diff -druN linux-libre-2.6.38-gnu/sound/soc/pxa/corgi.c linux-libre-2.6.38.8-gnu/sound/soc/pxa/corgi.c
--- linux-libre-2.6.38-gnu/sound/soc/pxa/corgi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/pxa/corgi.c	2011-06-02 21:35:11.000000000 -0400
@@ -310,7 +310,7 @@
 	.cpu_dai_name = "pxa2xx-i2s",
 	.codec_dai_name = "wm8731-hifi",
 	.platform_name = "pxa-pcm-audio",
-	.codec_name = "wm8731-codec-0.001b",
+	.codec_name = "wm8731-codec.0-001b",
 	.init = corgi_wm8731_init,
 	.ops = &corgi_ops,
 };
diff -druN linux-libre-2.6.38-gnu/sound/soc/pxa/z2.c linux-libre-2.6.38.8-gnu/sound/soc/pxa/z2.c
--- linux-libre-2.6.38-gnu/sound/soc/pxa/z2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/pxa/z2.c	2011-06-02 21:35:11.000000000 -0400
@@ -147,7 +147,7 @@
 	snd_soc_dapm_disable_pin(dapm, "LINPUT3");
 	snd_soc_dapm_disable_pin(dapm, "RINPUT3");
 	snd_soc_dapm_disable_pin(dapm, "OUT3");
-	snd_soc_dapm_disable_pin(dapm, "MONO");
+	snd_soc_dapm_disable_pin(dapm, "MONO1");
 
 	/* Add z2 specific widgets */
 	snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
diff -druN linux-libre-2.6.38-gnu/sound/soc/samsung/s3c24xx_uda134x.c linux-libre-2.6.38.8-gnu/sound/soc/samsung/s3c24xx_uda134x.c
--- linux-libre-2.6.38-gnu/sound/soc/samsung/s3c24xx_uda134x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/sound/soc/samsung/s3c24xx_uda134x.c	2011-06-02 21:35:11.000000000 -0400
@@ -226,7 +226,7 @@
 static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
 	.name = "UDA134X",
 	.stream_name = "UDA134X",
-	.codec_name = "uda134x-hifi",
+	.codec_name = "uda134x-codec",
 	.codec_dai_name = "uda134x-hifi",
 	.cpu_dai_name = "s3c24xx-iis",
 	.ops = &s3c24xx_uda134x_ops,
@@ -321,6 +321,7 @@
 
 	platform_set_drvdata(s3c24xx_uda134x_snd_device,
 			     &snd_soc_s3c24xx_uda134x);
+	platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x));
 	ret = platform_device_add(s3c24xx_uda134x_snd_device);
 	if (ret) {
 		printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
diff -druN linux-libre-2.6.38-gnu/tools/perf/bench/sched-pipe.c linux-libre-2.6.38.8-gnu/tools/perf/bench/sched-pipe.c
--- linux-libre-2.6.38-gnu/tools/perf/bench/sched-pipe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/bench/sched-pipe.c	2011-06-02 21:35:11.000000000 -0400
@@ -55,7 +55,7 @@
 	 * discarding returned value of read(), write()
 	 * causes error in building environment for perf
 	 */
-	int ret, wait_stat;
+	int __used ret, wait_stat;
 	pid_t pid, retpid;
 
 	argc = parse_options(argc, argv, options,
diff -druN linux-libre-2.6.38-gnu/tools/perf/builtin-sched.c linux-libre-2.6.38.8-gnu/tools/perf/builtin-sched.c
--- linux-libre-2.6.38-gnu/tools/perf/builtin-sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/builtin-sched.c	2011-06-02 21:35:11.000000000 -0400
@@ -369,11 +369,6 @@
 process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
 {
 	int ret = 0;
-	u64 now;
-	long long delta;
-
-	now = get_nsecs();
-	delta = start_time + atom->timestamp - now;
 
 	switch (atom->type) {
 		case SCHED_EVENT_RUN:
@@ -562,7 +557,7 @@
 
 static void run_one_test(void)
 {
-	u64 T0, T1, delta, avg_delta, fluct, std_dev;
+	u64 T0, T1, delta, avg_delta, fluct;
 
 	T0 = get_nsecs();
 	wait_for_tasks();
@@ -578,7 +573,6 @@
 	else
 		fluct = delta - avg_delta;
 	sum_fluct += fluct;
-	std_dev = sum_fluct / nr_runs / sqrt(nr_runs);
 	if (!run_avg)
 		run_avg = delta;
 	run_avg = (run_avg*9 + delta)/10;
@@ -799,7 +793,7 @@
 		    u64 timestamp,
 		    struct thread *thread __used)
 {
-	struct task_desc *prev, *next;
+	struct task_desc *prev, __used *next;
 	u64 timestamp0;
 	s64 delta;
 
@@ -1404,7 +1398,7 @@
 		 u64 timestamp,
 		 struct thread *thread __used)
 {
-	struct thread *sched_out, *sched_in;
+	struct thread *sched_out __used, *sched_in;
 	int new_shortname;
 	u64 timestamp0;
 	s64 delta;
diff -druN linux-libre-2.6.38-gnu/tools/perf/builtin-top.c linux-libre-2.6.38.8-gnu/tools/perf/builtin-top.c
--- linux-libre-2.6.38-gnu/tools/perf/builtin-top.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/builtin-top.c	2011-06-02 21:35:11.000000000 -0400
@@ -183,7 +183,6 @@
 	FILE *file;
 	char command[PATH_MAX*2];
 	const char *path;
-	u64 len;
 
 	if (!syme)
 		return -1;
@@ -212,8 +211,6 @@
 	}
 	path = map->dso->long_name;
 
-	len = sym->end - sym->start;
-
 	sprintf(command,
 		"objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
 		BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
@@ -1296,7 +1293,7 @@
 {
 	pthread_t thread;
 	struct perf_evsel *counter;
-	int i, ret;
+	int i, ret __used;
 	/*
 	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
 	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/header.c linux-libre-2.6.38.8-gnu/tools/perf/util/header.c
--- linux-libre-2.6.38-gnu/tools/perf/util/header.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/header.c	2011-06-02 21:35:11.000000000 -0400
@@ -1144,7 +1144,7 @@
 {
 	event_t ev;
 	ssize_t size = 0, aligned_size = 0, padding;
-	int err = 0;
+	int err __used = 0;
 
 	memset(&ev, 0, sizeof(ev));
 
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/hist.c linux-libre-2.6.38.8-gnu/tools/perf/util/hist.c
--- linux-libre-2.6.38-gnu/tools/perf/util/hist.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/hist.c	2011-06-02 21:35:11.000000000 -0400
@@ -1095,7 +1095,6 @@
 	char command[PATH_MAX * 2];
 	FILE *file;
 	int err = 0;
-	u64 len;
 	char symfs_filename[PATH_MAX];
 
 	if (filename) {
@@ -1140,8 +1139,6 @@
 		 filename, sym->name, map->unmap_ip(map, sym->start),
 		 map->unmap_ip(map, sym->end));
 
-	len = sym->end - sym->start;
-
 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
 		 dso, dso->long_name, sym, sym->name);
 
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/PERF-VERSION-GEN linux-libre-2.6.38.8-gnu/tools/perf/util/PERF-VERSION-GEN
--- linux-libre-2.6.38-gnu/tools/perf/util/PERF-VERSION-GEN	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/PERF-VERSION-GEN	2011-06-02 21:35:11.000000000 -0400
@@ -23,10 +23,10 @@
 then
 	VN=$(echo "$VN" | sed -e 's/-/./g');
 else
-	eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '`
+	eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
 
 	VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
 fi
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/scripting-engines/trace-event-python.c linux-libre-2.6.38.8-gnu/tools/perf/util/scripting-engines/trace-event-python.c
--- linux-libre-2.6.38-gnu/tools/perf/util/scripting-engines/trace-event-python.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/scripting-engines/trace-event-python.c	2011-06-02 21:35:11.000000000 -0400
@@ -248,8 +248,7 @@
 	context = PyCObject_FromVoidPtr(scripting_context, NULL);
 
 	PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
-	PyTuple_SetItem(t, n++,
-			PyCObject_FromVoidPtr(scripting_context, NULL));
+	PyTuple_SetItem(t, n++, context);
 
 	if (handler) {
 		PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/symbol.c linux-libre-2.6.38.8-gnu/tools/perf/util/symbol.c
--- linux-libre-2.6.38-gnu/tools/perf/util/symbol.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/symbol.c	2011-06-02 21:35:11.000000000 -0400
@@ -1525,8 +1525,8 @@
 			     symbol_conf.symfs, self->long_name);
 			break;
 		case DSO__ORIG_GUEST_KMODULE:
-			if (map->groups && map->groups->machine)
-				root_dir = map->groups->machine->root_dir;
+			if (map->groups && machine)
+				root_dir = machine->root_dir;
 			else
 				root_dir = "";
 			snprintf(name, size, "%s%s%s", symbol_conf.symfs,
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/trace-event-parse.c linux-libre-2.6.38.8-gnu/tools/perf/util/trace-event-parse.c
--- linux-libre-2.6.38-gnu/tools/perf/util/trace-event-parse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/trace-event-parse.c	2011-06-02 21:35:11.000000000 -0400
@@ -153,7 +153,7 @@
 	char *next = NULL;
 	char *addr_str;
 	char ch;
-	int ret;
+	int ret __used;
 	int i;
 
 	line = strtok_r(file, "\n", &next);
diff -druN linux-libre-2.6.38-gnu/tools/perf/util/ui/browsers/map.c linux-libre-2.6.38.8-gnu/tools/perf/util/ui/browsers/map.c
--- linux-libre-2.6.38-gnu/tools/perf/util/ui/browsers/map.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.38.8-gnu/tools/perf/util/ui/browsers/map.c	2011-06-02 21:35:11.000000000 -0400
@@ -41,7 +41,7 @@
 out_free_form:
 	newtPopWindow();
 	newtFormDestroy(form);
-	return 0;
+	return err;
 }
 
 struct map_browser {
