diff -druN linux-libre-3.3-gnu/arch/arm/mach-at91/at91sam9263_devices.c linux-libre-3.3.2-gnu/arch/arm/mach-at91/at91sam9263_devices.c
--- linux-libre-3.3-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2012-04-13 12:42:02.000000000 -0400
@@ -71,7 +71,8 @@
 	/* Enable VBus control for UHP ports */
 	for (i = 0; i < data->ports; i++) {
 		if (gpio_is_valid(data->vbus_pin[i]))
-			at91_set_gpio_output(data->vbus_pin[i], 0);
+			at91_set_gpio_output(data->vbus_pin[i],
+					     data->vbus_pin_active_low[i]);
 	}
 
 	/* Enable overcurrent notification */
diff -druN linux-libre-3.3-gnu/arch/arm/mach-at91/at91sam9g45_devices.c linux-libre-3.3.2-gnu/arch/arm/mach-at91/at91sam9g45_devices.c
--- linux-libre-3.3-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2012-04-13 12:42:02.000000000 -0400
@@ -122,7 +122,8 @@
 	/* Enable VBus control for UHP ports */
 	for (i = 0; i < data->ports; i++) {
 		if (gpio_is_valid(data->vbus_pin[i]))
-			at91_set_gpio_output(data->vbus_pin[i], 0);
+			at91_set_gpio_output(data->vbus_pin[i],
+					     data->vbus_pin_active_low[i]);
 	}
 
 	/* Enable overcurrent notification */
@@ -183,7 +184,8 @@
 	/* Enable VBus control for UHP ports */
 	for (i = 0; i < data->ports; i++) {
 		if (gpio_is_valid(data->vbus_pin[i]))
-			at91_set_gpio_output(data->vbus_pin[i], 0);
+			at91_set_gpio_output(data->vbus_pin[i],
+					     data->vbus_pin_active_low[i]);
 	}
 
 	usbh_ehci_data = *data;
diff -druN linux-libre-3.3-gnu/arch/arm/mach-at91/board-sam9263ek.c linux-libre-3.3.2-gnu/arch/arm/mach-at91/board-sam9263ek.c
--- linux-libre-3.3-gnu/arch/arm/mach-at91/board-sam9263ek.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-at91/board-sam9263ek.c	2012-04-13 12:42:02.000000000 -0400
@@ -74,6 +74,7 @@
 static struct at91_usbh_data __initdata ek_usbh_data = {
 	.ports		= 2,
 	.vbus_pin	= { AT91_PIN_PA24, AT91_PIN_PA21 },
+	.vbus_pin_active_low = {1, 1},
 	.overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
diff -druN linux-libre-3.3-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c linux-libre-3.3.2-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c
--- linux-libre-3.3-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2012-04-13 12:42:02.000000000 -0400
@@ -69,6 +69,7 @@
 static struct at91_usbh_data __initdata ek_usbh_hs_data = {
 	.ports		= 2,
 	.vbus_pin	= {AT91_PIN_PD1, AT91_PIN_PD3},
+	.vbus_pin_active_low = {1, 1},
 	.overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
diff -druN linux-libre-3.3-gnu/arch/arm/mach-shmobile/setup-sh7372.c linux-libre-3.3.2-gnu/arch/arm/mach-shmobile/setup-sh7372.c
--- linux-libre-3.3-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2012-04-13 12:42:02.000000000 -0400
@@ -1043,6 +1043,8 @@
 	sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
 	sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
 	sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device);
 }
 
 void __init sh7372_add_early_devices(void)
diff -druN linux-libre-3.3-gnu/arch/arm/mach-tegra/board-dt-tegra20.c linux-libre-3.3.2-gnu/arch/arm/mach-tegra/board-dt-tegra20.c
--- linux-libre-3.3-gnu/arch/arm/mach-tegra/board-dt-tegra20.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-tegra/board-dt-tegra20.c	2012-04-13 12:42:02.000000000 -0400
@@ -68,11 +68,11 @@
 	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
-		       &tegra_ehci1_device.dev.platform_data),
+		       &tegra_ehci1_pdata),
 	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
-		       &tegra_ehci2_device.dev.platform_data),
+		       &tegra_ehci2_pdata),
 	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
-		       &tegra_ehci3_device.dev.platform_data),
+		       &tegra_ehci3_pdata),
 	{}
 };
 
diff -druN linux-libre-3.3-gnu/arch/arm/mach-tegra/devices.c linux-libre-3.3.2-gnu/arch/arm/mach-tegra/devices.c
--- linux-libre-3.3-gnu/arch/arm/mach-tegra/devices.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-tegra/devices.c	2012-04-13 12:42:02.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/serial_8250.h>
 #include <linux/i2c-tegra.h>
-#include <linux/platform_data/tegra_usb.h>
 #include <asm/pmu.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
@@ -446,18 +445,18 @@
 	.clk = "cdev2",
 };
 
-static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+struct tegra_ehci_platform_data tegra_ehci1_pdata = {
 	.operating_mode = TEGRA_USB_OTG,
 	.power_down_on_bus_suspend = 1,
 };
 
-static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+struct tegra_ehci_platform_data tegra_ehci2_pdata = {
 	.phy_config = &tegra_ehci2_ulpi_phy_config,
 	.operating_mode = TEGRA_USB_HOST,
 	.power_down_on_bus_suspend = 1,
 };
 
-static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+struct tegra_ehci_platform_data tegra_ehci3_pdata = {
 	.operating_mode = TEGRA_USB_HOST,
 	.power_down_on_bus_suspend = 1,
 };
diff -druN linux-libre-3.3-gnu/arch/arm/mach-tegra/devices.h linux-libre-3.3.2-gnu/arch/arm/mach-tegra/devices.h
--- linux-libre-3.3-gnu/arch/arm/mach-tegra/devices.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-tegra/devices.h	2012-04-13 12:42:02.000000000 -0400
@@ -20,6 +20,11 @@
 #define __MACH_TEGRA_DEVICES_H
 
 #include <linux/platform_device.h>
+#include <linux/platform_data/tegra_usb.h>
+
+extern struct tegra_ehci_platform_data tegra_ehci1_pdata;
+extern struct tegra_ehci_platform_data tegra_ehci2_pdata;
+extern struct tegra_ehci_platform_data tegra_ehci3_pdata;
 
 extern struct platform_device tegra_gpio_device;
 extern struct platform_device tegra_pinmux_device;
diff -druN linux-libre-3.3-gnu/arch/arm/mach-tegra/Kconfig linux-libre-3.3.2-gnu/arch/arm/mach-tegra/Kconfig
--- linux-libre-3.3-gnu/arch/arm/mach-tegra/Kconfig	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/arm/mach-tegra/Kconfig	2012-04-13 12:42:02.000000000 -0400
@@ -10,6 +10,13 @@
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB_SUPPORT
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_742230
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_754327
+	select ARM_ERRATA_764369
+	select PL310_ERRATA_727915 if CACHE_L2X0
+	select PL310_ERRATA_769419 if CACHE_L2X0
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -23,6 +30,11 @@
 	select USB_ULPI if USB_SUPPORT
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
 	select USE_OF
+	select ARM_ERRATA_743622
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_764369
+	select PL310_ERRATA_769419 if CACHE_L2X0
 	help
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff -druN linux-libre-3.3-gnu/arch/m68k/mac/config.c linux-libre-3.3.2-gnu/arch/m68k/mac/config.c
--- linux-libre-3.3-gnu/arch/m68k/mac/config.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/m68k/mac/config.c	2012-04-13 12:42:02.000000000 -0400
@@ -981,6 +981,9 @@
 {
 	u8 *swim_base;
 
+	if (!MACH_IS_MAC)
+		return -ENODEV;
+
 	/*
 	 * Serial devices
 	 */
diff -druN linux-libre-3.3-gnu/arch/x86/include/asm/timer.h linux-libre-3.3.2-gnu/arch/x86/include/asm/timer.h
--- linux-libre-3.3-gnu/arch/x86/include/asm/timer.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/include/asm/timer.h	2012-04-13 12:42:02.000000000 -0400
@@ -57,14 +57,10 @@
 
 static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
 {
-	unsigned long long quot;
-	unsigned long long rem;
 	int cpu = smp_processor_id();
 	unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
-	quot = (cyc >> CYC2NS_SCALE_FACTOR);
-	rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
-	ns += quot * per_cpu(cyc2ns, cpu) +
-		((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
+	ns += mult_frac(cyc, per_cpu(cyc2ns, cpu),
+			(1UL << CYC2NS_SCALE_FACTOR));
 	return ns;
 }
 
diff -druN linux-libre-3.3-gnu/arch/x86/kernel/entry_32.S linux-libre-3.3.2-gnu/arch/x86/kernel/entry_32.S
--- linux-libre-3.3-gnu/arch/x86/kernel/entry_32.S	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/kernel/entry_32.S	2012-04-13 12:42:02.000000000 -0400
@@ -98,12 +98,6 @@
 #endif
 .endm
 
-#ifdef CONFIG_VM86
-#define resume_userspace_sig	check_userspace
-#else
-#define resume_userspace_sig	resume_userspace
-#endif
-
 /*
  * User gs save/restore
  *
@@ -327,10 +321,19 @@
 	preempt_stop(CLBR_ANY)
 ret_from_intr:
 	GET_THREAD_INFO(%ebp)
-check_userspace:
+resume_userspace_sig:
+#ifdef CONFIG_VM86
 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
 	movb PT_CS(%esp), %al
 	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+	/*
+	 * We can be coming here from a syscall done in the kernel space,
+	 * e.g. a failed kernel_execve().
+	 */
+	movl PT_CS(%esp), %eax
+	andl $SEGMENT_RPL_MASK, %eax
+#endif
 	cmpl $USER_RPL, %eax
 	jb resume_kernel		# not returning to v8086 or userspace
 
diff -druN linux-libre-3.3-gnu/arch/x86/kernel/kgdb.c linux-libre-3.3.2-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-3.3-gnu/arch/x86/kernel/kgdb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/kernel/kgdb.c	2012-04-13 12:42:02.000000000 -0400
@@ -43,6 +43,8 @@
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
 
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
@@ -740,6 +742,64 @@
 	regs->ip = ip;
 }
 
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+	int err;
+	char opc[BREAK_INSTR_SIZE];
+
+	bpt->type = BP_BREAKPOINT;
+	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+				BREAK_INSTR_SIZE);
+	if (err)
+		return err;
+	err = probe_kernel_write((char *)bpt->bpt_addr,
+				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+#ifdef CONFIG_DEBUG_RODATA
+	if (!err)
+		return err;
+	/*
+	 * It is safe to call text_poke() because normal kernel execution
+	 * is stopped on all cores, so long as the text_mutex is not locked.
+	 */
+	if (mutex_is_locked(&text_mutex))
+		return -EBUSY;
+	text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+		  BREAK_INSTR_SIZE);
+	err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+	if (err)
+		return err;
+	if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
+		return -EINVAL;
+	bpt->type = BP_POKE_BREAKPOINT;
+#endif /* CONFIG_DEBUG_RODATA */
+	return err;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+#ifdef CONFIG_DEBUG_RODATA
+	int err;
+	char opc[BREAK_INSTR_SIZE];
+
+	if (bpt->type != BP_POKE_BREAKPOINT)
+		goto knl_write;
+	/*
+	 * It is safe to call text_poke() because normal kernel execution
+	 * is stopped on all cores, so long as the text_mutex is not locked.
+	 */
+	if (mutex_is_locked(&text_mutex))
+		goto knl_write;
+	text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE);
+	err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+	if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
+		goto knl_write;
+	return err;
+knl_write:
+#endif /* CONFIG_DEBUG_RODATA */
+	return probe_kernel_write((char *)bpt->bpt_addr,
+				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
+}
+
 struct kgdb_arch arch_kgdb_ops = {
 	/* Breakpoint instruction: */
 	.gdb_bpt_instr		= { 0xcc },
diff -druN linux-libre-3.3-gnu/arch/x86/kernel/tls.c linux-libre-3.3.2-gnu/arch/x86/kernel/tls.c
--- linux-libre-3.3-gnu/arch/x86/kernel/tls.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/kernel/tls.c	2012-04-13 12:42:02.000000000 -0400
@@ -163,7 +163,7 @@
 {
 	const struct desc_struct *tls;
 
-	if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+	if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
 	    (pos % sizeof(struct user_desc)) != 0 ||
 	    (count % sizeof(struct user_desc)) != 0)
 		return -EINVAL;
@@ -198,7 +198,7 @@
 	struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
 	const struct user_desc *info;
 
-	if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+	if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
 	    (pos % sizeof(struct user_desc)) != 0 ||
 	    (count % sizeof(struct user_desc)) != 0)
 		return -EINVAL;
diff -druN linux-libre-3.3-gnu/arch/x86/kernel/tsc.c linux-libre-3.3.2-gnu/arch/x86/kernel/tsc.c
--- linux-libre-3.3-gnu/arch/x86/kernel/tsc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/kernel/tsc.c	2012-04-13 12:42:02.000000000 -0400
@@ -620,7 +620,8 @@
 
 	if (cpu_khz) {
 		*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
-		*offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
+		*offset = ns_now - mult_frac(tsc_now, *scale,
+					     (1UL << CYC2NS_SCALE_FACTOR));
 	}
 
 	sched_clock_idle_wakeup_event(0);
@@ -932,6 +933,16 @@
 		clocksource_tsc.rating = 0;
 		clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
 	}
+
+	/*
+	 * Trust the results of the earlier calibration on systems
+	 * exporting a reliable TSC.
+	 */
+	if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+		clocksource_register_khz(&clocksource_tsc, tsc_khz);
+		return 0;
+	}
+
 	schedule_delayed_work(&tsc_irqwork, 0);
 	return 0;
 }
diff -druN linux-libre-3.3-gnu/arch/x86/kernel/vm86_32.c linux-libre-3.3.2-gnu/arch/x86/kernel/vm86_32.c
--- linux-libre-3.3-gnu/arch/x86/kernel/vm86_32.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/kernel/vm86_32.c	2012-04-13 12:42:02.000000000 -0400
@@ -172,6 +172,7 @@
 	spinlock_t *ptl;
 	int i;
 
+	down_write(&mm->mmap_sem);
 	pgd = pgd_offset(mm, 0xA0000);
 	if (pgd_none_or_clear_bad(pgd))
 		goto out;
@@ -190,6 +191,7 @@
 	}
 	pte_unmap_unlock(pte, ptl);
 out:
+	up_write(&mm->mmap_sem);
 	flush_tlb();
 }
 
diff -druN linux-libre-3.3-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-3.3.2-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-3.3-gnu/arch/x86/net/bpf_jit_comp.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/net/bpf_jit_comp.c	2012-04-13 12:42:02.000000000 -0400
@@ -289,7 +289,7 @@
 					EMIT2(0x24, K & 0xFF); /* and imm8,%al */
 				} else if (K >= 0xFFFF0000) {
 					EMIT2(0x66, 0x25);	/* and imm16,%ax */
-					EMIT2(K, 2);
+					EMIT(K, 2);
 				} else {
 					EMIT1_off32(0x25, K);	/* and imm32,%eax */
 				}
@@ -475,8 +475,10 @@
 			case BPF_S_LD_W_ABS:
 				func = sk_load_word;
 common_load:			seen |= SEEN_DATAREF;
-				if ((int)K < 0)
+				if ((int)K < 0) {
+					/* Abort the JIT because __load_pointer() is needed. */
 					goto out;
+				}
 				t_offset = func - (image + addrs[i]);
 				EMIT1_off32(0xbe, K); /* mov imm32,%esi */
 				EMIT1_off32(0xe8, t_offset); /* call */
@@ -489,14 +491,8 @@
 				goto common_load;
 			case BPF_S_LDX_B_MSH:
 				if ((int)K < 0) {
-					if (pc_ret0 > 0) {
-						/* addrs[pc_ret0 - 1] is the start address */
-						EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]);
-						break;
-					}
-					CLEAR_A();
-					EMIT_JMP(cleanup_addr - addrs[i]);
-					break;
+					/* Abort the JIT because __load_pointer() is needed. */
+					goto out;
 				}
 				seen |= SEEN_DATAREF | SEEN_XREG;
 				t_offset = sk_load_byte_msh - (image + addrs[i]);
diff -druN linux-libre-3.3-gnu/arch/x86/syscalls/syscall_32.tbl linux-libre-3.3.2-gnu/arch/x86/syscalls/syscall_32.tbl
--- linux-libre-3.3-gnu/arch/x86/syscalls/syscall_32.tbl	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/arch/x86/syscalls/syscall_32.tbl	2012-04-13 12:42:02.000000000 -0400
@@ -288,7 +288,7 @@
 279	i386	mq_timedsend		sys_mq_timedsend		compat_sys_mq_timedsend
 280	i386	mq_timedreceive		sys_mq_timedreceive		compat_sys_mq_timedreceive
 281	i386	mq_notify		sys_mq_notify			compat_sys_mq_notify
-282	i386	mq_getsetaddr		sys_mq_getsetattr		compat_sys_mq_getsetattr
+282	i386	mq_getsetattr		sys_mq_getsetattr		compat_sys_mq_getsetattr
 283	i386	kexec_load		sys_kexec_load			compat_sys_kexec_load
 284	i386	waitid			sys_waitid			compat_sys_waitid
 # 285 sys_setaltroot
diff -druN linux-libre-3.3-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-3.3.2-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-3.3-gnu/drivers/acpi/acpica/tbfadt.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/acpi/acpica/tbfadt.c	2012-04-13 12:42:02.000000000 -0400
@@ -363,10 +363,6 @@
 	u32 address32;
 	u32 i;
 
-	/* Update the local FADT table header length */
-
-	acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
-
 	/*
 	 * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
 	 * Later code will always use the X 64-bit field. Also, check for an
@@ -408,6 +404,10 @@
 		acpi_gbl_FADT.boot_flags = 0;
 	}
 
+	/* Update the local FADT table header length */
+
+	acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
+
 	/*
 	 * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
 	 * generic address structures as necessary. Later code will always use
diff -druN linux-libre-3.3-gnu/drivers/acpi/processor_thermal.c linux-libre-3.3.2-gnu/drivers/acpi/processor_thermal.c
--- linux-libre-3.3-gnu/drivers/acpi/processor_thermal.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/acpi/processor_thermal.c	2012-04-13 12:42:02.000000000 -0400
@@ -57,6 +57,27 @@
 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
 static unsigned int acpi_thermal_cpufreq_is_init = 0;
 
+#define reduction_pctg(cpu) \
+	per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
+
+/*
+ * Emulate "per package data" using per cpu data (which should really be
+ * provided elsewhere)
+ *
+ * Note we can lose a CPU on cpu hotunplug, in this case we forget the state
+ * temporarily. Fortunately that's not a big issue here (I hope)
+ */
+static int phys_package_first_cpu(int cpu)
+{
+	int i;
+	int id = topology_physical_package_id(cpu);
+
+	for_each_online_cpu(i)
+		if (topology_physical_package_id(i) == id)
+			return i;
+	return 0;
+}
+
 static int cpu_has_cpufreq(unsigned int cpu)
 {
 	struct cpufreq_policy policy;
@@ -76,7 +97,7 @@
 
 	max_freq = (
 	    policy->cpuinfo.max_freq *
-	    (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
+	    (100 - reduction_pctg(policy->cpu) * 20)
 	) / 100;
 
 	cpufreq_verify_within_limits(policy, 0, max_freq);
@@ -102,16 +123,28 @@
 	if (!cpu_has_cpufreq(cpu))
 		return 0;
 
-	return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+	return reduction_pctg(cpu);
 }
 
 static int cpufreq_set_cur_state(unsigned int cpu, int state)
 {
+	int i;
+
 	if (!cpu_has_cpufreq(cpu))
 		return 0;
 
-	per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
-	cpufreq_update_policy(cpu);
+	reduction_pctg(cpu) = state;
+
+	/*
+	 * Update all the CPUs in the same package because they all
+	 * contribute to the temperature and often share the same
+	 * frequency.
+	 */
+	for_each_online_cpu(i) {
+		if (topology_physical_package_id(i) ==
+		    topology_physical_package_id(cpu))
+			cpufreq_update_policy(i);
+	}
 	return 0;
 }
 
@@ -119,10 +152,6 @@
 {
 	int i;
 
-	for (i = 0; i < nr_cpu_ids; i++)
-		if (cpu_present(i))
-			per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
-
 	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
 				      CPUFREQ_POLICY_NOTIFIER);
 	if (!i)
diff -druN linux-libre-3.3-gnu/drivers/ata/ahci.c linux-libre-3.3.2-gnu/drivers/ata/ahci.c
--- linux-libre-3.3-gnu/drivers/ata/ahci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/ata/ahci.c	2012-04-13 12:42:02.000000000 -0400
@@ -103,8 +103,6 @@
 	.hardreset		= ahci_p5wdh_hardreset,
 };
 
-#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
-
 static const struct ata_port_info ahci_port_info[] = {
 	/* by features */
 	[board_ahci] =
diff -druN linux-libre-3.3-gnu/drivers/ata/ahci.h linux-libre-3.3.2-gnu/drivers/ata/ahci.h
--- linux-libre-3.3-gnu/drivers/ata/ahci.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/ata/ahci.h	2012-04-13 12:42:02.000000000 -0400
@@ -195,6 +195,9 @@
 	PORT_FBS_EN		= (1 << 0), /* Enable FBS */
 
 	/* hpriv->flags bits */
+
+#define AHCI_HFLAGS(flags)		.private_data	= (void *)(flags)
+
 	AHCI_HFLAG_NO_NCQ		= (1 << 0),
 	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */
 	AHCI_HFLAG_IGN_SERR_INTERNAL	= (1 << 2), /* ignore SERR_INTERNAL */
@@ -210,6 +213,9 @@
 	AHCI_HFLAG_NO_SNTF		= (1 << 12), /* no sntf */
 	AHCI_HFLAG_NO_FPDMA_AA		= (1 << 13), /* no FPDMA AA */
 	AHCI_HFLAG_YES_FBS		= (1 << 14), /* force FBS cap on */
+	AHCI_HFLAG_DELAY_ENGINE		= (1 << 15), /* do not start engine on
+						        port start (wait until
+						        error-handling stage) */
 
 	/* ap->flags bits */
 
diff -druN linux-libre-3.3-gnu/drivers/ata/ahci_platform.c linux-libre-3.3.2-gnu/drivers/ata/ahci_platform.c
--- linux-libre-3.3-gnu/drivers/ata/ahci_platform.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/ata/ahci_platform.c	2012-04-13 12:42:02.000000000 -0400
@@ -26,6 +26,7 @@
 enum ahci_type {
 	AHCI,		/* standard platform ahci */
 	IMX53_AHCI,	/* ahci on i.mx53 */
+	STRICT_AHCI,	/* delayed DMA engine start */
 };
 
 static struct platform_device_id ahci_devtype[] = {
@@ -36,6 +37,9 @@
 		.name = "imx53-ahci",
 		.driver_data = IMX53_AHCI,
 	}, {
+		.name = "strict-ahci",
+		.driver_data = STRICT_AHCI,
+	}, {
 		/* sentinel */
 	}
 };
@@ -56,6 +60,13 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_pmp_retry_srst_ops,
 	},
+	[STRICT_AHCI] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_DELAY_ENGINE),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 };
 
 static struct scsi_host_template ahci_platform_sht = {
diff -druN linux-libre-3.3-gnu/drivers/ata/libahci.c linux-libre-3.3.2-gnu/drivers/ata/libahci.c
--- linux-libre-3.3-gnu/drivers/ata/libahci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/ata/libahci.c	2012-04-13 12:42:02.000000000 -0400
@@ -737,6 +737,7 @@
 
 static void ahci_start_port(struct ata_port *ap)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp = ap->private_data;
 	struct ata_link *link;
 	struct ahci_em_priv *emp;
@@ -746,6 +747,10 @@
 	/* enable FIS reception */
 	ahci_start_fis_rx(ap);
 
+	/* enable DMA */
+	if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
+		ahci_start_engine(ap);
+
 	/* turn on LEDs */
 	if (ap->flags & ATA_FLAG_EM) {
 		ata_for_each_link(link, ap, EDGE) {
diff -druN linux-libre-3.3-gnu/drivers/ata/pata_legacy.c linux-libre-3.3.2-gnu/drivers/ata/pata_legacy.c
--- linux-libre-3.3-gnu/drivers/ata/pata_legacy.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/ata/pata_legacy.c	2012-04-13 12:42:02.000000000 -0400
@@ -401,8 +401,7 @@
 	ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
 
 	active = clamp_val(t.active, 2, 15);
-	recover = clamp_val(t.recover, 2, 16);
-	recover &= 0x15;
+	recover = clamp_val(t.recover, 2, 16) & 0x0F;
 
 	inb(0x3E6);
 	inb(0x3E6);
diff -druN linux-libre-3.3-gnu/drivers/base/firmware_class.c linux-libre-3.3.2-gnu/drivers/base/firmware_class.c
--- linux-libre-3.3-gnu/drivers/base/firmware_class.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/base/firmware_class.c	2012-04-13 12:42:02.000000000 -0400
@@ -81,6 +81,11 @@
 
 static int loading_timeout = 60;	/* In seconds */
 
+static inline long firmware_loading_timeout(void)
+{
+	return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
+}
+
 /* fw_lock could be moved to 'struct firmware_priv' but since it is just
  * guarding for corner cases a global lock should be OK */
 static DEFINE_MUTEX(fw_lock);
@@ -435,7 +440,7 @@
 }
 
 static struct firmware_priv *
-fw_create_instance(struct firmware *firmware, const char *fw_name,
+fw_create_instance(const struct firmware *firmware, const char *fw_name,
 		   struct device *device, bool uevent, bool nowait)
 {
 	struct firmware_priv *fw_priv;
@@ -449,7 +454,7 @@
 		goto err_out;
 	}
 
-	fw_priv->fw = firmware;
+	fw_priv->fw = (struct firmware *)firmware;
 	fw_priv->nowait = nowait;
 	strcpy(fw_priv->fw_id, fw_name);
 	init_completion(&fw_priv->completion);
@@ -510,13 +515,10 @@
 	device_unregister(f_dev);
 }
 
-static int _request_firmware(const struct firmware **firmware_p,
-			     const char *name, struct device *device,
-			     bool uevent, bool nowait)
+static int _request_firmware_prepare(const struct firmware **firmware_p,
+				     const char *name, struct device *device)
 {
-	struct firmware_priv *fw_priv;
 	struct firmware *firmware;
-	int retval = 0;
 
 	if (!firmware_p)
 		return -EINVAL;
@@ -533,28 +535,33 @@
 		return 0;
 	}
 
-	read_lock_usermodehelper();
+	return 1;
+}
 
-	if (WARN_ON(usermodehelper_is_disabled())) {
-		dev_err(device, "firmware: %s will not be loaded\n", name);
-		retval = -EBUSY;
-		goto out;
-	}
+static void _request_firmware_cleanup(const struct firmware **firmware_p)
+{
+	release_firmware(*firmware_p);
+	*firmware_p = NULL;
+}
+
+static int _request_firmware(const struct firmware *firmware,
+			     const char *name, struct device *device,
+			     bool uevent, bool nowait, long timeout)
+{
+	struct firmware_priv *fw_priv;
+	int retval = 0;
 
 	if (uevent)
 		dev_dbg(device, "firmware: requesting %s\n", name);
 
 	fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
-	if (IS_ERR(fw_priv)) {
-		retval = PTR_ERR(fw_priv);
-		goto out;
-	}
+	if (IS_ERR(fw_priv))
+		return PTR_ERR(fw_priv);
 
 	if (uevent) {
-		if (loading_timeout > 0)
+		if (timeout != MAX_SCHEDULE_TIMEOUT)
 			mod_timer(&fw_priv->timeout,
-				  round_jiffies_up(jiffies +
-						   loading_timeout * HZ));
+				  round_jiffies_up(jiffies + timeout));
 
 		kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
 	}
@@ -571,15 +578,6 @@
 	mutex_unlock(&fw_lock);
 
 	fw_destroy_instance(fw_priv);
-
-out:
-	read_unlock_usermodehelper();
-
-	if (retval) {
-		release_firmware(firmware);
-		*firmware_p = NULL;
-	}
-
 	return retval;
 }
 
@@ -602,7 +600,24 @@
 request_firmware(const struct firmware **firmware_p, const char *name,
                  struct device *device)
 {
-        return _request_firmware(firmware_p, name, device, true, false);
+	int ret;
+
+	ret = _request_firmware_prepare(firmware_p, name, device);
+	if (ret <= 0)
+		return ret;
+
+	ret = usermodehelper_read_trylock();
+	if (WARN_ON(ret)) {
+		dev_err(device, "firmware: %s will not be loaded\n", name);
+	} else {
+		ret = _request_firmware(*firmware_p, name, device, true, false,
+					firmware_loading_timeout());
+		usermodehelper_read_unlock();
+	}
+	if (ret)
+		_request_firmware_cleanup(firmware_p);
+
+	return ret;
 }
 
 /**
@@ -633,6 +648,7 @@
 {
 	struct firmware_work *fw_work = arg;
 	const struct firmware *fw;
+	long timeout;
 	int ret;
 
 	if (!arg) {
@@ -640,8 +656,24 @@
 		return 0;
 	}
 
-	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
-				fw_work->uevent, true);
+	ret = _request_firmware_prepare(&fw, fw_work->name, fw_work->device);
+	if (ret <= 0)
+		goto out;
+
+	timeout = usermodehelper_read_lock_wait(firmware_loading_timeout());
+	if (timeout) {
+		ret = _request_firmware(fw, fw_work->name, fw_work->device,
+					fw_work->uevent, true, timeout);
+		usermodehelper_read_unlock();
+	} else {
+		dev_dbg(fw_work->device, "firmware: %s loading timed out\n",
+			fw_work->name);
+		ret = -EAGAIN;
+	}
+	if (ret)
+		_request_firmware_cleanup(&fw);
+
+ out:
 	fw_work->cont(fw, fw_work->context);
 
 	module_put(fw_work->module);
diff -druN linux-libre-3.3-gnu/drivers/base/power/domain.c linux-libre-3.3.2-gnu/drivers/base/power/domain.c
--- linux-libre-3.3-gnu/drivers/base/power/domain.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/base/power/domain.c	2012-04-13 12:42:02.000000000 -0400
@@ -366,7 +366,7 @@
 	not_suspended = 0;
 	list_for_each_entry(pdd, &genpd->dev_list, list_node)
 		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-		    || pdd->dev->power.irq_safe))
+		    || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on))
 			not_suspended++;
 
 	if (not_suspended > genpd->in_progress)
@@ -503,6 +503,9 @@
 
 	might_sleep_if(!genpd->dev_irq_safe);
 
+	if (dev_gpd_data(dev)->always_on)
+		return -EBUSY;
+
 	stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
 	if (stop_ok && !stop_ok(dev))
 		return -EBUSY;
@@ -764,8 +767,10 @@
 
 	genpd_acquire_lock(genpd);
 
-	if (genpd->prepared_count++ == 0)
+	if (genpd->prepared_count++ == 0) {
+		genpd->suspended_count = 0;
 		genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
+	}
 
 	genpd_release_lock(genpd);
 
@@ -845,7 +850,8 @@
 	if (ret)
 		return ret;
 
-	if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
+	if (dev_gpd_data(dev)->always_on
+	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
 	genpd_stop_dev(genpd, dev);
@@ -880,7 +886,8 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
+	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
 	/*
@@ -957,7 +964,7 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
 		return 0;
 
 	ret = genpd_freeze_late(genpd, dev);
@@ -988,7 +995,7 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
 		return 0;
 
 	genpd_start_dev(genpd, dev);
@@ -1040,20 +1047,31 @@
 	 * Since all of the "noirq" callbacks are executed sequentially, it is
 	 * guaranteed that this function will never run twice in parallel for
 	 * the same PM domain, so it is not necessary to use locking here.
+	 *
+	 * At this point suspended_count == 0 means we are being run for the
+	 * first time for the given domain in the present cycle.
 	 */
-	genpd->status = GPD_STATE_POWER_OFF;
-	if (genpd->suspend_power_off) {
+	if (genpd->suspended_count++ == 0) {
 		/*
-		 * The boot kernel might put the domain into the power on state,
-		 * so make sure it really is powered off.
+		 * The boot kernel might put the domain into arbitrary state,
+		 * so make it appear as powered off to pm_genpd_poweron(), so
+		 * that it tries to power it on in case it was really off.
 		 */
-		if (genpd->power_off)
-			genpd->power_off(genpd);
-		return 0;
+		genpd->status = GPD_STATE_POWER_OFF;
+		if (genpd->suspend_power_off) {
+			/*
+			 * If the domain was off before the hibernation, make
+			 * sure it will be off going forward.
+			 */
+			if (genpd->power_off)
+				genpd->power_off(genpd);
+		}
 	}
 
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
+		return 0;
+
 	pm_genpd_poweron(genpd);
-	genpd->suspended_count--;
 	genpd_start_dev(genpd, dev);
 
 	return genpd_resume_early(genpd, dev);
@@ -1216,6 +1234,26 @@
 }
 
 /**
+ * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device.
+ * @dev: Device to set/unset the flag for.
+ * @val: The new value of the device's "always on" flag.
+ */
+void pm_genpd_dev_always_on(struct device *dev, bool val)
+{
+	struct pm_subsys_data *psd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	psd = dev_to_psd(dev);
+	if (psd && psd->domain_data)
+		to_gpd_data(psd->domain_data)->always_on = val;
+
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on);
+
+/**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
  * @genpd: Master PM domain to add the subdomain to.
  * @subdomain: Subdomain to be added.
@@ -1557,7 +1595,6 @@
 	genpd->poweroff_task = NULL;
 	genpd->resume_count = 0;
 	genpd->device_count = 0;
-	genpd->suspended_count = 0;
 	genpd->max_off_time_ns = -1;
 	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
 	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
diff -druN linux-libre-3.3-gnu/drivers/base/power/runtime.c linux-libre-3.3.2-gnu/drivers/base/power/runtime.c
--- linux-libre-3.3-gnu/drivers/base/power/runtime.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/base/power/runtime.c	2012-04-13 12:42:02.000000000 -0400
@@ -532,6 +532,8 @@
 	dev->power.suspend_time = ktime_set(0, 0);
 	dev->power.max_time_suspended_ns = -1;
 	dev->power.deferred_resume = false;
+	wake_up_all(&dev->power.wait_queue);
+
 	if (retval == -EAGAIN || retval == -EBUSY) {
 		dev->power.runtime_error = 0;
 
@@ -547,7 +549,6 @@
 	} else {
 		pm_runtime_cancel_pending(dev);
 	}
-	wake_up_all(&dev->power.wait_queue);
 	goto out;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/base/regmap/regcache-rbtree.c linux-libre-3.3.2-gnu/drivers/base/regmap/regcache-rbtree.c
--- linux-libre-3.3-gnu/drivers/base/regmap/regcache-rbtree.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/base/regmap/regcache-rbtree.c	2012-04-13 12:42:02.000000000 -0400
@@ -137,6 +137,7 @@
 	unsigned int base, top;
 	int nodes = 0;
 	int registers = 0;
+	int average;
 
 	mutex_lock(&map->lock);
 
@@ -151,8 +152,13 @@
 		registers += top - base + 1;
 	}
 
+	if (nodes)
+		average = registers / nodes;
+	else
+		average = 0;
+
 	seq_printf(s, "%d nodes, %d registers, average %d registers\n",
-		   nodes, registers, registers / nodes);
+		   nodes, registers, average);
 
 	mutex_unlock(&map->lock);
 
diff -druN linux-libre-3.3-gnu/drivers/bluetooth/ath3k.c linux-libre-3.3.2-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-3.3-gnu/drivers/bluetooth/ath3k.c	2012-03-19 01:20:14.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/bluetooth/ath3k.c	2012-04-13 23:04:11.000000000 -0400
@@ -65,6 +65,7 @@
 	{ USB_DEVICE(0x0CF3, 0x3002) },
 	{ USB_DEVICE(0x13d3, 0x3304) },
 	{ USB_DEVICE(0x0930, 0x0215) },
+	{ USB_DEVICE(0x0489, 0xE03D) },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
diff -druN linux-libre-3.3-gnu/drivers/bluetooth/btusb.c linux-libre-3.3.2-gnu/drivers/bluetooth/btusb.c
--- linux-libre-3.3-gnu/drivers/bluetooth/btusb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/bluetooth/btusb.c	2012-04-13 12:42:02.000000000 -0400
@@ -121,6 +121,7 @@
 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
diff -druN linux-libre-3.3-gnu/drivers/char/tpm/Kconfig linux-libre-3.3.2-gnu/drivers/char/tpm/Kconfig
--- linux-libre-3.3-gnu/drivers/char/tpm/Kconfig	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/char/tpm/Kconfig	2012-04-13 12:42:02.000000000 -0400
@@ -5,7 +5,6 @@
 menuconfig TCG_TPM
 	tristate "TPM Hardware Support"
 	depends on HAS_IOMEM
-	depends on EXPERIMENTAL
 	select SECURITYFS
 	---help---
 	  If you have a TPM security chip in your system, which
diff -druN linux-libre-3.3-gnu/drivers/char/tpm/tpm.c linux-libre-3.3.2-gnu/drivers/char/tpm/tpm.c
--- linux-libre-3.3-gnu/drivers/char/tpm/tpm.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/char/tpm/tpm.c	2012-04-13 12:42:02.000000000 -0400
@@ -1221,12 +1221,13 @@
 	ret_size = atomic_read(&chip->data_pending);
 	atomic_set(&chip->data_pending, 0);
 	if (ret_size > 0) {	/* relay data */
+		ssize_t orig_ret_size = ret_size;
 		if (size < ret_size)
 			ret_size = size;
 
 		mutex_lock(&chip->buffer_mutex);
 		rc = copy_to_user(buf, chip->data_buffer, ret_size);
-		memset(chip->data_buffer, 0, ret_size);
+		memset(chip->data_buffer, 0, orig_ret_size);
 		if (rc)
 			ret_size = -EFAULT;
 
diff -druN linux-libre-3.3-gnu/drivers/clocksource/sh_cmt.c linux-libre-3.3.2-gnu/drivers/clocksource/sh_cmt.c
--- linux-libre-3.3-gnu/drivers/clocksource/sh_cmt.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/clocksource/sh_cmt.c	2012-04-13 12:42:02.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
@@ -689,6 +690,9 @@
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
diff -druN linux-libre-3.3-gnu/drivers/clocksource/sh_mtu2.c linux-libre-3.3.2-gnu/drivers/clocksource/sh_mtu2.c
--- linux-libre-3.3-gnu/drivers/clocksource/sh_mtu2.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/clocksource/sh_mtu2.c	2012-04-13 12:42:02.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
@@ -306,6 +307,9 @@
 	struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
diff -druN linux-libre-3.3-gnu/drivers/clocksource/sh_tmu.c linux-libre-3.3.2-gnu/drivers/clocksource/sh_tmu.c
--- linux-libre-3.3-gnu/drivers/clocksource/sh_tmu.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/clocksource/sh_tmu.c	2012-04-13 12:42:02.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
@@ -410,6 +411,9 @@
 	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
diff -druN linux-libre-3.3-gnu/drivers/dma/ioat/dma.c linux-libre-3.3.2-gnu/drivers/dma/ioat/dma.c
--- linux-libre-3.3-gnu/drivers/dma/ioat/dma.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/dma/ioat/dma.c	2012-04-13 12:42:02.000000000 -0400
@@ -548,9 +548,9 @@
 			   PCI_DMA_TODEVICE, flags, 0);
 }
 
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan)
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan)
 {
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 	u64 completion;
 
 	completion = *chan->completion;
@@ -571,7 +571,7 @@
 }
 
 bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
-			   unsigned long *phys_complete)
+			   dma_addr_t *phys_complete)
 {
 	*phys_complete = ioat_get_current_completion(chan);
 	if (*phys_complete == chan->last_completion)
@@ -582,14 +582,14 @@
 	return true;
 }
 
-static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat_dma_chan *ioat, dma_addr_t phys_complete)
 {
 	struct ioat_chan_common *chan = &ioat->base;
 	struct list_head *_desc, *n;
 	struct dma_async_tx_descriptor *tx;
 
-	dev_dbg(to_dev(chan), "%s: phys_complete: %lx\n",
-		 __func__, phys_complete);
+	dev_dbg(to_dev(chan), "%s: phys_complete: %llx\n",
+		 __func__, (unsigned long long) phys_complete);
 	list_for_each_safe(_desc, n, &ioat->used_desc) {
 		struct ioat_desc_sw *desc;
 
@@ -655,7 +655,7 @@
 static void ioat1_cleanup(struct ioat_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 
 	prefetch(chan->completion);
 
@@ -701,7 +701,7 @@
 		mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
 		spin_unlock_bh(&ioat->desc_lock);
 	} else if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-		unsigned long phys_complete;
+		dma_addr_t phys_complete;
 
 		spin_lock_bh(&ioat->desc_lock);
 		/* if we haven't made progress and we have already
diff -druN linux-libre-3.3-gnu/drivers/dma/ioat/dma.h linux-libre-3.3.2-gnu/drivers/dma/ioat/dma.h
--- linux-libre-3.3-gnu/drivers/dma/ioat/dma.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/dma/ioat/dma.h	2012-04-13 12:42:02.000000000 -0400
@@ -88,7 +88,7 @@
 struct ioat_chan_common {
 	struct dma_chan common;
 	void __iomem *reg_base;
-	unsigned long last_completion;
+	dma_addr_t last_completion;
 	spinlock_t cleanup_lock;
 	dma_cookie_t completed_cookie;
 	unsigned long state;
@@ -333,7 +333,7 @@
 void __devexit ioat_dma_remove(struct ioatdma_device *device);
 struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,
 					      void __iomem *iobase);
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan);
 void ioat_init_channel(struct ioatdma_device *device,
 		       struct ioat_chan_common *chan, int idx);
 enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
@@ -341,7 +341,7 @@
 void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
 		    size_t len, struct ioat_dma_descriptor *hw);
 bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
-			   unsigned long *phys_complete);
+			   dma_addr_t *phys_complete);
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
 extern const struct sysfs_ops ioat_sysfs_ops;
diff -druN linux-libre-3.3-gnu/drivers/dma/ioat/dma_v2.c linux-libre-3.3.2-gnu/drivers/dma/ioat/dma_v2.c
--- linux-libre-3.3-gnu/drivers/dma/ioat/dma_v2.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/dma/ioat/dma_v2.c	2012-04-13 12:42:02.000000000 -0400
@@ -126,7 +126,7 @@
 	spin_unlock_bh(&ioat->prep_lock);
 }
 
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
 {
 	struct ioat_chan_common *chan = &ioat->base;
 	struct dma_async_tx_descriptor *tx;
@@ -178,7 +178,7 @@
 static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 
 	spin_lock_bh(&chan->cleanup_lock);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -259,7 +259,7 @@
 static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 
 	ioat2_quiesce(chan, 0);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -274,7 +274,7 @@
 	struct ioat_chan_common *chan = &ioat->base;
 
 	if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-		unsigned long phys_complete;
+		dma_addr_t phys_complete;
 		u64 status;
 
 		status = ioat_chansts(chan);
diff -druN linux-libre-3.3-gnu/drivers/dma/ioat/dma_v3.c linux-libre-3.3.2-gnu/drivers/dma/ioat/dma_v3.c
--- linux-libre-3.3-gnu/drivers/dma/ioat/dma_v3.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/dma/ioat/dma_v3.c	2012-04-13 12:42:02.000000000 -0400
@@ -256,7 +256,7 @@
  * The difference from the dma_v2.c __cleanup() is that this routine
  * handles extended descriptors and dma-unmapping raid operations.
  */
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
 {
 	struct ioat_chan_common *chan = &ioat->base;
 	struct ioat_ring_ent *desc;
@@ -314,7 +314,7 @@
 static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 
 	spin_lock_bh(&chan->cleanup_lock);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -333,7 +333,7 @@
 static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	dma_addr_t phys_complete;
 
 	ioat2_quiesce(chan, 0);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -348,7 +348,7 @@
 	struct ioat_chan_common *chan = &ioat->base;
 
 	if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-		unsigned long phys_complete;
+		dma_addr_t phys_complete;
 		u64 status;
 
 		status = ioat_chansts(chan);
diff -druN linux-libre-3.3-gnu/drivers/firewire/ohci.c linux-libre-3.3.2-gnu/drivers/firewire/ohci.c
--- linux-libre-3.3-gnu/drivers/firewire/ohci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/firewire/ohci.c	2012-04-13 12:42:02.000000000 -0400
@@ -2748,7 +2748,7 @@
 		container_of(context, struct iso_context, context);
 	u32 buffer_dma;
 
-	if (!last->transfer_status)
+	if (last->res_count != 0)
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
@@ -2762,8 +2762,7 @@
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
 		ctx->base.callback.mc(&ctx->base,
 				      le32_to_cpu(last->data_address) +
-				      le16_to_cpu(last->req_count) -
-				      le16_to_cpu(last->res_count),
+				      le16_to_cpu(last->req_count),
 				      ctx->base.callback_data);
 
 	return 1;
diff -druN linux-libre-3.3-gnu/drivers/gpio/gpio-davinci.c linux-libre-3.3.2-gnu/drivers/gpio/gpio-davinci.c
--- linux-libre-3.3-gnu/drivers/gpio/gpio-davinci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpio/gpio-davinci.c	2012-04-13 12:42:02.000000000 -0400
@@ -313,10 +313,16 @@
 		return -ENODEV;
 }
 
-static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
+static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
 {
-	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_handler_data(d);
+	struct davinci_gpio_controller *d;
+	struct davinci_gpio_regs __iomem *g;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	u32 mask;
+
+	d = (struct davinci_gpio_controller *)data->handler_data;
+	g = (struct davinci_gpio_regs __iomem *)d->regs;
+	mask = __gpio_mask(data->irq - soc_info->gpio_irq);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
@@ -380,7 +386,7 @@
 	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
 	 */
 	if (soc_info->gpio_unbanked) {
-		static struct irq_chip gpio_irqchip_unbanked;
+		static struct irq_chip_type gpio_unbanked;
 
 		/* pass "bank 0" GPIO IRQs to AINTC */
 		chips[0].chip.to_irq = gpio_to_irq_unbanked;
@@ -388,9 +394,10 @@
 
 		/* AINTC handles mask/unmask; GPIO handles triggering */
 		irq = bank_irq;
-		gpio_irqchip_unbanked = *irq_get_chip(irq);
-		gpio_irqchip_unbanked.name = "GPIO-AINTC";
-		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
+		gpio_unbanked = *container_of(irq_get_chip(irq),
+					      struct irq_chip_type, chip);
+		gpio_unbanked.chip.name = "GPIO-AINTC";
+		gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
 
 		/* default trigger: both edges */
 		g = gpio2regs(0);
@@ -399,9 +406,8 @@
 
 		/* set the direct IRQs up to use that irqchip */
 		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-			irq_set_chip(irq, &gpio_irqchip_unbanked);
-			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
-			irq_set_chip_data(irq, (__force void *)g);
+			irq_set_chip(irq, &gpio_unbanked.chip);
+			irq_set_handler_data(irq, &chips[gpio / 32]);
 			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
 		}
 
diff -druN linux-libre-3.3-gnu/drivers/gpio/gpio-omap.c linux-libre-3.3.2-gnu/drivers/gpio/gpio-omap.c
--- linux-libre-3.3-gnu/drivers/gpio/gpio-omap.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpio/gpio-omap.c	2012-04-13 12:42:02.000000000 -0400
@@ -508,7 +508,10 @@
 
 static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
 {
-	_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+	if (enable)
+		_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+	else
+		_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-3.3.2-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/drm_fb_helper.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/drm_fb_helper.c	2012-04-13 12:42:02.000000000 -0400
@@ -617,9 +617,13 @@
 		return -EINVAL;
 
 	/* Need to resize the fb object !!! */
-	if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+	if (var->bits_per_pixel > fb->bits_per_pixel ||
+	    var->xres > fb->width || var->yres > fb->height ||
+	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
 		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
-			  "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
+			  var->xres, var->yres, var->bits_per_pixel,
+			  var->xres_virtual, var->yres_virtual,
 			  fb->width, fb->height, fb->bits_per_pixel);
 		return -EINVAL;
 	}
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/gma500/framebuffer.c linux-libre-3.3.2-gnu/drivers/gpu/drm/gma500/framebuffer.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/gma500/framebuffer.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/gma500/framebuffer.c	2012-04-13 12:42:02.000000000 -0400
@@ -158,7 +158,7 @@
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
 
 	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	address = (unsigned long)vmf->virtual_address;
+	address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_drv.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_drv.c	2012-04-13 12:42:02.000000000 -0400
@@ -442,6 +442,10 @@
 	/* Modeset on resume, not lid events */
 	dev_priv->modeset_on_lid = 0;
 
+	console_lock();
+	intel_fbdev_set_suspend(dev, 1);
+	console_unlock();
+
 	return 0;
 }
 
@@ -504,7 +508,9 @@
 		drm_irq_install(dev);
 
 		/* Resume the modeset for every activated CRTC */
+		mutex_lock(&dev->mode_config.mutex);
 		drm_helper_resume_force_mode(dev);
+		mutex_unlock(&dev->mode_config.mutex);
 
 		if (IS_IRONLAKE_M(dev))
 			ironlake_enable_rc6(dev);
@@ -514,6 +520,9 @@
 
 	dev_priv->modeset_on_lid = 0;
 
+	console_lock();
+	intel_fbdev_set_suspend(dev, 0);
+	console_unlock();
 	return error;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_gem.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_gem.c	2012-04-13 12:42:02.000000000 -0400
@@ -3084,10 +3084,13 @@
 			return ret;
 	}
 
+	ret = i915_gem_object_wait_rendering(obj);
+	if (ret)
+		return ret;
+
 	/* Ensure that we invalidate the GPU's caches and TLBs. */
 	obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
-
-	return i915_gem_object_wait_rendering(obj);
+	return 0;
 }
 
 /**
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-04-13 12:42:02.000000000 -0400
@@ -2313,6 +2313,7 @@
 #define   PIPECONF_DISABLE	0
 #define   PIPECONF_DOUBLE_WIDE	(1<<30)
 #define   I965_PIPECONF_ACTIVE	(1<<30)
+#define   PIPECONF_FRAME_START_DELAY_MASK (3<<27)
 #define   PIPECONF_SINGLE_WIDE	0
 #define   PIPECONF_PIPE_UNLOCKED 0
 #define   PIPECONF_PIPE_LOCKED	(1<<25)
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_bios.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_bios.c	2012-04-13 12:42:02.000000000 -0400
@@ -24,6 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
+#include <linux/dmi.h>
 #include <drm/drm_dp_helper.h>
 #include "drmP.h"
 #include "drm.h"
@@ -621,6 +622,26 @@
 	dev_priv->edp.bpp = 18;
 }
 
+static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+		      "VBIOS ROM for %s\n",
+		      id->ident);
+	return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+	{
+		.callback = intel_no_opregion_vbt_callback,
+		.ident = "ThinkCentre A57",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+		},
+	},
+	{ }
+};
+
 /**
  * intel_parse_bios - find VBT and initialize settings from the BIOS
  * @dev: DRM device
@@ -641,7 +662,7 @@
 	init_vbt_defaults(dev_priv);
 
 	/* XXX Should this validation be moved to intel_opregion.c? */
-	if (dev_priv->opregion.vbt) {
+	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
 		struct vbt_header *vbt = dev_priv->opregion.vbt;
 		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
 			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_display.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_display.c	2012-04-13 12:42:02.000000000 -0400
@@ -7497,6 +7497,12 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg, val;
 
+	/* Clear any frame start delays used for debugging left by the BIOS */
+	for_each_pipe(pipe) {
+		reg = PIPECONF(pipe);
+		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	}
+
 	if (HAS_PCH_SPLIT(dev))
 		return;
 
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_drv.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_drv.h	2012-04-13 12:42:02.000000000 -0400
@@ -381,7 +381,7 @@
 				  struct drm_i915_gem_object *obj);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
-
+extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
 extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
 extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
 extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_fb.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_fb.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_fb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_fb.c	2012-04-13 12:42:02.000000000 -0400
@@ -258,6 +258,16 @@
 	kfree(dev_priv->fbdev);
 	dev_priv->fbdev = NULL;
 }
+
+void intel_fbdev_set_suspend(struct drm_device *dev, int state)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	if (!dev_priv->fbdev)
+		return;
+
+	fb_set_suspend(dev_priv->fbdev->helper.fbdev, state);
+}
+
 MODULE_LICENSE("GPL and additional rights");
 
 void intel_fb_output_poll_changed(struct drm_device *dev)
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_lvds.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_lvds.c	2012-04-13 12:42:02.000000000 -0400
@@ -739,6 +739,14 @@
 			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "MSI Wind Box DC500",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_sprite.c linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_sprite.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/i915/intel_sprite.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/i915/intel_sprite.c	2012-04-13 12:42:02.000000000 -0400
@@ -411,6 +411,9 @@
 
 	old_obj = intel_plane->obj;
 
+	src_w = src_w >> 16;
+	src_h = src_h >> 16;
+
 	/* Pipe must be running... */
 	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
 		return -EINVAL;
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2012-04-13 12:42:02.000000000 -0400
@@ -550,8 +550,8 @@
 		if (encoder->crtc == crtc) {
 			radeon_encoder = to_radeon_encoder(encoder);
 			connector = radeon_get_connector_for_encoder(encoder);
-			if (connector && connector->display_info.bpc)
-				bpc = connector->display_info.bpc;
+			/* if (connector && connector->display_info.bpc)
+				bpc = connector->display_info.bpc; */
 			encoder_mode = atombios_get_encoder_mode(encoder);
 			is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
 			if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
@@ -922,7 +922,9 @@
 		struct radeon_connector_atom_dig *dig_connector =
 			radeon_connector->con_priv;
 		int dp_clock;
-		bpc = connector->display_info.bpc;
+
+		/* if (connector->display_info.bpc)
+			bpc = connector->display_info.bpc; */
 
 		switch (encoder_mode) {
 		case ATOM_ENCODER_MODE_DP_MST:
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_dp.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_dp.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2012-04-13 12:42:02.000000000 -0400
@@ -405,10 +405,13 @@
 /* get bpc from the EDID */
 static int convert_bpc_to_bpp(int bpc)
 {
+#if 0
 	if (bpc == 0)
 		return 24;
 	else
 		return bpc * 3;
+#endif
+	return 24;
 }
 
 /* get the max pix clock supported by the link rate and lane num */
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2012-04-13 12:42:02.000000000 -0400
@@ -537,7 +537,7 @@
 		dp_clock = dig_connector->dp_clock;
 		dp_lane_count = dig_connector->dp_lane_count;
 		hpd_id = radeon_connector->hpd.hpd;
-		bpc = connector->display_info.bpc;
+		/* bpc = connector->display_info.bpc; */
 	}
 
 	/* no dig encoder assigned */
@@ -1098,7 +1098,7 @@
 		dp_lane_count = dig_connector->dp_lane_count;
 		connector_object_id =
 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-		bpc = connector->display_info.bpc;
+		/* bpc = connector->display_info.bpc; */
 	}
 
 	memset(&args, 0, sizeof(args));
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atom.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atom.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atom.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atom.c	2012-04-13 12:42:02.000000000 -0400
@@ -1306,8 +1306,11 @@
 
 int atom_asic_init(struct atom_context *ctx)
 {
+	struct radeon_device *rdev = ctx->card->dev->dev_private;
 	int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
 	uint32_t ps[16];
+	int ret;
+
 	memset(ps, 0, 64);
 
 	ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
@@ -1317,7 +1320,17 @@
 
 	if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
 		return 1;
-	return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+	ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+	if (ret)
+		return ret;
+
+	memset(ps, 0, 64);
+
+	if (rdev->family < CHIP_R600) {
+		if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
+			atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
+	}
+	return ret;
 }
 
 void atom_destroy(struct atom_context *ctx)
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atom.h linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atom.h
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/atom.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/atom.h	2012-04-13 12:42:02.000000000 -0400
@@ -44,6 +44,7 @@
 #define ATOM_CMD_SETSCLK	0x0A
 #define ATOM_CMD_SETMCLK	0x0B
 #define ATOM_CMD_SETPCLK	0x0C
+#define ATOM_CMD_SPDFANCNTL	0x39
 
 #define ATOM_DATA_FWI_PTR	0xC
 #define ATOM_DATA_IIO_PTR	0x32
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2012-04-13 12:42:02.000000000 -0400
@@ -442,6 +442,20 @@
 		struct radeon_device *rdev = dev->dev_private;
 		*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
 	}
+
+	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
+	if ((dev->pdev->device == 0x9802) &&
+	    (dev->pdev->subsystem_vendor == 0x1734) &&
+	    (dev->pdev->subsystem_device == 0x11bd)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
+			*connector_type = DRM_MODE_CONNECTOR_DVII;
+			*line_mux = 0x3103;
+		} else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
+			*connector_type = DRM_MODE_CONNECTOR_DVII;
+		}
+	}
+
+
 	return true;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2012-04-13 12:42:02.000000000 -0400
@@ -946,6 +946,10 @@
 
 			encoder = obj_to_encoder(obj);
 
+			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
+			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
+				continue;
+
 			encoder_funcs = encoder->helper_private;
 			if (encoder_funcs->detect) {
 				if (ret != connector_status_connected) {
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_cursor.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_cursor.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2012-04-13 12:42:02.000000000 -0400
@@ -151,7 +151,9 @@
 			   uint32_t height)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
 	struct drm_gem_object *obj;
+	struct radeon_bo *robj;
 	uint64_t gpu_addr;
 	int ret;
 
@@ -173,7 +175,15 @@
 		return -ENOENT;
 	}
 
-	ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	robj = gem_to_radeon_bo(obj);
+	ret = radeon_bo_reserve(robj, false);
+	if (unlikely(ret != 0))
+		goto fail;
+	/* Only 27 bit offset for legacy cursor */
+	ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
+				       ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
+				       &gpu_addr);
+	radeon_bo_unreserve(robj);
 	if (ret)
 		goto fail;
 
@@ -181,7 +191,6 @@
 	radeon_crtc->cursor_height = height;
 
 	radeon_lock_cursor(crtc, true);
-	/* XXX only 27 bit offset for legacy cursor */
 	radeon_set_cursor(crtc, obj, gpu_addr);
 	radeon_show_cursor(crtc);
 	radeon_lock_cursor(crtc, false);
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_object.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_object.c	2012-04-13 12:42:02.000000000 -0400
@@ -224,7 +224,8 @@
 		*bo = NULL;
 }
 
-int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
+			     u64 *gpu_addr)
 {
 	int r, i;
 
@@ -232,6 +233,7 @@
 		bo->pin_count++;
 		if (gpu_addr)
 			*gpu_addr = radeon_bo_gpu_offset(bo);
+		WARN_ON_ONCE(max_offset != 0);
 		return 0;
 	}
 	radeon_ttm_placement_from_domain(bo, domain);
@@ -239,6 +241,15 @@
 		/* force to pin into visible video ram */
 		bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
 	}
+	if (max_offset) {
+		u64 lpfn = max_offset >> PAGE_SHIFT;
+
+		if (!bo->placement.lpfn)
+			bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
+
+		if (lpfn < bo->placement.lpfn)
+			bo->placement.lpfn = lpfn;
+	}
 	for (i = 0; i < bo->placement.num_placement; i++)
 		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
@@ -252,6 +263,11 @@
 	return r;
 }
 
+int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+{
+	return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
+}
+
 int radeon_bo_unpin(struct radeon_bo *bo)
 {
 	int r, i;
diff -druN linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-3.3-gnu/drivers/gpu/drm/radeon/radeon_object.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/gpu/drm/radeon/radeon_object.h	2012-04-13 12:42:02.000000000 -0400
@@ -118,6 +118,8 @@
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
 extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
+extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
+				    u64 max_offset, u64 *gpu_addr);
 extern int radeon_bo_unpin(struct radeon_bo *bo);
 extern int radeon_bo_evict_vram(struct radeon_device *rdev);
 extern void radeon_bo_force_delete(struct radeon_device *rdev);
diff -druN linux-libre-3.3-gnu/drivers/hid/hid-chicony.c linux-libre-3.3.2-gnu/drivers/hid/hid-chicony.c
--- linux-libre-3.3-gnu/drivers/hid/hid-chicony.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/hid/hid-chicony.c	2012-04-13 12:42:02.000000000 -0400
@@ -45,6 +45,12 @@
 	case 0xff09: ch_map_key_clear(BTN_9);	break;
 	case 0xff0a: ch_map_key_clear(BTN_A);	break;
 	case 0xff0b: ch_map_key_clear(BTN_B);	break;
+	case 0x00f1: ch_map_key_clear(KEY_WLAN);	break;
+	case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
+	case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP);	break;
+	case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF);	break;
+	case 0x00f7: ch_map_key_clear(KEY_CAMERA);	break;
+	case 0x00f8: ch_map_key_clear(KEY_PROG1);	break;
 	default:
 		return 0;
 	}
@@ -53,6 +59,7 @@
 
 static const struct hid_device_id ch_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ch_devices);
diff -druN linux-libre-3.3-gnu/drivers/hid/hid-core.c linux-libre-3.3.2-gnu/drivers/hid/hid-core.c
--- linux-libre-3.3-gnu/drivers/hid/hid-core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/hid/hid-core.c	2012-04-13 12:42:02.000000000 -0400
@@ -1396,6 +1396,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
diff -druN linux-libre-3.3-gnu/drivers/hid/hid-ids.h linux-libre-3.3.2-gnu/drivers/hid/hid-ids.h
--- linux-libre-3.3-gnu/drivers/hid/hid-ids.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/hid/hid-ids.h	2012-04-13 12:42:02.000000000 -0400
@@ -193,6 +193,7 @@
 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD	0x0418
 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH	0xb19d
 #define USB_DEVICE_ID_CHICONY_WIRELESS	0x0618
+#define USB_DEVICE_ID_CHICONY_WIRELESS2	0x1123
 
 #define USB_VENDOR_ID_CHUNGHWAT		0x2247
 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH	0x0001
diff -druN linux-libre-3.3-gnu/drivers/hwmon/fam15h_power.c linux-libre-3.3.2-gnu/drivers/hwmon/fam15h_power.c
--- linux-libre-3.3-gnu/drivers/hwmon/fam15h_power.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/hwmon/fam15h_power.c	2012-04-13 12:42:02.000000000 -0400
@@ -60,7 +60,7 @@
 	pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
 				  REG_TDP_RUNNING_AVERAGE, &val);
 	running_avg_capture = (val >> 4) & 0x3fffff;
-	running_avg_capture = sign_extend32(running_avg_capture, 22);
+	running_avg_capture = sign_extend32(running_avg_capture, 21);
 	running_avg_range = val & 0xf;
 
 	pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
diff -druN linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2012-04-13 12:42:02.000000000 -0400
@@ -364,6 +364,9 @@
 	}
 	ib_conn = ep->dd_data;
 
+	if (iser_alloc_rx_descriptors(ib_conn))
+		return -ENOMEM;
+
 	/* binds the iSER connection retrieved from the previously
 	 * connected ep_handle to the iSCSI layer connection. exchanges
 	 * connection pointers */
@@ -398,19 +401,6 @@
 	iser_conn->ib_conn = NULL;
 }
 
-static int
-iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	int err;
-
-	err = iser_conn_set_full_featured_mode(conn);
-	if (err)
-		return err;
-
-	return iscsi_conn_start(cls_conn);
-}
-
 static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
 {
 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
@@ -724,7 +714,7 @@
 	.get_conn_param		= iscsi_conn_get_param,
 	.get_ep_param		= iscsi_iser_get_ep_param,
 	.get_session_param	= iscsi_session_get_param,
-	.start_conn             = iscsi_iser_conn_start,
+	.start_conn             = iscsi_conn_start,
 	.stop_conn              = iscsi_iser_conn_stop,
 	/* iscsi host params */
 	.get_host_param		= iscsi_host_get_param,
diff -druN linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2012-04-13 12:42:02.000000000 -0400
@@ -366,4 +366,5 @@
 void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
 int  iser_initialize_task_headers(struct iscsi_task *task,
 			struct iser_tx_desc *tx_desc);
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn);
 #endif
diff -druN linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iser_initiator.c linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iser_initiator.c
--- linux-libre-3.3-gnu/drivers/infiniband/ulp/iser/iser_initiator.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/infiniband/ulp/iser/iser_initiator.c	2012-04-13 12:42:02.000000000 -0400
@@ -170,7 +170,7 @@
 }
 
 
-static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
 {
 	int i, j;
 	u64 dma_addr;
@@ -242,23 +242,24 @@
 	kfree(ib_conn->rx_descs);
 }
 
-/**
- *  iser_conn_set_full_featured_mode - (iSER API)
- */
-int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 
-	iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
-
-	/* Check that there is no posted recv or send buffers left - */
-	/* they must be consumed during the login phase */
-	BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
-	BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+	iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
+	/* check if this is the last login - going to full feature phase */
+	if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE)
+		return 0;
 
-	if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
-		return -ENOMEM;
+	/*
+	 * Check that there is one posted recv buffer (for the last login
+	 * response) and no posted send buffers left - they must have been
+	 * consumed during previous login phases.
+	 */
+	WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1);
+	WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
 
+	iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
 	/* Initial post receive buffers */
 	if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
 		return -ENOMEM;
@@ -438,6 +439,9 @@
 		err = iser_post_recvl(iser_conn->ib_conn);
 		if (err)
 			goto send_control_error;
+		err = iser_post_rx_bufs(conn, task->hdr);
+		if (err)
+			goto send_control_error;
 	}
 
 	err = iser_post_send(iser_conn->ib_conn, mdesc);
diff -druN linux-libre-3.3-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c linux-libre-3.3.2-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c
--- linux-libre-3.3-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2012-04-13 12:42:02.000000000 -0400
@@ -1750,6 +1750,7 @@
 		       srp_cmd->tag);
 		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
 		goto send_sense;
 	}
 
@@ -1757,15 +1758,19 @@
 	cmd->data_direction = dir;
 	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
 				       sizeof(srp_cmd->lun));
-	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0)
+	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) {
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
 		goto send_sense;
+	}
 	ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);
-	if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
-		srpt_queue_status(cmd);
-	else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)
-		goto send_sense;
-	else
-		WARN_ON_ONCE(ret);
+	if (ret < 0) {
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
+		if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) {
+			srpt_queue_status(cmd);
+			return 0;
+		} else
+			goto send_sense;
+	}
 
 	transport_handle_cdb_direct(cmd);
 	return 0;
diff -druN linux-libre-3.3-gnu/drivers/iommu/amd_iommu.c linux-libre-3.3.2-gnu/drivers/iommu/amd_iommu.c
--- linux-libre-3.3-gnu/drivers/iommu/amd_iommu.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/iommu/amd_iommu.c	2012-04-13 12:42:02.000000000 -0400
@@ -2804,7 +2804,7 @@
  * we don't need to preallocate the protection domains anymore.
  * For now we have to.
  */
-static void prealloc_protection_domains(void)
+static void __init prealloc_protection_domains(void)
 {
 	struct iommu_dev_data *dev_data;
 	struct dma_ops_domain *dma_dom;
diff -druN linux-libre-3.3-gnu/drivers/iommu/amd_iommu_init.c linux-libre-3.3.2-gnu/drivers/iommu/amd_iommu_init.c
--- linux-libre-3.3-gnu/drivers/iommu/amd_iommu_init.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/iommu/amd_iommu_init.c	2012-04-13 12:42:02.000000000 -0400
@@ -1131,8 +1131,9 @@
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1142,27 +1143,36 @@
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
-
-	if (iommu->ppr_log != NULL)
-		iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	if (iommu->ppr_log != NULL)
+		iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
diff -druN linux-libre-3.3-gnu/drivers/md/bitmap.c linux-libre-3.3.2-gnu/drivers/md/bitmap.c
--- linux-libre-3.3-gnu/drivers/md/bitmap.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/bitmap.c	2012-04-13 12:42:02.000000000 -0400
@@ -1904,6 +1904,8 @@
 			if (mddev->pers) {
 				mddev->pers->quiesce(mddev, 1);
 				rv = bitmap_create(mddev);
+				if (!rv)
+					rv = bitmap_load(mddev);
 				if (rv) {
 					bitmap_destroy(mddev);
 					mddev->bitmap_info.offset = 0;
diff -druN linux-libre-3.3-gnu/drivers/md/dm-crypt.c linux-libre-3.3.2-gnu/drivers/md/dm-crypt.c
--- linux-libre-3.3-gnu/drivers/md/dm-crypt.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/dm-crypt.c	2012-04-13 12:42:02.000000000 -0400
@@ -176,7 +176,6 @@
 
 #define MIN_IOS        16
 #define MIN_POOL_PAGES 32
-#define MIN_BIO_PAGES  8
 
 static struct kmem_cache *_crypt_io_pool;
 
@@ -848,12 +847,11 @@
 		}
 
 		/*
-		 * if additional pages cannot be allocated without waiting,
-		 * return a partially allocated bio, the caller will then try
-		 * to allocate additional bios while submitting this partial bio
+		 * If additional pages cannot be allocated without waiting,
+		 * return a partially-allocated bio.  The caller will then try
+		 * to allocate more bios while submitting this partial bio.
 		 */
-		if (i == (MIN_BIO_PAGES - 1))
-			gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+		gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
 
 		len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
 
@@ -1046,16 +1044,14 @@
 	queue_work(cc->io_queue, &io->work);
 }
 
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
-					  int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
 {
 	struct bio *clone = io->ctx.bio_out;
 	struct crypt_config *cc = io->target->private;
 
-	if (unlikely(error < 0)) {
+	if (unlikely(io->error < 0)) {
 		crypt_free_buffer_pages(cc, clone);
 		bio_put(clone);
-		io->error = -EIO;
 		crypt_dec_pending(io);
 		return;
 	}
@@ -1106,12 +1102,16 @@
 		sector += bio_sectors(clone);
 
 		crypt_inc_pending(io);
+
 		r = crypt_convert(cc, &io->ctx);
+		if (r < 0)
+			io->error = -EIO;
+
 		crypt_finished = atomic_dec_and_test(&io->ctx.pending);
 
 		/* Encryption was already finished, submit io now */
 		if (crypt_finished) {
-			kcryptd_crypt_write_io_submit(io, r, 0);
+			kcryptd_crypt_write_io_submit(io, 0);
 
 			/*
 			 * If there was an error, do not try next fragments.
@@ -1162,11 +1162,8 @@
 	crypt_dec_pending(io);
 }
 
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
 {
-	if (unlikely(error < 0))
-		io->error = -EIO;
-
 	crypt_dec_pending(io);
 }
 
@@ -1181,9 +1178,11 @@
 			   io->sector);
 
 	r = crypt_convert(cc, &io->ctx);
+	if (r < 0)
+		io->error = -EIO;
 
 	if (atomic_dec_and_test(&io->ctx.pending))
-		kcryptd_crypt_read_done(io, r);
+		kcryptd_crypt_read_done(io);
 
 	crypt_dec_pending(io);
 }
@@ -1204,15 +1203,18 @@
 	if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
 		error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
 
+	if (error < 0)
+		io->error = -EIO;
+
 	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
 	if (!atomic_dec_and_test(&ctx->pending))
 		return;
 
 	if (bio_data_dir(io->base_bio) == READ)
-		kcryptd_crypt_read_done(io, error);
+		kcryptd_crypt_read_done(io);
 	else
-		kcryptd_crypt_write_io_submit(io, error, 1);
+		kcryptd_crypt_write_io_submit(io, 1);
 }
 
 static void kcryptd_crypt(struct work_struct *work)
diff -druN linux-libre-3.3-gnu/drivers/md/dm-exception-store.c linux-libre-3.3.2-gnu/drivers/md/dm-exception-store.c
--- linux-libre-3.3-gnu/drivers/md/dm-exception-store.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/dm-exception-store.c	2012-04-13 12:42:02.000000000 -0400
@@ -283,7 +283,7 @@
 	return 0;
 
 persistent_fail:
-	dm_persistent_snapshot_exit();
+	dm_transient_snapshot_exit();
 transient_fail:
 	return r;
 }
diff -druN linux-libre-3.3-gnu/drivers/md/dm-thin.c linux-libre-3.3.2-gnu/drivers/md/dm-thin.c
--- linux-libre-3.3-gnu/drivers/md/dm-thin.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/dm-thin.c	2012-04-13 12:42:02.000000000 -0400
@@ -124,7 +124,7 @@
 	struct hlist_node list;
 	struct bio_prison *prison;
 	struct cell_key key;
-	unsigned count;
+	struct bio *holder;
 	struct bio_list bios;
 };
 
@@ -220,54 +220,59 @@
  * This may block if a new cell needs allocating.  You must ensure that
  * cells will be unlocked even if the calling thread is blocked.
  *
- * Returns the number of entries in the cell prior to the new addition
- * or < 0 on failure.
+ * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
  */
 static int bio_detain(struct bio_prison *prison, struct cell_key *key,
 		      struct bio *inmate, struct cell **ref)
 {
-	int r;
+	int r = 1;
 	unsigned long flags;
 	uint32_t hash = hash_key(prison, key);
-	struct cell *uninitialized_var(cell), *cell2 = NULL;
+	struct cell *cell, *cell2;
 
 	BUG_ON(hash > prison->nr_buckets);
 
 	spin_lock_irqsave(&prison->lock, flags);
+
 	cell = __search_bucket(prison->cells + hash, key);
+	if (cell) {
+		bio_list_add(&cell->bios, inmate);
+		goto out;
+	}
 
-	if (!cell) {
-		/*
-		 * Allocate a new cell
-		 */
-		spin_unlock_irqrestore(&prison->lock, flags);
-		cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
-		spin_lock_irqsave(&prison->lock, flags);
+	/*
+	 * Allocate a new cell
+	 */
+	spin_unlock_irqrestore(&prison->lock, flags);
+	cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+	spin_lock_irqsave(&prison->lock, flags);
 
-		/*
-		 * We've been unlocked, so we have to double check that
-		 * nobody else has inserted this cell in the meantime.
-		 */
-		cell = __search_bucket(prison->cells + hash, key);
+	/*
+	 * We've been unlocked, so we have to double check that
+	 * nobody else has inserted this cell in the meantime.
+	 */
+	cell = __search_bucket(prison->cells + hash, key);
+	if (cell) {
+		mempool_free(cell2, prison->cell_pool);
+		bio_list_add(&cell->bios, inmate);
+		goto out;
+	}
 
-		if (!cell) {
-			cell = cell2;
-			cell2 = NULL;
+	/*
+	 * Use new cell.
+	 */
+	cell = cell2;
 
-			cell->prison = prison;
-			memcpy(&cell->key, key, sizeof(cell->key));
-			cell->count = 0;
-			bio_list_init(&cell->bios);
-			hlist_add_head(&cell->list, prison->cells + hash);
-		}
-	}
+	cell->prison = prison;
+	memcpy(&cell->key, key, sizeof(cell->key));
+	cell->holder = inmate;
+	bio_list_init(&cell->bios);
+	hlist_add_head(&cell->list, prison->cells + hash);
 
-	r = cell->count++;
-	bio_list_add(&cell->bios, inmate);
-	spin_unlock_irqrestore(&prison->lock, flags);
+	r = 0;
 
-	if (cell2)
-		mempool_free(cell2, prison->cell_pool);
+out:
+	spin_unlock_irqrestore(&prison->lock, flags);
 
 	*ref = cell;
 
@@ -283,8 +288,8 @@
 
 	hlist_del(&cell->list);
 
-	if (inmates)
-		bio_list_merge(inmates, &cell->bios);
+	bio_list_add(inmates, cell->holder);
+	bio_list_merge(inmates, &cell->bios);
 
 	mempool_free(cell, prison->cell_pool);
 }
@@ -305,22 +310,44 @@
  * bio may be in the cell.  This function releases the cell, and also does
  * a sanity check.
  */
+static void __cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+	hlist_del(&cell->list);
+	BUG_ON(cell->holder != bio);
+	BUG_ON(!bio_list_empty(&cell->bios));
+}
+
 static void cell_release_singleton(struct cell *cell, struct bio *bio)
 {
-	struct bio_prison *prison = cell->prison;
-	struct bio_list bios;
-	struct bio *b;
 	unsigned long flags;
-
-	bio_list_init(&bios);
+	struct bio_prison *prison = cell->prison;
 
 	spin_lock_irqsave(&prison->lock, flags);
-	__cell_release(cell, &bios);
+	__cell_release_singleton(cell, bio);
 	spin_unlock_irqrestore(&prison->lock, flags);
+}
 
-	b = bio_list_pop(&bios);
-	BUG_ON(b != bio);
-	BUG_ON(!bio_list_empty(&bios));
+/*
+ * Sometimes we don't want the holder, just the additional bios.
+ */
+static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+	struct bio_prison *prison = cell->prison;
+
+	hlist_del(&cell->list);
+	bio_list_merge(inmates, &cell->bios);
+
+	mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+	unsigned long flags;
+	struct bio_prison *prison = cell->prison;
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release_no_holder(cell, inmates);
+	spin_unlock_irqrestore(&prison->lock, flags);
 }
 
 static void cell_error(struct cell *cell)
@@ -800,21 +827,16 @@
  * Same as cell_defer above, except it omits one particular detainee,
  * a write bio that covers the block and has already been processed.
  */
-static void cell_defer_except(struct thin_c *tc, struct cell *cell,
-			      struct bio *exception)
+static void cell_defer_except(struct thin_c *tc, struct cell *cell)
 {
 	struct bio_list bios;
-	struct bio *bio;
 	struct pool *pool = tc->pool;
 	unsigned long flags;
 
 	bio_list_init(&bios);
-	cell_release(cell, &bios);
 
 	spin_lock_irqsave(&pool->lock, flags);
-	while ((bio = bio_list_pop(&bios)))
-		if (bio != exception)
-			bio_list_add(&pool->deferred_bios, bio);
+	cell_release_no_holder(cell, &pool->deferred_bios);
 	spin_unlock_irqrestore(&pool->lock, flags);
 
 	wake_worker(pool);
@@ -854,7 +876,7 @@
 	 * the bios in the cell.
 	 */
 	if (bio) {
-		cell_defer_except(tc, m->cell, bio);
+		cell_defer_except(tc, m->cell);
 		bio_endio(bio, 0);
 	} else
 		cell_defer(tc, m->cell, m->data_block);
diff -druN linux-libre-3.3-gnu/drivers/md/md.c linux-libre-3.3.2-gnu/drivers/md/md.c
--- linux-libre-3.3-gnu/drivers/md/md.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/md.c	2012-04-13 12:42:02.000000000 -0400
@@ -1805,13 +1805,13 @@
 						| BB_LEN(internal_bb));
 				*bbp++ = cpu_to_le64(store_bb);
 			}
+			bb->changed = 0;
 			if (read_seqretry(&bb->lock, seq))
 				goto retry;
 
 			bb->sector = (rdev->sb_start +
 				      (int)le32_to_cpu(sb->bblog_offset));
 			bb->size = le16_to_cpu(sb->bblog_size);
-			bb->changed = 0;
 		}
 	}
 
@@ -2366,6 +2366,7 @@
 			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
 			list_for_each_entry(rdev, &mddev->disks, same_set) {
 				if (rdev->badblocks.changed) {
+					rdev->badblocks.changed = 0;
 					md_ack_all_badblocks(&rdev->badblocks);
 					md_error(mddev, rdev);
 				}
@@ -8157,30 +8158,23 @@
 	struct mddev *mddev;
 	int need_delay = 0;
 
-	if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
-
-		printk(KERN_INFO "md: stopping all md devices.\n");
-
-		for_each_mddev(mddev, tmp) {
-			if (mddev_trylock(mddev)) {
-				/* Force a switch to readonly even array
-				 * appears to still be in use.  Hence
-				 * the '100'.
-				 */
-				md_set_readonly(mddev, 100);
-				mddev_unlock(mddev);
-			}
-			need_delay = 1;
+	for_each_mddev(mddev, tmp) {
+		if (mddev_trylock(mddev)) {
+			__md_stop_writes(mddev);
+			mddev->safemode = 2;
+			mddev_unlock(mddev);
 		}
-		/*
-		 * certain more exotic SCSI devices are known to be
-		 * volatile wrt too early system reboots. While the
-		 * right place to handle this issue is the given
-		 * driver, we do want to have a safe RAID driver ...
-		 */
-		if (need_delay)
-			mdelay(1000*1);
+		need_delay = 1;
 	}
+	/*
+	 * certain more exotic SCSI devices are known to be
+	 * volatile wrt too early system reboots. While the
+	 * right place to handle this issue is the given
+	 * driver, we do want to have a safe RAID driver ...
+	 */
+	if (need_delay)
+		mdelay(1000*1);
+
 	return NOTIFY_DONE;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/md/persistent-data/dm-btree-remove.c linux-libre-3.3.2-gnu/drivers/md/persistent-data/dm-btree-remove.c
--- linux-libre-3.3-gnu/drivers/md/persistent-data/dm-btree-remove.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/persistent-data/dm-btree-remove.c	2012-04-13 12:42:02.000000000 -0400
@@ -128,18 +128,9 @@
 	n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned del_threshold(struct node *n)
-{
-	return le32_to_cpu(n->header.max_entries) / 3;
-}
-
 static unsigned merge_threshold(struct node *n)
 {
-	/*
-	 * The extra one is because we know we're potentially going to
-	 * delete an entry.
-	 */
-	return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+	return le32_to_cpu(n->header.max_entries) / 3;
 }
 
 struct child {
@@ -188,6 +179,15 @@
 
 static void shift(struct node *left, struct node *right, int count)
 {
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+	uint32_t r_max_entries = le32_to_cpu(right->header.max_entries);
+
+	BUG_ON(max_entries != r_max_entries);
+	BUG_ON(nr_left - count > max_entries);
+	BUG_ON(nr_right + count > max_entries);
+
 	if (!count)
 		return;
 
@@ -199,13 +199,8 @@
 		node_shift(right, count);
 	}
 
-	left->header.nr_entries =
-		cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
-	BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
-
-	right->header.nr_entries =
-		cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
-	BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+	left->header.nr_entries = cpu_to_le32(nr_left - count);
+	right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
 static void __rebalance2(struct dm_btree_info *info, struct node *parent,
@@ -215,8 +210,9 @@
 	struct node *right = r->n;
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+	unsigned threshold = 2 * merge_threshold(left) + 1;
 
-	if (nr_left + nr_right <= merge_threshold(left)) {
+	if (nr_left + nr_right < threshold) {
 		/*
 		 * Merge
 		 */
@@ -234,9 +230,6 @@
 		 * Rebalance.
 		 */
 		unsigned target_left = (nr_left + nr_right) / 2;
-		unsigned shift_ = nr_left - target_left;
-		BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
-		BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
 		shift(left, right, nr_left - target_left);
 		*key_ptr(parent, r->index) = right->keys[0];
 	}
@@ -272,74 +265,108 @@
 	return exit_child(info, &right);
 }
 
-static void __rebalance3(struct dm_btree_info *info, struct node *parent,
-			 struct child *l, struct child *c, struct child *r)
+/*
+ * We dump as many entries from center as possible into left, then the rest
+ * in right, then rebalance2.  This wastes some cpu, but I want something
+ * simple atm.
+ */
+static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+			       struct child *l, struct child *c, struct child *r,
+			       struct node *left, struct node *center, struct node *right,
+			       uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
-	struct node *left = l->n;
-	struct node *center = c->n;
-	struct node *right = r->n;
-
-	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
-	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
-	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
 	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+	unsigned shift = min(max_entries - nr_left, nr_center);
 
-	unsigned target;
+	BUG_ON(nr_left + shift > max_entries);
+	node_copy(left, center, -shift);
+	left->header.nr_entries = cpu_to_le32(nr_left + shift);
 
-	BUG_ON(left->header.max_entries != center->header.max_entries);
-	BUG_ON(center->header.max_entries != right->header.max_entries);
+	if (shift != nr_center) {
+		shift = nr_center - shift;
+		BUG_ON((nr_right + shift) > max_entries);
+		node_shift(right, shift);
+		node_copy(center, right, shift);
+		right->header.nr_entries = cpu_to_le32(nr_right + shift);
+	}
+	*key_ptr(parent, r->index) = right->keys[0];
 
-	if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
-		/*
-		 * Delete center node:
-		 *
-		 * We dump as many entries from center as possible into
-		 * left, then the rest in right, then rebalance2.  This
-		 * wastes some cpu, but I want something simple atm.
-		 */
-		unsigned shift = min(max_entries - nr_left, nr_center);
+	delete_at(parent, c->index);
+	r->index--;
 
-		BUG_ON(nr_left + shift > max_entries);
-		node_copy(left, center, -shift);
-		left->header.nr_entries = cpu_to_le32(nr_left + shift);
+	dm_tm_dec(info->tm, dm_block_location(c->block));
+	__rebalance2(info, parent, l, r);
+}
 
-		if (shift != nr_center) {
-			shift = nr_center - shift;
-			BUG_ON((nr_right + shift) >= max_entries);
-			node_shift(right, shift);
-			node_copy(center, right, shift);
-			right->header.nr_entries = cpu_to_le32(nr_right + shift);
-		}
-		*key_ptr(parent, r->index) = right->keys[0];
+/*
+ * Redistributes entries among 3 sibling nodes.
+ */
+static void redistribute3(struct dm_btree_info *info, struct node *parent,
+			  struct child *l, struct child *c, struct child *r,
+			  struct node *left, struct node *center, struct node *right,
+			  uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
+{
+	int s;
+	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+	unsigned target = (nr_left + nr_center + nr_right) / 3;
+	BUG_ON(target > max_entries);
 
-		delete_at(parent, c->index);
-		r->index--;
+	if (nr_left < nr_right) {
+		s = nr_left - target;
 
-		dm_tm_dec(info->tm, dm_block_location(c->block));
-		__rebalance2(info, parent, l, r);
+		if (s < 0 && nr_center < -s) {
+			/* not enough in central node */
+			shift(left, center, nr_center);
+			s = nr_center - target;
+			shift(left, right, s);
+			nr_right += s;
+		} else
+			shift(left, center, s);
 
-		return;
-	}
+		shift(center, right, target - nr_right);
 
-	/*
-	 * Rebalance
-	 */
-	target = (nr_left + nr_center + nr_right) / 3;
-	BUG_ON(target > max_entries);
+	} else {
+		s = target - nr_right;
+		if (s > 0 && nr_center < s) {
+			/* not enough in central node */
+			shift(center, right, nr_center);
+			s = target - nr_center;
+			shift(left, right, s);
+			nr_left -= s;
+		} else
+			shift(center, right, s);
 
-	/*
-	 * Adjust the left node
-	 */
-	shift(left, center, nr_left - target);
+		shift(left, center, nr_left - target);
+	}
 
-	/*
-	 * Adjust the right node
-	 */
-	shift(center, right, target - nr_right);
 	*key_ptr(parent, c->index) = center->keys[0];
 	*key_ptr(parent, r->index) = right->keys[0];
 }
 
+static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *c, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *center = c->n;
+	struct node *right = r->n;
+
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+
+	unsigned threshold = merge_threshold(left) * 4 + 1;
+
+	BUG_ON(left->header.max_entries != center->header.max_entries);
+	BUG_ON(center->header.max_entries != right->header.max_entries);
+
+	if ((nr_left + nr_center + nr_right) < threshold)
+		delete_center_node(info, parent, l, c, r, left, center, right,
+				   nr_left, nr_center, nr_right);
+	else
+		redistribute3(info, parent, l, c, r, left, center, right,
+			      nr_left, nr_center, nr_right);
+}
+
 static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
 		      unsigned left_index)
 {
@@ -441,9 +468,6 @@
 	if (r)
 		return r;
 
-	if (child_entries > del_threshold(n))
-		return 0;
-
 	has_left_sibling = i > 0;
 	has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
 
diff -druN linux-libre-3.3-gnu/drivers/md/raid10.c linux-libre-3.3.2-gnu/drivers/md/raid10.c
--- linux-libre-3.3-gnu/drivers/md/raid10.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/raid10.c	2012-04-13 12:42:02.000000000 -0400
@@ -863,9 +863,22 @@
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
 		conf->nr_waiting++;
-		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+		/* Wait for the barrier to drop.
+		 * However if there are already pending
+		 * requests (preventing the barrier from
+		 * rising completely), and the
+		 * pre-process bio queue isn't empty,
+		 * then don't wait, as we need to empty
+		 * that queue to get the nr_pending
+		 * count down.
+		 */
+		wait_event_lock_irq(conf->wait_barrier,
+				    !conf->barrier ||
+				    (conf->nr_pending &&
+				     current->bio_list &&
+				     !bio_list_empty(current->bio_list)),
 				    conf->resync_lock,
-				    );
+			);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
diff -druN linux-libre-3.3-gnu/drivers/md/raid1.c linux-libre-3.3.2-gnu/drivers/md/raid1.c
--- linux-libre-3.3-gnu/drivers/md/raid1.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/md/raid1.c	2012-04-13 12:42:02.000000000 -0400
@@ -737,9 +737,22 @@
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
 		conf->nr_waiting++;
-		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+		/* Wait for the barrier to drop.
+		 * However if there are already pending
+		 * requests (preventing the barrier from
+		 * rising completely), and the
+		 * pre-process bio queue isn't empty,
+		 * then don't wait, as we need to empty
+		 * that queue to get the nr_pending
+		 * count down.
+		 */
+		wait_event_lock_irq(conf->wait_barrier,
+				    !conf->barrier ||
+				    (conf->nr_pending &&
+				     current->bio_list &&
+				     !bio_list_empty(current->bio_list)),
 				    conf->resync_lock,
-				    );
+			);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
diff -druN linux-libre-3.3-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-3.3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-3.3-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2012-04-13 12:42:02.000000000 -0400
@@ -143,6 +143,8 @@
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 static int dtv_get_frontend(struct dvb_frontend *fe,
 			    struct dvb_frontend_parameters *p_out);
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *p);
 
 static bool has_get_frontend(struct dvb_frontend *fe)
 {
@@ -655,6 +657,8 @@
 					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
 					re_tune = true;
 					fepriv->state = FESTATE_TUNED;
+				} else {
+					re_tune = false;
 				}
 
 				if (fe->ops.tune)
@@ -695,6 +699,7 @@
 					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
 					fepriv->delay = HZ / 2;
 				}
+				dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
 				fe->ops.read_status(fe, &s);
 				if (s != fepriv->status) {
 					dvb_frontend_add_event(fe, s); /* update event list */
@@ -1831,6 +1836,13 @@
 		return -EINVAL;
 
 	/*
+	 * Initialize output parameters to match the values given by
+	 * the user. FE_SET_FRONTEND triggers an initial frontend event
+	 * with status = 0, which copies output parameters to userspace.
+	 */
+	dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
+
+	/*
 	 * Be sure that the bandwidth will be filled for all
 	 * non-satellite systems, as tuners need to know what
 	 * low pass/Nyquist half filter should be applied, in
diff -druN linux-libre-3.3-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c linux-libre-3.3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c
--- linux-libre-3.3-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c	2012-04-13 12:42:02.000000000 -0400
@@ -351,15 +351,13 @@
 					      adap_state->ep6_clockphase,
 					      0, 0);
 		mxl_fail(ret);
+#if 0
 	} else {
 		ret = mxl111sf_disable_656_port(state);
 		mxl_fail(ret);
+#endif
 	}
 
-	mxl111sf_read_reg(state, 0x12, &tmp);
-	tmp &= ~0x04;
-	mxl111sf_write_reg(state, 0x12, tmp);
-
 	return ret;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/media/dvb/frontends/au8522_dig.c linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/au8522_dig.c
--- linux-libre-3.3-gnu/drivers/media/dvb/frontends/au8522_dig.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/au8522_dig.c	2012-04-13 12:42:02.000000000 -0400
@@ -588,11 +588,6 @@
 	    (state->current_modulation == c->modulation))
 		return 0;
 
-	au8522_enable_modulation(fe, c->modulation);
-
-	/* Allow the demod to settle */
-	msleep(100);
-
 	if (fe->ops.tuner_ops.set_params) {
 		if (fe->ops.i2c_gate_ctrl)
 			fe->ops.i2c_gate_ctrl(fe, 1);
@@ -604,6 +599,11 @@
 	if (ret < 0)
 		return ret;
 
+	/* Allow the tuner to settle */
+	msleep(100);
+
+	au8522_enable_modulation(fe, c->modulation);
+
 	state->current_frequency = c->frequency;
 
 	return 0;
diff -druN linux-libre-3.3-gnu/drivers/media/dvb/frontends/lgdt330x.c linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/lgdt330x.c
--- linux-libre-3.3-gnu/drivers/media/dvb/frontends/lgdt330x.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/lgdt330x.c	2012-04-13 12:42:02.000000000 -0400
@@ -104,8 +104,8 @@
  * then reads the data returned for (len) bytes.
  */
 
-static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
-			       enum I2C_REG reg, u8* buf, int len)
+static int i2c_read_demod_bytes(struct lgdt330x_state *state,
+				enum I2C_REG reg, u8 *buf, int len)
 {
 	u8 wr [] = { reg };
 	struct i2c_msg msg [] = {
@@ -118,6 +118,8 @@
 	ret = i2c_transfer(state->i2c, msg, 2);
 	if (ret != 2) {
 		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+		if (ret >= 0)
+			ret = -EIO;
 	} else {
 		ret = 0;
 	}
diff -druN linux-libre-3.3-gnu/drivers/media/dvb/frontends/tda10071.c linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/tda10071.c
--- linux-libre-3.3-gnu/drivers/media/dvb/frontends/tda10071.c	2012-03-19 01:13:42.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/dvb/frontends/tda10071.c	2012-04-13 22:57:37.000000000 -0400
@@ -1215,7 +1215,7 @@
 EXPORT_SYMBOL(tda10071_attach);
 
 static struct dvb_frontend_ops tda10071_ops = {
-	.delsys = { SYS_DVBT, SYS_DVBT2 },
+	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "NXP TDA10071",
 		.frequency_min = 950000,
diff -druN linux-libre-3.3-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c linux-libre-3.3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c
--- linux-libre-3.3-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-19 01:14:39.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-04-13 22:58:33.000000000 -0400
@@ -320,7 +320,17 @@
 	.probe_tuner = TDA829X_DONT_PROBE,
 };
 
+static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = {
+        .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
 static struct tda18271_config hauppauge_tda18271_dvb_config = {
+	.std_map = &hauppauge_tda18271_dvbt_std_map,
 	.gate    = TDA18271_GATE_ANALOG,
 	.output_opt = TDA18271_OUTPUT_LT_OFF,
 };
diff -druN linux-libre-3.3-gnu/drivers/media/video/uvc/uvc_video.c linux-libre-3.3.2-gnu/drivers/media/video/uvc/uvc_video.c
--- linux-libre-3.3-gnu/drivers/media/video/uvc/uvc_video.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/media/video/uvc/uvc_video.c	2012-04-13 12:42:02.000000000 -0400
@@ -468,22 +468,30 @@
 	spin_unlock_irqrestore(&stream->clock.lock, flags);
 }
 
-static int uvc_video_clock_init(struct uvc_streaming *stream)
+static void uvc_video_clock_reset(struct uvc_streaming *stream)
 {
 	struct uvc_clock *clock = &stream->clock;
 
-	spin_lock_init(&clock->lock);
 	clock->head = 0;
 	clock->count = 0;
-	clock->size = 32;
 	clock->last_sof = -1;
 	clock->sof_offset = -1;
+}
+
+static int uvc_video_clock_init(struct uvc_streaming *stream)
+{
+	struct uvc_clock *clock = &stream->clock;
+
+	spin_lock_init(&clock->lock);
+	clock->size = 32;
 
 	clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
 				 GFP_KERNEL);
 	if (clock->samples == NULL)
 		return -ENOMEM;
 
+	uvc_video_clock_reset(stream);
+
 	return 0;
 }
 
@@ -1424,8 +1432,6 @@
 
 	if (free_buffers)
 		uvc_free_urb_buffers(stream);
-
-	uvc_video_clock_cleanup(stream);
 }
 
 /*
@@ -1555,10 +1561,6 @@
 
 	uvc_video_stats_start(stream);
 
-	ret = uvc_video_clock_init(stream);
-	if (ret < 0)
-		return ret;
-
 	if (intf->num_altsetting > 1) {
 		struct usb_host_endpoint *best_ep = NULL;
 		unsigned int best_psize = 3 * 1024;
@@ -1683,6 +1685,8 @@
 
 	stream->frozen = 0;
 
+	uvc_video_clock_reset(stream);
+
 	ret = uvc_commit_video(stream, &stream->ctrl);
 	if (ret < 0) {
 		uvc_queue_enable(&stream->queue, 0);
@@ -1819,25 +1823,35 @@
 		uvc_uninit_video(stream, 1);
 		usb_set_interface(stream->dev->udev, stream->intfnum, 0);
 		uvc_queue_enable(&stream->queue, 0);
+		uvc_video_clock_cleanup(stream);
 		return 0;
 	}
 
-	ret = uvc_queue_enable(&stream->queue, 1);
+	ret = uvc_video_clock_init(stream);
 	if (ret < 0)
 		return ret;
 
+	ret = uvc_queue_enable(&stream->queue, 1);
+	if (ret < 0)
+		goto error_queue;
+
 	/* Commit the streaming parameters. */
 	ret = uvc_commit_video(stream, &stream->ctrl);
-	if (ret < 0) {
-		uvc_queue_enable(&stream->queue, 0);
-		return ret;
-	}
+	if (ret < 0)
+		goto error_commit;
 
 	ret = uvc_init_video(stream, GFP_KERNEL);
-	if (ret < 0) {
-		usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-		uvc_queue_enable(&stream->queue, 0);
-	}
+	if (ret < 0)
+		goto error_video;
+
+	return 0;
+
+error_video:
+	usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+error_commit:
+	uvc_queue_enable(&stream->queue, 0);
+error_queue:
+	uvc_video_clock_cleanup(stream);
 
 	return ret;
 }
diff -druN linux-libre-3.3-gnu/drivers/mfd/da9052-spi.c linux-libre-3.3.2-gnu/drivers/mfd/da9052-spi.c
--- linux-libre-3.3-gnu/drivers/mfd/da9052-spi.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mfd/da9052-spi.c	2012-04-13 12:42:02.000000000 -0400
@@ -21,7 +21,7 @@
 
 #include <linux/mfd/da9052/da9052.h>
 
-static int da9052_spi_probe(struct spi_device *spi)
+static int __devinit da9052_spi_probe(struct spi_device *spi)
 {
 	int ret;
 	const struct spi_device_id *id = spi_get_device_id(spi);
@@ -61,7 +61,7 @@
 	return ret;
 }
 
-static int da9052_spi_remove(struct spi_device *spi)
+static int __devexit da9052_spi_remove(struct spi_device *spi)
 {
 	struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
 
diff -druN linux-libre-3.3-gnu/drivers/mfd/twl6030-irq.c linux-libre-3.3.2-gnu/drivers/mfd/twl6030-irq.c
--- linux-libre-3.3-gnu/drivers/mfd/twl6030-irq.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mfd/twl6030-irq.c	2012-04-13 12:42:02.000000000 -0400
@@ -185,8 +185,17 @@
 			}
 		local_irq_enable();
 		}
-		ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
-				REG_INT_STS_A, 3); /* clear INT_STS_A */
+
+		/*
+		 * NOTE:
+		 * Simulation confirms that documentation is wrong w.r.t the
+		 * interrupt status clear operation. A single *byte* write to
+		 * any one of STS_A to STS_C register results in all three
+		 * STS registers being reset. Since it does not matter which
+		 * value is written, all three registers are cleared on a
+		 * single byte write, so we just use 0x0 to clear.
+		 */
+		ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
 		if (ret)
 			pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
diff -druN linux-libre-3.3-gnu/drivers/mfd/wm8994-core.c linux-libre-3.3.2-gnu/drivers/mfd/wm8994-core.c
--- linux-libre-3.3-gnu/drivers/mfd/wm8994-core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mfd/wm8994-core.c	2012-04-13 12:42:02.000000000 -0400
@@ -270,6 +270,20 @@
 		break;
 	}
 
+	switch (wm8994->type) {
+	case WM1811:
+		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
+		if (ret < 0) {
+			dev_err(dev, "Failed to read jackdet: %d\n", ret);
+		} else if (ret & WM1811_JACKDET_MODE_MASK) {
+			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+			return 0;
+		}
+		break;
+	default:
+		break;
+	}
+
 	/* Disable LDO pulldowns while the device is suspended if we
 	 * don't know that something will be driving them. */
 	if (!wm8994->ldo_ena_always_driven)
diff -druN linux-libre-3.3-gnu/drivers/misc/kgdbts.c linux-libre-3.3.2-gnu/drivers/misc/kgdbts.c
--- linux-libre-3.3-gnu/drivers/misc/kgdbts.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/misc/kgdbts.c	2012-04-13 12:42:02.000000000 -0400
@@ -134,12 +134,17 @@
 static int hwbreaks_ok;
 static int hw_break_val;
 static int hw_break_val2;
+static int cont_instead_of_sstep;
+static unsigned long cont_thread_id;
+static unsigned long sstep_thread_id;
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
 static int arch_needs_sstep_emulation = 1;
 #else
 static int arch_needs_sstep_emulation;
 #endif
+static unsigned long cont_addr;
 static unsigned long sstep_addr;
+static int restart_from_top_after_write;
 static int sstep_state;
 
 /* Storage for the registers, in GDB format. */
@@ -187,7 +192,8 @@
 	 */
 	while (!final_ack)
 		msleep_interruptible(1500);
-
+	/* Pause for any other threads to exit after final ack. */
+	msleep_interruptible(1000);
 	if (configured)
 		kgdb_unregister_io_module(&kgdbts_io_ops);
 	configured = 0;
@@ -211,7 +217,7 @@
 	if (!strcmp(arg, "kgdbts_break_test"))
 		addr = (unsigned long)kgdbts_break_test;
 	else if (!strcmp(arg, "sys_open"))
-		addr = (unsigned long)sys_open;
+		addr = (unsigned long)do_sys_open;
 	else if (!strcmp(arg, "do_fork"))
 		addr = (unsigned long)do_fork;
 	else if (!strcmp(arg, "hw_break_val"))
@@ -283,6 +289,16 @@
 	hw_break_val++;
 }
 
+static int get_thread_id_continue(char *put_str, char *arg)
+{
+	char *ptr = &put_str[11];
+
+	if (put_str[1] != 'T' || put_str[2] != '0')
+		return 1;
+	kgdb_hex2long(&ptr, &cont_thread_id);
+	return 0;
+}
+
 static int check_and_rewind_pc(char *put_str, char *arg)
 {
 	unsigned long addr = lookup_addr(arg);
@@ -299,13 +315,21 @@
 	if (addr + BREAK_INSTR_SIZE == ip)
 		offset = -BREAK_INSTR_SIZE;
 #endif
-	if (strcmp(arg, "silent") && ip + offset != addr) {
+
+	if (arch_needs_sstep_emulation && sstep_addr &&
+	    ip + offset == sstep_addr &&
+	    ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
+		/* This is special case for emulated single step */
+		v2printk("Emul: rewind hit single step bp\n");
+		restart_from_top_after_write = 1;
+	} else if (strcmp(arg, "silent") && ip + offset != addr) {
 		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
 			   ip + offset, addr);
 		return 1;
 	}
 	/* Readjust the instruction pointer if needed */
 	ip += offset;
+	cont_addr = ip;
 #ifdef GDB_ADJUSTS_BREAK_OFFSET
 	instruction_pointer_set(&kgdbts_regs, ip);
 #endif
@@ -315,6 +339,8 @@
 static int check_single_step(char *put_str, char *arg)
 {
 	unsigned long addr = lookup_addr(arg);
+	static int matched_id;
+
 	/*
 	 * From an arch indepent point of view the instruction pointer
 	 * should be on a different instruction
@@ -324,6 +350,29 @@
 	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
 	v2printk("Singlestep stopped at IP: %lx\n",
 		   instruction_pointer(&kgdbts_regs));
+
+	if (sstep_thread_id != cont_thread_id) {
+		/*
+		 * Ensure we stopped in the same thread id as before, else the
+		 * debugger should continue until the original thread that was
+		 * single stepped is scheduled again, emulating gdb's behavior.
+		 */
+		v2printk("ThrID does not match: %lx\n", cont_thread_id);
+		if (arch_needs_sstep_emulation) {
+			if (matched_id &&
+			    instruction_pointer(&kgdbts_regs) != addr)
+				goto continue_test;
+			matched_id++;
+			ts.idx -= 2;
+			sstep_state = 0;
+			return 0;
+		}
+		cont_instead_of_sstep = 1;
+		ts.idx -= 4;
+		return 0;
+	}
+continue_test:
+	matched_id = 0;
 	if (instruction_pointer(&kgdbts_regs) == addr) {
 		eprintk("kgdbts: SingleStep failed at %lx\n",
 			   instruction_pointer(&kgdbts_regs));
@@ -365,10 +414,40 @@
 	return 1;
 }
 
+static void get_cont_catch(char *arg)
+{
+	/* Always send detach because the test is completed at this point */
+	fill_get_buf("D");
+}
+
+static int put_cont_catch(char *put_str, char *arg)
+{
+	/* This is at the end of the test and we catch any and all input */
+	v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
+	ts.idx--;
+	return 0;
+}
+
+static int emul_reset(char *put_str, char *arg)
+{
+	if (strncmp(put_str, "$OK", 3))
+		return 1;
+	if (restart_from_top_after_write) {
+		restart_from_top_after_write = 0;
+		ts.idx = -1;
+	}
+	return 0;
+}
+
 static void emul_sstep_get(char *arg)
 {
 	if (!arch_needs_sstep_emulation) {
-		fill_get_buf(arg);
+		if (cont_instead_of_sstep) {
+			cont_instead_of_sstep = 0;
+			fill_get_buf("c");
+		} else {
+			fill_get_buf(arg);
+		}
 		return;
 	}
 	switch (sstep_state) {
@@ -398,9 +477,11 @@
 static int emul_sstep_put(char *put_str, char *arg)
 {
 	if (!arch_needs_sstep_emulation) {
-		if (!strncmp(put_str+1, arg, 2))
-			return 0;
-		return 1;
+		char *ptr = &put_str[11];
+		if (put_str[1] != 'T' || put_str[2] != '0')
+			return 1;
+		kgdb_hex2long(&ptr, &sstep_thread_id);
+		return 0;
 	}
 	switch (sstep_state) {
 	case 1:
@@ -411,8 +492,7 @@
 		v2printk("Stopped at IP: %lx\n",
 			 instruction_pointer(&kgdbts_regs));
 		/* Want to stop at IP + break instruction size by default */
-		sstep_addr = instruction_pointer(&kgdbts_regs) +
-			BREAK_INSTR_SIZE;
+		sstep_addr = cont_addr + BREAK_INSTR_SIZE;
 		break;
 	case 2:
 		if (strncmp(put_str, "$OK", 3)) {
@@ -424,6 +504,9 @@
 		if (strncmp(put_str, "$T0", 3)) {
 			eprintk("kgdbts: failed continue sstep\n");
 			return 1;
+		} else {
+			char *ptr = &put_str[11];
+			kgdb_hex2long(&ptr, &sstep_thread_id);
 		}
 		break;
 	case 4:
@@ -502,10 +585,10 @@
 static struct test_struct singlestep_break_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
+	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
 	{ "write", "OK", write_regs }, /* Write registers */
-	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "kgdbts_break_test", NULL, check_single_step },
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
@@ -523,16 +606,16 @@
 static struct test_struct do_fork_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
-	{ "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
-	{ "write", "OK", write_regs }, /* Write registers */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
 	{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
+	{ "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
+	{ "write", "OK", write_regs, emul_reset }, /* Write registers */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "do_fork", NULL, check_single_step },
 	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
 	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
 	{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-	{ "", "" },
+	{ "", "", get_cont_catch, put_cont_catch },
 };
 
 /* Test for hitting a breakpoint at sys_open for what ever the number
@@ -541,16 +624,16 @@
 static struct test_struct sys_open_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
-	{ "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
-	{ "write", "OK", write_regs }, /* Write registers */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
 	{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
+	{ "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
+	{ "write", "OK", write_regs, emul_reset }, /* Write registers */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "sys_open", NULL, check_single_step },
 	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
 	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
 	{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-	{ "", "" },
+	{ "", "", get_cont_catch, put_cont_catch },
 };
 
 /*
@@ -693,8 +776,8 @@
 	/* This callback is a put char which is when kgdb sends data to
 	 * this I/O module.
 	 */
-	if (ts.tst[ts.idx].get[0] == '\0' &&
-		ts.tst[ts.idx].put[0] == '\0') {
+	if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' &&
+	    !ts.tst[ts.idx].get_handler) {
 		eprintk("kgdbts: ERROR: beyond end of test on"
 			   " '%s' line %i\n", ts.name, ts.idx);
 		return 0;
@@ -907,6 +990,17 @@
 	if (ptr)
 		sstep_test = simple_strtol(ptr+1, NULL, 10);
 
+	/* All HW break point tests */
+	if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+		hwbreaks_ok = 1;
+		v1printk("kgdbts:RUN hw breakpoint test\n");
+		run_breakpoint_test(1);
+		v1printk("kgdbts:RUN hw write breakpoint test\n");
+		run_hw_break_test(1);
+		v1printk("kgdbts:RUN access write breakpoint test\n");
+		run_hw_break_test(0);
+	}
+
 	/* required internal KGDB tests */
 	v1printk("kgdbts:RUN plant and detach test\n");
 	run_plant_and_detach_test(0);
@@ -924,35 +1018,11 @@
 
 	/* ===Optional tests=== */
 
-	/* All HW break point tests */
-	if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
-		hwbreaks_ok = 1;
-		v1printk("kgdbts:RUN hw breakpoint test\n");
-		run_breakpoint_test(1);
-		v1printk("kgdbts:RUN hw write breakpoint test\n");
-		run_hw_break_test(1);
-		v1printk("kgdbts:RUN access write breakpoint test\n");
-		run_hw_break_test(0);
-	}
-
 	if (nmi_sleep) {
 		v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
 		run_nmi_sleep_test(nmi_sleep);
 	}
 
-#ifdef CONFIG_DEBUG_RODATA
-	/* Until there is an api to write to read-only text segments, use
-	 * HW breakpoints for the remainder of any tests, else print a
-	 * failure message if hw breakpoints do not work.
-	 */
-	if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
-		eprintk("kgdbts: HW breakpoints do not work,"
-			"skipping remaining tests\n");
-		return;
-	}
-	force_hwbrks = 1;
-#endif /* CONFIG_DEBUG_RODATA */
-
 	/* If the do_fork test is run it will be the last test that is
 	 * executed because a kernel thread will be spawned at the very
 	 * end to unregister the debug hooks.
diff -druN linux-libre-3.3-gnu/drivers/mmc/core/sdio_bus.c linux-libre-3.3.2-gnu/drivers/mmc/core/sdio_bus.c
--- linux-libre-3.3-gnu/drivers/mmc/core/sdio_bus.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mmc/core/sdio_bus.c	2012-04-13 12:42:02.000000000 -0400
@@ -192,9 +192,15 @@
 	return ret;
 }
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
+
+static int pm_no_operation(struct device *dev)
+{
+	return 0;
+}
 
 static const struct dev_pm_ops sdio_bus_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
 	SET_RUNTIME_PM_OPS(
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_resume,
@@ -204,11 +210,11 @@
 
 #define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)
 
-#else /* !CONFIG_PM_RUNTIME */
+#else /* !CONFIG_PM */
 
 #define SDIO_PM_OPS_PTR	NULL
 
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* !CONFIG_PM */
 
 static struct bus_type sdio_bus_type = {
 	.name		= "sdio",
diff -druN linux-libre-3.3-gnu/drivers/mmc/host/atmel-mci.c linux-libre-3.3.2-gnu/drivers/mmc/host/atmel-mci.c
--- linux-libre-3.3-gnu/drivers/mmc/host/atmel-mci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mmc/host/atmel-mci.c	2012-04-13 12:42:02.000000000 -0400
@@ -480,7 +480,14 @@
 static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
 					unsigned int ns)
 {
-	return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+	/*
+	 * It is easier here to use us instead of ns for the timeout,
+	 * it prevents from overflows during calculation.
+	 */
+	unsigned int us = DIV_ROUND_UP(ns, 1000);
+
+	/* Maximum clock frequency is host->bus_hz/2 */
+	return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
 }
 
 static void atmci_set_timeout(struct atmel_mci *host,
diff -druN linux-libre-3.3-gnu/drivers/mmc/host/sdhci-dove.c linux-libre-3.3.2-gnu/drivers/mmc/host/sdhci-dove.c
--- linux-libre-3.3-gnu/drivers/mmc/host/sdhci-dove.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mmc/host/sdhci-dove.c	2012-04-13 12:42:02.000000000 -0400
@@ -20,6 +20,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/mmc/host.h>
 
 #include "sdhci-pltfm.h"
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/block2mtd.c linux-libre-3.3.2-gnu/drivers/mtd/devices/block2mtd.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/block2mtd.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/block2mtd.c	2012-04-13 12:42:02.000000000 -0400
@@ -283,6 +283,7 @@
 	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
 	dev->mtd.writesize = 1;
+	dev->mtd.writebufsize = PAGE_SIZE;
 	dev->mtd.type = MTD_RAM;
 	dev->mtd.flags = MTD_CAP_RAM;
 	dev->mtd.erase = block2mtd_erase;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/doc2000.c linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2000.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/doc2000.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2000.c	2012-04-13 12:42:02.000000000 -0400
@@ -562,7 +562,7 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->writesize = 512;
+	mtd->writebufsize = mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/doc2001.c linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2001.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/doc2001.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2001.c	2012-04-13 12:42:02.000000000 -0400
@@ -346,7 +346,7 @@
 
 	/* FIXME: erase size is not always 8KiB */
 	mtd->erasesize = 0x2000;
-	mtd->writesize = 512;
+	mtd->writebufsize = mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/doc2001plus.c linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2001plus.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/doc2001plus.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/doc2001plus.c	2012-04-13 12:42:02.000000000 -0400
@@ -467,7 +467,7 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->writesize = 512;
+	mtd->writebufsize = mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/docg3.c linux-libre-3.3.2-gnu/drivers/mtd/devices/docg3.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/docg3.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/docg3.c	2012-04-13 12:42:02.000000000 -0400
@@ -1817,7 +1817,7 @@
 	mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
 	if (docg3->reliable == 2)
 		mtd->erasesize /= 2;
-	mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+	mtd->writebufsize = mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
 	mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/lart.c linux-libre-3.3.2-gnu/drivers/mtd/devices/lart.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/lart.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/lart.c	2012-04-13 12:42:02.000000000 -0400
@@ -630,6 +630,7 @@
    mtd.name = module_name;
    mtd.type = MTD_NORFLASH;
    mtd.writesize = 1;
+   mtd.writebufsize = 4;
    mtd.flags = MTD_CAP_NORFLASH;
    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/m25p80.c linux-libre-3.3.2-gnu/drivers/mtd/devices/m25p80.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/m25p80.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/m25p80.c	2012-04-13 12:42:02.000000000 -0400
@@ -932,6 +932,7 @@
 	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
+	flash->mtd.writebufsize = flash->page_size;
 
 	if (info->addr_width)
 		flash->addr_width = info->addr_width;
diff -druN linux-libre-3.3-gnu/drivers/mtd/devices/sst25l.c linux-libre-3.3.2-gnu/drivers/mtd/devices/sst25l.c
--- linux-libre-3.3-gnu/drivers/mtd/devices/sst25l.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/devices/sst25l.c	2012-04-13 12:42:02.000000000 -0400
@@ -402,6 +402,7 @@
 	flash->mtd.flags	= MTD_CAP_NORFLASH;
 	flash->mtd.erasesize	= flash_info->erase_size;
 	flash->mtd.writesize	= flash_info->page_size;
+	flash->mtd.writebufsize	= flash_info->page_size;
 	flash->mtd.size		= flash_info->page_size * flash_info->nr_pages;
 	flash->mtd.erase	= sst25l_erase;
 	flash->mtd.read		= sst25l_read;
diff -druN linux-libre-3.3-gnu/drivers/mtd/maps/ixp4xx.c linux-libre-3.3.2-gnu/drivers/mtd/maps/ixp4xx.c
--- linux-libre-3.3-gnu/drivers/mtd/maps/ixp4xx.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/maps/ixp4xx.c	2012-04-13 12:42:02.000000000 -0400
@@ -182,6 +182,9 @@
 {
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info;
+	struct mtd_part_parser_data ppdata = {
+		.origin = dev->resource->start,
+	};
 	int err = -1;
 
 	if (!plat)
@@ -247,7 +250,7 @@
 	/* Use the fast version */
 	info->map.write = ixp4xx_write16;
 
-	err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
+	err = mtd_device_parse_register(info->mtd, probes, &ppdata,
 			plat->parts, plat->nr_parts);
 	if (err) {
 		printk(KERN_ERR "Could not parse partitions\n");
diff -druN linux-libre-3.3-gnu/drivers/mtd/maps/lantiq-flash.c linux-libre-3.3.2-gnu/drivers/mtd/maps/lantiq-flash.c
--- linux-libre-3.3-gnu/drivers/mtd/maps/lantiq-flash.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/maps/lantiq-flash.c	2012-04-13 12:42:02.000000000 -0400
@@ -45,6 +45,7 @@
 };
 
 static char ltq_map_name[] = "ltq_nor";
+static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL };
 
 static map_word
 ltq_read16(struct map_info *map, unsigned long adr)
@@ -168,7 +169,7 @@
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
+	err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, 0,
 			ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
diff -druN linux-libre-3.3-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c linux-libre-3.3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
--- linux-libre-3.3-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	2012-04-13 12:42:02.000000000 -0400
@@ -1124,7 +1124,7 @@
 		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
 	/* Do we have a flash based bad block table ? */
-	if (chip->options & NAND_BBT_USE_FLASH)
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		ret = nand_update_bbt(mtd, ofs);
 	else {
 		chipnr = (int)(ofs >> chip->chip_shift);
diff -druN linux-libre-3.3-gnu/drivers/mtd/ubi/scan.c linux-libre-3.3.2-gnu/drivers/mtd/ubi/scan.c
--- linux-libre-3.3-gnu/drivers/mtd/ubi/scan.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/ubi/scan.c	2012-04-13 12:42:02.000000000 -0400
@@ -1174,7 +1174,7 @@
 
 	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
 	if (!ech)
-		goto out_slab;
+		goto out_si;
 
 	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vidh)
@@ -1235,8 +1235,6 @@
 	ubi_free_vid_hdr(ubi, vidh);
 out_ech:
 	kfree(ech);
-out_slab:
-	kmem_cache_destroy(si->scan_leb_slab);
 out_si:
 	ubi_scan_destroy_si(si);
 	return ERR_PTR(err);
@@ -1325,7 +1323,9 @@
 		}
 	}
 
-	kmem_cache_destroy(si->scan_leb_slab);
+	if (si->scan_leb_slab)
+		kmem_cache_destroy(si->scan_leb_slab);
+
 	kfree(si);
 }
 
diff -druN linux-libre-3.3-gnu/drivers/mtd/ubi/wl.c linux-libre-3.3.2-gnu/drivers/mtd/ubi/wl.c
--- linux-libre-3.3-gnu/drivers/mtd/ubi/wl.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/mtd/ubi/wl.c	2012-04-13 12:42:02.000000000 -0400
@@ -389,7 +389,7 @@
  */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
 {
-	int err, medium_ec;
+	int err;
 	struct ubi_wl_entry *e, *first, *last;
 
 	ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
@@ -427,7 +427,7 @@
 		 * For unknown data we pick a physical eraseblock with medium
 		 * erase counter. But we by no means can pick a physical
 		 * eraseblock with erase counter greater or equivalent than the
-		 * lowest erase counter plus %WL_FREE_MAX_DIFF.
+		 * lowest erase counter plus %WL_FREE_MAX_DIFF/2.
 		 */
 		first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
 					u.rb);
@@ -436,10 +436,8 @@
 		if (last->ec - first->ec < WL_FREE_MAX_DIFF)
 			e = rb_entry(ubi->free.rb_node,
 					struct ubi_wl_entry, u.rb);
-		else {
-			medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
-			e = find_wl_entry(&ubi->free, medium_ec);
-		}
+		else
+			e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
 		break;
 	case UBI_SHORTTERM:
 		/*
diff -druN linux-libre-3.3-gnu/drivers/net/ethernet/broadcom/tg3.c linux-libre-3.3.2-gnu/drivers/net/ethernet/broadcom/tg3.c
--- linux-libre-3.3-gnu/drivers/net/ethernet/broadcom/tg3.c	2012-03-19 01:16:43.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/ethernet/broadcom/tg3.c	2012-04-13 23:00:42.000000000 -0400
@@ -2762,7 +2762,9 @@
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
-	     (tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
+	     (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+	     !tp->pci_fn))
 		return;
 
 	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
diff -druN linux-libre-3.3-gnu/drivers/net/ethernet/freescale/fsl_pq_mdio.c linux-libre-3.3.2-gnu/drivers/net/ethernet/freescale/fsl_pq_mdio.c
--- linux-libre-3.3-gnu/drivers/net/ethernet/freescale/fsl_pq_mdio.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/ethernet/freescale/fsl_pq_mdio.c	2012-04-13 12:42:02.000000000 -0400
@@ -356,13 +356,13 @@
 
 		if (prop)
 			tbiaddr = *prop;
-	}
 
-	if (tbiaddr == -1) {
-		err = -EBUSY;
-		goto err_free_irqs;
-	} else {
-		out_be32(tbipa, tbiaddr);
+		if (tbiaddr == -1) {
+			err = -EBUSY;
+			goto err_free_irqs;
+		} else {
+			out_be32(tbipa, tbiaddr);
+		}
 	}
 
 	err = of_mdiobus_register(new_bus, np);
diff -druN linux-libre-3.3-gnu/drivers/net/ethernet/marvell/sky2.c linux-libre-3.3.2-gnu/drivers/net/ethernet/marvell/sky2.c
--- linux-libre-3.3-gnu/drivers/net/ethernet/marvell/sky2.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/ethernet/marvell/sky2.c	2012-04-13 12:42:02.000000000 -0400
@@ -95,6 +95,10 @@
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
+static int legacy_pme = 0;
+module_param(legacy_pme, int, 0);
+MODULE_PARM_DESC(legacy_pme, "Legacy power management");
+
 static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
@@ -867,6 +871,13 @@
 	/* Disable PiG firmware */
 	sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF);
 
+	/* Needed by some broken BIOSes, use PCI rather than PCI-e for WOL */
+	if (legacy_pme) {
+		u32 reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+		reg1 |= PCI_Y2_PME_LEGACY;
+		sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+	}
+
 	/* block receiver */
 	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
 	sky2_read32(hw, B0_CTST);
@@ -1756,13 +1767,14 @@
 
 	sky2_hw_up(sky2);
 
+	/* Enable interrupts from phy/mac for port */
+	imask = sky2_read32(hw, B0_IMSK);
+
 	if (hw->chip_id == CHIP_ID_YUKON_OPT ||
 	    hw->chip_id == CHIP_ID_YUKON_PRM ||
 	    hw->chip_id == CHIP_ID_YUKON_OP_2)
 		imask |= Y2_IS_PHY_QLNK;	/* enable PHY Quick Link */
 
-	/* Enable interrupts from phy/mac for port */
-	imask = sky2_read32(hw, B0_IMSK);
 	imask |= portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
 	sky2_read32(hw, B0_IMSK);
diff -druN linux-libre-3.3-gnu/drivers/net/ethernet/mellanox/mlx4/main.c linux-libre-3.3.2-gnu/drivers/net/ethernet/mellanox/mlx4/main.c
--- linux-libre-3.3-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2012-04-13 12:42:02.000000000 -0400
@@ -394,7 +394,7 @@
 	return ret;
 }
 
-static int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
+int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_slave_state *s_slave;
diff -druN linux-libre-3.3-gnu/drivers/net/ethernet/via/via-rhine.c linux-libre-3.3.2-gnu/drivers/net/ethernet/via/via-rhine.c
--- linux-libre-3.3-gnu/drivers/net/ethernet/via/via-rhine.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/ethernet/via/via-rhine.c	2012-04-13 12:42:02.000000000 -0400
@@ -503,30 +503,32 @@
 static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
 static void rhine_restart_tx(struct net_device *dev);
 
-static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high)
+static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool low)
 {
 	void __iomem *ioaddr = rp->base;
 	int i;
 
 	for (i = 0; i < 1024; i++) {
-		if (high ^ !!(ioread8(ioaddr + reg) & mask))
+		bool has_mask_bits = !!(ioread8(ioaddr + reg) & mask);
+
+		if (low ^ has_mask_bits)
 			break;
 		udelay(10);
 	}
 	if (i > 64) {
 		netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle "
-			  "count: %04d\n", high ? "high" : "low", reg, mask, i);
+			  "count: %04d\n", low ? "low" : "high", reg, mask, i);
 	}
 }
 
 static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask)
 {
-	rhine_wait_bit(rp, reg, mask, true);
+	rhine_wait_bit(rp, reg, mask, false);
 }
 
 static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask)
 {
-	rhine_wait_bit(rp, reg, mask, false);
+	rhine_wait_bit(rp, reg, mask, true);
 }
 
 static u32 rhine_get_events(struct rhine_private *rp)
diff -druN linux-libre-3.3-gnu/drivers/net/usb/cdc_eem.c linux-libre-3.3.2-gnu/drivers/net/usb/cdc_eem.c
--- linux-libre-3.3-gnu/drivers/net/usb/cdc_eem.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/usb/cdc_eem.c	2012-04-13 12:42:02.000000000 -0400
@@ -93,6 +93,7 @@
 	/* no jumbogram (16K) support for now */
 
 	dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
 	return 0;
 }
diff -druN linux-libre-3.3-gnu/drivers/net/usb/usbnet.c linux-libre-3.3.2-gnu/drivers/net/usb/usbnet.c
--- linux-libre-3.3-gnu/drivers/net/usb/usbnet.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/usb/usbnet.c	2012-04-13 12:42:02.000000000 -0400
@@ -589,6 +589,14 @@
 		entry = (struct skb_data *) skb->cb;
 		urb = entry->urb;
 
+		/*
+		 * Get reference count of the URB to avoid it to be
+		 * freed during usb_unlink_urb, which may trigger
+		 * use-after-free problem inside usb_unlink_urb since
+		 * usb_unlink_urb is always racing with .complete
+		 * handler(include defer_bh).
+		 */
+		usb_get_urb(urb);
 		spin_unlock_irqrestore(&q->lock, flags);
 		// during some PM-driven resume scenarios,
 		// these (async) unlinks complete immediately
@@ -597,6 +605,7 @@
 			netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
 		else
 			count++;
+		usb_put_urb(urb);
 		spin_lock_irqsave(&q->lock, flags);
 	}
 	spin_unlock_irqrestore (&q->lock, flags);
@@ -1028,7 +1037,6 @@
 	}
 
 	usb_autopm_put_interface_async(dev->intf);
-	urb->dev = NULL;
 	entry->state = tx_done;
 	defer_bh(dev, skb, &dev->txq);
 }
diff -druN linux-libre-3.3-gnu/drivers/net/usb/zaurus.c linux-libre-3.3.2-gnu/drivers/net/usb/zaurus.c
--- linux-libre-3.3-gnu/drivers/net/usb/zaurus.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/usb/zaurus.c	2012-04-13 12:42:02.000000000 -0400
@@ -337,6 +337,11 @@
 	.driver_info = ZAURUS_PXA_INFO,
 },
 {
+	/* Motorola Rokr E6 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
 	/* Motorola MOTOMAGX phones */
 	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/ath/ath9k/calib.c linux-libre-3.3.2-gnu/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-3.3-gnu/drivers/net/wireless/ath/ath9k/calib.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/ath/ath9k/calib.c	2012-04-13 12:42:02.000000000 -0400
@@ -20,7 +20,6 @@
 
 /* Common calibration code */
 
-#define ATH9K_NF_TOO_HIGH	-60
 
 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
 {
@@ -346,10 +345,10 @@
 			"NF calibrated [%s] [chain %d] is %d\n",
 			(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 
-		if (nf[i] > ATH9K_NF_TOO_HIGH) {
+		if (nf[i] > limit->max) {
 			ath_dbg(common, CALIBRATE,
 				"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
-				i, nf[i], ATH9K_NF_TOO_HIGH);
+				i, nf[i], limit->max);
 			nf[i] = limit->max;
 		} else if (nf[i] < limit->min) {
 			ath_dbg(common, CALIBRATE,
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/3945-mac.c linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/3945-mac.c
--- linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/3945-mac.c	2012-03-19 01:18:04.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/3945-mac.c	2012-04-13 23:02:03.000000000 -0400
@@ -2684,7 +2684,6 @@
 
 	if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
 		mutex_lock(&il->mutex);
-		il->ctx.vif = NULL;
 		il->is_open = 0;
 		mutex_unlock(&il->mutex);
 		il3945_down(il);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/4965-mac.c linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/4965-mac.c
--- linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2012-03-19 01:18:22.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2012-04-13 23:02:20.000000000 -0400
@@ -5381,7 +5381,6 @@
 
 	if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
 		mutex_lock(&il->mutex);
-		il->ctx.vif = NULL;
 		il->is_open = 0;
 
 		__il4965_down(il);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/common.c linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/common.c
--- linux-libre-3.3-gnu/drivers/net/wireless/iwlegacy/common.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/iwlegacy/common.c	2012-04-13 12:42:02.000000000 -0400
@@ -4575,6 +4575,7 @@
 	struct il_priv *il = hw->priv;
 	struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
 	int err;
+	bool reset;
 	u32 modes;
 
 	D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr);
@@ -4594,6 +4595,16 @@
 		goto out;
 	}
 
+	/*
+	 * We do not support multiple virtual interfaces, but on hardware reset
+	 * we have to add the same interface again.
+	 */
+	reset = (il->ctx.vif == vif);
+	if (il->ctx.vif && !reset) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
 	modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes;
 	if (!(modes & BIT(vif->type))) {
 		err = -EOPNOTSUPP;
@@ -4605,8 +4616,11 @@
 
 	err = il_setup_interface(il, &il->ctx);
 	if (err) {
-		il->ctx.vif = NULL;
-		il->iw_mode = NL80211_IFTYPE_STATION;
+		IL_WARN("Fail to set mode %d\n", vif->type);
+		if (!reset) {
+			il->ctx.vif = NULL;
+			il->iw_mode = NL80211_IFTYPE_STATION;
+		}
 	}
 
 out:
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/iwlwifi/iwl-core.c linux-libre-3.3.2-gnu/drivers/net/wireless/iwlwifi/iwl-core.c
--- linux-libre-3.3-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2012-04-13 12:42:02.000000000 -0400
@@ -1465,20 +1465,10 @@
 	if (timeout == 0)
 		return;
 
-	/* monitor and check for stuck cmd queue */
-	if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
-		return;
-
-	/* monitor and check for other stuck queues */
-	if (iwl_is_any_associated(priv)) {
-		for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
-			/* skip as we already checked the command queue */
-			if (cnt == priv->shrd->cmd_queue)
-				continue;
-			if (iwl_check_stuck_queue(priv, cnt))
-				return;
-		}
-	}
+	/* monitor and check for stuck queues */
+	for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++)
+		if (iwl_check_stuck_queue(priv, cnt))
+			return;
 
 	mod_timer(&priv->watchdog, jiffies +
 		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/p54/p54spi.c linux-libre-3.3.2-gnu/drivers/net/wireless/p54/p54spi.c
--- linux-libre-3.3-gnu/drivers/net/wireless/p54/p54spi.c	2012-03-19 01:19:11.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/p54/p54spi.c	2012-04-13 23:03:11.000000000 -0400
@@ -618,19 +618,19 @@
 	ret = spi_setup(spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "spi_setup failed");
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_power, "p54spi power");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free_gpio_power;
 	}
 
 	gpio_direction_output(p54spi_gpio_power, 0);
@@ -641,7 +641,7 @@
 			  priv->spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "request_irq() failed");
-		goto err_free_common;
+		goto err_free_gpio_irq;
 	}
 
 	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -673,6 +673,12 @@
 	return 0;
 
 err_free_common:
+	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+	gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+	gpio_free(p54spi_gpio_power);
+err_free:
 	p54_free_common(priv->hw);
 	return ret;
 }
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rt2x00/rt2800usb.c linux-libre-3.3.2-gnu/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2012-03-19 01:19:36.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2012-04-13 23:03:36.000000000 -0400
@@ -922,6 +922,7 @@
 	{ USB_DEVICE(0x07d1, 0x3c13) },
 	{ USB_DEVICE(0x07d1, 0x3c15) },
 	{ USB_DEVICE(0x07d1, 0x3c16) },
+	{ USB_DEVICE(0x2001, 0x3c1b) },
 	/* Draytek */
 	{ USB_DEVICE(0x07fa, 0x7712) },
 	/* DVICO */
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/base.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/base.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/base.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/base.c	2012-04-13 12:42:02.000000000 -0400
@@ -413,6 +413,7 @@
 
 	wiphy_rfkill_start_polling(hw->wiphy);
 }
+EXPORT_SYMBOL(rtl_init_rfkill);
 
 void rtl_deinit_rfkill(struct ieee80211_hw *hw)
 {
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/core.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/core.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/core.c	2012-04-13 12:42:02.000000000 -0400
@@ -31,8 +31,50 @@
 #include "core.h"
 #include "cam.h"
 #include "base.h"
+#include "pci.h"
 #include "ps.h"
 
+#include <linux/export.h>
+
+void rtl_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct ieee80211_hw *hw = context;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err;
+
+	RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+			 ("Firmware callback routine entered!\n"));
+	complete(&rtlpriv->firmware_loading_complete);
+	if (!firmware) {
+		pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
+		rtlpriv->max_fw_size = 0;
+		return;
+	}
+	if (firmware->size > rtlpriv->max_fw_size) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is too big!\n"));
+		release_firmware(firmware);
+		return;
+	}
+	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+	rtlpriv->rtlhal.fwsize = firmware->size;
+	release_firmware(firmware);
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't register mac80211 hw\n"));
+		return;
+	} else {
+		rtlpriv->mac80211.mac80211_registered = 1;
+	}
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+
+	/*init rfkill */
+	rtl_init_rfkill(hw);
+}
+EXPORT_SYMBOL(rtl_fw_cb);
+
 /*mutex for start & stop is must here. */
 static int rtl_op_start(struct ieee80211_hw *hw)
 {
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/core.h linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/core.h
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/core.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/core.h	2012-04-13 12:42:02.000000000 -0400
@@ -30,8 +30,6 @@
 #ifndef __RTL_CORE_H__
 #define __RTL_CORE_H__
 
-#include <net/mac80211.h>
-
 #define RTL_SUPPORTED_FILTERS		\
 	(FIF_PROMISC_IN_BSS | \
 	FIF_ALLMULTI | FIF_CONTROL | \
@@ -42,4 +40,6 @@
 #define RTL_SUPPORTED_CTRL_FILTER	0xFF
 
 extern const struct ieee80211_ops rtl_ops;
+void rtl_fw_cb(const struct firmware *firmware, void *context);
+
 #endif
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/pci.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/pci.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/pci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/pci.c	2012-04-13 12:42:02.000000000 -0400
@@ -28,8 +28,8 @@
  *****************************************************************************/
 
 #include <linux/export.h>
-#include "core.h"
 #include "wifi.h"
+#include "core.h"
 #include "pci.h"
 #include "base.h"
 #include "ps.h"
@@ -657,6 +657,8 @@
 		return;
 
 	uskb = dev_alloc_skb(skb->len + 128);
+	if (!uskb)
+		return;		/* exit if allocation failed */
 	memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
 	pdata = (u8 *)skb_put(uskb, skb->len);
 	memcpy(pdata, skb->data, skb->len);
@@ -1155,10 +1157,12 @@
 		ring->idx = (ring->idx + 1) % ring->entries;
 	}
 
-	pci_free_consistent(rtlpci->pdev,
-			    sizeof(*ring->desc) * ring->entries,
-			    ring->desc, ring->dma);
-	ring->desc = NULL;
+	if (ring->desc) {
+		pci_free_consistent(rtlpci->pdev,
+				    sizeof(*ring->desc) * ring->entries,
+				    ring->desc, ring->dma);
+		ring->desc = NULL;
+	}
 }
 
 static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
@@ -1182,12 +1186,14 @@
 			kfree_skb(skb);
 		}
 
-		pci_free_consistent(rtlpci->pdev,
+		if (rtlpci->rx_ring[rx_queue_idx].desc) {
+			pci_free_consistent(rtlpci->pdev,
 				    sizeof(*rtlpci->rx_ring[rx_queue_idx].
 					   desc) * rtlpci->rxringcount,
 				    rtlpci->rx_ring[rx_queue_idx].desc,
 				    rtlpci->rx_ring[rx_queue_idx].dma);
-		rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+			rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+		}
 	}
 }
 
@@ -1573,6 +1579,9 @@
 
 	rtlpci->driver_is_goingto_unload = true;
 	rtlpriv->cfg->ops->hw_disable(hw);
+	/* some things are not needed if firmware not available */
+	if (!rtlpriv->max_fw_size)
+		return;
 	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
@@ -1791,6 +1800,7 @@
 	rtlpriv = hw->priv;
 	pcipriv = (void *)rtlpriv->priv;
 	pcipriv->dev.pdev = pdev;
+	init_completion(&rtlpriv->firmware_loading_complete);
 
 	/* init cfg & intf_ops */
 	rtlpriv->rtlhal.interface = INTF_PCI;
@@ -1811,7 +1821,7 @@
 	err = pci_request_regions(pdev, KBUILD_MODNAME);
 	if (err) {
 		RT_ASSERT(false, ("Can't obtain PCI resources\n"));
-		return err;
+		goto fail2;
 	}
 
 	pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id);
@@ -1877,15 +1887,6 @@
 		goto fail3;
 	}
 
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Can't register mac80211 hw.\n"));
-		goto fail3;
-	} else {
-		rtlpriv->mac80211.mac80211_registered = 1;
-	}
-
 	err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
@@ -1893,9 +1894,6 @@
 		goto fail3;
 	}
 
-	/*init rfkill */
-	rtl_init_rfkill(hw);
-
 	rtlpci = rtl_pcidev(pcipriv);
 	err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
 			  IRQF_SHARED, KBUILD_MODNAME, hw);
@@ -1904,24 +1902,22 @@
 			 ("%s: failed to register IRQ handler\n",
 			  wiphy_name(hw->wiphy)));
 		goto fail3;
-	} else {
-		rtlpci->irq_alloc = 1;
 	}
+	rtlpci->irq_alloc = 1;
 
-	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 
 fail3:
 	pci_set_drvdata(pdev, NULL);
 	rtl_deinit_core(hw);
 	_rtl_pci_io_handler_release(hw);
-	ieee80211_free_hw(hw);
 
 	if (rtlpriv->io.pci_mem_start != 0)
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
 fail2:
 	pci_release_regions(pdev);
+	complete(&rtlpriv->firmware_loading_complete);
 
 fail1:
 
@@ -1940,6 +1936,8 @@
 	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
 	struct rtl_mac *rtlmac = rtl_mac(rtlpriv);
 
+	/* just in case driver is removed before firmware callback */
+	wait_for_completion(&rtlpriv->firmware_loading_complete);
 	clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 
 	sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/pci.h linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/pci.h
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/pci.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/pci.h	2012-04-13 12:42:02.000000000 -0400
@@ -239,7 +239,6 @@
 void rtl_pci_disconnect(struct pci_dev *pdev);
 int rtl_pci_suspend(struct device *dev);
 int rtl_pci_resume(struct device *dev);
-
 static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
 	return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/ps.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/ps.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/ps.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/ps.c	2012-04-13 12:42:02.000000000 -0400
@@ -47,7 +47,8 @@
 			 ("Driver is already down!\n"));
 
 	/*<2> Enable Adapter */
-	rtlpriv->cfg->ops->hw_init(hw);
+	if (rtlpriv->cfg->ops->hw_init(hw))
+		return 1;
 	RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
 	/*<3> Enable Interrupt */
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c	2012-04-13 12:42:02.000000000 -0400
@@ -524,6 +524,10 @@
 		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
 		  dm_digtable.backoff_val));
 
+	dm_digtable.cur_igvalue += 2;
+	if (dm_digtable.cur_igvalue > 0x3f)
+		dm_digtable.cur_igvalue = 0x3f;
+
 	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
 		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 			      dm_digtable.cur_igvalue);
@@ -1219,13 +1223,18 @@
 				 ("PreState = %d, CurState = %d\n",
 				  p_ra->pre_ratr_state, p_ra->ratr_state));
 
-			rcu_read_lock();
-			sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			/* Only the PCI card uses sta in the update rate table
+			 * callback routine */
+			if (rtlhal->interface == INTF_PCI) {
+				rcu_read_lock();
+				sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			}
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 					p_ra->ratr_state);
 
 			p_ra->pre_ratr_state = p_ra->ratr_state;
-			rcu_read_unlock();
+			if (rtlhal->interface == INTF_PCI)
+				rcu_read_unlock();
 		}
 	}
 }
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c	2012-04-13 12:42:02.000000000 -0400
@@ -262,10 +262,9 @@
 	u32 fwsize;
 	enum version_8192c version = rtlhal->version;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 
-	pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
 	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
 	pfwdata = (u8 *) rtlhal->pfirmware;
 	fwsize = rtlhal->fwsize;
@@ -518,15 +517,8 @@
 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
 {
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u32 tmp_cmdbuf[2];
 
-	if (rtlhal->fw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
-
 	memset(tmp_cmdbuf, 0, 8);
 	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
 	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
@@ -788,6 +780,8 @@
 
 
 	skb = dev_alloc_skb(totalpacketlen);
+	if (!skb)
+		return;
 	memcpy((u8 *) skb_put(skb, totalpacketlen),
 	       &reserved_page_packet, totalpacketlen);
 
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c	2012-04-13 12:42:02.000000000 -0400
@@ -1968,7 +1968,7 @@
 		break;
 	case IO_CMD_PAUSE_DM_BY_SCAN:
 		rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
-		dm_digtable.cur_igvalue = 0x17;
+		dm_digtable.cur_igvalue = 0x37;
 		rtl92c_dm_write_dig(hw);
 		break;
 	default:
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2012-04-13 12:42:02.000000000 -0400
@@ -921,10 +921,7 @@
 			 ("Failed to download FW. Init HW "
 			  "without FW now..\n"));
 		err = 1;
-		rtlhal->fw_ready = false;
 		return err;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 
 	rtlhal->last_hmeboxnum = 0;
@@ -1199,7 +1196,6 @@
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u8 u1b_tmp;
 	u32 u4b_tmp;
 
@@ -1210,7 +1206,7 @@
 	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
-	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
+	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7))
 		rtl92c_firmware_selfreset(hw);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
 	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2012-03-19 01:19:38.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2012-04-13 23:03:38.000000000 -0400
@@ -92,9 +92,7 @@
 	int err;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	const struct firmware *firmware;
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	char *fw_name = NULL;
 
 	rtl8192ce_bt_reg_init(hw);
 
@@ -166,26 +164,20 @@
 	/* request fw */
 	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
 	    !IS_92C_SERIAL(rtlhal->version))
-		fw_name = "/*(DEBLOBBED)*/";
+		rtlpriv->cfg->fw_name = "/*(DEBLOBBED)*/";
 	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
-		fw_name = "/*(DEBLOBBED)*/";
-	else
-		fw_name = rtlpriv->cfg->fw_name;
-	err = reject_firmware(&firmware, fw_name, rtlpriv->io.dev);
+		rtlpriv->cfg->fw_name = "/*(DEBLOBBED)*/";
+
+	rtlpriv->max_fw_size = 0x4000;
+	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+	err = reject_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Failed to request firmware!\n"));
 		return 1;
 	}
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
 
 	return 0;
 }
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2012-04-13 12:42:02.000000000 -0400
@@ -1171,10 +1171,7 @@
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. Init HW without FW now..\n"));
 		err = 1;
-		rtlhal->fw_ready = false;
 		return err;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 	rtlhal->last_hmeboxnum = 0; /* h2c */
 	_rtl92cu_phy_param_tab_init(hw);
@@ -1270,24 +1267,22 @@
 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) {
 			/* reset MCU ready status */
 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
-			if (rtlhal->fw_ready) {
-				/* 8051 reset by self */
-				rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
-				while ((retry_cnts++ < 100) &&
-				       (FEN_CPUEN & rtl_read_word(rtlpriv,
-				       REG_SYS_FUNC_EN))) {
-					udelay(50);
-				}
-				if (retry_cnts >= 100) {
-					RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			/* 8051 reset by self */
+			rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
+			while ((retry_cnts++ < 100) &&
+			       (FEN_CPUEN & rtl_read_word(rtlpriv,
+			       REG_SYS_FUNC_EN))) {
+				udelay(50);
+			}
+			if (retry_cnts >= 100) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 						("#####=> 8051 reset failed!.."
 						".......................\n"););
-					/* if 8051 reset fail, reset MAC. */
-					rtl_write_byte(rtlpriv,
-						       REG_SYS_FUNC_EN + 1,
-						       0x50);
-					udelay(100);
-				}
+				/* if 8051 reset fail, reset MAC. */
+				rtl_write_byte(rtlpriv,
+					       REG_SYS_FUNC_EN + 1,
+					       0x50);
+				udelay(100);
 			}
 		}
 		/* Reset MAC and Enable 8051 */
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2012-03-19 01:19:41.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2012-04-13 23:03:40.000000000 -0400
@@ -54,7 +54,6 @@
 static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	const struct firmware *firmware;
 	int err;
 
 	rtlpriv->dm.dm_initialgain_enable = true;
@@ -62,29 +61,21 @@
 	rtlpriv->dm.disable_framebursting = false;
 	rtlpriv->dm.thermalvalue = 0;
 	rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
-	rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
+
+	/* for firmware buf */
+	rtlpriv->rtlhal.pfirmware = vzalloc(0x4000);
 	if (!rtlpriv->rtlhal.pfirmware) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Can't alloc buffer for fw.\n"));
 		return 1;
 	}
-	/* request fw */
-	err = reject_firmware(&firmware, rtlpriv->cfg->fw_name,
-			rtlpriv->io.dev);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Failed to request firmware!\n"));
-		return 1;
-	}
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
+
+	pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
+	rtlpriv->max_fw_size = 0x4000;
+	err = reject_firmware_nowait(THIS_MODULE, 1,
+				      rtlpriv->cfg->fw_name, rtlpriv->io.dev,
+				      GFP_KERNEL, hw, rtl_fw_cb);
+
 
 	return 0;
 }
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/fw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/fw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/fw.c	2012-04-13 12:42:02.000000000 -0400
@@ -257,7 +257,7 @@
 	bool fw_downloaded = false, fwdl_in_process = false;
 	unsigned long flags;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 	fwsize = rtlhal->fwsize;
 	pfwheader = (u8 *) rtlhal->pfirmware;
@@ -539,14 +539,8 @@
 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 {
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u32 tmp_cmdbuf[2];
 
-	if (rtlhal->fw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
 	memset(tmp_cmdbuf, 0, 8);
 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
@@ -763,12 +757,16 @@
 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 		      u1RsvdPageLoc, 3);
 	skb = dev_alloc_skb(totalpacketlen);
-	memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
-		totalpacketlen);
-	rtstatus = _rtl92d_cmd_send_packet(hw, skb);
+	if (!skb) {
+		dlok = false;
+	} else {
+		memcpy((u8 *) skb_put(skb, totalpacketlen),
+			&reserved_page_packet, totalpacketlen);
+		rtstatus = _rtl92d_cmd_send_packet(hw, skb);
 
-	if (rtstatus)
-		dlok = true;
+		if (rtstatus)
+			dlok = true;
+	}
 	if (dlok) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			("Set RSVD page location to Fw.\n"));
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c	2012-04-13 12:42:02.000000000 -0400
@@ -932,10 +932,7 @@
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. Init HW "
 			 "without FW..\n"));
-		rtlhal->fw_ready = false;
 		return 1;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 	rtlhal->last_hmeboxnum = 0;
 	rtlpriv->psc.fw_current_inpsmode = false;
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c	2012-04-13 12:42:02.000000000 -0400
@@ -3192,7 +3192,7 @@
 		break;
 	case IO_CMD_PAUSE_DM_BY_SCAN:
 		rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
-		de_digtable.cur_igvalue = 0x17;
+		de_digtable.cur_igvalue = 0x37;
 		rtl92d_dm_write_dig(hw);
 		break;
 	default:
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/sw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192de/sw.c	2012-03-19 01:19:42.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192de/sw.c	2012-04-13 23:03:42.000000000 -0400
@@ -94,7 +94,6 @@
 	u8 tid;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	const struct firmware *firmware;
 	static int header_print;
 
 	rtlpriv->dm.dm_initialgain_enable = true;
@@ -170,6 +169,15 @@
 	else if (rtlpriv->psc.reg_fwctrl_lps == 3)
 		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
 
+	/* for early mode */
+	rtlpriv->rtlhal.earlymode_enable = true;
+	for (tid = 0; tid < 8; tid++)
+		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+
+	/* Only load firmware for first MAC */
+	if (header_print)
+		return 0;
+
 	/* for firmware buf */
 	rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
 	if (!rtlpriv->rtlhal.pfirmware) {
@@ -178,33 +186,21 @@
 		return 1;
 	}
 
-	if (!header_print) {
-		pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
-		pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
-		header_print++;
-	}
+	rtlpriv->max_fw_size = 0x8000;
+	pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
+	pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
+	header_print++;
+
 	/* request fw */
-	err = reject_firmware(&firmware, rtlpriv->cfg->fw_name,
-			       rtlpriv->io.dev);
+	err = reject_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Failed to request firmware!\n"));
 		return 1;
 	}
-	if (firmware->size > 0x8000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
 
-	/* for early mode */
-	rtlpriv->rtlhal.earlymode_enable = true;
-	for (tid = 0; tid < 8; tid++)
-		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
 	return 0;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c	2012-04-13 12:42:02.000000000 -0400
@@ -364,7 +364,7 @@
 	u8 fwstatus = FW_STATUS_INIT;
 	bool rtstatus = true;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 
 	firmware = (struct rt_firmware *)rtlhal->pfirmware;
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c	2012-04-13 12:42:02.000000000 -0400
@@ -952,11 +952,10 @@
 	if (!rtstatus) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. "
-			 "Init HW without FW now.., Please copy FW into"
+			 "Init HW without FW now.., "
+			 "Please copy FW into"
 			 "/lib/firmware/rtlwifi\n"));
-		rtlhal->fw_ready = false;
-	} else {
-		rtlhal->fw_ready = true;
+		return 1;
 	}
 
 	/* After FW download, we have to reset MAC register */
@@ -1219,9 +1218,14 @@
 
 void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
 {
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv;
+	struct rtl_pci *rtlpci;
 
+	rtlpriv = rtl_priv(hw);
+	/* if firmware not available, no interrupts */
+	if (!rtlpriv || !rtlpriv->max_fw_size)
+		return;
+	rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	rtl_write_dword(rtlpriv, INTA_MASK, 0);
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
 
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/led.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/led.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/led.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/led.c	2012-04-13 12:42:02.000000000 -0400
@@ -76,10 +76,13 @@
 
 void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 {
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_priv *rtlpriv;
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	u8 ledcfg;
 
+	rtlpriv = rtl_priv(hw);
+	if (!rtlpriv || rtlpriv->max_fw_size)
+		return;
 	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
 		 ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin));
 
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/sw.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/rtl8192se/sw.c	2012-03-19 01:19:44.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/rtl8192se/sw.c	2012-04-13 23:03:44.000000000 -0400
@@ -35,6 +35,8 @@
 #include "../wifi.h"
 #include "../core.h"
 #include "../pci.h"
+#include "../base.h"
+#include "../pci.h"
 #include "reg.h"
 #include "def.h"
 #include "phy.h"
@@ -89,12 +91,53 @@
 	rtlpci->const_support_pciaspm = 2;
 }
 
+static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct ieee80211_hw *hw = context;
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
+	struct rt_firmware *pfirmware = NULL;
+	int err;
+
+	RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+			 ("Firmware callback routine entered!\n"));
+	complete(&rtlpriv->firmware_loading_complete);
+	if (!firmware) {
+		pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
+		rtlpriv->max_fw_size = 0;
+		return;
+	}
+	if (firmware->size > rtlpriv->max_fw_size) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is too big!\n"));
+		release_firmware(firmware);
+		return;
+	}
+	pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
+	memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
+	pfirmware->sz_fw_tmpbufferlen = firmware->size;
+	release_firmware(firmware);
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't register mac80211 hw\n"));
+		return;
+	} else {
+		rtlpriv->mac80211.mac80211_registered = 1;
+	}
+	rtlpci->irq_alloc = 1;
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+
+	/*init rfkill */
+	rtl_init_rfkill(hw);
+}
+
 static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	const struct firmware *firmware;
-	struct rt_firmware *pfirmware = NULL;
 	int err = 0;
 	u16 earlyrxthreshold = 7;
 
@@ -192,27 +235,19 @@
 		return 1;
 	}
 
+	rtlpriv->max_fw_size = sizeof(struct rt_firmware);
+
 	pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
 		"Loading firmware %s\n", rtlpriv->cfg->fw_name);
 	/* request fw */
-	err = reject_firmware(&firmware, rtlpriv->cfg->fw_name,
-			rtlpriv->io.dev);
+	err = reject_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl92se_fw_cb);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Failed to request firmware!\n"));
 		return 1;
 	}
-	if (firmware->size > sizeof(struct rt_firmware)) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-
-	pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
-	memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
-	pfirmware->sz_fw_tmpbufferlen = firmware->size;
-	release_firmware(firmware);
 
 	return err;
 }
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/usb.c linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/usb.c
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/usb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/usb.c	2012-04-13 12:42:02.000000000 -0400
@@ -29,8 +29,8 @@
 
 #include <linux/usb.h>
 #include <linux/export.h>
-#include "core.h"
 #include "wifi.h"
+#include "core.h"
 #include "usb.h"
 #include "base.h"
 #include "ps.h"
@@ -520,12 +520,14 @@
 			u8 *pdata;
 
 			uskb = dev_alloc_skb(skb->len + 128);
-			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
-			       sizeof(rx_status));
-			pdata = (u8 *)skb_put(uskb, skb->len);
-			memcpy(pdata, skb->data, skb->len);
+			if (uskb) {	/* drop packet on allocation failure */
+				memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+				       sizeof(rx_status));
+				pdata = (u8 *)skb_put(uskb, skb->len);
+				memcpy(pdata, skb->data, skb->len);
+				ieee80211_rx_irqsafe(hw, uskb);
+			}
 			dev_kfree_skb_any(skb);
-			ieee80211_rx_irqsafe(hw, uskb);
 		} else {
 			dev_kfree_skb_any(skb);
 		}
@@ -665,15 +667,17 @@
 	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 
 	err = rtlpriv->cfg->ops->hw_init(hw);
-	rtl_init_rx_config(hw);
+	if (!err) {
+		rtl_init_rx_config(hw);
 
-	/* Enable software */
-	SET_USB_START(rtlusb);
-	/* should after adapter start and interrupt enable. */
-	set_hal_start(rtlhal);
+		/* Enable software */
+		SET_USB_START(rtlusb);
+		/* should after adapter start and interrupt enable. */
+		set_hal_start(rtlhal);
 
-	/* Start bulk IN */
-	_rtl_usb_receive(hw);
+		/* Start bulk IN */
+		_rtl_usb_receive(hw);
+	}
 
 	return err;
 }
@@ -950,6 +954,7 @@
 		return -ENOMEM;
 	}
 	rtlpriv = hw->priv;
+	init_completion(&rtlpriv->firmware_loading_complete);
 	SET_IEEE80211_DEV(hw, &intf->dev);
 	udev = interface_to_usbdev(intf);
 	usb_get_dev(udev);
@@ -984,24 +989,12 @@
 		goto error_out;
 	}
 
-	/*init rfkill */
-	/* rtl_init_rfkill(hw); */
-
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
-			 ("Can't register mac80211 hw.\n"));
-		goto error_out;
-	} else {
-		rtlpriv->mac80211.mac80211_registered = 1;
-	}
-	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 error_out:
 	rtl_deinit_core(hw);
 	_rtl_usb_io_handler_release(hw);
-	ieee80211_free_hw(hw);
 	usb_put_dev(udev);
+	complete(&rtlpriv->firmware_loading_complete);
 	return -ENODEV;
 }
 EXPORT_SYMBOL(rtl_usb_probe);
@@ -1015,6 +1008,9 @@
 
 	if (unlikely(!rtlpriv))
 		return;
+
+	/* just in case driver is removed before firmware callback */
+	wait_for_completion(&rtlpriv->firmware_loading_complete);
 	/*ieee80211_unregister_hw will call ops_stop */
 	if (rtlmac->mac80211_registered == 1) {
 		ieee80211_unregister_hw(hw);
diff -druN linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/wifi.h linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/wifi.h
--- linux-libre-3.3-gnu/drivers/net/wireless/rtlwifi/wifi.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/net/wireless/rtlwifi/wifi.h	2012-04-13 12:42:02.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
 #include <net/mac80211.h>
+#include <linux/completion.h>
 #include "debug.h"
 
 #define RF_CHANGE_BY_INIT			0
@@ -1045,7 +1046,6 @@
 	u16 fw_subversion;
 	bool h2c_setinprogress;
 	u8 last_hmeboxnum;
-	bool fw_ready;
 	/*Reserve page start offset except beacon in TxQ. */
 	u8 fw_rsvdpage_startoffset;
 	u8 h2c_txcmd_seq;
@@ -1591,6 +1591,7 @@
 };
 
 struct rtl_priv {
+	struct completion firmware_loading_complete;
 	struct rtl_locks locks;
 	struct rtl_works works;
 	struct rtl_mac mac80211;
@@ -1612,6 +1613,7 @@
 	struct rtl_rate_priv *rate_priv;
 
 	struct rtl_debug dbg;
+	int max_fw_size;
 
 	/*
 	 *hal_cfg : for diff cards
diff -druN linux-libre-3.3-gnu/drivers/pci/pcie/aspm.c linux-libre-3.3.2-gnu/drivers/pci/pcie/aspm.c
--- linux-libre-3.3-gnu/drivers/pci/pcie/aspm.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/pci/pcie/aspm.c	2012-04-13 12:42:02.000000000 -0400
@@ -500,9 +500,6 @@
 	int pos;
 	u32 reg32;
 
-	if (aspm_disabled)
-		return 0;
-
 	/*
 	 * Some functions in a slot might not all be PCIe functions,
 	 * very strange. Disable ASPM for the whole slot
@@ -511,6 +508,16 @@
 		pos = pci_pcie_cap(child);
 		if (!pos)
 			return -EINVAL;
+
+		/*
+		 * If ASPM is disabled then we're not going to change
+		 * the BIOS state. It's safe to continue even if it's a
+		 * pre-1.1 device
+		 */
+
+		if (aspm_disabled)
+			continue;
+
 		/*
 		 * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
 		 * RBER bit to determine if a function is 1.1 version device
diff -druN linux-libre-3.3-gnu/drivers/platform/x86/acer-wmi.c linux-libre-3.3.2-gnu/drivers/platform/x86/acer-wmi.c
--- linux-libre-3.3-gnu/drivers/platform/x86/acer-wmi.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/platform/x86/acer-wmi.c	2012-04-13 12:42:02.000000000 -0400
@@ -692,6 +692,7 @@
 	{ "VPC2004", 0},
 	{ "IBM0068", 0},
 	{ "LEN0068", 0},
+	{ "SNY5001", 0},	/* sony-laptop in charge */
 	{ "", 0},
 };
 
diff -druN linux-libre-3.3-gnu/drivers/pnp/pnpacpi/core.c linux-libre-3.3.2-gnu/drivers/pnp/pnpacpi/core.c
--- linux-libre-3.3-gnu/drivers/pnp/pnpacpi/core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/pnp/pnpacpi/core.c	2012-04-13 12:42:02.000000000 -0400
@@ -321,9 +321,14 @@
 {
 	struct acpi_device *acpi = to_acpi_device(dev);
 	struct pnp_dev *pnp = _pnp;
+	struct device *physical_device;
+
+	physical_device = acpi_get_physical_device(acpi->handle);
+	if (physical_device)
+		put_device(physical_device);
 
 	/* true means it matched */
-	return !acpi_get_physical_device(acpi->handle)
+	return !physical_device
 	    && compare_pnp_id(pnp->id, acpi_device_hid(acpi));
 }
 
diff -druN linux-libre-3.3-gnu/drivers/rtc/interface.c linux-libre-3.3.2-gnu/drivers/rtc/interface.c
--- linux-libre-3.3-gnu/drivers/rtc/interface.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/rtc/interface.c	2012-04-13 12:42:02.000000000 -0400
@@ -445,6 +445,11 @@
 	if (rtc->uie_rtctimer.enabled == enabled)
 		goto out;
 
+	if (rtc->uie_unsupported) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	if (enabled) {
 		struct rtc_time tm;
 		ktime_t now, onesec;
@@ -763,6 +768,14 @@
 	return 0;
 }
 
+static void rtc_alarm_disable(struct rtc_device *rtc)
+{
+	if (!rtc->ops || !rtc->ops->alarm_irq_enable)
+		return;
+
+	rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
+}
+
 /**
  * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
  * @rtc rtc device
@@ -784,8 +797,10 @@
 		struct rtc_wkalrm alarm;
 		int err;
 		next = timerqueue_getnext(&rtc->timerqueue);
-		if (!next)
+		if (!next) {
+			rtc_alarm_disable(rtc);
 			return;
+		}
 		alarm.time = rtc_ktime_to_tm(next->expires);
 		alarm.enabled = 1;
 		err = __rtc_set_alarm(rtc, &alarm);
@@ -847,7 +862,8 @@
 		err = __rtc_set_alarm(rtc, &alarm);
 		if (err == -ETIME)
 			goto again;
-	}
+	} else
+		rtc_alarm_disable(rtc);
 
 	mutex_unlock(&rtc->ops_lock);
 }
diff -druN linux-libre-3.3-gnu/drivers/rtc/rtc-mpc5121.c linux-libre-3.3.2-gnu/drivers/rtc/rtc-mpc5121.c
--- linux-libre-3.3-gnu/drivers/rtc/rtc-mpc5121.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/rtc/rtc-mpc5121.c	2012-04-13 12:42:02.000000000 -0400
@@ -360,6 +360,8 @@
 						&mpc5200_rtc_ops, THIS_MODULE);
 	}
 
+	rtc->rtc->uie_unsupported = 1;
+
 	if (IS_ERR(rtc->rtc)) {
 		err = PTR_ERR(rtc->rtc);
 		goto out_free_irq;
diff -druN linux-libre-3.3-gnu/drivers/scsi/scsi_transport_iscsi.c linux-libre-3.3.2-gnu/drivers/scsi/scsi_transport_iscsi.c
--- linux-libre-3.3-gnu/drivers/scsi/scsi_transport_iscsi.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/scsi/scsi_transport_iscsi.c	2012-04-13 12:42:02.000000000 -0400
@@ -1941,7 +1941,7 @@
 	switch (nlh->nlmsg_type) {
 	case ISCSI_UEVENT_CREATE_SESSION:
 		err = iscsi_if_create_session(priv, ep, ev,
-					      NETLINK_CREDS(skb)->pid,
+					      NETLINK_CB(skb).pid,
 					      ev->u.c_session.initial_cmdsn,
 					      ev->u.c_session.cmds_max,
 					      ev->u.c_session.queue_depth);
@@ -1954,7 +1954,7 @@
 		}
 
 		err = iscsi_if_create_session(priv, ep, ev,
-					NETLINK_CREDS(skb)->pid,
+					NETLINK_CB(skb).pid,
 					ev->u.c_bound_session.initial_cmdsn,
 					ev->u.c_bound_session.cmds_max,
 					ev->u.c_bound_session.queue_depth);
diff -druN linux-libre-3.3-gnu/drivers/staging/android/lowmemorykiller.c linux-libre-3.3.2-gnu/drivers/staging/android/lowmemorykiller.c
--- linux-libre-3.3-gnu/drivers/staging/android/lowmemorykiller.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/android/lowmemorykiller.c	2012-04-13 12:42:02.000000000 -0400
@@ -53,7 +53,6 @@
 };
 static int lowmem_minfree_size = 4;
 
-static struct task_struct *lowmem_deathpending;
 static unsigned long lowmem_deathpending_timeout;
 
 #define lowmem_print(level, x...)			\
@@ -62,24 +61,6 @@
 			printk(x);			\
 	} while (0)
 
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data);
-
-static struct notifier_block task_nb = {
-	.notifier_call	= task_notify_func,
-};
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data)
-{
-	struct task_struct *task = data;
-	if (task == lowmem_deathpending) {
-		lowmem_deathpending = NULL;
-		task_handoff_unregister(&task_nb);
-	}
-	return NOTIFY_OK;
-}
-
 static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 {
 	struct task_struct *p;
@@ -95,19 +76,6 @@
 	int other_file = global_page_state(NR_FILE_PAGES) -
 						global_page_state(NR_SHMEM);
 
-	/*
-	 * If we already have a death outstanding, then
-	 * bail out right away; indicating to vmscan
-	 * that we have nothing further to offer on
-	 * this pass.
-	 *
-	 * Note: Currently you need CONFIG_PROFILING
-	 * for this to work correctly.
-	 */
-	if (lowmem_deathpending &&
-	    time_before_eq(jiffies, lowmem_deathpending_timeout))
-		return 0;
-
 	if (lowmem_adj_size < array_size)
 		array_size = lowmem_adj_size;
 	if (lowmem_minfree_size < array_size)
@@ -140,6 +108,11 @@
 		struct signal_struct *sig;
 		int oom_adj;
 
+		if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
+		    time_before_eq(jiffies, lowmem_deathpending_timeout)) {
+			read_unlock(&tasklist_lock);
+			return 0;
+		}
 		task_lock(p);
 		mm = p->mm;
 		sig = p->signal;
@@ -173,17 +146,9 @@
 		lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
 			     selected->pid, selected->comm,
 			     selected_oom_adj, selected_tasksize);
-		/*
-		 * If CONFIG_PROFILING is off, then task_handoff_register()
-		 * is a nop. In that case we don't want to stall the killer
-		 * by setting lowmem_deathpending.
-		 */
-#ifdef CONFIG_PROFILING
-		lowmem_deathpending = selected;
 		lowmem_deathpending_timeout = jiffies + HZ;
-		task_handoff_register(&task_nb);
-#endif
 		force_sig(SIGKILL, selected);
+		set_tsk_thread_flag(selected, TIF_MEMDIE);
 		rem -= selected_tasksize;
 	}
 	lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
diff -druN linux-libre-3.3-gnu/drivers/staging/media/as102/as102_fw.h linux-libre-3.3.2-gnu/drivers/staging/media/as102/as102_fw.h
--- linux-libre-3.3-gnu/drivers/staging/media/as102/as102_fw.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/media/as102/as102_fw.h	2012-04-13 12:42:02.000000000 -0400
@@ -29,7 +29,7 @@
 	union {
 		unsigned char request[2];
 		unsigned char length[2];
-	} u;
+	} __packed u;
 	struct as10x_raw_fw_pkt raw;
 } __packed;
 
diff -druN linux-libre-3.3-gnu/drivers/staging/media/as102/as10x_cmd.h linux-libre-3.3.2-gnu/drivers/staging/media/as102/as10x_cmd.h
--- linux-libre-3.3-gnu/drivers/staging/media/as102/as10x_cmd.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/media/as102/as10x_cmd.h	2012-04-13 12:42:02.000000000 -0400
@@ -99,14 +99,14 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_turn_off {
@@ -114,14 +114,14 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t err;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_set_tune {
@@ -131,14 +131,14 @@
 		uint16_t proc_id;
 		/* tune params */
 		struct as10x_tune_args args;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* response error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_get_tune_status {
@@ -146,7 +146,7 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -155,7 +155,7 @@
 		uint8_t error;
 		/* tune status */
 		struct as10x_tune_status sts;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_get_tps {
@@ -163,7 +163,7 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -172,7 +172,7 @@
 		uint8_t error;
 		/* tps details */
 		struct as10x_tps tps;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_common {
@@ -180,14 +180,14 @@
 	struct {
 		/* request identifier */
 		uint16_t  proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* response error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_add_pid_filter {
@@ -201,7 +201,7 @@
 		uint8_t stream_type;
 		/* PID index in filter table */
 		uint8_t idx;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -210,7 +210,7 @@
 		uint8_t error;
 		/* Filter id */
 		uint8_t filter_id;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_del_pid_filter {
@@ -220,14 +220,14 @@
 		uint16_t  proc_id;
 		/* PID to remove */
 		uint16_t  pid;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* response error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_start_streaming {
@@ -235,14 +235,14 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_stop_streaming {
@@ -250,14 +250,14 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_get_demod_stats {
@@ -265,7 +265,7 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -274,7 +274,7 @@
 		uint8_t error;
 		/* demod stats */
 		struct as10x_demod_stats stats;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_get_impulse_resp {
@@ -282,7 +282,7 @@
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -291,7 +291,7 @@
 		uint8_t error;
 		/* impulse response ready */
 		uint8_t is_ready;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_fw_context {
@@ -305,7 +305,7 @@
 		uint16_t tag;
 		/* context request type */
 		uint16_t type;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -316,7 +316,7 @@
 		uint16_t type;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_set_register {
@@ -328,14 +328,14 @@
 		struct as10x_register_addr reg_addr;
 		/* register content */
 		struct as10x_register_value reg_val;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_get_register {
@@ -345,7 +345,7 @@
 		uint16_t proc_id;
 		/* register description */
 		struct as10x_register_addr reg_addr;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -354,7 +354,7 @@
 		uint8_t error;
 		/* register content */
 		struct as10x_register_value reg_val;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_cfg_change_mode {
@@ -364,14 +364,14 @@
 		uint16_t proc_id;
 		/* mode */
 		uint8_t mode;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
 		uint16_t proc_id;
 		/* error */
 		uint8_t error;
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 struct as10x_cmd_header_t {
@@ -394,7 +394,7 @@
 		struct as10x_register_addr reg_addr;
 		/* nb blocks to read */
 		uint16_t num_blocks;
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		/* response identifier */
@@ -408,8 +408,8 @@
 			uint8_t  data8[DUMP_BLOCK_SIZE];
 			uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
 			uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
-		} u;
-	} rsp;
+		} __packed u;
+	} __packed rsp;
 } __packed;
 
 union as10x_dumplog_memory {
@@ -418,7 +418,7 @@
 		uint16_t proc_id;
 		/* dump memory type request */
 		uint8_t dump_req;
-	} req;
+	} __packed req;
 	struct {
 		/* request identifier */
 		uint16_t proc_id;
@@ -428,7 +428,7 @@
 		uint8_t dump_rsp;
 		/* dump data */
 		uint8_t data[DUMP_BLOCK_SIZE];
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 union as10x_raw_data {
@@ -437,14 +437,14 @@
 		uint16_t proc_id;
 		uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
 			     - 2 /* proc_id */];
-	} req;
+	} __packed req;
 	/* response */
 	struct {
 		uint16_t proc_id;
 		uint8_t error;
 		uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
 			     - 2 /* proc_id */ - 1 /* rc */];
-	} rsp;
+	} __packed rsp;
 } __packed;
 
 struct as10x_cmd_t {
@@ -469,7 +469,7 @@
 		union as10x_dump_memory		dump_memory;
 		union as10x_dumplog_memory	dumplog_memory;
 		union as10x_raw_data		raw_data;
-	} body;
+	} __packed body;
 } __packed;
 
 struct as10x_token_cmd_t {
diff -druN linux-libre-3.3-gnu/drivers/staging/media/as102/as10x_types.h linux-libre-3.3.2-gnu/drivers/staging/media/as102/as10x_types.h
--- linux-libre-3.3-gnu/drivers/staging/media/as102/as10x_types.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/media/as102/as10x_types.h	2012-04-13 12:42:02.000000000 -0400
@@ -181,7 +181,7 @@
 		uint8_t  value8;   /* 8 bit value */
 		uint16_t value16;  /* 16 bit value */
 		uint32_t value32;  /* 32 bit value */
-	} u;
+	} __packed u;
 } __packed;
 
 struct as10x_register_addr {
diff -druN linux-libre-3.3-gnu/drivers/staging/octeon/ethernet-mdio.c linux-libre-3.3.2-gnu/drivers/staging/octeon/ethernet-mdio.c
--- linux-libre-3.3-gnu/drivers/staging/octeon/ethernet-mdio.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/octeon/ethernet-mdio.c	2012-04-13 12:42:02.000000000 -0400
@@ -164,9 +164,9 @@
 
 	int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
 	if (phy_addr != -1) {
-		char phy_id[20];
+		char phy_id[MII_BUS_ID_SIZE + 3];
 
-		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr);
 
 		priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
 					PHY_INTERFACE_MODE_GMII);
diff -druN linux-libre-3.3-gnu/drivers/staging/rtl8712/Kconfig linux-libre-3.3.2-gnu/drivers/staging/rtl8712/Kconfig
--- linux-libre-3.3-gnu/drivers/staging/rtl8712/Kconfig	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/rtl8712/Kconfig	2012-04-13 12:42:02.000000000 -0400
@@ -9,13 +9,6 @@
 	This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130.
 	If built as a module, it will be called r8712u.
 
-config R8712_AP
-	bool "Realtek RTL8712U AP code"
-	depends on R8712U
-	default N
-	---help---
-	This option allows the Realtek RTL8712 USB device to be an Access Point.
-
 config R8712_TX_AGGR
 	bool "Realtek RTL8712U Transmit Aggregation code"
 	depends on R8712U && BROKEN
diff -druN linux-libre-3.3-gnu/drivers/staging/rtl8712/os_intfs.c linux-libre-3.3.2-gnu/drivers/staging/rtl8712/os_intfs.c
--- linux-libre-3.3-gnu/drivers/staging/rtl8712/os_intfs.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/rtl8712/os_intfs.c	2012-04-13 12:42:02.000000000 -0400
@@ -476,8 +476,6 @@
 	r8712_free_assoc_resources(padapter);
 	/*s2-4.*/
 	r8712_free_network_queue(padapter);
-	/* The interface is no longer Up: */
-	padapter->bup = false;
 	release_firmware(padapter->fw);
 	/* never exit with a firmware callback pending */
 	wait_for_completion(&padapter->rtl8712_fw_ready);
diff -druN linux-libre-3.3-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c linux-libre-3.3.2-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
--- linux-libre-3.3-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c	2012-04-13 12:42:02.000000000 -0400
@@ -2380,13 +2380,7 @@
 		tmp_qual = padapter->recvpriv.signal;
 		tmp_noise = padapter->recvpriv.noise;
 		piwstats->qual.level = tmp_level;
-		/*piwstats->qual.qual = tmp_qual;
-		 * The NetworkManager of Fedora 10, 13 will use the link
-		 * quality for its display.
-		 * So, use the fw_rssi on link quality variable because
-		 * fw_rssi will be updated per 2 seconds.
-		 */
-		piwstats->qual.qual = tmp_level;
+		piwstats->qual.qual = tmp_qual;
 		piwstats->qual.noise = tmp_noise;
 	}
 	piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
diff -druN linux-libre-3.3-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c linux-libre-3.3.2-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c
--- linux-libre-3.3-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c	2012-04-13 12:42:02.000000000 -0400
@@ -42,10 +42,8 @@
 	_init_listhead(&psta->hash_list);
 	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
 	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
-#ifdef CONFIG_R8712_AP
 	_init_listhead(&psta->asoc_list);
 	_init_listhead(&psta->auth_list);
-#endif
 }
 
 u32 _r8712_init_sta_priv(struct	sta_priv *pstapriv)
@@ -72,10 +70,8 @@
 				 get_list_head(&pstapriv->free_sta_queue));
 		psta++;
 	}
-#ifdef CONFIG_R8712_AP
 	_init_listhead(&pstapriv->asoc_list);
 	_init_listhead(&pstapriv->auth_list);
-#endif
 	return _SUCCESS;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/staging/rtl8712/sta_info.h linux-libre-3.3.2-gnu/drivers/staging/rtl8712/sta_info.h
--- linux-libre-3.3-gnu/drivers/staging/rtl8712/sta_info.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/rtl8712/sta_info.h	2012-04-13 12:42:02.000000000 -0400
@@ -90,7 +90,6 @@
 	 * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO
 	 * sta_info: (AP & STA) CAP/INFO
 	 */
-#ifdef CONFIG_R8712_AP
 	struct list_head asoc_list;
 	struct list_head auth_list;
 	unsigned int expire_to;
@@ -98,7 +97,6 @@
 	unsigned int authalg;
 	unsigned char chg_txt[128];
 	unsigned int tx_ra_bitmap;
-#endif
 };
 
 struct	sta_priv {
@@ -111,13 +109,11 @@
 	struct  __queue sleep_q;
 	struct  __queue wakeup_q;
 	struct _adapter *padapter;
-#ifdef CONFIG_R8712_AP
 	struct list_head asoc_list;
 	struct list_head auth_list;
 	unsigned int auth_to;  /* sec, time to expire in authenticating. */
 	unsigned int assoc_to; /* sec, time to expire before associating. */
 	unsigned int expire_to; /* sec , time to expire after associated. */
-#endif
 };
 
 static inline u32 wifi_mac_hash(u8 *mac)
diff -druN linux-libre-3.3-gnu/drivers/staging/vme/devices/vme_pio2_gpio.c linux-libre-3.3.2-gnu/drivers/staging/vme/devices/vme_pio2_gpio.c
--- linux-libre-3.3-gnu/drivers/staging/vme/devices/vme_pio2_gpio.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/vme/devices/vme_pio2_gpio.c	2012-04-13 12:42:02.000000000 -0400
@@ -187,7 +187,7 @@
 	return 0;
 }
 
-int __init pio2_gpio_init(struct pio2_card *card)
+int __devinit pio2_gpio_init(struct pio2_card *card)
 {
 	int retval = 0;
 	char *label;
@@ -220,7 +220,7 @@
 	return retval;
 };
 
-void __exit pio2_gpio_exit(struct pio2_card *card)
+void pio2_gpio_exit(struct pio2_card *card)
 {
 	const char *label = card->gc.label;
 
diff -druN linux-libre-3.3-gnu/drivers/staging/vme/devices/vme_pio2.h linux-libre-3.3.2-gnu/drivers/staging/vme/devices/vme_pio2.h
--- linux-libre-3.3-gnu/drivers/staging/vme/devices/vme_pio2.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/vme/devices/vme_pio2.h	2012-04-13 12:42:02.000000000 -0400
@@ -243,7 +243,7 @@
 int pio2_cntr_reset(struct pio2_card *);
 
 int pio2_gpio_reset(struct pio2_card *);
-int __init pio2_gpio_init(struct pio2_card *);
-void __exit pio2_gpio_exit(struct pio2_card *);
+int __devinit pio2_gpio_init(struct pio2_card *);
+void pio2_gpio_exit(struct pio2_card *);
 
 #endif /* _VME_PIO2_H_ */
diff -druN linux-libre-3.3-gnu/drivers/staging/zcache/zcache-main.c linux-libre-3.3.2-gnu/drivers/staging/zcache/zcache-main.c
--- linux-libre-3.3-gnu/drivers/staging/zcache/zcache-main.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/staging/zcache/zcache-main.c	2012-04-13 12:42:02.000000000 -0400
@@ -299,10 +299,12 @@
 	struct zbud_page *zbpg =
 		container_of(zh, struct zbud_page, buddy[budnum]);
 
+	spin_lock(&zbud_budlists_spinlock);
 	spin_lock(&zbpg->lock);
 	if (list_empty(&zbpg->bud_list)) {
 		/* ignore zombie page... see zbud_evict_pages() */
 		spin_unlock(&zbpg->lock);
+		spin_unlock(&zbud_budlists_spinlock);
 		return;
 	}
 	size = zbud_free(zh);
@@ -310,7 +312,6 @@
 	zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0];
 	if (zh_other->size == 0) { /* was unbuddied: unlist and free */
 		chunks = zbud_size_to_chunks(size) ;
-		spin_lock(&zbud_budlists_spinlock);
 		BUG_ON(list_empty(&zbud_unbuddied[chunks].list));
 		list_del_init(&zbpg->bud_list);
 		zbud_unbuddied[chunks].count--;
@@ -318,7 +319,6 @@
 		zbud_free_raw_page(zbpg);
 	} else { /* was buddied: move remaining buddy to unbuddied list */
 		chunks = zbud_size_to_chunks(zh_other->size) ;
-		spin_lock(&zbud_budlists_spinlock);
 		list_del_init(&zbpg->bud_list);
 		zcache_zbud_buddied_count--;
 		list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list);
diff -druN linux-libre-3.3-gnu/drivers/target/iscsi/iscsi_target.c linux-libre-3.3.2-gnu/drivers/target/iscsi/iscsi_target.c
--- linux-libre-3.3-gnu/drivers/target/iscsi/iscsi_target.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/iscsi/iscsi_target.c	2012-04-13 12:42:02.000000000 -0400
@@ -780,7 +780,7 @@
 	struct scatterlist *sgl;
 	u32 length = cmd->se_cmd.data_length;
 	int nents = DIV_ROUND_UP(length, PAGE_SIZE);
-	int i = 0, ret;
+	int i = 0, j = 0, ret;
 	/*
 	 * If no SCSI payload is present, allocate the default iovecs used for
 	 * iSCSI PDU Header
@@ -821,17 +821,15 @@
 	 */
         ret = iscsit_allocate_iovecs(cmd);
         if (ret < 0)
-		goto page_alloc_failed;
+		return -ENOMEM;
 
 	return 0;
 
 page_alloc_failed:
-	while (i >= 0) {
-		__free_page(sg_page(&sgl[i]));
-		i--;
-	}
-	kfree(cmd->t_mem_sg);
-	cmd->t_mem_sg = NULL;
+	while (j < i)
+		__free_page(sg_page(&sgl[j++]));
+
+	kfree(sgl);
 	return -ENOMEM;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/target/iscsi/iscsi_target_configfs.c linux-libre-3.3.2-gnu/drivers/target/iscsi/iscsi_target_configfs.c
--- linux-libre-3.3-gnu/drivers/target/iscsi/iscsi_target_configfs.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/iscsi/iscsi_target_configfs.c	2012-04-13 12:42:02.000000000 -0400
@@ -812,9 +812,6 @@
 	if (!se_nacl_new)
 		return ERR_PTR(-ENOMEM);
 
-	acl = container_of(se_nacl_new, struct iscsi_node_acl,
-				se_node_acl);
-
 	cmdsn_depth = ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
 	/*
 	 * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
@@ -825,7 +822,8 @@
 	if (IS_ERR(se_nacl))
 		return se_nacl;
 
-	stats_cg = &acl->se_node_acl.acl_fabric_stat_group;
+	acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
+	stats_cg = &se_nacl->acl_fabric_stat_group;
 
 	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
diff -druN linux-libre-3.3-gnu/drivers/target/loopback/tcm_loop.c linux-libre-3.3.2-gnu/drivers/target/loopback/tcm_loop.c
--- linux-libre-3.3-gnu/drivers/target/loopback/tcm_loop.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/loopback/tcm_loop.c	2012-04-13 12:42:02.000000000 -0400
@@ -855,6 +855,9 @@
 
 	sc->result = SAM_STAT_GOOD;
 	set_host_byte(sc, DID_OK);
+	if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+	    (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+		scsi_set_resid(sc, se_cmd->residual_count);
 	sc->scsi_done(sc);
 	return 0;
 }
@@ -880,6 +883,9 @@
 		sc->result = se_cmd->scsi_status;
 
 	set_host_byte(sc, DID_OK);
+	if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+	    (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+		scsi_set_resid(sc, se_cmd->residual_count);
 	sc->scsi_done(sc);
 	return 0;
 }
diff -druN linux-libre-3.3-gnu/drivers/target/target_core_alua.c linux-libre-3.3.2-gnu/drivers/target/target_core_alua.c
--- linux-libre-3.3-gnu/drivers/target/target_core_alua.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/target_core_alua.c	2012-04-13 12:42:02.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/export.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
+#include <asm/unaligned.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
@@ -267,8 +268,7 @@
 		 * changed.
 		 */
 		if (primary) {
-			tg_pt_id = ((ptr[2] << 8) & 0xff);
-			tg_pt_id |= (ptr[3] & 0xff);
+			tg_pt_id = get_unaligned_be16(ptr + 2);
 			/*
 			 * Locate the matching target port group ID from
 			 * the global tg_pt_gp list
@@ -312,8 +312,7 @@
 			 * the Target Port in question for the the incoming
 			 * SET_TARGET_PORT_GROUPS op.
 			 */
-			rtpi = ((ptr[2] << 8) & 0xff);
-			rtpi |= (ptr[3] & 0xff);
+			rtpi = get_unaligned_be16(ptr + 2);
 			/*
 			 * Locate the matching relative target port identifer
 			 * for the struct se_device storage object.
diff -druN linux-libre-3.3-gnu/drivers/target/target_core_cdb.c linux-libre-3.3.2-gnu/drivers/target/target_core_cdb.c
--- linux-libre-3.3-gnu/drivers/target/target_core_cdb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/target_core_cdb.c	2012-04-13 12:42:02.000000000 -0400
@@ -66,32 +66,15 @@
 }
 
 static int
-target_emulate_inquiry_std(struct se_cmd *cmd)
+target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 {
 	struct se_lun *lun = cmd->se_lun;
 	struct se_device *dev = cmd->se_dev;
-	struct se_portal_group *tpg = lun->lun_sep->sep_tpg;
-	unsigned char *buf;
-
-	/*
-	 * Make sure we at least have 6 bytes of INQUIRY response
-	 * payload going back for EVPD=0
-	 */
-	if (cmd->data_length < 6) {
-		pr_err("SCSI Inquiry payload length: %u"
-			" too small for EVPD=0\n", cmd->data_length);
-		return -EINVAL;
-	}
 
-	buf = transport_kmap_data_sg(cmd);
+	/* Set RMB (removable media) for tape devices */
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
+		buf[1] = 0x80;
 
-	if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
-		buf[0] = 0x3f; /* Not connected */
-	} else {
-		buf[0] = dev->transport->get_device_type(dev);
-		if (buf[0] == TYPE_TAPE)
-			buf[1] = 0x80;
-	}
 	buf[2] = dev->transport->get_device_rev(dev);
 
 	/*
@@ -112,29 +95,13 @@
 	if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
 		target_fill_alua_data(lun->lun_sep, buf);
 
-	if (cmd->data_length < 8) {
-		buf[4] = 1; /* Set additional length to 1 */
-		goto out;
-	}
-
-	buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
-
-	/*
-	 * Do not include vendor, product, reversion info in INQUIRY
-	 * response payload for cdbs with a small allocation length.
-	 */
-	if (cmd->data_length < 36) {
-		buf[4] = 3; /* Set additional length to 3 */
-		goto out;
-	}
+	buf[7] = 0x2; /* CmdQue=1 */
 
 	snprintf(&buf[8], 8, "LIO-ORG");
 	snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
 	snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
 	buf[4] = 31; /* Set additional length to 31 */
 
-out:
-	transport_kunmap_data_sg(cmd);
 	return 0;
 }
 
@@ -152,12 +119,6 @@
 		unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
 		unit_serial_len++; /* For NULL Terminator */
 
-		if (((len + 4) + unit_serial_len) > cmd->data_length) {
-			len += unit_serial_len;
-			buf[2] = ((len >> 8) & 0xff);
-			buf[3] = (len & 0xff);
-			return 0;
-		}
 		len += sprintf(&buf[4], "%s",
 			dev->se_sub_dev->t10_wwn.unit_serial);
 		len++; /* Extra Byte for NULL Terminator */
@@ -229,9 +190,6 @@
 	if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL))
 		goto check_t10_vend_desc;
 
-	if (off + 20 > cmd->data_length)
-		goto check_t10_vend_desc;
-
 	/* CODE SET == Binary */
 	buf[off++] = 0x1;
 
@@ -283,12 +241,6 @@
 			strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 		unit_serial_len++; /* For NULL Terminator */
 
-		if ((len + (id_len + 4) +
-		    (prod_len + unit_serial_len)) >
-				cmd->data_length) {
-			len += (prod_len + unit_serial_len);
-			goto check_port;
-		}
 		id_len += sprintf(&buf[off+12], "%s:%s", prod,
 				&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 	}
@@ -306,7 +258,6 @@
 	/*
 	 * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD
 	 */
-check_port:
 	port = lun->lun_sep;
 	if (port) {
 		struct t10_alua_lu_gp *lu_gp;
@@ -323,10 +274,6 @@
 		 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 		 * section 7.5.1 Table 362
 		 */
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_tpgi;
-		}
 		buf[off] =
 			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x1; /* CODE SET == Binary */
@@ -350,15 +297,10 @@
 		 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 		 * section 7.5.1 Table 362
 		 */
-check_tpgi:
 		if (dev->se_sub_dev->t10_alua.alua_type !=
 				SPC3_ALUA_EMULATED)
 			goto check_scsi_name;
 
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_lu_gp;
-		}
 		tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
 		if (!tg_pt_gp_mem)
 			goto check_lu_gp;
@@ -391,10 +333,6 @@
 		 * section 7.7.3.8
 		 */
 check_lu_gp:
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_scsi_name;
-		}
 		lu_gp_mem = dev->dev_alua_lu_gp_mem;
 		if (!lu_gp_mem)
 			goto check_scsi_name;
@@ -435,10 +373,6 @@
 		/* Header size + Designation descriptor */
 		scsi_name_len += 4;
 
-		if (((len + 4) + scsi_name_len) > cmd->data_length) {
-			len += scsi_name_len;
-			goto set_len;
-		}
 		buf[off] =
 			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x3; /* CODE SET == UTF-8 */
@@ -474,7 +408,6 @@
 		/* Header size + Designation descriptor */
 		len += (scsi_name_len + 4);
 	}
-set_len:
 	buf[2] = ((len >> 8) & 0xff);
 	buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
 	return 0;
@@ -484,9 +417,6 @@
 static int
 target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 {
-	if (cmd->data_length < 60)
-		return 0;
-
 	buf[3] = 0x3c;
 	/* Set HEADSUP, ORDSUP, SIMPSUP */
 	buf[5] = 0x07;
@@ -512,20 +442,6 @@
 	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
 		have_tp = 1;
 
-	if (cmd->data_length < (0x10 + 4)) {
-		pr_debug("Received data_length: %u"
-			" too small for EVPD 0xb0\n",
-			cmd->data_length);
-		return -EINVAL;
-	}
-
-	if (have_tp && cmd->data_length < (0x3c + 4)) {
-		pr_debug("Received data_length: %u"
-			" too small for TPE=1 EVPD 0xb0\n",
-			cmd->data_length);
-		have_tp = 0;
-	}
-
 	buf[0] = dev->transport->get_device_type(dev);
 	buf[3] = have_tp ? 0x3c : 0x10;
 
@@ -548,10 +464,9 @@
 	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
 
 	/*
-	 * Exit now if we don't support TP or the initiator sent a too
-	 * short buffer.
+	 * Exit now if we don't support TP.
 	 */
-	if (!have_tp || cmd->data_length < (0x3c + 4))
+	if (!have_tp)
 		return 0;
 
 	/*
@@ -589,10 +504,7 @@
 
 	buf[0] = dev->transport->get_device_type(dev);
 	buf[3] = 0x3c;
-
-	if (cmd->data_length >= 5 &&
-	    dev->se_sub_dev->se_dev_attrib.is_nonrot)
-		buf[5] = 1;
+	buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0;
 
 	return 0;
 }
@@ -671,8 +583,6 @@
 {
 	int p;
 
-	if (cmd->data_length < 8)
-		return 0;
 	/*
 	 * Only report the INQUIRY EVPD=1 pages after a valid NAA
 	 * Registered Extended LUN WWN has been set via ConfigFS
@@ -681,8 +591,7 @@
 	if (cmd->se_dev->se_sub_dev->su_dev_flags &
 			SDF_EMULATED_VPD_UNIT_SERIAL) {
 		buf[3] = ARRAY_SIZE(evpd_handlers);
-		for (p = 0; p < min_t(int, ARRAY_SIZE(evpd_handlers),
-				      cmd->data_length - 4); ++p)
+		for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
 			buf[p + 4] = evpd_handlers[p].page;
 	}
 
@@ -693,45 +602,54 @@
 {
 	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = cmd->se_dev;
-	unsigned char *buf;
+	struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
+	unsigned char *buf, *map_buf;
 	unsigned char *cdb = cmd->t_task_cdb;
 	int p, ret;
 
+	map_buf = transport_kmap_data_sg(cmd);
+	/*
+	 * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
+	 * know we actually allocated a full page.  Otherwise, if the
+	 * data buffer is too small, allocate a temporary buffer so we
+	 * don't have to worry about overruns in all our INQUIRY
+	 * emulation handling.
+	 */
+	if (cmd->data_length < SE_INQUIRY_BUF &&
+	    (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
+		buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
+		if (!buf) {
+			transport_kunmap_data_sg(cmd);
+			cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			return -ENOMEM;
+		}
+	} else {
+		buf = map_buf;
+	}
+
+	if (dev == tpg->tpg_virt_lun0.lun_se_dev)
+		buf[0] = 0x3f; /* Not connected */
+	else
+		buf[0] = dev->transport->get_device_type(dev);
+
 	if (!(cdb[1] & 0x1)) {
 		if (cdb[2]) {
 			pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
 			       cdb[2]);
 			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 
-		ret = target_emulate_inquiry_std(cmd);
+		ret = target_emulate_inquiry_std(cmd, buf);
 		goto out;
 	}
 
-	/*
-	 * Make sure we at least have 4 bytes of INQUIRY response
-	 * payload for 0x00 going back for EVPD=1.  Note that 0x80
-	 * and 0x83 will check for enough payload data length and
-	 * jump to set_len: label when there is not enough inquiry EVPD
-	 * payload length left for the next outgoing EVPD metadata
-	 */
-	if (cmd->data_length < 4) {
-		pr_err("SCSI Inquiry payload length: %u"
-			" too small for EVPD=1\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
-
-	buf = transport_kmap_data_sg(cmd);
-
-	buf[0] = dev->transport->get_device_type(dev);
-
 	for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) {
 		if (cdb[2] == evpd_handlers[p].page) {
 			buf[1] = cdb[2];
 			ret = evpd_handlers[p].emulate(cmd, buf);
-			goto out_unmap;
+			goto out;
 		}
 	}
 
@@ -739,9 +657,13 @@
 	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
 	ret = -EINVAL;
 
-out_unmap:
-	transport_kunmap_data_sg(cmd);
 out:
+	if (buf != map_buf) {
+		memcpy(map_buf, buf, cmd->data_length);
+		kfree(buf);
+	}
+	transport_kunmap_data_sg(cmd);
+
 	if (!ret) {
 		task->task_scsi_status = GOOD;
 		transport_complete_task(task, 1);
diff -druN linux-libre-3.3-gnu/drivers/target/target_core_device.c linux-libre-3.3.2-gnu/drivers/target/target_core_device.c
--- linux-libre-3.3-gnu/drivers/target/target_core_device.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/target_core_device.c	2012-04-13 12:42:02.000000000 -0400
@@ -657,7 +657,9 @@
 	unsigned char *buf;
 	u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
 
-	buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
+	buf = transport_kmap_data_sg(se_cmd);
+	if (!buf)
+		return -ENOMEM;
 
 	/*
 	 * If no struct se_session pointer is present, this struct se_cmd is
@@ -695,12 +697,12 @@
 	 * See SPC3 r07, page 159.
 	 */
 done:
-	transport_kunmap_data_sg(se_cmd);
 	lun_count *= 8;
 	buf[0] = ((lun_count >> 24) & 0xff);
 	buf[1] = ((lun_count >> 16) & 0xff);
 	buf[2] = ((lun_count >> 8) & 0xff);
 	buf[3] = (lun_count & 0xff);
+	transport_kunmap_data_sg(se_cmd);
 
 	se_task->task_scsi_status = GOOD;
 	transport_complete_task(se_task, 1);
diff -druN linux-libre-3.3-gnu/drivers/target/tcm_fc/tcm_fc.h linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tcm_fc.h
--- linux-libre-3.3-gnu/drivers/target/tcm_fc/tcm_fc.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tcm_fc.h	2012-04-13 12:42:02.000000000 -0400
@@ -124,6 +124,7 @@
 	/* Local sense buffer */
 	unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
 	u32 was_ddp_setup:1;		/* Set only if ddp is setup */
+	u32 aborted:1;			/* Set if aborted by reset or timeout */
 	struct scatterlist *sg;		/* Set only if DDP is setup */
 	u32 sg_cnt;			/* No. of item in scatterlist */
 };
diff -druN linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_cmd.c linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_cmd.c
--- linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_cmd.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_cmd.c	2012-04-13 12:42:02.000000000 -0400
@@ -126,6 +126,8 @@
 	struct fc_exch *ep;
 	size_t len;
 
+	if (cmd->aborted)
+		return 0;
 	ft_dump_cmd(cmd, __func__);
 	ep = fc_seq_exch(cmd->seq);
 	lport = ep->lp;
@@ -192,6 +194,8 @@
 
 	ft_dump_cmd(cmd, __func__);
 
+	if (cmd->aborted)
+		return 0;
 	ep = fc_seq_exch(cmd->seq);
 	lport = ep->lp;
 	fp = fc_frame_alloc(lport, sizeof(*txrdy));
@@ -262,10 +266,10 @@
 	struct ft_cmd *cmd = arg;
 	struct fc_frame_header *fh;
 
-	if (IS_ERR(fp)) {
+	if (unlikely(IS_ERR(fp))) {
 		/* XXX need to find cmd if queued */
 		cmd->seq = NULL;
-		transport_generic_free_cmd(&cmd->se_cmd, 0);
+		cmd->aborted = true;
 		return;
 	}
 
@@ -325,10 +329,12 @@
 
 	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
 	sp = fr_seq(fp);
-	if (sp)
+	if (sp) {
 		lport->tt.seq_send(lport, sp, fp);
-	else
+		lport->tt.exch_done(sp);
+	} else {
 		lport->tt.frame_send(lport, fp);
+	}
 }
 
 /*
@@ -445,6 +451,8 @@
 	struct se_tmr_req *tmr = se_cmd->se_tmr_req;
 	enum fcp_resp_rsp_codes code;
 
+	if (cmd->aborted)
+		return 0;
 	switch (tmr->response) {
 	case TMR_FUNCTION_COMPLETE:
 		code = FCP_TMF_CMPL;
diff -druN linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_conf.c linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_conf.c
--- linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_conf.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_conf.c	2012-04-13 12:42:02.000000000 -0400
@@ -300,6 +300,7 @@
 {
 	struct ft_lport_acl *lacl;
 	struct ft_tpg *tpg;
+	struct workqueue_struct *wq;
 	unsigned long index;
 	int ret;
 
@@ -321,18 +322,20 @@
 	tpg->lport_acl = lacl;
 	INIT_LIST_HEAD(&tpg->lun_list);
 
-	ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
-				tpg, TRANSPORT_TPG_TYPE_NORMAL);
-	if (ret < 0) {
+	wq = alloc_workqueue("tcm_fc", 0, 1);
+	if (!wq) {
 		kfree(tpg);
 		return NULL;
 	}
 
-	tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1);
-	if (!tpg->workqueue) {
+	ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+				tpg, TRANSPORT_TPG_TYPE_NORMAL);
+	if (ret < 0) {
+		destroy_workqueue(wq);
 		kfree(tpg);
 		return NULL;
 	}
+	tpg->workqueue = wq;
 
 	mutex_lock(&ft_lport_lock);
 	list_add_tail(&tpg->list, &lacl->tpg_list);
diff -druN linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_io.c linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_io.c
--- linux-libre-3.3-gnu/drivers/target/tcm_fc/tfc_io.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/target/tcm_fc/tfc_io.c	2012-04-13 12:42:02.000000000 -0400
@@ -81,6 +81,8 @@
 	void *from;
 	void *to = NULL;
 
+	if (cmd->aborted)
+		return 0;
 	ep = fc_seq_exch(cmd->seq);
 	lport = ep->lp;
 	cmd->seq = lport->tt.seq_start_next(cmd->seq);
diff -druN linux-libre-3.3-gnu/drivers/tty/moxa.c linux-libre-3.3.2-gnu/drivers/tty/moxa.c
--- linux-libre-3.3-gnu/drivers/tty/moxa.c	2012-03-19 01:11:40.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/tty/moxa.c	2012-04-13 22:55:44.000000000 -0400
@@ -1329,7 +1329,7 @@
 	if (ch == NULL)
 		return;
 
-	if (!(ch->statusflags & TXSTOPPED))
+	if (!test_bit(TXSTOPPED, &ch->statusflags))
 		return;
 
 	MoxaPortTxEnable(ch);
diff -druN linux-libre-3.3-gnu/drivers/tty/serial/omap-serial.c linux-libre-3.3.2-gnu/drivers/tty/serial/omap-serial.c
--- linux-libre-3.3-gnu/drivers/tty/serial/omap-serial.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/tty/serial/omap-serial.c	2012-04-13 12:42:02.000000000 -0400
@@ -159,7 +159,7 @@
 		serial_out(up, UART_IER, up->ier);
 	}
 
-	if (!up->use_dma && pdata->set_forceidle)
+	if (!up->use_dma && pdata && pdata->set_forceidle)
 		pdata->set_forceidle(up->pdev);
 
 	pm_runtime_mark_last_busy(&up->pdev->dev);
@@ -298,7 +298,7 @@
 	if (!up->use_dma) {
 		pm_runtime_get_sync(&up->pdev->dev);
 		serial_omap_enable_ier_thri(up);
-		if (pdata->set_noidle)
+		if (pdata && pdata->set_noidle)
 			pdata->set_noidle(up->pdev);
 		pm_runtime_mark_last_busy(&up->pdev->dev);
 		pm_runtime_put_autosuspend(&up->pdev->dev);
@@ -1613,7 +1613,7 @@
 	struct uart_omap_port *up = dev_get_drvdata(dev);
 	struct omap_uart_port_info *pdata = dev->platform_data;
 
-	if (up) {
+	if (up && pdata) {
 		if (pdata->get_context_loss_count) {
 			u32 loss_cnt = pdata->get_context_loss_count(dev);
 
diff -druN linux-libre-3.3-gnu/drivers/tty/serial/sh-sci.c linux-libre-3.3.2-gnu/drivers/tty/serial/sh-sci.c
--- linux-libre-3.3-gnu/drivers/tty/serial/sh-sci.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/tty/serial/sh-sci.c	2012-04-13 12:42:02.000000000 -0400
@@ -1229,17 +1229,20 @@
 	port->icount.tx += sg_dma_len(&s->sg_tx);
 
 	async_tx_ack(s->desc_tx);
-	s->cookie_tx = -EINVAL;
 	s->desc_tx = NULL;
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
 
 	if (!uart_circ_empty(xmit)) {
+		s->cookie_tx = 0;
 		schedule_work(&s->work_tx);
-	} else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-		u16 ctrl = sci_in(port, SCSCR);
-		sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+	} else {
+		s->cookie_tx = -EINVAL;
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+			u16 ctrl = sci_in(port, SCSCR);
+			sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+		}
 	}
 
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -1501,8 +1504,10 @@
 	}
 
 	if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
-	    s->cookie_tx < 0)
+	    s->cookie_tx < 0) {
+		s->cookie_tx = 0;
 		schedule_work(&s->work_tx);
+	}
 #endif
 
 	if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
diff -druN linux-libre-3.3-gnu/drivers/tty/vt/consolemap.c linux-libre-3.3.2-gnu/drivers/tty/vt/consolemap.c
--- linux-libre-3.3-gnu/drivers/tty/vt/consolemap.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/tty/vt/consolemap.c	2012-04-13 12:42:02.000000000 -0400
@@ -516,6 +516,7 @@
 	int err = 0, err1, i;
 	struct uni_pagedir *p, *q;
 
+	/* Save original vc_unipagdir_loc in case we allocate a new one */
 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	if (p->readonly) return -EIO;
 	
@@ -528,26 +529,57 @@
 		err1 = con_clear_unimap(vc, NULL);
 		if (err1) return err1;
 		
+		/*
+		 * Since refcount was > 1, con_clear_unimap() allocated a
+		 * a new uni_pagedir for this vc.  Re: p != q
+		 */
 		q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
-		for (i = 0, l = 0; i < 32; i++)
+
+		/*
+		 * uni_pgdir is a 32*32*64 table with rows allocated
+		 * when its first entry is added.  The unicode value must
+		 * still be incremented for empty rows.  We are copying
+		 * entries from "p" (old) to "q" (new).
+		 */
+		l = 0;		/* unicode value */
+		for (i = 0; i < 32; i++)
 		if ((p1 = p->uni_pgdir[i]))
 			for (j = 0; j < 32; j++)
-			if ((p2 = p1[j]))
+			if ((p2 = p1[j])) {
 				for (k = 0; k < 64; k++, l++)
 				if (p2[k] != 0xffff) {
+					/*
+					 * Found one, copy entry for unicode
+					 * l with fontpos value p2[k].
+					 */
 					err1 = con_insert_unipair(q, l, p2[k]);
 					if (err1) {
 						p->refcount++;
 						*vc->vc_uni_pagedir_loc = (unsigned long)p;
 						con_release_unimap(q);
 						kfree(q);
-						return err1; 
+						return err1;
 					}
-              			}
-              	p = q;
-	} else if (p == dflt)
+				}
+			} else {
+				/* Account for row of 64 empty entries */
+				l += 64;
+			}
+		else
+			/* Account for empty table */
+			l += 32 * 64;
+
+		/*
+		 * Finished copying font table, set vc_uni_pagedir to new table
+		 */
+		p = q;
+	} else if (p == dflt) {
 		dflt = NULL;
-	
+	}
+
+	/*
+	 * Insert user specified unicode pairs into new table.
+	 */
 	while (ct--) {
 		unsigned short unicode, fontpos;
 		__get_user(unicode, &list->unicode);
@@ -557,11 +589,14 @@
 		list++;
 	}
 	
+	/*
+	 * Merge with fontmaps of any other virtual consoles.
+	 */
 	if (con_unify_unimap(vc, p))
 		return err;
 
 	for (i = 0; i <= 3; i++)
-		set_inverse_transl(vc, p, i); /* Update all inverse translations */
+		set_inverse_transl(vc, p, i); /* Update inverse translations */
 	set_inverse_trans_unicode(vc, p);
   
 	return err;
diff -druN linux-libre-3.3-gnu/drivers/usb/class/cdc-wdm.c linux-libre-3.3.2-gnu/drivers/usb/class/cdc-wdm.c
--- linux-libre-3.3-gnu/drivers/usb/class/cdc-wdm.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/class/cdc-wdm.c	2012-04-13 12:42:02.000000000 -0400
@@ -397,7 +397,7 @@
 static ssize_t wdm_read
 (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	int rv, cntr = 0;
+	int rv, cntr;
 	int i = 0;
 	struct wdm_device *desc = file->private_data;
 
@@ -406,7 +406,8 @@
 	if (rv < 0)
 		return -ERESTARTSYS;
 
-	if (desc->length == 0) {
+	cntr = ACCESS_ONCE(desc->length);
+	if (cntr == 0) {
 		desc->read = 0;
 retry:
 		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -456,26 +457,30 @@
 			spin_unlock_irq(&desc->iuspin);
 			goto retry;
 		}
-		clear_bit(WDM_READ, &desc->flags);
+		cntr = desc->length;
 		spin_unlock_irq(&desc->iuspin);
 	}
 
-	cntr = count > desc->length ? desc->length : count;
+	if (cntr > count)
+		cntr = count;
 	rv = copy_to_user(buffer, desc->ubuf, cntr);
 	if (rv > 0) {
 		rv = -EFAULT;
 		goto err;
 	}
 
+	spin_lock_irq(&desc->iuspin);
+
 	for (i = 0; i < desc->length - cntr; i++)
 		desc->ubuf[i] = desc->ubuf[i + cntr];
 
-	spin_lock_irq(&desc->iuspin);
 	desc->length -= cntr;
-	spin_unlock_irq(&desc->iuspin);
 	/* in case we had outstanding data */
 	if (!desc->length)
 		clear_bit(WDM_READ, &desc->flags);
+
+	spin_unlock_irq(&desc->iuspin);
+
 	rv = cntr;
 
 err:
diff -druN linux-libre-3.3-gnu/drivers/usb/dwc3/core.c linux-libre-3.3.2-gnu/drivers/usb/dwc3/core.c
--- linux-libre-3.3-gnu/drivers/usb/dwc3/core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/dwc3/core.c	2012-04-13 12:42:02.000000000 -0400
@@ -86,7 +86,7 @@
 		id = -ENOMEM;
 	}
 
-	return 0;
+	return id;
 }
 EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 
diff -druN linux-libre-3.3-gnu/drivers/usb/dwc3/gadget.c linux-libre-3.3.2-gnu/drivers/usb/dwc3/gadget.c
--- linux-libre-3.3-gnu/drivers/usb/dwc3/gadget.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/dwc3/gadget.c	2012-04-13 12:42:02.000000000 -0400
@@ -440,6 +440,7 @@
 
 	dep->stream_capable = false;
 	dep->desc = NULL;
+	dep->endpoint.desc = NULL;
 	dep->comp_desc = NULL;
 	dep->type = 0;
 	dep->flags = 0;
@@ -485,16 +486,16 @@
 
 	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
-		strncat(dep->name, "-control", sizeof(dep->name));
+		strlcat(dep->name, "-control", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		strncat(dep->name, "-isoc", sizeof(dep->name));
+		strlcat(dep->name, "-isoc", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_BULK:
-		strncat(dep->name, "-bulk", sizeof(dep->name));
+		strlcat(dep->name, "-bulk", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		strncat(dep->name, "-int", sizeof(dep->name));
+		strlcat(dep->name, "-int", sizeof(dep->name));
 		break;
 	default:
 		dev_err(dwc->dev, "invalid endpoint transfer type\n");
@@ -667,6 +668,7 @@
 {
 	struct dwc3_request	*req, *n;
 	u32			trbs_left;
+	u32			max;
 	unsigned int		last_one = 0;
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
@@ -674,6 +676,13 @@
 	/* the first request must not be queued */
 	trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
 
+	/* Can't wrap around on a non-isoc EP since there's no link TRB */
+	if (!usb_endpoint_xfer_isoc(dep->desc)) {
+		max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
+		if (trbs_left > max)
+			trbs_left = max;
+	}
+
 	/*
 	 * if busy & slot are equal than it is either full or empty. If we are
 	 * starting to proceed requests then we are empty. Otherwise we ar
@@ -1490,7 +1499,7 @@
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
 		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
-	u32 uf;
+	u32 uf, mask;
 
 	if (list_empty(&dep->request_list)) {
 		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
@@ -1498,16 +1507,10 @@
 		return;
 	}
 
-	if (event->parameters) {
-		u32 mask;
-
-		mask = ~(dep->interval - 1);
-		uf = event->parameters & mask;
-		/* 4 micro frames in the future */
-		uf += dep->interval * 4;
-	} else {
-		uf = 0;
-	}
+	mask = ~(dep->interval - 1);
+	uf = event->parameters & mask;
+	/* 4 micro frames in the future */
+	uf += dep->interval * 4;
 
 	__dwc3_gadget_kick_transfer(dep, uf, 1);
 }
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/amd5536udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/amd5536udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/amd5536udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/amd5536udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -445,6 +445,7 @@
 
 	VDBG(ep->dev, "ep-%d reset\n", ep->num);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
 
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/at91_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/at91_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/at91_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/at91_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -558,6 +558,7 @@
 
 	/* restore the endpoint's pristine config */
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.maxpacket = ep->maxpacket;
 
 	/* reset fifos and endpoint */
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/atmel_usba_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/atmel_usba_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/atmel_usba_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/atmel_usba_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -659,6 +659,7 @@
 		return -EINVAL;
 	}
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 
 	list_splice_init(&ep->queue, &req_list);
 	if (ep->can_dma) {
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/ci13xxx_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/ci13xxx_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/ci13xxx_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/ci13xxx_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -2181,6 +2181,7 @@
 	} while (mEp->dir != direction);
 
 	mEp->desc = NULL;
+	mEp->ep.desc = NULL;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/fsl_qe_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/fsl_qe_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/fsl_qe_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/fsl_qe_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -1638,6 +1638,7 @@
 	/* Nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->tx_req = NULL;
 	qe_ep_reset(udc, ep->epnum);
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/fsl_udc_core.c linux-libre-3.3.2-gnu/drivers/usb/gadget/fsl_udc_core.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/fsl_udc_core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/fsl_udc_core.c	2012-04-13 12:42:02.000000000 -0400
@@ -659,6 +659,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
@@ -768,7 +769,7 @@
  * @is_last: return flag if it is the last dTD of the request
  * return: pointer to the built dTD */
 static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
-		dma_addr_t *dma, int *is_last)
+		dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
 {
 	u32 swap_temp;
 	struct ep_td_struct *dtd;
@@ -777,7 +778,7 @@
 	*length = min(req->req.length - req->req.actual,
 			(unsigned)EP_MAX_LENGTH_TRANSFER);
 
-	dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+	dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
 	if (dtd == NULL)
 		return dtd;
 
@@ -827,7 +828,7 @@
 }
 
 /* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
 {
 	unsigned	count;
 	int		is_last;
@@ -836,7 +837,7 @@
 	dma_addr_t dma;
 
 	do {
-		dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+		dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
 		if (dtd == NULL)
 			return -ENOMEM;
 
@@ -910,13 +911,11 @@
 	req->req.actual = 0;
 	req->dtd_count = 0;
 
-	spin_lock_irqsave(&udc->lock, flags);
-
 	/* build dtds and push them to device queue */
-	if (!fsl_req_to_dtd(req)) {
+	if (!fsl_req_to_dtd(req, gfp_flags)) {
+		spin_lock_irqsave(&udc->lock, flags);
 		fsl_queue_td(ep, req);
 	} else {
-		spin_unlock_irqrestore(&udc->lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1295,7 +1294,7 @@
 			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	req->mapped = 1;
 
-	if (fsl_req_to_dtd(req) == 0)
+	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
 	else
 		return -ENOMEM;
@@ -1379,7 +1378,7 @@
 	req->mapped = 1;
 
 	/* prime the data phase */
-	if ((fsl_req_to_dtd(req) == 0))
+	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 		fsl_queue_td(ep, req);
 	else			/* no mem */
 		goto stall;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/f_subset.c linux-libre-3.3.2-gnu/drivers/usb/gadget/f_subset.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/f_subset.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/f_subset.c	2012-04-13 12:42:02.000000000 -0400
@@ -74,7 +74,7 @@
 
 /* interface descriptor: */
 
-static struct usb_interface_descriptor subset_data_intf __initdata = {
+static struct usb_interface_descriptor subset_data_intf = {
 	.bLength =		sizeof subset_data_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -87,7 +87,7 @@
 	/* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+static struct usb_cdc_header_desc mdlm_header_desc = {
 	.bLength =		sizeof mdlm_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
@@ -95,7 +95,7 @@
 	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
-static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+static struct usb_cdc_mdlm_desc mdlm_desc = {
 	.bLength =		sizeof mdlm_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
@@ -111,7 +111,7 @@
  * can't really use its struct.  All we do here is say that we're using
  * the submode of "SAFE" which directly matches the CDC Subset.
  */
-static u8 mdlm_detail_desc[] __initdata = {
+static u8 mdlm_detail_desc[] = {
 	6,
 	USB_DT_CS_INTERFACE,
 	USB_CDC_MDLM_DETAIL_TYPE,
@@ -121,7 +121,7 @@
 	0,	/* network data capabilities ("raw" encapsulation) */
 };
 
-static struct usb_cdc_ether_desc ether_desc __initdata = {
+static struct usb_cdc_ether_desc ether_desc = {
 	.bLength =		sizeof ether_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
@@ -136,7 +136,7 @@
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -144,7 +144,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -152,7 +152,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+static struct usb_descriptor_header *fs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -165,7 +165,7 @@
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -173,7 +173,7 @@
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -181,7 +181,7 @@
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+static struct usb_descriptor_header *hs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -194,7 +194,7 @@
 
 /* super speed support: */
 
-static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -202,7 +202,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -210,7 +210,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = {
 	.bLength =		sizeof ss_subset_bulk_comp_desc,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -219,7 +219,7 @@
 	/* .bmAttributes =	0, */
 };
 
-static struct usb_descriptor_header *ss_eth_function[] __initdata = {
+static struct usb_descriptor_header *ss_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -290,7 +290,7 @@
 
 /* serial function driver setup/binding */
 
-static int __init
+static int
 geth_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
@@ -404,7 +404,7 @@
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
 	struct f_gether	*geth;
 	int		status;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/goku_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/goku_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/goku_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/goku_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -235,6 +235,7 @@
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
 	ep->dma = 0;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/hid.c linux-libre-3.3.2-gnu/drivers/usb/gadget/hid.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/hid.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/hid.c	2012-04-13 12:42:02.000000000 -0400
@@ -60,9 +60,9 @@
 	/* .bDeviceClass =		USB_CLASS_COMM, */
 	/* .bDeviceSubClass =	0, */
 	/* .bDeviceProtocol =	0, */
-	.bDeviceClass =		0xEF,
-	.bDeviceSubClass =	2,
-	.bDeviceProtocol =	1,
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id can be overridden by module parameters.  */
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/inode.c linux-libre-3.3.2-gnu/drivers/usb/gadget/inode.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/inode.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/inode.c	2012-04-13 12:42:02.000000000 -0400
@@ -1043,6 +1043,8 @@
 // FIXME don't call this with the spinlock held ...
 				if (copy_to_user (buf, dev->req->buf, len))
 					retval = -EFAULT;
+				else
+					retval = len;
 				clean_req (dev->gadget->ep0, dev->req);
 				/* NOTE userspace can't yet choose to stall */
 			}
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/langwell_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/langwell_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/langwell_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/langwell_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -487,6 +487,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&dev->lock, flags);
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/mv_udc_core.c linux-libre-3.3.2-gnu/drivers/usb/gadget/mv_udc_core.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/mv_udc_core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/mv_udc_core.c	2012-04-13 12:42:02.000000000 -0400
@@ -608,6 +608,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&udc->lock, flags);
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/omap_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/omap_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/omap_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/omap_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -251,6 +251,7 @@
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/pch_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/pch_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/pch_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/pch_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -1493,6 +1493,7 @@
 	pch_udc_ep_disable(ep);
 	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 	spin_unlock_irqrestore(&ep->dev->lock, iflags);
 	return 0;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/pxa25x_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/pxa25x_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/pxa25x_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/pxa25x_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -283,6 +283,7 @@
 	pxa25x_ep_fifo_flush (_ep);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	local_irq_restore(flags);
@@ -1192,6 +1193,7 @@
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = 0;
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/s3c2410_udc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/s3c2410_udc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/s3c2410_udc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/s3c2410_udc.c	2012-04-13 12:42:02.000000000 -0400
@@ -1148,6 +1148,7 @@
 	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->halted = 1;
 
 	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
@@ -1630,6 +1631,7 @@
 
 		ep->dev = dev;
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD (&ep->queue);
 	}
diff -druN linux-libre-3.3-gnu/drivers/usb/gadget/s3c-hsudc.c linux-libre-3.3.2-gnu/drivers/usb/gadget/s3c-hsudc.c
--- linux-libre-3.3-gnu/drivers/usb/gadget/s3c-hsudc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/gadget/s3c-hsudc.c	2012-04-13 12:42:02.000000000 -0400
@@ -816,6 +816,7 @@
 	s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
 
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 1;
 
 	spin_unlock_irqrestore(&hsudc->lock, flags);
@@ -1005,6 +1006,7 @@
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 0;
 	hsep->wedge = 0;
 
diff -druN linux-libre-3.3-gnu/drivers/usb/host/ehci-fsl.c linux-libre-3.3.2-gnu/drivers/usb/host/ehci-fsl.c
--- linux-libre-3.3-gnu/drivers/usb/host/ehci-fsl.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/host/ehci-fsl.c	2012-04-13 12:42:02.000000000 -0400
@@ -216,6 +216,8 @@
 			       unsigned int port_offset)
 {
 	u32 portsc;
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
+	void __iomem *non_ehci = hcd->regs;
 
 	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@
 		portsc |= PORT_PTS_PTW;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
+		/* enable UTMI PHY */
+		setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
 		portsc |= PORT_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_NONE:
diff -druN linux-libre-3.3-gnu/drivers/usb/host/ehci-fsl.h linux-libre-3.3.2-gnu/drivers/usb/host/ehci-fsl.h
--- linux-libre-3.3-gnu/drivers/usb/host/ehci-fsl.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/host/ehci-fsl.h	2012-04-13 12:42:02.000000000 -0400
@@ -45,5 +45,6 @@
 #define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN	(1<<9)
 #define SNOOP_SIZE_2GB		0x1e
 #endif				/* _EHCI_FSL_H */
diff -druN linux-libre-3.3-gnu/drivers/usb/host/fsl-mph-dr-of.c linux-libre-3.3.2-gnu/drivers/usb/host/fsl-mph-dr-of.c
--- linux-libre-3.3-gnu/drivers/usb/host/fsl-mph-dr-of.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/host/fsl-mph-dr-of.c	2012-04-13 12:42:02.000000000 -0400
@@ -94,7 +94,6 @@
 	pdev->dev.parent = &ofdev->dev;
 
 	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
-	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
 	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
 
 	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
diff -druN linux-libre-3.3-gnu/drivers/usb/host/ohci-at91.c linux-libre-3.3.2-gnu/drivers/usb/host/ohci-at91.c
--- linux-libre-3.3-gnu/drivers/usb/host/ohci-at91.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/host/ohci-at91.c	2012-04-13 12:42:02.000000000 -0400
@@ -245,7 +245,7 @@
 		return;
 
 	gpio_set_value(pdata->vbus_pin[port],
-		       !pdata->vbus_pin_active_low[port] ^ enable);
+		       pdata->vbus_pin_active_low[port] ^ enable);
 }
 
 static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
@@ -257,7 +257,7 @@
 		return -EINVAL;
 
 	return gpio_get_value(pdata->vbus_pin[port]) ^
-		!pdata->vbus_pin_active_low[port];
+		pdata->vbus_pin_active_low[port];
 }
 
 /*
diff -druN linux-libre-3.3-gnu/drivers/usb/musb/musb_gadget.c linux-libre-3.3.2-gnu/drivers/usb/musb/musb_gadget.c
--- linux-libre-3.3-gnu/drivers/usb/musb/musb_gadget.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/musb/musb_gadget.c	2012-04-13 12:42:02.000000000 -0400
@@ -574,6 +574,15 @@
 
 		if (request->actual == request->length) {
 			musb_g_giveback(musb_ep, request, 0);
+			/*
+			 * In the giveback function the MUSB lock is
+			 * released and acquired after sometime. During
+			 * this time period the INDEX register could get
+			 * changed by the gadget_queue function especially
+			 * on SMP systems. Reselect the INDEX to be sure
+			 * we are reading/modifying the right registers
+			 */
+			musb_ep_select(mbase, epnum);
 			req = musb_ep->desc ? next_request(musb_ep) : NULL;
 			if (!req) {
 				dev_dbg(musb->controller, "%s idle now\n",
@@ -983,6 +992,15 @@
 		}
 #endif
 		musb_g_giveback(musb_ep, request, 0);
+		/*
+		 * In the giveback function the MUSB lock is
+		 * released and acquired after sometime. During
+		 * this time period the INDEX register could get
+		 * changed by the gadget_queue function especially
+		 * on SMP systems. Reselect the INDEX to be sure
+		 * we are reading/modifying the right registers
+		 */
+		musb_ep_select(mbase, epnum);
 
 		req = next_request(musb_ep);
 		if (!req)
diff -druN linux-libre-3.3-gnu/drivers/usb/renesas_usbhs/mod_gadget.c linux-libre-3.3.2-gnu/drivers/usb/renesas_usbhs/mod_gadget.c
--- linux-libre-3.3-gnu/drivers/usb/renesas_usbhs/mod_gadget.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/renesas_usbhs/mod_gadget.c	2012-04-13 12:42:02.000000000 -0400
@@ -941,6 +941,11 @@
 	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+	/* do nothing */
+}
+
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv;
@@ -989,6 +994,7 @@
 	 */
 	dev_set_name(&gpriv->gadget.dev, "gadget");
 	gpriv->gadget.dev.parent	= dev;
+	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;
 	gpriv->gadget.name		= "renesas_usbhs_udc";
 	gpriv->gadget.ops		= &usbhsg_gadget_ops;
 	gpriv->gadget.max_speed		= USB_SPEED_HIGH;
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/cp210x.c linux-libre-3.3.2-gnu/drivers/usb/serial/cp210x.c
--- linux-libre-3.3-gnu/drivers/usb/serial/cp210x.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/cp210x.c	2012-04-13 12:42:02.000000000 -0400
@@ -49,6 +49,7 @@
 		unsigned int, unsigned int);
 static void cp210x_break_ctl(struct tty_struct *, int);
 static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
 static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
 
 static bool debug;
@@ -121,6 +122,8 @@
 	{ 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, 0xEA70) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -149,6 +152,10 @@
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+struct cp210x_port_private {
+	__u8			bInterfaceNumber;
+};
+
 static struct usb_driver cp210x_driver = {
 	.name		= "cp210x",
 	.probe		= usb_serial_probe,
@@ -174,6 +181,7 @@
 	.tiocmget 		= cp210x_tiocmget,
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_startup,
+	.release		= cp210x_release,
 	.dtr_rts		= cp210x_dtr_rts
 };
 
@@ -261,6 +269,7 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -276,7 +285,7 @@
 	/* Issue the request, attempting to read 'size' bytes */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 
 	/* Convert data into an array of integers */
 	for (i = 0; i < length; i++)
@@ -307,6 +316,7 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -328,12 +338,12 @@
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 	} else {
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, data[0],
-				0, NULL, 0, 300);
+				port_priv->bInterfaceNumber, NULL, 0, 300);
 	}
 
 	kfree(buf);
@@ -844,11 +854,39 @@
 
 static int cp210x_startup(struct usb_serial *serial)
 {
+	struct cp210x_port_private *port_priv;
+	int i;
+
 	/* cp210x buffers behave strangely unless device is reset */
 	usb_reset_device(serial->dev);
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+		if (!port_priv)
+			return -ENOMEM;
+
+		memset(port_priv, 0x00, sizeof(*port_priv));
+		port_priv->bInterfaceNumber =
+		    serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+		usb_set_serial_port_data(serial->port[i], port_priv);
+	}
+
 	return 0;
 }
 
+static void cp210x_release(struct usb_serial *serial)
+{
+	struct cp210x_port_private *port_priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = usb_get_serial_port_data(serial->port[i]);
+		kfree(port_priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+}
+
 static int __init cp210x_init(void)
 {
 	int retval;
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio.c	2012-04-13 12:42:02.000000000 -0400
@@ -188,6 +188,7 @@
 		.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -536,6 +537,10 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
@@ -797,7 +802,7 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
+	{ USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -846,6 +851,9 @@
 	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -868,7 +876,8 @@
 	[FT232RL] = "FT232RL",
 	[FT2232H] = "FT2232H",
 	[FT4232H] = "FT4232H",
-	[FT232H]  = "FT232H"
+	[FT232H]  = "FT232H",
+	[FTX]     = "FT-X"
 };
 
 
@@ -1169,7 +1178,8 @@
 		break;
 	case FT232BM: /* FT232BM chip */
 	case FT2232C: /* FT2232C chip */
-	case FT232RL:
+	case FT232RL: /* FT232RL chip */
+	case FTX:     /* FT-X series */
 		if (baud <= 3000000) {
 			__u16 product_id = le16_to_cpu(
 				port->serial->dev->descriptor.idProduct);
@@ -1458,10 +1468,14 @@
 	} else if (version < 0x900) {
 		/* Assume it's an FT232RL */
 		priv->chip_type = FT232RL;
-	} else {
+	} else if (version < 0x1000) {
 		/* Assume it's an FT232H */
 		priv->chip_type = FT232H;
+	} else {
+		/* Assume it's an FT-X series device */
+		priv->chip_type = FTX;
 	}
+
 	dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
 }
 
@@ -1589,7 +1603,8 @@
 		     priv->chip_type == FT232RL ||
 		     priv->chip_type == FT2232H ||
 		     priv->chip_type == FT4232H ||
-		     priv->chip_type == FT232H)) {
+		     priv->chip_type == FT232H ||
+		     priv->chip_type == FTX)) {
 			retval = device_create_file(&port->dev,
 						    &dev_attr_latency_timer);
 		}
@@ -1611,7 +1626,8 @@
 		    priv->chip_type == FT232RL ||
 		    priv->chip_type == FT2232H ||
 		    priv->chip_type == FT4232H ||
-                    priv->chip_type == FT232H) {
+		    priv->chip_type == FT232H ||
+		    priv->chip_type == FTX) {
 			device_remove_file(&port->dev, &dev_attr_latency_timer);
 		}
 	}
@@ -1763,7 +1779,8 @@
 
 	dbg("%s", __func__);
 
-	if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+	if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
 		return ftdi_jtag_probe(serial);
 
 	return 0;
@@ -2288,6 +2305,7 @@
 	case FT2232H:
 	case FT4232H:
 	case FT232H:
+	case FTX:
 		len = 2;
 		break;
 	default:
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio.h linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio.h
--- linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio.h	2012-04-13 12:42:02.000000000 -0400
@@ -157,7 +157,8 @@
 	FT232RL = 5,
 	FT2232H = 6,
 	FT4232H = 7,
-	FT232H  = 8
+	FT232H  = 8,
+	FTX     = 9,
 };
 
 enum ftdi_sio_baudrate {
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio_ids.h linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-3.3-gnu/drivers/usb/serial/ftdi_sio_ids.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/ftdi_sio_ids.h	2012-04-13 12:42:02.000000000 -0400
@@ -23,12 +23,15 @@
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
 #define FTDI_232H_PID  0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID   0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX */
 #define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 
 
 /*** third-party PIDs (using FTDI_VID) ***/
 
+#define FTDI_LUMEL_PD12_PID	0x6002
+
 /*
  * Marvell OpenRD Base, Client
  * http://www.open-rd.org
@@ -97,6 +100,8 @@
 #define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
 
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID	0xCFF8
+
 /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
 /* the VID is the standard ftdi vid (FTDI_VID) */
 #define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
@@ -532,10 +537,14 @@
 #define ADI_GNICEPLUS_PID	0xF001
 
 /*
- * Hornby Elite
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
  */
-#define HORNBY_VID		0x04D8
-#define HORNBY_ELITE_PID	0x000A
+#define MICROCHIP_VID		0x04D8
+#define MICROCHIP_USB_BOARD_PID	0x000A /* CDC RS-232 Emulation Demo */
 
 /*
  * RATOC REX-USB60F
@@ -680,6 +689,10 @@
 #define SEALEVEL_2803_6_PID	0X2863	/* SeaLINK+8 (2803) Port 6 */
 #define SEALEVEL_2803_7_PID	0X2873	/* SeaLINK+8 (2803) Port 7 */
 #define SEALEVEL_2803_8_PID	0X2883	/* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID	0Xa02a	/* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID	0Xa02b	/* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID	0Xa02c	/* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID	0Xa02d	/* SeaLINK+8 (2803-ROHS) Port 7+8 */
 
 /*
  * JETI SPECTROMETER SPECBOS 1201
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/generic.c linux-libre-3.3.2-gnu/drivers/usb/serial/generic.c
--- linux-libre-3.3-gnu/drivers/usb/serial/generic.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/generic.c	2012-04-13 12:42:02.000000000 -0400
@@ -217,8 +217,10 @@
 	clear_bit(i, &port->write_urbs_free);
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - error submitting urb: %d\n",
+		if (!port->port.console) {
+			dev_err(&port->dev, "%s - error submitting urb: %d\n",
 						__func__, result);
+		}
 		set_bit(i, &port->write_urbs_free);
 		spin_lock_irqsave(&port->lock, flags);
 		port->tx_bytes -= count;
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/mos7840.c linux-libre-3.3.2-gnu/drivers/usb/serial/mos7840.c
--- linux-libre-3.3-gnu/drivers/usb/serial/mos7840.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/mos7840.c	2012-04-13 12:42:02.000000000 -0400
@@ -174,6 +174,7 @@
 
 #define CLK_MULTI_REGISTER         ((__u16)(0x02))
 #define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+#define GPIO_REGISTER              ((__u16)(0x07))
 
 #define SERIAL_LCR_DLAB            ((__u16)(0x0080))
 
@@ -1101,14 +1102,25 @@
 	mos7840_port->read_urb = port->read_urb;
 
 	/* set up our bulk in urb */
-
-	usb_fill_bulk_urb(mos7840_port->read_urb,
-			  serial->dev,
-			  usb_rcvbulkpipe(serial->dev,
-					  port->bulk_in_endpointAddress),
-			  port->bulk_in_buffer,
-			  mos7840_port->read_urb->transfer_buffer_length,
-			  mos7840_bulk_in_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				(port->bulk_in_endpointAddress) + 2),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				port->bulk_in_endpointAddress),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	}
 
 	dbg("mos7840_open: bulkin endpoint is %d",
 	    port->bulk_in_endpointAddress);
@@ -1519,13 +1531,25 @@
 	memcpy(urb->transfer_buffer, current_position, transfer_size);
 
 	/* fill urb with data and submit  */
-	usb_fill_bulk_urb(urb,
-			  serial->dev,
-			  usb_sndbulkpipe(serial->dev,
-					  port->bulk_out_endpointAddress),
-			  urb->transfer_buffer,
-			  transfer_size,
-			  mos7840_bulk_out_data_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				(port->bulk_out_endpointAddress) + 2),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				port->bulk_out_endpointAddress),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	}
 
 	data1 = urb->transfer_buffer;
 	dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
@@ -1838,7 +1862,7 @@
 
 	} else {
 #ifdef HW_flow_control
-		/ *setting h/w flow control bit to 0 */
+		/* setting h/w flow control bit to 0 */
 		Data = 0xb;
 		mos7840_port->shadowMCR = Data;
 		status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
@@ -2305,19 +2329,26 @@
 
 static int mos7840_calc_num_ports(struct usb_serial *serial)
 {
-	int mos7840_num_ports = 0;
+	__u16 Data = 0x00;
+	int ret = 0;
+	int mos7840_num_ports;
 
-	dbg("numberofendpoints: cur %d, alt %d",
-	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
-	    (int)serial->interface->altsetting->desc.bNumEndpoints);
-	if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
-		mos7840_num_ports = serial->num_ports = 2;
-	} else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+	ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+		MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+		VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+	if ((Data & 0x01) == 0) {
+		mos7840_num_ports = 2;
+		serial->num_bulk_in = 2;
+		serial->num_bulk_out = 2;
+		serial->num_ports = 2;
+	} else {
+		mos7840_num_ports = 4;
 		serial->num_bulk_in = 4;
 		serial->num_bulk_out = 4;
-		mos7840_num_ports = serial->num_ports = 4;
+		serial->num_ports = 4;
 	}
-	dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+
 	return mos7840_num_ports;
 }
 
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/option.c linux-libre-3.3.2-gnu/drivers/usb/serial/option.c
--- linux-libre-3.3-gnu/drivers/usb/serial/option.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/option.c	2012-04-13 12:42:02.000000000 -0400
@@ -307,6 +307,9 @@
 #define TELIT_VENDOR_ID				0x1bc7
 #define TELIT_PRODUCT_UC864E			0x1003
 #define TELIT_PRODUCT_UC864G			0x1004
+#define TELIT_PRODUCT_CC864_DUAL		0x1005
+#define TELIT_PRODUCT_CC864_SINGLE		0x1006
+#define TELIT_PRODUCT_DE910_DUAL		0x1010
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID				0x19d2
@@ -484,6 +487,9 @@
 #define LG_VENDOR_ID				0x1004
 #define LG_PRODUCT_L02C				0x618f
 
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID			0x0e8d
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -768,6 +774,9 @@
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -892,6 +901,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1198,6 +1209,10 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) },        /* MediaTek MT6276M modem & app port */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1360,6 +1375,7 @@
 		serial->interface->cur_altsetting->desc.bInterfaceNumber,
 		OPTION_BLACKLIST_RESERVED_IF,
 		(const struct option_blacklist_info *) id->driver_info))
+		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 &&
diff -druN linux-libre-3.3-gnu/drivers/usb/serial/qcserial.c linux-libre-3.3.2-gnu/drivers/usb/serial/qcserial.c
--- linux-libre-3.3-gnu/drivers/usb/serial/qcserial.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/serial/qcserial.c	2012-04-13 12:42:02.000000000 -0400
@@ -24,39 +24,44 @@
 
 static bool debug;
 
+#define DEVICE_G1K(v, p) \
+	USB_DEVICE(v, p), .driver_info = 1
+
 static const struct usb_device_id id_table[] = {
-	{USB_DEVICE(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
-	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */
-	{USB_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
-	{USB_DEVICE(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
-	{USB_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */
-	{USB_DEVICE(0x413c, 0x8171)},	/* Dell Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
-	{USB_DEVICE(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
-	{USB_DEVICE(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
-	{USB_DEVICE(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
-	{USB_DEVICE(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
-	{USB_DEVICE(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+	/* Gobi 1000 devices */
+	{DEVICE_G1K(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
+	{DEVICE_G1K(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
+	{DEVICE_G1K(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
+	{DEVICE_G1K(0x413c, 0x8172)},	/* Dell Gobi Modem device */
+	{DEVICE_G1K(0x413c, 0x8171)},	/* Dell Gobi QDL device */
+	{DEVICE_G1K(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
+	{DEVICE_G1K(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
+	{DEVICE_G1K(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
+	{DEVICE_G1K(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
+	{DEVICE_G1K(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
+	{DEVICE_G1K(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
+	{DEVICE_G1K(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+
+	/* Gobi 2000 devices */
+	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi 2000 QDL device */
 	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
 	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
 	{USB_DEVICE(0x05c6, 0x9208)},	/* Generic Gobi 2000 QDL device */
@@ -92,6 +97,8 @@
 	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */
 	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
 
+	/* Gobi 3000 devices */
+	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920c)},	/* Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920d)},	/* Gobi 3000 Composite */
 	{USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */
@@ -122,8 +129,10 @@
 	int retval = -ENODEV;
 	__u8 nintf;
 	__u8 ifnum;
+	bool is_gobi1k = id->driver_info ? true : false;
 
 	dbg("%s", __func__);
+	dbg("Is Gobi 1000 = %d", is_gobi1k);
 
 	nintf = serial->dev->actconfig->desc.bNumInterfaces;
 	dbg("Num Interfaces = %d", nintf);
@@ -169,15 +178,25 @@
 
 	case 3:
 	case 4:
-		/* Composite mode */
-		/* ifnum == 0 is a broadband network adapter */
-		if (ifnum == 1) {
-			/*
-			 * Diagnostics Monitor (serial line 9600 8N1)
-			 * Qualcomm DM protocol
-			 * use "libqcdm" (ModemManager) for communication
-			 */
-			dbg("Diagnostics Monitor found");
+		/* Composite mode; don't bind to the QMI/net interface as that
+		 * gets handled by other drivers.
+		 */
+
+		/* Gobi 1K USB layout:
+		 * 0: serial port (doesn't respond)
+		 * 1: serial port (doesn't respond)
+		 * 2: AT-capable modem port
+		 * 3: QMI/net
+		 *
+		 * Gobi 2K+ USB layout:
+		 * 0: QMI/net
+		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+		 * 2: AT-capable modem port
+		 * 3: NMEA
+		 */
+
+		if (ifnum == 1 && !is_gobi1k) {
+			dbg("Gobi 2K+ DM/DIAG interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
@@ -196,13 +215,13 @@
 				retval = -ENODEV;
 				kfree(data);
 			}
-		} else if (ifnum==3) {
+		} else if (ifnum==3 && !is_gobi1k) {
 			/*
 			 * NMEA (serial line 9600 8N1)
 			 * # echo "\$GPS_START" > /dev/ttyUSBx
 			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
 			 */
-			dbg("NMEA GPS interface found");
+			dbg("Gobi 2K+ NMEA GPS interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
diff -druN linux-libre-3.3-gnu/drivers/usb/storage/realtek_cr.c linux-libre-3.3.2-gnu/drivers/usb/storage/realtek_cr.c
--- linux-libre-3.3-gnu/drivers/usb/storage/realtek_cr.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/usb/storage/realtek_cr.c	2012-04-13 12:42:02.000000000 -0400
@@ -507,9 +507,14 @@
 {
 	int retval;
 	u8 cmnd[12] = {0};
+	u8 *buf;
 
 	US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
 
+	buf = kmemdup(data, len, GFP_NOIO);
+	if (!buf)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	cmnd[0] = 0xF0;
 	cmnd[1] = 0x0E;
 	cmnd[2] = 0xfe;
@@ -517,7 +522,8 @@
 	cmnd[4] = (u8)(len >> 8);
 	cmnd[5] = (u8)len;
 
-	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
+	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+	kfree(buf);
 	if (retval != USB_STOR_TRANSPORT_GOOD) {
 		return -EIO;
 	}
diff -druN linux-libre-3.3-gnu/drivers/video/backlight/tosa_lcd.c linux-libre-3.3.2-gnu/drivers/video/backlight/tosa_lcd.c
--- linux-libre-3.3-gnu/drivers/video/backlight/tosa_lcd.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/video/backlight/tosa_lcd.c	2012-04-13 12:42:02.000000000 -0400
@@ -271,7 +271,7 @@
 }
 #else
 #define tosa_lcd_suspend	NULL
-#define tosa_lcd_reume NULL
+#define tosa_lcd_resume NULL
 #endif
 
 static struct spi_driver tosa_lcd_driver = {
diff -druN linux-libre-3.3-gnu/drivers/video/fbmem.c linux-libre-3.3.2-gnu/drivers/video/fbmem.c
--- linux-libre-3.3-gnu/drivers/video/fbmem.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/video/fbmem.c	2012-04-13 12:42:02.000000000 -0400
@@ -1665,6 +1665,7 @@
 	if (ret)
 		return -EINVAL;
 
+	unlink_framebuffer(fb_info);
 	if (fb_info->pixmap.addr &&
 	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
@@ -1672,7 +1673,6 @@
 	registered_fb[i] = NULL;
 	num_registered_fb--;
 	fb_cleanup_device(fb_info);
-	device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	event.info = fb_info;
 	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
 
@@ -1681,6 +1681,22 @@
 	return 0;
 }
 
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+	int i;
+
+	i = fb_info->node;
+	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+		return -EINVAL;
+
+	if (fb_info->dev) {
+		device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+		fb_info->dev = NULL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(unlink_framebuffer);
+
 void remove_conflicting_framebuffers(struct apertures_struct *a,
 				     const char *name, bool primary)
 {
diff -druN linux-libre-3.3-gnu/drivers/video/udlfb.c linux-libre-3.3.2-gnu/drivers/video/udlfb.c
--- linux-libre-3.3-gnu/drivers/video/udlfb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/drivers/video/udlfb.c	2012-04-13 12:42:02.000000000 -0400
@@ -1739,7 +1739,7 @@
 	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
 		device_remove_file(info->dev, &fb_device_attrs[i]);
 	device_remove_bin_file(info->dev, &edid_attr);
-
+	unlink_framebuffer(info);
 	usb_set_intfdata(interface, NULL);
 
 	/* if clients still have us open, will be freed on last close */
diff -druN linux-libre-3.3-gnu/fs/cifs/cifsfs.c linux-libre-3.3.2-gnu/fs/cifs/cifsfs.c
--- linux-libre-3.3-gnu/fs/cifs/cifsfs.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/cifsfs.c	2012-04-13 12:42:02.000000000 -0400
@@ -76,7 +76,7 @@
 unsigned int cifs_max_pending = CIFS_MAX_REQ;
 module_param(cifs_max_pending, int, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
-				   "Default: 50 Range: 2 to 256");
+				   "Default: 32767 Range: 2 to 32767.");
 unsigned short echo_retries = 5;
 module_param(echo_retries, ushort, 0644);
 MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
@@ -1116,9 +1116,9 @@
 	if (cifs_max_pending < 2) {
 		cifs_max_pending = 2;
 		cFYI(1, "cifs_max_pending set to min of 2");
-	} else if (cifs_max_pending > 256) {
-		cifs_max_pending = 256;
-		cFYI(1, "cifs_max_pending set to max of 256");
+	} else if (cifs_max_pending > CIFS_MAX_REQ) {
+		cifs_max_pending = CIFS_MAX_REQ;
+		cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
 	}
 
 	rc = cifs_fscache_register();
diff -druN linux-libre-3.3-gnu/fs/cifs/cifsglob.h linux-libre-3.3.2-gnu/fs/cifs/cifsglob.h
--- linux-libre-3.3-gnu/fs/cifs/cifsglob.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/cifsglob.h	2012-04-13 12:42:02.000000000 -0400
@@ -55,14 +55,9 @@
 
 /*
  * MAX_REQ is the maximum number of requests that WE will send
- * on one socket concurrently. It also matches the most common
- * value of max multiplex returned by servers.  We may
- * eventually want to use the negotiated value (in case
- * future servers can handle more) when we are more confident that
- * we will not have problems oveloading the socket with pending
- * write data.
+ * on one socket concurrently.
  */
-#define CIFS_MAX_REQ 50
+#define CIFS_MAX_REQ 32767
 
 #define RFC1001_NAME_LEN 15
 #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
@@ -263,6 +258,7 @@
 	bool session_estab; /* mark when very first sess is established */
 	u16 dialect; /* dialect index that server chose */
 	enum securityEnum secType;
+	bool oplocks:1; /* enable oplocks */
 	unsigned int maxReq;	/* Clients should submit no more */
 	/* than maxReq distinct unanswered SMBs to the server when using  */
 	/* multiplexed reads or writes */
diff -druN linux-libre-3.3-gnu/fs/cifs/cifssmb.c linux-libre-3.3.2-gnu/fs/cifs/cifssmb.c
--- linux-libre-3.3-gnu/fs/cifs/cifssmb.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/cifssmb.c	2012-04-13 12:42:02.000000000 -0400
@@ -458,7 +458,10 @@
 			goto neg_err_exit;
 		}
 		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
-		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
+		server->maxReq = min_t(unsigned int,
+				       le16_to_cpu(rsp->MaxMpxCount),
+				       cifs_max_pending);
+		server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
 		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
 		/* even though we do not use raw we might as well set this
@@ -564,7 +567,9 @@
 
 	/* one byte, so no need to convert this or EncryptionKeyLen from
 	   little endian */
-	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
+			       cifs_max_pending);
+	server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 	/* probably no need to store and check maxvcs */
 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
diff -druN linux-libre-3.3-gnu/fs/cifs/connect.c linux-libre-3.3.2-gnu/fs/cifs/connect.c
--- linux-libre-3.3-gnu/fs/cifs/connect.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/connect.c	2012-04-13 12:42:02.000000000 -0400
@@ -642,14 +642,10 @@
 	spin_unlock(&GlobalMid_Lock);
 	wake_up_all(&server->response_q);
 
-	/*
-	 * Check if we have blocked requests that need to free. Note that
-	 * cifs_max_pending is normally 50, but can be set at module install
-	 * time to as little as two.
-	 */
+	/* Check if we have blocked requests that need to free. */
 	spin_lock(&GlobalMid_Lock);
-	if (atomic_read(&server->inFlight) >= cifs_max_pending)
-		atomic_set(&server->inFlight, cifs_max_pending - 1);
+	if (atomic_read(&server->inFlight) >= server->maxReq)
+		atomic_set(&server->inFlight, server->maxReq - 1);
 	/*
 	 * We do not want to set the max_pending too low or we could end up
 	 * with the counter going negative.
@@ -1910,6 +1906,7 @@
 	tcp_ses->noautotune = volume_info->noautotune;
 	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
 	atomic_set(&tcp_ses->inFlight, 0);
+	tcp_ses->maxReq = 1; /* enough to send negotiate request */
 	init_waitqueue_head(&tcp_ses->response_q);
 	init_waitqueue_head(&tcp_ses->request_q);
 	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
@@ -3371,7 +3368,7 @@
 int
 cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
-	int rc = 0;
+	int rc;
 	int xid;
 	struct cifs_ses *pSesInfo;
 	struct cifs_tcon *tcon;
@@ -3398,6 +3395,7 @@
 		FreeXid(xid);
 	}
 #endif
+	rc = 0;
 	tcon = NULL;
 	pSesInfo = NULL;
 	srvTcp = NULL;
diff -druN linux-libre-3.3-gnu/fs/cifs/dir.c linux-libre-3.3.2-gnu/fs/cifs/dir.c
--- linux-libre-3.3-gnu/fs/cifs/dir.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/dir.c	2012-04-13 12:42:02.000000000 -0400
@@ -171,7 +171,7 @@
 	}
 	tcon = tlink_tcon(tlink);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 
 	if (nd)
@@ -492,7 +492,7 @@
 {
 	int xid;
 	int rc = 0; /* to get around spurious gcc warning, set to zero here */
-	__u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
+	__u32 oplock;
 	__u16 fileHandle = 0;
 	bool posix_open = false;
 	struct cifs_sb_info *cifs_sb;
@@ -518,6 +518,8 @@
 	}
 	pTcon = tlink_tcon(tlink);
 
+	oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
+
 	/*
 	 * Don't allow the separator character in a path component.
 	 * The VFS will not allow "/", but "\" is allowed by posix.
diff -druN linux-libre-3.3-gnu/fs/cifs/file.c linux-libre-3.3.2-gnu/fs/cifs/file.c
--- linux-libre-3.3-gnu/fs/cifs/file.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/file.c	2012-04-13 12:42:02.000000000 -0400
@@ -380,7 +380,7 @@
 	cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
 		 inode, file->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
@@ -505,7 +505,7 @@
 	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
 		 inode, pCifsFile->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
@@ -835,13 +835,21 @@
 	if ((flock->fl_flags & FL_POSIX) == 0)
 		return rc;
 
+try_again:
 	mutex_lock(&cinode->lock_mutex);
 	if (!cinode->can_cache_brlcks) {
 		mutex_unlock(&cinode->lock_mutex);
 		return rc;
 	}
-	rc = posix_lock_file_wait(file, flock);
+
+	rc = posix_lock_file(file, flock, NULL);
 	mutex_unlock(&cinode->lock_mutex);
+	if (rc == FILE_LOCK_DEFERRED) {
+		rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
+		if (!rc)
+			goto try_again;
+		locks_delete_block(flock);
+	}
 	return rc;
 }
 
@@ -960,9 +968,9 @@
 	INIT_LIST_HEAD(&locks_to_send);
 
 	/*
-	 * Allocating count locks is enough because no locks can be added to
-	 * the list while we are holding cinode->lock_mutex that protects
-	 * locking operations of this inode.
+	 * Allocating count locks is enough because no FL_POSIX locks can be
+	 * added to the list while we are holding cinode->lock_mutex that
+	 * protects locking operations of this inode.
 	 */
 	for (; i < count; i++) {
 		lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
@@ -973,18 +981,20 @@
 		list_add_tail(&lck->llist, &locks_to_send);
 	}
 
-	i = 0;
 	el = locks_to_send.next;
 	lock_flocks();
 	cifs_for_each_lock(cfile->dentry->d_inode, before) {
+		flock = *before;
+		if ((flock->fl_flags & FL_POSIX) == 0)
+			continue;
 		if (el == &locks_to_send) {
-			/* something is really wrong */
+			/*
+			 * The list ended. We don't have enough allocated
+			 * structures - something is really wrong.
+			 */
 			cERROR(1, "Can't push all brlocks!");
 			break;
 		}
-		flock = *before;
-		if ((flock->fl_flags & FL_POSIX) == 0)
-			continue;
 		length = 1 + flock->fl_end - flock->fl_start;
 		if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
 			type = CIFS_RDLCK;
@@ -996,7 +1006,6 @@
 		lck->length = length;
 		lck->type = type;
 		lck->offset = flock->fl_start;
-		i++;
 		el = el->next;
 	}
 	unlock_flocks();
diff -druN linux-libre-3.3-gnu/fs/cifs/transport.c linux-libre-3.3.2-gnu/fs/cifs/transport.c
--- linux-libre-3.3-gnu/fs/cifs/transport.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/cifs/transport.c	2012-04-13 12:42:02.000000000 -0400
@@ -265,12 +265,12 @@
 
 	spin_lock(&GlobalMid_Lock);
 	while (1) {
-		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
+		if (atomic_read(&server->inFlight) >= server->maxReq) {
 			spin_unlock(&GlobalMid_Lock);
 			cifs_num_waiters_inc(server);
 			wait_event(server->request_q,
 				   atomic_read(&server->inFlight)
-				     < cifs_max_pending);
+				     < server->maxReq);
 			cifs_num_waiters_dec(server);
 			spin_lock(&GlobalMid_Lock);
 		} else {
diff -druN linux-libre-3.3-gnu/fs/dcache.c linux-libre-3.3.2-gnu/fs/dcache.c
--- linux-libre-3.3-gnu/fs/dcache.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/dcache.c	2012-04-13 12:42:02.000000000 -0400
@@ -2405,6 +2405,7 @@
 			if (d_ancestor(alias, dentry)) {
 				/* Check for loops */
 				actual = ERR_PTR(-ELOOP);
+				spin_unlock(&inode->i_lock);
 			} else if (IS_ROOT(alias)) {
 				/* Is this an anonymous mountpoint that we
 				 * could splice into our tree? */
@@ -2414,7 +2415,7 @@
 				goto found;
 			} else {
 				/* Nope, but we must(!) avoid directory
-				 * aliasing */
+				 * aliasing. This drops inode->i_lock */
 				actual = __d_unalias(inode, dentry, alias);
 			}
 			write_sequnlock(&rename_lock);
diff -druN linux-libre-3.3-gnu/fs/ext4/ext4.h linux-libre-3.3.2-gnu/fs/ext4/ext4.h
--- linux-libre-3.3-gnu/fs/ext4/ext4.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/ext4.h	2012-04-13 12:42:02.000000000 -0400
@@ -184,6 +184,8 @@
 #define	EXT4_IO_END_UNWRITTEN	0x0001
 #define EXT4_IO_END_ERROR	0x0002
 #define EXT4_IO_END_QUEUED	0x0004
+#define EXT4_IO_END_DIRECT	0x0008
+#define EXT4_IO_END_IN_FSYNC	0x0010
 
 struct ext4_io_page {
 	struct page	*p_page;
diff -druN linux-libre-3.3-gnu/fs/ext4/ext4_jbd2.h linux-libre-3.3.2-gnu/fs/ext4/ext4_jbd2.h
--- linux-libre-3.3-gnu/fs/ext4/ext4_jbd2.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/ext4_jbd2.h	2012-04-13 12:42:02.000000000 -0400
@@ -261,43 +261,45 @@
 /* super.c */
 int ext4_force_commit(struct super_block *sb);
 
-static inline int ext4_should_journal_data(struct inode *inode)
+/*
+ * Ext4 inode journal modes
+ */
+#define EXT4_INODE_JOURNAL_DATA_MODE	0x01 /* journal data mode */
+#define EXT4_INODE_ORDERED_DATA_MODE	0x02 /* ordered data mode */
+#define EXT4_INODE_WRITEBACK_DATA_MODE	0x04 /* writeback data mode */
+
+static inline int ext4_inode_journal_mode(struct inode *inode)
 {
 	if (EXT4_JOURNAL(inode) == NULL)
-		return 0;
-	if (!S_ISREG(inode->i_mode))
-		return 1;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
-		return 1;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 1;
-	return 0;
+		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
+	/* We do not support data journalling with delayed allocation */
+	if (!S_ISREG(inode->i_mode) ||
+	    test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
+	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
+	    !test_opt(inode->i_sb, DELALLOC))
+		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+		return EXT4_INODE_ORDERED_DATA_MODE;	/* ordered */
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
+	else
+		BUG();
+}
+
+static inline int ext4_should_journal_data(struct inode *inode)
+{
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE;
 }
 
 static inline int ext4_should_order_data(struct inode *inode)
 {
-	if (EXT4_JOURNAL(inode) == NULL)
-		return 0;
-	if (!S_ISREG(inode->i_mode))
-		return 0;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 0;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
-		return 1;
-	return 0;
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
 }
 
 static inline int ext4_should_writeback_data(struct inode *inode)
 {
-	if (EXT4_JOURNAL(inode) == NULL)
-		return 1;
-	if (!S_ISREG(inode->i_mode))
-		return 0;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 0;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
-		return 1;
-	return 0;
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE;
 }
 
 /*
diff -druN linux-libre-3.3-gnu/fs/ext4/extents.c linux-libre-3.3.2-gnu/fs/ext4/extents.c
--- linux-libre-3.3-gnu/fs/ext4/extents.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/extents.c	2012-04-13 12:42:02.000000000 -0400
@@ -300,6 +300,8 @@
 	ext4_fsblk_t block = ext4_ext_pblock(ext);
 	int len = ext4_ext_get_actual_len(ext);
 
+	if (len == 0)
+		return 0;
 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
 
diff -druN linux-libre-3.3-gnu/fs/ext4/fsync.c linux-libre-3.3.2-gnu/fs/ext4/fsync.c
--- linux-libre-3.3-gnu/fs/ext4/fsync.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/fsync.c	2012-04-13 12:42:02.000000000 -0400
@@ -89,6 +89,7 @@
 		io = list_entry(ei->i_completed_io_list.next,
 				ext4_io_end_t, list);
 		list_del_init(&io->list);
+		io->flag |= EXT4_IO_END_IN_FSYNC;
 		/*
 		 * Calling ext4_end_io_nolock() to convert completed
 		 * IO to written.
@@ -108,6 +109,7 @@
 		if (ret < 0)
 			ret2 = ret;
 		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+		io->flag &= ~EXT4_IO_END_IN_FSYNC;
 	}
 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	return (ret2 < 0) ? ret2 : 0;
diff -druN linux-libre-3.3-gnu/fs/ext4/inode.c linux-libre-3.3.2-gnu/fs/ext4/inode.c
--- linux-libre-3.3-gnu/fs/ext4/inode.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/inode.c	2012-04-13 12:42:02.000000000 -0400
@@ -2482,13 +2482,14 @@
 	int write_mode = (int)(unsigned long)fsdata;
 
 	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
-		if (ext4_should_order_data(inode)) {
+		switch (ext4_inode_journal_mode(inode)) {
+		case EXT4_INODE_ORDERED_DATA_MODE:
 			return ext4_ordered_write_end(file, mapping, pos,
 					len, copied, page, fsdata);
-		} else if (ext4_should_writeback_data(inode)) {
+		case EXT4_INODE_WRITEBACK_DATA_MODE:
 			return ext4_writeback_write_end(file, mapping, pos,
 					len, copied, page, fsdata);
-		} else {
+		default:
 			BUG();
 		}
 	}
@@ -2795,9 +2796,6 @@
 
 	/* queue the work to convert unwritten extents to written */
 	queue_work(wq, &io_end->work);
-
-	/* XXX: probably should move into the real I/O completion handler */
-	inode_dio_done(inode);
 }
 
 static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
@@ -2921,9 +2919,12 @@
 		iocb->private = NULL;
 		EXT4_I(inode)->cur_aio_dio = NULL;
 		if (!is_sync_kiocb(iocb)) {
-			iocb->private = ext4_init_io_end(inode, GFP_NOFS);
-			if (!iocb->private)
+			ext4_io_end_t *io_end =
+				ext4_init_io_end(inode, GFP_NOFS);
+			if (!io_end)
 				return -ENOMEM;
+			io_end->flag |= EXT4_IO_END_DIRECT;
+			iocb->private = io_end;
 			/*
 			 * we save the io structure for current async
 			 * direct IO, so that later ext4_map_blocks()
@@ -3086,18 +3087,25 @@
 
 void ext4_set_aops(struct inode *inode)
 {
-	if (ext4_should_order_data(inode) &&
-		test_opt(inode->i_sb, DELALLOC))
-		inode->i_mapping->a_ops = &ext4_da_aops;
-	else if (ext4_should_order_data(inode))
-		inode->i_mapping->a_ops = &ext4_ordered_aops;
-	else if (ext4_should_writeback_data(inode) &&
-		 test_opt(inode->i_sb, DELALLOC))
-		inode->i_mapping->a_ops = &ext4_da_aops;
-	else if (ext4_should_writeback_data(inode))
-		inode->i_mapping->a_ops = &ext4_writeback_aops;
-	else
+	switch (ext4_inode_journal_mode(inode)) {
+	case EXT4_INODE_ORDERED_DATA_MODE:
+		if (test_opt(inode->i_sb, DELALLOC))
+			inode->i_mapping->a_ops = &ext4_da_aops;
+		else
+			inode->i_mapping->a_ops = &ext4_ordered_aops;
+		break;
+	case EXT4_INODE_WRITEBACK_DATA_MODE:
+		if (test_opt(inode->i_sb, DELALLOC))
+			inode->i_mapping->a_ops = &ext4_da_aops;
+		else
+			inode->i_mapping->a_ops = &ext4_writeback_aops;
+		break;
+	case EXT4_INODE_JOURNAL_DATA_MODE:
 		inode->i_mapping->a_ops = &ext4_journalled_aops;
+		break;
+	default:
+		BUG();
+	}
 }
 
 
diff -druN linux-libre-3.3-gnu/fs/ext4/page-io.c linux-libre-3.3.2-gnu/fs/ext4/page-io.c
--- linux-libre-3.3-gnu/fs/ext4/page-io.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/ext4/page-io.c	2012-04-13 12:42:02.000000000 -0400
@@ -110,6 +110,8 @@
 	if (io->iocb)
 		aio_complete(io->iocb, io->result, 0);
 
+	if (io->flag & EXT4_IO_END_DIRECT)
+		inode_dio_done(inode);
 	/* Wake up anyone waiting on unwritten extent conversion */
 	if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
 		wake_up_all(ext4_ioend_wq(io->inode));
@@ -127,12 +129,18 @@
 	unsigned long		flags;
 
 	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	if (io->flag & EXT4_IO_END_IN_FSYNC)
+		goto requeue;
 	if (list_empty(&io->list)) {
 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 		goto free;
 	}
 
 	if (!mutex_trylock(&inode->i_mutex)) {
+		bool was_queued;
+requeue:
+		was_queued = !!(io->flag & EXT4_IO_END_QUEUED);
+		io->flag |= EXT4_IO_END_QUEUED;
 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 		/*
 		 * Requeue the work instead of waiting so that the work
@@ -145,9 +153,8 @@
 		 * yield the cpu if it sees an end_io request that has already
 		 * been requeued.
 		 */
-		if (io->flag & EXT4_IO_END_QUEUED)
+		if (was_queued)
 			yield();
-		io->flag |= EXT4_IO_END_QUEUED;
 		return;
 	}
 	list_del_init(&io->list);
diff -druN linux-libre-3.3-gnu/fs/hugetlbfs/inode.c linux-libre-3.3.2-gnu/fs/hugetlbfs/inode.c
--- linux-libre-3.3-gnu/fs/hugetlbfs/inode.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/hugetlbfs/inode.c	2012-04-13 12:42:02.000000000 -0400
@@ -238,17 +238,10 @@
 	loff_t isize;
 	ssize_t retval = 0;
 
-	mutex_lock(&inode->i_mutex);
-
 	/* validate length */
 	if (len == 0)
 		goto out;
 
-	isize = i_size_read(inode);
-	if (!isize)
-		goto out;
-
-	end_index = (isize - 1) >> huge_page_shift(h);
 	for (;;) {
 		struct page *page;
 		unsigned long nr, ret;
@@ -256,18 +249,21 @@
 
 		/* nr is the maximum number of bytes to copy from this page */
 		nr = huge_page_size(h);
+		isize = i_size_read(inode);
+		if (!isize)
+			goto out;
+		end_index = (isize - 1) >> huge_page_shift(h);
 		if (index >= end_index) {
 			if (index > end_index)
 				goto out;
 			nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
-			if (nr <= offset) {
+			if (nr <= offset)
 				goto out;
-			}
 		}
 		nr = nr - offset;
 
 		/* Find the page */
-		page = find_get_page(mapping, index);
+		page = find_lock_page(mapping, index);
 		if (unlikely(page == NULL)) {
 			/*
 			 * We have a HOLE, zero out the user-buffer for the
@@ -279,17 +275,18 @@
 			else
 				ra = 0;
 		} else {
+			unlock_page(page);
+
 			/*
 			 * We have the page, copy it to user space buffer.
 			 */
 			ra = hugetlbfs_read_actor(page, offset, buf, len, nr);
 			ret = ra;
+			page_cache_release(page);
 		}
 		if (ra < 0) {
 			if (retval == 0)
 				retval = ra;
-			if (page)
-				page_cache_release(page);
 			goto out;
 		}
 
@@ -299,16 +296,12 @@
 		index += offset >> huge_page_shift(h);
 		offset &= ~huge_page_mask(h);
 
-		if (page)
-			page_cache_release(page);
-
 		/* short read or no more work */
 		if ((ret != nr) || (len == 0))
 			break;
 	}
 out:
 	*ppos = ((loff_t)index << huge_page_shift(h)) + offset;
-	mutex_unlock(&inode->i_mutex);
 	return retval;
 }
 
diff -druN linux-libre-3.3-gnu/fs/jbd2/transaction.c linux-libre-3.3.2-gnu/fs/jbd2/transaction.c
--- linux-libre-3.3-gnu/fs/jbd2/transaction.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/jbd2/transaction.c	2012-04-13 12:42:02.000000000 -0400
@@ -1949,6 +1949,8 @@
 	clear_buffer_mapped(bh);
 	clear_buffer_req(bh);
 	clear_buffer_new(bh);
+	clear_buffer_delay(bh);
+	clear_buffer_unwritten(bh);
 	bh->b_bdev = NULL;
 	return may_free;
 }
diff -druN linux-libre-3.3-gnu/fs/lockd/svc.c linux-libre-3.3.2-gnu/fs/lockd/svc.c
--- linux-libre-3.3-gnu/fs/lockd/svc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/lockd/svc.c	2012-04-13 12:42:02.000000000 -0400
@@ -440,7 +440,7 @@
 	__typeof__(type) num = which_strtol(val, &endp, 0);		\
 	if (endp == val || *endp || num < (min) || num > (max))		\
 		return -EINVAL;						\
-	*((int *) kp->arg) = num;					\
+	*((type *) kp->arg) = num;					\
 	return 0;							\
 }
 
diff -druN linux-libre-3.3-gnu/fs/locks.c linux-libre-3.3.2-gnu/fs/locks.c
--- linux-libre-3.3-gnu/fs/locks.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/locks.c	2012-04-13 12:42:02.000000000 -0400
@@ -510,12 +510,13 @@
 
 /*
  */
-static void locks_delete_block(struct file_lock *waiter)
+void locks_delete_block(struct file_lock *waiter)
 {
 	lock_flocks();
 	__locks_delete_block(waiter);
 	unlock_flocks();
 }
+EXPORT_SYMBOL(locks_delete_block);
 
 /* Insert waiter into blocker's block list.
  * We use a circular list so that processes can be easily woken up in
diff -druN linux-libre-3.3-gnu/fs/nfs/callback_xdr.c linux-libre-3.3.2-gnu/fs/nfs/callback_xdr.c
--- linux-libre-3.3-gnu/fs/nfs/callback_xdr.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/callback_xdr.c	2012-04-13 12:42:02.000000000 -0400
@@ -9,6 +9,8 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include <linux/ratelimit.h>
+#include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/bc_xprt.h>
 #include "nfs4_fs.h"
@@ -167,7 +169,7 @@
 	if (hdr->minorversion <= 1) {
 		hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */
 	} else {
-		printk(KERN_WARNING "%s: NFSv4 server callback with "
+		pr_warn_ratelimited("NFS: %s: NFSv4 server callback with "
 			"illegal minor version %u!\n",
 			__func__, hdr->minorversion);
 		return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
diff -druN linux-libre-3.3-gnu/fs/nfs/delegation.c linux-libre-3.3.2-gnu/fs/nfs/delegation.c
--- linux-libre-3.3-gnu/fs/nfs/delegation.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/delegation.c	2012-04-13 12:42:02.000000000 -0400
@@ -466,6 +466,17 @@
 		nfs4_schedule_state_manager(clp);
 }
 
+void nfs_remove_bad_delegation(struct inode *inode)
+{
+	struct nfs_delegation *delegation;
+
+	delegation = nfs_detach_delegation(NFS_I(inode), NFS_SERVER(inode));
+	if (delegation) {
+		nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+		nfs_free_delegation(delegation);
+	}
+}
+
 /**
  * nfs_expire_all_delegation_types
  * @clp: client to process
diff -druN linux-libre-3.3-gnu/fs/nfs/delegation.h linux-libre-3.3.2-gnu/fs/nfs/delegation.h
--- linux-libre-3.3-gnu/fs/nfs/delegation.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/delegation.h	2012-04-13 12:42:02.000000000 -0400
@@ -45,6 +45,7 @@
 void nfs_handle_cb_pathdown(struct nfs_client *clp);
 int nfs_client_return_marked_delegations(struct nfs_client *clp);
 int nfs_delegations_present(struct nfs_client *clp);
+void nfs_remove_bad_delegation(struct inode *inode);
 
 void nfs_delegation_mark_reclaim(struct nfs_client *clp);
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
diff -druN linux-libre-3.3-gnu/fs/nfs/nfs4_fs.h linux-libre-3.3.2-gnu/fs/nfs/nfs4_fs.h
--- linux-libre-3.3-gnu/fs/nfs/nfs4_fs.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/nfs4_fs.h	2012-04-13 12:42:02.000000000 -0400
@@ -193,6 +193,7 @@
 	long timeout;
 	int retry;
 	struct nfs4_state *state;
+	struct inode *inode;
 };
 
 struct nfs4_state_recovery_ops {
@@ -327,6 +328,8 @@
 extern void nfs4_close_state(struct nfs4_state *, fmode_t);
 extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
+extern void nfs_inode_find_state_and_recover(struct inode *inode,
+		const nfs4_stateid *stateid);
 extern void nfs4_schedule_lease_recovery(struct nfs_client *);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
diff -druN linux-libre-3.3-gnu/fs/nfs/nfs4proc.c linux-libre-3.3.2-gnu/fs/nfs/nfs4proc.c
--- linux-libre-3.3-gnu/fs/nfs/nfs4proc.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/nfs4proc.c	2012-04-13 12:42:02.000000000 -0400
@@ -259,15 +259,28 @@
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_state *state = exception->state;
+	struct inode *inode = exception->inode;
 	int ret = errorcode;
 
 	exception->retry = 0;
 	switch(errorcode) {
 		case 0:
 			return 0;
+		case -NFS4ERR_OPENMODE:
+			if (nfs_have_delegation(inode, FMODE_READ)) {
+				nfs_inode_return_delegation(inode);
+				exception->retry = 1;
+				return 0;
+			}
+			if (state == NULL)
+				break;
+			nfs4_schedule_stateid_recovery(server, state);
+			goto wait_on_recovery;
+		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
-		case -NFS4ERR_OPENMODE:
+			if (state != NULL)
+				nfs_remove_bad_delegation(state->inode);
 			if (state == NULL)
 				break;
 			nfs4_schedule_stateid_recovery(server, state);
@@ -1319,8 +1332,11 @@
 				 * The show must go on: exit, but mark the
 				 * stateid as needing recovery.
 				 */
+			case -NFS4ERR_DELEG_REVOKED:
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_BAD_STATEID:
+				nfs_inode_find_state_and_recover(state->inode,
+						stateid);
 				nfs4_schedule_stateid_recovery(server, state);
 			case -EKEYEXPIRED:
 				/*
@@ -1829,7 +1845,7 @@
 		 * the user though...
 		 */
 		if (status == -NFS4ERR_BAD_SEQID) {
-			printk(KERN_WARNING "NFS: v4 server %s "
+			pr_warn_ratelimited("NFS: v4 server %s "
 					" returned a bad sequence-id error!\n",
 					NFS_SERVER(dir)->nfs_client->cl_hostname);
 			exception.retry = 1;
@@ -1900,7 +1916,10 @@
 			   struct nfs4_state *state)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {
+		.state = state,
+		.inode = inode,
+	};
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
@@ -2230,11 +2249,12 @@
 		switch (err) {
 		case 0:
 		case -NFS4ERR_WRONGSEC:
-			break;
+			goto out;
 		default:
 			err = nfs4_handle_exception(server, err, &exception);
 		}
 	} while (exception.retry);
+out:
 	return err;
 }
 
@@ -3605,7 +3625,7 @@
 		if (acl_len > buflen)
 			goto out_free;
 		_copy_from_pages(buf, pages, res.acl_data_offset,
-				res.acl_len);
+				acl_len);
 	}
 	ret = acl_len;
 out_free:
@@ -3714,8 +3734,11 @@
 	if (task->tk_status >= 0)
 		return 0;
 	switch(task->tk_status) {
+		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
+			if (state != NULL)
+				nfs_remove_bad_delegation(state->inode);
 		case -NFS4ERR_OPENMODE:
 			if (state == NULL)
 				break;
@@ -4533,7 +4556,9 @@
 
 static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {
+		.state = state,
+	};
 	int err;
 
 	do {
@@ -4626,6 +4651,7 @@
 				 * The show must go on: exit, but mark the
 				 * stateid as needing recovery.
 				 */
+			case -NFS4ERR_DELEG_REVOKED:
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_BAD_STATEID:
 			case -NFS4ERR_OPENMODE:
@@ -5926,21 +5952,22 @@
 		return;
 
 	switch (task->tk_status) { /* Just ignore these failures */
-	case NFS4ERR_DELEG_REVOKED: /* layout was recalled */
-	case NFS4ERR_BADIOMODE:     /* no IOMODE_RW layout for range */
-	case NFS4ERR_BADLAYOUT:     /* no layout */
-	case NFS4ERR_GRACE:	    /* loca_recalim always false */
+	case -NFS4ERR_DELEG_REVOKED: /* layout was recalled */
+	case -NFS4ERR_BADIOMODE:     /* no IOMODE_RW layout for range */
+	case -NFS4ERR_BADLAYOUT:     /* no layout */
+	case -NFS4ERR_GRACE:	    /* loca_recalim always false */
 		task->tk_status = 0;
-	}
-
-	if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
-		rpc_restart_call_prepare(task);
-		return;
-	}
-
-	if (task->tk_status == 0)
+		break;
+	case 0:
 		nfs_post_op_update_inode_force_wcc(data->args.inode,
 						   data->res.fattr);
+		break;
+	default:
+		if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+			rpc_restart_call_prepare(task);
+			return;
+		}
+	}
 }
 
 static void nfs4_layoutcommit_release(void *calldata)
@@ -6043,11 +6070,12 @@
 		case 0:
 		case -NFS4ERR_WRONGSEC:
 		case -NFS4ERR_NOTSUPP:
-			break;
+			goto out;
 		default:
 			err = nfs4_handle_exception(server, err, &exception);
 		}
 	} while (exception.retry);
+out:
 	return err;
 }
 
diff -druN linux-libre-3.3-gnu/fs/nfs/nfs4state.c linux-libre-3.3.2-gnu/fs/nfs/nfs4state.c
--- linux-libre-3.3-gnu/fs/nfs/nfs4state.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/nfs/nfs4state.c	2012-04-13 12:42:02.000000000 -0400
@@ -996,7 +996,7 @@
 		case -NFS4ERR_BAD_SEQID:
 			if (seqid->sequence->flags & NFS_SEQID_CONFIRMED)
 				return;
-			printk(KERN_WARNING "NFS: v4 server returned a bad"
+			pr_warn_ratelimited("NFS: v4 server returned a bad"
 					" sequence-id error on an"
 					" unconfirmed sequence %p!\n",
 					seqid->sequence);
@@ -1132,12 +1132,37 @@
 {
 	struct nfs_client *clp = server->nfs_client;
 
-	if (test_and_clear_bit(NFS_DELEGATED_STATE, &state->flags))
-		nfs_async_inode_return_delegation(state->inode, &state->stateid);
 	nfs4_state_mark_reclaim_nograce(clp, state);
 	nfs4_schedule_state_manager(clp);
 }
 
+void nfs_inode_find_state_and_recover(struct inode *inode,
+		const nfs4_stateid *stateid)
+{
+	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state;
+	bool found = false;
+
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(ctx, &nfsi->open_files, list) {
+		state = ctx->state;
+		if (state == NULL)
+			continue;
+		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+			continue;
+		if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+			continue;
+		nfs4_state_mark_reclaim_nograce(clp, state);
+		found = true;
+	}
+	spin_unlock(&inode->i_lock);
+	if (found)
+		nfs4_schedule_state_manager(clp);
+}
+
+
 static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
 {
 	struct inode *inode = state->inode;
@@ -1801,7 +1826,7 @@
 	} while (atomic_read(&clp->cl_count) > 1);
 	return;
 out_error:
-	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
+	pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s"
 			" with error %d\n", clp->cl_hostname, -status);
 	nfs4_end_drain_session(clp);
 	nfs4_clear_state_manager_bit(clp);
diff -druN linux-libre-3.3-gnu/fs/proc/namespaces.c linux-libre-3.3.2-gnu/fs/proc/namespaces.c
--- linux-libre-3.3-gnu/fs/proc/namespaces.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/proc/namespaces.c	2012-04-13 12:42:02.000000000 -0400
@@ -53,7 +53,7 @@
 	ei->ns_ops    = ns_ops;
 	ei->ns	      = ns;
 
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (pid_revalidate(dentry, NULL))
diff -druN linux-libre-3.3-gnu/fs/proc/proc_sysctl.c linux-libre-3.3.2-gnu/fs/proc/proc_sysctl.c
--- linux-libre-3.3-gnu/fs/proc/proc_sysctl.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/proc/proc_sysctl.c	2012-04-13 12:42:02.000000000 -0400
@@ -188,20 +188,32 @@
 
 static int proc_sys_open(struct inode *inode, struct file *filp)
 {
+	struct ctl_table_header *head = grab_header(inode);
 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
 
+	/* sysctl was unregistered */
+	if (IS_ERR(head))
+		return PTR_ERR(head);
+
 	if (table->poll)
 		filp->private_data = proc_sys_poll_event(table->poll);
 
+	sysctl_head_finish(head);
+
 	return 0;
 }
 
 static unsigned int proc_sys_poll(struct file *filp, poll_table *wait)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct ctl_table_header *head = grab_header(inode);
 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
-	unsigned long event = (unsigned long)filp->private_data;
 	unsigned int ret = DEFAULT_POLLMASK;
+	unsigned long event;
+
+	/* sysctl was unregistered */
+	if (IS_ERR(head))
+		return POLLERR | POLLHUP;
 
 	if (!table->proc_handler)
 		goto out;
@@ -209,6 +221,7 @@
 	if (!table->poll)
 		goto out;
 
+	event = (unsigned long)filp->private_data;
 	poll_wait(filp, &table->poll->wait, wait);
 
 	if (event != atomic_read(&table->poll->event)) {
@@ -217,6 +230,8 @@
 	}
 
 out:
+	sysctl_head_finish(head);
+
 	return ret;
 }
 
diff -druN linux-libre-3.3-gnu/fs/proc/task_mmu.c linux-libre-3.3.2-gnu/fs/proc/task_mmu.c
--- linux-libre-3.3-gnu/fs/proc/task_mmu.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/proc/task_mmu.c	2012-04-13 12:42:02.000000000 -0400
@@ -409,6 +409,9 @@
 	} else {
 		spin_unlock(&walk->mm->page_table_lock);
 	}
+
+	if (pmd_trans_unstable(pmd))
+		return 0;
 	/*
 	 * The mmap_sem held all the way back in m_start() is what
 	 * keeps khugepaged out of here and from collapsing things
@@ -507,6 +510,8 @@
 	struct page *page;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE) {
@@ -670,6 +675,8 @@
 	int err = 0;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	/* find the first VMA at or above 'addr' */
 	vma = find_vma(walk->mm, addr);
@@ -961,6 +968,8 @@
 		spin_unlock(&walk->mm->page_table_lock);
 	}
 
+	if (pmd_trans_unstable(pmd))
+		return 0;
 	orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
 	do {
 		struct page *page = can_gather_numa_stats(*pte, md->vma, addr);
diff -druN linux-libre-3.3-gnu/fs/sysfs/inode.c linux-libre-3.3.2-gnu/fs/sysfs/inode.c
--- linux-libre-3.3-gnu/fs/sysfs/inode.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/sysfs/inode.c	2012-04-13 12:42:02.000000000 -0400
@@ -136,12 +136,13 @@
 	void *old_secdata;
 	size_t old_secdata_len;
 
-	iattrs = sd->s_iattr;
-	if (!iattrs)
-		iattrs = sysfs_init_inode_attrs(sd);
-	if (!iattrs)
-		return -ENOMEM;
+	if (!sd->s_iattr) {
+		sd->s_iattr = sysfs_init_inode_attrs(sd);
+		if (!sd->s_iattr)
+			return -ENOMEM;
+	}
 
+	iattrs = sd->s_iattr;
 	old_secdata = iattrs->ia_secdata;
 	old_secdata_len = iattrs->ia_secdata_len;
 
diff -druN linux-libre-3.3-gnu/fs/xfs/xfs_iget.c linux-libre-3.3.2-gnu/fs/xfs/xfs_iget.c
--- linux-libre-3.3-gnu/fs/xfs/xfs_iget.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/xfs/xfs_iget.c	2012-04-13 12:42:02.000000000 -0400
@@ -350,9 +350,20 @@
 			BUG();
 	}
 
-	spin_lock(&pag->pag_ici_lock);
+	/*
+	 * These values must be set before inserting the inode into the radix
+	 * tree as the moment it is inserted a concurrent lookup (allowed by the
+	 * RCU locking mechanism) can find it and that lookup must see that this
+	 * is an inode currently under construction (i.e. that XFS_INEW is set).
+	 * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+	 * memory barrier that ensures this detection works correctly at lookup
+	 * time.
+	 */
+	ip->i_udquot = ip->i_gdquot = NULL;
+	xfs_iflags_set(ip, XFS_INEW);
 
 	/* insert the new inode */
+	spin_lock(&pag->pag_ici_lock);
 	error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
 	if (unlikely(error)) {
 		WARN_ON(error != -EEXIST);
@@ -360,11 +371,6 @@
 		error = EAGAIN;
 		goto out_preload_end;
 	}
-
-	/* These values _must_ be set before releasing the radix tree lock! */
-	ip->i_udquot = ip->i_gdquot = NULL;
-	xfs_iflags_set(ip, XFS_INEW);
-
 	spin_unlock(&pag->pag_ici_lock);
 	radix_tree_preload_end();
 
diff -druN linux-libre-3.3-gnu/fs/xfs/xfs_log_recover.c linux-libre-3.3.2-gnu/fs/xfs/xfs_log_recover.c
--- linux-libre-3.3-gnu/fs/xfs/xfs_log_recover.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/fs/xfs/xfs_log_recover.c	2012-04-13 12:42:02.000000000 -0400
@@ -3161,37 +3161,26 @@
 			 */
 			continue;
 		}
+		/*
+		 * Unlock the buffer so that it can be acquired in the normal
+		 * course of the transaction to truncate and free each inode.
+		 * Because we are not racing with anyone else here for the AGI
+		 * buffer, we don't even need to hold it locked to read the
+		 * initial unlinked bucket entries out of the buffer. We keep
+		 * buffer reference though, so that it stays pinned in memory
+		 * while we need the buffer.
+		 */
 		agi = XFS_BUF_TO_AGI(agibp);
+		xfs_buf_unlock(agibp);
 
 		for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
 			agino = be32_to_cpu(agi->agi_unlinked[bucket]);
 			while (agino != NULLAGINO) {
-				/*
-				 * Release the agi buffer so that it can
-				 * be acquired in the normal course of the
-				 * transaction to truncate and free the inode.
-				 */
-				xfs_buf_relse(agibp);
-
 				agino = xlog_recover_process_one_iunlink(mp,
 							agno, agino, bucket);
-
-				/*
-				 * Reacquire the agibuffer and continue around
-				 * the loop. This should never fail as we know
-				 * the buffer was good earlier on.
-				 */
-				error = xfs_read_agi(mp, NULL, agno, &agibp);
-				ASSERT(error == 0);
-				agi = XFS_BUF_TO_AGI(agibp);
 			}
 		}
-
-		/*
-		 * Release the buffer for the current agi so we can
-		 * go on to the next one.
-		 */
-		xfs_buf_relse(agibp);
+		xfs_buf_rele(agibp);
 	}
 
 	mp->m_dmevmask = mp_dmevmask;
diff -druN linux-libre-3.3-gnu/include/asm-generic/pgtable.h linux-libre-3.3.2-gnu/include/asm-generic/pgtable.h
--- linux-libre-3.3-gnu/include/asm-generic/pgtable.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/asm-generic/pgtable.h	2012-04-13 12:42:02.000000000 -0400
@@ -425,6 +425,8 @@
 				unsigned long size);
 #endif
 
+#ifdef CONFIG_MMU
+
 #ifndef CONFIG_TRANSPARENT_HUGEPAGE
 static inline int pmd_trans_huge(pmd_t pmd)
 {
@@ -441,7 +443,66 @@
 	return 0;
 }
 #endif /* __HAVE_ARCH_PMD_WRITE */
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+/*
+ * This function is meant to be used by sites walking pagetables with
+ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and
+ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd
+ * into a null pmd and the transhuge page fault can convert a null pmd
+ * into an hugepmd or into a regular pmd (if the hugepage allocation
+ * fails). While holding the mmap_sem in read mode the pmd becomes
+ * stable and stops changing under us only if it's not null and not a
+ * transhuge pmd. When those races occurs and this function makes a
+ * difference vs the standard pmd_none_or_clear_bad, the result is
+ * undefined so behaving like if the pmd was none is safe (because it
+ * can return none anyway). The compiler level barrier() is critically
+ * important to compute the two checks atomically on the same pmdval.
+ */
+static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
+{
+	/* depend on compiler for an atomic pmd read */
+	pmd_t pmdval = *pmd;
+	/*
+	 * The barrier will stabilize the pmdval in a register or on
+	 * the stack so that it will stop changing under the code.
+	 */
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	barrier();
 #endif
+	if (pmd_none(pmdval))
+		return 1;
+	if (unlikely(pmd_bad(pmdval))) {
+		if (!pmd_trans_huge(pmdval))
+			pmd_clear_bad(pmd);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * This is a noop if Transparent Hugepage Support is not built into
+ * the kernel. Otherwise it is equivalent to
+ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in
+ * places that already verified the pmd is not none and they want to
+ * walk ptes while holding the mmap sem in read mode (write mode don't
+ * need this). If THP is not enabled, the pmd can't go away under the
+ * code even if MADV_DONTNEED runs, but if THP is enabled we need to
+ * run a pmd_trans_unstable before walking the ptes after
+ * split_huge_page_pmd returns (because it may have run when the pmd
+ * become null, but then a page fault can map in a THP and not a
+ * regular page).
+ */
+static inline int pmd_trans_unstable(pmd_t *pmd)
+{
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	return pmd_none_or_trans_huge_or_clear_bad(pmd);
+#else
+	return 0;
+#endif
+}
+
+#endif /* CONFIG_MMU */
 
 #endif /* !__ASSEMBLY__ */
 
diff -druN linux-libre-3.3-gnu/include/asm-generic/unistd.h linux-libre-3.3.2-gnu/include/asm-generic/unistd.h
--- linux-libre-3.3-gnu/include/asm-generic/unistd.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/asm-generic/unistd.h	2012-04-13 12:42:02.000000000 -0400
@@ -218,7 +218,7 @@
 
 /* fs/sendfile.c */
 #define __NR3264_sendfile 71
-__SC_3264(__NR3264_sendfile, sys_sendfile64, sys_sendfile)
+__SYSCALL(__NR3264_sendfile, sys_sendfile64)
 
 /* fs/select.c */
 #define __NR_pselect6 72
diff -druN linux-libre-3.3-gnu/include/linux/fb.h linux-libre-3.3.2-gnu/include/linux/fb.h
--- linux-libre-3.3-gnu/include/linux/fb.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/fb.h	2012-04-13 12:42:02.000000000 -0400
@@ -1003,6 +1003,7 @@
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
+extern int unlink_framebuffer(struct fb_info *fb_info);
 extern void remove_conflicting_framebuffers(struct apertures_struct *a,
 				const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
diff -druN linux-libre-3.3-gnu/include/linux/fs.h linux-libre-3.3.2-gnu/include/linux/fs.h
--- linux-libre-3.3-gnu/include/linux/fs.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/fs.h	2012-04-13 12:42:02.000000000 -0400
@@ -1210,6 +1210,7 @@
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void locks_delete_block(struct file_lock *waiter);
 extern void lock_flocks(void);
 extern void unlock_flocks(void);
 #else /* !CONFIG_FILE_LOCKING */
@@ -1354,6 +1355,10 @@
 	return 1;
 }
 
+static inline void locks_delete_block(struct file_lock *waiter)
+{
+}
+
 static inline void lock_flocks(void)
 {
 }
diff -druN linux-libre-3.3-gnu/include/linux/kernel.h linux-libre-3.3.2-gnu/include/linux/kernel.h
--- linux-libre-3.3-gnu/include/linux/kernel.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/kernel.h	2012-04-13 12:42:02.000000000 -0400
@@ -85,6 +85,19 @@
 }							\
 )
 
+/*
+ * Multiplies an integer by a fraction, while avoiding unnecessary
+ * overflow or loss of precision.
+ */
+#define mult_frac(x, numer, denom)(			\
+{							\
+	typeof(x) quot = (x) / (denom);			\
+	typeof(x) rem  = (x) % (denom);			\
+	(quot * (numer)) + ((rem * (numer)) / (denom));	\
+}							\
+)
+
+
 #define _RET_IP_		(unsigned long)__builtin_return_address(0)
 #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
 
diff -druN linux-libre-3.3-gnu/include/linux/kgdb.h linux-libre-3.3.2-gnu/include/linux/kgdb.h
--- linux-libre-3.3-gnu/include/linux/kgdb.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/kgdb.h	2012-04-13 12:42:02.000000000 -0400
@@ -63,7 +63,8 @@
 	BP_HARDWARE_BREAKPOINT,
 	BP_WRITE_WATCHPOINT,
 	BP_READ_WATCHPOINT,
-	BP_ACCESS_WATCHPOINT
+	BP_ACCESS_WATCHPOINT,
+	BP_POKE_BREAKPOINT,
 };
 
 enum kgdb_bpstate {
@@ -207,8 +208,8 @@
 
 /* Optional functions. */
 extern int kgdb_validate_break_address(unsigned long addr);
-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
+extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
 
 /**
  *	kgdb_arch_late - Perform any architecture specific initalization.
diff -druN linux-libre-3.3-gnu/include/linux/kmod.h linux-libre-3.3.2-gnu/include/linux/kmod.h
--- linux-libre-3.3-gnu/include/linux/kmod.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/kmod.h	2012-04-13 12:42:02.000000000 -0400
@@ -112,12 +112,29 @@
 
 extern struct ctl_table usermodehelper_table[];
 
+enum umh_disable_depth {
+	UMH_ENABLED = 0,
+	UMH_FREEZING,
+	UMH_DISABLED,
+};
+
 extern void usermodehelper_init(void);
 
-extern int usermodehelper_disable(void);
-extern void usermodehelper_enable(void);
-extern bool usermodehelper_is_disabled(void);
-extern void read_lock_usermodehelper(void);
-extern void read_unlock_usermodehelper(void);
+extern int __usermodehelper_disable(enum umh_disable_depth depth);
+extern void __usermodehelper_set_disable_depth(enum umh_disable_depth depth);
+
+static inline int usermodehelper_disable(void)
+{
+	return __usermodehelper_disable(UMH_DISABLED);
+}
+
+static inline void usermodehelper_enable(void)
+{
+	__usermodehelper_set_disable_depth(UMH_ENABLED);
+}
+
+extern int usermodehelper_read_trylock(void);
+extern long usermodehelper_read_lock_wait(long timeout);
+extern void usermodehelper_read_unlock(void);
 
 #endif /* __LINUX_KMOD_H__ */
diff -druN linux-libre-3.3-gnu/include/linux/math64.h linux-libre-3.3.2-gnu/include/linux/math64.h
--- linux-libre-3.3-gnu/include/linux/math64.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/math64.h	2012-04-13 12:42:02.000000000 -0400
@@ -6,6 +6,8 @@
 
 #if BITS_PER_LONG == 64
 
+#define div64_long(x,y) div64_s64((x),(y))
+
 /**
  * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
  *
@@ -45,6 +47,8 @@
 
 #elif BITS_PER_LONG == 32
 
+#define div64_long(x,y) div_s64((x),(y))
+
 #ifndef div_u64_rem
 static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 {
diff -druN linux-libre-3.3-gnu/include/linux/pm_domain.h linux-libre-3.3.2-gnu/include/linux/pm_domain.h
--- linux-libre-3.3-gnu/include/linux/pm_domain.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/pm_domain.h	2012-04-13 12:42:02.000000000 -0400
@@ -97,6 +97,7 @@
 	struct gpd_dev_ops ops;
 	struct gpd_timing_data td;
 	bool need_restore;
+	bool always_on;
 };
 
 static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
@@ -125,6 +126,7 @@
 
 extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 				  struct device *dev);
+extern void pm_genpd_dev_always_on(struct device *dev, bool val);
 extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 				  struct generic_pm_domain *new_subdomain);
 extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
@@ -163,6 +165,7 @@
 {
 	return -ENOSYS;
 }
+static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {}
 static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 					 struct generic_pm_domain *new_sd)
 {
diff -druN linux-libre-3.3-gnu/include/linux/rtc.h linux-libre-3.3.2-gnu/include/linux/rtc.h
--- linux-libre-3.3-gnu/include/linux/rtc.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/linux/rtc.h	2012-04-13 12:42:02.000000000 -0400
@@ -202,7 +202,8 @@
 	struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */
 	int pie_enabled;
 	struct work_struct irqwork;
-
+	/* Some hardware can't support UIE mode */
+	int uie_unsupported;
 
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
 	struct work_struct uie_task;
diff -druN linux-libre-3.3-gnu/include/target/target_core_base.h linux-libre-3.3.2-gnu/include/target/target_core_base.h
--- linux-libre-3.3-gnu/include/target/target_core_base.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/include/target/target_core_base.h	2012-04-13 12:42:02.000000000 -0400
@@ -118,9 +118,9 @@
 /* Queue Algorithm Modifier default for restricted reordering in control mode page */
 #define DA_EMULATE_REST_REORD			0
 
+#define SE_INQUIRY_BUF				512
 #define SE_MODE_PAGE_BUF			512
 
-
 /* struct se_hba->hba_flags */
 enum hba_flags_table {
 	HBA_FLAGS_INTERNAL_USE	= 0x01,
diff -druN linux-libre-3.3-gnu/kernel/cred.c linux-libre-3.3.2-gnu/kernel/cred.c
--- linux-libre-3.3-gnu/kernel/cred.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/cred.c	2012-04-13 12:42:02.000000000 -0400
@@ -385,6 +385,8 @@
 	struct cred *new;
 	int ret;
 
+	p->replacement_session_keyring = NULL;
+
 	if (
 #ifdef CONFIG_KEYS
 		!p->cred->thread_keyring &&
diff -druN linux-libre-3.3-gnu/kernel/debug/debug_core.c linux-libre-3.3.2-gnu/kernel/debug/debug_core.c
--- linux-libre-3.3-gnu/kernel/debug/debug_core.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/debug/debug_core.c	2012-04-13 12:42:02.000000000 -0400
@@ -157,37 +157,39 @@
  * Weak aliases for breakpoint management,
  * can be overriden by architectures when needed:
  */
-int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
 	int err;
 
-	err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
+	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+				BREAK_INSTR_SIZE);
 	if (err)
 		return err;
-
-	return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
-				  BREAK_INSTR_SIZE);
+	err = probe_kernel_write((char *)bpt->bpt_addr,
+				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+	return err;
 }
 
-int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-	return probe_kernel_write((char *)addr,
-				  (char *)bundle, BREAK_INSTR_SIZE);
+	return probe_kernel_write((char *)bpt->bpt_addr,
+				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
 int __weak kgdb_validate_break_address(unsigned long addr)
 {
-	char tmp_variable[BREAK_INSTR_SIZE];
+	struct kgdb_bkpt tmp;
 	int err;
-	/* Validate setting the breakpoint and then removing it.  In the
+	/* Validate setting the breakpoint and then removing it.  If the
 	 * remove fails, the kernel needs to emit a bad message because we
 	 * are deep trouble not being able to put things back the way we
 	 * found them.
 	 */
-	err = kgdb_arch_set_breakpoint(addr, tmp_variable);
+	tmp.bpt_addr = addr;
+	err = kgdb_arch_set_breakpoint(&tmp);
 	if (err)
 		return err;
-	err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
+	err = kgdb_arch_remove_breakpoint(&tmp);
 	if (err)
 		printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
 		   "memory destroyed at: %lx", addr);
@@ -231,7 +233,6 @@
  */
 int dbg_activate_sw_breakpoints(void)
 {
-	unsigned long addr;
 	int error;
 	int ret = 0;
 	int i;
@@ -240,16 +241,15 @@
 		if (kgdb_break[i].state != BP_SET)
 			continue;
 
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_set_breakpoint(addr,
-				kgdb_break[i].saved_instr);
+		error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
 		if (error) {
 			ret = error;
-			printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
+			printk(KERN_INFO "KGDB: BP install failed: %lx",
+			       kgdb_break[i].bpt_addr);
 			continue;
 		}
 
-		kgdb_flush_swbreak_addr(addr);
+		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
 		kgdb_break[i].state = BP_ACTIVE;
 	}
 	return ret;
@@ -298,7 +298,6 @@
 
 int dbg_deactivate_sw_breakpoints(void)
 {
-	unsigned long addr;
 	int error;
 	int ret = 0;
 	int i;
@@ -306,15 +305,14 @@
 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
 		if (kgdb_break[i].state != BP_ACTIVE)
 			continue;
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_remove_breakpoint(addr,
-					kgdb_break[i].saved_instr);
+		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
 		if (error) {
-			printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
+			printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
+			       kgdb_break[i].bpt_addr);
 			ret = error;
 		}
 
-		kgdb_flush_swbreak_addr(addr);
+		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
 		kgdb_break[i].state = BP_SET;
 	}
 	return ret;
@@ -348,7 +346,6 @@
 
 int dbg_remove_all_break(void)
 {
-	unsigned long addr;
 	int error;
 	int i;
 
@@ -356,12 +353,10 @@
 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
 		if (kgdb_break[i].state != BP_ACTIVE)
 			goto setundefined;
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_remove_breakpoint(addr,
-				kgdb_break[i].saved_instr);
+		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
 		if (error)
 			printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
-			   addr);
+			       kgdb_break[i].bpt_addr);
 setundefined:
 		kgdb_break[i].state = BP_UNDEFINED;
 	}
diff -druN linux-libre-3.3-gnu/kernel/futex.c linux-libre-3.3.2-gnu/kernel/futex.c
--- linux-libre-3.3-gnu/kernel/futex.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/futex.c	2012-04-13 12:42:02.000000000 -0400
@@ -2641,6 +2641,16 @@
 	}
 
 	switch (cmd) {
+	case FUTEX_LOCK_PI:
+	case FUTEX_UNLOCK_PI:
+	case FUTEX_TRYLOCK_PI:
+	case FUTEX_WAIT_REQUEUE_PI:
+	case FUTEX_CMP_REQUEUE_PI:
+		if (!futex_cmpxchg_enabled)
+			return -ENOSYS;
+	}
+
+	switch (cmd) {
 	case FUTEX_WAIT:
 		val3 = FUTEX_BITSET_MATCH_ANY;
 	case FUTEX_WAIT_BITSET:
@@ -2661,16 +2671,13 @@
 		ret = futex_wake_op(uaddr, flags, uaddr2, val, val2, val3);
 		break;
 	case FUTEX_LOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, flags, val, timeout, 0);
+		ret = futex_lock_pi(uaddr, flags, val, timeout, 0);
 		break;
 	case FUTEX_UNLOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_unlock_pi(uaddr, flags);
+		ret = futex_unlock_pi(uaddr, flags);
 		break;
 	case FUTEX_TRYLOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, flags, 0, timeout, 1);
+		ret = futex_lock_pi(uaddr, flags, 0, timeout, 1);
 		break;
 	case FUTEX_WAIT_REQUEUE_PI:
 		val3 = FUTEX_BITSET_MATCH_ANY;
diff -druN linux-libre-3.3-gnu/kernel/irq/chip.c linux-libre-3.3.2-gnu/kernel/irq/chip.c
--- linux-libre-3.3-gnu/kernel/irq/chip.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/irq/chip.c	2012-04-13 12:42:02.000000000 -0400
@@ -61,8 +61,7 @@
 		return -EINVAL;
 
 	type &= IRQ_TYPE_SENSE_MASK;
-	if (type != IRQ_TYPE_NONE)
-		ret = __irq_set_trigger(desc, irq, type);
+	ret = __irq_set_trigger(desc, irq, type);
 	irq_put_desc_busunlock(desc, flags);
 	return ret;
 }
diff -druN linux-libre-3.3-gnu/kernel/irq/manage.c linux-libre-3.3.2-gnu/kernel/irq/manage.c
--- linux-libre-3.3-gnu/kernel/irq/manage.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/irq/manage.c	2012-04-13 12:42:02.000000000 -0400
@@ -773,7 +773,7 @@
 			struct irqaction *action);
 	int wake;
 
-	if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
+	if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
 					&action->thread_flags))
 		handler_fn = irq_forced_thread_fn;
 	else
diff -druN linux-libre-3.3-gnu/kernel/irq/migration.c linux-libre-3.3.2-gnu/kernel/irq/migration.c
--- linux-libre-3.3-gnu/kernel/irq/migration.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/irq/migration.c	2012-04-13 12:42:02.000000000 -0400
@@ -43,12 +43,16 @@
 	 * masking the irqs.
 	 */
 	if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
-		   < nr_cpu_ids))
-		if (!chip->irq_set_affinity(&desc->irq_data,
-					    desc->pending_mask, false)) {
+		   < nr_cpu_ids)) {
+		int ret = chip->irq_set_affinity(&desc->irq_data,
+						 desc->pending_mask, false);
+		switch (ret) {
+		case IRQ_SET_MASK_OK:
 			cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
+		case IRQ_SET_MASK_OK_NOCOPY:
 			irq_set_thread_affinity(desc);
 		}
+	}
 
 	cpumask_clear(desc->pending_mask);
 }
diff -druN linux-libre-3.3-gnu/kernel/kmod.c linux-libre-3.3.2-gnu/kernel/kmod.c
--- linux-libre-3.3-gnu/kernel/kmod.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/kmod.c	2012-04-13 12:42:02.000000000 -0400
@@ -279,7 +279,7 @@
  * land has been frozen during a system-wide hibernation or suspend operation).
  * Should always be manipulated under umhelper_sem acquired for write.
  */
-static int usermodehelper_disabled = 1;
+static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED;
 
 /* Number of helpers running */
 static atomic_t running_helpers = ATOMIC_INIT(0);
@@ -291,32 +291,110 @@
 static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
 
 /*
+ * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
+ * to become 'false'.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
+
+/*
  * Time to wait for running_helpers to become zero before the setting of
  * usermodehelper_disabled in usermodehelper_disable() fails
  */
 #define RUNNING_HELPERS_TIMEOUT	(5 * HZ)
 
-void read_lock_usermodehelper(void)
+int usermodehelper_read_trylock(void)
 {
+	DEFINE_WAIT(wait);
+	int ret = 0;
+
 	down_read(&umhelper_sem);
+	for (;;) {
+		prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+				TASK_INTERRUPTIBLE);
+		if (!usermodehelper_disabled)
+			break;
+
+		if (usermodehelper_disabled == UMH_DISABLED)
+			ret = -EAGAIN;
+
+		up_read(&umhelper_sem);
+
+		if (ret)
+			break;
+
+		schedule();
+		try_to_freeze();
+
+		down_read(&umhelper_sem);
+	}
+	finish_wait(&usermodehelper_disabled_waitq, &wait);
+	return ret;
 }
-EXPORT_SYMBOL_GPL(read_lock_usermodehelper);
+EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
 
-void read_unlock_usermodehelper(void)
+long usermodehelper_read_lock_wait(long timeout)
+{
+	DEFINE_WAIT(wait);
+
+	if (timeout < 0)
+		return -EINVAL;
+
+	down_read(&umhelper_sem);
+	for (;;) {
+		prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if (!usermodehelper_disabled)
+			break;
+
+		up_read(&umhelper_sem);
+
+		timeout = schedule_timeout(timeout);
+		if (!timeout)
+			break;
+
+		down_read(&umhelper_sem);
+	}
+	finish_wait(&usermodehelper_disabled_waitq, &wait);
+	return timeout;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
+
+void usermodehelper_read_unlock(void)
 {
 	up_read(&umhelper_sem);
 }
-EXPORT_SYMBOL_GPL(read_unlock_usermodehelper);
+EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
 
 /**
- * usermodehelper_disable - prevent new helpers from being started
+ * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled.
+ * depth: New value to assign to usermodehelper_disabled.
+ *
+ * Change the value of usermodehelper_disabled (under umhelper_sem locked for
+ * writing) and wakeup tasks waiting for it to change.
  */
-int usermodehelper_disable(void)
+void __usermodehelper_set_disable_depth(enum umh_disable_depth depth)
+{
+	down_write(&umhelper_sem);
+	usermodehelper_disabled = depth;
+	wake_up(&usermodehelper_disabled_waitq);
+	up_write(&umhelper_sem);
+}
+
+/**
+ * __usermodehelper_disable - Prevent new helpers from being started.
+ * @depth: New value to assign to usermodehelper_disabled.
+ *
+ * Set usermodehelper_disabled to @depth and wait for running helpers to exit.
+ */
+int __usermodehelper_disable(enum umh_disable_depth depth)
 {
 	long retval;
 
+	if (!depth)
+		return -EINVAL;
+
 	down_write(&umhelper_sem);
-	usermodehelper_disabled = 1;
+	usermodehelper_disabled = depth;
 	up_write(&umhelper_sem);
 
 	/*
@@ -331,31 +409,10 @@
 	if (retval)
 		return 0;
 
-	down_write(&umhelper_sem);
-	usermodehelper_disabled = 0;
-	up_write(&umhelper_sem);
+	__usermodehelper_set_disable_depth(UMH_ENABLED);
 	return -EAGAIN;
 }
 
-/**
- * usermodehelper_enable - allow new helpers to be started again
- */
-void usermodehelper_enable(void)
-{
-	down_write(&umhelper_sem);
-	usermodehelper_disabled = 0;
-	up_write(&umhelper_sem);
-}
-
-/**
- * usermodehelper_is_disabled - check if new helpers are allowed to be started
- */
-bool usermodehelper_is_disabled(void)
-{
-	return usermodehelper_disabled;
-}
-EXPORT_SYMBOL_GPL(usermodehelper_is_disabled);
-
 static void helper_lock(void)
 {
 	atomic_inc(&running_helpers);
diff -druN linux-libre-3.3-gnu/kernel/module.c linux-libre-3.3.2-gnu/kernel/module.c
--- linux-libre-3.3-gnu/kernel/module.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/module.c	2012-04-13 12:42:02.000000000 -0400
@@ -2380,8 +2380,7 @@
 		return -ENOEXEC;
 
 	/* Suck in entire file: we'll want most of it. */
-	/* vmalloc barfs on "unusual" numbers.  Check here */
-	if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
+	if ((hdr = vmalloc(len)) == NULL)
 		return -ENOMEM;
 
 	if (copy_from_user(hdr, umod, len) != 0) {
diff -druN linux-libre-3.3-gnu/kernel/power/hibernate.c linux-libre-3.3.2-gnu/kernel/power/hibernate.c
--- linux-libre-3.3-gnu/kernel/power/hibernate.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/power/hibernate.c	2012-04-13 12:42:02.000000000 -0400
@@ -16,7 +16,6 @@
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/async.h>
-#include <linux/kmod.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -609,10 +608,6 @@
 	if (error)
 		goto Exit;
 
-	error = usermodehelper_disable();
-	if (error)
-		goto Exit;
-
 	/* Allocate memory management structures */
 	error = create_basic_memory_bitmaps();
 	if (error)
@@ -624,7 +619,7 @@
 
 	error = freeze_processes();
 	if (error)
-		goto Finish;
+		goto Free_bitmaps;
 
 	error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
 	if (error)
@@ -657,9 +652,8 @@
 
  Thaw:
 	thaw_processes();
- Finish:
+ Free_bitmaps:
 	free_basic_memory_bitmaps();
-	usermodehelper_enable();
  Exit:
 	pm_notifier_call_chain(PM_POST_HIBERNATION);
 	pm_restore_console();
@@ -774,15 +768,9 @@
 	if (error)
 		goto close_finish;
 
-	error = usermodehelper_disable();
-	if (error)
-		goto close_finish;
-
 	error = create_basic_memory_bitmaps();
-	if (error) {
-		usermodehelper_enable();
+	if (error)
 		goto close_finish;
-	}
 
 	pr_debug("PM: Preparing processes for restore.\n");
 	error = freeze_processes();
@@ -803,7 +791,6 @@
 	thaw_processes();
  Done:
 	free_basic_memory_bitmaps();
-	usermodehelper_enable();
  Finish:
 	pm_notifier_call_chain(PM_POST_RESTORE);
 	pm_restore_console();
diff -druN linux-libre-3.3-gnu/kernel/power/process.c linux-libre-3.3.2-gnu/kernel/power/process.c
--- linux-libre-3.3-gnu/kernel/power/process.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/power/process.c	2012-04-13 12:42:02.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/kmod.h>
 
 /* 
  * Timeout for stopping processes
@@ -122,6 +123,10 @@
 {
 	int error;
 
+	error = __usermodehelper_disable(UMH_FREEZING);
+	if (error)
+		return error;
+
 	if (!pm_freezing)
 		atomic_inc(&system_freezing_cnt);
 
@@ -130,6 +135,7 @@
 	error = try_to_freeze_tasks(true);
 	if (!error) {
 		printk("done.");
+		__usermodehelper_set_disable_depth(UMH_DISABLED);
 		oom_killer_disable();
 	}
 	printk("\n");
@@ -187,6 +193,8 @@
 	} while_each_thread(g, p);
 	read_unlock(&tasklist_lock);
 
+	usermodehelper_enable();
+
 	schedule();
 	printk("done.\n");
 }
diff -druN linux-libre-3.3-gnu/kernel/power/suspend.c linux-libre-3.3.2-gnu/kernel/power/suspend.c
--- linux-libre-3.3-gnu/kernel/power/suspend.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/power/suspend.c	2012-04-13 12:42:02.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/kmod.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
@@ -101,17 +100,12 @@
 	if (error)
 		goto Finish;
 
-	error = usermodehelper_disable();
-	if (error)
-		goto Finish;
-
 	error = suspend_freeze_processes();
 	if (!error)
 		return 0;
 
 	suspend_stats.failed_freeze++;
 	dpm_save_failed_step(SUSPEND_FREEZE);
-	usermodehelper_enable();
  Finish:
 	pm_notifier_call_chain(PM_POST_SUSPEND);
 	pm_restore_console();
@@ -259,7 +253,6 @@
 static void suspend_finish(void)
 {
 	suspend_thaw_processes();
-	usermodehelper_enable();
 	pm_notifier_call_chain(PM_POST_SUSPEND);
 	pm_restore_console();
 }
diff -druN linux-libre-3.3-gnu/kernel/power/user.c linux-libre-3.3.2-gnu/kernel/power/user.c
--- linux-libre-3.3-gnu/kernel/power/user.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/power/user.c	2012-04-13 12:42:02.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
 #include <linux/reboot.h>
-#include <linux/kmod.h>
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
@@ -222,14 +221,8 @@
 		sys_sync();
 		printk("done.\n");
 
-		error = usermodehelper_disable();
-		if (error)
-			break;
-
 		error = freeze_processes();
-		if (error)
-			usermodehelper_enable();
-		else
+		if (!error)
 			data->frozen = 1;
 		break;
 
@@ -238,7 +231,6 @@
 			break;
 		pm_restore_gfp_mask();
 		thaw_processes();
-		usermodehelper_enable();
 		data->frozen = 0;
 		break;
 
diff -druN linux-libre-3.3-gnu/kernel/sysctl.c linux-libre-3.3.2-gnu/kernel/sysctl.c
--- linux-libre-3.3-gnu/kernel/sysctl.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/sysctl.c	2012-04-13 12:42:02.000000000 -0400
@@ -166,7 +166,7 @@
 #endif
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
@@ -713,7 +713,7 @@
 		.data		= &dmesg_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
+		.proc_handler	= proc_dointvec_minmax_sysadmin,
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
@@ -722,7 +722,7 @@
 		.data		= &kptr_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dmesg_restrict,
+		.proc_handler	= proc_dointvec_minmax_sysadmin,
 		.extra1		= &zero,
 		.extra2		= &two,
 	},
@@ -2431,7 +2431,7 @@
 }
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	if (write && !capable(CAP_SYS_ADMIN))
diff -druN linux-libre-3.3-gnu/kernel/time/ntp.c linux-libre-3.3.2-gnu/kernel/time/ntp.c
--- linux-libre-3.3-gnu/kernel/time/ntp.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/time/ntp.c	2012-04-13 12:42:02.000000000 -0400
@@ -275,7 +275,7 @@
 
 	time_status |= STA_MODE;
 
-	return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
+	return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
 }
 
 static void ntp_update_offset(long offset)
diff -druN linux-libre-3.3-gnu/kernel/trace/trace.c linux-libre-3.3.2-gnu/kernel/trace/trace.c
--- linux-libre-3.3-gnu/kernel/trace/trace.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/trace/trace.c	2012-04-13 12:42:02.000000000 -0400
@@ -1644,6 +1644,7 @@
 	int cpu_file = iter->cpu_file;
 	u64 next_ts = 0, ts;
 	int next_cpu = -1;
+	int next_size = 0;
 	int cpu;
 
 	/*
@@ -1675,9 +1676,12 @@
 			next_cpu = cpu;
 			next_ts = ts;
 			next_lost = lost_events;
+			next_size = iter->ent_size;
 		}
 	}
 
+	iter->ent_size = next_size;
+
 	if (ent_cpu)
 		*ent_cpu = next_cpu;
 
diff -druN linux-libre-3.3-gnu/kernel/trace/trace_entries.h linux-libre-3.3.2-gnu/kernel/trace/trace_entries.h
--- linux-libre-3.3-gnu/kernel/trace/trace_entries.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/trace/trace_entries.h	2012-04-13 12:42:02.000000000 -0400
@@ -156,6 +156,12 @@
 
 #define FTRACE_STACK_ENTRIES	8
 
+#ifndef CONFIG_64BIT
+# define IP_FMT "%08lx"
+#else
+# define IP_FMT "%016lx"
+#endif
+
 FTRACE_ENTRY(kernel_stack, stack_entry,
 
 	TRACE_STACK,
@@ -165,8 +171,9 @@
 		__dynamic_array(unsigned long,	caller	)
 	),
 
-	F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
-		 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+	F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
 		 __entry->caller[0], __entry->caller[1], __entry->caller[2],
 		 __entry->caller[3], __entry->caller[4], __entry->caller[5],
 		 __entry->caller[6], __entry->caller[7])
@@ -181,8 +188,9 @@
 		__array(	unsigned long,	caller, FTRACE_STACK_ENTRIES	)
 	),
 
-	F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
-		 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+	F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
 		 __entry->caller[0], __entry->caller[1], __entry->caller[2],
 		 __entry->caller[3], __entry->caller[4], __entry->caller[5],
 		 __entry->caller[6], __entry->caller[7])
diff -druN linux-libre-3.3-gnu/kernel/trace/trace_export.c linux-libre-3.3.2-gnu/kernel/trace/trace_export.c
--- linux-libre-3.3-gnu/kernel/trace/trace_export.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/kernel/trace/trace_export.c	2012-04-13 12:42:02.000000000 -0400
@@ -150,7 +150,7 @@
 #define __dynamic_array(type, item)
 
 #undef F_printk
-#define F_printk(fmt, args...) #fmt ", "  __stringify(args)
+#define F_printk(fmt, args...) __stringify(fmt) ", "  __stringify(args)
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, etype, tstruct, print)		\
diff -druN linux-libre-3.3-gnu/lib/kobject_uevent.c linux-libre-3.3.2-gnu/lib/kobject_uevent.c
--- linux-libre-3.3-gnu/lib/kobject_uevent.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/lib/kobject_uevent.c	2012-04-13 12:42:02.000000000 -0400
@@ -29,16 +29,17 @@
 
 u64 uevent_seqnum;
 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
-static DEFINE_SPINLOCK(sequence_lock);
 #ifdef CONFIG_NET
 struct uevent_sock {
 	struct list_head list;
 	struct sock *sk;
 };
 static LIST_HEAD(uevent_sock_list);
-static DEFINE_MUTEX(uevent_sock_mutex);
 #endif
 
+/* This lock protects uevent_seqnum and uevent_sock_list */
+static DEFINE_MUTEX(uevent_sock_mutex);
+
 /* the strings here must match the enum in include/linux/kobject.h */
 static const char *kobject_actions[] = {
 	[KOBJ_ADD] =		"add",
@@ -136,7 +137,6 @@
 	struct kobject *top_kobj;
 	struct kset *kset;
 	const struct kset_uevent_ops *uevent_ops;
-	u64 seq;
 	int i = 0;
 	int retval = 0;
 #ifdef CONFIG_NET
@@ -243,17 +243,16 @@
 	else if (action == KOBJ_REMOVE)
 		kobj->state_remove_uevent_sent = 1;
 
+	mutex_lock(&uevent_sock_mutex);
 	/* we will send an event, so request a new sequence number */
-	spin_lock(&sequence_lock);
-	seq = ++uevent_seqnum;
-	spin_unlock(&sequence_lock);
-	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
-	if (retval)
+	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
+	if (retval) {
+		mutex_unlock(&uevent_sock_mutex);
 		goto exit;
+	}
 
 #if defined(CONFIG_NET)
 	/* send netlink message */
-	mutex_lock(&uevent_sock_mutex);
 	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
 		struct sock *uevent_sock = ue_sk->sk;
 		struct sk_buff *skb;
@@ -290,8 +289,8 @@
 		} else
 			retval = -ENOMEM;
 	}
-	mutex_unlock(&uevent_sock_mutex);
 #endif
+	mutex_unlock(&uevent_sock_mutex);
 
 	/* call uevent_helper, usually only enabled during early boot */
 	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
diff -druN linux-libre-3.3-gnu/Makefile linux-libre-3.3.2-gnu/Makefile
--- linux-libre-3.3-gnu/Makefile	2012-03-19 01:11:02.000000000 -0400
+++ linux-libre-3.3.2-gnu/Makefile	2012-04-13 22:55:03.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 3
-SUBLEVEL = 0
+SUBLEVEL = 2
 EXTRAVERSION =-gnu
 NAME = Saber-toothed Squirrel
 
diff -druN linux-libre-3.3-gnu/mm/bootmem.c linux-libre-3.3.2-gnu/mm/bootmem.c
--- linux-libre-3.3-gnu/mm/bootmem.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/bootmem.c	2012-04-13 12:42:02.000000000 -0400
@@ -766,14 +766,13 @@
 				    unsigned long section_nr)
 {
 	bootmem_data_t *bdata;
-	unsigned long pfn, goal, limit;
+	unsigned long pfn, goal;
 
 	pfn = section_nr_to_pfn(section_nr);
 	goal = pfn << PAGE_SHIFT;
-	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
 	bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
-	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0);
 }
 #endif
 
diff -druN linux-libre-3.3-gnu/mm/memcontrol.c linux-libre-3.3.2-gnu/mm/memcontrol.c
--- linux-libre-3.3-gnu/mm/memcontrol.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/memcontrol.c	2012-04-13 12:42:02.000000000 -0400
@@ -5234,6 +5234,8 @@
 	spinlock_t *ptl;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE)
@@ -5396,6 +5398,8 @@
 	spinlock_t *ptl;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 retry:
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; addr += PAGE_SIZE) {
diff -druN linux-libre-3.3-gnu/mm/memory.c linux-libre-3.3.2-gnu/mm/memory.c
--- linux-libre-3.3-gnu/mm/memory.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/memory.c	2012-04-13 12:42:02.000000000 -0400
@@ -1247,16 +1247,24 @@
 	do {
 		next = pmd_addr_end(addr, end);
 		if (pmd_trans_huge(*pmd)) {
-			if (next-addr != HPAGE_PMD_SIZE) {
+			if (next - addr != HPAGE_PMD_SIZE) {
 				VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
 				split_huge_page_pmd(vma->vm_mm, pmd);
 			} else if (zap_huge_pmd(tlb, vma, pmd, addr))
-				continue;
+				goto next;
 			/* fall through */
 		}
-		if (pmd_none_or_clear_bad(pmd))
-			continue;
+		/*
+		 * Here there can be other concurrent MADV_DONTNEED or
+		 * trans huge page faults running, and if the pmd is
+		 * none or trans huge it can change under us. This is
+		 * because MADV_DONTNEED holds the mmap_sem in read
+		 * mode.
+		 */
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+			goto next;
 		next = zap_pte_range(tlb, vma, pmd, addr, next, details);
+next:
 		cond_resched();
 	} while (pmd++, addr = next, addr != end);
 
diff -druN linux-libre-3.3-gnu/mm/mempolicy.c linux-libre-3.3.2-gnu/mm/mempolicy.c
--- linux-libre-3.3-gnu/mm/mempolicy.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/mempolicy.c	2012-04-13 12:42:02.000000000 -0400
@@ -512,7 +512,7 @@
 	do {
 		next = pmd_addr_end(addr, end);
 		split_huge_page_pmd(vma->vm_mm, pmd);
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			continue;
 		if (check_pte_range(vma, pmd, addr, next, nodes,
 				    flags, private))
diff -druN linux-libre-3.3-gnu/mm/mincore.c linux-libre-3.3.2-gnu/mm/mincore.c
--- linux-libre-3.3-gnu/mm/mincore.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/mincore.c	2012-04-13 12:42:02.000000000 -0400
@@ -164,7 +164,7 @@
 			}
 			/* fall through */
 		}
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			mincore_unmapped_range(vma, addr, next, vec);
 		else
 			mincore_pte_range(vma, pmd, addr, next, vec);
diff -druN linux-libre-3.3-gnu/mm/pagewalk.c linux-libre-3.3.2-gnu/mm/pagewalk.c
--- linux-libre-3.3-gnu/mm/pagewalk.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/pagewalk.c	2012-04-13 12:42:02.000000000 -0400
@@ -59,7 +59,7 @@
 			continue;
 
 		split_huge_page_pmd(walk->mm, pmd);
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			goto again;
 		err = walk_pte_range(pmd, addr, next, walk);
 		if (err)
diff -druN linux-libre-3.3-gnu/mm/slub.c linux-libre-3.3.2-gnu/mm/slub.c
--- linux-libre-3.3-gnu/mm/slub.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/slub.c	2012-04-13 12:42:02.000000000 -0400
@@ -3929,13 +3929,14 @@
 		if (kmem_cache_open(s, n,
 				size, align, flags, ctor)) {
 			list_add(&s->list, &slab_caches);
+			up_write(&slub_lock);
 			if (sysfs_slab_add(s)) {
+				down_write(&slub_lock);
 				list_del(&s->list);
 				kfree(n);
 				kfree(s);
 				goto err;
 			}
-			up_write(&slub_lock);
 			return s;
 		}
 		kfree(n);
diff -druN linux-libre-3.3-gnu/mm/sparse.c linux-libre-3.3.2-gnu/mm/sparse.c
--- linux-libre-3.3-gnu/mm/sparse.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/sparse.c	2012-04-13 12:42:02.000000000 -0400
@@ -353,29 +353,21 @@
 
 	usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid),
 								 usemap_count);
-	if (usemap) {
-		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
-			if (!present_section_nr(pnum))
-				continue;
-			usemap_map[pnum] = usemap;
-			usemap += size;
+	if (!usemap) {
+		usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
+		if (!usemap) {
+			printk(KERN_WARNING "%s: allocation failed\n", __func__);
+			return;
 		}
-		return;
 	}
 
-	usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
-	if (usemap) {
-		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
-			if (!present_section_nr(pnum))
-				continue;
-			usemap_map[pnum] = usemap;
-			usemap += size;
-			check_usemap_section_nr(nodeid, usemap_map[pnum]);
-		}
-		return;
+	for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+		if (!present_section_nr(pnum))
+			continue;
+		usemap_map[pnum] = usemap;
+		usemap += size;
+		check_usemap_section_nr(nodeid, usemap_map[pnum]);
 	}
-
-	printk(KERN_WARNING "%s: allocation failed\n", __func__);
 }
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
diff -druN linux-libre-3.3-gnu/mm/swapfile.c linux-libre-3.3.2-gnu/mm/swapfile.c
--- linux-libre-3.3-gnu/mm/swapfile.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/swapfile.c	2012-04-13 12:42:02.000000000 -0400
@@ -932,9 +932,7 @@
 	pmd = pmd_offset(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
-		if (unlikely(pmd_trans_huge(*pmd)))
-			continue;
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			continue;
 		ret = unuse_pte_range(vma, pmd, addr, next, entry, page);
 		if (ret)
diff -druN linux-libre-3.3-gnu/mm/vmscan.c linux-libre-3.3.2-gnu/mm/vmscan.c
--- linux-libre-3.3-gnu/mm/vmscan.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/mm/vmscan.c	2012-04-13 12:42:02.000000000 -0400
@@ -1643,18 +1643,6 @@
 	unsigned long pgmoved = 0;
 	struct page *page;
 
-	if (buffer_heads_over_limit) {
-		spin_unlock_irq(&zone->lru_lock);
-		list_for_each_entry(page, list, lru) {
-			if (page_has_private(page) && trylock_page(page)) {
-				if (page_has_private(page))
-					try_to_release_page(page, 0);
-				unlock_page(page);
-			}
-		}
-		spin_lock_irq(&zone->lru_lock);
-	}
-
 	while (!list_empty(list)) {
 		struct lruvec *lruvec;
 
@@ -1737,6 +1725,14 @@
 			continue;
 		}
 
+		if (unlikely(buffer_heads_over_limit)) {
+			if (page_has_private(page) && trylock_page(page)) {
+				if (page_has_private(page))
+					try_to_release_page(page, 0);
+				unlock_page(page);
+			}
+		}
+
 		if (page_referenced(page, 0, mz->mem_cgroup, &vm_flags)) {
 			nr_rotated += hpage_nr_pages(page);
 			/*
@@ -2235,6 +2231,14 @@
 	unsigned long nr_soft_scanned;
 	bool aborted_reclaim = false;
 
+	/*
+	 * If the number of buffer_heads in the machine exceeds the maximum
+	 * allowed level, force direct reclaim to scan the highmem zone as
+	 * highmem pages could be pinning lowmem pages storing buffer_heads
+	 */
+	if (buffer_heads_over_limit)
+		sc->gfp_mask |= __GFP_HIGHMEM;
+
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 					gfp_zone(sc->gfp_mask), sc->nodemask) {
 		if (!populated_zone(zone))
@@ -2724,6 +2728,17 @@
 			 */
 			age_active_anon(zone, &sc, priority);
 
+			/*
+			 * If the number of buffer_heads in the machine
+			 * exceeds the maximum allowed level and this node
+			 * has a highmem zone, force kswapd to reclaim from
+			 * it to relieve lowmem pressure.
+			 */
+			if (buffer_heads_over_limit && is_highmem_idx(i)) {
+				end_zone = i;
+				break;
+			}
+
 			if (!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone), 0, 0)) {
 				end_zone = i;
@@ -2786,7 +2801,8 @@
 				(zone->present_pages +
 					KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
 				KSWAPD_ZONE_BALANCE_GAP_RATIO);
-			if (!zone_watermark_ok_safe(zone, order,
+			if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
+				    !zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone) + balance_gap,
 					end_zone, 0)) {
 				shrink_zone(priority, zone, &sc);
diff -druN linux-libre-3.3-gnu/net/core/dev.c linux-libre-3.3.2-gnu/net/core/dev.c
--- linux-libre-3.3-gnu/net/core/dev.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/core/dev.c	2012-04-13 12:42:02.000000000 -0400
@@ -3569,7 +3569,8 @@
 static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
 {
 	__skb_pull(skb, skb_headlen(skb));
-	skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+	/* restore the reserve we had after netdev_alloc_skb_ip_align() */
+	skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
 	skb->vlan_tci = 0;
 	skb->dev = napi->dev;
 	skb->skb_iif = 0;
diff -druN linux-libre-3.3-gnu/net/core/rtnetlink.c linux-libre-3.3.2-gnu/net/core/rtnetlink.c
--- linux-libre-3.3-gnu/net/core/rtnetlink.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/core/rtnetlink.c	2012-04-13 12:42:02.000000000 -0400
@@ -1133,6 +1133,8 @@
 				    .len = sizeof(struct ifla_vf_vlan) },
 	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY,
 				    .len = sizeof(struct ifla_vf_tx_rate) },
+	[IFLA_VF_SPOOFCHK]	= { .type = NLA_BINARY,
+				    .len = sizeof(struct ifla_vf_spoofchk) },
 };
 
 static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
diff -druN linux-libre-3.3-gnu/net/ipv6/ip6_output.c linux-libre-3.3.2-gnu/net/ipv6/ip6_output.c
--- linux-libre-3.3-gnu/net/ipv6/ip6_output.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/ipv6/ip6_output.c	2012-04-13 12:42:02.000000000 -0400
@@ -1416,8 +1416,9 @@
 			 */
 			skb->ip_summed = csummode;
 			skb->csum = 0;
-			/* reserve for fragmentation */
-			skb_reserve(skb, hh_len+sizeof(struct frag_hdr));
+			/* reserve for fragmentation and ipsec header */
+			skb_reserve(skb, hh_len + sizeof(struct frag_hdr) +
+				    dst_exthdrlen);
 
 			if (sk->sk_type == SOCK_DGRAM)
 				skb_shinfo(skb)->tx_flags = tx_flags;
@@ -1425,9 +1426,9 @@
 			/*
 			 *	Find where to start putting bytes
 			 */
-			data = skb_put(skb, fraglen + dst_exthdrlen);
-			skb_set_network_header(skb, exthdrlen + dst_exthdrlen);
-			data += fragheaderlen + dst_exthdrlen;
+			data = skb_put(skb, fraglen);
+			skb_set_network_header(skb, exthdrlen);
+			data += fragheaderlen;
 			skb->transport_header = (skb->network_header +
 						 fragheaderlen);
 			if (fraggap) {
diff -druN linux-libre-3.3-gnu/net/ipv6/route.c linux-libre-3.3.2-gnu/net/ipv6/route.c
--- linux-libre-3.3-gnu/net/ipv6/route.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/ipv6/route.c	2012-04-13 12:42:02.000000000 -0400
@@ -2461,8 +2461,12 @@
 
 	rcu_read_lock();
 	n = dst_get_neighbour_noref(&rt->dst);
-	if (n)
-		NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key);
+	if (n) {
+		if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) {
+			rcu_read_unlock();
+			goto nla_put_failure;
+		}
+	}
 	rcu_read_unlock();
 
 	if (rt->dst.dev)
diff -druN linux-libre-3.3-gnu/net/l2tp/l2tp_ppp.c linux-libre-3.3.2-gnu/net/l2tp/l2tp_ppp.c
--- linux-libre-3.3-gnu/net/l2tp/l2tp_ppp.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/l2tp/l2tp_ppp.c	2012-04-13 12:42:02.000000000 -0400
@@ -915,7 +915,7 @@
 		goto end_put_sess;
 	}
 
-	inet = inet_sk(sk);
+	inet = inet_sk(tunnel->sock);
 	if (tunnel->version == 2) {
 		struct sockaddr_pppol2tp sp;
 		len = sizeof(sp);
diff -druN linux-libre-3.3-gnu/net/mac80211/agg-rx.c linux-libre-3.3.2-gnu/net/mac80211/agg-rx.c
--- linux-libre-3.3-gnu/net/mac80211/agg-rx.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/mac80211/agg-rx.c	2012-04-13 12:42:02.000000000 -0400
@@ -49,6 +49,8 @@
 		container_of(h, struct tid_ampdu_rx, rcu_head);
 	int i;
 
+	del_timer_sync(&tid_rx->reorder_timer);
+
 	for (i = 0; i < tid_rx->buf_size; i++)
 		dev_kfree_skb(tid_rx->reorder_buf[i]);
 	kfree(tid_rx->reorder_buf);
@@ -91,7 +93,6 @@
 				     tid, WLAN_BACK_RECIPIENT, reason);
 
 	del_timer_sync(&tid_rx->session_timer);
-	del_timer_sync(&tid_rx->reorder_timer);
 
 	call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
 }
diff -druN linux-libre-3.3-gnu/net/rds/send.c linux-libre-3.3.2-gnu/net/rds/send.c
--- linux-libre-3.3-gnu/net/rds/send.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/rds/send.c	2012-04-13 12:42:02.000000000 -0400
@@ -935,7 +935,6 @@
 	/* Mirror Linux UDP mirror of BSD error message compatibility */
 	/* XXX: Perhaps MSG_MORE someday */
 	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
-		printk(KERN_INFO "msg_flags 0x%08X\n", msg->msg_flags);
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
diff -druN linux-libre-3.3-gnu/net/rose/rose_dev.c linux-libre-3.3.2-gnu/net/rose/rose_dev.c
--- linux-libre-3.3-gnu/net/rose/rose_dev.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/rose/rose_dev.c	2012-04-13 12:42:02.000000000 -0400
@@ -96,11 +96,11 @@
 	struct sockaddr *sa = addr;
 	int err;
 
-	if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+	if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
 		return 0;
 
 	if (dev->flags & IFF_UP) {
-		err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+		err = rose_add_loopback_node((rose_address *)sa->sa_data);
 		if (err)
 			return err;
 
diff -druN linux-libre-3.3-gnu/net/sunrpc/cache.c linux-libre-3.3.2-gnu/net/sunrpc/cache.c
--- linux-libre-3.3-gnu/net/sunrpc/cache.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/sunrpc/cache.c	2012-04-13 12:42:02.000000000 -0400
@@ -828,6 +828,8 @@
 {
 	ssize_t ret;
 
+	if (count == 0)
+		return -EINVAL;
 	if (copy_from_user(kaddr, buf, count))
 		return -EFAULT;
 	kaddr[count] = '\0';
diff -druN linux-libre-3.3-gnu/net/sunrpc/sched.c linux-libre-3.3.2-gnu/net/sunrpc/sched.c
--- linux-libre-3.3-gnu/net/sunrpc/sched.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/sunrpc/sched.c	2012-04-13 12:42:02.000000000 -0400
@@ -501,14 +501,18 @@
  */
 void rpc_wake_up(struct rpc_wait_queue *queue)
 {
-	struct rpc_task *task, *next;
 	struct list_head *head;
 
 	spin_lock_bh(&queue->lock);
 	head = &queue->tasks[queue->maxpriority];
 	for (;;) {
-		list_for_each_entry_safe(task, next, head, u.tk_wait.list)
+		while (!list_empty(head)) {
+			struct rpc_task *task;
+			task = list_first_entry(head,
+					struct rpc_task,
+					u.tk_wait.list);
 			rpc_wake_up_task_queue_locked(queue, task);
+		}
 		if (head == &queue->tasks[0])
 			break;
 		head--;
@@ -526,13 +530,16 @@
  */
 void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
 {
-	struct rpc_task *task, *next;
 	struct list_head *head;
 
 	spin_lock_bh(&queue->lock);
 	head = &queue->tasks[queue->maxpriority];
 	for (;;) {
-		list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
+		while (!list_empty(head)) {
+			struct rpc_task *task;
+			task = list_first_entry(head,
+					struct rpc_task,
+					u.tk_wait.list);
 			task->tk_status = status;
 			rpc_wake_up_task_queue_locked(queue, task);
 		}
diff -druN linux-libre-3.3-gnu/net/xfrm/xfrm_replay.c linux-libre-3.3.2-gnu/net/xfrm/xfrm_replay.c
--- linux-libre-3.3-gnu/net/xfrm/xfrm_replay.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/net/xfrm/xfrm_replay.c	2012-04-13 12:42:02.000000000 -0400
@@ -167,7 +167,7 @@
 	}
 
 	if (xfrm_aevent_is_on(xs_net(x)))
-		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+		x->repl->notify(x, XFRM_REPLAY_UPDATE);
 }
 
 static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
@@ -279,7 +279,7 @@
 	replay_esn->bmp[nr] |= (1U << bitnr);
 
 	if (xfrm_aevent_is_on(xs_net(x)))
-		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+		x->repl->notify(x, XFRM_REPLAY_UPDATE);
 }
 
 static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
@@ -473,7 +473,7 @@
 	replay_esn->bmp[nr] |= (1U << bitnr);
 
 	if (xfrm_aevent_is_on(xs_net(x)))
-		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+		x->repl->notify(x, XFRM_REPLAY_UPDATE);
 }
 
 static struct xfrm_replay xfrm_replay_legacy = {
diff -druN linux-libre-3.3-gnu/scripts/mod/modpost.c linux-libre-3.3.2-gnu/scripts/mod/modpost.c
--- linux-libre-3.3-gnu/scripts/mod/modpost.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/scripts/mod/modpost.c	2012-04-13 12:42:02.000000000 -0400
@@ -132,8 +132,10 @@
 	/* strip trailing .o */
 	s = strrchr(p, '.');
 	if (s != NULL)
-		if (strcmp(s, ".o") == 0)
+		if (strcmp(s, ".o") == 0) {
 			*s = '\0';
+			mod->is_dot_o = 1;
+		}
 
 	/* add to list */
 	mod->name = p;
@@ -587,7 +589,8 @@
 	unsigned int crc;
 	enum export export;
 
-	if (!is_vmlinux(mod->name) && strncmp(symname, "__ksymtab", 9) == 0)
+	if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+	    strncmp(symname, "__ksymtab", 9) == 0)
 		export = export_from_secname(info, get_secindex(info, sym));
 	else
 		export = export_from_sec(info, get_secindex(info, sym));
@@ -849,7 +852,7 @@
 
 #define ALL_INIT_DATA_SECTIONS \
 	".init.setup$", ".init.rodata$", \
-	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \
+	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \
 	".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
 #define ALL_EXIT_DATA_SECTIONS \
 	".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
diff -druN linux-libre-3.3-gnu/scripts/mod/modpost.h linux-libre-3.3.2-gnu/scripts/mod/modpost.h
--- linux-libre-3.3-gnu/scripts/mod/modpost.h	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/scripts/mod/modpost.h	2012-04-13 12:42:02.000000000 -0400
@@ -113,6 +113,7 @@
 	int has_cleanup;
 	struct buffer dev_table_buf;
 	char	     srcversion[25];
+	int is_dot_o;
 };
 
 struct elf_info {
diff -druN linux-libre-3.3-gnu/security/integrity/ima/Kconfig linux-libre-3.3.2-gnu/security/integrity/ima/Kconfig
--- linux-libre-3.3-gnu/security/integrity/ima/Kconfig	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/security/integrity/ima/Kconfig	2012-04-13 12:42:02.000000000 -0400
@@ -9,7 +9,7 @@
 	select CRYPTO_HMAC
 	select CRYPTO_MD5
 	select CRYPTO_SHA1
-	select TCG_TPM if !S390 && !UML
+	select TCG_TPM if HAS_IOMEM && !UML
 	select TCG_TIS if TCG_TPM
 	help
 	  The Trusted Computing Group(TCG) runtime Integrity
diff -druN linux-libre-3.3-gnu/security/tomoyo/mount.c linux-libre-3.3.2-gnu/security/tomoyo/mount.c
--- linux-libre-3.3-gnu/security/tomoyo/mount.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/security/tomoyo/mount.c	2012-04-13 12:42:02.000000000 -0400
@@ -199,30 +199,32 @@
 	if (flags & MS_REMOUNT) {
 		type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
 		flags &= ~MS_REMOUNT;
-	}
-	if (flags & MS_MOVE) {
-		type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
-		flags &= ~MS_MOVE;
-	}
-	if (flags & MS_BIND) {
+	} else if (flags & MS_BIND) {
 		type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
 		flags &= ~MS_BIND;
-	}
-	if (flags & MS_UNBINDABLE) {
-		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
-		flags &= ~MS_UNBINDABLE;
-	}
-	if (flags & MS_PRIVATE) {
+	} else if (flags & MS_SHARED) {
+		if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+			return -EINVAL;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
+		flags &= ~MS_SHARED;
+	} else if (flags & MS_PRIVATE) {
+		if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
+			return -EINVAL;
 		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
 		flags &= ~MS_PRIVATE;
-	}
-	if (flags & MS_SLAVE) {
+	} else if (flags & MS_SLAVE) {
+		if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
+			return -EINVAL;
 		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
 		flags &= ~MS_SLAVE;
-	}
-	if (flags & MS_SHARED) {
-		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
-		flags &= ~MS_SHARED;
+	} else if (flags & MS_UNBINDABLE) {
+		if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
+			return -EINVAL;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
+		flags &= ~MS_UNBINDABLE;
+	} else if (flags & MS_MOVE) {
+		type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
+		flags &= ~MS_MOVE;
 	}
 	if (!type)
 		type = "<NULL>";
diff -druN linux-libre-3.3-gnu/sound/pci/hda/hda_eld.c linux-libre-3.3.2-gnu/sound/pci/hda/hda_eld.c
--- linux-libre-3.3-gnu/sound/pci/hda/hda_eld.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/pci/hda/hda_eld.c	2012-04-13 12:42:02.000000000 -0400
@@ -385,8 +385,8 @@
 static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 {
 	static unsigned int alsa_rates[] = {
-		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
-		96000, 176400, 192000, 384000
+		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+		88200, 96000, 176400, 192000, 384000
 	};
 	int i, j;
 
diff -druN linux-libre-3.3-gnu/sound/pci/hda/patch_realtek.c linux-libre-3.3.2-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-3.3-gnu/sound/pci/hda/patch_realtek.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/pci/hda/patch_realtek.c	2012-04-13 12:42:02.000000000 -0400
@@ -2709,9 +2709,6 @@
 	int max_nums = ARRAY_SIZE(spec->private_adc_nids);
 	int i, nums = 0;
 
-	if (spec->shared_mic_hp)
-		max_nums = 1; /* no multi streams with the shared HP/mic */
-
 	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, nid++) {
 		hda_nid_t src;
@@ -3723,6 +3720,7 @@
 	if (spec->dyn_adc_switch)
 		return;
 
+ again:
 	nums = 0;
 	for (n = 0; n < spec->num_adc_nids; n++) {
 		hda_nid_t cap = spec->private_capsrc_nids[n];
@@ -3743,6 +3741,11 @@
 	if (!nums) {
 		/* check whether ADC-switch is possible */
 		if (!alc_check_dyn_adc_switch(codec)) {
+			if (spec->shared_mic_hp) {
+				spec->shared_mic_hp = 0;
+				spec->private_imux[0].num_items = 1;
+				goto again;
+			}
 			printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
 			       " using fallback 0x%x\n",
 			       codec->chip_name, spec->private_adc_nids[0]);
@@ -3760,7 +3763,7 @@
 
 	if (spec->auto_mic)
 		alc_auto_mic_check_imux(codec); /* check auto-mic setups */
-	else if (spec->input_mux->num_items == 1)
+	else if (spec->input_mux->num_items == 1 || spec->shared_mic_hp)
 		spec->num_adc_nids = 1; /* reduce to a single ADC */
 }
 
diff -druN linux-libre-3.3-gnu/sound/soc/codecs/ak4642.c linux-libre-3.3.2-gnu/sound/soc/codecs/ak4642.c
--- linux-libre-3.3-gnu/sound/soc/codecs/ak4642.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/soc/codecs/ak4642.c	2012-04-13 12:42:02.000000000 -0400
@@ -140,7 +140,7 @@
  * min : 0xFE : -115.0 dB
  * mute: 0xFF
  */
-static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -11550, 50, 1);
 
 static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 
diff -druN linux-libre-3.3-gnu/sound/soc/codecs/wm8994.c linux-libre-3.3.2-gnu/sound/soc/codecs/wm8994.c
--- linux-libre-3.3-gnu/sound/soc/codecs/wm8994.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/soc/codecs/wm8994.c	2012-04-13 12:42:02.000000000 -0400
@@ -3427,7 +3427,7 @@
 		case 2:
 		case 3:
 			wm8994->hubs.dcs_codes_l = -9;
-			wm8994->hubs.dcs_codes_r = -5;
+			wm8994->hubs.dcs_codes_r = -7;
 			break;
 		default:
 			break;
diff -druN linux-libre-3.3-gnu/sound/soc/fsl/p1022_ds.c linux-libre-3.3.2-gnu/sound/soc/fsl/p1022_ds.c
--- linux-libre-3.3-gnu/sound/soc/fsl/p1022_ds.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/soc/fsl/p1022_ds.c	2012-04-13 12:42:02.000000000 -0400
@@ -395,7 +395,8 @@
 	}
 
 	if (strcasecmp(sprop, "i2s-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 
@@ -412,31 +413,38 @@
 		}
 		mdata->clk_frequency = be32_to_cpup(iprop);
 	} else if (strcasecmp(sprop, "i2s-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "lj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "lj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "rj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "rj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "ac97-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "ac97-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else {
diff -druN linux-libre-3.3-gnu/sound/soc/pxa/pxa-ssp.c linux-libre-3.3.2-gnu/sound/soc/pxa/pxa-ssp.c
--- linux-libre-3.3-gnu/sound/soc/pxa/pxa-ssp.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/soc/pxa/pxa-ssp.c	2012-04-13 12:42:02.000000000 -0400
@@ -668,6 +668,38 @@
 	return 0;
 }
 
+static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
+				    struct ssp_device *ssp, int value)
+{
+	uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
+	uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
+	uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
+	uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
+
+	if (value && (sscr0 & SSCR0_SSE))
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (value)
+			sscr1 |= SSCR1_TSRE;
+		else
+			sscr1 &= ~SSCR1_TSRE;
+	} else {
+		if (value)
+			sscr1 |= SSCR1_RSRE;
+		else
+			sscr1 &= ~SSCR1_RSRE;
+	}
+
+	pxa_ssp_write_reg(ssp, SSCR1, sscr1);
+
+	if (value) {
+		pxa_ssp_write_reg(ssp, SSSR, sssr);
+		pxa_ssp_write_reg(ssp, SSPSP, sspsp);
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
+	}
+}
+
 static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *cpu_dai)
 {
@@ -681,42 +713,21 @@
 		pxa_ssp_enable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		val = pxa_ssp_read_reg(ssp, SSSR);
 		pxa_ssp_write_reg(ssp, SSSR, val);
 		break;
 	case SNDRV_PCM_TRIGGER_START:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
-		pxa_ssp_enable(ssp);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		pxa_ssp_disable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 
 	default:
diff -druN linux-libre-3.3-gnu/sound/soc/tegra/tegra_i2s.c linux-libre-3.3.2-gnu/sound/soc/tegra/tegra_i2s.c
--- linux-libre-3.3-gnu/sound/soc/tegra/tegra_i2s.c	2012-03-18 19:15:34.000000000 -0400
+++ linux-libre-3.3.2-gnu/sound/soc/tegra/tegra_i2s.c	2012-04-13 12:42:02.000000000 -0400
@@ -112,7 +112,7 @@
 		debugfs_remove(i2s->debug);
 }
 #else
-static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
+static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s)
 {
 }
 
